├── .github ├── FUNDING.yml └── ISSUE_TEMPLATE │ ├── bug_report.yml │ └── feature_request.md ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── bun.lockb ├── docs-example ├── .gitignore ├── README.md ├── analysis_options.yaml ├── codes │ ├── aggregate.dart │ ├── create_multiple_records.dart │ ├── create_single_record.dart │ ├── delete_all_records.dart │ ├── delete_multiple_records.dart │ ├── delete_single_record.dart │ ├── filter_by_multiple_field_values.dart │ ├── filter_by_related_record_field_values.dart │ ├── filter_by_single_field_value.dart │ ├── filtering_and_sorting.dart │ ├── find_or_create_record.dart │ ├── get_all_records.dart │ ├── get_first_record_that_matches_criteria.dart │ ├── get_record_by_id.dart │ ├── get_record_by_unique_field.dart │ ├── include_related_records.dart │ ├── include_relation_fields.dart │ ├── include_relation_fields_with_select.dart │ ├── nested_read.dart │ ├── pagination.dart │ ├── post_with_author.dart │ ├── relation-queries.dart │ ├── select_subset_of_fields.dart │ ├── select_subset_of_related_record_fields.dart │ ├── update_multiple_records.dart │ ├── update_number_field.dart │ ├── update_or_create_record.dart │ ├── update_single_record.dart │ ├── user_with_posts_title.dart │ └── user_with_posts_with_categories.dart ├── prisma.dart ├── prisma │ └── schema.prisma ├── pubspec.yaml └── transactions.dart ├── docs ├── .vitepress │ ├── .gitignore │ ├── config.mts │ └── theme │ │ ├── index.ts │ │ └── style.css ├── getting-started │ ├── deployment.md │ ├── flutter.md │ ├── index.md │ ├── schema.md │ ├── setup.md │ └── upgrade_guides.md ├── index.md ├── public │ └── prisma-dart.logo.svg ├── queries │ ├── aggregation-grouping-summarizing.md │ ├── crud.md │ ├── filtering-and-sorting.md │ ├── pagination.md │ ├── raw-database-access.md │ ├── relation-queries.md │ ├── select-fields.md │ └── transactions.md └── references │ ├── client-api.md │ └── model-delegate.md ├── examples ├── flutter_with_orm │ ├── .gitignore │ ├── .metadata │ ├── README.md │ ├── analysis_options.yaml │ ├── android │ │ ├── .gitignore │ │ ├── app │ │ │ ├── build.gradle │ │ │ └── src │ │ │ │ ├── debug │ │ │ │ └── AndroidManifest.xml │ │ │ │ ├── main │ │ │ │ ├── AndroidManifest.xml │ │ │ │ └── res │ │ │ │ │ ├── drawable-v21 │ │ │ │ │ └── launch_background.xml │ │ │ │ │ ├── drawable │ │ │ │ │ └── launch_background.xml │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── values-night │ │ │ │ │ └── styles.xml │ │ │ │ │ └── values │ │ │ │ │ └── styles.xml │ │ │ │ └── profile │ │ │ │ └── AndroidManifest.xml │ │ ├── build.gradle │ │ ├── gradle.properties │ │ ├── gradle │ │ │ └── wrapper │ │ │ │ └── gradle-wrapper.properties │ │ └── settings.gradle │ ├── ios │ │ ├── .gitignore │ │ ├── Flutter │ │ │ ├── AppFrameworkInfo.plist │ │ │ ├── Debug.xcconfig │ │ │ └── Release.xcconfig │ │ ├── Podfile │ │ ├── Podfile.lock │ │ ├── Runner.xcodeproj │ │ │ ├── project.pbxproj │ │ │ ├── project.xcworkspace │ │ │ │ ├── contents.xcworkspacedata │ │ │ │ └── xcshareddata │ │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ │ └── WorkspaceSettings.xcsettings │ │ │ └── xcshareddata │ │ │ │ └── xcschemes │ │ │ │ └── Runner.xcscheme │ │ ├── Runner.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ └── WorkspaceSettings.xcsettings │ │ ├── Runner │ │ │ ├── AppDelegate.swift │ │ │ ├── Assets.xcassets │ │ │ │ ├── AppIcon.appiconset │ │ │ │ │ ├── Contents.json │ │ │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ │ │ ├── Icon-App-20x20@1x.png │ │ │ │ │ ├── Icon-App-20x20@2x.png │ │ │ │ │ ├── Icon-App-20x20@3x.png │ │ │ │ │ ├── Icon-App-29x29@1x.png │ │ │ │ │ ├── Icon-App-29x29@2x.png │ │ │ │ │ ├── Icon-App-29x29@3x.png │ │ │ │ │ ├── Icon-App-40x40@1x.png │ │ │ │ │ ├── Icon-App-40x40@2x.png │ │ │ │ │ ├── Icon-App-40x40@3x.png │ │ │ │ │ ├── Icon-App-60x60@2x.png │ │ │ │ │ ├── Icon-App-60x60@3x.png │ │ │ │ │ ├── Icon-App-76x76@1x.png │ │ │ │ │ ├── Icon-App-76x76@2x.png │ │ │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ │ │ └── LaunchImage.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ ├── LaunchImage.png │ │ │ │ │ ├── LaunchImage@2x.png │ │ │ │ │ ├── LaunchImage@3x.png │ │ │ │ │ └── README.md │ │ │ ├── Base.lproj │ │ │ │ ├── LaunchScreen.storyboard │ │ │ │ └── Main.storyboard │ │ │ ├── Info.plist │ │ │ └── Runner-Bridging-Header.h │ │ └── RunnerTests │ │ │ └── RunnerTests.swift │ ├── lib │ │ ├── main.dart │ │ └── prisma.dart │ ├── prisma │ │ ├── migrations │ │ │ ├── 20240528135435_init │ │ │ │ └── migration.sql │ │ │ └── migration_lock.toml │ │ └── schema.prisma │ └── pubspec.yaml ├── with_postgres │ ├── .gitignore │ ├── README.md │ ├── analysis_options.yaml │ ├── app.dart │ ├── prisma │ │ └── schema.prisma │ └── pubspec.yaml └── with_sqlite │ ├── .env │ ├── .gitignore │ ├── analysis_options.yaml │ ├── bin │ └── with_sqlite.dart │ ├── lib │ └── with_sqlite.dart │ ├── prisma │ └── schema.prisma │ └── pubspec.yaml ├── graphs ├── alipay.jpg └── wechat_pay.jpg ├── package.json ├── packages ├── orm │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── analysis_options.yaml │ ├── bin │ │ ├── orm.dart │ │ └── src │ │ │ ├── download_engine.dart │ │ │ ├── generate_client.dart │ │ │ ├── generate_delegate.dart │ │ │ ├── generate_enum.dart │ │ │ ├── generate_field_ref.dart │ │ │ ├── generate_helpers.dart │ │ │ ├── generate_include.dart │ │ │ ├── generate_input.dart │ │ │ ├── generate_model_scalar.dart │ │ │ ├── generate_output.dart │ │ │ ├── generate_select.dart │ │ │ ├── generate_type.dart │ │ │ ├── generator+client.dart.without_code_builder_test.dart │ │ │ ├── generator.dart │ │ │ └── utils │ │ │ ├── dart_style_fixer.dart │ │ │ ├── is_flutter_engine_type.dart │ │ │ ├── iterable.dart │ │ │ ├── reference.dart │ │ │ └── scalars.dart │ ├── example │ │ └── README.md │ ├── integration_tests │ │ ├── i463.dart │ │ └── i467.dart │ ├── lib │ │ ├── dmmf.dart │ │ ├── engines │ │ │ └── binary.dart │ │ ├── generator_helper.dart │ │ ├── orm.dart │ │ ├── src │ │ │ ├── _internal │ │ │ │ └── project_directory.dart │ │ │ ├── base_prisma_client.dart │ │ │ ├── config │ │ │ │ ├── _loader.dart │ │ │ │ ├── _loader.io.dart │ │ │ │ ├── prisma+config.dart │ │ │ │ └── prisma+env.dart │ │ │ ├── datasources │ │ │ │ ├── _validate_datasource_url.dart │ │ │ │ ├── _validate_datasource_url.io.dart │ │ │ │ ├── datasources.dart │ │ │ │ └── prisma+datasource_utils.dart │ │ │ ├── dmmf │ │ │ │ ├── datamodel.dart │ │ │ │ ├── dmmf.dart │ │ │ │ ├── mappings.dart │ │ │ │ └── schema.dart │ │ │ ├── engines │ │ │ │ └── binary_engine.dart │ │ │ ├── errors.dart │ │ │ ├── generator_helper │ │ │ │ ├── binary_targets_env_value.dart │ │ │ │ ├── config.dart │ │ │ │ ├── env_value.dart │ │ │ │ ├── generator.dart │ │ │ │ ├── manifest.dart │ │ │ │ └── options.dart │ │ │ ├── logging.dart │ │ │ ├── prisma_client_options.dart │ │ │ ├── prisma_namespace.dart │ │ │ └── runtime │ │ │ │ ├── action_client.dart │ │ │ │ ├── decimal.dart │ │ │ │ ├── engine.dart │ │ │ │ ├── json_convertible.dart │ │ │ │ ├── json_protocol │ │ │ │ ├── deserialize.dart │ │ │ │ ├── protocol.dart │ │ │ │ └── serialize.dart │ │ │ │ ├── metrics │ │ │ │ ├── metrics_client.dart │ │ │ │ └── metrics_format.dart │ │ │ │ ├── prisma_enum.dart │ │ │ │ ├── prisma_json.dart │ │ │ │ ├── prisma_null.dart │ │ │ │ ├── prisma_union.dart │ │ │ │ ├── raw │ │ │ │ ├── _deserialize_raw_results.dart │ │ │ │ ├── _serialize_raw_params.dart │ │ │ │ └── raw_client.dart │ │ │ │ ├── reference.dart │ │ │ │ └── transaction │ │ │ │ ├── isolation_level.dart │ │ │ │ ├── transaction.dart │ │ │ │ ├── transaction_client.dart │ │ │ │ └── transaction_headers.dart │ │ └── version.dart │ ├── prisma │ │ └── schema.prisma │ ├── pubspec.yaml │ ├── test │ │ ├── json_protocol │ │ │ └── serialize_test.dart │ │ └── sqlite.prisma │ └── tool │ │ └── dmmf_generator.dart ├── orm_flutter │ ├── .gitignore │ ├── .metadata │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── analysis_options.yaml │ ├── example │ │ └── README.md │ ├── lib │ │ └── orm_flutter.dart │ └── pubspec.yaml ├── orm_flutter_android │ ├── .gitignore │ ├── .metadata │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── analysis_options.yaml │ ├── android │ │ ├── .gitignore │ │ ├── build.gradle │ │ ├── settings.gradle │ │ └── src │ │ │ └── main │ │ │ └── AndroidManifest.xml │ ├── example │ │ └── README.md │ ├── pubspec.yaml │ └── src │ │ ├── CMakeLists.txt │ │ ├── jniLibs │ │ ├── arm64-v8a │ │ │ └── libquery_engine.a │ │ ├── armeabi-v7a │ │ │ └── libquery_engine.a │ │ ├── x86 │ │ │ └── libquery_engine.a │ │ └── x86_64 │ │ │ └── libquery_engine.a │ │ └── query_engine_bridge │ │ ├── README.md │ │ ├── bridge.c │ │ ├── headers │ │ └── bridge.h │ │ └── include │ │ └── query_engine.h ├── orm_flutter_ffi │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── analysis_options.yaml │ ├── example │ │ └── README.md │ ├── lib │ │ ├── orm_flutter_ffi.dart │ │ └── src │ │ │ ├── _generate_bindings.dart │ │ │ ├── bindings.dart │ │ │ └── library_engine.dart │ └── pubspec.yaml ├── orm_flutter_ios │ ├── .gitignore │ ├── .metadata │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── example │ │ └── README.md │ ├── ios │ │ ├── orm_flutter_ios.podspec │ │ └── orm_flutter_ios │ │ │ ├── Frameworks │ │ │ └── QueryEngine.xcframework │ │ │ │ ├── Info.plist │ │ │ │ ├── ios-arm64 │ │ │ │ ├── Headers │ │ │ │ │ └── query_engine.h │ │ │ │ └── libquery_engine.a │ │ │ │ └── ios-arm64_x86_64-simulator │ │ │ │ ├── Headers │ │ │ │ └── query_engine.h │ │ │ │ └── libquery_engine.a │ │ │ ├── Package.swift │ │ │ └── Sources │ │ │ └── query_engine_bridge │ │ │ ├── README.md │ │ │ ├── bridge.c │ │ │ ├── headers │ │ │ └── bridge.h │ │ │ └── include │ │ │ └── query_engine.h │ └── pubspec.yaml └── query_engine_bridge │ ├── README.md │ ├── bridge.c │ ├── headers │ └── bridge.h │ └── include │ └── query_engine.h ├── pubspec.lock ├── pubspec.yaml ├── renovate.json ├── scripts └── update_query_engine.ts └── template └── example_stub.md /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: medz 2 | open_collective: openodroe 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: 🐛 Bug Report 2 | description: Report an issue that should be fixed 3 | labels: 4 | - bug 5 | - needs triage 6 | body: 7 | - type: markdown 8 | attributes: 9 | value: | 10 | Thank you for submitting a bug report. It helps make Prisma Dart better. 11 |  12 | If you need help or support using Prisma Dart, and are not reporting a bug, please 13 | join our [Discord](https://discord.gg/ms2X9TQMR8) server, where you can ask questions in the [`Q&A`](https://github.com/medz/prisma-dart/discussions/categories/q-a) forum. 14 |  15 | Make sure you are running the [latest](https://github.com/medz/prisma-dart/releases/latest) version of Prisma Dart. 16 | The bug you are experiencing may already have been fixed. 17 |  18 | Please try to include as much information as possible. 19 | - type: input 20 | attributes: 21 | label: What version of Prisma Dart is running? 22 | description: View the version number of the `orm` package in `pubspec.yaml` 23 | validations: 24 | required: true 25 | - type: input 26 | attributes: 27 | label: What version of Prisma CLI is running? 28 | description: Copy the output of `prisma version`. 29 | validations: 30 | required: true 31 | - type: dropdown 32 | attributes: 33 | label: What type of app are you using? 34 | multiple: false 35 | options: 36 | - Dart Native (Server/CLI) 37 | - Flutter 38 | validations: 39 | required: true 40 | - type: dropdown 41 | attributes: 42 | label: What database are you using? 43 | multiple: true 44 | options: 45 | - SQLite 46 | - MySQL 47 | - MariaDB 48 | - PostgreSQL 49 | - MongoDB 50 | - Microsoft SQL Server 51 | - CockroachDB 52 | - type: textarea 53 | attributes: 54 | label: What steps can reproduce the bug? 55 | description: Explain the bug and provide a code snippet that can reproduce it. 56 | validations: 57 | required: true 58 | - type: textarea 59 | attributes: 60 | label: What is the expected behavior? 61 | description: If possible, please provide text instead of a screenshot. 62 | - type: textarea 63 | attributes: 64 | label: What do you see instead? 65 | description: If possible, please provide text instead of a screenshot. 66 | - type: textarea 67 | attributes: 68 | label: Additional information 69 | description: Is there anything else you think we should know? 70 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .env 3 | .idea/ 4 | .vscode/ 5 | .dart_tool/ 6 | prisma-query-engine* 7 | generated_*/ 8 | node_modules/ 9 | dev/ 10 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Welcome to Prisma ORM (for Dart) contributing guide 2 | 3 | We're glad you've read this far and look forward to making this project a success! 4 | 5 | Here are some important references for this project: 6 | 7 | - [Code of Conduct](CODE_OF_CONDUCT.md) 8 | - [Prisma docs](https://www.prisma.io/docs/) 9 | - [Prisma engines](https://github.com/prisma/prisma-engines) 10 | 11 | ## How to contribute 12 | 13 | This project is divided into two parts: 14 | 15 | 1. binary 16 | 2. library 17 | 18 | ### Binary 19 | 20 | The Binary part is the generator for Prisma CLI, which is located in the `bin` directory of the project. If you plan to fix or change generator logic, your changes will be made in this directory. 21 | 22 | ### Library 23 | 24 | Here will be the implementation part of the Prisma client, which covers many auxiliary methods and the Prisma engine client. 25 | 26 | ## Reporting a bug 27 | 28 | Reporting a bug is also a contribution to the project, but it is not the same as fixing a bug. If you find a bug, please report it in the [issue](https://github.com/medz/prisma-dart/issues) section. 29 | 30 | ## Testing 31 | 32 | We write the test code in the `test` directory and in the `*_test.dart` obvious way, the current test code is not sound, if it can help us better test this project. 33 | 34 | ## Branching rules 35 | 36 | The `main` branch is the stable branch of the current version, we do not set up a development branch. For new changes and fixes in the future we use the experience branch to develop, and then merge it into the main branch when appropriate. 37 | 38 | So you don't have to worry about creating a PR to `main` breaking it. Because if your PR is not compatible with the current version, we will merge it again at the right time, and it is also possible to release a test version of a future version through the PR. 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2022, Odore, Inc. & Contributors All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its 16 | contributors may be used to endorse or promote products derived from 17 | this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Use this section to tell people about which versions of your project are 6 | currently being supported with security updates. 7 | 8 | | Version | Supported | 9 | | ------- | ------------------ | 10 | | 3.x | :white_check_mark: | 11 | | < 3.0 | :x: | 12 | 13 | ## Reporting a Vulnerability 14 | 15 | A security hole is different from a common error, For bugs that affect data security, we recommend reporting through the following channels: 16 | 17 | 1. [Twitter message](https://twitter.com/odroeinc) 18 | 2. [Email](mailto:hello@odroe.com) 19 | -------------------------------------------------------------------------------- /bun.lockb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/bun.lockb -------------------------------------------------------------------------------- /docs-example/.gitignore: -------------------------------------------------------------------------------- 1 | .dart_tool/ 2 | node_modules/ 3 | prisma/generated_* 4 | prisma-query-engine 5 | 6 | # Keep environment variables out of version control 7 | .env 8 | -------------------------------------------------------------------------------- /docs-example/README.md: -------------------------------------------------------------------------------- 1 | # Prisma Dart client examples 2 | 3 | All examples codes see `codes` directory. 4 | 5 | This example is [docs](https://prisma.pub) document example, you can see [here](https://prisma.pub/client/crud.html) 6 | -------------------------------------------------------------------------------- /docs-example/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the static analysis results for your project (errors, 2 | # warnings, and lints). 3 | # 4 | # This enables the 'recommended' set of lints from `package:lints`. 5 | # This set helps identify many issues that may lead to problems when running 6 | # or consuming Dart code, and enforces writing Dart using a single, idiomatic 7 | # style and format. 8 | # 9 | # If you want a smaller set of lints you can change this to specify 10 | # 'package:lints/core.yaml'. These are just the most critical lints 11 | # (the recommended set includes the core lints). 12 | # The core lints are also what is used by pub.dev for scoring packages. 13 | 14 | include: package:lints/recommended.yaml 15 | # Uncomment the following section to specify additional rules. 16 | 17 | # linter: 18 | # rules: 19 | # non_constant_identifier_names: false 20 | 21 | # analyzer: 22 | # exclude: 23 | # - path/to/excluded/files/** 24 | # language: 25 | # non-constant-identifier-names: false 26 | 27 | # For more information about the core and recommended set of lints, see 28 | # https://dart.dev/go/core-lints 29 | 30 | # For additional information about configuring this file, see 31 | # https://dart.dev/guides/language/analysis-options 32 | -------------------------------------------------------------------------------- /docs-example/codes/create_multiple_records.dart: -------------------------------------------------------------------------------- 1 | import 'package:orm/orm.dart'; 2 | 3 | import '../prisma.dart'; 4 | import '../prisma/generated_dart_client/client.dart'; 5 | import '../prisma/generated_dart_client/prisma.dart'; 6 | 7 | createMultipleRecords(PrismaClient prisma) async { 8 | // #region snippet 9 | final affectedRows = await prisma.user.createMany( 10 | data: PrismaUnion.$2([ 11 | UserCreateManyInput( 12 | name: PrismaUnion.$1("Bob1"), email: "bob@prisma.pub"), 13 | UserCreateManyInput( 14 | name: PrismaUnion.$1("Bob2"), email: "bob@prisma.pub"), 15 | UserCreateManyInput( 16 | name: PrismaUnion.$1("Yewande"), email: "yewande@prisma.pub"), 17 | UserCreateManyInput( 18 | name: PrismaUnion.$1("Ange"), email: "ange@prisma.pub"), 19 | ]), 20 | skipDuplicates: true, // Skip 'Bob2' 21 | ); 22 | // #endregion snippet 23 | 24 | print({ 25 | "count": affectedRows.count, 26 | }); 27 | } 28 | 29 | void main(List args) => providePrisma(createMultipleRecords); 30 | -------------------------------------------------------------------------------- /docs-example/codes/create_single_record.dart: -------------------------------------------------------------------------------- 1 | import 'package:orm/orm.dart'; 2 | 3 | import '../prisma.dart'; 4 | import '../prisma/generated_dart_client/client.dart'; 5 | import '../prisma/generated_dart_client/prisma.dart'; 6 | 7 | /// Create a single record. 8 | createSingleRecord(PrismaClient prisma) async { 9 | // #region snippet 10 | final user = await prisma.user.create( 11 | data: PrismaUnion.$1(UserCreateInput( 12 | email: "seven@odroe.com", 13 | name: PrismaUnion.$1("Seven Du"), 14 | )), 15 | ); 16 | // #endregion snippet 17 | 18 | print({ 19 | "id": user.id, 20 | "name": user.name, 21 | "email": user.email, 22 | "role": user.role, 23 | }); 24 | } 25 | 26 | void main(List args) => providePrisma(createSingleRecord); 27 | -------------------------------------------------------------------------------- /docs-example/codes/delete_all_records.dart: -------------------------------------------------------------------------------- 1 | import '../prisma.dart'; 2 | 3 | void main(List args) { 4 | providePrisma((prisma) async { 5 | // #region snippet 6 | final affectedRows = await prisma.user.deleteMany(); 7 | // #endregion snippet 8 | 9 | print(affectedRows); 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /docs-example/codes/delete_multiple_records.dart: -------------------------------------------------------------------------------- 1 | import 'package:orm/orm.dart'; 2 | 3 | import '../prisma.dart'; 4 | import '../prisma/generated_dart_client/prisma.dart'; 5 | 6 | void main(List args) { 7 | providePrisma((prisma) async { 8 | // #region snippet 9 | final affectedRows = await prisma.user.deleteMany( 10 | where: UserWhereInput( 11 | email: PrismaUnion.$1( 12 | StringFilter( 13 | endsWith: PrismaUnion.$1('@odroe.com'), 14 | ), 15 | ), 16 | ), 17 | ); 18 | // #endregion snippet 19 | 20 | print(affectedRows); 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /docs-example/codes/delete_single_record.dart: -------------------------------------------------------------------------------- 1 | import '../prisma.dart'; 2 | import '../prisma/generated_dart_client/prisma.dart'; 3 | 4 | void main(List args) { 5 | providePrisma((prisma) async { 6 | // #region snippet 7 | final deletedUser = await prisma.user.delete( 8 | where: UserWhereUniqueInput( 9 | email: "bob@prusma.pub", 10 | ), 11 | ); 12 | // #endregion snippet 13 | 14 | print(deletedUser); 15 | }); 16 | } 17 | -------------------------------------------------------------------------------- /docs-example/codes/filter_by_multiple_field_values.dart: -------------------------------------------------------------------------------- 1 | import 'package:orm/orm.dart'; 2 | 3 | import '../prisma.dart'; 4 | import '../prisma/generated_dart_client/model.dart'; 5 | import '../prisma/generated_dart_client/prisma.dart'; 6 | 7 | void main(List args) { 8 | providePrisma((prisma) async { 9 | // #region snippet 10 | final users = await prisma.user.findMany( 11 | where: UserWhereInput( 12 | OR: [ 13 | UserWhereInput( 14 | name: PrismaUnion.$1( 15 | StringNullableFilter(startsWith: PrismaUnion.$1("S")), 16 | ), 17 | ), 18 | UserWhereInput( 19 | role: PrismaUnion.$2(Role.admin), 20 | ), 21 | ], 22 | ), 23 | ); 24 | // #endregion snippet 25 | 26 | print(users); 27 | }); 28 | } 29 | -------------------------------------------------------------------------------- /docs-example/codes/filter_by_related_record_field_values.dart: -------------------------------------------------------------------------------- 1 | import 'package:orm/orm.dart'; 2 | 3 | import '../prisma.dart'; 4 | import '../prisma/generated_dart_client/prisma.dart'; 5 | 6 | void main(List args) { 7 | providePrisma((prisma) async { 8 | // #region snippet 9 | final users = await prisma.user.findMany( 10 | where: UserWhereInput( 11 | email: PrismaUnion.$1( 12 | StringFilter(endsWith: PrismaUnion.$1("@odroe.com")), 13 | ), 14 | posts: PostListRelationFilter( 15 | some: PostWhereInput( 16 | published: PrismaUnion.$2(false), 17 | ), 18 | ), 19 | ), 20 | ); 21 | // #endregion snippet 22 | 23 | print(users); 24 | }); 25 | } 26 | -------------------------------------------------------------------------------- /docs-example/codes/filter_by_single_field_value.dart: -------------------------------------------------------------------------------- 1 | import 'package:orm/orm.dart'; 2 | 3 | import '../prisma.dart'; 4 | import '../prisma/generated_dart_client/prisma.dart'; 5 | 6 | void main(List args) { 7 | providePrisma((prisma) async { 8 | // #region snippet 9 | final users = await prisma.user.findMany( 10 | where: UserWhereInput( 11 | email: PrismaUnion.$1( 12 | StringFilter(endsWith: PrismaUnion.$1('@odroe.com')), 13 | ), 14 | ), 15 | ); 16 | // #endregion snippet 17 | 18 | print(users); 19 | 20 | // #region 1 21 | await prisma.user.findMany( 22 | where: UserWhereInput( 23 | email: PrismaUnion.$1( 24 | StringFilter(endsWith: PrismaUnion.$1('@odroe.com')), 25 | ), 26 | ), 27 | ); 28 | // #endregion 1 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /docs-example/codes/find_or_create_record.dart: -------------------------------------------------------------------------------- 1 | import 'package:orm/orm.dart'; 2 | 3 | import '../prisma.dart'; 4 | import '../prisma/generated_dart_client/client.dart'; 5 | import '../prisma/generated_dart_client/model.dart'; 6 | import '../prisma/generated_dart_client/prisma.dart'; 7 | 8 | // #region extension 9 | extension UserFindOrCreate on UserDelegate { 10 | ActionClient findOrCreate({ 11 | required UserWhereUniqueInput where, 12 | required UserCreateInput data, 13 | // ... More fields can be added here 14 | }) { 15 | return upsert( 16 | where: where, 17 | create: PrismaUnion.$1(data), 18 | // Create a empty update input, make sure the update input is not null 19 | update: PrismaUnion.$2(UserUncheckedUpdateInput()), 20 | ); 21 | } 22 | } 23 | // #endregion extension 24 | 25 | void main(List args) { 26 | providePrisma((prisma) async { 27 | // #region snippet 28 | final user = await prisma.user.findOrCreate( 29 | where: UserWhereUniqueInput(email: "seven@odroe.com"), 30 | data: UserCreateInput( 31 | email: "seven@odroe.com", 32 | name: PrismaUnion.$1("Seven Du"), 33 | ), 34 | ); 35 | // #endregion snippet 36 | 37 | print(user); 38 | }); 39 | } 40 | -------------------------------------------------------------------------------- /docs-example/codes/get_all_records.dart: -------------------------------------------------------------------------------- 1 | import '../prisma.dart'; 2 | 3 | void main(List args) { 4 | providePrisma((prisma) async { 5 | // #region snippet 6 | final users = await prisma.user.findMany(); 7 | // #endregion snippet 8 | 9 | print(users); 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /docs-example/codes/get_first_record_that_matches_criteria.dart: -------------------------------------------------------------------------------- 1 | import 'package:orm/orm.dart'; 2 | 3 | import '../prisma.dart'; 4 | import '../prisma/generated_dart_client/prisma.dart'; 5 | 6 | void main(List args) { 7 | providePrisma((prisma) async { 8 | // #region snippet 9 | final user = await prisma.user.findFirst( 10 | where: UserWhereInput( 11 | posts: PostListRelationFilter( 12 | some: PostWhereInput( 13 | likes: PrismaUnion.$1( 14 | IntFilter(gt: PrismaUnion.$1(100)), 15 | ), 16 | ), 17 | ), 18 | ), 19 | orderBy: PrismaUnion.$2( 20 | UserOrderByWithRelationInput(id: SortOrder.desc), 21 | ), 22 | ); 23 | // #endregion snippet 24 | 25 | print(user); 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /docs-example/codes/get_record_by_id.dart: -------------------------------------------------------------------------------- 1 | import '../prisma.dart'; 2 | import '../prisma/generated_dart_client/prisma.dart'; 3 | 4 | void main(List args) { 5 | providePrisma((prisma) async { 6 | // #region snippet 7 | final user = await prisma.user.findUnique( 8 | where: UserWhereUniqueInput(id: 1), 9 | ); 10 | // #endregion snippet 11 | 12 | print(user); 13 | }); 14 | } 15 | -------------------------------------------------------------------------------- /docs-example/codes/get_record_by_unique_field.dart: -------------------------------------------------------------------------------- 1 | import '../prisma.dart'; 2 | import '../prisma/generated_dart_client/prisma.dart'; 3 | 4 | void main(List args) { 5 | providePrisma((prisma) async { 6 | // #region snippet 7 | final user = await prisma.user.findUnique( 8 | where: UserWhereUniqueInput(email: "seven@odroe.com"), 9 | ); 10 | // #endregion snippet 11 | 12 | print(user); 13 | }); 14 | } 15 | -------------------------------------------------------------------------------- /docs-example/codes/include_related_records.dart: -------------------------------------------------------------------------------- 1 | import 'package:orm/orm.dart'; 2 | 3 | import '../prisma.dart'; 4 | import '../prisma/generated_dart_client/model.dart'; 5 | import '../prisma/generated_dart_client/prisma.dart'; 6 | 7 | void main(List args) { 8 | providePrisma((prisma) async { 9 | // #region snippet 10 | final users = await prisma.user.findMany( 11 | where: UserWhereInput( 12 | role: PrismaUnion.$2(Role.admin), 13 | ), 14 | include: UserInclude( 15 | posts: PrismaUnion.$1(true), 16 | ), 17 | ); 18 | // #endregion snippet 19 | 20 | print(users); 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /docs-example/codes/include_relation_fields.dart: -------------------------------------------------------------------------------- 1 | import 'package:orm/orm.dart'; 2 | 3 | import '../prisma.dart'; 4 | import '../prisma/generated_dart_client/prisma.dart'; 5 | 6 | void main(List args) { 7 | providePrisma((prisma) async { 8 | // #region snippet 9 | final users = await prisma.user.findMany( 10 | select: UserSelect( 11 | name: true, 12 | posts: PrismaUnion.$2( 13 | UserPostsArgs( 14 | select: PostSelect(title: true), 15 | ), 16 | ), 17 | ), 18 | ); 19 | // #endregion snippet 20 | 21 | print(users); 22 | }); 23 | } 24 | -------------------------------------------------------------------------------- /docs-example/codes/include_relation_fields_with_select.dart: -------------------------------------------------------------------------------- 1 | import 'package:orm/orm.dart'; 2 | 3 | import '../prisma.dart'; 4 | import '../prisma/generated_dart_client/prisma.dart'; 5 | 6 | void main(List args) { 7 | providePrisma((prisma) async { 8 | // #region snippet 9 | final users = await prisma.user.findMany( 10 | include: UserInclude( 11 | posts: PrismaUnion.$2( 12 | UserPostsArgs( 13 | select: PostSelect(title: true), 14 | ), 15 | ), 16 | ), 17 | ); 18 | // #endregion snippet 19 | 20 | print(users); 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /docs-example/codes/nested_read.dart: -------------------------------------------------------------------------------- 1 | import 'package:orm/orm.dart'; 2 | 3 | import '../prisma.dart'; 4 | import '../prisma/generated_dart_client/prisma.dart'; 5 | 6 | void main(List args) { 7 | providePrisma((prisma) async { 8 | // #region snippet 9 | final user = await prisma.user.findFirst( 10 | include: UserInclude( 11 | posts: PrismaUnion.$1(true), 12 | ), 13 | ); 14 | // #endregion snippet 15 | 16 | print(user); 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /docs-example/codes/pagination.dart: -------------------------------------------------------------------------------- 1 | import '../prisma.dart'; 2 | 3 | void main(List args) => providePrisma((prisma) async { 4 | // #region 1 5 | final results = await prisma.user.findMany( 6 | take: 4, 7 | skip: 3, 8 | ); 9 | // #endregion 1 10 | print(results); 11 | }); 12 | -------------------------------------------------------------------------------- /docs-example/codes/post_with_author.dart: -------------------------------------------------------------------------------- 1 | import 'package:orm/orm.dart'; 2 | 3 | import '../prisma.dart'; 4 | import '../prisma/generated_dart_client/prisma.dart'; 5 | 6 | void main(List args) { 7 | providePrisma((prisma) async { 8 | // #region snippet 9 | final user = await prisma.post.findFirst( 10 | include: PostInclude( 11 | author: PrismaUnion.$1(true), 12 | ), 13 | ); 14 | // #endregion snippet 15 | 16 | print(user); 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /docs-example/codes/select_subset_of_fields.dart: -------------------------------------------------------------------------------- 1 | import '../prisma.dart'; 2 | import '../prisma/generated_dart_client/prisma.dart'; 3 | 4 | void main(List args) { 5 | providePrisma((prisma) async { 6 | // #region snippet 7 | final user = await prisma.user.findUnique( 8 | where: UserWhereUniqueInput(email: "seven@odroe.com"), 9 | select: UserSelect( 10 | name: true, 11 | email: true, 12 | ), 13 | ); 14 | // #endregion snippet 15 | 16 | print(user); 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /docs-example/codes/select_subset_of_related_record_fields.dart: -------------------------------------------------------------------------------- 1 | import 'package:orm/orm.dart'; 2 | 3 | import '../prisma.dart'; 4 | import '../prisma/generated_dart_client/prisma.dart'; 5 | 6 | void main(List args) { 7 | providePrisma((prisma) async { 8 | // #region snippet 9 | final user = await prisma.user.findUnique( 10 | where: UserWhereUniqueInput(email: "seven@odroe.com"), 11 | select: UserSelect( 12 | email: true, 13 | posts: PrismaUnion.$2( 14 | UserPostsArgs( 15 | select: PostSelect(likes: true), 16 | ), 17 | ), 18 | ), 19 | ); 20 | // #endregion snippet 21 | 22 | print(user); 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /docs-example/codes/update_multiple_records.dart: -------------------------------------------------------------------------------- 1 | import 'package:orm/orm.dart'; 2 | 3 | import '../prisma.dart'; 4 | import '../prisma/generated_dart_client/model.dart'; 5 | import '../prisma/generated_dart_client/prisma.dart'; 6 | 7 | void main(List args) { 8 | providePrisma((prisma) async { 9 | // #region snippet 10 | final affectedRows = await prisma.user.updateMany( 11 | where: UserWhereInput( 12 | email: PrismaUnion.$1( 13 | StringFilter(endsWith: PrismaUnion.$1("@odroe.com")), 14 | ), 15 | ), 16 | data: PrismaUnion.$1( 17 | UserUpdateManyMutationInput( 18 | role: PrismaUnion.$1(Role.admin), 19 | ), 20 | ), 21 | ); 22 | // #endregion snippet 23 | 24 | print(affectedRows); 25 | }); 26 | } 27 | -------------------------------------------------------------------------------- /docs-example/codes/update_number_field.dart: -------------------------------------------------------------------------------- 1 | import 'package:orm/orm.dart'; 2 | 3 | import '../prisma.dart'; 4 | import '../prisma/generated_dart_client/prisma.dart'; 5 | 6 | void main(List args) { 7 | providePrisma((prisma) async { 8 | // #region snippet 9 | final affectedRows = await prisma.post.updateMany( 10 | data: PrismaUnion.$1( 11 | PostUpdateManyMutationInput( 12 | views: PrismaUnion.$2( 13 | IntFieldUpdateOperationsInput(increment: 1), 14 | ), 15 | likes: PrismaUnion.$2( 16 | IntFieldUpdateOperationsInput(increment: 1), 17 | ), 18 | ), 19 | ), 20 | ); 21 | // #endregion snippet 22 | 23 | print(affectedRows); 24 | }); 25 | } 26 | -------------------------------------------------------------------------------- /docs-example/codes/update_or_create_record.dart: -------------------------------------------------------------------------------- 1 | import 'package:orm/orm.dart'; 2 | 3 | import '../prisma.dart'; 4 | import '../prisma/generated_dart_client/prisma.dart'; 5 | 6 | void main(List args) { 7 | providePrisma((prisma) async { 8 | // #region snippet 9 | final user = await prisma.user.upsert( 10 | where: UserWhereUniqueInput(email: "medz@prisma.pub"), 11 | create: PrismaUnion.$1(UserCreateInput( 12 | email: "medz@prisma.pub", 13 | name: PrismaUnion.$1("Seven at GitHub username"), 14 | )), 15 | update: PrismaUnion.$1( 16 | UserUpdateInput( 17 | name: PrismaUnion.$1("Seven at GitHub username"), 18 | ), 19 | ), 20 | ); 21 | // #endregion snippet 22 | 23 | print(user); 24 | }); 25 | } 26 | -------------------------------------------------------------------------------- /docs-example/codes/update_single_record.dart: -------------------------------------------------------------------------------- 1 | import 'package:orm/orm.dart'; 2 | 3 | import '../prisma.dart'; 4 | import '../prisma/generated_dart_client/prisma.dart'; 5 | 6 | void main(List args) { 7 | providePrisma((prisma) async { 8 | // #region snippet 9 | final updatedUser = await prisma.user.update( 10 | where: UserWhereUniqueInput(email: "seven@odroe.com"), 11 | data: PrismaUnion.$2( 12 | UserUncheckedUpdateInput( 13 | name: PrismaUnion.$1("Seven Odroe"), 14 | ), 15 | ), 16 | ); 17 | // #endregion snippet 18 | 19 | print(updatedUser); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /docs-example/codes/user_with_posts_title.dart: -------------------------------------------------------------------------------- 1 | import 'package:orm/orm.dart'; 2 | 3 | import '../prisma.dart'; 4 | import '../prisma/generated_dart_client/prisma.dart'; 5 | 6 | void main(List args) { 7 | providePrisma((prisma) async { 8 | // #region snippet 9 | final user = await prisma.user.findFirst( 10 | select: UserSelect( 11 | name: true, 12 | posts: PrismaUnion.$2( 13 | UserPostsArgs( 14 | select: PostSelect(title: true), 15 | ), 16 | ), 17 | ), 18 | ); 19 | // #endregion snippet 20 | 21 | print(user); 22 | }); 23 | 24 | providePrisma((prisma) async { 25 | // #region select-only-nested-posts-title 26 | final user = await prisma.user.findFirst( 27 | include: UserInclude( 28 | posts: PrismaUnion.$2( 29 | UserPostsArgs( 30 | select: PostSelect(title: true), 31 | ), 32 | ), 33 | ), 34 | ); 35 | // #endregion select-only-nested-posts-title 36 | 37 | print(user); 38 | }); 39 | } 40 | -------------------------------------------------------------------------------- /docs-example/codes/user_with_posts_with_categories.dart: -------------------------------------------------------------------------------- 1 | import 'package:orm/orm.dart'; 2 | 3 | import '../prisma.dart'; 4 | import '../prisma/generated_dart_client/prisma.dart'; 5 | 6 | void main(List args) { 7 | providePrisma((prisma) async { 8 | // #region snippet 9 | final user = await prisma.user.findFirst( 10 | include: UserInclude( 11 | posts: PrismaUnion.$2( 12 | UserPostsArgs( 13 | include: PostInclude( 14 | categories: PrismaUnion.$1(true), 15 | ), 16 | ), 17 | ), 18 | ), 19 | ); 20 | // #endregion snippet 21 | 22 | print(user); 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /docs-example/prisma.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'prisma/generated_dart_client/client.dart'; 4 | 5 | /// Create a new instance of PrismaClient 6 | final _client = PrismaClient(); 7 | 8 | /// Provide a PrismaClient instance to a function. 9 | /// 10 | /// Wrapped in a function to ensure that the instance is diconnected 11 | /// after the function is done. 12 | FutureOr providePrisma( 13 | FutureOr Function(PrismaClient prisma) main) async { 14 | try { 15 | return await main(_client); 16 | } finally { 17 | await _client.$disconnect(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /docs-example/prisma/schema.prisma: -------------------------------------------------------------------------------- 1 | // This is your Prisma schema file, 2 | // learn more about it in the docs: https://pris.ly/d/prisma-schema 3 | 4 | generator client { 5 | provider = "dart run orm" 6 | } 7 | 8 | datasource db { 9 | provider = "postgresql" 10 | url = env("DATABASE_URL") 11 | } 12 | 13 | model User { 14 | id Int @id @default(autoincrement()) 15 | email String @unique 16 | name String? 17 | age Int? 18 | role Role @default(USER) 19 | posts Post[] 20 | Profile Profile? 21 | country String? 22 | city String? 23 | profileViews Int @default(0) 24 | } 25 | 26 | model Post { 27 | id Int @id @default(autoincrement()) 28 | title String 29 | content String? 30 | published Boolean @default(false) 31 | author User? @relation(fields: [authorId], references: [id]) 32 | authorId Int? 33 | categories Category[] 34 | views Int @default(0) 35 | likes Int @default(0) 36 | tags String[] @default([]) 37 | } 38 | 39 | model Profile { 40 | id Int @id @default(autoincrement()) 41 | bio String? 42 | user User @relation(fields: [userId], references: [id]) 43 | userId Int @unique 44 | } 45 | 46 | model Category { 47 | id Int @id @default(autoincrement()) 48 | name String @unique 49 | posts Post[] 50 | } 51 | 52 | enum Role { 53 | USER 54 | ADMIN 55 | } 56 | -------------------------------------------------------------------------------- /docs-example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: prisma_dart_docs_example 2 | description: Prisma Dart Client Example 3 | version: 1.0.0 4 | publish_to: "none" 5 | resolution: workspace 6 | repository: https://github.com/medz/prisma-dart 7 | homepage: https://github.com/medz/prisma-dart/tree/master/example 8 | 9 | environment: 10 | sdk: ^3.5.0 11 | 12 | dependencies: 13 | orm: 14 | path: ../packages/orm 15 | 16 | dev_dependencies: 17 | lints: ^6.0.0 18 | test: ^1.24.8 19 | -------------------------------------------------------------------------------- /docs-example/transactions.dart: -------------------------------------------------------------------------------- 1 | import 'package:orm/orm.dart'; 2 | 3 | import 'prisma/generated_dart_client/client.dart'; 4 | import 'prisma/generated_dart_client/prisma.dart'; 5 | 6 | void main(List args) async { 7 | final prisma = PrismaClient(); 8 | try { 9 | // #region interactive 10 | /// Transfer views from one post to another 11 | transfer(int from, int to, int views) async { 12 | await prisma.$transaction((tx) async { 13 | // 1. Decrement views from the source post 14 | await tx.post.update( 15 | where: PostWhereUniqueInput(id: from), 16 | data: PrismaUnion.$1( 17 | PostUpdateInput( 18 | views: PrismaUnion.$2( 19 | IntFieldUpdateOperationsInput(decrement: views), 20 | ), 21 | ), 22 | ), 23 | ); 24 | 25 | // 2. Increment views from the destination post 26 | await tx.post.update( 27 | where: PostWhereUniqueInput(id: to), 28 | data: PrismaUnion.$1( 29 | PostUpdateInput( 30 | views: PrismaUnion.$2( 31 | IntFieldUpdateOperationsInput(increment: views), 32 | ), 33 | ), 34 | ), 35 | ); 36 | }); 37 | } 38 | 39 | await transfer(1, 2, 10); // Transfer 10 views from post 1 to post 2 40 | await transfer(2, 1, 10); // Transfer 10 views from post 2 to post 1 41 | // #endregion interactive 42 | 43 | // #region catch 44 | try { 45 | await prisma.$transaction((tx) async { 46 | // Code running in a transaction... 47 | }); 48 | } catch (e) { 49 | // Handle the rollback... 50 | } 51 | // #endregion catch 52 | 53 | // #region isolation 54 | await prisma.$transaction( 55 | isolationLevel: TransactionIsolationLevel.serializable, // [!code focus] 56 | (tx) async { 57 | // Code running in a transaction... 58 | }, 59 | ); 60 | // #endregion isolation 61 | 62 | // #region timeout 63 | await prisma.$transaction( 64 | (tx) async { 65 | // Code running in a transaction... 66 | }, 67 | maxWait: 5000, // Default is 2000 // [!code focus] 68 | timeout: 10000, // Default is 5000 // [!code focus] 69 | ); 70 | // #endregion timeout 71 | 72 | // #region manual 73 | final tx = await prisma.$transaction.start(); // [!code focus] 74 | try { 75 | // Delete all posts 76 | await tx.post.deleteMany(); 77 | // Delete all users 78 | await tx.user.deleteMany(); 79 | 80 | // Commit the transaction 81 | await tx.$transaction.commit(); // [!code focus] 82 | } catch (e) { 83 | // Rollback the transaction 84 | await tx.$transaction.rollback(); // [!code focus] 85 | } 86 | // #endregion manual 87 | } finally { 88 | await prisma.$disconnect(); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /docs/.vitepress/.gitignore: -------------------------------------------------------------------------------- 1 | /cache 2 | /dist -------------------------------------------------------------------------------- /docs/.vitepress/theme/index.ts: -------------------------------------------------------------------------------- 1 | // https://vitepress.dev/guide/custom-theme 2 | import { h } from 'vue'; 3 | import type { Theme } from 'vitepress'; 4 | import DefaultTheme from 'vitepress/theme'; 5 | import './style.css'; 6 | 7 | export default { 8 | extends: DefaultTheme, 9 | Layout: () => { 10 | return h(DefaultTheme.Layout, null, { 11 | // https://vitepress.dev/guide/extending-default-theme#layout-slots 12 | }); 13 | }, 14 | enhanceApp({ app, router, siteData }) { 15 | // ... 16 | }, 17 | } satisfies Theme; 18 | -------------------------------------------------------------------------------- /docs/getting-started/upgrade_guides.md: -------------------------------------------------------------------------------- 1 | # Upgrade Guides 2 | 3 | ## Prisma Dart v4 -> v5 & Flutter integration 4 | 5 | Upgrading from Prisma Dart v4 to v5 is relatively simple. Although it is a major version change, there are no changes to user APIs. 6 | 7 | ### `engineType` in Prisma schema 8 | 9 | Now, in the Flutter integration, you tell the generator that you want to generate a client for Flutter: 10 | 11 | ```prisma 12 | generator client { 13 | provider = "dart run orm" 14 | output = "../lib/_generated_prisma_client" 15 | engineType = "flutter" // [!code focus] 16 | } 17 | ``` 18 | 19 | ### `PrismaClient` 20 | 21 | Major changes to Prisma Client: 22 | 23 | 1. Changed from an isolated type to a self-dependent type with `Class PrismaClient extends BasePrismaClient`. 24 | 2. Deprecated `PrismaClient.use` method. 25 | 26 | Before: 27 | 28 | ```dart 29 | final prisma = PrismaClient.use((schema, datasoruce) { 30 | /// Your codes, create engine and returns. 31 | }); 32 | ``` 33 | 34 | Now: 35 | 36 | ```dart 37 | final engine = ...; // You created engine instance. 38 | final prisma = PrismaClient(engine: engine); 39 | ``` 40 | 41 | ### Logging 42 | 43 | Previously, we relied on the `logging` package for logging. Then you needed to listen for the logs and output them yourself. 44 | 45 | Now, Prisma Dart implements the same logging as the Prisma TS/JS client. 46 | 47 | For more logging information, see 👉 [Prisma Logging](https://www.prisma.io/docs/orm/prisma-client/observability-and-logging/logging). 48 | 49 | #### Output to console 50 | 51 | Before: 52 | 53 | ```dart 54 | import 'package:loging/loging.dart'; 55 | 56 | Logger.root.onRecore.listen((log) { 57 | print(log.message); 58 | }); 59 | ``` 60 | 61 | Now: 62 | 63 | ```dart 64 | final prisma = PrismaClient( 65 | log: { 66 | (LogLevel.query, LogEmit.stdout), 67 | // ... More level configs 68 | }, 69 | ); 70 | ``` 71 | 72 | #### Log event 73 | 74 | Before: 75 | 76 | ```dart 77 | import 'package:loging/loging.dart'; 78 | 79 | Logger.root.onRecore.listen((log) { 80 | //... You custon. 81 | }); 82 | ``` 83 | 84 | Now: 85 | 86 | ```dart 87 | final prisma = PrismaClient( 88 | log: { 89 | (LogLevel.query, LogEmit.event), 90 | // ... More level configs 91 | }, 92 | ); 93 | 94 | prisma.$on(LogLevel.query, (event) { 95 | // ... 96 | }); 97 | ``` 98 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | # https://vitepress.dev/reference/default-theme-home-page 3 | layout: home 4 | 5 | hero: 6 | name: Prisma Client Dart 7 | text: Auto-generated type-safe ORM 8 | tagline: It uses Prisma Engine as the data access layer and is as consistent as possible with the Prisma Client JS/TS APIs 9 | image: 10 | src: /prisma-dart.logo.svg 11 | alt: Prisma Dart client logo 12 | actions: 13 | - theme: brand 14 | text: ⚡️ Get Started 15 | link: /getting-started/ 16 | - theme: alt 17 | text: ♥︎ Sponsor 18 | link: https://github.com/sponsors/medz 19 | - theme: alt 20 | text: View on GitHub 21 | link: https://github.com/medz/prisma-dart?sponsor=1 22 | 23 | features: 24 | - title: Human Readability 25 | details: The Prisma schema is intuitive and lets you declare your database tables in a human-readable way — making your data modeling experience a delight. You define your models by hand or introspect them from an existing database. 26 | - title: Type-safe Client 27 | details: Prisma Client is a query builder that’s tailored to your schema. We designed its API to be intuitive, both for SQL veterans and developers brand new to databases. The auto-completion helps you figure out your query without the need for documentation. 28 | - title: Most Popular Databases 29 | details: Prisma works seamlessly across most popular databases and service providers. | PostgreSQL, MySQL, MariaDB, SQL Server, SQLite, MongoDB and CockroachDB. 30 | --- 31 | -------------------------------------------------------------------------------- /docs/public/prisma-dart.logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/queries/pagination.md: -------------------------------------------------------------------------------- 1 | # Pagination 2 | 3 | Offset pagination uses skip and take to skip a certain number of results and select a limited range. The following query skips the first 3 Post records and returns records 4 - 7: 4 | 5 | <<< @/../docs-example/codes/pagination.dart#1 6 | 7 | ![Offset pagination](https://www.prisma.io/docs/static/8df25c634020d1248b40fc93c59bc93d/4c573/offset-skip-take.png) 8 | 9 | ::: tip 10 | 11 | About more pagination see 👉 [Pagination](https://www.prisma.io/docs/orm/prisma-client/queries/pagination) Prisma documentation. 12 | 13 | ::: 14 | -------------------------------------------------------------------------------- /docs/queries/raw-database-access.md: -------------------------------------------------------------------------------- 1 | # Raw database access 2 | 3 | Although the model delegate API of Prisma Dart Client covers most database operations, in certain cases, you may need to directly access the database to perform SQL dialect-specific operations. 4 | 5 | In the Prisma Dart Client, you access the `$raw` property to get a Raw Client instance of the current database connection. This client provides the following two methods: 6 | 7 | - `$raw.query` 8 | - `$raw.execute` 9 | 10 | ## `$raw.query` 11 | 12 | Execute a raw query, for example: 13 | 14 | ```dart 15 | final result = await prisma.$raw.query('SELECT * FROM "User"'); // PostgreSQL 16 | ``` 17 | 18 | ## `$raw.execute` 19 | 20 | Execute a raw query, for example: 21 | 22 | ```dart 23 | final result = await prisma.$raw.execute('DELETE FROM "User"'); // PostgreSQL 24 | ``` 25 | 26 | ## Parameters 27 | 28 | `$raw.query` and `$raw.execute` support parameters, for example: 29 | 30 | ```dart 31 | // PostgreSQL 32 | final result = await prisma.$raw.query( 33 | 'SELECT * FROM "User" WHERE "id" = \$1', 34 | [1], 35 | ); 36 | 37 | // MySQL 38 | final result = await prisma.$raw.query( 39 | 'SELECT * FROM `User` WHERE `id` = ?', 40 | [1], 41 | ); 42 | ``` 43 | 44 | ::: tip 45 | 46 | SQL template strings vary depending on the database you are using, you should consult the documentation of the database you are using for details on the SQL dialect. 47 | 48 | ::: 49 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .build/ 9 | .buildlog/ 10 | .history 11 | .svn/ 12 | .swiftpm/ 13 | migrate_working_dir/ 14 | 15 | # IntelliJ related 16 | *.iml 17 | *.ipr 18 | *.iws 19 | .idea/ 20 | 21 | # The .vscode folder contains launch configuration and tasks you configure in 22 | # VS Code which you may wish to be included in version control, so this line 23 | # is commented out by default. 24 | #.vscode/ 25 | 26 | # Flutter/Dart/Pub related 27 | **/doc/api/ 28 | **/ios/Flutter/.last_build_id 29 | .dart_tool/ 30 | .flutter-plugins 31 | .flutter-plugins-dependencies 32 | .pub-cache/ 33 | .pub/ 34 | /build/ 35 | 36 | # Symbolication related 37 | app.*.symbols 38 | 39 | # Obfuscation related 40 | app.*.map.json 41 | 42 | # Android Studio will place build artifacts here 43 | /android/app/debug 44 | /android/app/profile 45 | /android/app/release 46 | 47 | # Project 48 | prisma-query-engine 49 | prisma/db.sqlite* 50 | lib/_generated_prisma_client 51 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: "2e2c358c9b14765c90343af9df11e12c5dfc3e6c" 8 | channel: "beta" 9 | 10 | project_type: app 11 | 12 | # Tracks metadata for the flutter migrate command 13 | migration: 14 | platforms: 15 | - platform: root 16 | create_revision: 2e2c358c9b14765c90343af9df11e12c5dfc3e6c 17 | base_revision: 2e2c358c9b14765c90343af9df11e12c5dfc3e6c 18 | - platform: android 19 | create_revision: 2e2c358c9b14765c90343af9df11e12c5dfc3e6c 20 | base_revision: 2e2c358c9b14765c90343af9df11e12c5dfc3e6c 21 | 22 | # User provided section 23 | 24 | # List of Local paths (relative to this file) that should be 25 | # ignored by the migrate tool. 26 | # 27 | # Files that are not part of the templates will be ignored by default. 28 | unmanaged_files: 29 | - 'lib/main.dart' 30 | - 'ios/Runner.xcodeproj/project.pbxproj' 31 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/README.md: -------------------------------------------------------------------------------- 1 | # flutter_with_orm 2 | 3 | A new Flutter project. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) 13 | 14 | For help getting started with Flutter development, view the 15 | [online documentation](https://docs.flutter.dev/), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the analyzer, which statically analyzes Dart code to 2 | # check for errors, warnings, and lints. 3 | # 4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled 5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be 6 | # invoked from the command line by running `flutter analyze`. 7 | 8 | # The following line activates a set of recommended lints for Flutter apps, 9 | # packages, and plugins designed to encourage good coding practices. 10 | include: package:flutter_lints/flutter.yaml 11 | 12 | linter: 13 | # The lint rules applied to this project can be customized in the 14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml` 15 | # included above or to enable additional rules. A list of all available lints 16 | # and their documentation is published at https://dart.dev/lints. 17 | # 18 | # Instead of disabling a lint rule for the entire project in the 19 | # section below, it can also be suppressed for a single line of code 20 | # or a specific dart file by using the `// ignore: name_of_lint` and 21 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file 22 | # producing the lint. 23 | rules: 24 | # avoid_print: false # Uncomment to disable the `avoid_print` rule 25 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule 26 | 27 | # Additional information about this file can be found at 28 | # https://dart.dev/guides/language/analysis-options 29 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/to/reference-keystore 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "com.android.application" 3 | id "kotlin-android" 4 | // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. 5 | id "dev.flutter.flutter-gradle-plugin" 6 | } 7 | 8 | android { 9 | namespace = "dev.odroe.prisma_flutter_example" 10 | compileSdk = flutter.compileSdkVersion 11 | ndkVersion = flutter.ndkVersion 12 | 13 | compileOptions { 14 | sourceCompatibility = JavaVersion.VERSION_1_8 15 | targetCompatibility = JavaVersion.VERSION_1_8 16 | } 17 | 18 | kotlinOptions { 19 | jvmTarget = JavaVersion.VERSION_1_8 20 | } 21 | 22 | defaultConfig { 23 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 24 | applicationId = "dev.odroe.prisma_flutter_example" 25 | // You can update the following values to match your application needs. 26 | // For more information, see: https://flutter.dev/to/review-gradle-config. 27 | minSdk = flutter.minSdkVersion 28 | targetSdk = flutter.targetSdkVersion 29 | versionCode = flutter.versionCode 30 | versionName = flutter.versionName 31 | } 32 | 33 | buildTypes { 34 | release { 35 | // TODO: Add your own signing config for the release build. 36 | // Signing with the debug keys for now, so `flutter run --release` works. 37 | signingConfig = signingConfigs.debug 38 | } 39 | } 40 | } 41 | 42 | flutter { 43 | source = "../.." 44 | } 45 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 15 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 33 | 34 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/examples/flutter_with_orm/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/flutter_with_orm/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/examples/flutter_with_orm/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/flutter_with_orm/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/examples/flutter_with_orm/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/flutter_with_orm/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/examples/flutter_with_orm/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/flutter_with_orm/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/examples/flutter_with_orm/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/flutter_with_orm/android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/android/build.gradle: -------------------------------------------------------------------------------- 1 | allprojects { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | } 6 | } 7 | 8 | rootProject.buildDir = "../build" 9 | subprojects { 10 | project.buildDir = "${rootProject.buildDir}/${project.name}" 11 | } 12 | subprojects { 13 | project.evaluationDependsOn(":app") 14 | } 15 | 16 | tasks.register("clean", Delete) { 17 | delete rootProject.buildDir 18 | } 19 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip 6 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | def flutterSdkPath = { 3 | def properties = new Properties() 4 | file("local.properties").withInputStream { properties.load(it) } 5 | def flutterSdkPath = properties.getProperty("flutter.sdk") 6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 7 | return flutterSdkPath 8 | }() 9 | 10 | includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") 11 | 12 | repositories { 13 | google() 14 | mavenCentral() 15 | gradlePluginPortal() 16 | } 17 | } 18 | 19 | plugins { 20 | id "dev.flutter.flutter-plugin-loader" version "1.0.0" 21 | id "com.android.application" version "8.1.0" apply false 22 | id "org.jetbrains.kotlin.android" version "1.8.22" apply false 23 | } 24 | 25 | include ":app" 26 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 12.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '12.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | use_frameworks! 32 | use_modular_headers! 33 | 34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 35 | target 'RunnerTests' do 36 | inherit! :search_paths 37 | end 38 | end 39 | 40 | post_install do |installer| 41 | installer.pods_project.targets.each do |target| 42 | flutter_additional_ios_build_settings(target) 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Flutter (1.0.0) 3 | - orm_flutter_ios (0.0.3): 4 | - Flutter 5 | - path_provider_foundation (0.0.1): 6 | - Flutter 7 | - FlutterMacOS 8 | 9 | DEPENDENCIES: 10 | - Flutter (from `Flutter`) 11 | - orm_flutter_ios (from `.symlinks/plugins/orm_flutter_ios/ios`) 12 | - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) 13 | 14 | EXTERNAL SOURCES: 15 | Flutter: 16 | :path: Flutter 17 | orm_flutter_ios: 18 | :path: ".symlinks/plugins/orm_flutter_ios/ios" 19 | path_provider_foundation: 20 | :path: ".symlinks/plugins/path_provider_foundation/darwin" 21 | 22 | SPEC CHECKSUMS: 23 | Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 24 | orm_flutter_ios: a86280da5be8ad09f28571bdab395ad0cb022b82 25 | path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 26 | 27 | PODFILE CHECKSUM: 819463e6a0290f5a72f145ba7cde16e8b6ef0796 28 | 29 | COCOAPODS: 1.15.2 30 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | 4 | @main 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/examples/flutter_with_orm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/examples/flutter_with_orm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/examples/flutter_with_orm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/examples/flutter_with_orm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/examples/flutter_with_orm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/examples/flutter_with_orm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/examples/flutter_with_orm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/examples/flutter_with_orm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/examples/flutter_with_orm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/examples/flutter_with_orm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/examples/flutter_with_orm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/examples/flutter_with_orm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/examples/flutter_with_orm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/examples/flutter_with_orm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/examples/flutter_with_orm/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/examples/flutter_with_orm/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/examples/flutter_with_orm/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/examples/flutter_with_orm/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | Flutter With Orm 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | flutter_with_orm 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(FLUTTER_BUILD_NUMBER) 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | CADisableMinimumFrameDurationOnPhone 45 | 46 | UIApplicationSupportsIndirectInputEvents 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/ios/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | import XCTest 4 | 5 | class RunnerTests: XCTestCase { 6 | 7 | func testExample() { 8 | // If you add code to the Runner application, consider adding tests here. 9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest. 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/lib/prisma.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | import 'package:orm_flutter/orm_flutter.dart'; 3 | import 'package:path/path.dart'; 4 | import 'package:path_provider/path_provider.dart'; 5 | 6 | import '_generated_prisma_client/client.dart'; 7 | 8 | late final PrismaClient prisma; 9 | 10 | Future initPrismaClient() async { 11 | WidgetsFlutterBinding.ensureInitialized(); 12 | 13 | final supportDir = await getApplicationSupportDirectory(); 14 | final database = join(supportDir.path, 'database.sqlite.db'); 15 | 16 | prisma = PrismaClient(datasourceUrl: 'file:$database'); 17 | final engine = switch (prisma.$engine) { 18 | LibraryEngine engine => engine, 19 | _ => null, 20 | }; 21 | 22 | await prisma.$connect(); 23 | await engine?.applyMigrations(path: 'prisma/migrations'); 24 | } 25 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/prisma/migrations/20240528135435_init/migration.sql: -------------------------------------------------------------------------------- 1 | -- CreateTable 2 | CREATE TABLE "User" ( 3 | "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, 4 | "name" TEXT NOT NULL 5 | ); 6 | -------------------------------------------------------------------------------- /examples/flutter_with_orm/prisma/migrations/migration_lock.toml: -------------------------------------------------------------------------------- 1 | # Please do not edit this file manually 2 | # It should be added in your version-control system (i.e. Git) 3 | provider = "sqlite" -------------------------------------------------------------------------------- /examples/flutter_with_orm/prisma/schema.prisma: -------------------------------------------------------------------------------- 1 | // This is your Prisma schema file, 2 | // learn more about it in the docs: https://pris.ly/d/prisma-schema 3 | 4 | generator client { 5 | provider = "dart run orm" 6 | output = "../lib/_generated_prisma_client" 7 | engineType = "flutter" 8 | } 9 | 10 | datasource db { 11 | provider = "sqlite" 12 | url = "file:./db.sqlite" 13 | } 14 | 15 | model User { 16 | id Int @id @default(autoincrement()) 17 | name String 18 | } 19 | -------------------------------------------------------------------------------- /examples/with_postgres/.gitignore: -------------------------------------------------------------------------------- 1 | # https://dart.dev/guides/libraries/private-files 2 | # Created by `dart pub` 3 | .dart_tool/ 4 | -------------------------------------------------------------------------------- /examples/with_postgres/README.md: -------------------------------------------------------------------------------- 1 | A sample command-line application with an entrypoint in `bin/`, library code 2 | in `lib/`, and example unit test in `test/`. 3 | -------------------------------------------------------------------------------- /examples/with_postgres/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the static analysis results for your project (errors, 2 | # warnings, and lints). 3 | # 4 | # This enables the 'recommended' set of lints from `package:lints`. 5 | # This set helps identify many issues that may lead to problems when running 6 | # or consuming Dart code, and enforces writing Dart using a single, idiomatic 7 | # style and format. 8 | # 9 | # If you want a smaller set of lints you can change this to specify 10 | # 'package:lints/core.yaml'. These are just the most critical lints 11 | # (the recommended set includes the core lints). 12 | # The core lints are also what is used by pub.dev for scoring packages. 13 | 14 | include: package:lints/recommended.yaml 15 | 16 | # Uncomment the following section to specify additional rules. 17 | 18 | # linter: 19 | # rules: 20 | # - camel_case_types 21 | 22 | # analyzer: 23 | # exclude: 24 | # - path/to/excluded/files/** 25 | 26 | # For more information about the core and recommended set of lints, see 27 | # https://dart.dev/go/core-lints 28 | 29 | # For additional information about configuring this file, see 30 | # https://dart.dev/guides/language/analysis-options 31 | -------------------------------------------------------------------------------- /examples/with_postgres/app.dart: -------------------------------------------------------------------------------- 1 | import 'package:orm/orm.dart'; 2 | 3 | import 'prisma/generated_dart_client/client.dart'; 4 | import 'prisma/generated_dart_client/prisma.dart'; 5 | 6 | final prisma = PrismaClient(); 7 | 8 | void main() async { 9 | try { 10 | final users = await prisma.user.findMany( 11 | where: UserWhereInput( 12 | name: PrismaUnion.$1( 13 | StringFilter($in: PrismaUnion.$1(['First', 'Last'])), 14 | ), 15 | ), 16 | ); 17 | 18 | print('Found ${users.length} users.'); 19 | } finally { 20 | await prisma.$disconnect(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/with_postgres/prisma/schema.prisma: -------------------------------------------------------------------------------- 1 | // This is your Prisma schema file, 2 | // learn more about it in the docs: https://pris.ly/d/prisma-schema 3 | 4 | // Looking for ways to speed up your queries, or scale easily with your serverless or edge functions? 5 | // Try Prisma Accelerate: https://pris.ly/cli/accelerate-init 6 | 7 | generator client { 8 | provider = "dart run orm" 9 | output = "generated_dart_client" 10 | } 11 | 12 | datasource db { 13 | provider = "postgresql" 14 | url = env("DATABASE_URL") 15 | } 16 | 17 | model User { 18 | id String @id @default(uuid(7)) 19 | name String 20 | createdAt DateTime @default(now()) 21 | } 22 | -------------------------------------------------------------------------------- /examples/with_postgres/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: prisma_with_postgres 2 | description: A sample command-line application. 3 | version: 1.0.0 4 | publish_to: none 5 | resolution: workspace 6 | 7 | environment: 8 | sdk: ^3.5.1 9 | 10 | # Add regular dependencies here. 11 | dependencies: 12 | orm: 13 | path: ../../packages/orm 14 | 15 | dev_dependencies: 16 | lints: ^6.0.0 17 | -------------------------------------------------------------------------------- /examples/with_sqlite/.env: -------------------------------------------------------------------------------- 1 | # Environment variables declared in this file are automatically made available to Prisma. 2 | # See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema 3 | 4 | # Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB. 5 | # See the documentation for all the connection string options: https://pris.ly/d/connection-strings 6 | 7 | DATABASE_URL="file:./prisma/dev.db" # Dart rintime using 8 | DIRECT_DATABASE_URL="file:./dev.db" # Prisma CLI using 9 | -------------------------------------------------------------------------------- /examples/with_sqlite/.gitignore: -------------------------------------------------------------------------------- 1 | # https://dart.dev/guides/libraries/private-files 2 | # Created by `dart pub` 3 | .dart_tool/ 4 | 5 | lib/src/generated_prisma_client 6 | prisma/dev.db 7 | prisma-query-engine 8 | -------------------------------------------------------------------------------- /examples/with_sqlite/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the static analysis results for your project (errors, 2 | # warnings, and lints). 3 | # 4 | # This enables the 'recommended' set of lints from `package:lints`. 5 | # This set helps identify many issues that may lead to problems when running 6 | # or consuming Dart code, and enforces writing Dart using a single, idiomatic 7 | # style and format. 8 | # 9 | # If you want a smaller set of lints you can change this to specify 10 | # 'package:lints/core.yaml'. These are just the most critical lints 11 | # (the recommended set includes the core lints). 12 | # The core lints are also what is used by pub.dev for scoring packages. 13 | 14 | include: package:lints/recommended.yaml 15 | 16 | # Uncomment the following section to specify additional rules. 17 | 18 | # linter: 19 | # rules: 20 | # - camel_case_types 21 | 22 | # analyzer: 23 | # exclude: 24 | # - path/to/excluded/files/** 25 | 26 | # For more information about the core and recommended set of lints, see 27 | # https://dart.dev/go/core-lints 28 | 29 | # For additional information about configuring this file, see 30 | # https://dart.dev/guides/language/analysis-options 31 | -------------------------------------------------------------------------------- /examples/with_sqlite/bin/with_sqlite.dart: -------------------------------------------------------------------------------- 1 | import 'package:orm/orm.dart'; 2 | import 'package:prisma_with_sqlite/with_sqlite.dart'; 3 | 4 | final prisma = PrismaClient(log: { 5 | (LogLevel.query, LogEmit.stdout), 6 | }); 7 | 8 | Future main() async { 9 | try { 10 | // With transaction run query 11 | final gamesWithTransaction = await prisma.$transaction((prisma) async { 12 | final result = await prisma.game.aggregate( 13 | select: AggregateGameSelect( 14 | $count: PrismaUnion.$2( 15 | AggregateGameCountArgs( 16 | select: GameCountAggregateOutputTypeSelect(id: true), 17 | ), 18 | ), 19 | ), 20 | ); 21 | if (result.$count!.id! <= 3) { 22 | await prisma.game.create( 23 | data: PrismaUnion.$2( 24 | GameUncheckedCreateInput(name: 'Game ${result.$count?.id}'), 25 | ), 26 | ); 27 | } 28 | 29 | return await prisma.game.findMany(); 30 | }); 31 | print(gamesWithTransaction.map((e) => e.toJson())); 32 | 33 | // Find many 34 | final games = await prisma.game.findMany(); 35 | print(games.map((e) => e.toJson())); 36 | 37 | // SQL query all rows. 38 | final result = await prisma.$raw.query('SELECT * FROM games'); 39 | print(result); 40 | 41 | // Delete a `game_id` eq "1" row, DB not found "1", returns `0` 42 | print(await prisma.$raw.execute(r'delete from games where game_id = "1"')); 43 | } finally { 44 | await prisma.$disconnect(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /examples/with_sqlite/lib/with_sqlite.dart: -------------------------------------------------------------------------------- 1 | export 'src/generated_prisma_client/client.dart'; 2 | export 'src/generated_prisma_client/model.dart'; 3 | export 'src/generated_prisma_client/prisma.dart'; 4 | -------------------------------------------------------------------------------- /examples/with_sqlite/prisma/schema.prisma: -------------------------------------------------------------------------------- 1 | // This is your Prisma schema file, 2 | // learn more about it in the docs: https://pris.ly/d/prisma-schema 3 | 4 | generator client { 5 | provider = "dart run orm" 6 | output = "../lib/src/generated_prisma_client" 7 | } 8 | 9 | datasource db { 10 | provider = "sqlite" 11 | url = env("DATABASE_URL") 12 | // Why need directUrl ? 13 | // The Prisma CLI tool uses the file URL relative to the prisma directory when it is configured at runtime. The Dart runtime uses PWD 14 | directUrl = env("DIRECT_DATABASE_URL") 15 | } 16 | 17 | model Game { 18 | id String @id @default(uuid()) @map("game_id") 19 | name String @map("game_name") 20 | startsAt DateTime? 21 | 22 | @@map("games") 23 | } 24 | -------------------------------------------------------------------------------- /examples/with_sqlite/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: prisma_with_sqlite 2 | description: A sample command-line application. 3 | version: 1.0.0 4 | publish_to: none 5 | resolution: workspace 6 | 7 | environment: 8 | sdk: ^3.5.0 9 | 10 | # Add regular dependencies here. 11 | dependencies: 12 | orm: 13 | path: ../../packages/orm 14 | 15 | dev_dependencies: 16 | lints: ^6.0.0 17 | -------------------------------------------------------------------------------- /graphs/alipay.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/graphs/alipay.jpg -------------------------------------------------------------------------------- /graphs/wechat_pay.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/graphs/wechat_pay.jpg -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "type": "module", 4 | "scripts": { 5 | "docs:dev": "vitepress dev docs", 6 | "docs:build": "vitepress build docs", 7 | "docs:preview": "vitepress preview docs" 8 | }, 9 | "dependencies": { 10 | "vitepress": "^1.3.4" 11 | }, 12 | "devDependencies": { 13 | "@types/bun": "^1.1.12", 14 | "prisma": "^6.2.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/orm/.gitignore: -------------------------------------------------------------------------------- 1 | # Files and directories created by pub. 2 | .dart_tool/ 3 | .env 4 | 5 | # Omit committing pubspec.lock for library packages; see 6 | # https://dart.dev/guides/libraries/private-files#pubspeclock. 7 | pubspec.lock 8 | 9 | # Development files or directories. 10 | prisma-query-* 11 | prisma/* 12 | !prisma/schema.prisma 13 | test/_generated/ 14 | test/test.db* 15 | -------------------------------------------------------------------------------- /packages/orm/LICENSE: -------------------------------------------------------------------------------- 1 | ../../LICENSE -------------------------------------------------------------------------------- /packages/orm/README.md: -------------------------------------------------------------------------------- 1 | ../../README.md -------------------------------------------------------------------------------- /packages/orm/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the static analysis results for your project (errors, 2 | # warnings, and lints). 3 | # 4 | # This enables the 'recommended' set of lints from `package:lints`. 5 | # This set helps identify many issues that may lead to problems when running 6 | # or consuming Dart code, and enforces writing Dart using a single, idiomatic 7 | # style and format. 8 | # 9 | # If you want a smaller set of lints you can change this to specify 10 | # 'package:lints/core.yaml'. These are just the most critical lints 11 | # (the recommended set includes the core lints). 12 | # The core lints are also what is used by pub.dev for scoring packages. 13 | 14 | include: package:lints/recommended.yaml 15 | # Uncomment the following section to specify additional rules. 16 | 17 | # linter: 18 | # rules: 19 | # non_constant_identifier_names: false 20 | 21 | analyzer: 22 | exclude: 23 | - node_modules/* 24 | # language: 25 | # non-constant-identifier-names: false 26 | 27 | # For more information about the core and recommended set of lints, see 28 | # https://dart.dev/go/core-lints 29 | 30 | # For additional information about configuring this file, see 31 | # https://dart.dev/guides/language/analysis-options 32 | -------------------------------------------------------------------------------- /packages/orm/bin/orm.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:code_builder/code_builder.dart'; 4 | import 'package:dart_style/dart_style.dart'; 5 | import 'package:orm/generator_helper.dart'; 6 | import 'package:orm/version.dart'; 7 | import 'package:path/path.dart'; 8 | 9 | import 'src/generator.dart'; 10 | import 'src/utils/is_flutter_engine_type.dart'; 11 | import 'src/download_engine.dart'; 12 | 13 | void main() async { 14 | final app = GeneratorApp.stdio(stdin: stdin, stdout: stderr); 15 | app.onManifest(manifest); 16 | app.onGenerate(generate); 17 | 18 | await app.listen(); 19 | } 20 | 21 | Future manifest(GeneratorConfig config) async { 22 | final engines = switch (isFlutterEngineType(config.config)) { 23 | true => null, 24 | _ => const [EngineType.queryEngine] 25 | }; 26 | 27 | return GeneratorManifest( 28 | prettyName: 'Prisma Dart Client', 29 | defaultOutput: 'generated_dart_client', 30 | version: 'v$version', 31 | requiresEngines: engines, 32 | ); 33 | } 34 | 35 | Future generate(GeneratorOptions options) async { 36 | if (options.generator.output == null) { 37 | throw StateError('No output directory specified'); 38 | } 39 | 40 | final generator = Generator(options); 41 | final libraries = generator.generate(); 42 | final formatter = 43 | DartFormatter(languageVersion: DartFormatter.latestLanguageVersion); 44 | 45 | for (final (filename, library) in libraries) { 46 | final emitter = DartEmitter.scoped( 47 | useNullSafetySyntax: true, 48 | orderDirectives: true, 49 | ); 50 | final source = library.accept(emitter); 51 | final formated = formatter.format(source.toString()); 52 | final output = await File(join(options.generator.output!.value, filename)) 53 | .autoCreate(); 54 | 55 | await output.writeAsString(formated); 56 | } 57 | 58 | await downloadEngine(options); 59 | } 60 | 61 | extension on File { 62 | Future autoCreate() async { 63 | if (await exists()) { 64 | return this; 65 | } 66 | 67 | await parent.create(recursive: true); 68 | return create(); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /packages/orm/bin/src/download_engine.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:orm/generator_helper.dart'; 4 | import 'package:path/path.dart' as path; 5 | 6 | import 'utils/is_flutter_engine_type.dart'; 7 | 8 | Future downloadEngine(GeneratorOptions options) async { 9 | if (isFlutterEngineType(options.generator.config)) { 10 | return; 11 | } 12 | 13 | final sourcePath = options.binaryPaths.queryEngine?.values.firstOrNull; 14 | if (sourcePath == null) { 15 | print("⚠️[orm] Binary engine not found."); 16 | return; 17 | } 18 | 19 | final source = File(sourcePath); 20 | if (!await source.exists()) { 21 | print( 22 | '⚠️[orm] Prisma provided the engine path, but the file does not exist'); 23 | return; 24 | } 25 | 26 | final target = 27 | File(path.join(path.dirname(options.schemaPath), 'prisma-query-engine')); 28 | if (await target.exists()) { 29 | await target.delete(recursive: true); 30 | } 31 | 32 | await source.copy(target.path); 33 | } 34 | -------------------------------------------------------------------------------- /packages/orm/bin/src/generate_field_ref.dart: -------------------------------------------------------------------------------- 1 | import 'package:code_builder/code_builder.dart'; 2 | import 'package:orm/dmmf.dart' as dmmf; 3 | 4 | import 'generate_type.dart'; 5 | import 'generator.dart'; 6 | 7 | extension GenerateFieldRef on Generator { 8 | Reference generateFieldRef(String name) { 9 | final ref = findRef(name).allowTypes.first; 10 | final type = generateType(ref); 11 | 12 | return TypeReference((builder) { 13 | builder.symbol = 'Reference'; 14 | builder.url = 'package:orm/orm.dart'; 15 | builder.types.add(type); 16 | }); 17 | } 18 | } 19 | 20 | extension on Generator { 21 | dmmf.FieldRefType findRef(String name) { 22 | return options.dmmf.schema.fieldRefTypes.prisma.firstWhere( 23 | (element) => element.name == name, 24 | orElse: () => throw ArgumentError( 25 | 'FieldRefType $name not found in namespace prisma.', name), 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/orm/bin/src/generate_helpers.dart: -------------------------------------------------------------------------------- 1 | import 'package:code_builder/code_builder.dart'; 2 | import 'package:orm/dmmf.dart' as dmmf; 3 | 4 | import 'generate_type.dart'; 5 | import 'generator.dart'; 6 | import 'utils/iterable.dart'; 7 | 8 | extension GenerateHelpers on Generator { 9 | LibraryBuilder getLibraryByNamespace(dmmf.TypeNamespace? namespace) { 10 | return switch (namespace) { 11 | dmmf.TypeNamespace.model => libraries.model, 12 | dmmf.TypeNamespace.prisma => libraries.prisma, 13 | _ => libraries.client, 14 | }; 15 | } 16 | 17 | Set getTypesWithNamespace(dmmf.TypeNamespace? namespace) { 18 | return switch (namespace) { 19 | dmmf.TypeNamespace.model => generated.model, 20 | dmmf.TypeNamespace.prisma => generated.prisma, 21 | _ => generated.client, 22 | }; 23 | } 24 | 25 | Reference generateUnionType(Iterable types) { 26 | if (types.length == 1) { 27 | return generateType(types.first); 28 | } 29 | 30 | return TypeReference((builder) { 31 | builder.symbol = 'PrismaUnion'; 32 | builder.url = 'package:orm/orm.dart'; 33 | builder.types.addAll([ 34 | generateType(types.first), 35 | generateUnionType(types.skip(1)), 36 | ]); 37 | }); 38 | } 39 | 40 | bool allowSelect(dmmf.ModelAction action) => 41 | !_disallowedSelectActions.contains(action); 42 | 43 | bool allowInclude(dmmf.TypeReference type) { 44 | final types = switch (type.namespace) { 45 | dmmf.TypeNamespace.model => options.dmmf.schema.outputTypes.model, 46 | dmmf.TypeNamespace.prisma => options.dmmf.schema.outputTypes.prisma, 47 | _ => const [], 48 | }; 49 | final models = options.dmmf.datamodel.models.map((e) => e.name); 50 | final output = 51 | types.firstWhereOrNull((element) => element.name == type.type); 52 | final modelRefs = output?.fields 53 | .where((element) => models.contains(element.outputType.type)); 54 | 55 | return modelRefs?.isNotEmpty ?? false; 56 | } 57 | } 58 | 59 | final _disallowedSelectActions = [ 60 | dmmf.ModelAction.createMany, 61 | dmmf.ModelAction.updateMany, 62 | dmmf.ModelAction.deleteMany, 63 | dmmf.ModelAction.findRaw, 64 | dmmf.ModelAction.aggregateRaw, 65 | ]; 66 | -------------------------------------------------------------------------------- /packages/orm/bin/src/generate_type.dart: -------------------------------------------------------------------------------- 1 | import 'package:code_builder/code_builder.dart'; 2 | import 'package:orm/dmmf.dart' as dmmf; 3 | 4 | import 'generate_enum.dart'; 5 | import 'generate_field_ref.dart'; 6 | import 'generate_input.dart'; 7 | import 'generate_output.dart'; 8 | import 'generator.dart'; 9 | import 'utils/reference.dart'; 10 | import 'utils/scalars.dart'; 11 | 12 | extension GenerateType on Generator { 13 | Reference generateType(dmmf.TypeReference type, {bool? isList}) { 14 | return switch (type.location) { 15 | dmmf.TypeLocation.inputObjectTypes => 16 | generateInput(type.type, type.namespace, isList ?? type.isList), 17 | dmmf.TypeLocation.outputObjectTypes => 18 | generateOutput(type.type, type.namespace, isList ?? type.isList), 19 | dmmf.TypeLocation.enumTypes => 20 | generateEnum(type.type, type.namespace, isList ?? type.isList), 21 | dmmf.TypeLocation.fieldRefTypes => 22 | generateFieldRef(type.type).list(isList ?? type.isList), 23 | _ => generateScalar(type.type, isList ?? type.isList), 24 | }; 25 | } 26 | } 27 | 28 | extension on Generator { 29 | Reference generateScalar(String type, bool isList) { 30 | final reference = type.scalar; 31 | if (isList) { 32 | return TypeReference((type) { 33 | type.symbol = 'Iterable'; 34 | type.types.add(reference); 35 | }); 36 | } 37 | 38 | return reference; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /packages/orm/bin/src/generator+client.dart.without_code_builder_test.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: file_names 2 | 3 | import 'generator.dart'; 4 | import 'package:orm/generator_helper.dart' as gh; 5 | 6 | import 'utils/is_flutter_engine_type.dart'; 7 | 8 | extension Generate$Client on Generator { 9 | String client() { 10 | return ''' 11 | import 'package:orm/orm.dart'; 12 | import '$enginePackageUrl' show $engineName; 13 | 14 | class PrismaClient extends BasePrismaClient { 15 | Engine? _engine; 16 | 17 | PrismaClient({ 18 | super.datasourceUrl, 19 | super.datasources, 20 | super.errorFormat, 21 | super.log, 22 | Engine? engine, 23 | }) : _engine = engine; 24 | 25 | @override 26 | Engine get \$engine => _engine ??= createEngineInstance(); 27 | } 28 | 29 | extension on PrismaClient { 30 | Engine createEngineInstance() { 31 | return $engineName( 32 | schema: '${options.schema.literal()}', 33 | datasources: $datasources, 34 | options: \$options, 35 | ); 36 | } 37 | } 38 | '''; 39 | } 40 | 41 | String get datasources { 42 | final datasources = options.datasources.map((e) { 43 | final datasource = switch (e.url) { 44 | gh.EnvVar(name: final String name) => 45 | 'const Datasource(DatasourceType.enviroment, \'${name.literal()}\')', 46 | gh.EnvValue(value: final String url) => 47 | 'const Datasource(DatasourceType.url, \'${url.literal()}\')', 48 | }; 49 | 50 | return '\'${e.name}\': $datasource'; 51 | }); 52 | 53 | return '{${datasources.join(',')}}'; 54 | } 55 | 56 | String get enginePackageUrl { 57 | return switch (isFlutterEngineType(options.generator.config)) { 58 | true => 'package:orm_flutter/orm_flutter.dart', 59 | _ => 'package:orm/engines/binary.dart', 60 | }; 61 | } 62 | 63 | String get engineName { 64 | return switch (isFlutterEngineType(options.generator.config)) { 65 | true => 'PrismaQueryEngine', 66 | _ => 'BinaryEngine', 67 | }; 68 | } 69 | } 70 | 71 | extension on String { 72 | String literal() { 73 | return replaceAll('\'', '\\\'') 74 | .replaceAll('\n', '\\n') 75 | .replaceAll('\r\n', '\n'); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /packages/orm/bin/src/generator.dart: -------------------------------------------------------------------------------- 1 | import 'package:code_builder/code_builder.dart'; 2 | import 'package:orm/generator_helper.dart'; 3 | 4 | import 'generate_client.dart'; 5 | 6 | class Libraries { 7 | final client = LibraryBuilder(); 8 | final prisma = LibraryBuilder(); 9 | final model = LibraryBuilder(); 10 | } 11 | 12 | class Generated { 13 | final Set client = {}; 14 | final Set prisma = {}; 15 | final Set model = {}; 16 | } 17 | 18 | class Generator { 19 | final GeneratorOptions options; 20 | final libraries = Libraries(); 21 | final generated = Generated(); 22 | 23 | Generator(this.options); 24 | 25 | Iterable<(String, Library)> generate() { 26 | libraries.prisma.ignoreForFile.add('non_constant_identifier_names'); 27 | libraries.client.body.add(generateClient()); 28 | 29 | return [ 30 | ('client.dart', libraries.client.build()), 31 | ('prisma.dart', libraries.prisma.build()), 32 | ('model.dart', libraries.model.build()), 33 | ]; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /packages/orm/bin/src/utils/dart_style_fixer.dart: -------------------------------------------------------------------------------- 1 | import 'package:recase/recase.dart'; 2 | 3 | const _dartReservedProperties = { 4 | 'is', 5 | 'throw', 6 | 'if', 7 | 'case', 8 | 'for', 9 | 'else', 10 | 'class', 11 | 'final', 12 | 'var', 13 | 'const', 14 | 'void', 15 | 'null', 16 | 'default', 17 | 'in', 18 | }; 19 | 20 | const prismaReservedpProperties = {'AND', 'OR', 'NOT'}; 21 | 22 | extension DartStyleFixer on String { 23 | /// Returns dart class name string. 24 | String get className => pascalCase._publicName; 25 | 26 | /// Returns dart property name string. 27 | String get propertyName { 28 | if (prismaReservedpProperties.contains(this)) return this; 29 | if (_dartReservedProperties.contains(toLowerCase())) { 30 | return '\$$this'.camelCase; 31 | } 32 | 33 | return _publicName.camelCase; 34 | } 35 | 36 | String get _publicName { 37 | if (startsWith('_')) { 38 | return r'$' + substring(1); 39 | } 40 | 41 | return this; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/orm/bin/src/utils/is_flutter_engine_type.dart: -------------------------------------------------------------------------------- 1 | bool isFlutterEngineType(Map config) => config['engineType'] == 'flutter'; 2 | -------------------------------------------------------------------------------- /packages/orm/bin/src/utils/iterable.dart: -------------------------------------------------------------------------------- 1 | extension IterableHelpers on Iterable { 2 | T? firstWhereOrNull(bool Function(T element) test) { 3 | for (final element in this) { 4 | if (test(element)) return element; 5 | } 6 | 7 | return null; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/orm/bin/src/utils/reference.dart: -------------------------------------------------------------------------------- 1 | import 'package:code_builder/code_builder.dart'; 2 | import 'package:orm/dmmf.dart' as dmmf; 3 | 4 | extension ReferenceHelpers on Reference { 5 | Reference nullable(bool isNullable) { 6 | if (this is TypeReference) { 7 | final TypeReference reference = this as TypeReference; 8 | 9 | return TypeReference((type) { 10 | type.symbol = reference.symbol; 11 | type.url = reference.url; 12 | type.bound = reference.bound; 13 | type.types.addAll(reference.types); 14 | type.isNullable = isNullable; 15 | }); 16 | } 17 | 18 | return TypeReference((type) { 19 | type.symbol = symbol; 20 | type.url = url; 21 | type.isNullable = isNullable; 22 | }); 23 | } 24 | 25 | Reference list(bool isList) { 26 | if (isList) { 27 | return TypeReference((type) { 28 | type.symbol = 'Iterable'; 29 | type.types.add(this); 30 | }); 31 | } 32 | 33 | return this; 34 | } 35 | 36 | Reference namespace(dmmf.TypeNamespace? namespace) { 37 | if (namespace == null) return this; 38 | final url = switch (namespace) { 39 | dmmf.TypeNamespace.prisma => 'prisma.dart', 40 | dmmf.TypeNamespace.model => 'model.dart', 41 | }; 42 | 43 | if (this is TypeReference) { 44 | final TypeReference reference = this as TypeReference; 45 | 46 | return TypeReference((type) { 47 | type.symbol = reference.symbol; 48 | type.url = url; 49 | type.bound = reference.bound; 50 | type.types.addAll(reference.types); 51 | type.isNullable = reference.isNullable; 52 | }); 53 | } 54 | 55 | return TypeReference((type) { 56 | type.symbol = symbol; 57 | type.url = url; 58 | }); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /packages/orm/bin/src/utils/scalars.dart: -------------------------------------------------------------------------------- 1 | import 'package:code_builder/code_builder.dart'; 2 | 3 | final _scalars = { 4 | 'Int': refer('int'), 5 | 'Float': refer('double'), 6 | 'String': refer('String'), 7 | 'Boolean': refer('bool'), 8 | 'BigInt': refer('BigInt'), 9 | 'DateTime': refer('DateTime'), 10 | 'Bytes': refer('Uint8List', 'dart:typed_data'), 11 | 'Decimal': refer('Decimal', 'package:orm/orm.dart'), 12 | 'Null': refer('PrismaNull', 'package:orm/orm.dart'), 13 | 'Json': refer('PrismaJson', 'package:orm/orm.dart'), 14 | }; 15 | 16 | extension Scalar on String { 17 | Reference get scalar => _scalars[this] ?? refer(this); 18 | } 19 | -------------------------------------------------------------------------------- /packages/orm/example/README.md: -------------------------------------------------------------------------------- 1 | # See [Examples](https://github.com/medz/prisma-dart/tree/main/examples) 2 | -------------------------------------------------------------------------------- /packages/orm/integration_tests/i463.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import '../prisma/client/client.dart'; 4 | 5 | final prisma = PrismaClient( 6 | datasourceUrl: "postgresql://seven@localhost:5432/prisma?schema=public"); 7 | 8 | main() async { 9 | await runZoned(() async { 10 | print(000); 11 | try { 12 | final query = 'SELECT * FROM "User"'; 13 | // A series of valid queries 14 | await prisma.$raw.query(query); 15 | await prisma.$raw.query(query); 16 | await prisma.$raw.query(query); 17 | await prisma.$raw.query(query); 18 | await prisma.$raw.query(query); 19 | 20 | // Execute multiple queries concurrently, including one with an intentional syntax error 21 | Future.wait([ 22 | prisma.$raw.query(query), 23 | prisma.$raw.query(query), 24 | prisma.$raw.query('SELEC Q FROM Q'), // Intentional syntax error 25 | prisma.$raw.query(query), 26 | prisma.$raw.query(query), 27 | prisma.$raw.query(query), 28 | prisma.$raw.query(query), 29 | prisma.$raw.query(query), 30 | prisma.$raw.query(query), 31 | prisma.$raw.query(query), 32 | prisma.$raw.query(query), 33 | ]); 34 | 35 | // More queries after the batch 36 | await prisma.$raw.query(query); 37 | await prisma.$raw.query(query); 38 | await prisma.$raw.query(query); 39 | await prisma.$raw.query(query); 40 | await prisma.$raw.query(query); 41 | } catch (e) { 42 | print(e); 43 | rethrow; 44 | } finally { 45 | print(333); 46 | await prisma.$disconnect(); 47 | } 48 | }, zoneSpecification: 49 | ZoneSpecification(errorCallback: (zone, parent, ___, e, s) { 50 | prisma.$disconnect(); 51 | return parent.errorCallback(zone, e, s) ?? AsyncError(e, s); 52 | })); 53 | 54 | print(444); 55 | } 56 | -------------------------------------------------------------------------------- /packages/orm/integration_tests/i467.dart: -------------------------------------------------------------------------------- 1 | import 'dart:typed_data'; 2 | 3 | import 'package:orm/orm.dart'; 4 | 5 | import '../prisma/client/client.dart'; 6 | import '../prisma/client/prisma.dart'; 7 | 8 | main() async { 9 | final prisma = PrismaClient( 10 | datasourceUrl: "postgresql://seven@localhost:5432/prisma?schema=public"); 11 | try { 12 | final byteList = List.filled(50, 1); 13 | await prisma.test.create( 14 | data: PrismaUnion.$1(TestCreateInput( 15 | bytes: Uint8List.fromList(byteList), 16 | )), 17 | ); 18 | } finally { 19 | await prisma.$disconnect(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/orm/lib/dmmf.dart: -------------------------------------------------------------------------------- 1 | export 'src/dmmf/dmmf.dart'; 2 | export 'src/dmmf/datamodel.dart'; 3 | export 'src/dmmf/mappings.dart'; 4 | export 'src/dmmf/schema.dart'; 5 | -------------------------------------------------------------------------------- /packages/orm/lib/engines/binary.dart: -------------------------------------------------------------------------------- 1 | export '../src/engines/binary_engine.dart'; 2 | -------------------------------------------------------------------------------- /packages/orm/lib/generator_helper.dart: -------------------------------------------------------------------------------- 1 | export 'src/generator_helper/binary_targets_env_value.dart'; 2 | export 'src/generator_helper/config.dart'; 3 | export 'src/generator_helper/env_value.dart'; 4 | export 'src/generator_helper/generator.dart'; 5 | export 'src/generator_helper/manifest.dart'; 6 | export 'src/generator_helper/options.dart'; 7 | -------------------------------------------------------------------------------- /packages/orm/lib/orm.dart: -------------------------------------------------------------------------------- 1 | export 'src/errors.dart'; 2 | export 'src/runtime/action_client.dart'; 3 | export 'src/runtime/decimal.dart'; 4 | export 'src/runtime/engine.dart'; 5 | export 'src/runtime/json_convertible.dart'; 6 | export 'src/runtime/prisma_enum.dart'; 7 | export 'src/runtime/prisma_null.dart'; 8 | export 'src/runtime/prisma_json.dart'; 9 | export 'src/runtime/prisma_union.dart'; 10 | export 'src/runtime/reference.dart'; 11 | 12 | // transaction 13 | export 'src/runtime/transaction/isolation_level.dart'; 14 | export 'src/runtime/transaction/transaction_headers.dart'; 15 | export 'src/runtime/transaction/transaction.dart'; 16 | export 'src/runtime/transaction/transaction_client.dart'; 17 | 18 | // JSON Protocol 19 | export 'src/runtime/json_protocol/protocol.dart'; 20 | export 'src/runtime/json_protocol/serialize.dart'; 21 | export 'src/runtime/json_protocol/deserialize.dart'; 22 | 23 | // Metrics 24 | export 'src/runtime/metrics/metrics_client.dart'; 25 | export 'src/runtime/metrics/metrics_format.dart'; 26 | 27 | // Raw 28 | export 'src/runtime/raw/raw_client.dart'; 29 | 30 | // v5.0 31 | export 'src/base_prisma_client.dart'; 32 | export 'src/logging.dart'; 33 | export 'src/prisma_client_options.dart'; 34 | export 'src/prisma_namespace.dart'; 35 | 36 | export 'src/config/prisma+env.dart'; 37 | export 'src/config/prisma+config.dart'; 38 | 39 | export 'src/datasources/datasources.dart'; 40 | export 'src/datasources/prisma+datasource_utils.dart'; 41 | -------------------------------------------------------------------------------- /packages/orm/lib/src/_internal/project_directory.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:path/path.dart' as path; 4 | 5 | Directory? findProjectDirectory([String? directory]) { 6 | if (directory != null) { 7 | return _nestFindPubspecDirectory(Directory(directory)); 8 | } 9 | 10 | return _nestFindPubspecDirectory(Directory.current) ?? 11 | _nestFindPubspecDirectory(File.fromUri(Platform.script).parent); 12 | } 13 | 14 | Directory? _nestFindPubspecDirectory(Directory directory) { 15 | try { 16 | final pubspec = File(path.join(directory.path, 'pubspec.yaml')); 17 | if (pubspec.existsSync()) return directory; 18 | if (_isOsRoot(directory)) return null; 19 | 20 | return _nestFindPubspecDirectory(directory.parent); 21 | } catch (_) { 22 | return null; 23 | } 24 | } 25 | 26 | bool _isOsRoot(Directory directory) { 27 | if (Platform.isWindows) { 28 | return directory.path.endsWith(':\\'); 29 | } 30 | 31 | return path.relative(directory.path, from: '/') == '.'; 32 | } 33 | -------------------------------------------------------------------------------- /packages/orm/lib/src/base_prisma_client.dart: -------------------------------------------------------------------------------- 1 | import 'dmmf/datamodel.dart' show DataModel; 2 | import 'logging.dart'; 3 | import 'prisma_client_options.dart'; 4 | import 'runtime/engine.dart'; 5 | import 'runtime/metrics/metrics_client.dart'; 6 | import 'runtime/raw/raw_client.dart'; 7 | import 'runtime/transaction/transaction_client.dart'; 8 | 9 | /// Base prisma client 10 | abstract class BasePrismaClient> { 11 | BasePrismaClient({ 12 | String? datasourceUrl, 13 | final Map? datasources, 14 | ErrorFormat errorFormat = ErrorFormat.colorless, 15 | LogDefinition? log, 16 | }) : _options = PrismaClientOptions( 17 | datasources: datasources, 18 | datasourceUrl: datasourceUrl, 19 | errorFormat: errorFormat, 20 | logEmitter: LogEmitter(log ?? const {}), 21 | ); 22 | 23 | final PrismaClientOptions _options; 24 | 25 | /// Prisma client options 26 | PrismaClientOptions get $options => _options; 27 | 28 | /// Returns the [Engine] instance typeof [E]. 29 | Engine get $engine; 30 | RawClient get $raw => RawClient(this as Client); 31 | MetricsClient get $metrics => MetricsClient($engine); 32 | TransactionClient get $transaction; 33 | DataModel get $datamodel; 34 | 35 | Future $connect() => $engine.start(); 36 | Future $disconnect() => $engine.stop(); 37 | 38 | void $on(LogLevel level, void Function(EngineEvent event) listener) => 39 | $options.logEmitter.on(level, listener); 40 | } 41 | -------------------------------------------------------------------------------- /packages/orm/lib/src/config/_loader.dart: -------------------------------------------------------------------------------- 1 | import 'package:rc/loaders/environment.dart'; 2 | 3 | const loader = EnvironmentLoader(); 4 | -------------------------------------------------------------------------------- /packages/orm/lib/src/config/_loader.io.dart: -------------------------------------------------------------------------------- 1 | import 'package:path/path.dart' as path; 2 | import 'package:rc/loaders/dotenv.dart'; 3 | 4 | final loader = DotenvLoader( 5 | files: ['.env', path.join('prisma', '.env')], 6 | includeSystemEnvironment: true, 7 | skipMultipleLocations: true, 8 | searchProjectDirectory: true, 9 | ); 10 | -------------------------------------------------------------------------------- /packages/orm/lib/src/config/prisma+config.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: file_names 2 | 3 | import 'package:rc/rc.dart'; 4 | 5 | import '../prisma_namespace.dart'; 6 | import '_loader.dart' if (dart.library.io) '_loader.io.dart'; 7 | 8 | extension Prisma$Config on PrismaNamespace { 9 | static final _config = () { 10 | return RC( 11 | shouldWarn: true, 12 | loaders: {loader}, 13 | ); 14 | }(); 15 | 16 | /// Returns prisma config 17 | RC get config => _config; 18 | } 19 | -------------------------------------------------------------------------------- /packages/orm/lib/src/config/prisma+env.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: file_names 2 | 3 | import 'package:rc/rc.dart'; 4 | 5 | import '../prisma_namespace.dart'; 6 | import 'prisma+config.dart'; 7 | 8 | extension Prisma$Environment on PrismaNamespace { 9 | bool get _skipDotiableKeys => envAsBoolean('prisma.env.skip_dotiable_keys'); 10 | 11 | /// Returns environment KV parts. 12 | Map get environment => 13 | config.toEnvironmentMap(skipDotiableKeys: _skipDotiableKeys); 14 | 15 | /// Returns a environment value by [name]. 16 | String? env(String name) => config.env(name); 17 | 18 | /// Returns bool env value. 19 | bool envAsBoolean(String name) { 20 | final value = config(name); 21 | return switch (value) { 22 | true || "on" || "true" || 1 || "1" => true, 23 | _ => false, 24 | }; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/orm/lib/src/datasources/_validate_datasource_url.dart: -------------------------------------------------------------------------------- 1 | import '../errors.dart'; 2 | 3 | const _allowdProtocels = [ 4 | 'file', 5 | 'mysql', 6 | 'postgresql', 7 | 'mongodb', 8 | 'sqlserver', 9 | 'prisma' 10 | ]; 11 | 12 | PrismaClientInitializationError _createInvalidDatasourceError(String message) => 13 | PrismaClientInitializationError(errorCode: 'P1013', message: message); 14 | 15 | String validateDatasourceURL(String datasourceUrl) { 16 | final url = Uri.tryParse(datasourceUrl); 17 | 18 | if (url?.scheme == 'file') { 19 | throw _createInvalidDatasourceError( 20 | "The current platform does not support SQLite, please change the datasource URL"); 21 | } 22 | 23 | if (url == null || !_allowdProtocels.contains(url.scheme)) { 24 | throw _createInvalidDatasourceError("Invalid Prisma datasource URL"); 25 | } 26 | 27 | return url.toString(); 28 | } 29 | -------------------------------------------------------------------------------- /packages/orm/lib/src/datasources/_validate_datasource_url.io.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:path/path.dart' as path; 4 | 5 | import '../_internal/project_directory.dart'; 6 | import '../errors.dart'; 7 | import '_validate_datasource_url.dart' as shared; 8 | 9 | String validateDatasourceURL(String datasourceUrl) { 10 | final url = Uri.tryParse(datasourceUrl); 11 | if (url?.scheme != 'file' || url == null) { 12 | return shared.validateDatasourceURL(datasourceUrl); 13 | } 14 | 15 | final pwd = findProjectDirectory()?.path ?? Directory.current.path; 16 | final databasePath = 17 | path.relative(path.join(pwd, datasourceUrl.substring(5))); 18 | if (File(databasePath).existsSync()) { 19 | return 'file:$databasePath'; 20 | } 21 | 22 | throw PrismaClientInitializationError( 23 | errorCode: "P1003", 24 | message: "The SQLite database file ($databasePath) does not exist"); 25 | } 26 | -------------------------------------------------------------------------------- /packages/orm/lib/src/datasources/datasources.dart: -------------------------------------------------------------------------------- 1 | enum DatasourceType { url, environment } 2 | 3 | class Datasource { 4 | final DatasourceType type; 5 | final String value; 6 | 7 | const Datasource(this.type, this.value); 8 | } 9 | 10 | typedef Datasources = Map; 11 | -------------------------------------------------------------------------------- /packages/orm/lib/src/datasources/prisma+datasource_utils.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: file_names 2 | 3 | import '../prisma_namespace.dart'; 4 | import '_validate_datasource_url.dart' 5 | if (dart.library.io) '_validate_datasource_url.io.dart' 6 | as validate_datasource_url; 7 | 8 | extension Prisma$DatasourceUtils on PrismaNamespace { 9 | String validateDatasourceURL(String datasourceUrl) => 10 | validate_datasource_url.validateDatasourceURL(datasourceUrl); 11 | } 12 | -------------------------------------------------------------------------------- /packages/orm/lib/src/dmmf/dmmf.dart: -------------------------------------------------------------------------------- 1 | import 'datamodel.dart'; 2 | import 'mappings.dart'; 3 | import 'schema.dart'; 4 | 5 | /// Prisma data model meta format(DMMF). 6 | class DMMF { 7 | /// The Data model AST 8 | final DataModel datamodel; 9 | 10 | /// The query engine API schema. 11 | final Schema schema; 12 | 13 | /// The operations map. Derived from the [schema]. 14 | final Mappings mappings; 15 | 16 | /// The DMMF source. 17 | final Map source; 18 | 19 | const DMMF({ 20 | required this.datamodel, 21 | required this.schema, 22 | required this.mappings, 23 | required this.source, 24 | }); 25 | 26 | factory DMMF.fromJson(Map json) { 27 | return DMMF( 28 | datamodel: DataModel.fromJson(json['datamodel']), 29 | schema: Schema.fromJson(json['schema']), 30 | mappings: Mappings.fromJson(json['mappings']), 31 | source: json.cast(), 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/orm/lib/src/dmmf/mappings.dart: -------------------------------------------------------------------------------- 1 | class Mappings { 2 | final Iterable modelOperations; 3 | final OtherOperationMappings otherOperations; 4 | 5 | const Mappings({ 6 | required this.modelOperations, 7 | required this.otherOperations, 8 | }); 9 | 10 | factory Mappings.fromJson(Map json) { 11 | return Mappings( 12 | modelOperations: (json['modelOperations'] as Iterable) 13 | .map((e) => ModelMapping.fromJson(e)), 14 | otherOperations: OtherOperationMappings.fromJson(json['otherOperations']), 15 | ); 16 | } 17 | } 18 | 19 | class OtherOperationMappings { 20 | final Iterable read; 21 | final Iterable write; 22 | 23 | const OtherOperationMappings({ 24 | required this.read, 25 | required this.write, 26 | }); 27 | 28 | factory OtherOperationMappings.fromJson(Map json) { 29 | return OtherOperationMappings( 30 | read: (json['read'] as Iterable).cast(), 31 | write: (json['write'] as Iterable).cast(), 32 | ); 33 | } 34 | } 35 | 36 | class ModelMapping { 37 | final String model; 38 | final String plural; 39 | final Map actions; 40 | 41 | const ModelMapping({ 42 | required this.model, 43 | required this.plural, 44 | required this.actions, 45 | }); 46 | 47 | factory ModelMapping.fromJson(Map json) { 48 | final entries = ModelAction.values 49 | .map((e) { 50 | return switch (json[e.name] ?? json['${e.name}One']) { 51 | String name => MapEntry(e, name), 52 | _ => null, 53 | }; 54 | }) 55 | .where((e) => e != null) 56 | .whereType>(); 57 | 58 | return ModelMapping( 59 | model: json['model'], 60 | plural: json['plural'] ?? json['model'], 61 | actions: Map.fromEntries(entries), 62 | ); 63 | } 64 | } 65 | 66 | enum ModelAction { 67 | findUnique, 68 | findUniqueOrThrow, 69 | findFirst, 70 | findFirstOrThrow, 71 | findMany, 72 | create, 73 | createMany, 74 | createManyAndReturn, 75 | update, 76 | updateMany, 77 | updateManyAndReturn, 78 | upsert, 79 | delete, 80 | deleteMany, 81 | groupBy, 82 | count, 83 | aggregate, 84 | findRaw, 85 | aggregateRaw, 86 | } 87 | -------------------------------------------------------------------------------- /packages/orm/lib/src/generator_helper/binary_targets_env_value.dart: -------------------------------------------------------------------------------- 1 | class BinaryTargetsEnvValue { 2 | final String? fromEnvVar; 3 | final bool native; 4 | final String value; 5 | 6 | const BinaryTargetsEnvValue({ 7 | this.fromEnvVar, 8 | required this.native, 9 | required this.value, 10 | }); 11 | 12 | factory BinaryTargetsEnvValue.fromJson(Map json) { 13 | return BinaryTargetsEnvValue( 14 | fromEnvVar: json['fromEnvVar'] as String?, 15 | native: (json['native'] as bool?) ?? false, 16 | value: json['value'] as String, 17 | ); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/orm/lib/src/generator_helper/config.dart: -------------------------------------------------------------------------------- 1 | import 'binary_targets_env_value.dart'; 2 | import 'env_value.dart'; 3 | 4 | class GeneratorConfig { 5 | final String name; 6 | final Env? output; 7 | final bool isCustomOutput; 8 | final Env provider; 9 | final Map config; 10 | final Iterable binaryTargets; 11 | final Iterable previewFeatures; 12 | 13 | const GeneratorConfig({ 14 | required this.name, 15 | this.output, 16 | required this.isCustomOutput, 17 | required this.provider, 18 | required this.config, 19 | required this.binaryTargets, 20 | required this.previewFeatures, 21 | }); 22 | 23 | factory GeneratorConfig.fromJson(Map json) { 24 | return GeneratorConfig( 25 | name: json['name'] as String, 26 | output: 27 | json['output'] == null ? null : Env.fromJson(json['output'] as Map), 28 | isCustomOutput: (json['isCustomOutput'] as bool?) ?? false, 29 | provider: Env.fromJson(json['provider'] as Map), 30 | config: (json['config'] as Map).cast(), 31 | binaryTargets: (json['binaryTargets'] as Iterable) 32 | .map((e) => BinaryTargetsEnvValue.fromJson(e as Map)), 33 | previewFeatures: (json['previewFeatures'] as Iterable).cast(), 34 | ); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/orm/lib/src/generator_helper/env_value.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | sealed class Env { 4 | factory Env.fromJson(Map json) { 5 | return switch (json) { 6 | {'value': final String value} => EnvValue(value), 7 | {'fromEnvVar': final String name} => EnvVar(name), 8 | _ => throw FormatException('Invalid env value: $json'), 9 | }; 10 | } 11 | 12 | String get value; 13 | } 14 | 15 | final class EnvVar implements Env { 16 | final String name; 17 | 18 | const EnvVar(this.name); 19 | 20 | @override 21 | String get value { 22 | if (bool.hasEnvironment(name)) { 23 | return String.fromEnvironment(name); 24 | } else if (Platform.environment.containsKey(name)) { 25 | return Platform.environment[name]!; 26 | } 27 | 28 | throw StateError('Env var $name is not set'); 29 | } 30 | } 31 | 32 | final class EnvValue implements Env { 33 | @override 34 | final String value; 35 | 36 | const EnvValue(this.value); 37 | } 38 | -------------------------------------------------------------------------------- /packages/orm/lib/src/generator_helper/generator.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:convert'; 3 | import 'dart:io'; 4 | 5 | import 'package:json_rpc_2/json_rpc_2.dart'; 6 | import 'package:stream_channel/stream_channel.dart'; 7 | 8 | import 'config.dart'; 9 | import 'manifest.dart'; 10 | import 'options.dart'; 11 | 12 | class GeneratorApp { 13 | final Server server; 14 | 15 | const GeneratorApp(this.server); 16 | 17 | factory GeneratorApp.channel({ 18 | required Stream input, 19 | required StreamSink output, 20 | }) { 21 | return GeneratorApp(Server(StreamChannel(input, output))); 22 | } 23 | 24 | factory GeneratorApp.stdio({ 25 | required Stdin stdin, 26 | required Stdout stdout, 27 | }) { 28 | final input = stdin.transform(utf8.decoder).transform(const LineSplitter()); 29 | 30 | final controller = StreamController(); 31 | controller.stream.listen(stdout.writeln); 32 | 33 | return GeneratorApp.channel(input: input, output: controller.sink); 34 | } 35 | 36 | void onManifest( 37 | FutureOr Function(GeneratorConfig config) handler, 38 | ) { 39 | server.registerMethod('getManifest', (Parameters params) async { 40 | final config = GeneratorConfig.fromJson(params.asMap.cast()); 41 | final manifest = await handler(config); 42 | 43 | return {'manifest': manifest?.toJson()}; 44 | }); 45 | } 46 | 47 | void onGenerate( 48 | FutureOr Function(GeneratorOptions options) handler, 49 | ) { 50 | server.registerMethod('generate', (Parameters params) async { 51 | final options = GeneratorOptions.fromJson(params.asMap); 52 | final result = await handler(options); 53 | 54 | return result; 55 | }); 56 | } 57 | 58 | Future listen() => server.listen(); 59 | Future close() => server.close(); 60 | } 61 | -------------------------------------------------------------------------------- /packages/orm/lib/src/generator_helper/manifest.dart: -------------------------------------------------------------------------------- 1 | import '../runtime/json_convertible.dart'; 2 | 3 | class GeneratorManifest implements JsonConvertible> { 4 | final String? prettyName; 5 | final String? defaultOutput; 6 | final String? version; 7 | final GeneratorManifestDenyList? denylists; 8 | final Iterable? requiresGenerators; 9 | final Iterable? requiresEngines; 10 | final String? requiresEngineVersion; 11 | 12 | const GeneratorManifest({ 13 | this.prettyName, 14 | this.defaultOutput, 15 | this.denylists, 16 | this.requiresGenerators, 17 | this.requiresEngines, 18 | this.requiresEngineVersion, 19 | this.version, 20 | }); 21 | 22 | @override 23 | Map toJson() { 24 | return { 25 | if (prettyName != null) 'prettyName': prettyName, 26 | if (defaultOutput != null) 'defaultOutput': defaultOutput, 27 | if (denylists != null) 'denylists': denylists?.toJson(), 28 | if (requiresGenerators != null) 'requiresGenerators': requiresGenerators, 29 | if (requiresEngines != null) 'requiresEngines': requiresEngines, 30 | if (requiresEngineVersion != null) 31 | 'requiresEngineVersion': requiresEngineVersion, 32 | if (version != null) 'version': version, 33 | }; 34 | } 35 | } 36 | 37 | class GeneratorManifestDenyList 38 | implements JsonConvertible> { 39 | final Iterable? models; 40 | final Iterable? fields; 41 | 42 | const GeneratorManifestDenyList({this.models, this.fields}); 43 | 44 | factory GeneratorManifestDenyList.fromJson(Map json) { 45 | return GeneratorManifestDenyList( 46 | models: json['models']?.cast(), 47 | fields: json['fields']?.cast(), 48 | ); 49 | } 50 | 51 | @override 52 | Map toJson() { 53 | return { 54 | if (models != null) 'models': models, 55 | if (fields != null) 'fields': fields, 56 | }; 57 | } 58 | } 59 | 60 | enum EngineType implements JsonConvertible { 61 | queryEngine, 62 | libqueryEngine, 63 | schemaEngine; 64 | 65 | @override 66 | String toJson() => name; 67 | } 68 | -------------------------------------------------------------------------------- /packages/orm/lib/src/logging.dart: -------------------------------------------------------------------------------- 1 | /// Log level 2 | enum LogLevel { info, query, warn, error } 3 | 4 | /// Log emit 5 | enum LogEmit { stdout, event } 6 | 7 | /// Prisma engine log event. 8 | /// 9 | /// @see [QueryEvent] 10 | /// @see [LogEvent] 11 | base class EngineEvent { 12 | /// Event timestamp. 13 | final DateTime timestamp; 14 | 15 | /// Event target. 16 | final String target; 17 | 18 | const EngineEvent({required this.timestamp, required this.target}); 19 | } 20 | 21 | /// Log event. 22 | final class LogEvent extends EngineEvent { 23 | /// Log message. 24 | final String message; 25 | 26 | const LogEvent( 27 | {required super.timestamp, required super.target, required this.message}); 28 | } 29 | 30 | /// Query log event. 31 | final class QueryEvent extends EngineEvent { 32 | final String query; 33 | final String params; 34 | final Duration duration; 35 | 36 | const QueryEvent( 37 | {required super.timestamp, 38 | required super.target, 39 | required this.duration, 40 | required this.params, 41 | required this.query}); 42 | } 43 | 44 | typedef LogDefinition = Set<(LogLevel level, LogEmit emit)>; 45 | typedef LogListener = void Function(EngineEvent event); 46 | 47 | /// Prisma log event emitter. 48 | class LogEmitter { 49 | final LogDefinition definition; 50 | final _listeners = <(LogLevel, LogListener)>[]; 51 | 52 | LogEmitter(LogDefinition definition) 53 | : definition = LogDefinition.unmodifiable(definition); 54 | 55 | void on(LogLevel level, LogListener listener) { 56 | final extsis = _listeners.any((e) => e.$1 == level && e.$2 == listener); 57 | if (extsis) return; 58 | 59 | _listeners.add((level, listener)); 60 | } 61 | 62 | void emit(LogLevel level, EngineEvent event) { 63 | _emitStdout(level, event); 64 | _emitEvent(level, event); 65 | } 66 | 67 | void _emitStdout(LogLevel level, EngineEvent event) { 68 | if (definition.should(level, LogEmit.stdout)) { 69 | final name = 'prisma:${level.name}'; 70 | final message = switch (event) { 71 | LogEvent(message: final String message) => message, 72 | QueryEvent(query: final String query, params: final String params) => 73 | '$query - $params', 74 | _ => 'Unknown log event: $event', 75 | }; 76 | 77 | print('$name $message'); 78 | } 79 | } 80 | 81 | void _emitEvent(LogLevel level, EngineEvent event) { 82 | if (!definition.should(level, LogEmit.event)) return; 83 | 84 | final listeners = _listeners.where((e) => e.$1 == level).map((e) => e.$2); 85 | for (final listener in listeners) { 86 | listener(event); 87 | } 88 | } 89 | } 90 | 91 | extension on LogDefinition { 92 | bool should(LogLevel level, LogEmit emit) { 93 | return any((e) => e.$1 == level && e.$2 == emit); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /packages/orm/lib/src/prisma_client_options.dart: -------------------------------------------------------------------------------- 1 | import 'logging.dart'; 2 | 3 | /// Error format 4 | enum ErrorFormat { 5 | ///Enables pretty error formatting. 6 | pretty, 7 | 8 | ///Enables colorless error formatting. 9 | colorless, 10 | 11 | /// Enables minimal error formatting. 12 | minimal 13 | } 14 | 15 | class PrismaClientOptions { 16 | /// Overwrites the primary datasource url from your schema.prisma file 17 | final String? datasourceUrl; 18 | 19 | /// Overwrites the datasource url from your schema.prisma file 20 | /// 21 | /// Example: 22 | /// ```dart 23 | /// final prisma = PrismaClient( 24 | /// datasources: {'db': 'file:./dev.db'} 25 | /// ); 26 | /// ``` 27 | final Map? datasources; 28 | 29 | /// Determines the level and formatting of errors returned by Prisma Client. 30 | final ErrorFormat errorFormat; 31 | 32 | /// Log emitter. 33 | LogEmitter logEmitter; 34 | 35 | /// Create Prisma client options 36 | PrismaClientOptions({ 37 | this.datasourceUrl, 38 | this.datasources, 39 | required this.errorFormat, 40 | required this.logEmitter, 41 | }) : assert(!(datasourceUrl != null && datasources != null), 42 | 'DatasourceUrl and datasources cannot be used together'); 43 | } 44 | -------------------------------------------------------------------------------- /packages/orm/lib/src/prisma_namespace.dart: -------------------------------------------------------------------------------- 1 | /// Prisma namespace utils 2 | class PrismaNamespace { 3 | const PrismaNamespace._(); 4 | } 5 | 6 | /// Priama Namespace, About Saving Public Tool Collections. 7 | /// ignore: constant_identifier_names 8 | const Prisma = PrismaNamespace._(); 9 | -------------------------------------------------------------------------------- /packages/orm/lib/src/runtime/action_client.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | class ActionClient implements Future { 4 | final Future _result; 5 | final String _action; 6 | final T Function(dynamic) _factory; 7 | 8 | const ActionClient({ 9 | required String action, 10 | required Future result, 11 | required T Function(dynamic unserialized) factory, 12 | }) : _action = action, 13 | _result = result, 14 | _factory = factory; 15 | 16 | Future unserialized() => 17 | Future.value(_result).then((value) => value[_action]); 18 | 19 | @override 20 | Stream asStream() => unserialized().then(_factory).asStream(); 21 | 22 | @override 23 | Future catchError(Function onError, {bool Function(Object error)? test}) { 24 | return unserialized().then(_factory).catchError(onError, test: test); 25 | } 26 | 27 | @override 28 | Future then(FutureOr Function(T value) onValue, 29 | {Function? onError}) { 30 | return unserialized().then(_factory).then(onValue, onError: onError); 31 | } 32 | 33 | @override 34 | Future timeout(Duration timeLimit, {FutureOr Function()? onTimeout}) { 35 | return unserialized() 36 | .then(_factory) 37 | .timeout(timeLimit, onTimeout: onTimeout); 38 | } 39 | 40 | @override 41 | Future whenComplete(FutureOr Function() action) { 42 | return unserialized().then(_factory).whenComplete(action); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /packages/orm/lib/src/runtime/decimal.dart: -------------------------------------------------------------------------------- 1 | export 'package:decimal/decimal.dart'; 2 | -------------------------------------------------------------------------------- /packages/orm/lib/src/runtime/json_convertible.dart: -------------------------------------------------------------------------------- 1 | import 'dart:typed_data'; 2 | 3 | /// An abstract interface for objects that can be converted to JSON. 4 | /// 5 | /// The `JsonConvertible` interface provides a method `toJson()` that converts 6 | /// the object to a JSON representation. 7 | /// 8 | /// The type parameter `T` represents the type of the JSON representation. 9 | abstract interface class JsonConvertible { 10 | /// Converts the object to a JSON representation. 11 | /// 12 | /// Returns the JSON representation of the object. 13 | T toJson(); 14 | 15 | /// Serializes a dynamic value into a JSON representation. 16 | /// 17 | /// The [value] parameter can be of any type. If the value is an instance of a class that implements the `JsonConvertible` interface, 18 | /// the `toJson()` method of that class will be called to obtain the JSON representation. 19 | /// If the value is an iterable, each element in the iterable will be recursively serialized using the `serialize()` function. 20 | /// If the value is a map, each key-value pair in the map will be recursively serialized using the `serialize()` function. 21 | /// If the value does not match any of the above cases, it will be returned as is. 22 | /// 23 | /// Returns the JSON representation of the value. 24 | static serialize(value) { 25 | return switch (value) { 26 | JsonConvertible value => serialize(value.toJson()), 27 | Uint8List bytes => bytes, 28 | TypedData bytes => bytes, 29 | Map values => values.map((key, value) => MapEntry(key, serialize(value))), 30 | Iterable values => values.map((e) => serialize(e)).toList(), 31 | _ => value, 32 | }; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/orm/lib/src/runtime/json_protocol/deserialize.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import '../decimal.dart'; 4 | 5 | dynamic deserializeJsonResponse(dynamic result) { 6 | return switch (result) { 7 | Iterable iterable => iterable.map(deserializeJsonResponse), 8 | Map object => _deserializeJsonObject(object), 9 | _ => result, 10 | }; 11 | } 12 | 13 | dynamic _deserializeJsonObject(Map object) { 14 | if (object.containsKey(r'$type')) { 15 | return _deserializeTaggedValue(object); 16 | } 17 | 18 | return object.map( 19 | (key, value) => MapEntry(key, deserializeJsonResponse(value)), 20 | ); 21 | } 22 | 23 | dynamic _deserializeTaggedValue(Map object) => switch (object) { 24 | {r'$type': 'BigInt', 'value': final String value} => BigInt.parse(value), 25 | {r'$type': 'Bytes', 'value': final String value} => base64.decode(value), 26 | {r'$type': 'DateTime', 'value': final String value} => 27 | DateTime.parse(value), 28 | {r'$type': 'Decimal', 'value': final String value} => 29 | Decimal.parse(value), 30 | {r'$type': 'Json', 'value': final String value} => json.decode(value), 31 | _ => throw Exception('Unknown tagged value: $object'), 32 | }; 33 | -------------------------------------------------------------------------------- /packages/orm/lib/src/runtime/json_protocol/protocol.dart: -------------------------------------------------------------------------------- 1 | import '../json_convertible.dart'; 2 | import '../prisma_enum.dart'; 3 | import '../prisma_union.dart'; 4 | 5 | class JsonQuery implements JsonConvertible> { 6 | final String? modelName; 7 | final JsonQueryAction action; 8 | final Map query; 9 | 10 | const JsonQuery({ 11 | this.modelName, 12 | required this.action, 13 | required this.query, 14 | }); 15 | 16 | @override 17 | Map toJson() => { 18 | if (modelName != null) 'modelName': modelName!, 19 | 'action': action.name, 20 | 'query': query, 21 | }; 22 | 23 | static groupBySerializer(dynamic value) { 24 | if (value is PrismaEnum) { 25 | return value.name; 26 | } else if (value is Iterable) { 27 | return value.map(groupBySerializer); 28 | } else if (value is PrismaUnion) { 29 | if (value.$1 != null) return groupBySerializer(value.$1); 30 | if (value.$2 != null) return groupBySerializer(value.$2); 31 | } 32 | 33 | return value; 34 | } 35 | 36 | static groupBySelectSerializer(dynamic value) { 37 | final by = groupBySerializer(value); 38 | final select = {}; 39 | 40 | if (by is String) { 41 | select[by] = true; 42 | } else if (by is Iterable) { 43 | for (final item in by) { 44 | if (item is String) { 45 | select[item] = true; 46 | } 47 | } 48 | } 49 | 50 | return select.isEmpty ? null : select; 51 | } 52 | } 53 | 54 | enum JsonQueryAction { 55 | findUnique, 56 | findUniqueOrThrow, 57 | findFirst, 58 | findFirstOrThrow, 59 | findMany, 60 | createOne, 61 | createMany, 62 | createManyAndReturn, 63 | updateOne, 64 | updateMany, 65 | updateManyAndReturn, 66 | deleteOne, 67 | deleteMany, 68 | upsertOne, 69 | aggregate, 70 | groupBy, 71 | executeRaw, 72 | queryRaw, 73 | runCommandRaw, 74 | findRaw, 75 | aggregateRaw, 76 | } 77 | -------------------------------------------------------------------------------- /packages/orm/lib/src/runtime/metrics/metrics_client.dart: -------------------------------------------------------------------------------- 1 | import '../engine.dart'; 2 | import 'metrics_format.dart'; 3 | 4 | class MetricsClient { 5 | const MetricsClient(Engine engine) : _engine = engine; 6 | 7 | final Engine _engine; 8 | 9 | /// Returns all metrics gathered up to this point in prometheus format. 10 | /// 11 | /// Result of this call can be exposed directly to prometheus scraping 12 | /// endpoint 13 | /// 14 | /// - [globalLabels] are the labels to be added to all metrics. 15 | Future prometheus({Map? globalLabels}) async { 16 | final result = await _engine.metrics( 17 | globalLabels: globalLabels, format: MetricsFormat.prometheus); 18 | 19 | return result.toString(); 20 | } 21 | 22 | /// Returns all metrics gathered up to this point in json format. 23 | Future> json({Map? globalLabels}) async { 24 | final result = await _engine.metrics( 25 | globalLabels: globalLabels, format: MetricsFormat.json); 26 | 27 | return result as Map; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/orm/lib/src/runtime/metrics/metrics_format.dart: -------------------------------------------------------------------------------- 1 | enum MetricsFormat { 2 | json, 3 | prometheus, 4 | } 5 | -------------------------------------------------------------------------------- /packages/orm/lib/src/runtime/prisma_enum.dart: -------------------------------------------------------------------------------- 1 | abstract interface class PrismaEnum implements Enum { 2 | /// Returns the name of this enum constant, exactly as declared in its enum 3 | /// declaration. 4 | String get name; 5 | } 6 | -------------------------------------------------------------------------------- /packages/orm/lib/src/runtime/prisma_json.dart: -------------------------------------------------------------------------------- 1 | import 'package:orm/orm.dart'; 2 | 3 | class PrismaJson implements JsonConvertible { 4 | final Object value; 5 | 6 | const PrismaJson(this.value); 7 | const PrismaJson.fromJson(this.value); 8 | 9 | @override 10 | Object toJson() => value; 11 | } 12 | -------------------------------------------------------------------------------- /packages/orm/lib/src/runtime/prisma_null.dart: -------------------------------------------------------------------------------- 1 | class PrismaNull { 2 | const PrismaNull(); 3 | } 4 | -------------------------------------------------------------------------------- /packages/orm/lib/src/runtime/prisma_union.dart: -------------------------------------------------------------------------------- 1 | import 'json_convertible.dart'; 2 | 3 | class PrismaUnion implements JsonConvertible { 4 | final A? $1; 5 | final B? $2; 6 | 7 | const PrismaUnion.$1(A value) 8 | : $1 = value, 9 | $2 = null; 10 | 11 | const PrismaUnion.$2(B value) 12 | : $1 = null, 13 | $2 = value; 14 | 15 | @override 16 | toJson() => JsonConvertible.serialize($1 ?? $2); 17 | } 18 | -------------------------------------------------------------------------------- /packages/orm/lib/src/runtime/raw/_deserialize_raw_results.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import '../decimal.dart'; 4 | 5 | extension type _TypedRawResult._(Map _) { 6 | Iterable get columns => (_['columns'] as Iterable).cast(); 7 | Iterable get types => (_['types'] as Iterable).cast(); 8 | Iterable get rows => (_['rows'] as Iterable).cast(); 9 | } 10 | 11 | List> deserializeRawResult(Map result) { 12 | final _TypedRawResult(:columns, :types, :rows) = _TypedRawResult._(result); 13 | final deserialized = >[]; 14 | 15 | for (final row in rows) { 16 | final mapped = {}; 17 | for (final (index, value) in row.indexed) { 18 | mapped[columns.elementAt(index)] = _decode(types.elementAt(index), value); 19 | } 20 | 21 | deserialized.add(mapped); 22 | } 23 | 24 | return deserialized; 25 | } 26 | 27 | Object? _decode(String type, Object? value) { 28 | if (value == null) return null; 29 | return switch (type) { 30 | 'bigint' => BigInt.parse(value.toString()), 31 | 'bytes' => base64.decode(value.toString()), 32 | 'decimal' => Decimal.parse(value.toString()), 33 | 'datetime' || 'date' => DateTime.parse(value.toString()), 34 | 'time' => DateTime.parse('1970-01-01T${value}Z'), 35 | 'bigint-array' => _decodeIterable('bigint', value as Iterable), 36 | 'bytes-array' => _decodeIterable('bytes', value as Iterable), 37 | 'decimal-array' => _decodeIterable('decimal', value as Iterable), 38 | 'datetime-array' => _decodeIterable('datetime', value as Iterable), 39 | 'date-array' => _decodeIterable('date', value as Iterable), 40 | 'time-array' => _decodeIterable('time', value as Iterable), 41 | _ => value, 42 | }; 43 | } 44 | 45 | List _decodeIterable(String type, Iterable values) { 46 | return values.map((value) => _decode(type, value)).toList(growable: false); 47 | } 48 | -------------------------------------------------------------------------------- /packages/orm/lib/src/runtime/raw/_serialize_raw_params.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:typed_data'; 3 | 4 | import '../decimal.dart'; 5 | import '../json_convertible.dart'; 6 | import '../prisma_null.dart'; 7 | 8 | /// Serialize RAW params. 9 | String serializeRawParams(Iterable params) { 10 | return json.encode( 11 | params.map(_encode).toList(growable: false), 12 | ); 13 | } 14 | 15 | Object? _encode(Object? value) { 16 | return switch (value) { 17 | PrismaNull() => null, 18 | BigInt value => _createTypedValue('bigint', value.toString()), 19 | DateTime value => 20 | _createTypedValue('date', value.toUtc().toIso8601String()), 21 | Decimal value => _createTypedValue('decimal', value.toString()), 22 | Uint8List bytes => _createTypedValue('bytes', base64.encode(bytes)), 23 | TypedData typedData => _encode(typedData.buffer), 24 | ByteBuffer byteBuffer => _encode(byteBuffer.asUint8List()), 25 | JsonConvertible value => _createTypedValue('json', value.toJson()), 26 | Iterable iterable => iterable.map(_encode).toList(growable: false), 27 | Map value => 28 | value.map((key, value) => MapEntry(key.toString(), _encode(value))), 29 | _ => value, 30 | }; 31 | } 32 | 33 | Map _createTypedValue(String type, Object value) { 34 | return { 35 | 'prisma__type': type, 36 | 'prisma__value': value, 37 | }; 38 | } 39 | -------------------------------------------------------------------------------- /packages/orm/lib/src/runtime/raw/raw_client.dart: -------------------------------------------------------------------------------- 1 | import '../../base_prisma_client.dart'; 2 | import '../json_protocol/protocol.dart'; 3 | import '../json_protocol/serialize.dart'; 4 | import '_serialize_raw_params.dart'; 5 | import '_deserialize_raw_results.dart'; 6 | 7 | class RawClient> { 8 | final Client _client; 9 | 10 | const RawClient(Client client) : _client = client; 11 | 12 | Future>> query( 13 | String sql, [ 14 | Iterable? parameters, 15 | ]) async { 16 | final results = await _innerRunSQL( 17 | action: JsonQueryAction.queryRaw, 18 | sql: sql, 19 | parameters: parameters, 20 | ); 21 | 22 | return deserializeRawResult(results[JsonQueryAction.queryRaw.name]); 23 | } 24 | 25 | Future execute(String sql, [Iterable? parameters]) async { 26 | final results = await _innerRunSQL( 27 | action: JsonQueryAction.executeRaw, 28 | sql: sql, 29 | parameters: parameters, 30 | ); 31 | 32 | return results[JsonQueryAction.executeRaw.name]; 33 | } 34 | 35 | Future _innerRunSQL({ 36 | required String sql, 37 | required JsonQueryAction action, 38 | Iterable? parameters, 39 | }) async { 40 | final args = { 41 | 'query': sql, 42 | 'parameters': serializeRawParams(parameters ?? const []), 43 | }; 44 | 45 | final query = serializeJsonQuery( 46 | datamodel: _client.$datamodel, 47 | action: action, 48 | args: args, 49 | ); 50 | 51 | return _client.$engine.request( 52 | query, 53 | headers: _client.$transaction.headers, 54 | transaction: _client.$transaction.transaction, 55 | ); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /packages/orm/lib/src/runtime/reference.dart: -------------------------------------------------------------------------------- 1 | import 'prisma_enum.dart'; 2 | 3 | abstract interface class Reference implements PrismaEnum { 4 | @override 5 | String get name; 6 | 7 | String get model; 8 | } 9 | -------------------------------------------------------------------------------- /packages/orm/lib/src/runtime/transaction/isolation_level.dart: -------------------------------------------------------------------------------- 1 | import '../prisma_enum.dart'; 2 | 3 | enum TransactionIsolationLevel implements PrismaEnum { 4 | readUncommitted("ReadUncommitted"), 5 | readCommitted("ReadCommitted"), 6 | repeatableRead("RepeatableRead"), 7 | snapshot("Snapshot"), 8 | serializable("Serializable"); 9 | 10 | @override 11 | final String name; 12 | 13 | const TransactionIsolationLevel(this.name); 14 | } 15 | -------------------------------------------------------------------------------- /packages/orm/lib/src/runtime/transaction/transaction.dart: -------------------------------------------------------------------------------- 1 | class Transaction { 2 | /// Transaction ID returned by the query engine. 3 | final String id; 4 | 5 | const Transaction(this.id); 6 | } 7 | -------------------------------------------------------------------------------- /packages/orm/lib/src/runtime/transaction/transaction_headers.dart: -------------------------------------------------------------------------------- 1 | import 'package:webfetch/webfetch.dart'; 2 | 3 | class TransactionHeaders implements Headers { 4 | final _headers = Headers(); 5 | 6 | TransactionHeaders({String? traceparent}) { 7 | if (traceparent != null) { 8 | _headers.set('traceparent', traceparent); 9 | } 10 | } 11 | 12 | @override 13 | void append(String name, String value) { 14 | if (name.toLowerCase() == 'traceparent') { 15 | return _headers.set(name, value); 16 | } 17 | 18 | _headers.append(name, value); 19 | } 20 | 21 | @override 22 | void delete(String name) => _headers.delete(name); 23 | 24 | @override 25 | Iterable<(String, String)> entries() => _headers.entries(); 26 | 27 | @override 28 | void forEach(void Function(String value, String name, Headers parent) fn) => 29 | _headers.forEach(fn); 30 | 31 | @override 32 | String? get(String name) => _headers.get(name); 33 | 34 | @override 35 | Iterable getSetCookie() => _headers.getSetCookie(); 36 | 37 | @override 38 | bool has(String name) => _headers.has(name); 39 | 40 | @override 41 | Iterable keys() => _headers.keys(); 42 | 43 | @override 44 | void set(String name, String value) => _headers.set(name, value); 45 | 46 | @override 47 | Iterable values() => _headers.values(); 48 | 49 | String? get traceparent => get('traceparent'); 50 | 51 | set traceparent(String? value) { 52 | if (value == null || value.isEmpty) { 53 | return delete('traceparent'); 54 | } 55 | 56 | set('traceparent', value); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /packages/orm/lib/version.dart: -------------------------------------------------------------------------------- 1 | const version = '5.3.2'; 2 | -------------------------------------------------------------------------------- /packages/orm/prisma/schema.prisma: -------------------------------------------------------------------------------- 1 | // This is your Prisma schema file, 2 | // learn more about it in the docs: https://pris.ly/d/prisma-schema 3 | 4 | generator client { 5 | provider = "dart run orm" 6 | output = "client" 7 | engineType = "binary" 8 | } 9 | 10 | datasource db { 11 | provider = "postgresql" 12 | url = env("DATABASE_URL") 13 | } 14 | 15 | model User { 16 | id String @id @default(uuid()) 17 | email String @unique 18 | name String? 19 | posts Post[] 20 | createdAt DateTime @default(now()) 21 | } 22 | 23 | model Post { 24 | id String @id @default(uuid()) @map("_id") 25 | title String 26 | content String 27 | published Boolean 28 | author User? @relation(fields: [authorId], references: [id]) 29 | authorId String? 30 | } 31 | 32 | model Test { 33 | id String @id @default(uuid(7)) 34 | bytes Bytes 35 | } 36 | -------------------------------------------------------------------------------- /packages/orm/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: orm 2 | description: Next-generation ORM for Dart & Flutter | PostgreSQL, MySQL, MariaDB, SQL Server, SQLite, MongoDB and CockroachDB. 3 | homepage: https://prisma.pub 4 | repository: https://github.com/medz/prisma-dart 5 | 6 | resolution: workspace 7 | version: 5.3.4 8 | 9 | funding: 10 | - https://github.com/sponsors/medz 11 | - https://opencollective.com/openodroe 12 | 13 | topics: 14 | - orm 15 | - prisma 16 | - database 17 | 18 | environment: 19 | sdk: ^3.5.0 20 | 21 | executables: 22 | prisma-client-dart: orm 23 | 24 | dependencies: 25 | code_builder: ^4.10.0 26 | dart_style: ^3.1.0 27 | decimal: ^3.1.0 28 | json_rpc_2: ^4.0.0 29 | path: ^1.9.0 30 | rc: ^0.3.3 31 | recase: ^4.1.0 32 | stream_channel: ^2.1.2 33 | webfetch: ^0.1.0 34 | 35 | dev_dependencies: 36 | lints: ^6.0.0 37 | test: ^1.24.8 38 | -------------------------------------------------------------------------------- /packages/orm/test/json_protocol/serialize_test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:typed_data'; 2 | 3 | import 'package:orm/orm.dart'; 4 | import 'package:test/test.dart'; 5 | 6 | import '../_generated/client.dart'; 7 | import '../_generated/prisma.dart'; 8 | 9 | void main() { 10 | test('createManyAndReturn', () { 11 | final query = serializeJsonQuery( 12 | datamodel: PrismaClient.datamodel, 13 | action: JsonQueryAction.createManyAndReturn, 14 | modelName: "User", 15 | ); 16 | 17 | expect(query.toJson(), { 18 | 'modelName': 'User', 19 | 'action': "createManyAndReturn", 20 | 'query': { 21 | 'arguments': allOf(isMap, isEmpty), 22 | 'selection': { 23 | '\$composites': equals(true), 24 | '\$scalars': equals(true), 25 | }, 26 | }, 27 | }); 28 | }); 29 | 30 | test('updateManyAndReturn', () { 31 | final query = serializeJsonQuery( 32 | datamodel: PrismaClient.datamodel, 33 | action: JsonQueryAction.updateManyAndReturn, 34 | modelName: "User", 35 | ); 36 | expect(query.toJson(), { 37 | 'modelName': 'User', 38 | 'action': "updateManyAndReturn", 39 | 'query': { 40 | 'arguments': allOf(isMap, isEmpty), 41 | 'selection': { 42 | '\$composites': equals(true), 43 | '\$scalars': equals(true), 44 | }, 45 | }, 46 | }); 47 | }); 48 | 49 | test("Bytes serialize", () { 50 | final bytes = Uint8List(50); 51 | final query = serializeJsonQuery( 52 | datamodel: PrismaClient.datamodel, 53 | action: JsonQueryAction.createOne, 54 | modelName: "Test", 55 | args: {'data': PrismaUnion.$1(TestCreateInput(bytes: bytes))}); 56 | expect(query.toJson(), { 57 | 'modelName': 'Test', 58 | 'action': "createOne", 59 | 'query': { 60 | 'arguments': { 61 | 'data': { 62 | "bytes": { 63 | '\$type': "Bytes", 64 | 'value': 65 | 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=' 66 | } 67 | }, 68 | }, 69 | 'selection': {'\$composites': true, '\$scalars': true} 70 | }, 71 | }); 72 | }); 73 | } 74 | -------------------------------------------------------------------------------- /packages/orm/test/sqlite.prisma: -------------------------------------------------------------------------------- 1 | generator client { 2 | provider = "dart run orm" 3 | output = "_generated" 4 | } 5 | 6 | datasource db { 7 | provider = "sqlite" 8 | url = env("DATABASE_URL") 9 | } 10 | 11 | model User { 12 | id Int @id @default(autoincrement()) 13 | name String? 14 | createdAt DateTime @default(now()) 15 | updatedAt DateTime @updatedAt 16 | posts Post[] 17 | role Role @default(User) 18 | } 19 | 20 | model Post { 21 | id Int @id @default(autoincrement()) 22 | title String 23 | contents String? 24 | authorId Int 25 | author User @relation(fields: [authorId], references: [id]) 26 | createdAt DateTime @default(now()) 27 | updatedAt DateTime @updatedAt 28 | publishAt DateTime? 29 | } 30 | 31 | model Test { 32 | id Int @id @default(autoincrement()) 33 | bytes Bytes 34 | } 35 | 36 | enum Role { 37 | Admin 38 | User 39 | } 40 | -------------------------------------------------------------------------------- /packages/orm/tool/dmmf_generator.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:io'; 3 | 4 | import 'package:orm/generator_helper.dart'; 5 | 6 | Future main() async { 7 | final generator = GeneratorApp.stdio(stdin: stdin, stdout: stderr); 8 | 9 | generator.onManifest(manifest); 10 | generator.onGenerate(generate); 11 | 12 | await generator.listen(); 13 | } 14 | 15 | Future manifest(GeneratorConfig config) async { 16 | return GeneratorManifest( 17 | prettyName: 'Prisma DMMF', 18 | defaultOutput: 'dmmf.json', 19 | ); 20 | } 21 | 22 | Future generate(GeneratorOptions options) async { 23 | final dmmf = File(options.generator.output!.value); 24 | if (dmmf.existsSync()) { 25 | await dmmf.delete(); 26 | } 27 | 28 | await dmmf.create(recursive: true); 29 | await dmmf.writeAsString(json.encode(options.dmmf.source)); 30 | } 31 | -------------------------------------------------------------------------------- /packages/orm_flutter/.gitignore: -------------------------------------------------------------------------------- 1 | .flutter-plugins* 2 | -------------------------------------------------------------------------------- /packages/orm_flutter/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: "a14f74ff3a1cbd521163c5f03d68113d50af93d3" 8 | channel: "stable" 9 | 10 | project_type: plugin_ffi 11 | 12 | # Tracks metadata for the flutter migrate command 13 | migration: 14 | platforms: 15 | - platform: root 16 | create_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3 17 | base_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3 18 | - platform: android 19 | create_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3 20 | base_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3 21 | - platform: ios 22 | create_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3 23 | base_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3 24 | 25 | # User provided section 26 | 27 | # List of Local paths (relative to this file) that should be 28 | # ignored by the migrate tool. 29 | # 30 | # Files that are not part of the templates will be ignored by default. 31 | unmanaged_files: 32 | - 'lib/main.dart' 33 | - 'ios/Runner.xcodeproj/project.pbxproj' 34 | -------------------------------------------------------------------------------- /packages/orm_flutter/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## v0.5.1 2 | 3 | chore: update `orm_flutter_ffi` to `v0.0.3` version 4 | 5 | ## v0.5.0 6 | 7 | To install Prisma Flutter Integration v0.5.0 run this command 8 | 9 | ```bash 10 | dart pub add orm_flutter:^0.5.0 11 | ``` 12 | 13 | Or update your `pubspec.yaml` file: 14 | 15 | ```yaml 16 | dependencies: 17 | orm_flutter: ^0.5.0 18 | ``` 19 | 20 | ### What's New 21 | 22 | - Upgrade Prisma CABI engine to `v6.0.0` 23 | - Support Swift Package Manager 24 | 25 | ## v0.4.0 26 | 27 | To install Prisma Flutter Integration v0.4.0 run this command 28 | 29 | ```bash 30 | dart pub add orm_flutter:^v0.4.0 31 | ``` 32 | 33 | Or update your `pubspec.yaml` file: 34 | 35 | ```yaml 36 | dependencies: 37 | orm_flutter: ^0.4.0 38 | ``` 39 | 40 | ### What's New 41 | 42 | - **upstream**: Upgrade `orm` package to `v5.2.1` version 43 | - **BREAKING CHANGE**: Engine is no longer implemented internally, only forwards platform-specific implementations, with iOS and Android support currently implemented. 44 | 45 | ### Optimizations 46 | 47 | Now `orm_flutter` no longer implements the engine itself, but forwards platform-specific engine implementations. 48 | 49 | Implemented `orm_flutter_ffi` for Prisma query engine (CABI) implementation: 50 | - `orm_flutter_android`: Dynamic library for Android platform. 51 | - `orm_flutter_ios`: Dynamic library for iOS platform. 52 | 53 | ## v0.3.1 54 | 55 | To install Prisma Flutter Integration v0.3.1 run this command 56 | 57 | ```bash 58 | dart pub add orm_flutter:^0.3.1 59 | ``` 60 | 61 | Or update your `pubspec.yaml` file: 62 | 63 | ```yaml 64 | dependencies: 65 | orm_flutter: ^0.3.1 66 | ``` 67 | 68 | ### What's New 69 | 70 | - **bug**: Fixed an issue where a transaction was not committed, Thx @Joschiller REF [#443](https://github.com/medz/prisma-dart/issues/443) 71 | - **upstream**: Upgrade CABI engine to `bf0e5e8a04cada8225617067eaa03d041e2bba36` (v5.21.1) 72 | 73 | ### Notes 74 | 75 | After upgrading the `orm_flutter` version, please run the `flutter clean` command. 76 | 77 | ## v0.3.0 78 | 79 | ### What's Changed 80 | 81 | - **BREAKING CHANGE**: Upgrade the Dart SDK min version to `^3.5.0` 82 | 83 | ## v0.2.0 84 | 85 | To install Prisma Flutter Integration v0.2.0 run this command 86 | 87 | ```bash 88 | dart pub add orm_flutter:^0.2.0 89 | ``` 90 | 91 | Or update your `pubspec.yaml` file: 92 | 93 | ```yaml 94 | dependencies: 95 | orm_flutter: ^0.2.0 96 | ``` 97 | 98 | ### What's Changed 99 | 100 | - **deps**: Upgrade the `webfetch` to `^0.1.0` version 101 | - **upstream**: Adapt the `orm` package `5.0.*` version 102 | -------------------------------------------------------------------------------- /packages/orm_flutter/LICENSE: -------------------------------------------------------------------------------- 1 | ../../LICENSE -------------------------------------------------------------------------------- /packages/orm_flutter/README.md: -------------------------------------------------------------------------------- 1 | ../../docs/getting-started/flutter.md -------------------------------------------------------------------------------- /packages/orm_flutter/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | 3 | # Additional information about this file can be found at 4 | # https://dart.dev/guides/language/analysis-options 5 | -------------------------------------------------------------------------------- /packages/orm_flutter/example/README.md: -------------------------------------------------------------------------------- 1 | ../../../template/example_stub.md -------------------------------------------------------------------------------- /packages/orm_flutter/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: orm_flutter 2 | description: "The engine of Prisma ORM for Flutter, Library for binding Prisma's C-Abi engine with Flutter." 3 | homepage: https://prisma.pub 4 | repository: https://github.com/medz/prisma-dart 5 | 6 | resolution: workspace 7 | version: 0.5.1 8 | 9 | funding: 10 | - https://github.com/sponsors/medz 11 | - https://opencollective.com/openodroe 12 | 13 | environment: 14 | sdk: ^3.5.0 15 | flutter: ">=3.3.0" 16 | 17 | dependencies: 18 | flutter: 19 | sdk: flutter 20 | orm: ^5.2.1 21 | orm_flutter_ffi: ^0.0.3 22 | 23 | dev_dependencies: 24 | flutter_lints: ^6.0.0 25 | -------------------------------------------------------------------------------- /packages/orm_flutter_android/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .build/ 9 | .buildlog/ 10 | .history 11 | .svn/ 12 | .swiftpm/ 13 | migrate_working_dir/ 14 | 15 | # IntelliJ related 16 | *.iml 17 | *.ipr 18 | *.iws 19 | .idea/ 20 | 21 | # The .vscode folder contains launch configuration and tasks you configure in 22 | # VS Code which you may wish to be included in version control, so this line 23 | # is commented out by default. 24 | #.vscode/ 25 | 26 | # Flutter/Dart/Pub related 27 | # Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. 28 | /pubspec.lock 29 | **/doc/api/ 30 | .dart_tool/ 31 | .flutter-plugins 32 | .flutter-plugins-dependencies 33 | build/ 34 | -------------------------------------------------------------------------------- /packages/orm_flutter_android/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: "2e2c358c9b14765c90343af9df11e12c5dfc3e6c" 8 | channel: "beta" 9 | 10 | project_type: plugin_ffi 11 | 12 | # Tracks metadata for the flutter migrate command 13 | migration: 14 | platforms: 15 | - platform: root 16 | create_revision: 2e2c358c9b14765c90343af9df11e12c5dfc3e6c 17 | base_revision: 2e2c358c9b14765c90343af9df11e12c5dfc3e6c 18 | - platform: android 19 | create_revision: 2e2c358c9b14765c90343af9df11e12c5dfc3e6c 20 | base_revision: 2e2c358c9b14765c90343af9df11e12c5dfc3e6c 21 | 22 | # User provided section 23 | 24 | # List of Local paths (relative to this file) that should be 25 | # ignored by the migrate tool. 26 | # 27 | # Files that are not part of the templates will be ignored by default. 28 | unmanaged_files: 29 | - 'lib/main.dart' 30 | - 'ios/Runner.xcodeproj/project.pbxproj' 31 | -------------------------------------------------------------------------------- /packages/orm_flutter_android/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.0.2 2 | 3 | * Upgrade Prisma CABI engine to `v6.0.0`. 4 | 5 | ## 0.0.1 6 | 7 | * Export dynamic library for Prisma query engine (CABI) 8 | -------------------------------------------------------------------------------- /packages/orm_flutter_android/LICENSE: -------------------------------------------------------------------------------- 1 | ../../LICENSE -------------------------------------------------------------------------------- /packages/orm_flutter_android/README.md: -------------------------------------------------------------------------------- 1 | # orm_flutter_android 2 | 3 | Dynamic library implementation library for Prisma Dart and Flutter integration on Android platform. 4 | 5 | > [!IMPORTANT] 6 | > This package only provides dynamic libraries related to Prisma Query Engine (CABI). For specific usage instructions, please refer to [orm_flutter_ffi](https://pub.dev/packages/orm_flutter_ffi) 7 | 8 | ## Support 9 | 10 | This project needs your support! You can help in the following ways: 11 | 12 | - [GitHub Sponsors](https://github.com/sponsors/medz) 13 | - [Open Collective](https://opencollective.com/openodroe) 14 | -------------------------------------------------------------------------------- /packages/orm_flutter_android/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | 3 | # Additional information about this file can be found at 4 | # https://dart.dev/guides/language/analysis-options 5 | -------------------------------------------------------------------------------- /packages/orm_flutter_android/android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .cxx 10 | -------------------------------------------------------------------------------- /packages/orm_flutter_android/android/build.gradle: -------------------------------------------------------------------------------- 1 | // The Android Gradle Plugin builds the native code with the Android NDK. 2 | 3 | group = "dev.odroe.orm_flutter_android" 4 | version = "0.0.2" 5 | 6 | buildscript { 7 | repositories { 8 | google() 9 | mavenCentral() 10 | } 11 | 12 | dependencies { 13 | // The Android Gradle Plugin knows how to build native code with the NDK. 14 | classpath("com.android.tools.build:gradle:8.7.3") 15 | } 16 | } 17 | 18 | rootProject.allprojects { 19 | repositories { 20 | google() 21 | mavenCentral() 22 | } 23 | } 24 | 25 | apply plugin: "com.android.library" 26 | 27 | android { 28 | namespace = "dev.odroe.orm_flutter_android" 29 | 30 | // Bumping the plugin compileSdk version requires all clients of this plugin 31 | // to bump the version in their app. 32 | compileSdk = 35 33 | 34 | // Use the NDK version 35 | // declared in /android/app/build.gradle file of the Flutter project. 36 | // Replace it with a version number if this plugin requires a specific NDK version. 37 | // (e.g. ndkVersion "23.1.7779620") 38 | ndkVersion = android.ndkVersion 39 | 40 | // Invoke the shared CMake build with the Android Gradle Plugin. 41 | externalNativeBuild { 42 | cmake { 43 | path = "../src/CMakeLists.txt" 44 | 45 | // The default CMake version for the Android Gradle Plugin is 3.10.2. 46 | // https://developer.android.com/studio/projects/install-ndk#vanilla_cmake 47 | // 48 | // The Flutter tooling requires that developers have CMake 3.10 or later 49 | // installed. You should not increase this version, as doing so will cause 50 | // the plugin to fail to compile for some customers of the plugin. 51 | // version "3.10.2" 52 | } 53 | } 54 | 55 | compileOptions { 56 | sourceCompatibility = JavaVersion.VERSION_1_8 57 | targetCompatibility = JavaVersion.VERSION_1_8 58 | } 59 | 60 | defaultConfig { 61 | minSdk = 21 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /packages/orm_flutter_android/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'orm_flutter_android' 2 | -------------------------------------------------------------------------------- /packages/orm_flutter_android/android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /packages/orm_flutter_android/example/README.md: -------------------------------------------------------------------------------- 1 | ../../../template/example_stub.md -------------------------------------------------------------------------------- /packages/orm_flutter_android/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: orm_flutter_android 2 | description: "Dynamic library implementation library for Prisma Dart and Flutter integration on Android platform." 3 | homepage: https://prisma.pub 4 | 5 | resolution: workspace 6 | version: 0.0.2 7 | 8 | funding: 9 | - https://github.com/sponsors/medz 10 | - https://opencollective.com/openodroe 11 | 12 | environment: 13 | sdk: ^3.5.0 14 | flutter: ">=3.3.0" 15 | 16 | flutter: 17 | plugin: 18 | platforms: 19 | android: 20 | ffiPlugin: true 21 | -------------------------------------------------------------------------------- /packages/orm_flutter_android/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The Flutter tooling requires that developers have CMake 3.10 or later 2 | # installed. You should not increase this version, as doing so will cause 3 | # the plugin to fail to compile for some customers of the plugin. 4 | cmake_minimum_required(VERSION 3.10) 5 | 6 | project(orm_flutter_android_library VERSION 0.0.2 LANGUAGES C) 7 | 8 | add_library(orm_flutter_android SHARED 9 | "query_engine_bridge/bridge.c" 10 | ) 11 | 12 | set_target_properties(orm_flutter_android PROPERTIES 13 | PUBLIC_HEADER query_engine_bridge/headers/bridge.h 14 | OUTPUT_NAME "orm_flutter_android" 15 | ) 16 | 17 | target_compile_definitions(orm_flutter_android PUBLIC DART_SHARED_LIB) 18 | 19 | if (ANDROID) 20 | # Support Android 15 16k page size 21 | target_link_options(orm_flutter_android PRIVATE "-Wl,-z,max-page-size=16384") 22 | endif() 23 | 24 | add_library(prisma_query_engine STATIC IMPORTED) 25 | 26 | if ((CMAKE_VERSION GREATER 3.20) OR (CMAKE_VERSION EQUAL 3.20)) 27 | cmake_path(SET PRISMA_QUERY_ENGINE_LIB ${CMAKE_CURRENT_SOURCE_DIR}/jniLibs/${ANDROID_ABI}/libquery_engine.a NORMALIZE) 28 | else() 29 | set(PRISMA_QUERY_ENGINE_LIB ${CMAKE_CURRENT_SOURCE_DIR}/jniLibs/${ANDROID_ABI}/libquery_engine.a) 30 | endif() 31 | 32 | set_target_properties(prisma_query_engine PROPERTIES 33 | IMPORTED_LOCATION ${PRISMA_QUERY_ENGINE_LIB} 34 | PUBLIC_HEADER query_engine_bridge/include/query_engine.h 35 | ) 36 | 37 | target_link_libraries( 38 | orm_flutter_android 39 | prisma_query_engine 40 | ) 41 | -------------------------------------------------------------------------------- /packages/orm_flutter_android/src/jniLibs/arm64-v8a/libquery_engine.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/packages/orm_flutter_android/src/jniLibs/arm64-v8a/libquery_engine.a -------------------------------------------------------------------------------- /packages/orm_flutter_android/src/jniLibs/armeabi-v7a/libquery_engine.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/packages/orm_flutter_android/src/jniLibs/armeabi-v7a/libquery_engine.a -------------------------------------------------------------------------------- /packages/orm_flutter_android/src/jniLibs/x86/libquery_engine.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/packages/orm_flutter_android/src/jniLibs/x86/libquery_engine.a -------------------------------------------------------------------------------- /packages/orm_flutter_android/src/jniLibs/x86_64/libquery_engine.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/packages/orm_flutter_android/src/jniLibs/x86_64/libquery_engine.a -------------------------------------------------------------------------------- /packages/orm_flutter_android/src/query_engine_bridge/README.md: -------------------------------------------------------------------------------- 1 | # Prisma Query Engine Bridge 2 | 3 | This is a bridge for the Prisma C-ABI query engine static library written by C. 4 | 5 | > Why do we need it? 6 | There is a problem with loading static libraries with the Flutter plugin, and it is very likely that symbols cannot be found. Therefore, adding bridges to generate dynamic libraries can solve this problem. 7 | 8 | ## Prisma Issues deps Dart issues 9 | - [[prisma/prisma#24295] - C-ABI Engine Feature Request](https://github.com/prisma/prisma/issues/24295) 10 | 11 | ## Dart issues 12 | - [[dart-lang/native#934#issuecomment-1894151501] - Using dart:ffi with a xcframework containing static binaries (iOS)](https://github.com/dart-lang/native/issues/934) 13 | - [[dart-lang/sdk#49418] - Explore using FfiNative for static linking](https://github.com/dart-lang/sdk/issues/49418) 14 | 15 | ## When will it no longer be needed? 16 | 17 | When Dart solves any linking issues between static libraries and DFI. 18 | -------------------------------------------------------------------------------- /packages/orm_flutter_android/src/query_engine_bridge/bridge.c: -------------------------------------------------------------------------------- 1 | #include "headers/bridge.h" 2 | 3 | /** 4 | * Create a new [QueryEngine] 5 | * 6 | * Returns a [Status] code. 7 | */ 8 | FFI_PLUGIN_EXPORT enum Status create( 9 | struct ConstructorOptions options, 10 | struct QueryEngine **qePtr, 11 | char **errorStringPtr) 12 | { 13 | return prisma_create(options, qePtr, errorStringPtr); 14 | } 15 | 16 | /** 17 | * Destroy a [QueryEngine] 18 | */ 19 | FFI_PLUGIN_EXPORT enum Status destroy(struct QueryEngine *qe) 20 | { 21 | return prisma_destroy(qe); 22 | } 23 | 24 | /** 25 | * Start a [QueryEngine] 26 | */ 27 | FFI_PLUGIN_EXPORT enum Status start( 28 | struct QueryEngine *qe, 29 | const char *trace, 30 | char **errorStringPtr) 31 | { 32 | return prisma_connect(qe, trace, errorStringPtr); 33 | } 34 | 35 | /** 36 | * Stop a [QueryEngine] 37 | */ 38 | FFI_PLUGIN_EXPORT enum Status stop( 39 | struct QueryEngine *qe, 40 | const char *headerStr) 41 | { 42 | return prisma_disconnect(qe, headerStr); 43 | } 44 | 45 | /** 46 | * Apply migrations 47 | */ 48 | FFI_PLUGIN_EXPORT enum Status applyMigrations( 49 | struct QueryEngine *qe, 50 | const char *migrationsPath, 51 | char **errorStringPtr) 52 | { 53 | return prisma_apply_pending_migrations(qe, migrationsPath, errorStringPtr); 54 | } 55 | 56 | /** 57 | * Query a prisma request 58 | */ 59 | FFI_PLUGIN_EXPORT const char *query( 60 | struct QueryEngine *qe, 61 | const char *bodyStr, 62 | const char *headerStr, 63 | const char *txIdStr, 64 | char **errorStringPtr) 65 | { 66 | return prisma_query(qe, bodyStr, headerStr, txIdStr, errorStringPtr); 67 | } 68 | 69 | /** 70 | * Start a transaction 71 | */ 72 | FFI_PLUGIN_EXPORT const char *startTransaction( 73 | struct QueryEngine *qe, 74 | const char *optionsStr, 75 | const char *headerStr) 76 | { 77 | return prisma_start_transaction(qe, optionsStr, headerStr); 78 | } 79 | 80 | /** 81 | * Commit a transaction querys 82 | */ 83 | FFI_PLUGIN_EXPORT const char *commitTransaction( 84 | struct QueryEngine *qe, 85 | const char *txIdStr, 86 | const char *headerStr) 87 | { 88 | return prisma_commit_transaction(qe, txIdStr, headerStr); 89 | } 90 | 91 | /** 92 | * Rollback a transaction 93 | */ 94 | FFI_PLUGIN_EXPORT const char *rollbackTransaction( 95 | struct QueryEngine *qe, 96 | const char *txIdStr, 97 | const char *headerStr) 98 | { 99 | return prisma_rollback_transaction(qe, txIdStr, headerStr); 100 | } 101 | -------------------------------------------------------------------------------- /packages/orm_flutter_android/src/query_engine_bridge/headers/bridge.h: -------------------------------------------------------------------------------- 1 | #include "../include/query_engine.h" 2 | 3 | #if _WIN32 4 | #include 5 | #endif 6 | 7 | #if _WIN32 8 | #define FFI_PLUGIN_EXPORT __declspec(dllexport) 9 | #else 10 | #define FFI_PLUGIN_EXPORT 11 | #endif 12 | 13 | #ifndef QueryEngine 14 | typedef struct QueryEngine {} QueryEngine; 15 | #endif 16 | 17 | /** 18 | * function returns status code. 19 | * 20 | * see: 21 | * - [QueryEngineBindings.create] 22 | * - [QueryEngineBindings.destroy] 23 | * - [QueryEngineBindings.start] 24 | * - [QueryEngineBindings.stop] 25 | * - [QueryEngineBindings.applyMigrations] 26 | */ 27 | FFI_PLUGIN_EXPORT enum Status { 28 | /** Success */ 29 | ok = 0, 30 | /** Error */ 31 | err = 1, 32 | /** Missing pointer, only create returns. */ 33 | miss = 2 34 | }; 35 | 36 | /** 37 | * Create a new [QueryEngine] 38 | * Returns a [Status] code. 39 | */ 40 | FFI_PLUGIN_EXPORT enum Status create( 41 | struct ConstructorOptions options, 42 | struct QueryEngine **qePtr, 43 | char **errorStringPtr 44 | ); 45 | 46 | /** 47 | * Destroy a [QueryEngine] 48 | */ 49 | FFI_PLUGIN_EXPORT enum Status destroy(struct QueryEngine *qe); 50 | 51 | /** 52 | * Start a [QueryEngine] 53 | */ 54 | FFI_PLUGIN_EXPORT enum Status start( 55 | struct QueryEngine *qe, 56 | const char *trace, 57 | char **errorStringPtr 58 | ); 59 | 60 | /** 61 | * Stop a [QueryEngine] 62 | */ 63 | FFI_PLUGIN_EXPORT enum Status stop( 64 | struct QueryEngine *qe, 65 | const char *headerStr 66 | ); 67 | 68 | /** 69 | * Apply migrations 70 | */ 71 | FFI_PLUGIN_EXPORT enum Status applyMigrations( 72 | struct QueryEngine *qe, 73 | const char *migrationsPath, 74 | char **errorStringPtr 75 | ); 76 | 77 | /** 78 | * Query a prisma request 79 | */ 80 | FFI_PLUGIN_EXPORT const char *query( 81 | struct QueryEngine *qe, 82 | const char *bodyStr, 83 | const char *headerStr, 84 | const char *txIdStr, 85 | char **errorStringPtr 86 | ); 87 | 88 | /** 89 | * Start a transaction 90 | */ 91 | FFI_PLUGIN_EXPORT const char *startTransaction( 92 | struct QueryEngine *qe, 93 | const char *optionsStr, 94 | const char *headerStr 95 | ); 96 | 97 | /** 98 | * Commit a transaction queries 99 | */ 100 | FFI_PLUGIN_EXPORT const char *commitTransaction( 101 | struct QueryEngine *qe, 102 | const char *txIdStr, 103 | const char *headerStr 104 | ); 105 | 106 | /** 107 | * Rollback a transaction 108 | */ 109 | FFI_PLUGIN_EXPORT const char *rollbackTransaction( 110 | struct QueryEngine *qe, 111 | const char *txIdStr, 112 | const char *headerStr 113 | ); 114 | -------------------------------------------------------------------------------- /packages/orm_flutter_ffi/.gitignore: -------------------------------------------------------------------------------- 1 | .flutter-plugins 2 | .flutter-plugins-dependencies 3 | .dart_tool/ 4 | 5 | pubspec.lock 6 | -------------------------------------------------------------------------------- /packages/orm_flutter_ffi/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## v0.0.3 2 | 3 | - chore: update `ffigen` to `v19` 4 | 5 | ## v0.0.2 6 | 7 | - Upgrade `orm_flutter_android` to 0.0.2 version 8 | - Upgrade `orm_flutter_ios` to 0.0.4 version 9 | - Support SPM build for iOS 10 | 11 | ## v0.0.1 12 | 13 | - FFI implementation of Prisma and Flutter integration query engine, acknowledged by `orm_flutter` 14 | -------------------------------------------------------------------------------- /packages/orm_flutter_ffi/LICENSE: -------------------------------------------------------------------------------- 1 | ../../LICENSE -------------------------------------------------------------------------------- /packages/orm_flutter_ffi/README.md: -------------------------------------------------------------------------------- 1 | # orm_flutter_ffi 2 | 3 | This is an implementation of the Prisma Query Engine (FFI) integrated with Flutter. 4 | 5 | > [!IMPORTANT] 6 | > This package is acknowledged by `orm_flutter`, implementing a dynamic library wrapper 7 | > that integrates the dynamic libraries (Prisma Query Engine CAPI) exported by 8 | > `orm_flutter_android` and `orm_flutter_ios`. 9 | 10 | ## Support 11 | 12 | This project needs your support! You can help in the following ways: 13 | 14 | - [GitHub Sponsors](https://github.com/sponsors/medz) 15 | - [Open Collective](https://opencollective.com/openodroe) 16 | -------------------------------------------------------------------------------- /packages/orm_flutter_ffi/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | -------------------------------------------------------------------------------- /packages/orm_flutter_ffi/example/README.md: -------------------------------------------------------------------------------- 1 | ../../../template/example_stub.md -------------------------------------------------------------------------------- /packages/orm_flutter_ffi/lib/orm_flutter_ffi.dart: -------------------------------------------------------------------------------- 1 | export 'src/library_engine.dart' show LibraryEngine; 2 | -------------------------------------------------------------------------------- /packages/orm_flutter_ffi/lib/src/bindings.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ffi'; 2 | import 'dart:io'; 3 | 4 | import '_generate_bindings.dart'; 5 | 6 | DynamicLibrary get _dl { 7 | if (Platform.isIOS) { 8 | // Try open SPM generated library. 9 | try { 10 | return DynamicLibrary.open('orm-flutter-ios.framework/orm-flutter-ios'); 11 | 12 | // Fallback open podspec defined library. 13 | } catch (_) { 14 | return DynamicLibrary.open('orm_flutter_ios.framework/orm_flutter_ios'); 15 | } 16 | } else if (Platform.isAndroid) { 17 | return DynamicLibrary.open("liborm_flutter_android.so"); 18 | } 19 | 20 | throw UnsupportedError('Susupported platform: ${Platform.operatingSystem}'); 21 | } 22 | 23 | final bindings = QueryEngineBindings(_dl); 24 | -------------------------------------------------------------------------------- /packages/orm_flutter_ffi/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: orm_flutter_ffi 2 | description: FFI implementation of Prisma and Flutter integration query engine, acknowledged by `orm_flutter`. 3 | homepage: https://prisma.pub 4 | repository: https://github.com/medz/prisma-dart 5 | 6 | resolution: workspace 7 | version: 0.0.3 8 | 9 | funding: 10 | - https://github.com/sponsors/medz 11 | - https://opencollective.com/openodroe 12 | 13 | environment: 14 | sdk: ^3.5.0 15 | flutter: ">=3.3.0" 16 | 17 | dependencies: 18 | flutter: 19 | sdk: flutter 20 | ffi: ^2.1.3 21 | orm: ^5.2.1 22 | orm_flutter_android: ^0.0.2 23 | orm_flutter_ios: ^0.0.4 24 | path_provider: ^2.1.5 25 | path: ^1.9.0 26 | 27 | dev_dependencies: 28 | flutter_lints: ^6.0.0 29 | ffigen: ^19.0.0 30 | 31 | ffigen: 32 | name: QueryEngineBindings 33 | description: | 34 | Bindings for `query_engine_bridge.h`. 35 | 36 | Regenerate bindings with `dart run ffigen`. 37 | output: lib/src/_generate_bindings.dart 38 | language: c 39 | headers: 40 | entry-points: 41 | - ../query_engine_bridge/headers/bridge.h 42 | include-directives: 43 | - ../query_engine_bridge/** 44 | comments: 45 | style: any 46 | length: full 47 | silence-enum-warning: true 48 | functions: 49 | exclude: 50 | - prisma_.* 51 | globals: 52 | exclude: 53 | - PRISMA_.* 54 | -------------------------------------------------------------------------------- /packages/orm_flutter_ios/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .build/ 9 | .buildlog/ 10 | .history 11 | .svn/ 12 | .swiftpm/ 13 | migrate_working_dir/ 14 | 15 | # IntelliJ related 16 | *.iml 17 | *.ipr 18 | *.iws 19 | .idea/ 20 | 21 | # The .vscode folder contains launch configuration and tasks you configure in 22 | # VS Code which you may wish to be included in version control, so this line 23 | # is commented out by default. 24 | #.vscode/ 25 | 26 | # Flutter/Dart/Pub related 27 | # Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. 28 | /pubspec.lock 29 | **/doc/api/ 30 | .dart_tool/ 31 | .flutter-plugins 32 | .flutter-plugins-dependencies 33 | build/ 34 | -------------------------------------------------------------------------------- /packages/orm_flutter_ios/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: "2e2c358c9b14765c90343af9df11e12c5dfc3e6c" 8 | channel: "beta" 9 | 10 | project_type: plugin_ffi 11 | 12 | # Tracks metadata for the flutter migrate command 13 | migration: 14 | platforms: 15 | - platform: root 16 | create_revision: 2e2c358c9b14765c90343af9df11e12c5dfc3e6c 17 | base_revision: 2e2c358c9b14765c90343af9df11e12c5dfc3e6c 18 | - platform: ios 19 | create_revision: 2e2c358c9b14765c90343af9df11e12c5dfc3e6c 20 | base_revision: 2e2c358c9b14765c90343af9df11e12c5dfc3e6c 21 | 22 | # User provided section 23 | 24 | # List of Local paths (relative to this file) that should be 25 | # ignored by the migrate tool. 26 | # 27 | # Files that are not part of the templates will be ignored by default. 28 | unmanaged_files: 29 | - 'lib/main.dart' 30 | - 'ios/Runner.xcodeproj/project.pbxproj' 31 | -------------------------------------------------------------------------------- /packages/orm_flutter_ios/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## v0.0.4 2 | 3 | * Support Swift Package Manager 4 | 5 | ## v0.0.3 6 | 7 | * Upgrade Prisma CABI engine to `v6.0.0`. 8 | 9 | ## v0.0.2 10 | 11 | 2024-11-03 12 | 13 | ### What's New 14 | 15 | - complexes 16 | 17 | ## 0.0.1 18 | 19 | first publish. 20 | -------------------------------------------------------------------------------- /packages/orm_flutter_ios/LICENSE: -------------------------------------------------------------------------------- 1 | ../../LICENSE -------------------------------------------------------------------------------- /packages/orm_flutter_ios/README.md: -------------------------------------------------------------------------------- 1 | # orm_flutter_ios 2 | 3 | Dynamic library implementation library for Prisma Dart and Flutter integration on iOS platform. 4 | 5 | > [!IMPORTANT] 6 | > This package only provides dynamic libraries related to Prisma Query Engine (CABI). For specific usage instructions, please refer to [orm_flutter_ffi](https://pub.dev/packages/orm_flutter_ffi) 7 | 8 | ## Support 9 | 10 | This project needs your support! You can help in the following ways: 11 | 12 | - [GitHub Sponsors](https://github.com/sponsors/medz) 13 | - [Open Collective](https://opencollective.com/openodroe) 14 | -------------------------------------------------------------------------------- /packages/orm_flutter_ios/example/README.md: -------------------------------------------------------------------------------- 1 | ../../../template/example_stub.md -------------------------------------------------------------------------------- /packages/orm_flutter_ios/ios/orm_flutter_ios.podspec: -------------------------------------------------------------------------------- 1 | require 'yaml' 2 | 3 | pubspec = YAML.load_file( 4 | File.join(__dir__, '../pubspec.yaml') 5 | ) 6 | 7 | Pod::Spec.new do |s| 8 | s.name = pubspec['name'] 9 | s.version = pubspec['version'] 10 | s.summary = pubspec['description'] 11 | s.homepage = pubspec['homepage'] 12 | s.license = { :file => '../LICENSE', :type => "BSD-3" } 13 | s.author = { 'Odroe Inc.' => 'hello@odroe.dev' } 14 | 15 | s.source = { :path => '.' } 16 | s.source_files = 'orm_flutter_ios/Sources/**/*' 17 | s.dependency 'Flutter' 18 | s.vendored_frameworks = 'orm_flutter_ios/Frameworks/QueryEngine.xcframework' 19 | s.platform = :ios, '12.0' 20 | 21 | # Flutter.framework does not contain a i386 slice. 22 | s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } 23 | s.swift_version = '5.0' 24 | end 25 | -------------------------------------------------------------------------------- /packages/orm_flutter_ios/ios/orm_flutter_ios/Frameworks/QueryEngine.xcframework/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | AvailableLibraries 6 | 7 | 8 | BinaryPath 9 | libquery_engine.a 10 | HeadersPath 11 | Headers 12 | LibraryIdentifier 13 | ios-arm64 14 | LibraryPath 15 | libquery_engine.a 16 | SupportedArchitectures 17 | 18 | arm64 19 | 20 | SupportedPlatform 21 | ios 22 | 23 | 24 | BinaryPath 25 | libquery_engine.a 26 | HeadersPath 27 | Headers 28 | LibraryIdentifier 29 | ios-arm64_x86_64-simulator 30 | LibraryPath 31 | libquery_engine.a 32 | SupportedArchitectures 33 | 34 | arm64 35 | x86_64 36 | 37 | SupportedPlatform 38 | ios 39 | SupportedPlatformVariant 40 | simulator 41 | 42 | 43 | CFBundlePackageType 44 | XFWK 45 | XCFrameworkFormatVersion 46 | 1.0 47 | 48 | 49 | -------------------------------------------------------------------------------- /packages/orm_flutter_ios/ios/orm_flutter_ios/Frameworks/QueryEngine.xcframework/ios-arm64/libquery_engine.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/packages/orm_flutter_ios/ios/orm_flutter_ios/Frameworks/QueryEngine.xcframework/ios-arm64/libquery_engine.a -------------------------------------------------------------------------------- /packages/orm_flutter_ios/ios/orm_flutter_ios/Frameworks/QueryEngine.xcframework/ios-arm64_x86_64-simulator/libquery_engine.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medz/prisma-dart/14719e45d270e7f0ff159a7ba1837730c4fae3b2/packages/orm_flutter_ios/ios/orm_flutter_ios/Frameworks/QueryEngine.xcframework/ios-arm64_x86_64-simulator/libquery_engine.a -------------------------------------------------------------------------------- /packages/orm_flutter_ios/ios/orm_flutter_ios/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.9 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "orm_flutter_ios", 7 | platforms: [ 8 | .iOS(.v12) 9 | ], 10 | products: [ 11 | .library( 12 | name: "orm-flutter-ios", 13 | type: .dynamic, 14 | targets: ["query_engine_bridge"] 15 | ) 16 | ], 17 | targets: [ 18 | .target( 19 | name: "query_engine_bridge", 20 | dependencies: [ 21 | .target(name: "PrismaQueryEngine") 22 | ], 23 | linkerSettings: [ 24 | .linkedFramework("CoreFoundation"), 25 | .linkedFramework("Security"), 26 | ] 27 | ), 28 | .binaryTarget( 29 | name: "PrismaQueryEngine", 30 | path: "Frameworks/QueryEngine.xcframework" 31 | ), 32 | ] 33 | ) 34 | -------------------------------------------------------------------------------- /packages/orm_flutter_ios/ios/orm_flutter_ios/Sources/query_engine_bridge/README.md: -------------------------------------------------------------------------------- 1 | # Prisma Query Engine Bridge 2 | 3 | This is a bridge for the Prisma C-ABI query engine static library written by C. 4 | 5 | > Why do we need it? 6 | There is a problem with loading static libraries with the Flutter plugin, and it is very likely that symbols cannot be found. Therefore, adding bridges to generate dynamic libraries can solve this problem. 7 | 8 | ## Prisma Issues deps Dart issues 9 | - [[prisma/prisma#24295] - C-ABI Engine Feature Request](https://github.com/prisma/prisma/issues/24295) 10 | 11 | ## Dart issues 12 | - [[dart-lang/native#934#issuecomment-1894151501] - Using dart:ffi with a xcframework containing static binaries (iOS)](https://github.com/dart-lang/native/issues/934) 13 | - [[dart-lang/sdk#49418] - Explore using FfiNative for static linking](https://github.com/dart-lang/sdk/issues/49418) 14 | 15 | ## When will it no longer be needed? 16 | 17 | When Dart solves any linking issues between static libraries and DFI. 18 | -------------------------------------------------------------------------------- /packages/orm_flutter_ios/ios/orm_flutter_ios/Sources/query_engine_bridge/bridge.c: -------------------------------------------------------------------------------- 1 | #include "headers/bridge.h" 2 | 3 | /** 4 | * Create a new [QueryEngine] 5 | * 6 | * Returns a [Status] code. 7 | */ 8 | FFI_PLUGIN_EXPORT enum Status create( 9 | struct ConstructorOptions options, 10 | struct QueryEngine **qePtr, 11 | char **errorStringPtr) 12 | { 13 | return prisma_create(options, qePtr, errorStringPtr); 14 | } 15 | 16 | /** 17 | * Destroy a [QueryEngine] 18 | */ 19 | FFI_PLUGIN_EXPORT enum Status destroy(struct QueryEngine *qe) 20 | { 21 | return prisma_destroy(qe); 22 | } 23 | 24 | /** 25 | * Start a [QueryEngine] 26 | */ 27 | FFI_PLUGIN_EXPORT enum Status start( 28 | struct QueryEngine *qe, 29 | const char *trace, 30 | char **errorStringPtr) 31 | { 32 | return prisma_connect(qe, trace, errorStringPtr); 33 | } 34 | 35 | /** 36 | * Stop a [QueryEngine] 37 | */ 38 | FFI_PLUGIN_EXPORT enum Status stop( 39 | struct QueryEngine *qe, 40 | const char *headerStr) 41 | { 42 | return prisma_disconnect(qe, headerStr); 43 | } 44 | 45 | /** 46 | * Apply migrations 47 | */ 48 | FFI_PLUGIN_EXPORT enum Status applyMigrations( 49 | struct QueryEngine *qe, 50 | const char *migrationsPath, 51 | char **errorStringPtr) 52 | { 53 | return prisma_apply_pending_migrations(qe, migrationsPath, errorStringPtr); 54 | } 55 | 56 | /** 57 | * Query a prisma request 58 | */ 59 | FFI_PLUGIN_EXPORT const char *query( 60 | struct QueryEngine *qe, 61 | const char *bodyStr, 62 | const char *headerStr, 63 | const char *txIdStr, 64 | char **errorStringPtr) 65 | { 66 | return prisma_query(qe, bodyStr, headerStr, txIdStr, errorStringPtr); 67 | } 68 | 69 | /** 70 | * Start a transaction 71 | */ 72 | FFI_PLUGIN_EXPORT const char *startTransaction( 73 | struct QueryEngine *qe, 74 | const char *optionsStr, 75 | const char *headerStr) 76 | { 77 | return prisma_start_transaction(qe, optionsStr, headerStr); 78 | } 79 | 80 | /** 81 | * Commit a transaction querys 82 | */ 83 | FFI_PLUGIN_EXPORT const char *commitTransaction( 84 | struct QueryEngine *qe, 85 | const char *txIdStr, 86 | const char *headerStr) 87 | { 88 | return prisma_commit_transaction(qe, txIdStr, headerStr); 89 | } 90 | 91 | /** 92 | * Rollback a transaction 93 | */ 94 | FFI_PLUGIN_EXPORT const char *rollbackTransaction( 95 | struct QueryEngine *qe, 96 | const char *txIdStr, 97 | const char *headerStr) 98 | { 99 | return prisma_rollback_transaction(qe, txIdStr, headerStr); 100 | } 101 | -------------------------------------------------------------------------------- /packages/orm_flutter_ios/ios/orm_flutter_ios/Sources/query_engine_bridge/headers/bridge.h: -------------------------------------------------------------------------------- 1 | #include "../include/query_engine.h" 2 | 3 | #if _WIN32 4 | #include 5 | #endif 6 | 7 | #if _WIN32 8 | #define FFI_PLUGIN_EXPORT __declspec(dllexport) 9 | #else 10 | #define FFI_PLUGIN_EXPORT 11 | #endif 12 | 13 | #ifndef QueryEngine 14 | typedef struct QueryEngine {} QueryEngine; 15 | #endif 16 | 17 | /** 18 | * function returns status code. 19 | * 20 | * see: 21 | * - [QueryEngineBindings.create] 22 | * - [QueryEngineBindings.destroy] 23 | * - [QueryEngineBindings.start] 24 | * - [QueryEngineBindings.stop] 25 | * - [QueryEngineBindings.applyMigrations] 26 | */ 27 | FFI_PLUGIN_EXPORT enum Status { 28 | /** Success */ 29 | ok = 0, 30 | /** Error */ 31 | err = 1, 32 | /** Missing pointer, only create returns. */ 33 | miss = 2 34 | }; 35 | 36 | /** 37 | * Create a new [QueryEngine] 38 | * Returns a [Status] code. 39 | */ 40 | FFI_PLUGIN_EXPORT enum Status create( 41 | struct ConstructorOptions options, 42 | struct QueryEngine **qePtr, 43 | char **errorStringPtr 44 | ); 45 | 46 | /** 47 | * Destroy a [QueryEngine] 48 | */ 49 | FFI_PLUGIN_EXPORT enum Status destroy(struct QueryEngine *qe); 50 | 51 | /** 52 | * Start a [QueryEngine] 53 | */ 54 | FFI_PLUGIN_EXPORT enum Status start( 55 | struct QueryEngine *qe, 56 | const char *trace, 57 | char **errorStringPtr 58 | ); 59 | 60 | /** 61 | * Stop a [QueryEngine] 62 | */ 63 | FFI_PLUGIN_EXPORT enum Status stop( 64 | struct QueryEngine *qe, 65 | const char *headerStr 66 | ); 67 | 68 | /** 69 | * Apply migrations 70 | */ 71 | FFI_PLUGIN_EXPORT enum Status applyMigrations( 72 | struct QueryEngine *qe, 73 | const char *migrationsPath, 74 | char **errorStringPtr 75 | ); 76 | 77 | /** 78 | * Query a prisma request 79 | */ 80 | FFI_PLUGIN_EXPORT const char *query( 81 | struct QueryEngine *qe, 82 | const char *bodyStr, 83 | const char *headerStr, 84 | const char *txIdStr, 85 | char **errorStringPtr 86 | ); 87 | 88 | /** 89 | * Start a transaction 90 | */ 91 | FFI_PLUGIN_EXPORT const char *startTransaction( 92 | struct QueryEngine *qe, 93 | const char *optionsStr, 94 | const char *headerStr 95 | ); 96 | 97 | /** 98 | * Commit a transaction queries 99 | */ 100 | FFI_PLUGIN_EXPORT const char *commitTransaction( 101 | struct QueryEngine *qe, 102 | const char *txIdStr, 103 | const char *headerStr 104 | ); 105 | 106 | /** 107 | * Rollback a transaction 108 | */ 109 | FFI_PLUGIN_EXPORT const char *rollbackTransaction( 110 | struct QueryEngine *qe, 111 | const char *txIdStr, 112 | const char *headerStr 113 | ); 114 | -------------------------------------------------------------------------------- /packages/orm_flutter_ios/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: orm_flutter_ios 2 | description: "Dynamic library implementation library for Prisma Dart and Flutter integration on iOS platform." 3 | homepage: https://prisma.pub 4 | 5 | resolution: workspace 6 | version: 0.0.4 7 | 8 | funding: 9 | - https://github.com/sponsors/medz 10 | - https://opencollective.com/openodroe 11 | 12 | environment: 13 | sdk: ^3.5.0 14 | flutter: ">=3.3.0" 15 | 16 | flutter: 17 | plugin: 18 | platforms: 19 | ios: 20 | ffiPlugin: true 21 | -------------------------------------------------------------------------------- /packages/query_engine_bridge/README.md: -------------------------------------------------------------------------------- 1 | # Prisma Query Engine Bridge 2 | 3 | This is a bridge for the Prisma C-ABI query engine static library written by C. 4 | 5 | > Why do we need it? 6 | There is a problem with loading static libraries with the Flutter plugin, and it is very likely that symbols cannot be found. Therefore, adding bridges to generate dynamic libraries can solve this problem. 7 | 8 | ## Prisma Issues deps Dart issues 9 | - [[prisma/prisma#24295] - C-ABI Engine Feature Request](https://github.com/prisma/prisma/issues/24295) 10 | 11 | ## Dart issues 12 | - [[dart-lang/native#934#issuecomment-1894151501] - Using dart:ffi with a xcframework containing static binaries (iOS)](https://github.com/dart-lang/native/issues/934) 13 | - [[dart-lang/sdk#49418] - Explore using FfiNative for static linking](https://github.com/dart-lang/sdk/issues/49418) 14 | 15 | ## When will it no longer be needed? 16 | 17 | When Dart solves any linking issues between static libraries and DFI. 18 | -------------------------------------------------------------------------------- /packages/query_engine_bridge/bridge.c: -------------------------------------------------------------------------------- 1 | #include "headers/bridge.h" 2 | 3 | /** 4 | * Create a new [QueryEngine] 5 | * 6 | * Returns a [Status] code. 7 | */ 8 | FFI_PLUGIN_EXPORT enum Status create( 9 | struct ConstructorOptions options, 10 | struct QueryEngine **qePtr, 11 | char **errorStringPtr) 12 | { 13 | return prisma_create(options, qePtr, errorStringPtr); 14 | } 15 | 16 | /** 17 | * Destroy a [QueryEngine] 18 | */ 19 | FFI_PLUGIN_EXPORT enum Status destroy(struct QueryEngine *qe) 20 | { 21 | return prisma_destroy(qe); 22 | } 23 | 24 | /** 25 | * Start a [QueryEngine] 26 | */ 27 | FFI_PLUGIN_EXPORT enum Status start( 28 | struct QueryEngine *qe, 29 | const char *trace, 30 | char **errorStringPtr) 31 | { 32 | return prisma_connect(qe, trace, errorStringPtr); 33 | } 34 | 35 | /** 36 | * Stop a [QueryEngine] 37 | */ 38 | FFI_PLUGIN_EXPORT enum Status stop( 39 | struct QueryEngine *qe, 40 | const char *headerStr) 41 | { 42 | return prisma_disconnect(qe, headerStr); 43 | } 44 | 45 | /** 46 | * Apply migrations 47 | */ 48 | FFI_PLUGIN_EXPORT enum Status applyMigrations( 49 | struct QueryEngine *qe, 50 | const char *migrationsPath, 51 | char **errorStringPtr) 52 | { 53 | return prisma_apply_pending_migrations(qe, migrationsPath, errorStringPtr); 54 | } 55 | 56 | /** 57 | * Query a prisma request 58 | */ 59 | FFI_PLUGIN_EXPORT const char *query( 60 | struct QueryEngine *qe, 61 | const char *bodyStr, 62 | const char *headerStr, 63 | const char *txIdStr, 64 | char **errorStringPtr) 65 | { 66 | return prisma_query(qe, bodyStr, headerStr, txIdStr, errorStringPtr); 67 | } 68 | 69 | /** 70 | * Start a transaction 71 | */ 72 | FFI_PLUGIN_EXPORT const char *startTransaction( 73 | struct QueryEngine *qe, 74 | const char *optionsStr, 75 | const char *headerStr) 76 | { 77 | return prisma_start_transaction(qe, optionsStr, headerStr); 78 | } 79 | 80 | /** 81 | * Commit a transaction querys 82 | */ 83 | FFI_PLUGIN_EXPORT const char *commitTransaction( 84 | struct QueryEngine *qe, 85 | const char *txIdStr, 86 | const char *headerStr) 87 | { 88 | return prisma_commit_transaction(qe, txIdStr, headerStr); 89 | } 90 | 91 | /** 92 | * Rollback a transaction 93 | */ 94 | FFI_PLUGIN_EXPORT const char *rollbackTransaction( 95 | struct QueryEngine *qe, 96 | const char *txIdStr, 97 | const char *headerStr) 98 | { 99 | return prisma_rollback_transaction(qe, txIdStr, headerStr); 100 | } 101 | -------------------------------------------------------------------------------- /packages/query_engine_bridge/headers/bridge.h: -------------------------------------------------------------------------------- 1 | #include "../include/query_engine.h" 2 | 3 | #if _WIN32 4 | #include 5 | #endif 6 | 7 | #if _WIN32 8 | #define FFI_PLUGIN_EXPORT __declspec(dllexport) 9 | #else 10 | #define FFI_PLUGIN_EXPORT 11 | #endif 12 | 13 | #ifndef QueryEngine 14 | typedef struct QueryEngine {} QueryEngine; 15 | #endif 16 | 17 | /** 18 | * function returns status code. 19 | * 20 | * see: 21 | * - [QueryEngineBindings.create] 22 | * - [QueryEngineBindings.destroy] 23 | * - [QueryEngineBindings.start] 24 | * - [QueryEngineBindings.stop] 25 | * - [QueryEngineBindings.applyMigrations] 26 | */ 27 | FFI_PLUGIN_EXPORT enum Status { 28 | /** Success */ 29 | ok = 0, 30 | /** Error */ 31 | err = 1, 32 | /** Missing pointer, only create returns. */ 33 | miss = 2 34 | }; 35 | 36 | /** 37 | * Create a new [QueryEngine] 38 | * Returns a [Status] code. 39 | */ 40 | FFI_PLUGIN_EXPORT enum Status create( 41 | struct ConstructorOptions options, 42 | struct QueryEngine **qePtr, 43 | char **errorStringPtr 44 | ); 45 | 46 | /** 47 | * Destroy a [QueryEngine] 48 | */ 49 | FFI_PLUGIN_EXPORT enum Status destroy(struct QueryEngine *qe); 50 | 51 | /** 52 | * Start a [QueryEngine] 53 | */ 54 | FFI_PLUGIN_EXPORT enum Status start( 55 | struct QueryEngine *qe, 56 | const char *trace, 57 | char **errorStringPtr 58 | ); 59 | 60 | /** 61 | * Stop a [QueryEngine] 62 | */ 63 | FFI_PLUGIN_EXPORT enum Status stop( 64 | struct QueryEngine *qe, 65 | const char *headerStr 66 | ); 67 | 68 | /** 69 | * Apply migrations 70 | */ 71 | FFI_PLUGIN_EXPORT enum Status applyMigrations( 72 | struct QueryEngine *qe, 73 | const char *migrationsPath, 74 | char **errorStringPtr 75 | ); 76 | 77 | /** 78 | * Query a prisma request 79 | */ 80 | FFI_PLUGIN_EXPORT const char *query( 81 | struct QueryEngine *qe, 82 | const char *bodyStr, 83 | const char *headerStr, 84 | const char *txIdStr, 85 | char **errorStringPtr 86 | ); 87 | 88 | /** 89 | * Start a transaction 90 | */ 91 | FFI_PLUGIN_EXPORT const char *startTransaction( 92 | struct QueryEngine *qe, 93 | const char *optionsStr, 94 | const char *headerStr 95 | ); 96 | 97 | /** 98 | * Commit a transaction queries 99 | */ 100 | FFI_PLUGIN_EXPORT const char *commitTransaction( 101 | struct QueryEngine *qe, 102 | const char *txIdStr, 103 | const char *headerStr 104 | ); 105 | 106 | /** 107 | * Rollback a transaction 108 | */ 109 | FFI_PLUGIN_EXPORT const char *rollbackTransaction( 110 | struct QueryEngine *qe, 111 | const char *txIdStr, 112 | const char *headerStr 113 | ); 114 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: _ 2 | publish_to: none 3 | 4 | environment: 5 | sdk: ^3.5.3 6 | 7 | workspace: 8 | - packages/orm 9 | - packages/orm_flutter 10 | - packages/orm_flutter_ffi 11 | - packages/orm_flutter_android 12 | - packages/orm_flutter_ios 13 | 14 | # Documentation example 15 | - docs-example 16 | 17 | # Examples 18 | - examples/with_sqlite 19 | - examples/with_postgres 20 | - examples/flutter_with_orm 21 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": ["config:recommended"] 4 | } 5 | -------------------------------------------------------------------------------- /template/example_stub.md: -------------------------------------------------------------------------------- 1 | See [https://github.com/medz/prisma-dart/tree/main/examples](https://github.com/medz/prisma-dart/tree/main/examples) 2 | --------------------------------------------------------------------------------