├── .all-contributorsrc ├── .dockerignore ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ ├── docs.yml │ ├── linux.yml │ ├── macos.yml │ ├── publish.yml │ └── windows.yml ├── .gitignore ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── assets ├── conduit-discord-transparent.png ├── conduit-discord.png ├── conduit-name-bg.svg ├── conduit-name.svg └── conduit-palette.svg ├── ci ├── .env ├── .gitignore ├── CHANGELOG.md ├── README.md ├── conduit.cert.pem ├── conduit.key.pem ├── docker-compose.yaml └── ssl │ ├── privkey.pem │ ├── server.crt │ ├── server.key │ └── server.req ├── docker ├── Dockerfile.beta ├── Dockerfile.flutter ├── Dockerfile.main └── Dockerfile.stable ├── docs ├── README.md ├── SUMMARY.md ├── application │ ├── README.md │ ├── channel.md │ ├── configure.md │ ├── structure.md │ └── threading.md ├── assets │ ├── 3437c10597c1526c3dbd98c737c2bcae.svg │ ├── authobjects.png │ ├── breakpoint_screenshot.png │ ├── content_type_components.png │ ├── debugger_screenshot.png │ ├── entrypoint (1).png │ ├── entrypoint (2).png │ ├── entrypoint.png │ ├── image (1).png │ ├── image (2) (1).png │ ├── image (2).png │ ├── image (3) (1).png │ ├── image (3).png │ ├── image (4).png │ ├── image.png │ ├── latency (1).png │ ├── latency.png │ ├── object_body_flow.png │ ├── paging.png │ ├── req_per_sec (1).png │ ├── req_per_sec.png │ ├── response_flow.png │ ├── run1 (1).png │ ├── run1 (2).png │ ├── run1.png │ ├── run2 (1).png │ ├── run2 (2).png │ ├── run2.png │ ├── run3 (1) (2).png │ ├── run3 (1) (3).png │ ├── run3 (1).png │ ├── run3.png │ ├── run4 (1).png │ ├── run4 (2).png │ ├── run4.png │ ├── simple_controller_diagram (1).png │ ├── simple_controller_diagram (2).png │ ├── simple_controller_diagram.png │ ├── structure (1).png │ ├── structure (2).png │ └── structure.png ├── auth │ ├── README.md │ ├── auth_scopes.md │ ├── authorizer.md │ ├── cli.md │ ├── controllers.md │ ├── server.md │ └── what_is_oauth.md ├── best_practices.md ├── cli │ ├── README.md │ ├── create.md │ ├── document.md │ └── running.md ├── core_concepts.md ├── core_concepts │ ├── README.md │ ├── best_practices.md │ └── tour.md ├── css │ ├── font-awesome.min.css │ ├── prism.css │ └── styles.css ├── db │ ├── README.md │ ├── advanced_queries.md │ ├── connecting.md │ ├── db_tools.md │ ├── executing_queries.md │ ├── json_columns.md │ ├── modeling_data.md │ ├── mysql.md │ ├── serialization.md │ ├── transactions.md │ └── validations.md ├── deploy │ ├── README.md │ ├── build.md │ ├── deploy_aws.md │ ├── deploy_docker.md │ ├── deploy_heroku.md │ ├── deploy_local.md │ └── script.md ├── files │ └── settings.jar ├── getting_started.md ├── http │ ├── README.md │ ├── controller.md │ ├── file_upload.md │ ├── request_and_response.md │ ├── resource_controller.md │ ├── routing.md │ ├── serving_files.md │ └── websockets.md ├── img │ ├── ChannelDiagram.png │ ├── authobjects.png │ ├── branching_controller.png │ ├── breakpoint_screenshot.png │ ├── callout_structure.png │ ├── conduit.png │ ├── content_type_components.png │ ├── debugger_screenshot.png │ ├── entrypoint.png │ ├── latency.png │ ├── object_body_flow.png │ ├── paging.png │ ├── req_per_sec.png │ ├── response_flow.png │ ├── run1.png │ ├── run2.png │ ├── run3.png │ ├── run4.png │ ├── simple_controller_diagram.png │ ├── structure.png │ ├── tut1.png │ └── tut3_db.png ├── migration │ ├── 4.1.8.md │ ├── 4.3.6.md │ └── README.md ├── openapi │ ├── README.md │ ├── cli.md │ ├── components.md │ ├── endpoint.md │ └── middleware.md ├── snippets │ ├── README.md │ ├── auth.md │ ├── http.md │ ├── orm.md │ └── test.md ├── testing │ ├── README.md │ ├── clients.md │ ├── debugger.md │ ├── mixins.md │ ├── mock.md │ └── tests.md ├── tour.md └── tut │ ├── README.md │ ├── deploying-and-other-fun-things.md │ ├── executing-queries.md │ ├── getting-started.md │ ├── oauth2.md │ ├── storing-data.md │ └── writing-tests.md ├── melos.yaml ├── mkdocs.yml ├── packages ├── cli │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── analysis_options.yaml │ ├── bin │ │ └── conduit.dart │ ├── dart_test.yaml │ ├── example │ │ └── main.dart │ ├── lib │ │ ├── conduit.dart │ │ └── src │ │ │ ├── command.dart │ │ │ ├── commands │ │ │ ├── auth.dart │ │ │ ├── auth_add_client.dart │ │ │ ├── auth_scope.dart │ │ │ ├── build.dart │ │ │ ├── create.dart │ │ │ ├── db.dart │ │ │ ├── db_generate.dart │ │ │ ├── db_schema.dart │ │ │ ├── db_show_migrations.dart │ │ │ ├── db_upgrade.dart │ │ │ ├── db_validate.dart │ │ │ ├── db_version.dart │ │ │ ├── document.dart │ │ │ ├── document_serve.dart │ │ │ ├── oai_client.dart │ │ │ ├── pub.dart │ │ │ ├── serve.dart │ │ │ └── setup.dart │ │ │ ├── metadata.dart │ │ │ ├── migration_source.dart │ │ │ ├── mixins │ │ │ ├── database_connecting.dart │ │ │ ├── database_managing.dart │ │ │ ├── openapi_options.dart │ │ │ └── project.dart │ │ │ ├── runner.dart │ │ │ ├── running_process.dart │ │ │ └── scripts │ │ │ ├── get_channel_type.dart │ │ │ ├── get_schema.dart │ │ │ ├── migration_builder.dart │ │ │ ├── openapi_builder.dart │ │ │ ├── run_upgrade.dart │ │ │ └── schema_builder.dart │ ├── mkdocs.yml │ ├── pubspec.yaml │ ├── pubspec_overrides.yaml │ ├── templates │ │ ├── db │ │ │ ├── .gitignore │ │ │ ├── README.md │ │ │ ├── analysis_options.yaml │ │ │ ├── bin │ │ │ │ └── main.dart │ │ │ ├── config.src.yaml │ │ │ ├── lib │ │ │ │ ├── channel.dart │ │ │ │ ├── controller │ │ │ │ │ └── simple_controller.dart │ │ │ │ ├── model │ │ │ │ │ └── model.dart │ │ │ │ └── wildfire.dart │ │ │ ├── pubspec.yaml │ │ │ ├── test │ │ │ │ ├── harness │ │ │ │ │ └── app.dart │ │ │ │ └── simple_controller_test.dart │ │ │ └── web │ │ │ │ └── login.html │ │ ├── db_and_auth │ │ │ ├── .gitignore │ │ │ ├── README.md │ │ │ ├── analysis_options.yaml │ │ │ ├── bin │ │ │ │ └── main.dart │ │ │ ├── config.src.yaml │ │ │ ├── lib │ │ │ │ ├── channel.dart │ │ │ │ ├── controller │ │ │ │ │ ├── identity_controller.dart │ │ │ │ │ ├── register_controller.dart │ │ │ │ │ └── user_controller.dart │ │ │ │ ├── model │ │ │ │ │ └── user.dart │ │ │ │ ├── utility │ │ │ │ │ └── html_template.dart │ │ │ │ └── wildfire.dart │ │ │ ├── pubspec.yaml │ │ │ ├── test │ │ │ │ ├── harness │ │ │ │ │ └── app.dart │ │ │ │ ├── identity_controller_test.dart │ │ │ │ ├── register_test.dart │ │ │ │ └── user_controller_test.dart │ │ │ └── web │ │ │ │ └── login.html │ │ └── default │ │ │ ├── .gitignore │ │ │ ├── README.md │ │ │ ├── analysis_options.yaml │ │ │ ├── bin │ │ │ └── main.dart │ │ │ ├── config.src.yaml │ │ │ ├── lib │ │ │ ├── channel.dart │ │ │ ├── controller │ │ │ │ └── simple_controller.dart │ │ │ └── wildfire.dart │ │ │ ├── pubspec.yaml │ │ │ └── test │ │ │ ├── example_test.dart │ │ │ └── harness │ │ │ └── app.dart │ └── test │ │ ├── auth_test.dart │ │ ├── build_test.dart │ │ ├── command_test.dart │ │ ├── create_test.dart │ │ ├── db_validate_test.dart │ │ ├── document_server_test.dart │ │ ├── document_test.dart │ │ ├── generate_test.dart │ │ ├── migration_execution_test.dart │ │ ├── migration_test.dart │ │ ├── not_tests │ │ ├── cli_helpers.dart │ │ └── postgres_test_config.dart │ │ ├── oai_client_test.dart │ │ ├── schema_test.dart │ │ └── serve_test.dart ├── codable │ ├── .gitignore │ ├── .travis.yml │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── analysis_options.yaml │ ├── lib │ │ ├── cast.dart │ │ ├── conduit_codable.dart │ │ └── src │ │ │ ├── codable.dart │ │ │ ├── coding.dart │ │ │ ├── keyed_archive.dart │ │ │ ├── list.dart │ │ │ └── resolver.dart │ ├── mkdocs.yml │ ├── pubspec.yaml │ └── test │ │ ├── decode_test.dart │ │ └── encode_test.dart ├── common │ ├── .gitignore │ ├── CHANGELOG.md │ ├── CONTRIBUTING.md │ ├── LICENSE │ ├── README.md │ ├── analysis_options.yaml │ ├── lib │ │ ├── conduit_common.dart │ │ └── src │ │ │ └── openapi │ │ │ └── documentable.dart │ ├── pubspec.yaml │ └── pubspec_overrides.yaml ├── config │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── analysis_options.yaml │ ├── lib │ │ ├── conduit_config.dart │ │ └── src │ │ │ ├── compiler.dart │ │ │ ├── configuration.dart │ │ │ ├── default_configurations.dart │ │ │ ├── intermediate_exception.dart │ │ │ ├── mirror_property.dart │ │ │ └── runtime.dart │ ├── mkdocs.yml │ ├── pubspec.yaml │ ├── pubspec_overrides.yaml │ └── test │ │ ├── config_test.dart │ │ ├── nested_test.dart │ │ └── no_default_constructor_test.dart ├── core │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── analysis_options.yaml │ ├── dart_test.yaml │ ├── lib │ │ ├── conduit_core.dart │ │ ├── managed_auth.dart │ │ └── src │ │ │ ├── application │ │ │ ├── application.dart │ │ │ ├── application_server.dart │ │ │ ├── channel.dart │ │ │ ├── isolate_application_server.dart │ │ │ ├── isolate_supervisor.dart │ │ │ ├── options.dart │ │ │ └── starter.dart │ │ │ ├── auth │ │ │ ├── auth.dart │ │ │ ├── auth_code_controller.dart │ │ │ ├── auth_controller.dart │ │ │ ├── auth_redirect_controller.dart │ │ │ ├── authorization_parser.dart │ │ │ ├── authorization_server.dart │ │ │ ├── authorizer.dart │ │ │ ├── exceptions.dart │ │ │ ├── objects.dart │ │ │ ├── protocols.dart │ │ │ └── validator.dart │ │ │ ├── db │ │ │ ├── db.dart │ │ │ ├── managed │ │ │ │ ├── attributes.dart │ │ │ │ ├── backing.dart │ │ │ │ ├── context.dart │ │ │ │ ├── data_model.dart │ │ │ │ ├── data_model_manager.dart │ │ │ │ ├── document.dart │ │ │ │ ├── entity.dart │ │ │ │ ├── exception.dart │ │ │ │ ├── key_path.dart │ │ │ │ ├── managed.dart │ │ │ │ ├── object.dart │ │ │ │ ├── property_description.dart │ │ │ │ ├── relationship_type.dart │ │ │ │ ├── set.dart │ │ │ │ ├── type.dart │ │ │ │ └── validation │ │ │ │ │ ├── impl.dart │ │ │ │ │ ├── managed.dart │ │ │ │ │ └── metadata.dart │ │ │ ├── persistent_store │ │ │ │ └── persistent_store.dart │ │ │ ├── query │ │ │ │ ├── error.dart │ │ │ │ ├── matcher_expression.dart │ │ │ │ ├── mixin.dart │ │ │ │ ├── page.dart │ │ │ │ ├── predicate.dart │ │ │ │ ├── query.dart │ │ │ │ ├── reduce.dart │ │ │ │ ├── sort_descriptor.dart │ │ │ │ └── sort_predicate.dart │ │ │ └── schema │ │ │ │ ├── migration.dart │ │ │ │ ├── schema.dart │ │ │ │ ├── schema_builder.dart │ │ │ │ ├── schema_column.dart │ │ │ │ └── schema_table.dart │ │ │ ├── http │ │ │ ├── body_decoder.dart │ │ │ ├── cache_policy.dart │ │ │ ├── controller.dart │ │ │ ├── cors_policy.dart │ │ │ ├── file_controller.dart │ │ │ ├── handler_exception.dart │ │ │ ├── http.dart │ │ │ ├── http_codec_repository.dart │ │ │ ├── managed_object_controller.dart │ │ │ ├── query_controller.dart │ │ │ ├── request.dart │ │ │ ├── request_body.dart │ │ │ ├── request_path.dart │ │ │ ├── resource_controller.dart │ │ │ ├── resource_controller_bindings.dart │ │ │ ├── resource_controller_interfaces.dart │ │ │ ├── resource_controller_scope.dart │ │ │ ├── response.dart │ │ │ ├── route_node.dart │ │ │ ├── route_specification.dart │ │ │ ├── router.dart │ │ │ └── serializable.dart │ │ │ ├── runtime │ │ │ ├── compiler.dart │ │ │ ├── impl.dart │ │ │ ├── orm │ │ │ │ ├── data_model_compiler.dart │ │ │ │ ├── entity_builder.dart │ │ │ │ ├── entity_mirrors.dart │ │ │ │ ├── property_builder.dart │ │ │ │ └── validator_builder.dart │ │ │ ├── orm_impl.dart │ │ │ ├── resource_controller │ │ │ │ ├── documenter.dart │ │ │ │ └── utility.dart │ │ │ ├── resource_controller_generator.dart │ │ │ └── resource_controller_impl.dart │ │ │ └── utilities │ │ │ ├── mirror_helpers.dart │ │ │ └── sourcify.dart │ ├── mkdocs.yml │ ├── pubspec.yaml │ ├── pubspec_overrides.yaml │ ├── test │ │ ├── auth │ │ │ ├── auth_controller_test.dart │ │ │ ├── auth_documentation_test.dart │ │ │ ├── auth_redirect_controller_test.dart │ │ │ ├── auth_scope_test.dart │ │ │ ├── auth_utility_test.dart │ │ │ ├── authenticate_test.dart │ │ │ └── authorizer_test.dart │ │ ├── db │ │ │ ├── compilation_errors │ │ │ │ ├── model_autoinc_and_default_test.dart │ │ │ │ ├── model_conflicting_null_rule_test.dart │ │ │ │ ├── model_conflicting_relate_annotation_test.dart │ │ │ │ ├── model_dupe_inverse_test.dart │ │ │ │ ├── model_has_no_constructor_test.dart │ │ │ │ ├── model_missing_inverse_test.dart │ │ │ │ ├── model_multi_request_empty_test.dart │ │ │ │ ├── model_multi_unique_has_one_test.dart │ │ │ │ ├── model_multi_unique_single_test.dart │ │ │ │ ├── model_multi_unique_unknown_test.dart │ │ │ │ ├── model_no_pk_test.dart │ │ │ │ ├── model_relationship_is_not_column_test.dart │ │ │ │ ├── model_required_args_test.dart │ │ │ │ ├── model_tables_same_name_test.dart │ │ │ │ ├── model_unsupported_transient_test.dart │ │ │ │ ├── model_unsupported_type_test.dart │ │ │ │ ├── model_wrong_inverse_test.dart │ │ │ │ ├── validate_date_time_parse_test.dart │ │ │ │ ├── validate_length_type_test.dart │ │ │ │ ├── validate_matches_type_test.dart │ │ │ │ ├── validate_one_of_wrong_type_test.dart │ │ │ │ ├── validate_oneof_empty_test.dart │ │ │ │ ├── validate_oneof_heterogenuous_test.dart │ │ │ │ ├── validate_unsupported_one_of_date_test.dart │ │ │ │ └── validate_unsupported_one_of_double_test.dart │ │ │ ├── context_test.dart │ │ │ ├── data_model_manager_test.dart │ │ │ ├── data_model_test.dart │ │ │ ├── data_model_type_search_test.dart │ │ │ ├── deferred_model_subclass_test.dart │ │ │ ├── entity_mirrors_test.dart │ │ │ ├── migration │ │ │ │ └── generate_code_test.dart │ │ │ ├── model_controller_test.dart │ │ │ ├── model_test.dart │ │ │ ├── predicate_test.dart │ │ │ ├── query_exception_test.dart │ │ │ ├── query_test.dart │ │ │ ├── schema_builder_test.dart │ │ │ ├── schema_invalid_difference_test.dart │ │ │ ├── schema_test.dart │ │ │ ├── tracking_test.dart │ │ │ └── validate_value_test.dart │ │ ├── http │ │ │ ├── application_test.dart │ │ │ ├── binding_type_test.dart │ │ │ ├── body_decoder_test.dart │ │ │ ├── body_encoder_streaming_test.dart │ │ │ ├── body_encoder_test.dart │ │ │ ├── cache_policy_test.dart │ │ │ ├── compilation_errors │ │ │ │ ├── controller_mutable_property_test.dart │ │ │ │ ├── controller_mutable_setter_test.dart │ │ │ │ ├── resource_controller_ambiguous_operation_test.dart │ │ │ │ ├── resource_controller_bind_dynamic_test.dart │ │ │ │ ├── resource_controller_bind_list_path_test.dart │ │ │ │ ├── resource_controller_bind_unparseable_test.dart │ │ │ │ ├── resource_controller_filter_nonserializable_test.dart │ │ │ │ └── resource_controller_unbound_path_test.dart │ │ │ ├── content_negotiation_test.dart │ │ │ ├── controller_error_test.dart │ │ │ ├── controller_test.dart │ │ │ ├── cors_test.dart │ │ │ ├── default_resource_controller_test.dart │ │ │ ├── file_controller_test.dart │ │ │ ├── isolate │ │ │ │ ├── isolate_application_test.dart │ │ │ │ ├── isolate_failure_test.dart │ │ │ │ ├── message_hub_test.dart │ │ │ │ └── recovery_test.dart │ │ │ ├── moc_openapi_test.dart │ │ │ ├── pattern_test.dart │ │ │ ├── recycling_test.dart │ │ │ ├── resource_controller_body_binding_test.dart │ │ │ ├── resource_controller_scope_test.dart │ │ │ ├── resource_controller_test.dart │ │ │ ├── response_test.dart │ │ │ ├── router_test.dart │ │ │ ├── serializable_test.dart │ │ │ ├── sink_test.dart │ │ │ ├── ssl_test.dart │ │ │ ├── subclass_managed_object_controller_test.dart │ │ │ └── websocket_test.dart │ │ ├── managed_auth │ │ │ ├── managed_auth_role_storage_test.dart │ │ │ └── managed_auth_storage_test.dart │ │ ├── not_tests │ │ │ ├── helpers.dart │ │ │ └── postgres_test_config.dart │ │ └── openapi │ │ │ ├── document_auth_test.dart │ │ │ ├── document_test.dart │ │ │ ├── managed_test.dart │ │ │ ├── resource_controller_document_test.dart │ │ │ ├── resource_controller_scope_test.dart │ │ │ └── serializable_test.dart │ └── tool │ │ └── generated_test_runner.dart ├── fs_test_agent │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── analysis_options.yaml │ ├── lib │ │ ├── dart_project_agent.dart │ │ └── working_directory_agent.dart │ ├── pubspec.yaml │ └── test │ │ └── project_agent_test.dart ├── isolate_exec │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── analysis_options.yaml │ ├── lib │ │ ├── conduit_isolate_exec.dart │ │ └── src │ │ │ ├── executable.dart │ │ │ ├── executor.dart │ │ │ └── source_generator.dart │ ├── mkdocs.yml │ ├── pubspec.yaml │ └── test │ │ └── isolate_executor_test.dart ├── isolate_exec_test_packages │ └── test_package │ │ ├── README.md │ │ ├── lib │ │ ├── lib.dart │ │ └── src │ │ │ └── src.dart │ │ └── pubspec.yaml ├── open_api │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── analysis_options.yaml │ ├── lib │ │ ├── src │ │ │ ├── object.dart │ │ │ ├── util │ │ │ │ ├── list_helper.dart │ │ │ │ └── map_helper.dart │ │ │ ├── v2 │ │ │ │ ├── document.dart │ │ │ │ ├── header.dart │ │ │ │ ├── metadata.dart │ │ │ │ ├── operation.dart │ │ │ │ ├── parameter.dart │ │ │ │ ├── path.dart │ │ │ │ ├── property.dart │ │ │ │ ├── response.dart │ │ │ │ ├── schema.dart │ │ │ │ ├── security.dart │ │ │ │ └── types.dart │ │ │ └── v3 │ │ │ │ ├── callback.dart │ │ │ │ ├── components.dart │ │ │ │ ├── document.dart │ │ │ │ ├── encoding.dart │ │ │ │ ├── header.dart │ │ │ │ ├── media_type.dart │ │ │ │ ├── metadata.dart │ │ │ │ ├── operation.dart │ │ │ │ ├── parameter.dart │ │ │ │ ├── path.dart │ │ │ │ ├── request_body.dart │ │ │ │ ├── response.dart │ │ │ │ ├── schema.dart │ │ │ │ ├── security.dart │ │ │ │ ├── server.dart │ │ │ │ └── types.dart │ │ ├── v2.dart │ │ └── v3.dart │ ├── mkdocs.yml │ ├── pubspec.yaml │ ├── pubspec_overrides.yaml │ └── test │ │ ├── v2_test.dart │ │ └── v3_test.dart ├── password_hash │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── analysis_options.yaml │ ├── lib │ │ ├── conduit_password_hash.dart │ │ ├── pbkdf2.dart │ │ └── salt.dart │ ├── mkdocs.yml │ ├── pubspec.yaml │ └── test │ │ └── pbkdf2_test.dart ├── postgresql │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── analysis_options.yaml │ ├── lib │ │ ├── conduit_postgresql.dart │ │ └── src │ │ │ ├── builders │ │ │ ├── column.dart │ │ │ ├── expression.dart │ │ │ ├── sort.dart │ │ │ ├── table.dart │ │ │ └── value.dart │ │ │ ├── postgresql_persistent_store.dart │ │ │ ├── postgresql_query.dart │ │ │ ├── postgresql_query_reduce.dart │ │ │ ├── postgresql_schema_generator.dart │ │ │ ├── query_builder.dart │ │ │ └── row_instantiator.dart │ ├── pubspec.yaml │ ├── pubspec_overrides.yaml │ └── test │ │ ├── adapter_test.dart │ │ ├── aggregate_function_test.dart │ │ ├── belongs_to_fetch_test.dart │ │ ├── cyclic_relationship_test.dart │ │ ├── delete_test.dart │ │ ├── document_test.dart │ │ ├── fetch_test.dart │ │ ├── has_many_fetch_test.dart │ │ ├── has_one_fetch_test.dart │ │ ├── insert_test.dart │ │ ├── many_to_many_fetch_test.dart │ │ ├── matcher_test.dart │ │ ├── migration │ │ ├── migration_test.dart │ │ ├── schema_generator_sql_mapping_test.dart │ │ └── store_migration_test.dart │ │ ├── not_tests │ │ ├── helpers.dart │ │ ├── model_graph.dart │ │ └── postgres_test_config.dart │ │ ├── paging_test.dart │ │ ├── reduce_with_joins.dart │ │ ├── tiered_where_test.dart │ │ ├── transaction_test.dart │ │ ├── typing_test.dart │ │ ├── update_test.dart │ │ └── validation_test.dart ├── runtime │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── analysis_options.yaml │ ├── bin │ │ └── create.dart │ ├── dart_test.yaml │ ├── lib │ │ ├── runtime.dart │ │ ├── slow_coerce.dart │ │ └── src │ │ │ ├── analyzer.dart │ │ │ ├── build.dart │ │ │ ├── build_context.dart │ │ │ ├── build_manager.dart │ │ │ ├── compiler.dart │ │ │ ├── context.dart │ │ │ ├── exceptions.dart │ │ │ ├── generator.dart │ │ │ ├── mirror_coerce.dart │ │ │ └── mirror_context.dart │ ├── mkdocs.yml │ ├── pubspec.yaml │ ├── pubspec_overrides.yaml │ └── test │ │ ├── .pubignore │ │ ├── build_test.dart │ │ ├── coerce_test.dart │ │ ├── context_test.dart │ │ └── project_analyzer_test.dart ├── runtime_test_packages │ ├── application │ │ ├── analysis_options.yaml │ │ ├── bin │ │ │ └── main.dart │ │ ├── lib │ │ │ ├── application.dart │ │ │ └── src │ │ │ │ └── file.dart │ │ ├── pubspec.yaml │ │ └── pubspec_overrides.yaml │ └── dependency │ │ ├── analysis_options.yaml │ │ ├── lib │ │ ├── dependency.dart │ │ └── src │ │ │ ├── compiler.dart │ │ │ └── dependency_base.dart │ │ ├── pubspec.yaml │ │ └── pubspec_overrides.yaml └── test_harness │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── analysis_options.yaml │ ├── dart_test.yaml │ ├── example │ └── main.dart │ ├── lib │ ├── conduit_test.dart │ └── src │ │ ├── agent.dart │ │ ├── auth_harness.dart │ │ ├── body_matcher.dart │ │ ├── db_harness.dart │ │ ├── harness.dart │ │ ├── header_matcher.dart │ │ ├── http_value_wrapper.dart │ │ ├── matchers.dart │ │ ├── mock_server.dart │ │ ├── partial_matcher.dart │ │ ├── request.dart │ │ ├── response.dart │ │ └── response_matcher.dart │ ├── mkdocs.yml │ ├── pubspec.yaml │ ├── pubspec_overrides.yaml │ └── test │ ├── agent_test.dart │ ├── auth_harness_test.dart │ ├── db_harness_test.dart │ ├── harness_test.dart │ ├── mock_server_test.dart │ ├── not_tests │ └── postgres_test_config.dart │ ├── request_test.dart │ ├── response_test.dart │ └── test_matcher_test.dart ├── pubspec.yaml └── utils ├── pubspec.yaml └── unused_port.dart /.dockerignore: -------------------------------------------------------------------------------- 1 | .dockerignore 2 | docker/ 3 | build/ 4 | .dart_tool/ 5 | .git/ 6 | .github/ 7 | .gitignore 8 | .packages -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [j4qfrost] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: conduit-dart 6 | ko_fi: j4qfrost 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG]" 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | Provide source code if possible. 20 | 21 | **Expected behavior** 22 | A clear and concise description of what you expected to happen. 23 | 24 | **Screenshots** 25 | If applicable, add screenshots to help explain your problem. 26 | 27 | **System Information:** 28 | - OS: [e.g. iOS] 29 | - Dart Version: 30 | - Conduit Version: 31 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "[Feature]" 5 | labels: enhancement 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 | -------------------------------------------------------------------------------- /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: Docs 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - master 7 | types: [closed] 8 | workflow_dispatch: 9 | branches: 10 | - master 11 | 12 | concurrency: 13 | group: "documentation" 14 | cancel-in-progress: true 15 | 16 | jobs: 17 | docs: 18 | if: | 19 | github.event_name == 'workflow_dispatch' 20 | || (github.event.pull_request.merged && startsWith(github.head_ref, 'docs/')) 21 | runs-on: ubuntu-latest 22 | steps: 23 | - uses: actions/checkout@v4 24 | - uses: dart-lang/setup-dart@v1 25 | with: 26 | sdk: stable 27 | - name: Print ref name 28 | run: echo ${{github.ref_name}} 29 | - name: Install melos 30 | run: dart pub global activate melos 31 | - name: Generate docs 32 | run: melos bootstrap && melos gen-docs && echo "mkdocs-monorepo-plugin==1.0.4" > requirements.txt 33 | - name: Deploy docs 34 | uses: mhausenblas/mkdocs-deploy-gh-pages@master 35 | env: 36 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 37 | CUSTOM_DOMAIN: docs.theconduit.dev 38 | CONFIG_FILE: mkdocs.yml 39 | EXTRA_PACKAGES: build-base 40 | REQUIREMENTS: requirements.txt 41 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Don’t commit the following directories created by pub. 2 | .buildlog 3 | .pub/ 4 | build/ 5 | .packages 6 | .dart_tool/ 7 | 8 | # Or the files created by dart2js. 9 | *.dart.js 10 | *.js_ 11 | *.js.deps 12 | *.js.map 13 | 14 | # Include when developing application packages. 15 | pubspec.lock 16 | 17 | workspace.xml 18 | Dart_Packages.xml 19 | .DS_Store 20 | .idea 21 | *.iml 22 | release.yaml 23 | tmp/ 24 | conduit/foobar 25 | conduit/migrations 26 | **/.history 27 | **/*.dart.vm.json 28 | stackoverflow 29 | **/.failed_tracker 30 | migration_tmp 31 | coverage 32 | application_test/ 33 | 34 | doc/ 35 | site/ 36 | _build/ 37 | 38 | *.reflectable.dart -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021, conduit-dart and contributors 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 8 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 9 | 10 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 11 | -------------------------------------------------------------------------------- /assets/conduit-discord-transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/assets/conduit-discord-transparent.png -------------------------------------------------------------------------------- /assets/conduit-discord.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/assets/conduit-discord.png -------------------------------------------------------------------------------- /ci/.env: -------------------------------------------------------------------------------- 1 | export POSTGRES_HOST='localhost' 2 | export POSTGRES_PORT='15432' 3 | export POSTGRES_USER='conduit_test_user' 4 | export POSTGRES_PASSWORD='conduit!' 5 | export POSTGRES_DB='conduit_test_db' 6 | export TEST_DB_ENV_VAR='postgres://user:password@host:5432/dbname' 7 | export TEST_VALUE=1 8 | export TEST_BOOL=true -------------------------------------------------------------------------------- /ci/.gitignore: -------------------------------------------------------------------------------- 1 | # Files and directories created by pub. 2 | .dart_tool/ 3 | .packages 4 | 5 | # Conventional directory for build output. 6 | build/ 7 | .failed_tracker 8 | -------------------------------------------------------------------------------- /ci/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.0.0 2 | 3 | - Initial version. 4 | -------------------------------------------------------------------------------- /ci/README.md: -------------------------------------------------------------------------------- 1 | A simple command-line application. 2 | -------------------------------------------------------------------------------- /ci/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | postgres: 3 | image: postgres:16.6 4 | # command: -c ssl=on -c ssl_cert_file=/var/lib/postgresql/server.crt -c ssl_key_file=/var/lib/postgresql/server.key 5 | container_name: conduit_postgres 6 | restart: always 7 | environment: 8 | POSTGRES_USER: conduit_test_user 9 | POSTGRES_PASSWORD: conduit! 10 | POSTGRES_DB: conduit_test_db 11 | POSTGRES_PORT: 15432 12 | ports: 13 | - 0.0.0.0:15432:5432 14 | volumes: 15 | - ./ssl/server.crt:/var/lib/postgresql/server.crt:ro 16 | - ./ssl/server.key:/var/lib/postgresql/server.key:ro 17 | -------------------------------------------------------------------------------- /docker/Dockerfile.beta: -------------------------------------------------------------------------------- 1 | FROM dart:beta 2 | 3 | COPY ci/ ci/ 4 | COPY packages/ packages/ 5 | COPY melos.yaml melos.yaml 6 | COPY pubspec.yaml pubspec.yaml 7 | RUN dart pub global activate -spath packages/cli 8 | RUN dart pub global activate melos 9 | ENV PUB_CACHE=/root/.pub-cache 10 | ENV PATH=$PATH:$PUB_CACHE/bin 11 | RUN melos cache-source --no-select 12 | RUN dart --disable-analytics 13 | -------------------------------------------------------------------------------- /docker/Dockerfile.flutter: -------------------------------------------------------------------------------- 1 | FROM ghcr.io/cirruslabs/flutter:latest 2 | 3 | RUN chown -R 1000:1000 /sdks/flutter 4 | RUN mkdir /conduit 5 | COPY ci/ /conduit/ci/ 6 | COPY packages/ /conduit/packages/ 7 | COPY melos.yaml /conduit/melos.yaml 8 | COPY pubspec.yaml /conduit/pubspec.yaml 9 | RUN chown -R 1000:1000 /conduit 10 | 11 | USER 1000 12 | 13 | WORKDIR /conduit 14 | 15 | ENV PUB_CACHE=/conduit/.pub-cache 16 | ENV PATH=$PATH:$PUB_CACHE/bin 17 | RUN dart pub global activate -spath packages/cli 18 | RUN dart pub global activate melos 19 | RUN melos cache-source --no-select 20 | RUN dart --disable-analytics -------------------------------------------------------------------------------- /docker/Dockerfile.main: -------------------------------------------------------------------------------- 1 | FROM dart:latest 2 | 3 | COPY ci/ ci/ 4 | COPY packages/ packages/ 5 | COPY melos.yaml melos.yaml 6 | COPY pubspec.yaml pubspec.yaml 7 | RUN dart pub global activate -spath packages/cli 8 | RUN dart pub global activate melos 9 | ENV PUB_CACHE=/root/.pub-cache 10 | ENV PATH=$PATH:$PUB_CACHE/bin 11 | RUN melos cache-source --no-select 12 | RUN dart --disable-analytics 13 | -------------------------------------------------------------------------------- /docker/Dockerfile.stable: -------------------------------------------------------------------------------- 1 | FROM dart:stable 2 | 3 | COPY ci/ ci/ 4 | COPY packages/ packages/ 5 | COPY melos.yaml melos.yaml 6 | COPY pubspec.yaml pubspec.yaml 7 | RUN dart pub global activate -spath packages/cli 8 | RUN dart pub global activate melos 9 | ENV PUB_CACHE=/root/.pub-cache 10 | ENV PATH=$PATH:$PUB_CACHE/bin 11 | RUN melos cache-source --no-select 12 | RUN dart --disable-analytics 13 | -------------------------------------------------------------------------------- /docs/application/README.md: -------------------------------------------------------------------------------- 1 | # Application 2 | 3 | A Conduit application starts an HTTP server and invokes your code for each request. The code that is invoked might depend on the request's path, method, and other attributes. For example, the request `GET /heroes` will invoke different code than `POST /authors`. You configure which code is invoked in an `ApplicationChannel` subclass; every application declares exactly one `ApplicationChannel` subclass. 4 | 5 | This subclass also sets up services, reads configuration data from files and environment variables and performs any other initialization for your application. For example, an application channel often reads database connection information from environment variables and then sets up a connection to that database. 6 | 7 | Conduit applications create multiple threads, and each thread takes turn handling incoming requests. Your application channel subclass is created for each thread, creating replica instances of your application. 8 | 9 | ## Guides 10 | 11 | * [Starting and Stopping Applications](channel.md) 12 | * [Configuring an Application and its Environment](configure.md) 13 | * [Application and Project Structure](structure.md) 14 | * [Performance: Multi-threading](threading.md) 15 | 16 | -------------------------------------------------------------------------------- /docs/assets/authobjects.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/authobjects.png -------------------------------------------------------------------------------- /docs/assets/breakpoint_screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/breakpoint_screenshot.png -------------------------------------------------------------------------------- /docs/assets/content_type_components.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/content_type_components.png -------------------------------------------------------------------------------- /docs/assets/debugger_screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/debugger_screenshot.png -------------------------------------------------------------------------------- /docs/assets/entrypoint (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/entrypoint (1).png -------------------------------------------------------------------------------- /docs/assets/entrypoint (2).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/entrypoint (2).png -------------------------------------------------------------------------------- /docs/assets/entrypoint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/entrypoint.png -------------------------------------------------------------------------------- /docs/assets/image (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/image (1).png -------------------------------------------------------------------------------- /docs/assets/image (2) (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/image (2) (1).png -------------------------------------------------------------------------------- /docs/assets/image (2).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/image (2).png -------------------------------------------------------------------------------- /docs/assets/image (3) (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/image (3) (1).png -------------------------------------------------------------------------------- /docs/assets/image (3).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/image (3).png -------------------------------------------------------------------------------- /docs/assets/image (4).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/image (4).png -------------------------------------------------------------------------------- /docs/assets/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/image.png -------------------------------------------------------------------------------- /docs/assets/latency (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/latency (1).png -------------------------------------------------------------------------------- /docs/assets/latency.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/latency.png -------------------------------------------------------------------------------- /docs/assets/object_body_flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/object_body_flow.png -------------------------------------------------------------------------------- /docs/assets/paging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/paging.png -------------------------------------------------------------------------------- /docs/assets/req_per_sec (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/req_per_sec (1).png -------------------------------------------------------------------------------- /docs/assets/req_per_sec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/req_per_sec.png -------------------------------------------------------------------------------- /docs/assets/response_flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/response_flow.png -------------------------------------------------------------------------------- /docs/assets/run1 (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/run1 (1).png -------------------------------------------------------------------------------- /docs/assets/run1 (2).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/run1 (2).png -------------------------------------------------------------------------------- /docs/assets/run1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/run1.png -------------------------------------------------------------------------------- /docs/assets/run2 (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/run2 (1).png -------------------------------------------------------------------------------- /docs/assets/run2 (2).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/run2 (2).png -------------------------------------------------------------------------------- /docs/assets/run2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/run2.png -------------------------------------------------------------------------------- /docs/assets/run3 (1) (2).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/run3 (1) (2).png -------------------------------------------------------------------------------- /docs/assets/run3 (1) (3).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/run3 (1) (3).png -------------------------------------------------------------------------------- /docs/assets/run3 (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/run3 (1).png -------------------------------------------------------------------------------- /docs/assets/run3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/run3.png -------------------------------------------------------------------------------- /docs/assets/run4 (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/run4 (1).png -------------------------------------------------------------------------------- /docs/assets/run4 (2).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/run4 (2).png -------------------------------------------------------------------------------- /docs/assets/run4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/run4.png -------------------------------------------------------------------------------- /docs/assets/simple_controller_diagram (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/simple_controller_diagram (1).png -------------------------------------------------------------------------------- /docs/assets/simple_controller_diagram (2).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/simple_controller_diagram (2).png -------------------------------------------------------------------------------- /docs/assets/simple_controller_diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/simple_controller_diagram.png -------------------------------------------------------------------------------- /docs/assets/structure (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/structure (1).png -------------------------------------------------------------------------------- /docs/assets/structure (2).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/structure (2).png -------------------------------------------------------------------------------- /docs/assets/structure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/assets/structure.png -------------------------------------------------------------------------------- /docs/auth/README.md: -------------------------------------------------------------------------------- 1 | # Authentication 2 | 3 | Conduit has types to manage authentication and authorization according to the [OAuth 2.0 specification](https://tools.ietf.org/html/rfc6749). 4 | 5 | You create an `AuthServer` service object for your application that manages authentication and authorization logic. An `AuthServer` requires a helper object that implements `AuthServerDelegate` to handle configuration and required data storage. Most often, this object is a `ManagedAuthDelegate` that uses the Conduit ORM to manage this storage. 6 | 7 | An `AuthServer` service object is injected into `Authorizer` controllers that protect access to controller channels. An `AuthServer` is also injected into `AuthCodeController` and `AuthController` to provide HTTP APIs for authentication. 8 | 9 | The `conduit auth` command-line tool manages configuration - such as client identifier management - for live applications. 10 | 11 | ![Authorization Objects](../assets/authobjects.png) 12 | 13 | ## Guides 14 | 15 | * [What is OAuth 2.0?]() 16 | * [Creating and Using AuthServers](server.md) 17 | * [Securing Routes with Authorizer](authorizer.md) 18 | * [Adding Authentication Endpoints](controllers.md) 19 | * [Using Scopes to Control Access](auth_scopes.md) 20 | * [Managing OAuth 2.0 Clients](cli.md) 21 | 22 | -------------------------------------------------------------------------------- /docs/cli/README.md: -------------------------------------------------------------------------------- 1 | # CLI 2 | 3 | The Conduit command-line utility creates projects, runs applications, manages database schemas and other tasks. 4 | 5 | This tool is installed through `pub`: 6 | 7 | ```text 8 | pub global activate conduit 9 | ``` 10 | 11 | The above command updates the tool if a new version is available. You should ensure that `conduit` and your application use the same version of Conduit. 12 | 13 | All command-line tools have a `--help` option to show their options. 14 | 15 | ## Guides 16 | 17 | * [Creating Applications](create.md) 18 | * [Running Applications](running.md) 19 | * [Managing a Database](../db/db_tools.md) 20 | * [Managing OAuth 2.0 Clients and Scopes](../auth/cli.md) 21 | * [Documenting an API](document.md) 22 | 23 | -------------------------------------------------------------------------------- /docs/cli/create.md: -------------------------------------------------------------------------------- 1 | # Creating Conduit Applications 2 | 3 | The `conduit create` command-line tool creates applications from a template. The usage is: 4 | 5 | ```text 6 | conduit create app_name 7 | ``` 8 | 9 | The application name must be snake_case - all lower case, no spaces, no symbols other than \`_\`. 10 | 11 | By default, a generated project is fairly empty - it has the minimal content, but the structure of a complete application. For applications that use Conduit's ORM or OAuth 2.0 behavior, extended templates exist. These can be listed with the following: 12 | 13 | ```text 14 | conduit create list-templates 15 | ``` 16 | 17 | To pick a template, add the `-t` option to `conduit create`. For example, the following uses the `db` template: 18 | 19 | ```text 20 | conduit create -t db app_name 21 | ``` 22 | 23 | The templates are located in the Conduit package under `examples/templates`. When creating a new project from a template, the tool copies the contents of one of the template directories into your current working directory and substitutes some names with your project name. 24 | 25 | -------------------------------------------------------------------------------- /docs/cli/document.md: -------------------------------------------------------------------------------- 1 | # Documenting Conduit Applications 2 | 3 | The `conduit document` tool generates an OpenAPI \(formerly Swagger\) specification by reflecting on your application's code. This command is run in a project directory and will emit the JSON specification to stdout. You can redirect this to a file: 4 | 5 | ```text 6 | conduit document > swagger.json 7 | ``` 8 | 9 | The file `config.src.yaml` must exist in your project directory so that the application can be initialized in 'test' mode for the documentation to be generated. 10 | 11 | -------------------------------------------------------------------------------- /docs/db/mysql.md: -------------------------------------------------------------------------------- 1 | # MySql 2 | 3 | Note: this is not as yet a released feature. 4 | 5 | 1. example: 6 | 7 | ```text 8 | aqueduct db upgrade --connect mysql://username:password@host:port/databaseName 9 | ``` 10 | 11 | or setting `database.yaml`: 12 | 13 | ```yaml 14 | schema: postgres|mysql 15 | host: host 16 | port: port 17 | username: username 18 | password: password 19 | databaseName: databaseName 20 | ``` 21 | 22 | 1. `MySqlPersistentStore`: 23 | 24 | ```dart 25 | final MySqlPersistentStore persistentStore = MySqlPersistentStore( 26 | _config.database.username, 27 | _config.database.password, 28 | _config.database.host, 29 | _config.database.port, 30 | _config.database.databaseName); 31 | 32 | context = ManagedContext(dataModel, persistentStore); 33 | 34 | /// ...... 35 | final query = Query(context,values: user) 36 | ..where((o) => o.username).equalTo(user.username); 37 | 38 | final res = await query.delete(); 39 | /// ...... 40 | ``` 41 | 42 | 1. Support setting field size 43 | 44 | ```dart 45 | class _User extends ResourceOwnerTableDefinition { 46 | @Column(size: 11) 47 | String mobile; 48 | 49 | @override 50 | @Column(unique: true, indexed: true, size: 20) 51 | String username; 52 | } 53 | ``` 54 | 55 | -------------------------------------------------------------------------------- /docs/deploy/README.md: -------------------------------------------------------------------------------- 1 | # Deploying Conduit 2 | 3 | Conduit has a built in CLI tool, `conduit`, for deploying Conduit applications, managing database schemas, OAuth 2.0 clients and creating projects. See [Getting Started](https://github.com/noojee/conduit/tree/3f4c01be85b7ff135772166173524e76a5f80c32/conduit/doc/source/source/docs/deploy/getting_started.html) for installation instructions. Many of the tasks for deployment rely on using this tool. Conduit has a built in tool, `conduit`, for deploying Conduit applications, managing database schemas, OAuth 2.0 clients and creating projects. See [Getting Started](https://github.com/noojee/conduit/tree/3f4c01be85b7ff135772166173524e76a5f80c32/conduit/doc/source/source/docs/deploy/getting_started.html) for installation instructions. Many of the tasks for deployment rely on using this tool. 4 | 5 | Conduit applications can be run anywhere that Dart can be installed. This topic covers deployment tasks on common hosting services. If you are just getting started or a hobbyist, you should consider using [Heroku](http://heroku.com) to host your applications. 6 | 7 | ## Guides 8 | 9 | * [Running a Conduit Application Locally](deploy_local.md) 10 | * [Running a Conduit Application with Docker, Docker Compose and Kubernetes](deploy_docker.md) 11 | * [Running a Conduit Application without conduit serve](script.md) 12 | 13 | -------------------------------------------------------------------------------- /docs/deploy/script.md: -------------------------------------------------------------------------------- 1 | # Script 2 | 3 | You may also run Conduit applications with a standalone script, instead of `conduit serve`. In fact, `conduit serve` creates a temporary Dart script to run the application. If you created your application with `conduit create`, a standalone already exists in your project named `bin/main.dart`. 4 | 5 | A sample script looks like this: 6 | 7 | ```dart 8 | import 'dart:async'; 9 | import 'dart:io'; 10 | 11 | import 'package:conduit_core/conduit_core.dart'; 12 | import 'package:my_application/my_application.dart'; 13 | 14 | Future main() async { 15 | var app = new Application() 16 | ..options.port = 8888 17 | ..options.configurationFilePath = "config.yaml"; 18 | 19 | await app.start(numberOfInstances: 3); 20 | } 21 | ``` 22 | 23 | This script can be used in place of `conduit serve`, but you must configure all `ApplicationOptions` in this script and not through the CLI. 24 | 25 | -------------------------------------------------------------------------------- /docs/files/settings.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/files/settings.jar -------------------------------------------------------------------------------- /docs/img/ChannelDiagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/img/ChannelDiagram.png -------------------------------------------------------------------------------- /docs/img/authobjects.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/img/authobjects.png -------------------------------------------------------------------------------- /docs/img/branching_controller.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/img/branching_controller.png -------------------------------------------------------------------------------- /docs/img/breakpoint_screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/img/breakpoint_screenshot.png -------------------------------------------------------------------------------- /docs/img/callout_structure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/img/callout_structure.png -------------------------------------------------------------------------------- /docs/img/conduit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/img/conduit.png -------------------------------------------------------------------------------- /docs/img/content_type_components.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/img/content_type_components.png -------------------------------------------------------------------------------- /docs/img/debugger_screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/img/debugger_screenshot.png -------------------------------------------------------------------------------- /docs/img/entrypoint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/img/entrypoint.png -------------------------------------------------------------------------------- /docs/img/latency.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/img/latency.png -------------------------------------------------------------------------------- /docs/img/object_body_flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/img/object_body_flow.png -------------------------------------------------------------------------------- /docs/img/paging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/img/paging.png -------------------------------------------------------------------------------- /docs/img/req_per_sec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/img/req_per_sec.png -------------------------------------------------------------------------------- /docs/img/response_flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/img/response_flow.png -------------------------------------------------------------------------------- /docs/img/run1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/img/run1.png -------------------------------------------------------------------------------- /docs/img/run2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/img/run2.png -------------------------------------------------------------------------------- /docs/img/run3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/img/run3.png -------------------------------------------------------------------------------- /docs/img/run4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/img/run4.png -------------------------------------------------------------------------------- /docs/img/simple_controller_diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/img/simple_controller_diagram.png -------------------------------------------------------------------------------- /docs/img/structure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/img/structure.png -------------------------------------------------------------------------------- /docs/img/tut1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/img/tut1.png -------------------------------------------------------------------------------- /docs/img/tut3_db.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/docs/img/tut3_db.png -------------------------------------------------------------------------------- /docs/migration/4.1.8.md: -------------------------------------------------------------------------------- 1 | Small step-by-step guide, conduit version 4.1.8 2 | -------------------------------------------------------- 3 | 1. Ensure your dart version is >=2.18.6 4 | 5 | 2. Activate latest conduit version 6 | ```dart pub global activate conduit``` 7 | 8 | 3. Update your pubspec.yaml: 9 | ```yaml 10 | dependencies: 11 | conduit: ^4.1.8 12 | dev_dependencies: 13 | conduit_test: ^4.1.8 14 | ``` 15 | 4. Update dependencies 16 | ```dart pub update``` 17 | 18 | 5. Replace all import 'package:conduit/managed_auth.dart'; in your project 19 | ```import 'package:conduit/managed_auth.dart'; -> import 'package:conduit_core/managed_auth.dart';``` 20 | 21 | 6. Replace all import 'package:conduit/conduit.dart'; in your project 22 | ```import 'package:conduit/conduit.dart'; -> import 'package:conduit_core/conduit_core.dart';``` 23 | 24 | 7. Replace all context.persistentStore! in your project 25 | ```context.persistentStore! -> context.persistentStore``` 26 | 27 | 8. Replace all AuthUtility.generateRandomSalt() in your project 28 | ```AuthUtility.generateRandomSalt() -> generateRandomSalt()``` -------------------------------------------------------------------------------- /docs/migration/4.3.6.md: -------------------------------------------------------------------------------- 1 | Small step-by-step guide, conduit version 4.3.6 2 | -------------------------------------------------------- 3 | 1. Ensure your dart version is >=2.19.0 4 | 5 | 2. Activate latest conduit version 6 | ```dart pub global activate conduit``` 7 | 8 | 3. Update your pubspec.yaml: 9 | ```yaml 10 | dependencies: 11 | conduit: ^4.3.6 12 | conduit_postgresql: ^4.3.6 # This has been separated from the core library. 13 | dev_dependencies: 14 | conduit_test: ^4.3.6 15 | ``` 16 | 4. Update dependencies 17 | ```dart pub update``` 18 | 19 | 5.Add import 'package:conduit_postgresql/conduit_postgresql.dart'; in your project where it appears necessary 20 | ```import 'package:conduit_postgresql/conduit_postgresql.dart'; -> import 'package:conduit_postgresql/conduit_postgresql.dart';``` 21 | -------------------------------------------------------------------------------- /docs/migration/README.md: -------------------------------------------------------------------------------- 1 | # Migration Notes 2 | 3 | * [4.1.8.md] 4 | * [4.3.6.md] 5 | -------------------------------------------------------------------------------- /docs/openapi/README.md: -------------------------------------------------------------------------------- 1 | # OpenAPI 2 | 3 | Conduit applications auto-generate an OpenAPI 3.0 document. 4 | 5 | Most of your OpenAPI document is generated by reflecting on your application code, especially `ResourceController` subclasses. You add customization or additional information by overriding methods in `APIComponentDocumenter` and `APIOperationDocumenter`. At minimum, you override methods in your `ResourceController` to document the responses your application will send for a particular endpoint. 6 | 7 | You create documents with the `conduit document` command-line tool. 8 | 9 | ## Guides 10 | 11 | * [Creating an OpenAPI Document](cli.md) 12 | * [Documenting Components](components.md) 13 | * [Documenting Endpoint Controllers](endpoint.md) 14 | * [Documenting Middleware Controllers](middleware.md) 15 | 16 | -------------------------------------------------------------------------------- /docs/openapi/middleware.md: -------------------------------------------------------------------------------- 1 | # Documenting Middleware Controllers 2 | 3 | In this document, you'll learn how to document middleware controllers. 4 | 5 | ## Adding to an Operation 6 | 7 | For the purposes of documentation, a middleware controller does not create operation request and responses. Rather, it modifies the operation details provided by its endpoint controller. When writing middleware controllers, you must override `documentOperations` and call the superclass' implementation. This allows the middleware's linked controller to document its operations, which will eventually reach an endpoint controller. 8 | 9 | Once the endpoint controller returns the meat of the operation document, a middleware controller can modify it. For example, a middleware that requires a query parameter named 'key' would like like so: 10 | 11 | ```dart 12 | class Middleware extends Controller { 13 | ... 14 | 15 | @override 16 | Map documentOperations(APIDocumentContext context, String route, APIPath path) { 17 | final ops = super.documentOperations(context, route, path); 18 | 19 | // ops has been filled out by an endpoint controller, 20 | // add 'key' query parameter to each operation. 21 | ops.forEach((method, op) { 22 | op.addParameter(APIParameter.query("key", schema: APISchemaObject.string())); 23 | }); 24 | 25 | return ops; 26 | } 27 | } 28 | ``` 29 | 30 | Each string key in an operations map is the lowercase name of an HTTP method, e.g. 'get' or 'post'. An `APIOperation` encapsulates its request parameters and responses. 31 | 32 | -------------------------------------------------------------------------------- /docs/snippets/README.md: -------------------------------------------------------------------------------- 1 | # Conduit Snippets 2 | 3 | These snippets are quick examples of common code that you can use and modify in your application. 4 | 5 | * [HTTP Routing, Request and Response Snippets](http.md) 6 | * [ORM and Database Snippets](orm.md) 7 | * [Authorization and Authentication Snippets](auth.md) 8 | 9 | -------------------------------------------------------------------------------- /docs/snippets/test.md: -------------------------------------------------------------------------------- 1 | # Conduit Test Snippets 2 | 3 | ## Expect that Response Returns a JSON Object with an ID 4 | 5 | ```dart 6 | test("that Response Returns a JSON Object", () async { 7 | expectResponse( 8 | await app.client.request("/endpoint").get(), 9 | 200, body: { 10 | "id": isNumber 11 | } 12 | ); 13 | }); 14 | ``` 15 | 16 | ## Expect that Response Returns a List of JSON Objects with IDs 17 | 18 | ```dart 19 | test("that Response returns a list of JSON Objects with IDs", () async { 20 | expectResponse( 21 | await app.client.request("/endpoint").get(), 22 | 200, body: everyElement({ 23 | "id": isNumber 24 | }) 25 | ); 26 | }); 27 | ``` 28 | 29 | ## Expect that Last-Modified Header Is After Date 30 | 31 | ```dart 32 | test("that Last-Modified Header Is After Date ", () async { 33 | expect( 34 | await app.client.request("/endpoint").get(), 35 | hasHeaders({ 36 | "last-modified": isAfter(new DateTime(2017)) 37 | }); 38 | }); 39 | ``` 40 | 41 | ## HTTP POST with JSON in Test 42 | 43 | ```dart 44 | test("that can send JSON body", () async { 45 | var request = app.client.request("/endpoint") 46 | ..json = { 47 | "id": 1 48 | }; 49 | expect(await request.post(), hasStatus(202)); 50 | }); 51 | ``` 52 | 53 | -------------------------------------------------------------------------------- /docs/testing/README.md: -------------------------------------------------------------------------------- 1 | # Testing 2 | 3 | Conduit applications can be run, tested, debugged and profiled. 4 | 5 | You create a subclass of `TestHarness` in your application's `test/` directory. For each test suite, you install this harness to start and stop your application in 'test' mode. A test harness runs your application like a live application. 6 | 7 | You use `Agent` objects to send HTTP requests to your application under test. Agents add default information to all of their requests, like authorization information. You use test matchers like `hasResponse` or `hasStatus` to validate the response your application sends for a given request. 8 | 9 | You provide mock services for external services that your application communicates with. These are often driven by the contents of a configuration file. \(By convention, a configuration file for tests is named `config.src.yaml`.\) You may also create mock services with `MockHTTPServer` to use during testing. 10 | 11 | ## Guides 12 | 13 | * [Writing Tests with a Test Harness](tests.md) 14 | * [Testing with the ORM and OAuth 2.0](mixins.md) 15 | * [Developing Client Applications](clients.md) 16 | * [Using the Debugger and Profiling](debugger.md) 17 | * [Use Mock Services](mock.md) 18 | 19 | -------------------------------------------------------------------------------- /docs/tut/README.md: -------------------------------------------------------------------------------- 1 | # Tutorial 2 | 3 | -------------------------------------------------------------------------------- /packages/cli/.gitignore: -------------------------------------------------------------------------------- 1 | .failed_tracker 2 | -------------------------------------------------------------------------------- /packages/cli/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018, Stable Kernel LLC 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 8 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 9 | 10 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 11 | -------------------------------------------------------------------------------- /packages/cli/README.md: -------------------------------------------------------------------------------- 1 | ../../README.md -------------------------------------------------------------------------------- /packages/cli/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:lints/recommended.yaml 2 | 3 | analyzer: 4 | exclude: 5 | - tmp/** 6 | - templates/** -------------------------------------------------------------------------------- /packages/cli/bin/conduit.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:io'; 3 | 4 | import 'package:conduit/src/runner.dart'; 5 | 6 | Future main(List args) async { 7 | final runner = Runner(); 8 | final values = runner.options.parse(args); 9 | exitCode = await runner.process(values); 10 | } 11 | -------------------------------------------------------------------------------- /packages/cli/dart_test.yaml: -------------------------------------------------------------------------------- 1 | timeout: 120s 2 | concurrency: 1 -------------------------------------------------------------------------------- /packages/cli/lib/src/commands/auth.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:conduit/src/command.dart'; 4 | import 'package:conduit/src/commands/auth_add_client.dart'; 5 | import 'package:conduit/src/commands/auth_scope.dart'; 6 | 7 | class CLIAuth extends CLICommand { 8 | CLIAuth() { 9 | registerCommand(CLIAuthAddClient()); 10 | registerCommand(CLIAuthScopeClient()); 11 | } 12 | 13 | @override 14 | Future handle() async { 15 | printHelp(parentCommandName: "conduit"); 16 | return 0; 17 | } 18 | 19 | @override 20 | Future cleanup() async {} 21 | 22 | @override 23 | String get name { 24 | return "auth"; 25 | } 26 | 27 | @override 28 | String get description { 29 | return "A tool for adding OAuth 2.0 clients to a database using the managed_auth package."; 30 | } 31 | 32 | @override 33 | String get detailedDescription { 34 | return "Some commands require connecting to a database to perform their action. These commands will " 35 | "have options for --connect and --database-config in their usage instructions. " 36 | "You may either use a connection string (--connect) or a database configuration (--database-config) to provide " 37 | "connection details. The format of a connection string is: \n\n" 38 | "\tpostgres://username:password@host:port/databaseName\n\n" 39 | "A database configuration file is a YAML file with the following format:\n\n" 40 | '\tusername: "user"\n' 41 | '\tpassword: "password"\n' 42 | '\thost: "host"\n' 43 | "\tport: port\n" 44 | '\tdatabaseName: "database"'; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/cli/lib/src/commands/db_schema.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:convert'; 3 | 4 | import 'package:conduit/src/command.dart'; 5 | import 'package:conduit/src/mixins/database_managing.dart'; 6 | import 'package:conduit/src/mixins/project.dart'; 7 | import 'package:conduit/src/scripts/get_schema.dart'; 8 | 9 | class CLIDatabaseSchema extends CLICommand 10 | with CLIDatabaseManagingCommand, CLIProject { 11 | @override 12 | Future handle() async { 13 | final map = (await getProjectSchema(this)).asMap(); 14 | if (isMachineOutput) { 15 | outputSink.write(json.encode(map)); 16 | } else { 17 | const encoder = JsonEncoder.withIndent(" "); 18 | outputSink.write(encoder.convert(map)); 19 | } 20 | return 0; 21 | } 22 | 23 | @override 24 | String get name { 25 | return "schema"; 26 | } 27 | 28 | @override 29 | String get description { 30 | return "Emits the data model of a project as JSON to stdout."; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/cli/lib/src/commands/db_show_migrations.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: avoid_print 2 | 3 | import 'dart:async'; 4 | 5 | import 'package:conduit/src/command.dart'; 6 | import 'package:conduit/src/mixins/database_connecting.dart'; 7 | import 'package:conduit/src/mixins/database_managing.dart'; 8 | import 'package:conduit/src/mixins/project.dart'; 9 | 10 | class CLIDatabaseShowMigrations extends CLICommand 11 | with CLIDatabaseManagingCommand, CLIProject, CLIDatabaseConnectingCommand { 12 | @override 13 | Future handle() async { 14 | final files = projectMigrations.map((mig) { 15 | final versionString = "${mig.versionNumber}".padLeft(8, "0"); 16 | return " $versionString | ${Uri.parse(mig.uri!).pathSegments.last}"; 17 | }).join("\n"); 18 | 19 | print(" Version | Path"); 20 | print("----------|-----------"); 21 | print(files); 22 | 23 | return 0; 24 | } 25 | 26 | @override 27 | String get name { 28 | return "list"; 29 | } 30 | 31 | @override 32 | String get description { 33 | return "Show the path and version all migration files for this project."; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /packages/cli/lib/src/commands/db_validate.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:conduit/src/command.dart'; 4 | import 'package:conduit/src/mixins/database_managing.dart'; 5 | import 'package:conduit/src/mixins/project.dart'; 6 | import 'package:conduit/src/scripts/get_schema.dart'; 7 | 8 | class CLIDatabaseValidate extends CLICommand 9 | with CLIDatabaseManagingCommand, CLIProject { 10 | @override 11 | Future handle() async { 12 | final migrations = projectMigrations; 13 | if (migrations.isEmpty) { 14 | displayError("No migration files found in ${migrationDirectory!.path}."); 15 | return 1; 16 | } 17 | 18 | final currentSchema = await getProjectSchema(this); 19 | final schemaFromMigrationFiles = 20 | await schemaByApplyingMigrationSources(migrations); 21 | 22 | final differences = currentSchema.differenceFrom(schemaFromMigrationFiles); 23 | 24 | if (differences.hasDifferences) { 25 | displayError("Validation failed"); 26 | differences.errorMessages.forEach(displayProgress); 27 | 28 | return 1; 29 | } 30 | 31 | displayInfo("Validation OK", color: CLIColor.boldGreen); 32 | displayProgress("Latest version is ${migrations.last.versionNumber}."); 33 | 34 | return 0; 35 | } 36 | 37 | @override 38 | String get name { 39 | return "validate"; 40 | } 41 | 42 | @override 43 | String get description { 44 | return "Compares the schema created by the sum of migration files to the current codebase's schema."; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/cli/lib/src/runner.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:conduit/src/command.dart'; 4 | import 'package:conduit/src/commands/auth.dart'; 5 | import 'package:conduit/src/commands/build.dart'; 6 | import 'package:conduit/src/commands/create.dart'; 7 | import 'package:conduit/src/commands/db.dart'; 8 | import 'package:conduit/src/commands/document.dart'; 9 | import 'package:conduit/src/commands/serve.dart'; 10 | import 'package:conduit/src/commands/setup.dart'; 11 | 12 | class Runner extends CLICommand { 13 | Runner() { 14 | registerCommand(CLITemplateCreator()); 15 | registerCommand(CLIDatabase()); 16 | registerCommand(CLIServer()); 17 | registerCommand(CLISetup()); 18 | registerCommand(CLIAuth()); 19 | registerCommand(CLIDocument()); 20 | registerCommand(CLIBuild()); 21 | } 22 | 23 | @override 24 | Future handle() async { 25 | printHelp(); 26 | return 0; 27 | } 28 | 29 | @override 30 | String get name { 31 | return "conduit"; 32 | } 33 | 34 | @override 35 | String get description { 36 | return "Conduit is a tool for managing Conduit applications."; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/cli/lib/src/running_process.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:io'; 3 | 4 | class StoppableProcess { 5 | StoppableProcess(Future Function(String reason) onStop) : _stop = onStop { 6 | final l1 = ProcessSignal.sigint.watch().listen((_) { 7 | stop(0, reason: "Process interrupted."); 8 | }); 9 | _listeners.add(l1); 10 | 11 | if (!Platform.isWindows) { 12 | final l2 = ProcessSignal.sigterm.watch().listen((_) { 13 | stop(0, reason: "Process terminated by OS."); 14 | }); 15 | _listeners.add(l2); 16 | } 17 | } 18 | 19 | Future get exitCode => _completer.future; 20 | 21 | final List _listeners = []; 22 | 23 | final Future Function(String) _stop; 24 | final Completer _completer = Completer(); 25 | 26 | Future stop(int exitCode, {String? reason}) async { 27 | if (_completer.isCompleted) { 28 | return; 29 | } 30 | 31 | await Future.forEach(_listeners, (StreamSubscription sub) => sub.cancel()); 32 | await _stop(reason ?? "Terminated normally."); 33 | _completer.complete(exitCode); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /packages/cli/lib/src/scripts/get_channel_type.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:mirrors'; 3 | 4 | import 'package:conduit_core/conduit_core.dart'; 5 | import 'package:conduit_isolate_exec/conduit_isolate_exec.dart'; 6 | import 'package:conduit_runtime/runtime.dart'; 7 | 8 | class GetChannelExecutable extends Executable { 9 | GetChannelExecutable(super.message); 10 | 11 | @override 12 | Future execute() async { 13 | final channels = 14 | RuntimeContext.current.runtimes.iterable.whereType(); 15 | if (channels.length != 1) { 16 | throw StateError( 17 | "No ApplicationChannel subclass was found for this project. " 18 | "Make sure it is imported in your application library file."); 19 | } 20 | final runtime = channels.first; 21 | 22 | return MirrorSystem.getName(reflectClass(runtime.channelType).simpleName); 23 | } 24 | 25 | static List importsForPackage(String? packageName) => [ 26 | "package:conduit_core/conduit_core.dart", 27 | "package:$packageName/$packageName.dart", 28 | "package:conduit_runtime/runtime.dart" 29 | ]; 30 | } 31 | -------------------------------------------------------------------------------- /packages/cli/lib/src/scripts/get_schema.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:conduit/src/command.dart'; 4 | import 'package:conduit/src/mixins/project.dart'; 5 | import 'package:conduit_core/conduit_core.dart'; 6 | import 'package:conduit_isolate_exec/conduit_isolate_exec.dart'; 7 | 8 | class GetSchemaExecutable extends Executable> { 9 | GetSchemaExecutable(super.message); 10 | 11 | @override 12 | Future> execute() async { 13 | try { 14 | final dataModel = ManagedDataModel.fromCurrentMirrorSystem(); 15 | final schema = Schema.fromDataModel(dataModel); 16 | return schema.asMap(); 17 | } on SchemaException catch (e) { 18 | return {"error": e.message}; 19 | } on ManagedDataModelError catch (e) { 20 | return {"error": e.message}; 21 | } 22 | } 23 | 24 | static List importsForPackage(String? packageName) => [ 25 | "package:conduit_core/conduit_core.dart", 26 | "package:$packageName/$packageName.dart", 27 | "package:conduit_runtime/runtime.dart" 28 | ]; 29 | } 30 | 31 | Future getProjectSchema(CLIProject project) async { 32 | final response = await IsolateExecutor.run( 33 | GetSchemaExecutable({}), 34 | imports: GetSchemaExecutable.importsForPackage(project.libraryName), 35 | packageConfigURI: project.packageConfigUri, 36 | logHandler: project.displayProgress, 37 | ); 38 | 39 | if (response.containsKey("error")) { 40 | throw CLIException(response["error"] as String?); 41 | } 42 | 43 | return Schema.fromMap(response); 44 | } 45 | -------------------------------------------------------------------------------- /packages/cli/mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: conduit 2 | docs_dir: doc/api 3 | 4 | nav: 5 | - Docs: "index.html" -------------------------------------------------------------------------------- /packages/cli/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: conduit 2 | description: A modern HTTP server application framework, ORM and OAuth2 provider with OpenAPI 3.0 integration. Foundation for REST, RPC or GraphQL services. 3 | version: 5.1.5 4 | home: https://www.theconduit.dev 5 | repository: https://github.com/conduit-dart/conduit 6 | issue_tracker: https://github.com/conduit-dart/conduit/issues 7 | 8 | environment: 9 | sdk: ">=3.7.0 <4.0.0" 10 | 11 | dependencies: 12 | analyzer: ^7.1.0 13 | args: ^2.4.2 14 | collection: ^1.18.0 15 | conduit_common: ^5.1.5 16 | conduit_config: ^5.1.5 17 | conduit_core: ^5.1.5 18 | conduit_isolate_exec: ^5.1.5 19 | conduit_open_api: ^5.1.5 20 | conduit_password_hash: ^5.1.5 21 | conduit_postgresql: ^5.1.5 22 | conduit_runtime: ^5.1.5 23 | crypto: ^3.0.3 24 | io: ^1.0.4 25 | logging: ^1.2.0 26 | meta: ^1.12.0 27 | path: ^1.9.0 28 | postgres: ^3.1.1 29 | pub_semver: ^2.1.4 30 | yaml: ^3.1.2 31 | 32 | dev_dependencies: 33 | conduit_test: 34 | path: ../test_harness 35 | fs_test_agent: 36 | path: ../fs_test_agent 37 | http: ^1.2.1 38 | lints: ^5.1.1 39 | matcher: ^0.12.16+1 40 | mockito: ^5.4.4 41 | test: ^1.25.2 42 | web_socket_channel: ^3.0.0 43 | 44 | executables: 45 | conduit: conduit 46 | -------------------------------------------------------------------------------- /packages/cli/pubspec_overrides.yaml: -------------------------------------------------------------------------------- 1 | # melos_managed_dependency_overrides: fs_test_agent 2 | dependency_overrides: 3 | conduit_codable: 4 | path: ../codable 5 | conduit_common: 6 | path: ../common 7 | conduit_config: 8 | path: ../config 9 | conduit_core: 10 | path: ../core 11 | conduit_isolate_exec: 12 | path: ../isolate_exec 13 | conduit_open_api: 14 | path: ../open_api 15 | conduit_password_hash: 16 | path: ../password_hash 17 | conduit_postgresql: 18 | path: ../postgresql 19 | conduit_runtime: 20 | path: ../runtime 21 | conduit_test: 22 | path: ../test_harness 23 | fs_test_agent: 24 | path: ../fs_test_agent 25 | -------------------------------------------------------------------------------- /packages/cli/templates/db/.gitignore: -------------------------------------------------------------------------------- 1 | .buildlog 2 | .pub/ 3 | build/ 4 | packages 5 | .packages 6 | *.dart.js 7 | *.js_ 8 | *.js.deps 9 | *.js.map 10 | workspace.xml 11 | Dart_Packages.xml 12 | .DS_Store 13 | .idea/ 14 | .dart_tool/ 15 | *.conduit.pid -------------------------------------------------------------------------------- /packages/cli/templates/db/README.md: -------------------------------------------------------------------------------- 1 | # wildfire 2 | 3 | ## Running the Application Locally 4 | 5 | Run `conduit serve` from this directory to run the application. For running within an IDE, run `bin/main.dart`. By default, a configuration file named `config.yaml` will be used. 6 | 7 | You must have a `config.yaml` file that has correct database connection info, which should point to a local database. To configure a database to match your application's schema, run the following commands: 8 | 9 | ``` 10 | # if this is a project, run db generate first 11 | conduit db generate 12 | conduit db upgrade --connect postgres://user:password@localhost:5432/app_name 13 | ``` 14 | 15 | To generate a SwaggerUI client, run `conduit document client`. 16 | 17 | ## Running Application Tests 18 | 19 | Tests are run with a local PostgreSQL database named `conduit_test_db`. If this database does not exist, create it from your SQL prompt: 20 | 21 | CREATE DATABASE conduit_test_db; 22 | CREATE USER conduit_test_user WITH createdb; 23 | ALTER USER conduit_test_user WITH password 'conduit!'; 24 | GRANT all ON DATABASE conduit_test_db TO conduit_test_user; 25 | 26 | 27 | To run all tests for this application, run the following in this directory: 28 | 29 | ``` 30 | pub run test 31 | ``` 32 | 33 | The default configuration file used when testing is `config.src.yaml`. This file should be checked into version control. It also the template for configuration files used in deployment. 34 | 35 | ## Deploying an Application 36 | 37 | See the documentation for [Deployment](https://www.theconduit.dev/docs/deploy/). -------------------------------------------------------------------------------- /packages/cli/templates/db/bin/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:wildfire/wildfire.dart'; 2 | 3 | Future main(List args) async { 4 | final values = ApplicationOptions.parser.parse(args); 5 | if (values["help"] == true) { 6 | print(ApplicationOptions.parser.usage); 7 | return 0; 8 | } 9 | 10 | final app = Application(); 11 | app.options = ApplicationOptions() 12 | ..port = int.parse(values['port'] as String) 13 | ..address = values['address'] 14 | ..isIpv6Only = values['ipv6-only'] == true 15 | ..configurationFilePath = values['config-path'] as String? 16 | ..certificateFilePath = values['ssl-certificate-path'] as String? 17 | ..privateKeyFilePath = values['ssl-key-path'] as String?; 18 | final isolateCountString = values['isolates']; 19 | if (isolateCountString == null) { 20 | await app.startOnCurrentIsolate(); 21 | } else { 22 | await app.start(numberOfInstances: int.parse(isolateCountString as String)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/cli/templates/db/config.src.yaml: -------------------------------------------------------------------------------- 1 | database: 2 | username: conduit_test_user 3 | password: conduit! 4 | host: localhost 5 | port: 15432 # change this value 6 | databaseName: conduit_test_db 7 | -------------------------------------------------------------------------------- /packages/cli/templates/db/lib/controller/simple_controller.dart: -------------------------------------------------------------------------------- 1 | import 'package:wildfire/wildfire.dart'; 2 | 3 | class SimpleController extends Controller { 4 | SimpleController(this.context); 5 | 6 | final ManagedContext context; 7 | 8 | @override 9 | Future handle(Request request) async { 10 | return Response.ok({"key": "value"}); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/cli/templates/db/lib/model/model.dart: -------------------------------------------------------------------------------- 1 | import 'package:wildfire/wildfire.dart'; 2 | 3 | class Model extends ManagedObject<_Model> implements _Model { 4 | @override 5 | void willInsert() { 6 | createdAt = DateTime.now().toUtc(); 7 | } 8 | } 9 | 10 | class _Model { 11 | @primaryKey 12 | int? id; 13 | 14 | @Column(indexed: true) 15 | String? name; 16 | 17 | DateTime? createdAt; 18 | } 19 | -------------------------------------------------------------------------------- /packages/cli/templates/db/lib/wildfire.dart: -------------------------------------------------------------------------------- 1 | /// wildfire 2 | /// 3 | /// A conduit web server. 4 | library wildfire; 5 | 6 | export 'dart:async'; 7 | export 'dart:io'; 8 | 9 | export 'package:conduit_core/conduit_core.dart'; 10 | export 'package:conduit_postgresql/conduit_postgresql.dart'; 11 | 12 | export 'channel.dart'; 13 | -------------------------------------------------------------------------------- /packages/cli/templates/db/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: wildfire 2 | description: An conduit application with a database connection and data model. 3 | version: 0.0.1 4 | homepage: https://github.com/conduit-dart/conduit-codable 5 | publish_to: none 6 | 7 | environment: 8 | sdk: ">=3.7.0 <4.0.0" 9 | 10 | dependencies: 11 | conduit: ^5.1.0 12 | conduit_core: ^5.1.0 13 | conduit_postgresql: ^5.1.0 14 | 15 | dev_dependencies: 16 | test: ^1.25.2 17 | conduit_test: ^5.1.0 18 | -------------------------------------------------------------------------------- /packages/cli/templates/db/test/harness/app.dart: -------------------------------------------------------------------------------- 1 | import 'package:wildfire/wildfire.dart'; 2 | import 'package:conduit_test/conduit_test.dart'; 3 | 4 | export 'package:wildfire/wildfire.dart'; 5 | export 'package:conduit_test/conduit_test.dart'; 6 | export 'package:test/test.dart'; 7 | export 'package:conduit_core/conduit_core.dart'; 8 | 9 | /// A testing harness for wildfire. 10 | /// 11 | /// A harness for testing an conduit application. Example test file: 12 | /// 13 | /// void main() { 14 | /// Harness harness = Harness()..install(); 15 | /// 16 | /// test("GET /path returns 200", () async { 17 | /// final response = await harness.agent.get("/path"); 18 | /// expectResponse(response, 200); 19 | /// }); 20 | /// } 21 | /// 22 | class Harness extends TestHarness with TestHarnessORMMixin { 23 | @override 24 | ManagedContext? get context => channel?.context; 25 | 26 | @override 27 | Future onSetUp() async { 28 | await resetData(); 29 | } 30 | 31 | @override 32 | Future onTearDown() async {} 33 | 34 | @override 35 | Future seed() async { 36 | // restore any static data. called by resetData. 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/cli/templates/db/test/simple_controller_test.dart: -------------------------------------------------------------------------------- 1 | import 'harness/app.dart'; 2 | 3 | Future main() async { 4 | final harness = Harness()..install(); 5 | 6 | tearDown(() async { 7 | await harness.resetData(); 8 | }); 9 | 10 | test("POST /model", () async { 11 | final response = await harness.agent!.post("/model", body: {"name": "Bob"}); 12 | expect( 13 | response, 14 | hasResponse(200, 15 | body: {"id": isNotNull, "name": "Bob", "createdAt": isTimestamp})); 16 | }); 17 | 18 | test("GET /model/:id returns previously created object", () async { 19 | var response = await harness.agent!.post("/model", body: {"name": "Bob"}); 20 | 21 | final createdObject = response?.body.as(); 22 | response = 23 | await harness.agent!.request("/model/${createdObject["id"]}").get(); 24 | expect( 25 | response, 26 | hasResponse(200, body: { 27 | "id": createdObject["id"], 28 | "name": createdObject["name"], 29 | "createdAt": createdObject["createdAt"] 30 | })); 31 | }); 32 | } 33 | -------------------------------------------------------------------------------- /packages/cli/templates/db/web/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Login 7 | 8 | 9 | 10 |
11 |

Login

12 |
13 | 14 | 15 | 16 |
17 | 18 | 19 |
20 |
21 | 22 | 23 |
24 | 25 |
26 |
27 | 28 | 29 | -------------------------------------------------------------------------------- /packages/cli/templates/db_and_auth/.gitignore: -------------------------------------------------------------------------------- 1 | .buildlog 2 | .pub/ 3 | build/ 4 | packages 5 | .packages 6 | *.dart.js 7 | *.js_ 8 | *.js.deps 9 | *.js.map 10 | workspace.xml 11 | Dart_Packages.xml 12 | .DS_Store 13 | .idea/ 14 | .dart_tool/ 15 | *.conduit.pid -------------------------------------------------------------------------------- /packages/cli/templates/db_and_auth/bin/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:wildfire/wildfire.dart'; 2 | 3 | Future main(List args) async { 4 | final values = ApplicationOptions.parser.parse(args); 5 | if (values["help"] == true) { 6 | print(ApplicationOptions.parser.usage); 7 | return 0; 8 | } 9 | 10 | final app = Application(); 11 | app.options = ApplicationOptions() 12 | ..port = int.parse(values['port'] as String) 13 | ..address = values['address'] 14 | ..isIpv6Only = values['ipv6-only'] == true 15 | ..configurationFilePath = values['config-path'] as String? 16 | ..certificateFilePath = values['ssl-certificate-path'] as String? 17 | ..privateKeyFilePath = values['ssl-key-path'] as String?; 18 | final isolateCountString = values['isolates']; 19 | if (isolateCountString == null) { 20 | await app.startOnCurrentIsolate(); 21 | } else { 22 | await app.start(numberOfInstances: int.parse(isolateCountString as String)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/cli/templates/db_and_auth/config.src.yaml: -------------------------------------------------------------------------------- 1 | database: 2 | username: conduit_test_user 3 | password: conduit! 4 | host: localhost 5 | port: 15432 # change this value 6 | databaseName: conduit_test_db 7 | -------------------------------------------------------------------------------- /packages/cli/templates/db_and_auth/lib/controller/identity_controller.dart: -------------------------------------------------------------------------------- 1 | import 'package:wildfire/model/user.dart'; 2 | import 'package:wildfire/wildfire.dart'; 3 | 4 | class IdentityController extends ResourceController { 5 | IdentityController(this.context); 6 | 7 | final ManagedContext context; 8 | 9 | @Operation.get() 10 | Future getIdentity() async { 11 | final q = Query(context) 12 | ..where((o) => o.id).equalTo(request?.authorization?.ownerID); 13 | 14 | final u = await q.fetchOne(); 15 | if (u == null) { 16 | return Response.notFound(); 17 | } 18 | 19 | return Response.ok(u); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/cli/templates/db_and_auth/lib/model/user.dart: -------------------------------------------------------------------------------- 1 | import 'package:wildfire/wildfire.dart'; 2 | 3 | class User extends ManagedObject<_User> 4 | implements _User, ManagedAuthResourceOwner<_User> { 5 | @Serialize(input: true, output: false) 6 | String? password; 7 | } 8 | 9 | class _User extends ResourceOwnerTableDefinition { 10 | /* This class inherits the following from ManagedAuthenticatable: 11 | 12 | @primaryKey 13 | int? id; 14 | 15 | @Column(unique: true, indexed: true) 16 | String? username; 17 | 18 | @Column(omitByDefault: true) 19 | String? hashedPassword; 20 | 21 | @Column(omitByDefault: true) 22 | String? salt; 23 | 24 | ManagedSet? tokens; 25 | */ 26 | } 27 | -------------------------------------------------------------------------------- /packages/cli/templates/db_and_auth/lib/utility/html_template.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:io'; 3 | 4 | class HTMLRenderer { 5 | final Map _cache = {}; 6 | 7 | Future renderHTML( 8 | String path, Map templateVariables) async { 9 | final template = await _loadHTMLTemplate(path); 10 | 11 | return template!.replaceAllMapped(RegExp("{{([a-zA-Z_]+)}}"), (match) { 12 | final key = match.group(1); 13 | return templateVariables[key] ?? "null"; 14 | }); 15 | } 16 | 17 | Future _loadHTMLTemplate(String path) async { 18 | var contents = _cache[path]; 19 | if (contents == null) { 20 | try { 21 | final file = File(path); 22 | contents = file.readAsStringSync(); 23 | _cache[path] = contents; 24 | } catch (_) {} 25 | } 26 | 27 | return contents; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/cli/templates/db_and_auth/lib/wildfire.dart: -------------------------------------------------------------------------------- 1 | /// wildfire 2 | /// 3 | /// A conduit web server. 4 | library wildfire; 5 | 6 | export 'dart:async'; 7 | export 'dart:io'; 8 | 9 | export 'package:conduit_core/conduit_core.dart'; 10 | export 'package:conduit_postgresql/conduit_postgresql.dart'; 11 | export 'package:conduit_core/managed_auth.dart'; 12 | export 'package:conduit_open_api/v3.dart'; 13 | export 'package:conduit_common/conduit_common.dart'; 14 | 15 | export 'channel.dart'; 16 | -------------------------------------------------------------------------------- /packages/cli/templates/db_and_auth/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: wildfire 2 | description: An conduit application with a database connection, data model and OAuth 2.0 endpoints. 3 | version: 0.0.1 4 | publish_to: none 5 | 6 | environment: 7 | sdk: ">=3.7.0 <4.0.0" 8 | 9 | dependencies: 10 | conduit: ^5.1.0 11 | conduit_core: ^5.1.0 12 | conduit_postgresql: ^5.1.0 13 | 14 | dev_dependencies: 15 | test: ^1.25.2 16 | conduit_test: ^5.1.0 17 | -------------------------------------------------------------------------------- /packages/cli/templates/db_and_auth/test/identity_controller_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:wildfire/model/user.dart'; 2 | 3 | import 'harness/app.dart'; 4 | 5 | Future main() async { 6 | final harness = Harness()..install(); 7 | 8 | Agent? userClient; 9 | User? defaultUser; 10 | 11 | setUp(() async { 12 | defaultUser = User() 13 | ..username = "bob@stablekernel.com" 14 | ..password = "foobaraxegrind12%"; 15 | userClient = await harness.registerUser(defaultUser!); 16 | }); 17 | 18 | // After each test, reset the database to remove any rows it inserted. 19 | tearDown(() async { 20 | await harness.resetData(); 21 | }); 22 | 23 | test("Identity returns user associated with bearer token", () async { 24 | expectResponse(await userClient!.get("/me"), 200, 25 | body: {"id": greaterThan(0), "username": defaultUser!.username}); 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /packages/cli/templates/db_and_auth/test/user_controller_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:wildfire/model/user.dart'; 2 | 3 | import 'harness/app.dart'; 4 | 5 | Future main() async { 6 | final harness = Harness()..install(); 7 | 8 | Map? agents; 9 | 10 | setUp(() async { 11 | agents = {}; 12 | for (var i = 0; i < 6; i++) { 13 | final user = User() 14 | ..username = "bob+$i@conduit.dart.com" 15 | ..password = "foobaraxegrind$i%"; 16 | agents![i] = await harness.registerUser(user); 17 | } 18 | }); 19 | 20 | tearDown(() async { 21 | await harness.resetData(); 22 | }); 23 | 24 | test("Can get user with valid credentials", () async { 25 | final response = await agents![0]!.get("/users/1"); 26 | expect( 27 | response, 28 | hasResponse(200, 29 | body: partial({"username": "bob+0@conduit.dart.com"}))); 30 | }); 31 | 32 | test("Updating user fails if not owner", () async { 33 | final response = 34 | await agents![4]!.put("/users/1", body: {"username": "a@a.com"}); 35 | expect(response, hasStatus(401)); 36 | }); 37 | } 38 | -------------------------------------------------------------------------------- /packages/cli/templates/db_and_auth/web/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Login 7 | 8 | 9 | 10 |
11 |

Login

12 |
13 | 14 | 15 | 16 |
17 | 18 | 19 |
20 |
21 | 22 | 23 |
24 | 25 |
26 |
27 | 28 | 29 | -------------------------------------------------------------------------------- /packages/cli/templates/default/.gitignore: -------------------------------------------------------------------------------- 1 | .buildlog 2 | .pub/ 3 | build/ 4 | packages 5 | .packages 6 | *.dart.js 7 | *.js_ 8 | *.js.deps 9 | *.js.map 10 | workspace.xml 11 | Dart_Packages.xml 12 | .DS_Store 13 | .idea/ 14 | .dart_tool/ 15 | *.conduit.pid -------------------------------------------------------------------------------- /packages/cli/templates/default/README.md: -------------------------------------------------------------------------------- 1 | # wildfire 2 | 3 | ## Running the Application Locally 4 | 5 | Run `conduit serve` from this directory to run the application. For running within an IDE, run `bin/main.dart`. By default, a configuration file named `config.yaml` will be used. 6 | 7 | To generate a SwaggerUI client, run `conduit document client`. 8 | 9 | ## Running Application Tests 10 | 11 | To run all tests for this application, run the following in this directory: 12 | 13 | ``` 14 | pub run test 15 | ``` 16 | 17 | The default configuration file used when testing is `config.src.yaml`. This file should be checked into version control. It also the template for configuration files used in deployment. 18 | 19 | ## Deploying an Application 20 | 21 | See the documentation for [Deployment](https://www.theconduit.dev/docs/deploy/). -------------------------------------------------------------------------------- /packages/cli/templates/default/bin/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:wildfire/wildfire.dart'; 2 | 3 | Future main(List args) async { 4 | final values = ApplicationOptions.parser.parse(args); 5 | if (values["help"] == true) { 6 | print(ApplicationOptions.parser.usage); 7 | return 0; 8 | } 9 | 10 | final app = Application(); 11 | app.options = ApplicationOptions() 12 | ..port = int.parse(values['port'] as String) 13 | ..address = values['address'] 14 | ..isIpv6Only = values['ipv6-only'] == true 15 | ..configurationFilePath = values['config-path'] as String? 16 | ..certificateFilePath = values['ssl-certificate-path'] as String? 17 | ..privateKeyFilePath = values['ssl-key-path'] as String?; 18 | final isolateCountString = values['isolates']; 19 | if (isolateCountString == null) { 20 | await app.startOnCurrentIsolate(); 21 | } else { 22 | await app.start(numberOfInstances: int.parse(isolateCountString as String)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/cli/templates/default/config.src.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conduit-dart/conduit/c2c5c3298dd4da45daeb31469e708f71659e17f2/packages/cli/templates/default/config.src.yaml -------------------------------------------------------------------------------- /packages/cli/templates/default/lib/channel.dart: -------------------------------------------------------------------------------- 1 | import 'package:wildfire/controller/simple_controller.dart'; 2 | import 'package:wildfire/wildfire.dart'; 3 | 4 | /// This type initializes an application. 5 | /// 6 | /// Override methods in this class to set up routes and initialize services like 7 | /// database connections. See http://www.theconduit.dev/docs/http/channel/. 8 | class WildfireChannel extends ApplicationChannel { 9 | /// Initialize services in this method. 10 | /// 11 | /// Implement this method to initialize services, read values from [options] 12 | /// and any other initialization required before constructing [entryPoint]. 13 | /// 14 | /// This method is invoked prior to [entryPoint] being accessed. 15 | @override 16 | Future prepare() async { 17 | logger.onRecord.listen( 18 | (rec) => print("$rec ${rec.error ?? ""} ${rec.stackTrace ?? ""}")); 19 | } 20 | 21 | /// Construct the request channel. 22 | /// 23 | /// Return an instance of some [Controller] that will be the initial receiver 24 | /// of all [Request]s. 25 | /// 26 | /// This method is invoked after [prepare]. 27 | @override 28 | Controller get entryPoint { 29 | final router = Router(); 30 | 31 | router.route("/example").link(() => SimpleController()); 32 | 33 | return router; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /packages/cli/templates/default/lib/controller/simple_controller.dart: -------------------------------------------------------------------------------- 1 | import 'package:wildfire/wildfire.dart'; 2 | 3 | class SimpleController extends Controller { 4 | SimpleController(); 5 | 6 | @override 7 | Future handle(Request request) async { 8 | return Response.ok({"key": "value"}); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/cli/templates/default/lib/wildfire.dart: -------------------------------------------------------------------------------- 1 | /// wildfire 2 | /// 3 | /// A conduit web server. 4 | library wildfire; 5 | 6 | export 'dart:async'; 7 | export 'dart:io'; 8 | 9 | export 'package:conduit_core/conduit_core.dart'; 10 | 11 | export 'channel.dart'; 12 | -------------------------------------------------------------------------------- /packages/cli/templates/default/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: wildfire 2 | description: An empty conduit application. 3 | version: 0.0.1 4 | publish_to: none 5 | 6 | environment: 7 | sdk: ">=3.7.0 <4.0.0" 8 | 9 | dependencies: 10 | conduit: ^5.1.0 11 | conduit_core: ^5.1.0 12 | 13 | dev_dependencies: 14 | test: ^1.25.2 15 | conduit_test: ^5.1.0 16 | -------------------------------------------------------------------------------- /packages/cli/templates/default/test/example_test.dart: -------------------------------------------------------------------------------- 1 | import 'harness/app.dart'; 2 | 3 | Future main() async { 4 | final harness = Harness()..install(); 5 | 6 | test("GET /example returns 200 {'key': 'value'}", () async { 7 | expectResponse(await harness.agent?.get("/example"), 200, 8 | body: {"key": "value"}); 9 | }); 10 | } 11 | -------------------------------------------------------------------------------- /packages/cli/templates/default/test/harness/app.dart: -------------------------------------------------------------------------------- 1 | import 'package:wildfire/wildfire.dart'; 2 | import 'package:conduit_test/conduit_test.dart'; 3 | 4 | export 'package:wildfire/wildfire.dart'; 5 | export 'package:conduit_test/conduit_test.dart'; 6 | export 'package:test/test.dart'; 7 | export 'package:conduit_core/conduit_core.dart'; 8 | 9 | /// A testing harness for wildfire. 10 | /// 11 | /// A harness for testing an conduit application. Example test file: 12 | /// 13 | /// void main() { 14 | /// Harness harness = Harness()..install(); 15 | /// 16 | /// test("GET /path returns 200", () async { 17 | /// final response = await harness.agent.get("/path"); 18 | /// expectResponse(response, 200); 19 | /// }); 20 | /// } 21 | /// 22 | class Harness extends TestHarness { 23 | @override 24 | Future onSetUp() async {} 25 | 26 | @override 27 | Future onTearDown() async {} 28 | } 29 | -------------------------------------------------------------------------------- /packages/cli/test/schema_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:fs_test_agent/dart_project_agent.dart'; 2 | import 'package:fs_test_agent/working_directory_agent.dart'; 3 | import 'package:test/test.dart'; 4 | 5 | import 'not_tests/cli_helpers.dart'; 6 | 7 | void main() { 8 | late CLIClient cli; 9 | 10 | // This group handles checking the tool itself, 11 | // not the behavior of creating the appropriate migration file given schemas 12 | setUp(() async { 13 | cli = await CLIClient( 14 | WorkingDirectoryAgent(DartProjectAgent.projectsDirectory), 15 | ).createTestProject(); 16 | await cli.agent.getDependencies(); 17 | cli.agent.addOrReplaceFile("lib/application_test.dart", """ 18 | import 'package:conduit_core/conduit_core.dart'; 19 | import 'package:conduit_postgresql/conduit_postgresql.dart'; 20 | 21 | class TestObject extends ManagedObject<_TestObject> {} 22 | 23 | class _TestObject { 24 | @primaryKey 25 | int? id; 26 | 27 | String? foo; 28 | } 29 | """); 30 | }); 31 | 32 | tearDown(DartProjectAgent.tearDownAll); 33 | 34 | test("Ensure migration directory will get created on generation", () async { 35 | final res = await cli.run("db", ["schema"]); 36 | expect(res, 0); 37 | expect(cli.output, contains("_TestObject")); 38 | }); 39 | } 40 | -------------------------------------------------------------------------------- /packages/codable/.gitignore: -------------------------------------------------------------------------------- 1 | # Files and directories created by pub 2 | .dart_tool/ 3 | .packages 4 | .pub/ 5 | build/ 6 | # Remove the following pattern if you wish to check in your lock file 7 | pubspec.lock 8 | 9 | # Directory created by dartdoc 10 | doc/api/ 11 | .idea/ 12 | *.iml 13 | .metadata 14 | .project 15 | .failed_tracker 16 | -------------------------------------------------------------------------------- /packages/codable/.travis.yml: -------------------------------------------------------------------------------- 1 | language: dart 2 | dart: 3 | - beta 4 | 5 | jobs: 6 | include: 7 | - stage: test 8 | script: pub get && pub run test 9 | 10 | stages: 11 | - test 12 | 13 | branches: 14 | only: 15 | - master 16 | -------------------------------------------------------------------------------- /packages/codable/LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2018, stable/kernel 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /packages/codable/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:lints/recommended.yaml -------------------------------------------------------------------------------- /packages/codable/lib/conduit_codable.dart: -------------------------------------------------------------------------------- 1 | export 'package:conduit_codable/src/coding.dart'; 2 | export 'package:conduit_codable/src/keyed_archive.dart'; 3 | export 'package:conduit_codable/src/list.dart'; 4 | -------------------------------------------------------------------------------- /packages/codable/lib/src/codable.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_codable/src/resolver.dart'; 2 | 3 | abstract class Referencable { 4 | void resolveOrThrow(ReferenceResolver resolver); 5 | } 6 | -------------------------------------------------------------------------------- /packages/codable/lib/src/coding.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_codable/cast.dart' as cast; 2 | import 'package:conduit_codable/src/keyed_archive.dart'; 3 | import 'package:meta/meta.dart'; 4 | 5 | /// A base class for encodable and decodable objects. 6 | /// 7 | /// Types that can read or write their values to a document should extend this abstract class. 8 | /// By overriding [decode] and [encode], an instance of this type will read or write its values 9 | /// into a data container that can be transferred into formats like JSON or YAML. 10 | abstract class Coding { 11 | Uri? referenceURI; 12 | Map>? get castMap => null; 13 | 14 | @mustCallSuper 15 | void decode(KeyedArchive object) { 16 | referenceURI = object.referenceURI; 17 | object.castValues(castMap); 18 | } 19 | 20 | // would prefer to write referenceURI to object here, but see note in KeyedArchive._encodedObject 21 | void encode(KeyedArchive object); 22 | } 23 | -------------------------------------------------------------------------------- /packages/codable/lib/src/resolver.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_codable/src/keyed_archive.dart'; 2 | 3 | class ReferenceResolver { 4 | ReferenceResolver(this.document); 5 | 6 | final KeyedArchive document; 7 | 8 | /// resolves a reference of the form '#/yyy/xxx' 9 | /// To the value stored in a document 10 | /// 11 | /// e.g. 12 | /// if [ref] == '#/definitions/child' then we would 13 | /// return a [KeyedArchive] with the child named Sally. 14 | /// 15 | /// ``` 16 | /// { 17 | /// "definitions": { 18 | /// "child": {"name": "Sally"} 19 | /// }, 20 | /// "root": { 21 | /// "name": "Bob", 22 | /// "child": {"\$ref": "#/definitions/child"} 23 | ///} 24 | /// ``` 25 | KeyedArchive? resolve(Uri ref) { 26 | final folded = ref.pathSegments.fold(document, 27 | (KeyedArchive? objectPtr, pathSegment) { 28 | if (objectPtr != null) { 29 | return objectPtr[pathSegment] as KeyedArchive?; 30 | } else { 31 | return null; 32 | } 33 | }); 34 | 35 | return folded; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /packages/codable/mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: conduit_codable 2 | docs_dir: doc/api 3 | 4 | nav: 5 | - Docs: "index.html" -------------------------------------------------------------------------------- /packages/codable/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: conduit_codable 2 | description: A serialization library for converting dynamic, structured data (JSON, YAML) into Dart types. 3 | version: 5.1.5 4 | home: https://www.theconduit.dev 5 | repository: https://github.com/conduit-dart/conduit 6 | issue_tracker: https://github.com/conduit-dart/conduit/issues 7 | 8 | environment: 9 | sdk: ">=3.7.0 <4.0.0" 10 | 11 | dependencies: 12 | meta: ^1.3.0 13 | 14 | dev_dependencies: 15 | lints: ^5.1.1 16 | test: ^1.25.2 17 | -------------------------------------------------------------------------------- /packages/common/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://www.dartlang.org/guides/libraries/private-files 2 | 3 | # Files and directories created by pub 4 | .dart_tool/ 5 | .packages 6 | build/ 7 | # If you're building an application, you may want to check-in your pubspec.lock 8 | pubspec.lock 9 | 10 | # Directory created by dartdoc 11 | # If you don't generate documentation locally you can remove this line. 12 | doc/api/ 13 | 14 | # Avoid committing generated Javascript files: 15 | *.dart.js 16 | *.info.json # Produced by the --dump-info flag. 17 | *.js # When generated by dart2js. Don't specify *.js if your 18 | # project includes source files written in JavaScript. 19 | *.js_ 20 | *.js.deps 21 | *.js.map 22 | .failed_tracker 23 | -------------------------------------------------------------------------------- /packages/common/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | - For bug fixes, please file an issue or submit a pull request to master. 2 | - For documentation improvements (typos, errors, etc.), please submit a pull request to the branch `docs/source`. 3 | - For new features that are not already identified in issues, please file a new issue to discuss. 4 | 5 | ## Pull Request Requirements 6 | 7 | Please document the intent of the pull request. All non-documentation pull requests must also include automated tests that cover the new code, including failure cases. If applicable, please update the documentation in the `docs/source` branch. 8 | 9 | ## Running Tests 10 | 11 | Tests will automatically be run when you submit a pull request, but you will need to run tests locally. 12 | 13 | Run all tests with the following command: 14 | 15 | pub run test -j 1 16 | -------------------------------------------------------------------------------- /packages/common/LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2018, stable/kernel 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /packages/common/README.md: -------------------------------------------------------------------------------- 1 | # conduit-common 2 | Common utility classes and interfaces shared by conduit packages. 3 | 4 | The primary purpose of this package is to aid in decoupling conduit components. 5 | -------------------------------------------------------------------------------- /packages/common/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:lints/recommended.yaml 2 | -------------------------------------------------------------------------------- /packages/common/lib/conduit_common.dart: -------------------------------------------------------------------------------- 1 | export 'package:conduit_common/src/openapi/documentable.dart'; 2 | -------------------------------------------------------------------------------- /packages/common/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: conduit_common 2 | description: Common classes shared by conduit projects. 3 | version: 5.1.5 4 | home: https://www.theconduit.dev 5 | repository: https://github.com/conduit-dart/conduit 6 | issue_tracker: https://github.com/conduit-dart/conduit/issues 7 | 8 | environment: 9 | sdk: ">=3.7.0 <4.0.0" 10 | 11 | dependencies: 12 | conduit_open_api: ^5.1.5 13 | 14 | dev_dependencies: 15 | lints: ^5.1.1 16 | -------------------------------------------------------------------------------- /packages/common/pubspec_overrides.yaml: -------------------------------------------------------------------------------- 1 | dependency_overrides: 2 | conduit_codable: 3 | path: ../codable 4 | conduit_open_api: 5 | path: ../open_api -------------------------------------------------------------------------------- /packages/config/.gitignore: -------------------------------------------------------------------------------- 1 | # Files and directories created by pub 2 | .dart_tool/ 3 | .packages 4 | .pub/ 5 | build/ 6 | packages 7 | pubspec.lock 8 | 9 | # Files created by dart2js 10 | *.dart.js 11 | *.part.js 12 | *.js.deps 13 | *.js.map 14 | *.info.json 15 | 16 | # Directory created by dartdoc 17 | doc/api/ 18 | 19 | # JetBrains IDEs 20 | .idea/ 21 | *.iml 22 | *.ipr 23 | *.iws 24 | .failed_tracker 25 | -------------------------------------------------------------------------------- /packages/config/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Stable Kernel LLC 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * Neither the name of the organization nor the 12 | names of its contributors may be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /packages/config/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | analyzer: 2 | errors: 3 | empty_catches: ignore 4 | include: package:lints/recommended.yaml 5 | -------------------------------------------------------------------------------- /packages/config/lib/conduit_config.dart: -------------------------------------------------------------------------------- 1 | export 'package:conduit_config/src/compiler.dart'; 2 | export 'package:conduit_config/src/configuration.dart'; 3 | export 'package:conduit_config/src/default_configurations.dart'; 4 | -------------------------------------------------------------------------------- /packages/config/lib/src/compiler.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | import 'dart:mirrors'; 3 | 4 | import 'package:conduit_config/src/configuration.dart'; 5 | import 'package:conduit_config/src/runtime.dart'; 6 | import 'package:conduit_runtime/runtime.dart'; 7 | 8 | class ConfigurationCompiler extends Compiler { 9 | @override 10 | Map compile(MirrorContext context) { 11 | return Map.fromEntries( 12 | context.getSubclassesOf(Configuration).map((c) { 13 | return MapEntry( 14 | MirrorSystem.getName(c.simpleName), 15 | ConfigurationRuntimeImpl(c), 16 | ); 17 | }), 18 | ); 19 | } 20 | 21 | @override 22 | void deflectPackage(Directory destinationDirectory) { 23 | final libFile = File.fromUri( 24 | destinationDirectory.uri.resolve("lib/").resolve("conduit_config.dart"), 25 | ); 26 | final contents = libFile.readAsStringSync(); 27 | libFile.writeAsStringSync( 28 | contents.replaceFirst( 29 | "export 'package:conduit_config/src/compiler.dart';", ""), 30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/config/lib/src/intermediate_exception.dart: -------------------------------------------------------------------------------- 1 | class IntermediateException implements Exception { 2 | IntermediateException(this.underlying, this.keyPath); 3 | 4 | final dynamic underlying; 5 | 6 | final List keyPath; 7 | } 8 | -------------------------------------------------------------------------------- /packages/config/mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: conduit_config 2 | docs_dir: doc/api 3 | nav: 4 | - Docs: "index.html" -------------------------------------------------------------------------------- /packages/config/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: conduit_config 2 | description: A safe and convenient way to read YAML configuration files. 3 | version: 5.1.5 4 | home: https://www.theconduit.dev 5 | repository: https://github.com/conduit-dart/conduit 6 | issue_tracker: https://github.com/conduit-dart/conduit/issues 7 | 8 | environment: 9 | sdk: ">=3.7.0 <4.0.0" 10 | 11 | dependencies: 12 | conduit_runtime: ^5.1.5 13 | meta: ^1.3.0 14 | yaml: ^3.1.2 15 | 16 | dev_dependencies: 17 | lints: ^5.1.1 18 | test: ^1.25.2 19 | -------------------------------------------------------------------------------- /packages/config/pubspec_overrides.yaml: -------------------------------------------------------------------------------- 1 | dependency_overrides: 2 | conduit_isolate_exec: 3 | path: ../isolate_exec 4 | conduit_runtime: 5 | path: ../runtime -------------------------------------------------------------------------------- /packages/config/test/no_default_constructor_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_config/conduit_config.dart'; 2 | import 'package:conduit_runtime/runtime.dart'; 3 | import 'package:test/test.dart'; 4 | 5 | void main() { 6 | test( 7 | "Nested configuration without unnamed constructor is an error at compile time", 8 | () { 9 | try { 10 | RuntimeContext.current; 11 | fail('unreachable'); 12 | } on StateError catch (e) { 13 | expect(e.toString(), contains("Failed to compile 'BadConfig'")); 14 | } 15 | }, 16 | ); 17 | } 18 | 19 | class ParentConfig extends Configuration { 20 | late BadConfig badConfig; 21 | } 22 | 23 | class BadConfig extends Configuration { 24 | BadConfig.from(this.id); 25 | String id; 26 | } 27 | -------------------------------------------------------------------------------- /packages/core/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018, Stable Kernel LLC 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 8 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 9 | 10 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 11 | -------------------------------------------------------------------------------- /packages/core/README.md: -------------------------------------------------------------------------------- 1 | ../../README.md -------------------------------------------------------------------------------- /packages/core/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:lints/recommended.yaml 2 | 3 | analyzer: 4 | errors: 5 | empty_catches: ignore 6 | exclude: 7 | - tmp/** 8 | - templates/** -------------------------------------------------------------------------------- /packages/core/dart_test.yaml: -------------------------------------------------------------------------------- 1 | timeout: 120s 2 | concurrency: 1 -------------------------------------------------------------------------------- /packages/core/lib/src/application/starter.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:isolate'; 3 | 4 | import 'package:conduit_core/src/application/application.dart'; 5 | import 'package:conduit_core/src/application/channel.dart'; 6 | 7 | /* 8 | Warning: do not remove. This method is invoked by a generated script. 9 | 10 | */ 11 | Future startApplication( 12 | Application app, 13 | int isolateCount, 14 | SendPort parentPort, 15 | ) async { 16 | final port = ReceivePort(); 17 | 18 | port.listen((msg) { 19 | if (msg["command"] == "stop") { 20 | port.close(); 21 | app.stop().then((_) { 22 | parentPort.send({"status": "stopped"}); 23 | }); 24 | } 25 | }); 26 | 27 | if (isolateCount == 0) { 28 | await app.startOnCurrentIsolate(); 29 | } else { 30 | await app.start(numberOfInstances: isolateCount); 31 | } 32 | parentPort.send({"status": "ok", "port": port.sendPort}); 33 | } 34 | -------------------------------------------------------------------------------- /packages/core/lib/src/db/db.dart: -------------------------------------------------------------------------------- 1 | export 'managed/managed.dart'; 2 | export 'persistent_store/persistent_store.dart'; 3 | export 'query/query.dart'; 4 | export 'schema/schema.dart'; 5 | -------------------------------------------------------------------------------- /packages/core/lib/src/db/managed/data_model_manager.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/src/db/managed/data_model.dart'; 2 | import 'package:conduit_core/src/db/managed/entity.dart'; 3 | 4 | Map _dataModels = {}; 5 | 6 | ManagedEntity findEntity( 7 | Type type, { 8 | ManagedEntity Function()? orElse, 9 | }) { 10 | for (final d in _dataModels.keys) { 11 | final entity = d.tryEntityForType(type); 12 | if (entity != null) { 13 | return entity; 14 | } 15 | } 16 | 17 | if (orElse == null) { 18 | throw StateError( 19 | "No entity found for '$type. Did you forget to create a 'ManagedContext'?", 20 | ); 21 | } 22 | 23 | return orElse(); 24 | } 25 | 26 | void add(ManagedDataModel dataModel) { 27 | _dataModels.update(dataModel, (count) => count + 1, ifAbsent: () => 1); 28 | } 29 | 30 | void remove(ManagedDataModel dataModel) { 31 | if (_dataModels[dataModel] != null) { 32 | _dataModels.update(dataModel, (count) => count - 1); 33 | if (_dataModels[dataModel]! < 1) { 34 | _dataModels.remove(dataModel); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /packages/core/lib/src/db/managed/exception.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/src/http/serializable.dart'; 2 | 3 | /// An exception thrown when an ORM property validator is violated. 4 | /// 5 | /// Behaves the same as [SerializableException]. 6 | class ValidationException extends SerializableException { 7 | ValidationException(super.errors); 8 | } 9 | -------------------------------------------------------------------------------- /packages/core/lib/src/db/managed/key_path.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/src/db/managed/managed.dart'; 2 | 3 | class KeyPath { 4 | KeyPath(ManagedPropertyDescription? root) : path = [root]; 5 | 6 | KeyPath.byRemovingFirstNKeys(KeyPath original, int offset) 7 | : path = original.path.sublist(offset); 8 | 9 | KeyPath.byAddingKey(KeyPath original, ManagedPropertyDescription key) 10 | : path = List.from(original.path)..add(key); 11 | 12 | final List path; 13 | List? dynamicElements; 14 | 15 | ManagedPropertyDescription? operator [](int index) => path[index]; 16 | 17 | int get length => path.length; 18 | 19 | void add(ManagedPropertyDescription element) { 20 | path.add(element); 21 | } 22 | 23 | void addDynamicElement(dynamic element) { 24 | dynamicElements ??= []; 25 | dynamicElements!.add(element); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/core/lib/src/db/managed/managed.dart: -------------------------------------------------------------------------------- 1 | export 'attributes.dart'; 2 | export 'context.dart'; 3 | export 'data_model.dart'; 4 | export 'document.dart'; 5 | export 'entity.dart'; 6 | export 'exception.dart'; 7 | export 'object.dart'; 8 | export 'property_description.dart'; 9 | export 'set.dart'; 10 | export 'type.dart'; 11 | export 'validation/managed.dart'; 12 | export 'validation/metadata.dart'; 13 | export 'key_path.dart'; 14 | -------------------------------------------------------------------------------- /packages/core/lib/src/db/managed/relationship_type.dart: -------------------------------------------------------------------------------- 1 | /// The possible database relationships. 2 | enum ManagedRelationshipType { hasOne, hasMany, belongsTo } 3 | -------------------------------------------------------------------------------- /packages/core/lib/src/db/query/sort_descriptor.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/src/db/query/query.dart'; 2 | 3 | /// The order in which a collection of objects should be sorted when returned from a database. 4 | /// 5 | /// See [Query.sortBy] and [Query.pageBy] for more details. 6 | class QuerySortDescriptor { 7 | QuerySortDescriptor(this.key, this.order); 8 | 9 | /// The name of a property to sort by. 10 | String key; 11 | 12 | /// The order in which values should be sorted. 13 | /// 14 | /// See [QuerySortOrder] for possible values. 15 | QuerySortOrder order; 16 | } 17 | -------------------------------------------------------------------------------- /packages/core/lib/src/db/query/sort_predicate.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/src/db/query/query.dart'; 2 | 3 | /// The order in which a collection of objects should be sorted when returned from a database. 4 | class QuerySortPredicate { 5 | QuerySortPredicate( 6 | this.predicate, 7 | this.order, 8 | ); 9 | 10 | /// The name of a property to sort by. 11 | String predicate; 12 | 13 | /// The order in which values should be sorted. 14 | /// 15 | /// See [QuerySortOrder] for possible values. 16 | QuerySortOrder order; 17 | } 18 | -------------------------------------------------------------------------------- /packages/core/lib/src/http/handler_exception.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/src/http/http.dart'; 2 | 3 | class HandlerException implements Exception { 4 | HandlerException(this._response); 5 | 6 | Response get response => _response; 7 | 8 | final Response _response; 9 | } 10 | -------------------------------------------------------------------------------- /packages/core/lib/src/http/http.dart: -------------------------------------------------------------------------------- 1 | export 'body_decoder.dart'; 2 | export 'cache_policy.dart'; 3 | export 'controller.dart'; 4 | export 'cors_policy.dart'; 5 | export 'file_controller.dart'; 6 | export 'handler_exception.dart'; 7 | export 'http_codec_repository.dart'; 8 | export 'managed_object_controller.dart'; 9 | export 'query_controller.dart'; 10 | export 'request.dart'; 11 | export 'request_body.dart'; 12 | export 'request_path.dart'; 13 | export 'resource_controller.dart'; 14 | export 'resource_controller_bindings.dart'; 15 | export 'resource_controller_interfaces.dart'; 16 | export 'resource_controller_scope.dart'; 17 | export 'response.dart'; 18 | export 'route_node.dart'; 19 | export 'route_specification.dart'; 20 | export 'router.dart'; 21 | export 'serializable.dart'; 22 | -------------------------------------------------------------------------------- /packages/core/lib/src/runtime/resource_controller/utility.dart: -------------------------------------------------------------------------------- 1 | import 'dart:mirrors'; 2 | 3 | import 'package:collection/collection.dart' show IterableExtension; 4 | import 'package:conduit_core/src/auth/auth.dart'; 5 | import 'package:conduit_core/src/http/http.dart'; 6 | 7 | bool isOperation(DeclarationMirror m) { 8 | return getMethodOperationMetadata(m) != null; 9 | } 10 | 11 | List? getMethodScopes(DeclarationMirror m) { 12 | if (!isOperation(m)) { 13 | return null; 14 | } 15 | 16 | final method = m as MethodMirror; 17 | final metadata = method.metadata 18 | .firstWhereOrNull((im) => im.reflectee is Scope) 19 | ?.reflectee as Scope?; 20 | 21 | return metadata?.scopes.map((scope) => AuthScope(scope)).toList(); 22 | } 23 | 24 | Operation? getMethodOperationMetadata(DeclarationMirror m) { 25 | if (m is! MethodMirror) { 26 | return null; 27 | } 28 | 29 | final method = m; 30 | if (!method.isRegularMethod || method.isStatic) { 31 | return null; 32 | } 33 | 34 | final metadata = method.metadata 35 | .firstWhereOrNull((im) => im.reflectee is Operation) 36 | ?.reflectee as Operation?; 37 | 38 | return metadata; 39 | } 40 | -------------------------------------------------------------------------------- /packages/core/lib/src/utilities/mirror_helpers.dart: -------------------------------------------------------------------------------- 1 | import 'dart:mirrors'; 2 | import 'package:collection/collection.dart' show IterableExtension; 3 | 4 | Iterable classHierarchyForClass(ClassMirror t) sync* { 5 | var tableDefinitionPtr = t; 6 | while (tableDefinitionPtr.superclass != null) { 7 | yield tableDefinitionPtr; 8 | tableDefinitionPtr = tableDefinitionPtr.superclass!; 9 | } 10 | } 11 | 12 | T? firstMetadataOfType(DeclarationMirror dm, {TypeMirror? dynamicType}) { 13 | final tMirror = dynamicType ?? reflectType(T); 14 | return dm.metadata 15 | .firstWhereOrNull((im) => im.type.isSubtypeOf(tMirror)) 16 | ?.reflectee as T?; 17 | } 18 | 19 | List allMetadataOfType(DeclarationMirror dm) { 20 | final tMirror = reflectType(T); 21 | return dm.metadata 22 | .where((im) => im.type.isSubtypeOf(tMirror)) 23 | .map((im) => im.reflectee) 24 | .toList() 25 | .cast(); 26 | } 27 | 28 | String getMethodAndClassName(VariableMirror mirror) { 29 | return "${MirrorSystem.getName(mirror.owner!.owner!.simpleName)}.${MirrorSystem.getName(mirror.owner!.simpleName)}"; 30 | } 31 | -------------------------------------------------------------------------------- /packages/core/lib/src/utilities/sourcify.dart: -------------------------------------------------------------------------------- 1 | String sourcifyValue(dynamic v, {String? onError}) { 2 | if (v is String) { 3 | if (!v.contains("'")) { 4 | return "'$v'"; 5 | } 6 | if (!v.contains('"')) { 7 | return '"$v"'; 8 | } 9 | 10 | // todo: not urgent 11 | throw StateError( 12 | "${onError ?? "A string literal contains both a single and double quote"}. " 13 | "This is not yet implemented - please submit a pull request."); 14 | } 15 | 16 | return v.toString(); 17 | } 18 | -------------------------------------------------------------------------------- /packages/core/mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: conduit_core 2 | docs_dir: doc/api 3 | 4 | nav: 5 | - Docs: "index.html" 6 | -------------------------------------------------------------------------------- /packages/core/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: conduit_core 2 | version: 5.1.5 3 | description: This is the core of the framework. 4 | home: https://www.theconduit.dev 5 | repository: https://github.com/conduit-dart/conduit 6 | issue_tracker: https://github.com/conduit-dart/conduit/issues 7 | 8 | environment: 9 | sdk: ">=3.7.0 <4.0.0" 10 | 11 | dependencies: 12 | analyzer: ^7.1.0 13 | args: ^2.4.2 14 | collection: ^1.18.0 15 | conduit_common: ^5.1.5 16 | conduit_config: ^5.1.5 17 | conduit_isolate_exec: ^5.1.5 18 | conduit_open_api: ^5.1.5 19 | conduit_password_hash: ^5.1.5 20 | conduit_runtime: ^5.1.5 21 | crypto: ^3.0.3 22 | io: ^1.0.4 23 | logging: ^1.2.0 24 | meta: ^1.12.0 25 | path: ^1.9.0 26 | postgres: ^3.1.1 27 | pub_semver: ^2.1.4 28 | recase: ^4.1.0 29 | yaml: ^3.1.2 30 | 31 | dev_dependencies: 32 | conduit_postgresql: 33 | path: ../postgresql 34 | conduit_test: 35 | path: ../test_harness 36 | fs_test_agent: 37 | path: ../fs_test_agent 38 | http: ^1.2.1 39 | lints: ^5.1.1 40 | matcher: ^0.12.16+1 41 | mockito: ^5.4.4 42 | test: ^1.25.2 43 | web_socket_channel: ^3.0.0 44 | -------------------------------------------------------------------------------- /packages/core/pubspec_overrides.yaml: -------------------------------------------------------------------------------- 1 | dependency_overrides: 2 | conduit_codable: 3 | path: ../codable 4 | conduit_common: 5 | path: ../common 6 | conduit_config: 7 | path: ../config 8 | conduit_isolate_exec: 9 | path: ../isolate_exec 10 | conduit_open_api: 11 | path: ../open_api 12 | conduit_password_hash: 13 | path: ../password_hash 14 | conduit_postgresql: 15 | path: ../postgresql 16 | conduit_runtime: 17 | path: ../runtime 18 | conduit_test: 19 | path: ../test_harness 20 | fs_test_agent: 21 | path: ../fs_test_agent 22 | -------------------------------------------------------------------------------- /packages/core/test/auth/auth_utility_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/conduit_core.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | test("Generated confidential, redirectable API client has valid values", () { 6 | final client = generateAPICredentialPair( 7 | "a", 8 | "b", 9 | redirectURI: "http://a.com", 10 | ); 11 | expect(client.id, "a"); 12 | expect( 13 | client.hashedSecret, 14 | generatePasswordHash("b", client.salt!), 15 | ); 16 | expect(client.redirectURI, "http://a.com"); 17 | }); 18 | 19 | test("Generated confidential, non-redirectable API client has valid values", 20 | () { 21 | final client = generateAPICredentialPair("a", "b"); 22 | expect(client.id, "a"); 23 | expect( 24 | client.hashedSecret, 25 | generatePasswordHash("b", client.salt!), 26 | ); 27 | expect(client.redirectURI, isNull); 28 | }); 29 | 30 | test("Generated public API client has valid values", () { 31 | final client = generateAPICredentialPair("a", null); 32 | expect(client.id, "a"); 33 | expect(client.hashedSecret, isNull); 34 | expect(client.salt, isNull); 35 | expect(client.redirectURI, isNull); 36 | }); 37 | 38 | test("Generated public, redirectable API client has valid values", () { 39 | final client = generateAPICredentialPair( 40 | "a", 41 | null, 42 | redirectURI: "http://a.com", 43 | ); 44 | expect(client.id, "a"); 45 | expect(client.hashedSecret, isNull); 46 | expect(client.salt, isNull); 47 | expect(client.redirectURI, "http://a.com"); 48 | }); 49 | } 50 | -------------------------------------------------------------------------------- /packages/core/test/db/compilation_errors/model_autoinc_and_default_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/conduit_core.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | class AutoincrementAndDefault extends ManagedObject<_AutoincrementAndDefault> {} 5 | 6 | class _AutoincrementAndDefault { 7 | @primaryKey 8 | int? id; 9 | 10 | @Column(autoincrement: true, defaultValue: "1") 11 | int? i; 12 | } 13 | 14 | void main() { 15 | test("Property is both autoincrement and default value, fails", () { 16 | try { 17 | final _ = ManagedDataModel([AutoincrementAndDefault]); 18 | expect(true, false); 19 | } on ManagedDataModelError catch (e) { 20 | expect(e.message, contains("_AutoincrementAndDefault.i")); 21 | expect(e.message, contains("autoincrement")); 22 | expect(e.message, contains("default value")); 23 | } 24 | }); 25 | } 26 | -------------------------------------------------------------------------------- /packages/core/test/db/compilation_errors/model_conflicting_null_rule_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/conduit_core.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | test("Delete rule of setNull throws exception if property is not nullable", 6 | () { 7 | try { 8 | ManagedDataModel([Owner, FailingChild]); 9 | expect(true, false); 10 | } on ManagedDataModelError catch (e) { 11 | expect( 12 | e.message, 13 | contains("Relationship 'ref' on '_FailingChild' has both"), 14 | ); 15 | } 16 | }); 17 | } 18 | 19 | class Owner extends ManagedObject<_Owner> implements _Owner {} 20 | 21 | class _Owner { 22 | @primaryKey 23 | int? id; 24 | 25 | FailingChild? gen; 26 | } 27 | 28 | class FailingChild extends ManagedObject<_FailingChild> 29 | implements _FailingChild {} 30 | 31 | class _FailingChild { 32 | @primaryKey 33 | int? id; 34 | 35 | @Relate(Symbol('gen'), onDelete: DeleteRule.nullify, isRequired: true) 36 | Owner? ref; 37 | } 38 | -------------------------------------------------------------------------------- /packages/core/test/db/compilation_errors/model_conflicting_relate_annotation_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/conduit_core.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | class InvalidCyclicLeft extends ManagedObject<_InvalidCyclicLeft> {} 5 | 6 | class _InvalidCyclicLeft { 7 | @primaryKey 8 | int? id; 9 | 10 | @Relate(Symbol('ref')) 11 | InvalidCyclicRight? ref; 12 | } 13 | 14 | class InvalidCyclicRight extends ManagedObject<_InvalidCyclicRight> {} 15 | 16 | class _InvalidCyclicRight { 17 | @primaryKey 18 | int? id; 19 | 20 | @Relate(Symbol('ref')) 21 | InvalidCyclicLeft? ref; 22 | } 23 | 24 | void main() { 25 | test("Both properties have Relationship metadata", () { 26 | try { 27 | final _ = ManagedDataModel([InvalidCyclicLeft, InvalidCyclicRight]); 28 | expect(true, false); 29 | } on ManagedDataModelError catch (e) { 30 | expect(e.message, contains("_InvalidCyclicLeft")); 31 | expect(e.message, contains("_InvalidCyclicRight")); 32 | expect(e.message, contains("but only one can")); 33 | } 34 | }); 35 | } 36 | -------------------------------------------------------------------------------- /packages/core/test/db/compilation_errors/model_dupe_inverse_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/conduit_core.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | test("Duplicate inverse properties fail compilation", () { 6 | try { 7 | ManagedDataModel([DupInverse, DupInverseHas]); 8 | expect(true, false); 9 | } on ManagedDataModelError catch (e) { 10 | expect(e.message, contains("has multiple relationship properties")); 11 | expect(e.message, contains("'inverse'")); 12 | expect(e.message, contains("foo, bar")); 13 | } 14 | }); 15 | } 16 | 17 | class DupInverseHas extends ManagedObject<_DupInverseHas> {} 18 | 19 | class _DupInverseHas { 20 | @primaryKey 21 | int? id; 22 | 23 | ManagedSet? inverse; 24 | } 25 | 26 | class DupInverse extends ManagedObject<_DupInverse> {} 27 | 28 | class _DupInverse { 29 | @primaryKey 30 | int? id; 31 | 32 | @Relate(Symbol('inverse')) 33 | DupInverseHas? foo; 34 | 35 | @Relate(Symbol('inverse')) 36 | DupInverseHas? bar; 37 | } 38 | -------------------------------------------------------------------------------- /packages/core/test/db/compilation_errors/model_has_no_constructor_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/conduit_core.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | test("Cannot have only named constructor", () { 6 | try { 7 | ManagedDataModel([HasNoDefaultConstructor]); 8 | fail('unreachable'); 9 | } on ManagedDataModelError catch (e) { 10 | expect(e.toString(), contains("HasNoDefaultConstructor")); 11 | expect(e.toString(), contains("default, unnamed constructor")); 12 | } 13 | }); 14 | } 15 | 16 | class HasNoDefaultConstructor extends ManagedObject<_ConstructorTableDef> { 17 | HasNoDefaultConstructor.foo(); 18 | } 19 | 20 | class _ConstructorTableDef { 21 | @primaryKey 22 | int? id; 23 | } 24 | -------------------------------------------------------------------------------- /packages/core/test/db/compilation_errors/model_missing_inverse_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/conduit_core.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | class MissingInverse2 extends ManagedObject<_MissingInverse2> {} 5 | 6 | class _MissingInverse2 { 7 | @primaryKey 8 | int? id; 9 | 10 | ManagedSet? inverseMany; 11 | } 12 | 13 | class MissingInverseAbsent extends ManagedObject<_MissingInverseAbsent> {} 14 | 15 | class _MissingInverseAbsent { 16 | @primaryKey 17 | int? id; 18 | } 19 | 20 | void main() { 21 | test("Managed objects with missing inverses fail compilation", () { 22 | try { 23 | ManagedDataModel([MissingInverse2, MissingInverseAbsent]); 24 | expect(true, false); 25 | } on ManagedDataModelError catch (e) { 26 | expect(e.message, contains("'_MissingInverse2'")); 27 | expect(e.message, contains("'inverseMany'")); 28 | } 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /packages/core/test/db/compilation_errors/model_multi_request_empty_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/conduit_core.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | test("Add Table to table definition with empty unique list throws exception", 6 | () { 7 | try { 8 | ManagedDataModel([MultiUniqueFailureNoElement]); 9 | expect(true, false); 10 | } on ManagedDataModelError catch (e) { 11 | expect(e.message, contains("Must contain two or more attributes")); 12 | } 13 | }); 14 | } 15 | 16 | class MultiUniqueFailureNoElement 17 | extends ManagedObject<_MultiUniqueFailureNoElement> {} 18 | 19 | @Table.unique([]) 20 | class _MultiUniqueFailureNoElement { 21 | @primaryKey 22 | int? id; 23 | } 24 | -------------------------------------------------------------------------------- /packages/core/test/db/compilation_errors/model_multi_unique_has_one_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/conduit_core.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | test( 6 | "Add Table to table definition with has- property in unique list throws exception", 7 | () { 8 | try { 9 | ManagedDataModel([ 10 | MultiUniqueFailureRelationship, 11 | MultiUniqueFailureRelationshipInverse 12 | ]); 13 | expect(true, false); 14 | } on ManagedDataModelError catch (e) { 15 | expect(e.message, contains("declares 'a' as unique")); 16 | } 17 | }); 18 | } 19 | 20 | class MultiUniqueFailureRelationship 21 | extends ManagedObject<_MultiUniqueFailureRelationship> {} 22 | 23 | @Table.unique([Symbol('a'), Symbol('b')]) 24 | class _MultiUniqueFailureRelationship { 25 | @primaryKey 26 | int? id; 27 | 28 | MultiUniqueFailureRelationshipInverse? a; 29 | int? b; 30 | } 31 | 32 | class MultiUniqueFailureRelationshipInverse 33 | extends ManagedObject<_MultiUniqueFailureRelationshipInverse> {} 34 | 35 | class _MultiUniqueFailureRelationshipInverse { 36 | @primaryKey 37 | int? id; 38 | 39 | @Relate(Symbol('a')) 40 | MultiUniqueFailureRelationship? rel; 41 | } 42 | -------------------------------------------------------------------------------- /packages/core/test/db/compilation_errors/model_multi_unique_single_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/conduit_core.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | test( 6 | "Add Table to table definition with only single element in unique list throws exception, warns to use Table", 7 | () { 8 | try { 9 | ManagedDataModel([MultiUniqueFailureSingleElement]); 10 | expect(true, false); 11 | } on ManagedDataModelError catch (e) { 12 | expect( 13 | e.message, 14 | contains("add 'Column(unique: true)' to declaration of 'a'"), 15 | ); 16 | } 17 | }); 18 | } 19 | 20 | class MultiUniqueFailureSingleElement 21 | extends ManagedObject<_MultiUniqueFailureSingleElement> {} 22 | 23 | @Table.unique([Symbol('a')]) 24 | class _MultiUniqueFailureSingleElement { 25 | @primaryKey 26 | int? id; 27 | 28 | int? a; 29 | } 30 | -------------------------------------------------------------------------------- /packages/core/test/db/compilation_errors/model_multi_unique_unknown_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/conduit_core.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | test( 6 | "Add Table to table definition with non-existent property in unique list throws exception", 7 | () { 8 | try { 9 | ManagedDataModel([MultiUniqueFailureUnknown]); 10 | expect(true, false); 11 | } on ManagedDataModelError catch (e) { 12 | expect(e.message, contains("'a' is not a property of this type")); 13 | } 14 | }); 15 | } 16 | 17 | class MultiUniqueFailureUnknown 18 | extends ManagedObject<_MultiUniqueFailureUnknown> {} 19 | 20 | @Table.unique([Symbol('a'), Symbol('b')]) 21 | class _MultiUniqueFailureUnknown { 22 | @primaryKey 23 | int? id; 24 | 25 | int? b; 26 | } 27 | -------------------------------------------------------------------------------- /packages/core/test/db/compilation_errors/model_no_pk_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/conduit_core.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | class NoPrimaryKey extends ManagedObject<_NoPrimaryKey> 5 | implements _NoPrimaryKey {} 6 | 7 | class _NoPrimaryKey { 8 | String? foo; 9 | } 10 | 11 | void main() { 12 | test("Entity without primary key fails", () { 13 | try { 14 | ManagedDataModel([NoPrimaryKey]); 15 | expect(true, false); 16 | } on ManagedDataModelError catch (e) { 17 | expect( 18 | e.message, 19 | contains( 20 | "Class '_NoPrimaryKey' doesn't declare a primary key property", 21 | ), 22 | ); 23 | } 24 | }); 25 | } 26 | -------------------------------------------------------------------------------- /packages/core/test/db/compilation_errors/model_relationship_is_not_column_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/conduit_core.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | test("Model with Relationship and Column fails compilation", () { 6 | try { 7 | ManagedDataModel([InvalidMetadata, InvalidMetadata1]); 8 | expect(true, false); 9 | } on ManagedDataModelError catch (e) { 10 | expect(e.message, contains("cannot both have")); 11 | expect(e.message, contains("InvalidMetadata")); 12 | expect(e.message, contains("'bar'")); 13 | } 14 | }); 15 | } 16 | 17 | class InvalidMetadata extends ManagedObject<_InvalidMetadata> {} 18 | 19 | class _InvalidMetadata { 20 | @Column(primaryKey: true) 21 | int? id; 22 | 23 | @Relate(Symbol('foo')) 24 | @Column(indexed: true) 25 | InvalidMetadata1? bar; 26 | } 27 | 28 | class InvalidMetadata1 extends ManagedObject<_InvalidMetadata1> {} 29 | 30 | class _InvalidMetadata1 { 31 | @primaryKey 32 | int? id; 33 | 34 | InvalidMetadata? foo; 35 | } 36 | -------------------------------------------------------------------------------- /packages/core/test/db/compilation_errors/model_required_args_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/conduit_core.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | test("Cannot have unnamed constructor with required args", () { 6 | try { 7 | ManagedDataModel([DefaultConstructorHasRequiredArgs]); 8 | fail('unreachable'); 9 | } on ManagedDataModelError catch (e) { 10 | expect(e.toString(), contains("DefaultConstructorHasRequiredArgs")); 11 | expect(e.toString(), contains("default, unnamed constructor")); 12 | } 13 | }); 14 | } 15 | 16 | class DefaultConstructorHasRequiredArgs 17 | extends ManagedObject<_ConstructorTableDef> { 18 | // ignore: avoid_unused_constructor_parameters 19 | DefaultConstructorHasRequiredArgs(int foo); 20 | } 21 | 22 | class _ConstructorTableDef { 23 | @primaryKey 24 | int? id; 25 | } 26 | -------------------------------------------------------------------------------- /packages/core/test/db/compilation_errors/model_tables_same_name_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/conduit_core.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | test("Two entities with same tableName should throw exception", () { 6 | try { 7 | final _ = ManagedDataModel([SameNameOne, SameNameTwo]); 8 | expect(true, false); 9 | } on ManagedDataModelError catch (e) { 10 | expect(e.message, contains("SameNameOne")); 11 | expect(e.message, contains("SameNameTwo")); 12 | expect(e.message, contains("'fo'")); 13 | } 14 | }); 15 | } 16 | 17 | class SameNameOne extends ManagedObject<_SameNameOne> {} 18 | 19 | @Table(name: "fo") 20 | class _SameNameOne { 21 | @primaryKey 22 | int? id; 23 | 24 | // ignore: unused_element 25 | static String tableName() => "fo"; 26 | } 27 | 28 | class SameNameTwo extends ManagedObject<_SameNameTwo> {} 29 | 30 | @Table(name: "fo") 31 | class _SameNameTwo { 32 | @primaryKey 33 | int? id; 34 | 35 | // ignore: unused_element 36 | static String tableName() => "fo"; 37 | } 38 | -------------------------------------------------------------------------------- /packages/core/test/db/compilation_errors/model_unsupported_transient_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/conduit_core.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | class InvalidTransientModel extends ManagedObject<_InvalidTransientModel> 5 | implements _InvalidTransientModel { 6 | @Serialize() 7 | Uri? uri; 8 | } 9 | 10 | class _InvalidTransientModel { 11 | @primaryKey 12 | int? id; 13 | } 14 | 15 | void main() { 16 | test("Model with unsupported transient property type fails on compilation", 17 | () { 18 | try { 19 | ManagedDataModel([InvalidTransientModel]); 20 | expect(true, false); 21 | } on ManagedDataModelError catch (e) { 22 | expect(e.message, contains("'InvalidTransientModel'")); 23 | expect(e.message, contains("'uri'")); 24 | expect(e.message, contains("unsupported type")); 25 | } 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /packages/core/test/db/compilation_errors/model_unsupported_type_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/conduit_core.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | class InvalidModel extends ManagedObject<_InvalidModel> 5 | implements _InvalidModel {} 6 | 7 | class _InvalidModel { 8 | @primaryKey 9 | int? id; 10 | 11 | Uri? uri; 12 | } 13 | 14 | void main() { 15 | test("Model with unsupported property type fails on compilation", () { 16 | try { 17 | ManagedDataModel([InvalidModel]); 18 | expect(true, false); 19 | } on ManagedDataModelError catch (e) { 20 | expect(e.message, contains("'_InvalidModel'")); 21 | expect(e.message, contains("'uri'")); 22 | expect(e.message, contains("unsupported type")); 23 | } 24 | }); 25 | } 26 | -------------------------------------------------------------------------------- /packages/core/test/db/compilation_errors/model_wrong_inverse_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/conduit_core.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | test("Managed objects with missing inverses fail compilation", () { 6 | try { 7 | ManagedDataModel([MissingInverse1, MissingInverseWrongSymbol]); 8 | expect(true, false); 9 | } on ManagedDataModelError catch (e) { 10 | expect(e.message, contains("has no inverse property")); 11 | expect(e.message, contains("'_MissingInverseWrongSymbol'")); 12 | expect(e.message, contains("'has'")); 13 | } 14 | }); 15 | } 16 | 17 | class MissingInverse1 extends ManagedObject<_MissingInverse1> {} 18 | 19 | class _MissingInverse1 { 20 | @primaryKey 21 | int? id; 22 | 23 | MissingInverseWrongSymbol? inverse; 24 | } 25 | 26 | class MissingInverseWrongSymbol 27 | extends ManagedObject<_MissingInverseWrongSymbol> {} 28 | 29 | class _MissingInverseWrongSymbol { 30 | @primaryKey 31 | int? id; 32 | 33 | @Relate(Symbol('foobar')) 34 | MissingInverse1? has; 35 | } 36 | -------------------------------------------------------------------------------- /packages/core/test/db/compilation_errors/validate_date_time_parse_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/conduit_core.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | class FailingDateTime extends ManagedObject<_FDT> {} 5 | 6 | class _FDT { 7 | @primaryKey 8 | int? id; 9 | 10 | @Validate.compare(greaterThanEqualTo: "19x34") 11 | DateTime? d; 12 | } 13 | 14 | void main() { 15 | test("DateTime fails to parse", () { 16 | try { 17 | ManagedDataModel([FailingDateTime]); 18 | expect(true, false); 19 | } on ManagedDataModelError catch (e) { 20 | expect(e.toString(), contains("19x34")); 21 | expect(e.toString(), contains("cannot be parsed as expected")); 22 | expect(e.toString(), contains("_FDT.d")); 23 | } 24 | }); 25 | } 26 | -------------------------------------------------------------------------------- /packages/core/test/db/compilation_errors/validate_length_type_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/conduit_core.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | class FailingLength extends ManagedObject<_FLEN> {} 5 | 6 | class _FLEN { 7 | @primaryKey 8 | int? id; 9 | 10 | @Validate.length(equalTo: 6) 11 | int? d; 12 | } 13 | 14 | void main() { 15 | test("Non-string Validate.length", () { 16 | try { 17 | ManagedDataModel([FailingLength]); 18 | expect(true, false); 19 | } on ManagedDataModelError catch (e) { 20 | expect(e.toString(), contains("is only valid for 'String'")); 21 | expect(e.toString(), contains("_FLEN.d")); 22 | } 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /packages/core/test/db/compilation_errors/validate_matches_type_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/conduit_core.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | class FailingRegex extends ManagedObject<_FRX> {} 5 | 6 | class _FRX { 7 | @primaryKey 8 | int? id; 9 | 10 | @Validate.matches("xyz") 11 | int? d; 12 | } 13 | 14 | void main() { 15 | test("Non-string Validate.matches", () { 16 | try { 17 | ManagedDataModel([FailingRegex]); 18 | expect(true, false); 19 | } on ManagedDataModelError catch (e) { 20 | expect(e.toString(), contains("is only valid for 'String'")); 21 | expect(e.toString(), contains("_FRX.d")); 22 | } 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /packages/core/test/db/compilation_errors/validate_one_of_wrong_type_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/conduit_core.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | class FailingOneOf extends ManagedObject<_FOO> {} 5 | 6 | class _FOO { 7 | @primaryKey 8 | int? id; 9 | 10 | @Validate.oneOf(["x", "y"]) 11 | int? d; 12 | } 13 | 14 | void main() { 15 | test("Non-matching type for oneOf", () { 16 | try { 17 | ManagedDataModel([FailingOneOf]); 18 | expect(true, false); 19 | } on ManagedDataModelError catch (e) { 20 | expect(e.toString(), contains("Validate.oneOf")); 21 | expect(e.toString(), contains("_FOO.d")); 22 | } 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /packages/core/test/db/compilation_errors/validate_oneof_empty_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/conduit_core.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | class FailingEmptyOneOf extends ManagedObject<_FEO> {} 5 | 6 | class _FEO { 7 | @primaryKey 8 | int? id; 9 | 10 | @Validate.oneOf([]) 11 | int? d; 12 | } 13 | 14 | void main() { 15 | test("Empty oneOf", () { 16 | try { 17 | ManagedDataModel([FailingEmptyOneOf]); 18 | expect(true, false); 19 | } on ManagedDataModelError catch (e) { 20 | expect(e.toString(), contains("Validate.oneOf")); 21 | expect(e.toString(), contains("_FEO.d")); 22 | } 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /packages/core/test/db/compilation_errors/validate_oneof_heterogenuous_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/conduit_core.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | class FailingHeterogenous extends ManagedObject<_FH> {} 5 | 6 | class _FH { 7 | @primaryKey 8 | int? id; 9 | 10 | @Validate.oneOf(["x", 1]) 11 | int? d; 12 | } 13 | 14 | void main() { 15 | test("Heterogenous oneOf", () { 16 | try { 17 | ManagedDataModel([FailingHeterogenous]); 18 | expect(true, false); 19 | } on ManagedDataModelError catch (e) { 20 | expect(e.toString(), contains("Validate.oneOf")); 21 | expect(e.toString(), contains("_FH.d")); 22 | } 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /packages/core/test/db/compilation_errors/validate_unsupported_one_of_date_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/conduit_core.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | class UnsupportedDateOneOf extends ManagedObject<_UDAOO> {} 5 | 6 | class _UDAOO { 7 | @primaryKey 8 | int? id; 9 | 10 | @Validate.oneOf(["2016-01-01T00:00:00", "2017-01-01T00:00:00"]) 11 | DateTime? compareDateOneOf20162017; 12 | } 13 | 14 | void main() { 15 | test("Unsupported type, date, for oneOf", () { 16 | try { 17 | ManagedDataModel([UnsupportedDateOneOf]); 18 | expect(true, false); 19 | } on ManagedDataModelError catch (e) { 20 | expect(e.toString(), contains("Validate.oneOf")); 21 | expect(e.toString(), contains("compareDateOneOf20162017")); 22 | } 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /packages/core/test/db/compilation_errors/validate_unsupported_one_of_double_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/conduit_core.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | class UnsupportedDoubleOneOf extends ManagedObject<_UDOOO> {} 5 | 6 | class _UDOOO { 7 | @primaryKey 8 | int? id; 9 | 10 | @Validate.oneOf(["3.14159265359", "2.71828"]) 11 | double? someFloatingNumber; 12 | } 13 | 14 | void main() { 15 | test("Unsupported type, double, for oneOf", () { 16 | try { 17 | ManagedDataModel([UnsupportedDoubleOneOf]); 18 | expect(true, false); 19 | } on ManagedDataModelError catch (e) { 20 | expect(e.toString(), contains("Validate.oneOf")); 21 | expect(e.toString(), contains("someFloatingNumber")); 22 | } 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /packages/core/test/db/deferred_model_subclass_test.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: overridden_fields 2 | 3 | import 'package:conduit_core/conduit_core.dart'; 4 | import 'package:test/test.dart'; 5 | 6 | void main() { 7 | test("Can override property in partial and modify attrs/validators", () { 8 | final dataModel = 9 | ManagedDataModel([OverriddenTotalModel, PartialReferenceModel]); 10 | 11 | final entity = dataModel.entityForType(OverriddenTotalModel); 12 | final field = entity.attributes["field"]!; 13 | expect(field.isUnique, true); 14 | expect(field.validators.length, 1); 15 | }); 16 | } 17 | 18 | class OverriddenTotalModel extends ManagedObject<_OverriddenTotalModel> 19 | implements _OverriddenTotalModel {} 20 | 21 | class _OverriddenTotalModel extends PartialModel { 22 | @override 23 | @Column(indexed: true, unique: true) 24 | @Validate.oneOf(["a", "b"]) 25 | String? field; 26 | } 27 | 28 | class PartialModel { 29 | @primaryKey 30 | int? id; 31 | 32 | @Column(indexed: true) 33 | String? field; 34 | 35 | ManagedSet? hasManyRelationship; 36 | 37 | static String tableName() { 38 | return "predefined"; 39 | } 40 | } 41 | 42 | class PartialReferenceModel extends ManagedObject<_PartialReferenceModel> 43 | implements _PartialReferenceModel {} 44 | 45 | class _PartialReferenceModel { 46 | @primaryKey 47 | int? id; 48 | 49 | String? field; 50 | 51 | @Relate.deferred(DeleteRule.cascade, isRequired: true) 52 | PartialModel? foreignKeyColumn; 53 | } 54 | -------------------------------------------------------------------------------- /packages/core/test/db/query_exception_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/conduit_core.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | test("Conflict returns 409", () { 6 | final exception = QueryException.conflict("invalid", ["xyz"]); 7 | expect(exception.response.statusCode, 409); 8 | expect( 9 | exception.response.body, 10 | {"error": "invalid", "detail": "Offending Items: xyz"}, 11 | ); 12 | }); 13 | 14 | test("Input returns 400", () { 15 | final exception = QueryException.input("invalid", ["xyz"]); 16 | expect(exception.response.statusCode, 400); 17 | expect( 18 | exception.response.body, 19 | {"error": "invalid", "detail": "Offending Items: xyz"}, 20 | ); 21 | }); 22 | 23 | test("Transport returns 503", () { 24 | final exception = QueryException.transport("invalid"); 25 | expect(exception.response.statusCode, 503); 26 | expect(exception.response.body, {"error": "invalid"}); 27 | }); 28 | 29 | test("Offending items show in response detail", () { 30 | final exception = QueryException.input("invalid", ["xyz"]); 31 | expect(exception.response.body["detail"], contains("xyz")); 32 | }); 33 | 34 | test("No detail is provided when there are no offending items", () { 35 | final exception = QueryException.input("invalid", []); 36 | expect(exception.response.body, {"error": "invalid"}); 37 | }); 38 | } 39 | -------------------------------------------------------------------------------- /packages/core/test/http/compilation_errors/controller_mutable_property_test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:conduit_core/conduit_core.dart'; 4 | import 'package:conduit_runtime/runtime.dart'; 5 | import 'package:test/test.dart'; 6 | 7 | void main() { 8 | test( 9 | "A controller that is not Recyclable, but declares non-final properties throws a runtime error", 10 | () { 11 | try { 12 | // ignore: unnecessary_statements 13 | RuntimeContext.current; 14 | fail('unreachable'); 15 | } on StateError catch (e) { 16 | expect(e.toString(), contains("MutablePropertyController")); 17 | } 18 | }, 19 | ); 20 | } 21 | 22 | class MutablePropertyController extends Controller { 23 | String? mutableProperty; 24 | 25 | @override 26 | FutureOr handle(Request request) { 27 | return request; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/core/test/http/compilation_errors/controller_mutable_setter_test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:conduit_core/conduit_core.dart'; 4 | import 'package:conduit_runtime/runtime.dart'; 5 | import 'package:test/test.dart'; 6 | 7 | void main() { 8 | test( 9 | "A controller that is not Recyclable, but declares a setter throws a runtime error", 10 | () { 11 | try { 12 | // ignore: unnecessary_statements 13 | RuntimeContext.current; 14 | fail('unreachable'); 15 | } on StateError catch (e) { 16 | expect(e.toString(), contains("MutableSetterController")); 17 | } 18 | }, 19 | ); 20 | } 21 | 22 | class MutableSetterController extends Controller { 23 | set mutableSetter(String s) {} 24 | 25 | @override 26 | FutureOr handle(Request request) { 27 | return request; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/core/test/http/compilation_errors/resource_controller_ambiguous_operation_test.dart: -------------------------------------------------------------------------------- 1 | import "dart:core"; 2 | 3 | import 'package:conduit_core/conduit_core.dart'; 4 | import 'package:conduit_runtime/runtime.dart'; 5 | import "package:test/test.dart"; 6 | 7 | void main() { 8 | test("Ambiguous methods throws exception", () { 9 | try { 10 | // ignore: unnecessary_statements 11 | RuntimeContext.current; 12 | fail('unreachable'); 13 | } on StateError catch (e) { 14 | expect(e.toString(), contains("'get1'")); 15 | expect(e.toString(), contains("'get2'")); 16 | expect(e.toString(), contains("'AmbiguousController'")); 17 | } 18 | }); 19 | } 20 | 21 | class AmbiguousController extends ResourceController { 22 | @Operation.get("id") 23 | Future get1(@Bind.path("id") int id) async { 24 | return Response.ok(null); 25 | } 26 | 27 | @Operation.get("id") 28 | Future get2(@Bind.path("id") int id) async { 29 | return Response.ok(null); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/core/test/http/compilation_errors/resource_controller_bind_dynamic_test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:conduit_core/conduit_core.dart'; 4 | import 'package:conduit_runtime/runtime.dart'; 5 | import "package:test/test.dart"; 6 | 7 | void main() { 8 | test("Cannot bind dynamic to header", () { 9 | try { 10 | // ignore: unnecessary_statements 11 | RuntimeContext.current; 12 | fail('unreachable'); 13 | } on StateError catch (e) { 14 | expect( 15 | e.toString(), 16 | contains("Invalid binding 'x' on 'ErrorDynamic.get1'"), 17 | ); 18 | } 19 | }); 20 | } 21 | 22 | class ErrorDynamic extends ResourceController { 23 | @Operation.get() 24 | Future get1(@Bind.header("foo") dynamic x) async { 25 | return Response.ok(null); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/core/test/http/compilation_errors/resource_controller_bind_list_path_test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:conduit_core/conduit_core.dart'; 4 | import 'package:conduit_runtime/runtime.dart'; 5 | import "package:test/test.dart"; 6 | 7 | void main() { 8 | test("Cannot bind dynamic to header", () { 9 | try { 10 | // ignore: unnecessary_statements 11 | RuntimeContext.current; 12 | fail('unreachable'); 13 | } on StateError catch (e) { 14 | expect( 15 | e.toString(), 16 | contains("Invalid binding 'x' on 'ErrorListPath.get1'"), 17 | ); 18 | } 19 | }); 20 | } 21 | 22 | class ErrorListPath extends ResourceController { 23 | @Operation.get('id') 24 | Future get1(@Bind.path("id") List x) async { 25 | return Response.ok(null); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/core/test/http/compilation_errors/resource_controller_bind_unparseable_test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:io'; 3 | 4 | import 'package:conduit_core/conduit_core.dart'; 5 | import 'package:conduit_runtime/runtime.dart'; 6 | import "package:test/test.dart"; 7 | 8 | void main() { 9 | test("Cannot bind invalid type to default implementation", () { 10 | try { 11 | // ignore: unnecessary_statements 12 | RuntimeContext.current; 13 | fail('unreachable'); 14 | } on StateError catch (e) { 15 | expect( 16 | e.toString(), 17 | // ignore: missing_whitespace_between_adjacent_strings 18 | "Bad state: Invalid binding 'x' on 'ErrorDefault.get1':" 19 | "Parameter type does not implement static parse method.", 20 | ); 21 | } 22 | }); 23 | } 24 | 25 | class ErrorDefault extends ResourceController { 26 | @Operation.get() 27 | Future get1(@Bind.header("foo") HttpHeaders x) async { 28 | return Response.ok(null); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/core/test/http/compilation_errors/resource_controller_filter_nonserializable_test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:conduit_core/conduit_core.dart'; 4 | import 'package:conduit_runtime/runtime.dart'; 5 | import "package:test/test.dart"; 6 | 7 | void main() { 8 | test("Cannot bind invalid type to default implementation", () { 9 | try { 10 | // ignore: unnecessary_statements 11 | RuntimeContext.current; 12 | fail('unreachable'); 13 | } on StateError catch (e) { 14 | expect( 15 | e.toString(), 16 | // ignore: missing_whitespace_between_adjacent_strings 17 | "Bad state: Invalid binding 'a' on 'FilterNonSerializable.get1':" 18 | "Filters can only be used on Serializable or List.", 19 | ); 20 | } 21 | }); 22 | } 23 | 24 | class FilterNonSerializable extends ResourceController { 25 | @Operation.post() 26 | Future get1( 27 | @Bind.body(ignore: ["id"]) Map a, 28 | ) async { 29 | return Response.ok(null); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/core/test/http/compilation_errors/resource_controller_unbound_path_test.dart: -------------------------------------------------------------------------------- 1 | import "dart:core"; 2 | 3 | import 'package:conduit_core/conduit_core.dart'; 4 | import 'package:conduit_runtime/runtime.dart'; 5 | import "package:test/test.dart"; 6 | 7 | void main() { 8 | test("Ambiguous methods throws exception", () { 9 | try { 10 | // ignore: unnecessary_statements 11 | RuntimeContext.current; 12 | fail('unreachable'); 13 | } on StateError catch (e) { 14 | expect(e.toString(), contains("Invalid controller")); 15 | expect(e.toString(), contains("'UnboundController'")); 16 | expect(e.toString(), contains("'getOne'")); 17 | } 18 | }); 19 | } 20 | 21 | class UnboundController extends ResourceController { 22 | @Operation.get() 23 | Future getOne(@Bind.path("id") int id) async { 24 | return Response.ok(null); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/core/test/http/sink_test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:conduit_core/conduit_core.dart'; 4 | import 'package:conduit_runtime/runtime.dart'; 5 | import 'package:test/test.dart'; 6 | 7 | void main() { 8 | test("Find default ApplicationChannel", () { 9 | expect( 10 | RuntimeContext.current.runtimes.iterable 11 | .whereType() 12 | .length, 13 | equals(1), 14 | ); 15 | expect( 16 | RuntimeContext.current.runtimes.iterable 17 | .whereType() 18 | .first 19 | .channelType, 20 | equals(TestChannel), 21 | ); 22 | }); 23 | } 24 | 25 | class TestChannel extends ApplicationChannel { 26 | @override 27 | Controller get entryPoint { 28 | final router = Router(); 29 | router.route("/controller/[:id]").link(() => FailingController()); 30 | return router; 31 | } 32 | } 33 | 34 | class FailingController extends ResourceController { 35 | @Operation.get() 36 | Future get() async { 37 | return Response.ok(null); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /packages/fs_test_agent/.gitignore: -------------------------------------------------------------------------------- 1 | # Files and directories created by pub 2 | .dart_tool/ 3 | .idea/ 4 | .packages 5 | *.iml 6 | # Remove the following pattern if you wish to check in your lock file 7 | pubspec.lock 8 | 9 | # Conventional directory for build outputs 10 | build/ 11 | 12 | # Directory created by dartdoc 13 | doc/api/ 14 | 15 | .history 16 | .failed_tracker 17 | .dart_tool/ 18 | -------------------------------------------------------------------------------- /packages/fs_test_agent/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019, Stable Kernel LLC 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 8 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 9 | 10 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /packages/fs_test_agent/README.md: -------------------------------------------------------------------------------- 1 | Utilities for writing tests to validate file system and Dart project directory operations. -------------------------------------------------------------------------------- /packages/fs_test_agent/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:lints/recommended.yaml 2 | 3 | linter: 4 | rules: 5 | dangling_library_doc_comments: false -------------------------------------------------------------------------------- /packages/fs_test_agent/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: fs_test_agent 2 | version: 5.1.5 3 | description: Utilities for writing tests to validate file system and Dart project directory operations. 4 | home: https://www.theconduit.dev 5 | repository: https://github.com/conduit-dart/conduit 6 | issue_tracker: https://github.com/conduit-dart/conduit/issues 7 | 8 | environment: 9 | sdk: ">=3.7.0 <4.0.0" 10 | 11 | dependencies: 12 | path: ^1.9.0 13 | pubspec_parse: ^1.5.0 14 | 15 | dev_dependencies: 16 | lints: ^5.1.1 17 | test: ^1.25.2 18 | -------------------------------------------------------------------------------- /packages/fs_test_agent/test/project_agent_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:fs_test_agent/dart_project_agent.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | test("Create agent", () { 6 | final agent = DartProjectAgent("test_project"); 7 | print(agent.workingDirectory); //ignore: avoid_print 8 | }); 9 | } 10 | -------------------------------------------------------------------------------- /packages/isolate_exec/.gitignore: -------------------------------------------------------------------------------- 1 | # Files and directories created by pub 2 | .packages 3 | .pub/ 4 | build/ 5 | # Remove the following pattern if you wish to check in your lock file 6 | pubspec.lock 7 | .idea/ 8 | .dart_tool/ 9 | 10 | # Directory created by dartdoc 11 | doc/api/ 12 | 13 | *.iml 14 | .tool-versions.failed_tracker 15 | .failed_tracker 16 | -------------------------------------------------------------------------------- /packages/isolate_exec/LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2018, stable/kernel 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /packages/isolate_exec/README.md: -------------------------------------------------------------------------------- 1 | # conduit_isolate_exec 2 | 3 | This library contains types that allow for executing code in a spawned isolate, perhaps with additional imports. 4 | 5 | Subclass `Executable` and override its `execute` method. Invoke `IsolateExecutor.executeWithType`, passing in that subclass. 6 | The code in `execute` will run in another isolate. Any value it returns will be returned by `IsolateExecutor.executeWithType`. 7 | 8 | A returned value must be a primitive type (anything that is encodable as JSON). You may pass parameters to the other isolate by providing 9 | a message map. 10 | 11 | Example: 12 | 13 | ```dart 14 | class Echo extends Executable { 15 | Echo(Map message) 16 | : echoMessage = message['echo'], 17 | super(message); 18 | 19 | final String echoMessage; 20 | 21 | @override 22 | Future execute() async { 23 | return echoMessage; 24 | } 25 | } 26 | 27 | Future main() async { 28 | final result = await IsolateExecutor.executeWithType(Echo, message: {'echo': 'hello'}); 29 | assert(result == 'hello'); 30 | } 31 | ``` -------------------------------------------------------------------------------- /packages/isolate_exec/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:lints/recommended.yaml -------------------------------------------------------------------------------- /packages/isolate_exec/lib/conduit_isolate_exec.dart: -------------------------------------------------------------------------------- 1 | /// Executes closures on isolates. 2 | /// 3 | /// 4 | library; 5 | 6 | export 'package:conduit_isolate_exec/src/executable.dart'; 7 | export 'package:conduit_isolate_exec/src/executor.dart'; 8 | export 'package:conduit_isolate_exec/src/source_generator.dart'; 9 | -------------------------------------------------------------------------------- /packages/isolate_exec/mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: conduit_isolate_exec 2 | docs_dir: doc/api 3 | 4 | nav: 5 | - Docs: "index.html" -------------------------------------------------------------------------------- /packages/isolate_exec/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: conduit_isolate_exec 2 | version: 5.1.5 3 | description: This library contains types that allow for executing code in a spawned isolate, perhaps with additional imports. 4 | home: https://www.theconduit.dev 5 | repository: https://github.com/conduit-dart/conduit 6 | issue_tracker: https://github.com/conduit-dart/conduit/issues 7 | 8 | environment: 9 | sdk: ">=3.7.0 <4.0.0" 10 | 11 | dependencies: 12 | analyzer: ^7.1.0 13 | glob: ^2.1.2 14 | path: ^1.9.0 15 | 16 | dev_dependencies: 17 | lints: ^5.1.1 18 | test: ^1.25.2 19 | test_package: 20 | path: ../isolate_exec_test_packages/test_package 21 | -------------------------------------------------------------------------------- /packages/isolate_exec_test_packages/test_package/README.md: -------------------------------------------------------------------------------- 1 | This package is part of the isolate_exec package. 2 | 3 | Unfortunately due to https://github.com/dart-lang/sdk/issues/42910 this 4 | package can't live under the isolate_exec root. 5 | 6 | -------------------------------------------------------------------------------- /packages/isolate_exec_test_packages/test_package/lib/lib.dart: -------------------------------------------------------------------------------- 1 | import 'package:test_package/src/src.dart'; 2 | export 'package:test_package/src/src.dart'; 3 | 4 | String libFunction() => "libFunction"; 5 | 6 | class DefaultObject implements SomeObjectBaseClass { 7 | @override 8 | String get id => "default"; 9 | } 10 | 11 | class PositionalArgumentsObject implements SomeObjectBaseClass { 12 | PositionalArgumentsObject(this.id); 13 | 14 | @override 15 | String id; 16 | } 17 | 18 | class NamedArgumentsObject implements SomeObjectBaseClass { 19 | NamedArgumentsObject({this.id = ''}); 20 | 21 | @override 22 | String id; 23 | } 24 | 25 | class NamedConstructorObject implements SomeObjectBaseClass { 26 | NamedConstructorObject.fromID(); 27 | 28 | @override 29 | String get id => "fromID"; 30 | } 31 | -------------------------------------------------------------------------------- /packages/isolate_exec_test_packages/test_package/lib/src/src.dart: -------------------------------------------------------------------------------- 1 | String sourceFunction() => "sourceFunction"; 2 | 3 | abstract class SomeObjectBaseClass { 4 | String get id; 5 | } 6 | -------------------------------------------------------------------------------- /packages/isolate_exec_test_packages/test_package/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: test_package 2 | version: 3.1.0 3 | description: test dependency 4 | publish_to: none 5 | 6 | environment: 7 | sdk: ">=3.7.0 <4.0.0" 8 | -------------------------------------------------------------------------------- /packages/open_api/.gitignore: -------------------------------------------------------------------------------- 1 | # Files and directories created by pub 2 | .packages 3 | .pub/ 4 | build/ 5 | # Remove the following pattern if you wish to check in your lock file 6 | pubspec.lock 7 | 8 | # Directory created by dartdoc 9 | doc/api/ 10 | .DS_Store 11 | .dart_tool/ 12 | .idea/ 13 | *.iml 14 | test/specs/kubernetes.json 15 | test/specs/stripe.json 16 | test/specs/petstore-simple.json 17 | .failed_tracker 18 | .dart_tool/ 19 | -------------------------------------------------------------------------------- /packages/open_api/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Stable Kernel LLC 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 8 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 9 | 10 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 11 | -------------------------------------------------------------------------------- /packages/open_api/README.md: -------------------------------------------------------------------------------- 1 | # conduit_open_api 2 | 3 | Reads and writes OpenAPI (Swagger) specifications. 4 | 5 | conduit_open_api supports both v2 and v3 of the open_api specification. 6 | 7 | To use v2 import: 8 | 9 | ```dart 10 | import 'package:conduit_open_api/v2.dart'; 11 | ``` 12 | 13 | To use v3 import: 14 | 15 | ```dart 16 | import 'package:conduit_open_api/v3.dart'; 17 | ``` 18 | 19 | You can us v2 and v3 within a single project. 20 | 21 | 22 | Example 23 | --- 24 | 25 | ```dart 26 | import 'package:conduit_open_api/v3.dart'; 27 | 28 | 29 | final file = File("test/specs/kubernetes.json"); 30 | final contents = await file.readAsString(); 31 | final doc = APIDocument.fromJSON(contents); 32 | 33 | final output = JSON.encode(doc.asMap()); 34 | ``` 35 | 36 | -------------------------------------------------------------------------------- /packages/open_api/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:lints/recommended.yaml -------------------------------------------------------------------------------- /packages/open_api/lib/src/object.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_codable/conduit_codable.dart'; 2 | import 'package:meta/meta.dart'; 3 | 4 | class APIObject extends Coding { 5 | Map extensions = {}; 6 | 7 | @mustCallSuper 8 | @override 9 | void decode(KeyedArchive object) { 10 | super.decode(object); 11 | 12 | final extensionKeys = object.keys.where((k) => k.startsWith("x-")); 13 | for (final key in extensionKeys) { 14 | extensions[key] = object.decode(key); 15 | } 16 | } 17 | 18 | @override 19 | @mustCallSuper 20 | void encode(KeyedArchive object) { 21 | final invalidKeys = extensions.keys 22 | .where((key) => !key.startsWith("x-")) 23 | .map((key) => "'$key'") 24 | .toList(); 25 | if (invalidKeys.isNotEmpty) { 26 | throw ArgumentError( 27 | "extension keys must start with 'x-'. The following keys are invalid: ${invalidKeys.join(", ")}", 28 | ); 29 | } 30 | 31 | extensions.forEach((key, value) { 32 | object.encode(key, value); 33 | }); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /packages/open_api/lib/src/util/list_helper.dart: -------------------------------------------------------------------------------- 1 | /// Remove any null entries from the list and convert the type. 2 | /// In reality I don't think the list can have nulls but we still 3 | /// need the conversion. 4 | List? removeNullsFromList(List? list) { 5 | if (list == null) return null; 6 | 7 | // remove nulls and convert to List 8 | return list.nonNulls.toList(); 9 | } 10 | -------------------------------------------------------------------------------- /packages/open_api/lib/src/util/map_helper.dart: -------------------------------------------------------------------------------- 1 | /// Remove any entries with a null value from the list and convert the type. 2 | Map removeNullsFromMap(Map? map) { 3 | if (map == null) return {}; 4 | 5 | final fixed = {}; 6 | 7 | // remove nulls 8 | for (final key in map.keys) { 9 | final value = map[key]; 10 | if (value != null) { 11 | fixed[key] = value; 12 | } 13 | } 14 | 15 | return fixed; 16 | } 17 | -------------------------------------------------------------------------------- /packages/open_api/lib/src/v2/header.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_codable/conduit_codable.dart'; 2 | import 'package:conduit_open_api/src/v2/property.dart'; 3 | import 'package:conduit_open_api/src/v2/types.dart'; 4 | 5 | /// Represents a header in the OpenAPI specification. 6 | class APIHeader extends APIProperty { 7 | APIHeader(); 8 | 9 | String? description; 10 | APIProperty? items; 11 | 12 | @override 13 | void decode(KeyedArchive object) { 14 | super.decode(object); 15 | description = object.decode("description"); 16 | if (type == APIType.array) { 17 | items = object.decodeObject("items", () => APIProperty()); 18 | } 19 | } 20 | 21 | @override 22 | void encode(KeyedArchive object) { 23 | super.encode(object); 24 | object.encode("description", description); 25 | if (type == APIType.array) { 26 | object.encodeObject("items", items); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/open_api/lib/src/v2/path.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_codable/conduit_codable.dart'; 2 | import 'package:conduit_open_api/src/object.dart'; 3 | import 'package:conduit_open_api/src/v2/operation.dart'; 4 | import 'package:conduit_open_api/src/v2/parameter.dart'; 5 | 6 | /// Represents a path (also known as a route) in the OpenAPI specification. 7 | class APIPath extends APIObject { 8 | APIPath(); 9 | 10 | List parameters = []; 11 | Map operations = {}; 12 | 13 | @override 14 | void decode(KeyedArchive object) { 15 | super.decode(object); 16 | 17 | for (final k in object.keys) { 18 | if (k == r"$ref") { 19 | // todo: reference 20 | } else if (k == "parameters") { 21 | parameters = object.decodeObjects(k, () => APIParameter())!; 22 | } else { 23 | operations[k] = object.decodeObject(k, () => APIOperation()); 24 | } 25 | } 26 | } 27 | 28 | @override 29 | void encode(KeyedArchive object) { 30 | super.encode(object); 31 | 32 | object.encodeObjects("parameters", parameters); 33 | operations.forEach((opName, op) { 34 | object.encodeObject(opName, op); 35 | }); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /packages/open_api/lib/src/v2/response.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_codable/conduit_codable.dart'; 2 | import 'package:conduit_open_api/src/object.dart'; 3 | import 'package:conduit_open_api/src/v2/header.dart'; 4 | import 'package:conduit_open_api/src/v2/schema.dart'; 5 | 6 | /// Represents an HTTP response in the OpenAPI specification. 7 | class APIResponse extends APIObject { 8 | APIResponse(); 9 | 10 | String? description = ""; 11 | APISchemaObject? schema; 12 | Map? headers = {}; 13 | 14 | @override 15 | void decode(KeyedArchive object) { 16 | super.decode(object); 17 | 18 | description = object.decode("description"); 19 | schema = object.decodeObject("schema", () => APISchemaObject()); 20 | headers = object.decodeObjectMap("headers", () => APIHeader()); 21 | } 22 | 23 | @override 24 | void encode(KeyedArchive object) { 25 | super.encode(object); 26 | 27 | object.encodeObjectMap("headers", headers); 28 | object.encodeObject("schema", schema); 29 | object.encode("description", description); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/open_api/lib/src/v2/types.dart: -------------------------------------------------------------------------------- 1 | enum APIType { string, number, integer, boolean, array, file, object } 2 | 3 | class APITypeCodec { 4 | static APIType? decode(String? type) { 5 | switch (type) { 6 | case "string": 7 | return APIType.string; 8 | case "number": 9 | return APIType.number; 10 | case "integer": 11 | return APIType.integer; 12 | case "boolean": 13 | return APIType.boolean; 14 | case "array": 15 | return APIType.array; 16 | case "file": 17 | return APIType.file; 18 | case "object": 19 | return APIType.object; 20 | } 21 | return null; 22 | } 23 | 24 | static String? encode(APIType? type) { 25 | switch (type) { 26 | case APIType.string: 27 | return "string"; 28 | case APIType.number: 29 | return "number"; 30 | case APIType.integer: 31 | return "integer"; 32 | case APIType.boolean: 33 | return "boolean"; 34 | case APIType.array: 35 | return "array"; 36 | case APIType.file: 37 | return "file"; 38 | case APIType.object: 39 | return "object"; 40 | default: 41 | return null; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /packages/open_api/lib/src/v3/callback.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_codable/conduit_codable.dart'; 2 | import 'package:conduit_open_api/src/object.dart'; 3 | import 'package:conduit_open_api/src/v3/path.dart'; 4 | 5 | /// A map of possible out-of band callbacks related to the parent operation. 6 | /// 7 | /// Each value in the map is a [APIPath] that describes a set of requests that may be initiated by the API provider and the expected responses. The key value used to identify the callback object is an expression, evaluated at runtime, that identifies a URL to use for the callback operation. 8 | class APICallback extends APIObject { 9 | APICallback({this.paths}); 10 | APICallback.empty(); 11 | 12 | /// Callback paths. 13 | /// 14 | /// The key that identifies the [APIPath] is a runtime expression that can be evaluated in the context of a runtime HTTP request/response to identify the URL to be used for the callback request. A simple example might be $request.body#/url. 15 | Map? paths; 16 | 17 | @override 18 | void decode(KeyedArchive object) { 19 | super.decode(object); 20 | 21 | paths = {}; 22 | object.forEach((key, dynamic value) { 23 | if (value is! KeyedArchive) { 24 | throw ArgumentError( 25 | "Invalid specification. Callback contains non-object value.", 26 | ); 27 | } 28 | paths![key] = value.decodeObject(key, () => APIPath())!; 29 | }); 30 | } 31 | 32 | @override 33 | void encode(KeyedArchive object) { 34 | super.encode(object); 35 | throw StateError("APICallback.encode: not yet implemented."); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /packages/open_api/lib/src/v3/header.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_codable/conduit_codable.dart'; 2 | import 'package:conduit_open_api/src/v3/parameter.dart'; 3 | import 'package:conduit_open_api/src/v3/schema.dart'; 4 | 5 | /// [APIHeader] follows the structure of the [APIParameter] with the following changes: 6 | /// 7 | /// name MUST NOT be specified, it is given in the corresponding headers map. 8 | /// in MUST NOT be specified, it is implicitly in header. 9 | /// All traits that are affected by the location MUST be applicable to a location of header (for example, style). 10 | class APIHeader extends APIParameter { 11 | APIHeader({APISchemaObject? schema}) : super.header(null, schema: schema); 12 | APIHeader.empty() : super.header(null); 13 | 14 | @override 15 | void encode(KeyedArchive object) { 16 | name = "temporary"; 17 | super.encode(object); 18 | object.remove("name"); 19 | object.remove("in"); 20 | name = null; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/open_api/lib/src/v3/media_type.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_codable/conduit_codable.dart'; 2 | import 'package:conduit_open_api/src/object.dart'; 3 | import 'package:conduit_open_api/src/v3/encoding.dart'; 4 | import 'package:conduit_open_api/src/v3/schema.dart'; 5 | 6 | /// Each [APIMediaType] provides schema and examples for the media type identified by its key. 7 | class APIMediaType extends APIObject { 8 | APIMediaType({this.schema, this.encoding}); 9 | APIMediaType.empty(); 10 | 11 | /// The schema defining the type used for the request body. 12 | APISchemaObject? schema; 13 | 14 | /// A map between a property name and its encoding information. 15 | /// 16 | /// The key, being the property name, MUST exist in the schema as a property. The encoding object SHALL only apply to requestBody objects when the media type is multipart or application/x-www-form-urlencoded. 17 | Map? encoding; 18 | 19 | @override 20 | void decode(KeyedArchive object) { 21 | super.decode(object); 22 | 23 | schema = object.decodeObject("schema", () => APISchemaObject()); 24 | encoding = object.decodeObjectMap("encoding", () => APIEncoding()); 25 | } 26 | 27 | @override 28 | void encode(KeyedArchive object) { 29 | super.encode(object); 30 | 31 | object.encodeObject("schema", schema); 32 | object.encodeObjectMap("encoding", encoding); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/open_api/lib/src/v3/types.dart: -------------------------------------------------------------------------------- 1 | enum APIType { string, number, integer, boolean, array, object } 2 | 3 | class APITypeCodec { 4 | static APIType? decode(String? type) { 5 | switch (type) { 6 | case "string": 7 | return APIType.string; 8 | case "number": 9 | return APIType.number; 10 | case "integer": 11 | return APIType.integer; 12 | case "boolean": 13 | return APIType.boolean; 14 | case "array": 15 | return APIType.array; 16 | case "object": 17 | return APIType.object; 18 | default: 19 | return null; 20 | } 21 | } 22 | 23 | static String? encode(APIType? type) { 24 | switch (type) { 25 | case APIType.string: 26 | return "string"; 27 | case APIType.number: 28 | return "number"; 29 | case APIType.integer: 30 | return "integer"; 31 | case APIType.boolean: 32 | return "boolean"; 33 | case APIType.array: 34 | return "array"; 35 | case APIType.object: 36 | return "object"; 37 | default: 38 | return null; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /packages/open_api/lib/v2.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, joeconway. All rights reserved. Use of this source code 2 | // is governed by a BSD-style license that can be found in the LICENSE file. 3 | 4 | /// Support for doing something awesome. 5 | /// 6 | /// More dartdocs go here. 7 | library; 8 | 9 | export 'package:conduit_open_api/src/v2/document.dart'; 10 | export 'package:conduit_open_api/src/v2/header.dart'; 11 | export 'package:conduit_open_api/src/v2/metadata.dart'; 12 | export 'package:conduit_open_api/src/v2/operation.dart'; 13 | export 'package:conduit_open_api/src/v2/parameter.dart'; 14 | export 'package:conduit_open_api/src/v2/path.dart'; 15 | export 'package:conduit_open_api/src/v2/response.dart'; 16 | export 'package:conduit_open_api/src/v2/schema.dart'; 17 | export 'package:conduit_open_api/src/v2/security.dart'; 18 | export 'package:conduit_open_api/src/v2/types.dart'; 19 | -------------------------------------------------------------------------------- /packages/open_api/lib/v3.dart: -------------------------------------------------------------------------------- 1 | library; 2 | 3 | export 'package:conduit_open_api/src/object.dart'; 4 | export 'package:conduit_open_api/src/v3/callback.dart'; 5 | export 'package:conduit_open_api/src/v3/components.dart'; 6 | export 'package:conduit_open_api/src/v3/document.dart'; 7 | export 'package:conduit_open_api/src/v3/encoding.dart'; 8 | export 'package:conduit_open_api/src/v3/header.dart'; 9 | export 'package:conduit_open_api/src/v3/media_type.dart'; 10 | export 'package:conduit_open_api/src/v3/metadata.dart'; 11 | export 'package:conduit_open_api/src/v3/operation.dart'; 12 | export 'package:conduit_open_api/src/v3/parameter.dart'; 13 | export 'package:conduit_open_api/src/v3/path.dart'; 14 | export 'package:conduit_open_api/src/v3/request_body.dart'; 15 | export 'package:conduit_open_api/src/v3/response.dart'; 16 | export 'package:conduit_open_api/src/v3/schema.dart'; 17 | export 'package:conduit_open_api/src/v3/security.dart'; 18 | export 'package:conduit_open_api/src/v3/server.dart'; 19 | export 'package:conduit_open_api/src/v3/types.dart'; 20 | -------------------------------------------------------------------------------- /packages/open_api/mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: conduit_open_api 2 | docs_dir: doc/api 3 | 4 | nav: 5 | - Docs: "index.html" -------------------------------------------------------------------------------- /packages/open_api/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: conduit_open_api 2 | version: 5.1.5 3 | description: Data structures for OpenAPI (Swagger) specification. Reads and writes JSON specifications. 4 | home: https://www.theconduit.dev 5 | repository: https://github.com/conduit-dart/conduit 6 | issue_tracker: https://github.com/conduit-dart/conduit/issues 7 | 8 | environment: 9 | sdk: ">=3.7.0 <4.0.0" 10 | 11 | dependencies: 12 | conduit_codable: ^5.1.5 13 | meta: ^1.12.0 14 | 15 | dev_dependencies: 16 | lints: ^5.1.1 17 | test: ^1.25.2 18 | -------------------------------------------------------------------------------- /packages/open_api/pubspec_overrides.yaml: -------------------------------------------------------------------------------- 1 | dependency_overrides: 2 | conduit_codable: 3 | path: ../codable -------------------------------------------------------------------------------- /packages/password_hash/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://www.dartlang.org/tools/private-files.html 2 | 3 | # Files and directories created by pub 4 | .packages 5 | .pub/ 6 | build/ 7 | # If you're building an application, you may want to check-in your pubspec.lock 8 | pubspec.lock 9 | 10 | # Directory created by dartdoc 11 | # If you don't generate documentation locally you can remove this line. 12 | doc/api/ 13 | .idea/ 14 | 15 | .dart_tool/ 16 | .failed_tracker 17 | -------------------------------------------------------------------------------- /packages/password_hash/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 stable/kernel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/password_hash/README.md: -------------------------------------------------------------------------------- 1 | # conduit_password_hash 2 | 3 | [![Build Status](https://travis-ci.org/stablekernel/dart-password-hash.svg?branch=master)](https://travis-ci.org/stablekernel/dart-password-hash) 4 | 5 | Implements PBKDF2 algorithm for securely hashing passwords. 6 | 7 | Usage: 8 | 9 | ``` 10 | var generator = PBKDF2(); 11 | var salt = generateAsBase64String(); 12 | var hash = generator.generateKey("mytopsecretpassword", salt, 1000, 32); 13 | ``` 14 | 15 | 16 | -------------------------------------------------------------------------------- /packages/password_hash/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:lints/recommended.yaml 2 | -------------------------------------------------------------------------------- /packages/password_hash/lib/conduit_password_hash.dart: -------------------------------------------------------------------------------- 1 | export 'pbkdf2.dart'; 2 | export 'salt.dart'; 3 | -------------------------------------------------------------------------------- /packages/password_hash/lib/salt.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:math'; 3 | import 'dart:typed_data'; 4 | 5 | /// Generates a random salt of [length] bytes from a cryptographically secure random number generator. 6 | /// 7 | /// Each element of this list is a byte. 8 | List generate(int length) { 9 | final buffer = Uint8List(length); 10 | final rng = Random.secure(); 11 | for (var i = 0; i < length; i++) { 12 | buffer[i] = rng.nextInt(256); 13 | } 14 | 15 | return buffer; 16 | } 17 | 18 | /// Generates a random salt of [length] bytes from a cryptographically secure random number generator and encodes it to Base64. 19 | /// 20 | /// [length] is the number of bytes generated, not the [length] of the base64 encoded string returned. Decoding 21 | /// the base64 encoded string will yield [length] number of bytes. 22 | String generateAsBase64String(int length) { 23 | const encoder = Base64Encoder(); 24 | return encoder.convert(generate(length)); 25 | } 26 | -------------------------------------------------------------------------------- /packages/password_hash/mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: conduit_password_hash 2 | docs_dir: doc/api 3 | 4 | nav: 5 | - Docs: "index.html" -------------------------------------------------------------------------------- /packages/password_hash/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: conduit_password_hash 2 | version: 5.1.5 3 | description: PBKDF2 password hashing utility 4 | home: https://www.theconduit.dev 5 | repository: https://github.com/conduit-dart/conduit 6 | issue_tracker: https://github.com/conduit-dart/conduit/issues 7 | 8 | environment: 9 | sdk: ">=3.7.0 <4.0.0" 10 | 11 | dependencies: 12 | crypto: ^3.0.3 13 | 14 | dev_dependencies: 15 | lints: ^5.1.1 16 | test: ^1.25.2 17 | -------------------------------------------------------------------------------- /packages/postgresql/.gitignore: -------------------------------------------------------------------------------- 1 | # https://dart.dev/guides/libraries/private-files 2 | # Created by `dart pub` 3 | .dart_tool/ 4 | 5 | # Avoid committing pubspec.lock for library packages; see 6 | # https://dart.dev/guides/libraries/private-files#pubspeclock. 7 | pubspec.lock 8 | -------------------------------------------------------------------------------- /packages/postgresql/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018, Stable Kernel LLC 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 8 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 9 | 10 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 11 | -------------------------------------------------------------------------------- /packages/postgresql/README.md: -------------------------------------------------------------------------------- 1 | WIP -------------------------------------------------------------------------------- /packages/postgresql/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 | -------------------------------------------------------------------------------- /packages/postgresql/lib/conduit_postgresql.dart: -------------------------------------------------------------------------------- 1 | /// Support for doing something awesome. 2 | /// 3 | /// More dartdocs go here. 4 | library; 5 | 6 | export 'package:conduit_postgresql/src/postgresql_persistent_store.dart'; 7 | -------------------------------------------------------------------------------- /packages/postgresql/lib/src/builders/sort.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/conduit_core.dart'; 2 | 3 | import 'column.dart'; 4 | import 'table.dart'; 5 | 6 | class ColumnSortBuilder extends ColumnBuilder { 7 | ColumnSortBuilder(TableBuilder table, String key, QuerySortOrder order) 8 | : order = order == QuerySortOrder.ascending ? "ASC" : "DESC", 9 | super(table, table.entity.properties[key]); 10 | 11 | final String order; 12 | 13 | String get sqlOrderBy => "${sqlColumnName(withTableNamespace: true)} $order"; 14 | } 15 | 16 | class ColumnSortPredicateBuilder extends ColumnSortBuilder { 17 | ColumnSortPredicateBuilder(super.table, super.key, super.order) 18 | : _key = key; 19 | 20 | final String _key; 21 | 22 | @override 23 | String get sqlOrderBy => "$_key $order"; 24 | } 25 | -------------------------------------------------------------------------------- /packages/postgresql/lib/src/builders/value.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/conduit_core.dart'; 2 | import 'package:postgres/postgres.dart'; 3 | import 'column.dart'; 4 | import 'table.dart'; 5 | 6 | class ColumnValueBuilder extends ColumnBuilder { 7 | ColumnValueBuilder( 8 | TableBuilder super.table, 9 | ManagedPropertyDescription super.property, 10 | dynamic value, 11 | ) { 12 | this.value = TypedValue(ColumnBuilder.typeMap[property!.type!.kind]!, 13 | convertValueForStorage(value)); 14 | } 15 | 16 | late TypedValue value; 17 | } 18 | -------------------------------------------------------------------------------- /packages/postgresql/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: conduit_postgresql 2 | description: The postgresql ORM for conduit. 3 | version: 5.1.5 4 | home: https://www.theconduit.dev 5 | repository: https://github.com/conduit-dart/conduit 6 | issue_tracker: https://github.com/conduit-dart/conduit/issues 7 | 8 | environment: 9 | sdk: ">=3.7.0 <4.0.0" 10 | 11 | dependencies: 12 | collection: ^1.17.1 13 | conduit_core: ^5.1.5 14 | postgres: ^3.1.1 15 | 16 | dev_dependencies: 17 | lints: ^5.1.1 18 | test: ^1.25.2 19 | -------------------------------------------------------------------------------- /packages/postgresql/pubspec_overrides.yaml: -------------------------------------------------------------------------------- 1 | # melos_managed_dependency_overrides: conduit_codable,conduit_common,conduit_config,conduit_isolate_exec,conduit_open_api,conduit_password_hash,conduit_runtime 2 | dependency_overrides: 3 | conduit_codable: 4 | path: ../codable 5 | conduit_common: 6 | path: ../common 7 | conduit_config: 8 | path: ../config 9 | conduit_core: 10 | path: ../core 11 | conduit_isolate_exec: 12 | path: ../isolate_exec 13 | conduit_open_api: 14 | path: ../open_api 15 | conduit_password_hash: 16 | path: ../password_hash 17 | conduit_runtime: 18 | path: ../runtime 19 | -------------------------------------------------------------------------------- /packages/runtime/.gitignore: -------------------------------------------------------------------------------- 1 | # Files and directories created by pub 2 | .dart_tool/ 3 | .packages 4 | # Remove the following pattern if you wish to check in your lock file 5 | pubspec.lock 6 | 7 | # Conventional directory for build outputs 8 | build/ 9 | 10 | # Directory created by dartdoc 11 | doc/api/ 12 | 13 | *.iml 14 | .idea/ 15 | .failed_tracker 16 | -------------------------------------------------------------------------------- /packages/runtime/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019, Stable Kernel LLC 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 8 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 9 | 10 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 11 | -------------------------------------------------------------------------------- /packages/runtime/README.md: -------------------------------------------------------------------------------- 1 | Generates a replica of a application package and it's dependencies that strips dart:mirror usage so that it may be compiled. -------------------------------------------------------------------------------- /packages/runtime/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:lints/recommended.yaml -------------------------------------------------------------------------------- /packages/runtime/dart_test.yaml: -------------------------------------------------------------------------------- 1 | timeout: 120s -------------------------------------------------------------------------------- /packages/runtime/lib/src/compiler.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:conduit_runtime/runtime.dart'; 4 | 5 | abstract class Compiler { 6 | /// Modifies a package on the filesystem in order to remove dart:mirrors from the package. 7 | /// 8 | /// A copy of this compiler's package will be written to [destinationDirectory]. 9 | /// This method is overridden to modify the contents of that directory 10 | /// to remove all uses of dart:mirrors. 11 | /// 12 | /// Packages should export their [Compiler] in their main library file and only 13 | /// import mirrors in files directly or transitively imported by the Compiler file. 14 | /// This method should remove that export statement and therefore remove all transitive mirror imports. 15 | void deflectPackage(Directory destinationDirectory); 16 | 17 | /// Returns a map of runtime objects that can be used at runtime while running in mirrored mode. 18 | Map compile(MirrorContext context); 19 | 20 | void didFinishPackageGeneration(BuildContext context) {} 21 | 22 | List getUrisToResolve(BuildContext context) => []; 23 | } 24 | 25 | /// Runtimes that generate source code implement this method. 26 | abstract class SourceCompiler { 27 | /// The source code, including directives, that declare a class that is equivalent in behavior to this runtime. 28 | Future compile(BuildContext ctx) async { 29 | throw UnimplementedError(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/runtime/lib/src/exceptions.dart: -------------------------------------------------------------------------------- 1 | class TypeCoercionException implements Exception { 2 | TypeCoercionException(this.expectedType, this.actualType); 3 | 4 | final Type expectedType; 5 | final Type actualType; 6 | 7 | @override 8 | String toString() { 9 | return "input is not expected type '$expectedType' (input is '$actualType')"; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/runtime/mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: conduit_runtime 2 | docs_dir: doc/api 3 | 4 | nav: 5 | - Docs: "index.html" -------------------------------------------------------------------------------- /packages/runtime/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: conduit_runtime 2 | version: 5.1.5 3 | description: Provides behaviors and base types for packages that can use mirrors and be AOT compiled. 4 | home: https://www.theconduit.dev 5 | repository: https://github.com/conduit-dart/conduit 6 | issue_tracker: https://github.com/conduit-dart/conduit/issues 7 | 8 | environment: 9 | sdk: ">=3.7.0 <4.0.0" 10 | 11 | dependencies: 12 | analyzer: ^7.1.0 13 | args: ^2.0.0 14 | conduit_isolate_exec: ^5.1.5 15 | io: ^1.0.4 16 | package_config: ^2.1.0 17 | path: ^1.9.0 18 | pubspec_parse: ^1.5.0 19 | yaml: ^3.1.2 20 | 21 | dev_dependencies: 22 | fs_test_agent: 23 | path: ../fs_test_agent 24 | lints: ^5.1.1 25 | test: ^1.25.2 26 | -------------------------------------------------------------------------------- /packages/runtime/pubspec_overrides.yaml: -------------------------------------------------------------------------------- 1 | dependency_overrides: 2 | conduit_isolate_exec: 3 | path: ../isolate_exec 4 | fs_test_agent: 5 | path: ../fs_test_agent 6 | -------------------------------------------------------------------------------- /packages/runtime/test/.pubignore: -------------------------------------------------------------------------------- 1 | test_packages -------------------------------------------------------------------------------- /packages/runtime/test/project_analyzer_test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:conduit_runtime/src/analyzer.dart'; 4 | import 'package:fs_test_agent/dart_project_agent.dart'; 5 | import 'package:test/test.dart'; 6 | 7 | void main() { 8 | test("ProjectAnalyzer can find a specific class declaration in project", 9 | () async { 10 | final terminal = DartProjectAgent.existing( 11 | Directory.current.uri 12 | .resolve("../") 13 | .resolve("runtime_test_packages/") 14 | .resolve("application/"), 15 | ); 16 | await terminal.getDependencies(); 17 | 18 | final path = terminal.workingDirectory.absolute.uri; 19 | final p = CodeAnalyzer(path); 20 | final klass = p.getClassFromFile( 21 | "ConsumerSubclass", 22 | terminal.libraryDirectory.absolute.uri.resolve("application.dart"), 23 | ); 24 | expect(klass, isNotNull); 25 | expect(klass!.name.value(), "ConsumerSubclass"); 26 | expect(klass.extendsClause!.superclass.name2.toString(), "Consumer"); 27 | }); 28 | } 29 | -------------------------------------------------------------------------------- /packages/runtime_test_packages/application/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:lints/recommended.yaml 2 | -------------------------------------------------------------------------------- /packages/runtime_test_packages/application/bin/main.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:application/application.dart'; 4 | import 'package:dependency/dependency.dart'; 5 | 6 | void main() { 7 | const foo = String.fromEnvironment("FOO"); 8 | // ignore: avoid_print 9 | print( 10 | json.encode({ 11 | "Consumer": Consumer().message, 12 | "ConsumerSubclass": ConsumerSubclass().message, 13 | "ConsumerScript": ConsumerScript().message, 14 | ...foo.isNotEmpty ? {"FOO": foo} : {}, 15 | }), 16 | ); 17 | } 18 | 19 | class ConsumerScript extends Consumer {} 20 | -------------------------------------------------------------------------------- /packages/runtime_test_packages/application/lib/application.dart: -------------------------------------------------------------------------------- 1 | /// Support for doing something awesome. 2 | /// 3 | /// More dartdocs go here. 4 | library application; 5 | 6 | import 'package:dependency/dependency.dart'; 7 | 8 | import 'src/file.dart'; // ignore: unused_import 9 | 10 | class ConsumerSubclass extends Consumer {} 11 | -------------------------------------------------------------------------------- /packages/runtime_test_packages/application/lib/src/file.dart: -------------------------------------------------------------------------------- 1 | import '../application.dart'; //ignore: unused_import 2 | -------------------------------------------------------------------------------- /packages/runtime_test_packages/application/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: application 2 | description: A starting point for Dart libraries or applications. 3 | version: 1.0.0 4 | publish_to: none 5 | 6 | environment: 7 | sdk: ">=3.7.0 <4.0.0" 8 | 9 | dependencies: 10 | dependency: 11 | path: ../dependency/ 12 | meta: ^1.3.0 13 | 14 | dev_dependencies: 15 | lints: ^5.1.1 16 | test: ^1.25.2 17 | -------------------------------------------------------------------------------- /packages/runtime_test_packages/application/pubspec_overrides.yaml: -------------------------------------------------------------------------------- 1 | # melos_managed_dependency_overrides: conduit_isolate_exec,conduit_runtime,dependency 2 | dependency_overrides: 3 | conduit_isolate_exec: 4 | path: ../../isolate_exec 5 | conduit_runtime: 6 | path: ../../runtime 7 | dependency: 8 | path: ../dependency 9 | -------------------------------------------------------------------------------- /packages/runtime_test_packages/dependency/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:lints/recommended.yaml 2 | -------------------------------------------------------------------------------- /packages/runtime_test_packages/dependency/lib/dependency.dart: -------------------------------------------------------------------------------- 1 | /// Support for doing something awesome. 2 | /// 3 | /// More dartdocs go here. 4 | library dependency; 5 | 6 | export 'src/compiler.dart'; 7 | export 'src/dependency_base.dart'; 8 | -------------------------------------------------------------------------------- /packages/runtime_test_packages/dependency/lib/src/compiler.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | import 'dart:mirrors'; 3 | 4 | import 'package:conduit_runtime/runtime.dart'; 5 | 6 | import '../dependency.dart'; 7 | 8 | class DependencyCompiler extends Compiler { 9 | @override 10 | Map compile(MirrorContext context) { 11 | return Map.fromEntries( 12 | context.getSubclassesOf(Consumer).map((c) { 13 | return MapEntry( 14 | MirrorSystem.getName(c.simpleName), 15 | ConsumerRuntimeImpl(), 16 | ); 17 | }), 18 | )..addAll({"Consumer": ConsumerRuntimeImpl()}); 19 | } 20 | 21 | @override 22 | void deflectPackage(Directory destinationDirectory) { 23 | final libFile = File.fromUri( 24 | destinationDirectory.uri.resolve("lib/").resolve("dependency.dart"), 25 | ); 26 | var contents = libFile.readAsStringSync(); 27 | contents = contents.replaceFirst("export 'src/compiler.dart';", ""); 28 | libFile.writeAsStringSync(contents); 29 | } 30 | } 31 | 32 | class ConsumerRuntimeImpl extends ConsumerRuntime implements SourceCompiler { 33 | @override 34 | String get message => "mirrored"; 35 | 36 | @override 37 | Future compile(BuildContext ctx) async => """ 38 | import 'package:dependency/dependency.dart'; 39 | 40 | final instance = ConsumerRuntimeImpl(); 41 | 42 | class ConsumerRuntimeImpl extends ConsumerRuntime { 43 | @override 44 | String get message => "generated"; 45 | } 46 | """; 47 | } 48 | -------------------------------------------------------------------------------- /packages/runtime_test_packages/dependency/lib/src/dependency_base.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_runtime/runtime.dart'; 2 | 3 | class Consumer { 4 | String get message => 5 | (RuntimeContext.current[runtimeType] as ConsumerRuntime).message; 6 | } 7 | 8 | abstract class ConsumerRuntime { 9 | String get message; 10 | } 11 | -------------------------------------------------------------------------------- /packages/runtime_test_packages/dependency/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: dependency 2 | description: A starting point for Dart libraries or applications. 3 | version: 1.0.0 4 | publish_to: none 5 | 6 | environment: 7 | sdk: ">=3.7.0 <4.0.0" 8 | 9 | dependencies: 10 | conduit_runtime: 11 | path: ../../runtime 12 | 13 | dev_dependencies: 14 | lints: ^5.1.1 15 | test: ^1.25.2 16 | -------------------------------------------------------------------------------- /packages/runtime_test_packages/dependency/pubspec_overrides.yaml: -------------------------------------------------------------------------------- 1 | # melos_managed_dependency_overrides: conduit_isolate_exec,conduit_runtime 2 | dependency_overrides: 3 | conduit_isolate_exec: 4 | path: ../../isolate_exec 5 | conduit_runtime: 6 | path: ../../runtime 7 | -------------------------------------------------------------------------------- /packages/test_harness/.gitignore: -------------------------------------------------------------------------------- 1 | .failed_tracker 2 | -------------------------------------------------------------------------------- /packages/test_harness/LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2018, stable/kernel 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /packages/test_harness/README.md: -------------------------------------------------------------------------------- 1 | Test framework for [conduit](https://www.theconduit.dev/) applications. This package is included as a `dev_dependency` of `conduit` applications. 2 | 3 | The documentation for this package is available at [https://www.theconduit.dev/docs/testing/](https://www.theconduit.dev/docs/testing/). 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/test_harness/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:lints/recommended.yaml 2 | 3 | linter: 4 | rules: 5 | use_string_in_part_of_directives: false -------------------------------------------------------------------------------- /packages/test_harness/dart_test.yaml: -------------------------------------------------------------------------------- 1 | timeout: 120s -------------------------------------------------------------------------------- /packages/test_harness/example/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/conduit_core.dart'; 2 | import 'package:conduit_test/conduit_test.dart'; 3 | import 'package:test/test.dart'; 4 | 5 | void main() { 6 | final harness = TestHarness()..install(); 7 | 8 | test("GET /example returns simple map", () async { 9 | final response = await harness.agent!.get("/example"); 10 | expectResponse(response, 200, body: {"key": "value"}); 11 | }); 12 | } 13 | 14 | class App extends ApplicationChannel { 15 | @override 16 | Controller get entryPoint { 17 | final router = Router(); 18 | router 19 | .route("/example") 20 | .linkFunction((req) async => Response.ok({"key": "value"})); 21 | return router; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/test_harness/lib/conduit_test.dart: -------------------------------------------------------------------------------- 1 | /// Testing utilities for Conduit applications 2 | /// 3 | /// This library should be imported in test scripts. It should not be imported in application code. 4 | /// 5 | /// Example: 6 | /// 7 | /// import 'package:test/test.dart'; 8 | /// import 'package:conduit_core/conduit_core.dart'; 9 | /// import 'package:conduit_core/test.dart'; 10 | /// 11 | /// void main() { 12 | /// test("...", () async => ...); 13 | /// } 14 | library; 15 | 16 | export 'package:conduit_test/src/agent.dart'; 17 | export 'package:conduit_test/src/auth_harness.dart'; 18 | export 'package:conduit_test/src/db_harness.dart'; 19 | export 'package:conduit_test/src/harness.dart'; 20 | export 'package:conduit_test/src/matchers.dart'; 21 | export 'package:conduit_test/src/mock_server.dart'; 22 | -------------------------------------------------------------------------------- /packages/test_harness/lib/src/body_matcher.dart: -------------------------------------------------------------------------------- 1 | import 'package:matcher/matcher.dart'; 2 | import 'matchers.dart'; 3 | 4 | /// A test matcher that matches an HTTP response body. 5 | /// 6 | /// See [hasBody] or [hasResponse] for more details. 7 | class HTTPBodyMatcher extends Matcher { 8 | HTTPBodyMatcher(dynamic matcher) { 9 | if (matcher is Matcher) { 10 | contentMatcher = matcher; 11 | } else { 12 | contentMatcher = equals(matcher); 13 | } 14 | } 15 | 16 | Matcher? contentMatcher; 17 | 18 | @override 19 | bool matches(dynamic item, Map matchState) { 20 | if (!contentMatcher!.matches(item, matchState)) { 21 | return false; 22 | } 23 | 24 | return true; 25 | } 26 | 27 | @override 28 | Description describe(Description description) { 29 | description.add("- Body after decoding must be:\n\n "); 30 | description.addDescriptionOf(contentMatcher); 31 | 32 | return description; 33 | } 34 | 35 | @override 36 | Description describeMismatch(dynamic item, Description mismatchDescription, 37 | Map matchState, bool verbose) { 38 | mismatchDescription.add("the body differs for the following reasons:\n"); 39 | 40 | contentMatcher! 41 | .describeMismatch(item, mismatchDescription, matchState, verbose); 42 | 43 | return mismatchDescription; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /packages/test_harness/mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: conduit_test 2 | docs_dir: doc/api 3 | 4 | nav: 5 | - Docs: "index.html" -------------------------------------------------------------------------------- /packages/test_harness/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: conduit_test 2 | version: 5.1.5 3 | description: Utilities for writing automated tests for Conduit applications 4 | home: https://www.theconduit.dev 5 | repository: https://github.com/conduit-dart/conduit 6 | issue_tracker: https://github.com/conduit-dart/conduit/issues 7 | 8 | environment: 9 | sdk: ">=3.7.0 <4.0.0" 10 | 11 | dependencies: 12 | test: ^1.25.2 13 | matcher: ^0.12.16+1 14 | conduit_core: ^5.1.5 15 | 16 | dev_dependencies: 17 | conduit_postgresql: 18 | path: ../postgresql 19 | lints: ^5.1.1 20 | test_core: ^0.6.0 21 | -------------------------------------------------------------------------------- /packages/test_harness/pubspec_overrides.yaml: -------------------------------------------------------------------------------- 1 | # melos_managed_dependency_overrides: conduit_postgresql 2 | dependency_overrides: 3 | conduit_codable: 4 | path: ../codable 5 | conduit_common: 6 | path: ../common 7 | conduit_config: 8 | path: ../config 9 | conduit_core: 10 | path: ../core 11 | conduit_isolate_exec: 12 | path: ../isolate_exec 13 | conduit_open_api: 14 | path: ../open_api 15 | conduit_password_hash: 16 | path: ../password_hash 17 | conduit_postgresql: 18 | path: ../postgresql 19 | conduit_runtime: 20 | path: ../runtime 21 | -------------------------------------------------------------------------------- /packages/test_harness/test/response_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:conduit_core/conduit_core.dart'; 2 | import 'package:conduit_test/conduit_test.dart'; 3 | import 'package:conduit_test/src/body_matcher.dart'; 4 | import 'package:conduit_test/src/response_matcher.dart'; 5 | import 'package:test/test.dart'; 6 | import 'package:test_core/src/util/io.dart'; 7 | 8 | void main() async { 9 | late MockHTTPServer server; 10 | late Agent agent; 11 | 12 | setUpAll(() async { 13 | server = await getUnusedPort(MockHTTPServer.new); 14 | agent = Agent.onPort(server.port); 15 | await server.open(); 16 | }); 17 | 18 | tearDown(() async { 19 | await server.close(); 20 | }); 21 | 22 | test("Mismatched body shows decoded body and teh reason for the mismatch", 23 | () async { 24 | server.queueHandler((req) { 25 | return Response.ok({"key": "value"}); 26 | }); 27 | 28 | final response = await agent.get("/"); 29 | final responseMatcher = HTTPResponseMatcher( 30 | 200, null, HTTPBodyMatcher(equals({"notkey": "bar"}))); 31 | expect(responseMatcher.matches(response, {}), false); 32 | 33 | final desc = StringDescription(); 34 | responseMatcher.describe(desc); 35 | expect(desc.toString(), contains("Status code must be 200")); 36 | expect(desc.toString(), contains("{'notkey': 'bar'}")); 37 | 38 | final actual = response.toString(); 39 | expect(actual, contains("Status code is 200")); 40 | expect(actual, contains("{key: value}")); 41 | }); 42 | } 43 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: conduit_workspace 2 | version: 5.1.5 3 | home: https://www.theconduit.dev 4 | repository: https://github.com/conduit-dart/conduit 5 | issue_tracker: https://github.com/conduit-dart/conduit/issues 6 | 7 | environment: 8 | sdk: ">=3.7.0 <4.0.0" 9 | 10 | dev_dependencies: 11 | melos: ^6.3.2 12 | -------------------------------------------------------------------------------- /utils/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: utils 2 | 3 | environment: 4 | sdk: ">=3.7.0 <4.0.0" 5 | 6 | dependencies: 7 | test: ^1.25.2 8 | -------------------------------------------------------------------------------- /utils/unused_port.dart: -------------------------------------------------------------------------------- 1 | import 'package:test_core/src/util/io.dart'; 2 | 3 | void main() async { 4 | print(await getUnusedPort((port) => port)); 5 | } 6 | --------------------------------------------------------------------------------