├── .github └── workflows │ ├── audit.yml │ ├── ci.yml │ ├── docdeploy.yml │ └── release.yml ├── .gitignore ├── CHANGELOG.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── annotation ├── Cargo.toml ├── rust-toolchain.toml └── src │ └── lib.rs ├── cli ├── Cargo.toml ├── README.md ├── data │ └── tests │ │ ├── constraints_config.toml │ │ ├── decorators_config.toml │ │ ├── default_config.toml │ │ ├── empty_config.toml │ │ ├── go_config.toml │ │ ├── mappings_config.toml │ │ └── swift_prefix_config.toml ├── rust-toolchain.toml └── src │ ├── args.rs │ ├── config.rs │ ├── main.rs │ ├── parse.rs │ └── writer.rs ├── core ├── Cargo.toml ├── README.md ├── data │ └── tests │ │ ├── .gitignore │ │ ├── README.md │ │ ├── algebraic_enum_decorator │ │ ├── input.rs │ │ └── output.swift │ │ ├── anonymous_struct_with_rename │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── can_apply_prefix_correctly │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── can_generate_algebraic_enum │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── can_generate_algebraic_enum_with_skipped_variants │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── can_generate_anonymous_struct_with_skipped_fields │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── can_generate_bare_string_enum │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── can_generate_const │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.py │ │ └── output.ts │ │ ├── can_generate_double_option_pattern │ │ ├── input.rs │ │ └── output.ts │ │ ├── can_generate_empty_algebraic_enum │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── can_generate_generic_enum │ │ ├── input.rs │ │ ├── output.kt │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── can_generate_generic_struct │ │ ├── input.rs │ │ ├── output.kt │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── can_generate_generic_type_alias │ │ ├── input.rs │ │ ├── output.kt │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── can_generate_readonly_fields │ │ ├── input.rs │ │ └── output.ts │ │ ├── can_generate_simple_enum │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── can_generate_simple_struct_with_a_comment │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── can_generate_slice_of_user_type │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── can_generate_struct_with_skipped_fields │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── can_generate_unit_structs │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── can_handle_anonymous_struct │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── can_handle_quote_in_serde_rename │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── can_handle_serde_rename │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── can_handle_serde_rename_all │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── can_handle_serde_rename_on_top_level │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── can_handle_unit_type │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── can_override_types │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── can_recognize_types_inside_modules │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── const_enum_decorator │ │ ├── input.rs │ │ └── output.swift │ │ ├── enum_is_properly_named_with_serde_overrides │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── excluded_by_target_os │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── excluded_by_target_os_full_module │ │ ├── input.rs │ │ └── output.swift │ │ ├── generate_types │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── generate_types_with_keywords │ │ ├── input.rs │ │ └── output.swift │ │ ├── generates_configured_generic_constraints │ │ ├── input.rs │ │ └── output.swift │ │ ├── generates_empty_structs_and_initializers │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── generic_struct_with_constraints_and_decorators │ │ ├── input.rs │ │ └── output.swift │ │ ├── kebab_case_rename │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── orders_types │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ └── output.swift │ │ ├── recursive_enum_decorator │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── resolves_qualified_type │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── serde_rename_references │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── serialize_anonymous_field_as │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── serialize_field_as │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── serialize_type_alias │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── smart_pointers │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── struct_decorator │ │ ├── input.rs │ │ ├── output.kt │ │ └── output.swift │ │ ├── test_algebraic_enum_case_name_support │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── test_custom_serialize_deserialize_functions │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.py │ │ └── output.ts │ │ ├── test_default_decorators │ │ ├── input.rs │ │ └── output.swift │ │ ├── test_default_generic_constraints │ │ ├── input.rs │ │ └── output.swift │ │ ├── test_generate_char │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── test_i54_u53_type │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── test_optional_type_alias │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── test_serde_default_struct │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── test_serde_iso8601 │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── test_serde_url │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── test_serialized_as │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── test_serialized_as_tuple │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── test_simple_enum_case_name_support │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── test_type_alias │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ ├── uppercase_go_acronyms │ │ ├── input.rs │ │ └── output.go │ │ ├── use_correct_decoded_variable_name │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts │ │ └── use_correct_integer_types │ │ ├── input.rs │ │ ├── output.go │ │ ├── output.kt │ │ ├── output.py │ │ ├── output.scala │ │ ├── output.swift │ │ └── output.ts ├── rust-toolchain.toml ├── src │ ├── context.rs │ ├── language │ │ ├── go.rs │ │ ├── kotlin.rs │ │ ├── mod.rs │ │ ├── python.rs │ │ ├── scala.rs │ │ ├── swift.rs │ │ └── typescript.rs │ ├── lib.rs │ ├── parser.rs │ ├── reconcile.rs │ ├── rename.rs │ ├── rust_types.rs │ ├── target_os_check.rs │ ├── topsort.rs │ └── visitors.rs └── tests │ ├── agnostic_tests.rs │ └── snapshot_tests.rs ├── docs ├── .gitignore ├── README.md ├── book.toml └── src │ ├── SUMMARY.md │ ├── contributing.md │ ├── installation.md │ ├── overview.md │ └── usage │ ├── annotations.md │ ├── configuration.md │ ├── target_os.md │ └── usage.md ├── flake.lock ├── flake.nix ├── lib ├── Cargo.toml ├── README.md ├── rust-toolchain.toml └── src │ ├── integer.rs │ ├── json_date.rs │ └── lib.rs ├── rust-toolchain.toml └── tests ├── .gitignore ├── data └── determinism-base.rs └── justfile /.github/workflows/audit.yml: -------------------------------------------------------------------------------- 1 | name: Security audit 2 | on: 3 | schedule: 4 | - cron: '0 0 * * 0' 5 | push: 6 | paths: 7 | - '**/Cargo.toml' 8 | - '**/Cargo.lock' 9 | pull_request: 10 | 11 | jobs: 12 | audit: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v2 16 | - uses: actions-rs/audit-check@v1 17 | with: 18 | token: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /.github/workflows/docdeploy.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - main 5 | 6 | name: Deploy Documentation 7 | 8 | jobs: 9 | deploy-docs: 10 | name: Deploy Documentation 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v2 14 | - uses: actions-rust-lang/setup-rust-toolchain@v1 15 | with: 16 | toolchain: stable 17 | - run: (test -x $HOME/.cargo/bin/mdbook || cargo install mdbook) 18 | - run: mdbook build docs 19 | - uses: JamesIves/github-pages-deploy-action@4.1.7 20 | with: 21 | branch: gh-pages # The branch the action should deploy to. 22 | folder: docs/book # The folder the action should deploy. 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | debug/ 4 | target/ 5 | dist/ 6 | 7 | # These are backup files generated by rustfmt 8 | **/*.rs.bk 9 | 10 | # MSVC Windows builds of rustc generate these, which store debugging information 11 | *.pdb 12 | 13 | # IDE specific files 14 | .idea/ 15 | .vscode/ 16 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = ["annotation", "cli", "core", "lib"] 3 | resolver = "2" 4 | 5 | # Config for 'cargo dist' 6 | [workspace.metadata.dist] 7 | # The preferred cargo-dist version to use in CI (Cargo.toml SemVer syntax) 8 | cargo-dist-version = "0.0.4" 9 | # The preferred Rust toolchain to use in CI (rustup toolchain syntax) 10 | # CI backends to support (see 'cargo dist generate-ci') 11 | ci = ["github"] 12 | # The installers to generate for each app 13 | installers = ["shell", "powershell"] 14 | # Target platforms to build apps for (Rust target-triple syntax) 15 | targets = [ 16 | "x86_64-unknown-linux-gnu", 17 | "x86_64-apple-darwin", 18 | "x86_64-pc-windows-msvc", 19 | "aarch64-apple-darwin", 20 | ] 21 | 22 | [profile.test] 23 | 24 | 25 | [profile.release] 26 | lto = 'thin' 27 | opt-level = 2 28 | debug-assertions = false 29 | codegen-units = 16 30 | incremental = true 31 | 32 | # The profile that 'cargo dist' will build with 33 | [profile.dist] 34 | inherits = "release" 35 | 36 | [workspace.dependencies] 37 | log = "0.4" 38 | flexi_logger = "0.28" 39 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 1Password 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 | -------------------------------------------------------------------------------- /annotation/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "typeshare-annotation" 3 | version = "1.0.4" 4 | edition = "2021" 5 | license = "MIT OR Apache-2.0" 6 | description = "The annotation used to mark types for typeshare" 7 | repository = "https://github.com/1Password/typeshare" 8 | 9 | [lib] 10 | proc-macro = true 11 | 12 | [dependencies] 13 | syn = { version = "2", features = ["parsing", "proc-macro"] } 14 | quote = "1.0" 15 | -------------------------------------------------------------------------------- /annotation/rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "stable" 3 | components = ["clippy"] 4 | profile = "default" 5 | -------------------------------------------------------------------------------- /cli/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "typeshare-cli" 3 | version = "1.13.2" 4 | edition = "2021" 5 | description = "Command Line Tool for generating language files with typeshare" 6 | license = "MIT OR Apache-2.0" 7 | repository = "https://github.com/1Password/typeshare" 8 | readme = "README.md" 9 | 10 | [[bin]] 11 | name = "typeshare" 12 | path = "src/main.rs" 13 | 14 | [features] 15 | go = [] 16 | python = [] 17 | 18 | [dependencies] 19 | clap = { version = "4.5", features = [ 20 | "cargo", 21 | "derive", 22 | "unicode", 23 | "wrap_help", 24 | ] } 25 | ignore = "0.4" 26 | once_cell = "1" 27 | serde = { version = "1", features = ["derive"] } 28 | toml = "0.8" 29 | typeshare-core = { path = "../core", version = "=1.13.2" } 30 | log.workspace = true 31 | flexi_logger.workspace = true 32 | anyhow = "1" 33 | clap_complete = "4.5.32" 34 | crossbeam = "0.8" 35 | -------------------------------------------------------------------------------- /cli/README.md: -------------------------------------------------------------------------------- 1 | # typeshare 2 | 3 | CLI built on top of `typeshare-core`. Generate code in different languages from Rust type definitions for FFI interop. 4 | 5 | ## Usage 6 | 7 | ``` 8 | cargo install typeshare 9 | typeshare --lang=typescript some/file.rs 10 | typeshare --lang=swift some/file.rs 11 | typeshare --lang=kotlin --java-package=com.some.package.name some/file.rs 12 | typeshare --lang=scala --scala-package=com.some.package.name some/file.rs 13 | ``` 14 | 15 | ## Generating FFI bindings 16 | 17 | Include the typeshare annotation to generate a FFI binding for that function. Available languages are `kotlin` and `swift`. 18 | 19 | ```rust 20 | #[typeshare(kotlin = "generateTotp", swift = "generate_totp")] 21 | pub fn generate_totp(request: TotpGeneratorRequest) -> Result` 22 | ``` 23 | 24 | Until the build system is changed to generate bindings during a build, it must be done manually and committed into the repo. FFI bindings are generated into the `ffi/src/generated.rs` file. 25 | 26 | To generate all FFI bindings run `make ffi`. When adding or removing FFI bindings, don't forget to include the changes in the `Makefile`. 27 | -------------------------------------------------------------------------------- /cli/data/tests/constraints_config.toml: -------------------------------------------------------------------------------- 1 | [swift] 2 | default_generic_constraints = ["Sendable"] -------------------------------------------------------------------------------- /cli/data/tests/decorators_config.toml: -------------------------------------------------------------------------------- 1 | [swift] 2 | default_decorators = ["Sendable"] -------------------------------------------------------------------------------- /cli/data/tests/default_config.toml: -------------------------------------------------------------------------------- 1 | [swift] 2 | prefix = '' 3 | 4 | [kotlin] 5 | module_name = '' 6 | package = '' 7 | 8 | [scala] 9 | module_name = '' 10 | package = '' 11 | 12 | [typescript] 13 | 14 | [go] 15 | 16 | [swift.type_mappings] 17 | 18 | [typescript.type_mappings] 19 | 20 | [kotlin.type_mappings] 21 | 22 | [scala.type_mappings] -------------------------------------------------------------------------------- /cli/data/tests/empty_config.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1Password/typeshare/8c8041c37ab8887981a3c37133c736f424653d88/cli/data/tests/empty_config.toml -------------------------------------------------------------------------------- /cli/data/tests/go_config.toml: -------------------------------------------------------------------------------- 1 | [go] 2 | package="testPackage" -------------------------------------------------------------------------------- /cli/data/tests/mappings_config.toml: -------------------------------------------------------------------------------- 1 | [swift.type_mappings] 2 | "DateTime" = "Date" 3 | 4 | [typescript.type_mappings] 5 | "DateTime" = "string" 6 | 7 | [kotlin.type_mappings] 8 | "DateTime" = "String" 9 | 10 | [scala.type_mappings] 11 | "DateTime" = "String" 12 | 13 | [go.type_mappings] 14 | "DateTime" = "string" 15 | 16 | [python.type_mappings] 17 | "DateTime" = "datetime" 18 | "Url" = "AnyUrl" 19 | -------------------------------------------------------------------------------- /cli/data/tests/swift_prefix_config.toml: -------------------------------------------------------------------------------- 1 | [swift] 2 | prefix = 'test' -------------------------------------------------------------------------------- /cli/rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "stable" 3 | components = ["clippy"] 4 | profile = "default" 5 | -------------------------------------------------------------------------------- /core/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "typeshare-core" 3 | version = "1.13.2" 4 | license = "MIT OR Apache-2.0" 5 | edition = "2021" 6 | description = "The code generator used by Typeshare's command line tool" 7 | repository = "https://github.com/1Password/typeshare" 8 | 9 | [dependencies] 10 | proc-macro2 = "1" 11 | quote = "1" 12 | syn = { version = "2", features = ["full", "visit"] } 13 | thiserror = "1" 14 | itertools = "0.12" 15 | lazy_format = "2" 16 | joinery = "2" 17 | topological-sort = { version = "0.2.2"} 18 | convert_case = { version = "0.6.0"} 19 | log.workspace = true 20 | flexi_logger.workspace = true 21 | 22 | [dev-dependencies] 23 | expect-test = "1.5" 24 | once_cell = "1" 25 | cool_asserts = "2" 26 | syn = { version = "2", features = ["full", "visit", "extra-traits"] } 27 | anyhow = "1" 28 | -------------------------------------------------------------------------------- /core/data/tests/.gitignore: -------------------------------------------------------------------------------- 1 | **/output_formatted.* 2 | -------------------------------------------------------------------------------- /core/data/tests/README.md: -------------------------------------------------------------------------------- 1 | # typeshare snapshot tests 2 | 3 | This folder stores the auto-generated data for typeshare's snapshot tests. These are used to verify the correctness of typeshare's output. 4 | 5 | See the [the testing section](../../README.md#testing) of the main README for more details. 6 | -------------------------------------------------------------------------------- /core/data/tests/algebraic_enum_decorator/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | #[serde(tag = "type", content = "content")] 3 | pub enum BestHockeyTeams { 4 | PittsburghPenguins, 5 | Lies(String), 6 | } 7 | #[typeshare(swift = "Equatable")] 8 | #[serde(tag = "type", content = "content")] 9 | pub enum BestHockeyTeams1 { 10 | PittsburghPenguins, 11 | Lies(String), 12 | } 13 | 14 | #[typeshare(swift = "Equatable, Codable, Comparable, Hashable")] 15 | #[serde(tag = "type", content = "content")] 16 | pub enum BestHockeyTeams2 { 17 | PittsburghPenguins, 18 | Lies(String), 19 | } 20 | 21 | #[typeshare(kotlin = "idk")] 22 | #[serde(tag = "type", content = "content")] 23 | pub enum BestHockeyTeams3 { 24 | PittsburghPenguins, 25 | Lies(String), 26 | } 27 | 28 | #[typeshare(swift = "Equatable", swift = "Hashable")] 29 | #[serde(tag = "type", content = "content")] 30 | pub enum BestHockeyTeams4 { 31 | PittsburghPenguins, 32 | Lies(String), 33 | } 34 | -------------------------------------------------------------------------------- /core/data/tests/anonymous_struct_with_rename/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] 3 | #[serde(tag = "type", content = "content", rename_all = "camelCase")] 4 | pub enum AnonymousStructWithRename { 5 | List { 6 | list: Vec, 7 | }, 8 | LongFieldNames { 9 | // Note that the `#[serde(rename_all)]` attribute applied to the overall enum 10 | // does not apply to these anonymous struct variant fields. 11 | // 12 | // These fields should rename in snake_case. 13 | some_long_field_name: String, 14 | and: bool, 15 | but_one_more: Vec, 16 | }, 17 | #[serde(rename_all = "kebab-case")] 18 | KebabCase { 19 | // Similar to the above, the `#[serde(rename_all)]` attribute applied to 20 | // this enum variant will apply, rather than the one applied to the overall 21 | // enum. 22 | anotherList: Vec, 23 | // However, this even more specific `#[serde(rename)]` attribute should 24 | // cause this field to remain in camelCase. 25 | #[serde(rename = "camelCaseStringField")] 26 | camelCaseStringField: String, 27 | something_else: bool, 28 | }, 29 | } 30 | -------------------------------------------------------------------------------- /core/data/tests/anonymous_struct_with_rename/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | /// Generated type representing the anonymous struct variant `List` of the `AnonymousStructWithRename` Rust enum 7 | @Serializable 8 | data class AnonymousStructWithRenameListInner ( 9 | val list: List 10 | ) 11 | 12 | /// Generated type representing the anonymous struct variant `LongFieldNames` of the `AnonymousStructWithRename` Rust enum 13 | @Serializable 14 | data class AnonymousStructWithRenameLongFieldNamesInner ( 15 | val some_long_field_name: String, 16 | val and: Boolean, 17 | val but_one_more: List 18 | ) 19 | 20 | /// Generated type representing the anonymous struct variant `KebabCase` of the `AnonymousStructWithRename` Rust enum 21 | @Serializable 22 | data class AnonymousStructWithRenameKebabCaseInner ( 23 | @SerialName("another-list") 24 | val another_list: List, 25 | @SerialName("camelCaseStringField") 26 | val camelCaseStringField: String, 27 | @SerialName("something-else") 28 | val something_else: Boolean 29 | ) 30 | 31 | @Serializable 32 | sealed class AnonymousStructWithRename { 33 | @Serializable 34 | @SerialName("list") 35 | data class List(val content: AnonymousStructWithRenameListInner): AnonymousStructWithRename() 36 | @Serializable 37 | @SerialName("longFieldNames") 38 | data class LongFieldNames(val content: AnonymousStructWithRenameLongFieldNamesInner): AnonymousStructWithRename() 39 | @Serializable 40 | @SerialName("kebabCase") 41 | data class KebabCase(val content: AnonymousStructWithRenameKebabCaseInner): AnonymousStructWithRename() 42 | } 43 | 44 | -------------------------------------------------------------------------------- /core/data/tests/anonymous_struct_with_rename/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package onepassword { 4 | 5 | // Generated type representing the anonymous struct variant `List` of the `AnonymousStructWithRename` Rust enum 6 | case class AnonymousStructWithRenameListInner ( 7 | list: Vector[String] 8 | ) 9 | 10 | // Generated type representing the anonymous struct variant `LongFieldNames` of the `AnonymousStructWithRename` Rust enum 11 | case class AnonymousStructWithRenameLongFieldNamesInner ( 12 | some_long_field_name: String, 13 | and: Boolean, 14 | but_one_more: Vector[String] 15 | ) 16 | 17 | // Generated type representing the anonymous struct variant `KebabCase` of the `AnonymousStructWithRename` Rust enum 18 | case class AnonymousStructWithRenameKebabCaseInner ( 19 | another_list: Vector[String], 20 | camelCaseStringField: String, 21 | something_else: Boolean 22 | ) 23 | 24 | sealed trait AnonymousStructWithRename { 25 | def serialName: String 26 | } 27 | object AnonymousStructWithRename { 28 | case class List(content: AnonymousStructWithRenameListInner) extends AnonymousStructWithRename { 29 | val serialName: String = "list" 30 | } 31 | case class LongFieldNames(content: AnonymousStructWithRenameLongFieldNamesInner) extends AnonymousStructWithRename { 32 | val serialName: String = "longFieldNames" 33 | } 34 | case class KebabCase(content: AnonymousStructWithRenameKebabCaseInner) extends AnonymousStructWithRename { 35 | val serialName: String = "kebabCase" 36 | } 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /core/data/tests/anonymous_struct_with_rename/output.ts: -------------------------------------------------------------------------------- 1 | export type AnonymousStructWithRename = 2 | | { type: "list", content: { 3 | list: string[]; 4 | }} 5 | | { type: "longFieldNames", content: { 6 | some_long_field_name: string; 7 | and: boolean; 8 | but_one_more: string[]; 9 | }} 10 | | { type: "kebabCase", content: { 11 | "another-list": string[]; 12 | camelCaseStringField: string; 13 | "something-else": boolean; 14 | }}; 15 | 16 | -------------------------------------------------------------------------------- /core/data/tests/can_apply_prefix_correctly/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | pub struct ItemDetailsFieldValue { 3 | hello: String, 4 | } 5 | 6 | #[typeshare] 7 | #[serde(tag = "t", content = "c")] 8 | pub enum AdvancedColors { 9 | String(String), 10 | Number(i32), 11 | NumberArray(Vec), 12 | ReallyCoolType(ItemDetailsFieldValue), 13 | ArrayReallyCoolType(Vec), 14 | DictionaryReallyCoolType(HashMap), 15 | } 16 | -------------------------------------------------------------------------------- /core/data/tests/can_apply_prefix_correctly/output.kt: -------------------------------------------------------------------------------- 1 | @Serializable 2 | data class OPItemDetailsFieldValue ( 3 | val hello: String 4 | ) 5 | 6 | @Serializable 7 | sealed class OPAdvancedColors { 8 | @Serializable 9 | @SerialName("String") 10 | data class String(val c: String): OPAdvancedColors() 11 | @Serializable 12 | @SerialName("Number") 13 | data class Number(val c: Int): OPAdvancedColors() 14 | @Serializable 15 | @SerialName("NumberArray") 16 | data class NumberArray(val c: List): OPAdvancedColors() 17 | @Serializable 18 | @SerialName("ReallyCoolType") 19 | data class ReallyCoolType(val c: OPItemDetailsFieldValue): OPAdvancedColors() 20 | @Serializable 21 | @SerialName("ArrayReallyCoolType") 22 | data class ArrayReallyCoolType(val c: List): OPAdvancedColors() 23 | @Serializable 24 | @SerialName("DictionaryReallyCoolType") 25 | data class DictionaryReallyCoolType(val c: HashMap): OPAdvancedColors() 26 | } 27 | 28 | -------------------------------------------------------------------------------- /core/data/tests/can_apply_prefix_correctly/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package onepassword { 4 | 5 | case class ItemDetailsFieldValue ( 6 | hello: String 7 | ) 8 | 9 | sealed trait AdvancedColors { 10 | def serialName: String 11 | } 12 | object AdvancedColors { 13 | case class String(c: String) extends AdvancedColors { 14 | val serialName: String = "String" 15 | } 16 | case class Number(c: Int) extends AdvancedColors { 17 | val serialName: String = "Number" 18 | } 19 | case class NumberArray(c: Vector[Int]) extends AdvancedColors { 20 | val serialName: String = "NumberArray" 21 | } 22 | case class ReallyCoolType(c: ItemDetailsFieldValue) extends AdvancedColors { 23 | val serialName: String = "ReallyCoolType" 24 | } 25 | case class ArrayReallyCoolType(c: Vector[ItemDetailsFieldValue]) extends AdvancedColors { 26 | val serialName: String = "ArrayReallyCoolType" 27 | } 28 | case class DictionaryReallyCoolType(c: Map[String, ItemDetailsFieldValue]) extends AdvancedColors { 29 | val serialName: String = "DictionaryReallyCoolType" 30 | } 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /core/data/tests/can_apply_prefix_correctly/output.ts: -------------------------------------------------------------------------------- 1 | export interface ItemDetailsFieldValue { 2 | hello: string; 3 | } 4 | 5 | export type AdvancedColors = 6 | | { t: "String", c: string } 7 | | { t: "Number", c: number } 8 | | { t: "NumberArray", c: number[] } 9 | | { t: "ReallyCoolType", c: ItemDetailsFieldValue } 10 | | { t: "ArrayReallyCoolType", c: ItemDetailsFieldValue[] } 11 | | { t: "DictionaryReallyCoolType", c: Record }; 12 | 13 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_algebraic_enum/input.rs: -------------------------------------------------------------------------------- 1 | /// Struct comment 2 | #[typeshare] 3 | pub struct ItemDetailsFieldValue {} 4 | 5 | /// Enum comment 6 | #[typeshare] 7 | #[serde(tag = "type", content = "content")] 8 | pub enum AdvancedColors { 9 | /// This is a case comment 10 | String(String), 11 | Number(i32), 12 | UnsignedNumber(u32), 13 | NumberArray(Vec), 14 | /// Comment on the last element 15 | ReallyCoolType(ItemDetailsFieldValue), 16 | } 17 | 18 | #[typeshare] 19 | #[serde(tag = "type", content = "content", rename_all = "kebab-case")] 20 | pub enum AdvancedColors2 { 21 | /// This is a case comment 22 | String(String), 23 | Number(i32), 24 | NumberArray(Vec), 25 | /// Comment on the last element 26 | ReallyCoolType(ItemDetailsFieldValue), 27 | } 28 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_algebraic_enum/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | /// Struct comment 7 | @Serializable 8 | object ItemDetailsFieldValue 9 | 10 | /// Enum comment 11 | @Serializable 12 | sealed class AdvancedColors { 13 | /// This is a case comment 14 | @Serializable 15 | @SerialName("String") 16 | data class String(val content: String): AdvancedColors() 17 | @Serializable 18 | @SerialName("Number") 19 | data class Number(val content: Int): AdvancedColors() 20 | @Serializable 21 | @SerialName("UnsignedNumber") 22 | data class UnsignedNumber(val content: UInt): AdvancedColors() 23 | @Serializable 24 | @SerialName("NumberArray") 25 | data class NumberArray(val content: List): AdvancedColors() 26 | /// Comment on the last element 27 | @Serializable 28 | @SerialName("ReallyCoolType") 29 | data class ReallyCoolType(val content: ItemDetailsFieldValue): AdvancedColors() 30 | } 31 | 32 | @Serializable 33 | sealed class AdvancedColors2 { 34 | /// This is a case comment 35 | @Serializable 36 | @SerialName("string") 37 | data class String(val content: String): AdvancedColors2() 38 | @Serializable 39 | @SerialName("number") 40 | data class Number(val content: Int): AdvancedColors2() 41 | @Serializable 42 | @SerialName("number-array") 43 | data class NumberArray(val content: List): AdvancedColors2() 44 | /// Comment on the last element 45 | @Serializable 46 | @SerialName("really-cool-type") 47 | data class ReallyCoolType(val content: ItemDetailsFieldValue): AdvancedColors2() 48 | } 49 | 50 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_algebraic_enum/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package object onepassword { 4 | 5 | type UByte = Byte 6 | type UShort = Short 7 | type UInt = Int 8 | type ULong = Int 9 | 10 | } 11 | package onepassword { 12 | 13 | // Struct comment 14 | class ItemDetailsFieldValue extends Serializable 15 | 16 | // Enum comment 17 | sealed trait AdvancedColors { 18 | def serialName: String 19 | } 20 | object AdvancedColors { 21 | // This is a case comment 22 | case class String(content: String) extends AdvancedColors { 23 | val serialName: String = "String" 24 | } 25 | case class Number(content: Int) extends AdvancedColors { 26 | val serialName: String = "Number" 27 | } 28 | case class UnsignedNumber(content: UInt) extends AdvancedColors { 29 | val serialName: String = "UnsignedNumber" 30 | } 31 | case class NumberArray(content: Vector[Int]) extends AdvancedColors { 32 | val serialName: String = "NumberArray" 33 | } 34 | // Comment on the last element 35 | case class ReallyCoolType(content: ItemDetailsFieldValue) extends AdvancedColors { 36 | val serialName: String = "ReallyCoolType" 37 | } 38 | } 39 | 40 | sealed trait AdvancedColors2 { 41 | def serialName: String 42 | } 43 | object AdvancedColors2 { 44 | // This is a case comment 45 | case class String(content: String) extends AdvancedColors2 { 46 | val serialName: String = "string" 47 | } 48 | case class Number(content: Int) extends AdvancedColors2 { 49 | val serialName: String = "number" 50 | } 51 | case class NumberArray(content: Vector[Int]) extends AdvancedColors2 { 52 | val serialName: String = "number-array" 53 | } 54 | // Comment on the last element 55 | case class ReallyCoolType(content: ItemDetailsFieldValue) extends AdvancedColors2 { 56 | val serialName: String = "really-cool-type" 57 | } 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_algebraic_enum/output.ts: -------------------------------------------------------------------------------- 1 | /** Struct comment */ 2 | export interface ItemDetailsFieldValue { 3 | } 4 | 5 | /** Enum comment */ 6 | export type AdvancedColors = 7 | /** This is a case comment */ 8 | | { type: "String", content: string } 9 | | { type: "Number", content: number } 10 | | { type: "UnsignedNumber", content: number } 11 | | { type: "NumberArray", content: number[] } 12 | /** Comment on the last element */ 13 | | { type: "ReallyCoolType", content: ItemDetailsFieldValue }; 14 | 15 | export type AdvancedColors2 = 16 | /** This is a case comment */ 17 | | { type: "string", content: string } 18 | | { type: "number", content: number } 19 | | { type: "number-array", content: number[] } 20 | /** Comment on the last element */ 21 | | { type: "really-cool-type", content: ItemDetailsFieldValue }; 22 | 23 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_algebraic_enum_with_skipped_variants/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | #[serde(tag = "type", content = "content")] 3 | pub enum SomeEnum { 4 | A, 5 | #[typeshare(skip)] 6 | B, 7 | C(i32), 8 | #[typeshare(skip, asdf)] 9 | D(u32), 10 | #[serde(skip)] 11 | E, 12 | } 13 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_algebraic_enum_with_skipped_variants/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | type SomeEnumTypes string 6 | const ( 7 | SomeEnumTypeVariantA SomeEnumTypes = "A" 8 | SomeEnumTypeVariantC SomeEnumTypes = "C" 9 | ) 10 | type SomeEnum struct{ 11 | Type SomeEnumTypes `json:"type"` 12 | content interface{} 13 | } 14 | 15 | func (s *SomeEnum) UnmarshalJSON(data []byte) error { 16 | var enum struct { 17 | Tag SomeEnumTypes `json:"type"` 18 | Content json.RawMessage `json:"content"` 19 | } 20 | if err := json.Unmarshal(data, &enum); err != nil { 21 | return err 22 | } 23 | 24 | s.Type = enum.Tag 25 | switch s.Type { 26 | case SomeEnumTypeVariantA: 27 | return nil 28 | case SomeEnumTypeVariantC: 29 | var res int 30 | s.content = &res 31 | 32 | } 33 | if err := json.Unmarshal(enum.Content, &s.content); err != nil { 34 | return err 35 | } 36 | 37 | return nil 38 | } 39 | 40 | func (s SomeEnum) MarshalJSON() ([]byte, error) { 41 | var enum struct { 42 | Tag SomeEnumTypes `json:"type"` 43 | Content interface{} `json:"content,omitempty"` 44 | } 45 | enum.Tag = s.Type 46 | enum.Content = s.content 47 | return json.Marshal(enum) 48 | } 49 | 50 | func (s SomeEnum) C() int { 51 | res, _ := s.content.(*int) 52 | return *res 53 | } 54 | 55 | func NewSomeEnumTypeVariantA() SomeEnum { 56 | return SomeEnum{ 57 | Type: SomeEnumTypeVariantA, 58 | } 59 | } 60 | func NewSomeEnumTypeVariantC(content int) SomeEnum { 61 | return SomeEnum{ 62 | Type: SomeEnumTypeVariantC, 63 | content: &content, 64 | } 65 | } 66 | 67 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_algebraic_enum_with_skipped_variants/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | @Serializable 7 | sealed class SomeEnum { 8 | @Serializable 9 | @SerialName("A") 10 | object A: SomeEnum() 11 | @Serializable 12 | @SerialName("C") 13 | data class C(val content: Int): SomeEnum() 14 | } 15 | 16 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_algebraic_enum_with_skipped_variants/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from enum import Enum 4 | from pydantic import BaseModel 5 | from typing import Literal, Union 6 | 7 | 8 | class SomeEnumTypes(str, Enum): 9 | A = "A" 10 | C = "C" 11 | 12 | class SomeEnumA(BaseModel): 13 | type: Literal[SomeEnumTypes.A] = SomeEnumTypes.A 14 | 15 | class SomeEnumC(BaseModel): 16 | type: Literal[SomeEnumTypes.C] = SomeEnumTypes.C 17 | content: int 18 | 19 | SomeEnum = Union[SomeEnumA, SomeEnumC] 20 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_algebraic_enum_with_skipped_variants/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package onepassword { 4 | 5 | sealed trait SomeEnum { 6 | def serialName: String 7 | } 8 | object SomeEnum { 9 | case object A extends SomeEnum { 10 | val serialName: String = "A" 11 | } 12 | case class C(content: Int) extends SomeEnum { 13 | val serialName: String = "C" 14 | } 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_algebraic_enum_with_skipped_variants/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public enum SomeEnum: Codable { 4 | case a 5 | case c(Int32) 6 | 7 | enum CodingKeys: String, CodingKey, Codable { 8 | case a = "A", 9 | c = "C" 10 | } 11 | 12 | private enum ContainerCodingKeys: String, CodingKey { 13 | case type, content 14 | } 15 | 16 | public init(from decoder: Decoder) throws { 17 | let container = try decoder.container(keyedBy: ContainerCodingKeys.self) 18 | if let type = try? container.decode(CodingKeys.self, forKey: .type) { 19 | switch type { 20 | case .a: 21 | self = .a 22 | return 23 | case .c: 24 | if let content = try? container.decode(Int32.self, forKey: .content) { 25 | self = .c(content) 26 | return 27 | } 28 | } 29 | } 30 | throw DecodingError.typeMismatch(SomeEnum.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for SomeEnum")) 31 | } 32 | 33 | public func encode(to encoder: Encoder) throws { 34 | var container = encoder.container(keyedBy: ContainerCodingKeys.self) 35 | switch self { 36 | case .a: 37 | try container.encode(CodingKeys.a, forKey: .type) 38 | case .c(let content): 39 | try container.encode(CodingKeys.c, forKey: .type) 40 | try container.encode(content, forKey: .content) 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_algebraic_enum_with_skipped_variants/output.ts: -------------------------------------------------------------------------------- 1 | export type SomeEnum = 2 | | { type: "A", content?: undefined } 3 | | { type: "C", content: number }; 4 | 5 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_anonymous_struct_with_skipped_fields/input.rs: -------------------------------------------------------------------------------- 1 | /// Enum keeping track of who autofilled a field 2 | #[typeshare] 3 | #[serde(tag = "type", content = "content")] 4 | pub enum AutofilledBy { 5 | /// This field was autofilled by us 6 | Us { 7 | /// The UUID for the fill 8 | uuid: String, 9 | }, 10 | /// Something else autofilled this field 11 | SomethingElse { 12 | /// The UUID for the fill 13 | uuid: String, 14 | /// Some other thing 15 | #[typeshare(skip)] 16 | thing: i32, 17 | }, 18 | } 19 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_anonymous_struct_with_skipped_fields/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | /// Generated type representing the anonymous struct variant `Us` of the `AutofilledBy` Rust enum 7 | @Serializable 8 | data class AutofilledByUsInner ( 9 | /// The UUID for the fill 10 | val uuid: String 11 | ) 12 | 13 | /// Generated type representing the anonymous struct variant `SomethingElse` of the `AutofilledBy` Rust enum 14 | @Serializable 15 | data class AutofilledBySomethingElseInner ( 16 | /// The UUID for the fill 17 | val uuid: String 18 | ) 19 | 20 | /// Enum keeping track of who autofilled a field 21 | @Serializable 22 | sealed class AutofilledBy { 23 | /// This field was autofilled by us 24 | @Serializable 25 | @SerialName("Us") 26 | data class Us(val content: AutofilledByUsInner): AutofilledBy() 27 | /// Something else autofilled this field 28 | @Serializable 29 | @SerialName("SomethingElse") 30 | data class SomethingElse(val content: AutofilledBySomethingElseInner): AutofilledBy() 31 | } 32 | 33 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_anonymous_struct_with_skipped_fields/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from enum import Enum 4 | from pydantic import BaseModel 5 | from typing import Literal, Union 6 | 7 | 8 | class AutofilledByUsInner(BaseModel): 9 | """ 10 | Generated type representing the anonymous struct variant `Us` of the `AutofilledBy` Rust enum 11 | """ 12 | uuid: str 13 | """ 14 | The UUID for the fill 15 | """ 16 | 17 | class AutofilledBySomethingElseInner(BaseModel): 18 | """ 19 | Generated type representing the anonymous struct variant `SomethingElse` of the `AutofilledBy` Rust enum 20 | """ 21 | uuid: str 22 | """ 23 | The UUID for the fill 24 | """ 25 | 26 | class AutofilledByTypes(str, Enum): 27 | US = "Us" 28 | SOMETHING_ELSE = "SomethingElse" 29 | 30 | class AutofilledByUs(BaseModel): 31 | """ 32 | This field was autofilled by us 33 | """ 34 | type: Literal[AutofilledByTypes.US] = AutofilledByTypes.US 35 | content: AutofilledByUsInner 36 | 37 | class AutofilledBySomethingElse(BaseModel): 38 | """ 39 | Something else autofilled this field 40 | """ 41 | type: Literal[AutofilledByTypes.SOMETHING_ELSE] = AutofilledByTypes.SOMETHING_ELSE 42 | content: AutofilledBySomethingElseInner 43 | 44 | # Enum keeping track of who autofilled a field 45 | AutofilledBy = Union[AutofilledByUs, AutofilledBySomethingElse] 46 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_anonymous_struct_with_skipped_fields/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package onepassword { 4 | 5 | // Generated type representing the anonymous struct variant `Us` of the `AutofilledBy` Rust enum 6 | case class AutofilledByUsInner ( 7 | // The UUID for the fill 8 | uuid: String 9 | ) 10 | 11 | // Generated type representing the anonymous struct variant `SomethingElse` of the `AutofilledBy` Rust enum 12 | case class AutofilledBySomethingElseInner ( 13 | // The UUID for the fill 14 | uuid: String 15 | ) 16 | 17 | // Enum keeping track of who autofilled a field 18 | sealed trait AutofilledBy { 19 | def serialName: String 20 | } 21 | object AutofilledBy { 22 | // This field was autofilled by us 23 | case class Us(content: AutofilledByUsInner) extends AutofilledBy { 24 | val serialName: String = "Us" 25 | } 26 | // Something else autofilled this field 27 | case class SomethingElse(content: AutofilledBySomethingElseInner) extends AutofilledBy { 28 | val serialName: String = "SomethingElse" 29 | } 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_anonymous_struct_with_skipped_fields/output.ts: -------------------------------------------------------------------------------- 1 | /** Enum keeping track of who autofilled a field */ 2 | export type AutofilledBy = 3 | /** This field was autofilled by us */ 4 | | { type: "Us", content: { 5 | /** The UUID for the fill */ 6 | uuid: string; 7 | }} 8 | /** Something else autofilled this field */ 9 | | { type: "SomethingElse", content: { 10 | /** The UUID for the fill */ 11 | uuid: string; 12 | }}; 13 | 14 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_bare_string_enum/input.rs: -------------------------------------------------------------------------------- 1 | /// This is a comment. 2 | #[typeshare] 3 | pub enum Colors { 4 | Red, 5 | Blue, 6 | Green, 7 | } 8 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_bare_string_enum/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | // This is a comment. 6 | type Colors string 7 | const ( 8 | ColorsRed Colors = "Red" 9 | ColorsBlue Colors = "Blue" 10 | ColorsGreen Colors = "Green" 11 | ) 12 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_bare_string_enum/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | /// This is a comment. 7 | @Serializable 8 | enum class Colors(val string: String) { 9 | @SerialName("Red") 10 | Red("Red"), 11 | @SerialName("Blue") 12 | Blue("Blue"), 13 | @SerialName("Green") 14 | Green("Green"), 15 | } 16 | 17 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_bare_string_enum/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from enum import Enum 4 | 5 | 6 | class Colors(str, Enum): 7 | """ 8 | This is a comment. 9 | """ 10 | RED = "Red" 11 | BLUE = "Blue" 12 | GREEN = "Green" 13 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_bare_string_enum/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package onepassword { 4 | 5 | // This is a comment. 6 | sealed trait Colors { 7 | def serialName: String 8 | } 9 | object Colors { 10 | case object Red extends Colors { 11 | val serialName: String = "Red" 12 | } 13 | case object Blue extends Colors { 14 | val serialName: String = "Blue" 15 | } 16 | case object Green extends Colors { 17 | val serialName: String = "Green" 18 | } 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_bare_string_enum/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// This is a comment. 4 | public enum Colors: String, Codable { 5 | case red = "Red" 6 | case blue = "Blue" 7 | case green = "Green" 8 | } 9 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_bare_string_enum/output.ts: -------------------------------------------------------------------------------- 1 | /** This is a comment. */ 2 | export enum Colors { 3 | Red = "Red", 4 | Blue = "Blue", 5 | Green = "Green", 6 | } 7 | 8 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_const/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | pub const MY_VAR: u32 = 12; 3 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_const/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | const MyVar uint32 = 12 6 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_const/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | 4 | 5 | 6 | MY_VAR: int = 12 7 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_const/output.ts: -------------------------------------------------------------------------------- 1 | export const MY_VAR: number = 12; 2 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_double_option_pattern/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | pub struct SomeStruct { 3 | field_a: Option>, 4 | } 5 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_double_option_pattern/output.ts: -------------------------------------------------------------------------------- 1 | export interface SomeStruct { 2 | field_a?: number | null; 3 | } 4 | 5 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_empty_algebraic_enum/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | pub struct AddressDetails {} 3 | 4 | #[typeshare] 5 | #[serde(tag = "type", content = "content")] 6 | pub enum Address { 7 | FixedAddress(AddressDetails), 8 | NoFixedAddress, 9 | } 10 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_empty_algebraic_enum/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | type AddressDetails struct { 6 | } 7 | type AddressTypes string 8 | const ( 9 | AddressTypeVariantFixedAddress AddressTypes = "FixedAddress" 10 | AddressTypeVariantNoFixedAddress AddressTypes = "NoFixedAddress" 11 | ) 12 | type Address struct{ 13 | Type AddressTypes `json:"type"` 14 | content interface{} 15 | } 16 | 17 | func (a *Address) UnmarshalJSON(data []byte) error { 18 | var enum struct { 19 | Tag AddressTypes `json:"type"` 20 | Content json.RawMessage `json:"content"` 21 | } 22 | if err := json.Unmarshal(data, &enum); err != nil { 23 | return err 24 | } 25 | 26 | a.Type = enum.Tag 27 | switch a.Type { 28 | case AddressTypeVariantFixedAddress: 29 | var res AddressDetails 30 | a.content = &res 31 | case AddressTypeVariantNoFixedAddress: 32 | return nil 33 | 34 | } 35 | if err := json.Unmarshal(enum.Content, &a.content); err != nil { 36 | return err 37 | } 38 | 39 | return nil 40 | } 41 | 42 | func (a Address) MarshalJSON() ([]byte, error) { 43 | var enum struct { 44 | Tag AddressTypes `json:"type"` 45 | Content interface{} `json:"content,omitempty"` 46 | } 47 | enum.Tag = a.Type 48 | enum.Content = a.content 49 | return json.Marshal(enum) 50 | } 51 | 52 | func (a Address) FixedAddress() *AddressDetails { 53 | res, _ := a.content.(*AddressDetails) 54 | return res 55 | } 56 | 57 | func NewAddressTypeVariantFixedAddress(content *AddressDetails) Address { 58 | return Address{ 59 | Type: AddressTypeVariantFixedAddress, 60 | content: content, 61 | } 62 | } 63 | func NewAddressTypeVariantNoFixedAddress() Address { 64 | return Address{ 65 | Type: AddressTypeVariantNoFixedAddress, 66 | } 67 | } 68 | 69 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_empty_algebraic_enum/output.kt: -------------------------------------------------------------------------------- 1 | @Serializable 2 | object OPAddressDetails 3 | 4 | @Serializable 5 | sealed class OPAddress { 6 | @Serializable 7 | @SerialName("FixedAddress") 8 | data class FixedAddress(val content: OPAddressDetails): OPAddress() 9 | @Serializable 10 | @SerialName("NoFixedAddress") 11 | object NoFixedAddress: OPAddress() 12 | } 13 | 14 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_empty_algebraic_enum/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from enum import Enum 4 | from pydantic import BaseModel 5 | from typing import Literal, Union 6 | 7 | 8 | class AddressDetails(BaseModel): 9 | pass 10 | class AddressTypes(str, Enum): 11 | FIXED_ADDRESS = "FixedAddress" 12 | NO_FIXED_ADDRESS = "NoFixedAddress" 13 | 14 | class AddressFixedAddress(BaseModel): 15 | type: Literal[AddressTypes.FIXED_ADDRESS] = AddressTypes.FIXED_ADDRESS 16 | content: AddressDetails 17 | 18 | class AddressNoFixedAddress(BaseModel): 19 | type: Literal[AddressTypes.NO_FIXED_ADDRESS] = AddressTypes.NO_FIXED_ADDRESS 20 | 21 | Address = Union[AddressFixedAddress, AddressNoFixedAddress] 22 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_empty_algebraic_enum/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package onepassword { 4 | 5 | class AddressDetails extends Serializable 6 | 7 | sealed trait Address { 8 | def serialName: String 9 | } 10 | object Address { 11 | case class FixedAddress(content: AddressDetails) extends Address { 12 | val serialName: String = "FixedAddress" 13 | } 14 | case object NoFixedAddress extends Address { 15 | val serialName: String = "NoFixedAddress" 16 | } 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_empty_algebraic_enum/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct OPAddressDetails: Codable { 4 | public init() {} 5 | } 6 | 7 | public enum OPAddress: Codable { 8 | case fixedAddress(OPAddressDetails) 9 | case noFixedAddress 10 | 11 | enum CodingKeys: String, CodingKey, Codable { 12 | case fixedAddress = "FixedAddress", 13 | noFixedAddress = "NoFixedAddress" 14 | } 15 | 16 | private enum ContainerCodingKeys: String, CodingKey { 17 | case type, content 18 | } 19 | 20 | public init(from decoder: Decoder) throws { 21 | let container = try decoder.container(keyedBy: ContainerCodingKeys.self) 22 | if let type = try? container.decode(CodingKeys.self, forKey: .type) { 23 | switch type { 24 | case .fixedAddress: 25 | if let content = try? container.decode(OPAddressDetails.self, forKey: .content) { 26 | self = .fixedAddress(content) 27 | return 28 | } 29 | case .noFixedAddress: 30 | self = .noFixedAddress 31 | return 32 | } 33 | } 34 | throw DecodingError.typeMismatch(OPAddress.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for OPAddress")) 35 | } 36 | 37 | public func encode(to encoder: Encoder) throws { 38 | var container = encoder.container(keyedBy: ContainerCodingKeys.self) 39 | switch self { 40 | case .fixedAddress(let content): 41 | try container.encode(CodingKeys.fixedAddress, forKey: .type) 42 | try container.encode(content, forKey: .content) 43 | case .noFixedAddress: 44 | try container.encode(CodingKeys.noFixedAddress, forKey: .type) 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_empty_algebraic_enum/output.ts: -------------------------------------------------------------------------------- 1 | export interface AddressDetails { 2 | } 3 | 4 | export type Address = 5 | | { type: "FixedAddress", content: AddressDetails } 6 | | { type: "NoFixedAddress", content?: undefined }; 7 | 8 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_generic_enum/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | #[serde(tag = "type", content = "content")] 3 | pub enum GenericEnum { 4 | VariantA(A), 5 | VariantB(B), 6 | } 7 | 8 | #[typeshare] 9 | pub struct StructUsingGenericEnum { 10 | enum_field: GenericEnum, 11 | } 12 | 13 | #[typeshare] 14 | #[serde(tag = "type", content = "content")] 15 | pub enum GenericEnumUsingGenericEnum { 16 | VariantC(GenericEnum), 17 | VariantD(GenericEnum<&'static str, std::collections::HashMap>), 18 | VariantE(GenericEnum<&'static str, u32>), 19 | } 20 | 21 | #[typeshare] 22 | #[serde(tag = "type", content = "content")] 23 | pub enum GenericEnumsUsingStructVariants { 24 | VariantF { action: T }, 25 | VariantG { action: T, response: U }, 26 | VariantH { non_generic: i32 }, 27 | VariantI { vec: Vec, action: MyType }, 28 | } 29 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_generic_enum/output.ts: -------------------------------------------------------------------------------- 1 | export type GenericEnum = 2 | | { type: "VariantA", content: A } 3 | | { type: "VariantB", content: B }; 4 | 5 | export interface StructUsingGenericEnum { 6 | enum_field: GenericEnum; 7 | } 8 | 9 | export type GenericEnumUsingGenericEnum = 10 | | { type: "VariantC", content: GenericEnum } 11 | | { type: "VariantD", content: GenericEnum> } 12 | | { type: "VariantE", content: GenericEnum }; 13 | 14 | export type GenericEnumsUsingStructVariants = 15 | | { type: "VariantF", content: { 16 | action: T; 17 | }} 18 | | { type: "VariantG", content: { 19 | action: T; 20 | response: U; 21 | }} 22 | | { type: "VariantH", content: { 23 | non_generic: number; 24 | }} 25 | | { type: "VariantI", content: { 26 | vec: T[]; 27 | action: MyType; 28 | }}; 29 | 30 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_generic_struct/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | pub struct GenericStruct { 3 | field_a: A, 4 | field_b: Vec 5 | } 6 | 7 | #[typeshare] 8 | #[serde(tag = "type", content = "content")] 9 | pub enum EnumUsingGenericStruct{ 10 | VariantA(GenericStruct), 11 | VariantB(GenericStruct<&'static str, i32>), 12 | VariantC(GenericStruct<&'static str, bool>), 13 | VariantD(GenericStructUsingGenericStruct<()>) 14 | } 15 | 16 | #[typeshare] 17 | pub struct GenericStructUsingGenericStruct { 18 | struct_field: GenericStruct, 19 | second_struct_field: GenericStruct, 20 | third_struct_field: GenericStruct> 21 | } 22 | 23 | 24 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_generic_struct/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | @Serializable 7 | data class GenericStruct ( 8 | val field_a: A, 9 | val field_b: List 10 | ) 11 | 12 | @Serializable 13 | data class GenericStructUsingGenericStruct ( 14 | val struct_field: GenericStruct, 15 | val second_struct_field: GenericStruct, 16 | val third_struct_field: GenericStruct> 17 | ) 18 | 19 | @Serializable 20 | sealed class EnumUsingGenericStruct { 21 | @Serializable 22 | @SerialName("VariantA") 23 | data class VariantA(val content: GenericStruct): EnumUsingGenericStruct() 24 | @Serializable 25 | @SerialName("VariantB") 26 | data class VariantB(val content: GenericStruct): EnumUsingGenericStruct() 27 | @Serializable 28 | @SerialName("VariantC") 29 | data class VariantC(val content: GenericStruct): EnumUsingGenericStruct() 30 | @Serializable 31 | @SerialName("VariantD") 32 | data class VariantD(val content: GenericStructUsingGenericStruct): EnumUsingGenericStruct() 33 | } 34 | 35 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_generic_struct/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package onepassword { 4 | 5 | case class GenericStruct[A, B] ( 6 | field_a: A, 7 | field_b: Vector[B] 8 | ) 9 | 10 | case class GenericStructUsingGenericStruct[T] ( 11 | struct_field: GenericStruct[String, T], 12 | second_struct_field: GenericStruct[T, String], 13 | third_struct_field: GenericStruct[T, Vector[T]] 14 | ) 15 | 16 | sealed trait EnumUsingGenericStruct { 17 | def serialName: String 18 | } 19 | object EnumUsingGenericStruct { 20 | case class VariantA(content: GenericStruct[String, Float]) extends EnumUsingGenericStruct { 21 | val serialName: String = "VariantA" 22 | } 23 | case class VariantB(content: GenericStruct[String, Int]) extends EnumUsingGenericStruct { 24 | val serialName: String = "VariantB" 25 | } 26 | case class VariantC(content: GenericStruct[String, Boolean]) extends EnumUsingGenericStruct { 27 | val serialName: String = "VariantC" 28 | } 29 | case class VariantD(content: GenericStructUsingGenericStruct[Unit]) extends EnumUsingGenericStruct { 30 | val serialName: String = "VariantD" 31 | } 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_generic_struct/output.ts: -------------------------------------------------------------------------------- 1 | export interface GenericStruct { 2 | field_a: A; 3 | field_b: B[]; 4 | } 5 | 6 | export interface GenericStructUsingGenericStruct { 7 | struct_field: GenericStruct; 8 | second_struct_field: GenericStruct; 9 | third_struct_field: GenericStruct; 10 | } 11 | 12 | export type EnumUsingGenericStruct = 13 | | { type: "VariantA", content: GenericStruct } 14 | | { type: "VariantB", content: GenericStruct } 15 | | { type: "VariantC", content: GenericStruct } 16 | | { type: "VariantD", content: GenericStructUsingGenericStruct }; 17 | 18 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_generic_type_alias/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | type GenericTypeAlias = Vec; 3 | 4 | #[typeshare] 5 | type NonGenericAlias = GenericTypeAlias>; 6 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_generic_type_alias/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | typealias GenericTypeAlias = List 7 | 8 | typealias NonGenericAlias = GenericTypeAlias 9 | 10 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_generic_type_alias/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package object onepassword { 4 | 5 | type GenericTypeAlias[T] = Vector[T] 6 | 7 | type NonGenericAlias = GenericTypeAlias[Option[String]] 8 | 9 | } 10 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_generic_type_alias/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public typealias CoreGenericTypeAlias = [T] 4 | 5 | public typealias CoreNonGenericAlias = CoreGenericTypeAlias 6 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_generic_type_alias/output.ts: -------------------------------------------------------------------------------- 1 | export type GenericTypeAlias = T[]; 2 | 3 | export type NonGenericAlias = GenericTypeAlias; 4 | 5 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_readonly_fields/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | pub struct SomeStruct { 3 | #[typeshare(typescript(readonly))] 4 | field_a: u32, 5 | } 6 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_readonly_fields/output.ts: -------------------------------------------------------------------------------- 1 | export interface SomeStruct { 2 | readonly field_a: number; 3 | } 4 | 5 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_simple_enum/input.rs: -------------------------------------------------------------------------------- 1 | /// This is a comment. 2 | /// Continued lovingly here 3 | #[typeshare] 4 | pub enum Colors { 5 | Red = 0, 6 | Blue = 1, 7 | /// Green is a cool color 8 | Green = 2, 9 | } 10 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_simple_enum/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | // This is a comment. 6 | // Continued lovingly here 7 | type Colors string 8 | const ( 9 | ColorsRed Colors = "Red" 10 | ColorsBlue Colors = "Blue" 11 | // Green is a cool color 12 | ColorsGreen Colors = "Green" 13 | ) 14 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_simple_enum/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | /// This is a comment. 7 | /// Continued lovingly here 8 | @Serializable 9 | enum class Colors(val string: String) { 10 | @SerialName("Red") 11 | Red("Red"), 12 | @SerialName("Blue") 13 | Blue("Blue"), 14 | /// Green is a cool color 15 | @SerialName("Green") 16 | Green("Green"), 17 | } 18 | 19 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_simple_enum/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from enum import Enum 4 | 5 | 6 | class Colors(str, Enum): 7 | """ 8 | This is a comment. 9 | Continued lovingly here 10 | """ 11 | RED = "Red" 12 | BLUE = "Blue" 13 | GREEN = "Green" 14 | """ 15 | Green is a cool color 16 | """ 17 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_simple_enum/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package onepassword { 4 | 5 | // This is a comment. 6 | // Continued lovingly here 7 | sealed trait Colors { 8 | def serialName: String 9 | } 10 | object Colors { 11 | case object Red extends Colors { 12 | val serialName: String = "Red" 13 | } 14 | case object Blue extends Colors { 15 | val serialName: String = "Blue" 16 | } 17 | // Green is a cool color 18 | case object Green extends Colors { 19 | val serialName: String = "Green" 20 | } 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_simple_enum/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// This is a comment. 4 | /// Continued lovingly here 5 | public enum TypeShareColors: String, Codable { 6 | case red = "Red" 7 | case blue = "Blue" 8 | /// Green is a cool color 9 | case green = "Green" 10 | } 11 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_simple_enum/output.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This is a comment. 3 | * Continued lovingly here 4 | */ 5 | export enum Colors { 6 | Red = "Red", 7 | Blue = "Blue", 8 | /** Green is a cool color */ 9 | Green = "Green", 10 | } 11 | 12 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_simple_struct_with_a_comment/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | pub struct Location {} 3 | 4 | /// This is a comment. 5 | #[typeshare] 6 | pub struct Person { 7 | /** This is another comment */ 8 | pub name: String, 9 | pub age: u8, 10 | pub info: Option, 11 | pub emails: Vec, 12 | pub location: Location, 13 | } 14 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_simple_struct_with_a_comment/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | type Location struct { 6 | } 7 | // This is a comment. 8 | type Person struct { 9 | // This is another comment 10 | Name string `json:"name"` 11 | Age int `json:"age"` 12 | Info *string `json:"info,omitempty"` 13 | Emails []string `json:"emails"` 14 | Location Location `json:"location"` 15 | } 16 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_simple_struct_with_a_comment/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | @Serializable 7 | object Location 8 | 9 | /// This is a comment. 10 | @Serializable 11 | data class Person ( 12 | /// This is another comment 13 | val name: String, 14 | val age: UByte, 15 | val info: String? = null, 16 | val emails: List, 17 | val location: Location 18 | ) 19 | 20 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_simple_struct_with_a_comment/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pydantic import BaseModel, Field 4 | from typing import List, Optional 5 | 6 | 7 | class Location(BaseModel): 8 | pass 9 | class Person(BaseModel): 10 | """ 11 | This is a comment. 12 | """ 13 | name: str 14 | """ 15 | This is another comment 16 | """ 17 | age: int 18 | info: Optional[str] = Field(default=None) 19 | emails: List[str] 20 | location: Location 21 | 22 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_simple_struct_with_a_comment/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package object onepassword { 4 | 5 | type UByte = Byte 6 | type UShort = Short 7 | type UInt = Int 8 | type ULong = Int 9 | 10 | } 11 | package onepassword { 12 | 13 | class Location extends Serializable 14 | 15 | // This is a comment. 16 | case class Person ( 17 | // This is another comment 18 | name: String, 19 | age: UByte, 20 | info: Option[String] = None, 21 | emails: Vector[String], 22 | location: Location 23 | ) 24 | 25 | } 26 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_simple_struct_with_a_comment/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct Location: Codable { 4 | public init() {} 5 | } 6 | 7 | /// This is a comment. 8 | public struct Person: Codable { 9 | /// This is another comment 10 | public let name: String 11 | public let age: UInt8 12 | public let info: String? 13 | public let emails: [String] 14 | public let location: Location 15 | 16 | public init(name: String, age: UInt8, info: String?, emails: [String], location: Location) { 17 | self.name = name 18 | self.age = age 19 | self.info = info 20 | self.emails = emails 21 | self.location = location 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_simple_struct_with_a_comment/output.ts: -------------------------------------------------------------------------------- 1 | export interface Location { 2 | } 3 | 4 | /** This is a comment. */ 5 | export interface Person { 6 | /** This is another comment */ 7 | name: string; 8 | age: number; 9 | info?: string; 10 | emails: string[]; 11 | location: Location; 12 | } 13 | 14 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_slice_of_user_type/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | #[derive(Serialize)] 3 | pub struct Video<'a> { 4 | pub tags: &'a [Tag], 5 | } 6 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_slice_of_user_type/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | type Video struct { 6 | Tags []Tag `json:"tags"` 7 | } 8 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_slice_of_user_type/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | @Serializable 7 | data class Video ( 8 | val tags: List 9 | ) 10 | 11 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_slice_of_user_type/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pydantic import BaseModel 4 | from typing import List 5 | 6 | 7 | class Video(BaseModel): 8 | tags: List[Tag] 9 | 10 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_slice_of_user_type/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package onepassword { 4 | 5 | case class Video ( 6 | tags: Vector[Tag] 7 | ) 8 | 9 | } 10 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_slice_of_user_type/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct Video: Codable { 4 | public let tags: [Tag] 5 | 6 | public init(tags: [Tag]) { 7 | self.tags = tags 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_slice_of_user_type/output.ts: -------------------------------------------------------------------------------- 1 | export interface Video { 2 | tags: Tag[]; 3 | } 4 | 5 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_struct_with_skipped_fields/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | pub struct MyStruct { 3 | a: i32, 4 | #[serde(skip)] 5 | b: i32, 6 | c: i32, 7 | #[typeshare(skip)] 8 | d: i32, 9 | } 10 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_struct_with_skipped_fields/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | type MyStruct struct { 6 | A int `json:"a"` 7 | C int `json:"c"` 8 | } 9 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_struct_with_skipped_fields/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | @Serializable 7 | data class MyStruct ( 8 | val a: Int, 9 | val c: Int 10 | ) 11 | 12 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_struct_with_skipped_fields/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pydantic import BaseModel 4 | 5 | 6 | class MyStruct(BaseModel): 7 | a: int 8 | c: int 9 | 10 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_struct_with_skipped_fields/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package onepassword { 4 | 5 | case class MyStruct ( 6 | a: Int, 7 | c: Int 8 | ) 9 | 10 | } 11 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_struct_with_skipped_fields/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct MyStruct: Codable { 4 | public let a: Int32 5 | public let c: Int32 6 | 7 | public init(a: Int32, c: Int32) { 8 | self.a = a 9 | self.c = c 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_struct_with_skipped_fields/output.ts: -------------------------------------------------------------------------------- 1 | export interface MyStruct { 2 | a: number; 3 | c: number; 4 | } 5 | 6 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_unit_structs/input.rs: -------------------------------------------------------------------------------- 1 | // This test verifies that unit structs created without bracket syntax can still be generated. 2 | 3 | #[typeshare] 4 | struct UnitStruct; -------------------------------------------------------------------------------- /core/data/tests/can_generate_unit_structs/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | type UnitStruct struct { 6 | } 7 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_unit_structs/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | @Serializable 7 | object UnitStruct 8 | 9 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_unit_structs/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pydantic import BaseModel 4 | 5 | 6 | class UnitStruct(BaseModel): 7 | pass 8 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_unit_structs/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package onepassword { 4 | 5 | class UnitStruct extends Serializable 6 | 7 | } 8 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_unit_structs/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct UnitStruct: Codable { 4 | public init() {} 5 | } 6 | -------------------------------------------------------------------------------- /core/data/tests/can_generate_unit_structs/output.ts: -------------------------------------------------------------------------------- 1 | export interface UnitStruct { 2 | } 3 | 4 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_anonymous_struct/input.rs: -------------------------------------------------------------------------------- 1 | /// Enum keeping track of who autofilled a field 2 | #[typeshare] 3 | #[serde(tag = "type", content = "content")] 4 | pub enum AutofilledBy { 5 | /// This field was autofilled by us 6 | Us { 7 | /// The UUID for the fill 8 | uuid: String, 9 | }, 10 | /// Something else autofilled this field 11 | SomethingElse { 12 | /// The UUID for the fill 13 | uuid: String, 14 | /// Some other thing 15 | thing: i32, 16 | }, 17 | } 18 | 19 | /// This is a comment (yareek sameek wuz here) 20 | #[typeshare] 21 | #[serde(tag = "type", content = "content")] 22 | pub enum EnumWithManyVariants { 23 | UnitVariant, 24 | TupleVariantString(String), 25 | AnonVariant { uuid: String }, 26 | TupleVariantInt(i32), 27 | AnotherUnitVariant, 28 | AnotherAnonVariant { uuid: String, thing: i32 }, 29 | } 30 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_anonymous_struct/output.ts: -------------------------------------------------------------------------------- 1 | /** Enum keeping track of who autofilled a field */ 2 | export type AutofilledBy = 3 | /** This field was autofilled by us */ 4 | | { type: "Us", content: { 5 | /** The UUID for the fill */ 6 | uuid: string; 7 | }} 8 | /** Something else autofilled this field */ 9 | | { type: "SomethingElse", content: { 10 | /** The UUID for the fill */ 11 | uuid: string; 12 | /** Some other thing */ 13 | thing: number; 14 | }}; 15 | 16 | /** This is a comment (yareek sameek wuz here) */ 17 | export type EnumWithManyVariants = 18 | | { type: "UnitVariant", content?: undefined } 19 | | { type: "TupleVariantString", content: string } 20 | | { type: "AnonVariant", content: { 21 | uuid: string; 22 | }} 23 | | { type: "TupleVariantInt", content: number } 24 | | { type: "AnotherUnitVariant", content?: undefined } 25 | | { type: "AnotherAnonVariant", content: { 26 | uuid: string; 27 | thing: number; 28 | }}; 29 | 30 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_quote_in_serde_rename/input.rs: -------------------------------------------------------------------------------- 1 | /// This is a comment. 2 | #[typeshare] 3 | pub enum Colors { 4 | #[serde(rename = "Green\"")] 5 | Green, 6 | } 7 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_quote_in_serde_rename/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | // This is a comment. 6 | type Colors string 7 | const ( 8 | ColorsGreen Colors = "Green\"" 9 | ) 10 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_quote_in_serde_rename/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | /// This is a comment. 7 | @Serializable 8 | enum class Colors(val string: String) { 9 | @SerialName("Green\"") 10 | Green("Green\""), 11 | } 12 | 13 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_quote_in_serde_rename/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from enum import Enum 4 | 5 | 6 | class Colors(str, Enum): 7 | """ 8 | This is a comment. 9 | """ 10 | GREEN = "Green\"" 11 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_quote_in_serde_rename/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package onepassword { 4 | 5 | // This is a comment. 6 | sealed trait Colors { 7 | def serialName: String 8 | } 9 | object Colors { 10 | case object Green extends Colors { 11 | val serialName: String = "Green\"" 12 | } 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_quote_in_serde_rename/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// This is a comment. 4 | public enum Colors: String, Codable { 5 | case green = "Green\"" 6 | } 7 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_quote_in_serde_rename/output.ts: -------------------------------------------------------------------------------- 1 | /** This is a comment. */ 2 | export enum Colors { 3 | Green = "Green\"", 4 | } 5 | 6 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_serde_rename/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | pub struct OtherType {} 3 | 4 | /// This is a comment. 5 | #[typeshare] 6 | pub struct Person { 7 | pub name: String, 8 | pub age: u8, 9 | #[serde(rename = "extraSpecialFieldOne")] 10 | pub extra_special_field1: i32, 11 | #[serde(rename = "extraSpecialFieldTwo")] 12 | pub extra_special_field2: Option>, 13 | #[serde(rename = "nonStandardDataType")] 14 | pub non_standard_data_type: OtherType, 15 | #[serde(rename = "nonStandardDataTypeInArray")] 16 | pub non_standard_data_type_in_array: Option>, 17 | } 18 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_serde_rename/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | type OtherType struct { 6 | } 7 | // This is a comment. 8 | type Person struct { 9 | Name string `json:"name"` 10 | Age int `json:"age"` 11 | ExtraSpecialField1 int `json:"extraSpecialFieldOne"` 12 | ExtraSpecialField2 *[]string `json:"extraSpecialFieldTwo,omitempty"` 13 | NonStandardDataType OtherType `json:"nonStandardDataType"` 14 | NonStandardDataTypeInArray *[]OtherType `json:"nonStandardDataTypeInArray,omitempty"` 15 | } 16 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_serde_rename/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | @Serializable 7 | object OtherType 8 | 9 | /// This is a comment. 10 | @Serializable 11 | data class Person ( 12 | val name: String, 13 | val age: UByte, 14 | val extraSpecialFieldOne: Int, 15 | val extraSpecialFieldTwo: List? = null, 16 | val nonStandardDataType: OtherType, 17 | val nonStandardDataTypeInArray: List? = null 18 | ) 19 | 20 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_serde_rename/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pydantic import BaseModel, ConfigDict, Field 4 | from typing import List, Optional 5 | 6 | 7 | class OtherType(BaseModel): 8 | pass 9 | class Person(BaseModel): 10 | """ 11 | This is a comment. 12 | """ 13 | model_config = ConfigDict(populate_by_name=True) 14 | 15 | name: str 16 | age: int 17 | extra_special_field_1: int = Field(alias="extraSpecialFieldOne") 18 | extra_special_field_2: Optional[List[str]] = Field(alias="extraSpecialFieldTwo", default=None) 19 | non_standard_data_type: OtherType = Field(alias="nonStandardDataType") 20 | non_standard_data_type_in_array: Optional[List[OtherType]] = Field(alias="nonStandardDataTypeInArray", default=None) 21 | 22 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_serde_rename/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package object onepassword { 4 | 5 | type UByte = Byte 6 | type UShort = Short 7 | type UInt = Int 8 | type ULong = Int 9 | 10 | } 11 | package onepassword { 12 | 13 | class OtherType extends Serializable 14 | 15 | // This is a comment. 16 | case class Person ( 17 | name: String, 18 | age: UByte, 19 | extraSpecialFieldOne: Int, 20 | extraSpecialFieldTwo: Option[Vector[String]] = None, 21 | nonStandardDataType: OtherType, 22 | nonStandardDataTypeInArray: Option[Vector[OtherType]] = None 23 | ) 24 | 25 | } 26 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_serde_rename/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct TypeShareX_OtherType: Codable { 4 | public init() {} 5 | } 6 | 7 | /// This is a comment. 8 | public struct TypeShareX_Person: Codable { 9 | public let name: String 10 | public let age: UInt8 11 | public let extraSpecialFieldOne: Int32 12 | public let extraSpecialFieldTwo: [String]? 13 | public let nonStandardDataType: TypeShareX_OtherType 14 | public let nonStandardDataTypeInArray: [TypeShareX_OtherType]? 15 | 16 | public init(name: String, age: UInt8, extraSpecialFieldOne: Int32, extraSpecialFieldTwo: [String]?, nonStandardDataType: TypeShareX_OtherType, nonStandardDataTypeInArray: [TypeShareX_OtherType]?) { 17 | self.name = name 18 | self.age = age 19 | self.extraSpecialFieldOne = extraSpecialFieldOne 20 | self.extraSpecialFieldTwo = extraSpecialFieldTwo 21 | self.nonStandardDataType = nonStandardDataType 22 | self.nonStandardDataTypeInArray = nonStandardDataTypeInArray 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_serde_rename/output.ts: -------------------------------------------------------------------------------- 1 | export interface OtherType { 2 | } 3 | 4 | /** This is a comment. */ 5 | export interface Person { 6 | name: string; 7 | age: number; 8 | extraSpecialFieldOne: number; 9 | extraSpecialFieldTwo?: string[]; 10 | nonStandardDataType: OtherType; 11 | nonStandardDataTypeInArray?: OtherType[]; 12 | } 13 | 14 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_serde_rename_all/input.rs: -------------------------------------------------------------------------------- 1 | /// This is a Person struct with camelCase rename 2 | #[typeshare] 3 | #[serde(default, rename_all = "camelCase")] 4 | pub struct Person { 5 | pub first_name: String, 6 | pub last_name: String, 7 | pub age: u8, 8 | pub extra_special_field1: i32, 9 | pub extra_special_field2: Option>, 10 | } 11 | 12 | /// This is a Person2 struct with UPPERCASE rename 13 | #[typeshare] 14 | #[serde(default, rename_all = "UPPERCASE")] 15 | pub struct Person2 { 16 | pub first_name: String, 17 | pub last_name: String, 18 | pub age: u8, 19 | } 20 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_serde_rename_all/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | // This is a Person struct with camelCase rename 6 | type Person struct { 7 | FirstName string `json:"firstName"` 8 | LastName string `json:"lastName"` 9 | Age int `json:"age"` 10 | ExtraSpecialField1 int `json:"extraSpecialField1"` 11 | ExtraSpecialField2 *[]string `json:"extraSpecialField2,omitempty"` 12 | } 13 | // This is a Person2 struct with UPPERCASE rename 14 | type Person2 struct { 15 | FirstName string `json:"FIRST_NAME"` 16 | LastName string `json:"LAST_NAME"` 17 | Age int `json:"AGE"` 18 | } 19 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_serde_rename_all/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | /// This is a Person struct with camelCase rename 7 | @Serializable 8 | data class Person ( 9 | val firstName: String, 10 | val lastName: String, 11 | val age: UByte, 12 | val extraSpecialField1: Int, 13 | val extraSpecialField2: List? = null 14 | ) 15 | 16 | /// This is a Person2 struct with UPPERCASE rename 17 | @Serializable 18 | data class Person2 ( 19 | val FIRST_NAME: String, 20 | val LAST_NAME: String, 21 | val AGE: UByte 22 | ) 23 | 24 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_serde_rename_all/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pydantic import BaseModel, ConfigDict, Field 4 | from typing import List, Optional 5 | 6 | 7 | class Person(BaseModel): 8 | """ 9 | This is a Person struct with camelCase rename 10 | """ 11 | model_config = ConfigDict(populate_by_name=True) 12 | 13 | first_name: str = Field(alias="firstName") 14 | last_name: str = Field(alias="lastName") 15 | age: int 16 | extra_special_field_1: int = Field(alias="extraSpecialField1") 17 | extra_special_field_2: Optional[List[str]] = Field(alias="extraSpecialField2", default=None) 18 | 19 | class Person2(BaseModel): 20 | """ 21 | This is a Person2 struct with UPPERCASE rename 22 | """ 23 | model_config = ConfigDict(populate_by_name=True) 24 | 25 | first_name: str = Field(alias="FIRST_NAME") 26 | last_name: str = Field(alias="LAST_NAME") 27 | age: int = Field(alias="AGE") 28 | 29 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_serde_rename_all/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package object onepassword { 4 | 5 | type UByte = Byte 6 | type UShort = Short 7 | type UInt = Int 8 | type ULong = Int 9 | 10 | } 11 | package onepassword { 12 | 13 | // This is a Person struct with camelCase rename 14 | case class Person ( 15 | firstName: String, 16 | lastName: String, 17 | age: UByte, 18 | extraSpecialField1: Int, 19 | extraSpecialField2: Option[Vector[String]] = None 20 | ) 21 | 22 | // This is a Person2 struct with UPPERCASE rename 23 | case class Person2 ( 24 | FIRST_NAME: String, 25 | LAST_NAME: String, 26 | AGE: UByte 27 | ) 28 | 29 | } 30 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_serde_rename_all/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// This is a Person struct with camelCase rename 4 | public struct Person: Codable { 5 | public let firstName: String 6 | public let lastName: String 7 | public let age: UInt8 8 | public let extraSpecialField1: Int32 9 | public let extraSpecialField2: [String]? 10 | 11 | public init(firstName: String, lastName: String, age: UInt8, extraSpecialField1: Int32, extraSpecialField2: [String]?) { 12 | self.firstName = firstName 13 | self.lastName = lastName 14 | self.age = age 15 | self.extraSpecialField1 = extraSpecialField1 16 | self.extraSpecialField2 = extraSpecialField2 17 | } 18 | } 19 | 20 | /// This is a Person2 struct with UPPERCASE rename 21 | public struct Person2: Codable { 22 | public let FIRST_NAME: String 23 | public let LAST_NAME: String 24 | public let AGE: UInt8 25 | 26 | public init(FIRST_NAME: String, LAST_NAME: String, AGE: UInt8) { 27 | self.FIRST_NAME = FIRST_NAME 28 | self.LAST_NAME = LAST_NAME 29 | self.AGE = AGE 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_serde_rename_all/output.ts: -------------------------------------------------------------------------------- 1 | /** This is a Person struct with camelCase rename */ 2 | export interface Person { 3 | firstName: string; 4 | lastName: string; 5 | age: number; 6 | extraSpecialField1: number; 7 | extraSpecialField2?: string[]; 8 | } 9 | 10 | /** This is a Person2 struct with UPPERCASE rename */ 11 | export interface Person2 { 12 | FIRST_NAME: string; 13 | LAST_NAME: string; 14 | AGE: number; 15 | } 16 | 17 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_serde_rename_on_top_level/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | pub struct OtherType {} 3 | 4 | /// This is a comment. 5 | #[typeshare] 6 | #[serde(rename = "PersonTwo")] 7 | pub struct Person { 8 | pub name: String, 9 | pub age: u8, 10 | #[serde(rename = "extraSpecialFieldOne")] 11 | pub extra_special_field1: i32, 12 | #[serde(rename = "extraSpecialFieldTwo")] 13 | pub extra_special_field2: Option>, 14 | #[serde(rename = "nonStandardDataType")] 15 | pub non_standard_data_type: OtherType, 16 | #[serde(rename = "nonStandardDataTypeInArray")] 17 | pub non_standard_data_type_in_array: Option>, 18 | } 19 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_serde_rename_on_top_level/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | type OtherType struct { 6 | } 7 | // This is a comment. 8 | type PersonTwo struct { 9 | Name string `json:"name"` 10 | Age int `json:"age"` 11 | ExtraSpecialField1 int `json:"extraSpecialFieldOne"` 12 | ExtraSpecialField2 *[]string `json:"extraSpecialFieldTwo,omitempty"` 13 | NonStandardDataType OtherType `json:"nonStandardDataType"` 14 | NonStandardDataTypeInArray *[]OtherType `json:"nonStandardDataTypeInArray,omitempty"` 15 | } 16 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_serde_rename_on_top_level/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | @Serializable 7 | object OtherType 8 | 9 | /// This is a comment. 10 | @Serializable 11 | data class PersonTwo ( 12 | val name: String, 13 | val age: UByte, 14 | val extraSpecialFieldOne: Int, 15 | val extraSpecialFieldTwo: List? = null, 16 | val nonStandardDataType: OtherType, 17 | val nonStandardDataTypeInArray: List? = null 18 | ) 19 | 20 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_serde_rename_on_top_level/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pydantic import BaseModel, ConfigDict, Field 4 | from typing import List, Optional 5 | 6 | 7 | class OtherType(BaseModel): 8 | pass 9 | class PersonTwo(BaseModel): 10 | """ 11 | This is a comment. 12 | """ 13 | model_config = ConfigDict(populate_by_name=True) 14 | 15 | name: str 16 | age: int 17 | extra_special_field_1: int = Field(alias="extraSpecialFieldOne") 18 | extra_special_field_2: Optional[List[str]] = Field(alias="extraSpecialFieldTwo", default=None) 19 | non_standard_data_type: OtherType = Field(alias="nonStandardDataType") 20 | non_standard_data_type_in_array: Optional[List[OtherType]] = Field(alias="nonStandardDataTypeInArray", default=None) 21 | 22 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_serde_rename_on_top_level/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package object onepassword { 4 | 5 | type UByte = Byte 6 | type UShort = Short 7 | type UInt = Int 8 | type ULong = Int 9 | 10 | } 11 | package onepassword { 12 | 13 | class OtherType extends Serializable 14 | 15 | // This is a comment. 16 | case class PersonTwo ( 17 | name: String, 18 | age: UByte, 19 | extraSpecialFieldOne: Int, 20 | extraSpecialFieldTwo: Option[Vector[String]] = None, 21 | nonStandardDataType: OtherType, 22 | nonStandardDataTypeInArray: Option[Vector[OtherType]] = None 23 | ) 24 | 25 | } 26 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_serde_rename_on_top_level/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct OPOtherType: Codable { 4 | public init() {} 5 | } 6 | 7 | /// This is a comment. 8 | public struct OPPersonTwo: Codable { 9 | public let name: String 10 | public let age: UInt8 11 | public let extraSpecialFieldOne: Int32 12 | public let extraSpecialFieldTwo: [String]? 13 | public let nonStandardDataType: OPOtherType 14 | public let nonStandardDataTypeInArray: [OPOtherType]? 15 | 16 | public init(name: String, age: UInt8, extraSpecialFieldOne: Int32, extraSpecialFieldTwo: [String]?, nonStandardDataType: OPOtherType, nonStandardDataTypeInArray: [OPOtherType]?) { 17 | self.name = name 18 | self.age = age 19 | self.extraSpecialFieldOne = extraSpecialFieldOne 20 | self.extraSpecialFieldTwo = extraSpecialFieldTwo 21 | self.nonStandardDataType = nonStandardDataType 22 | self.nonStandardDataTypeInArray = nonStandardDataTypeInArray 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_serde_rename_on_top_level/output.ts: -------------------------------------------------------------------------------- 1 | export interface OtherType { 2 | } 3 | 4 | /** This is a comment. */ 5 | export interface PersonTwo { 6 | name: string; 7 | age: number; 8 | extraSpecialFieldOne: number; 9 | extraSpecialFieldTwo?: string[]; 10 | nonStandardDataType: OtherType; 11 | nonStandardDataTypeInArray?: OtherType[]; 12 | } 13 | 14 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_unit_type/input.rs: -------------------------------------------------------------------------------- 1 | /// This struct has a unit field 2 | #[typeshare] 3 | #[serde(default, rename_all = "camelCase")] 4 | struct StructHasVoidType { 5 | this_is_a_unit: (), 6 | } 7 | 8 | /// This enum has a variant associated with unit data 9 | #[typeshare] 10 | #[serde(default, rename_all = "camelCase", tag = "type", content = "content")] 11 | enum EnumHasVoidType { 12 | HasAUnit(()), 13 | } 14 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_unit_type/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | // This struct has a unit field 6 | type StructHasVoidType struct { 7 | ThisIsAUnit struct{} `json:"thisIsAUnit"` 8 | } 9 | // This enum has a variant associated with unit data 10 | type EnumHasVoidTypeTypes string 11 | const ( 12 | EnumHasVoidTypeTypeVariantHasAUnit EnumHasVoidTypeTypes = "hasAUnit" 13 | ) 14 | type EnumHasVoidType struct{ 15 | Type EnumHasVoidTypeTypes `json:"type"` 16 | content interface{} 17 | } 18 | 19 | func (e *EnumHasVoidType) UnmarshalJSON(data []byte) error { 20 | var enum struct { 21 | Tag EnumHasVoidTypeTypes `json:"type"` 22 | Content json.RawMessage `json:"content"` 23 | } 24 | if err := json.Unmarshal(data, &enum); err != nil { 25 | return err 26 | } 27 | 28 | e.Type = enum.Tag 29 | switch e.Type { 30 | case EnumHasVoidTypeTypeVariantHasAUnit: 31 | var res struct{} 32 | e.content = &res 33 | 34 | } 35 | if err := json.Unmarshal(enum.Content, &e.content); err != nil { 36 | return err 37 | } 38 | 39 | return nil 40 | } 41 | 42 | func (e EnumHasVoidType) MarshalJSON() ([]byte, error) { 43 | var enum struct { 44 | Tag EnumHasVoidTypeTypes `json:"type"` 45 | Content interface{} `json:"content,omitempty"` 46 | } 47 | enum.Tag = e.Type 48 | enum.Content = e.content 49 | return json.Marshal(enum) 50 | } 51 | 52 | func (e EnumHasVoidType) HasAUnit() struct{} { 53 | res, _ := e.content.(*struct{}) 54 | return *res 55 | } 56 | 57 | func NewEnumHasVoidTypeTypeVariantHasAUnit(content struct{}) EnumHasVoidType { 58 | return EnumHasVoidType{ 59 | Type: EnumHasVoidTypeTypeVariantHasAUnit, 60 | content: &content, 61 | } 62 | } 63 | 64 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_unit_type/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | /// This struct has a unit field 7 | @Serializable 8 | data class StructHasVoidType ( 9 | val thisIsAUnit: Unit 10 | ) 11 | 12 | /// This enum has a variant associated with unit data 13 | @Serializable 14 | sealed class EnumHasVoidType { 15 | @Serializable 16 | @SerialName("hasAUnit") 17 | data class HasAUnit(val content: Unit): EnumHasVoidType() 18 | } 19 | 20 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_unit_type/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from enum import Enum 4 | from pydantic import BaseModel, ConfigDict, Field 5 | from typing import Literal 6 | 7 | 8 | class StructHasVoidType(BaseModel): 9 | """ 10 | This struct has a unit field 11 | """ 12 | model_config = ConfigDict(populate_by_name=True) 13 | 14 | this_is_a_unit: None = Field(alias="thisIsAUnit") 15 | 16 | class EnumHasVoidTypeTypes(str, Enum): 17 | HAS_A_UNIT = "hasAUnit" 18 | 19 | class EnumHasVoidTypeHasAUnit(BaseModel): 20 | type: Literal[EnumHasVoidTypeTypes.HAS_A_UNIT] = EnumHasVoidTypeTypes.HAS_A_UNIT 21 | content: None 22 | 23 | # This enum has a variant associated with unit data 24 | EnumHasVoidType = EnumHasVoidTypeHasAUnit 25 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_unit_type/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package onepassword { 4 | 5 | // This struct has a unit field 6 | case class StructHasVoidType ( 7 | thisIsAUnit: Unit 8 | ) 9 | 10 | // This enum has a variant associated with unit data 11 | sealed trait EnumHasVoidType { 12 | def serialName: String 13 | } 14 | object EnumHasVoidType { 15 | case class HasAUnit(content: Unit) extends EnumHasVoidType { 16 | val serialName: String = "hasAUnit" 17 | } 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_unit_type/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// This struct has a unit field 4 | public struct StructHasVoidType: Codable { 5 | public let thisIsAUnit: CodableVoid 6 | 7 | public init(thisIsAUnit: CodableVoid) { 8 | self.thisIsAUnit = thisIsAUnit 9 | } 10 | } 11 | 12 | /// This enum has a variant associated with unit data 13 | public enum EnumHasVoidType: Codable { 14 | case hasAUnit(CodableVoid) 15 | 16 | enum CodingKeys: String, CodingKey, Codable { 17 | case hasAUnit 18 | } 19 | 20 | private enum ContainerCodingKeys: String, CodingKey { 21 | case type, content 22 | } 23 | 24 | public init(from decoder: Decoder) throws { 25 | let container = try decoder.container(keyedBy: ContainerCodingKeys.self) 26 | if let type = try? container.decode(CodingKeys.self, forKey: .type) { 27 | switch type { 28 | case .hasAUnit: 29 | if let content = try? container.decode(CodableVoid.self, forKey: .content) { 30 | self = .hasAUnit(content) 31 | return 32 | } 33 | } 34 | } 35 | throw DecodingError.typeMismatch(EnumHasVoidType.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for EnumHasVoidType")) 36 | } 37 | 38 | public func encode(to encoder: Encoder) throws { 39 | var container = encoder.container(keyedBy: ContainerCodingKeys.self) 40 | switch self { 41 | case .hasAUnit(let content): 42 | try container.encode(CodingKeys.hasAUnit, forKey: .type) 43 | try container.encode(content, forKey: .content) 44 | } 45 | } 46 | } 47 | 48 | /// () isn't codable, so we use this instead to represent Rust's unit type 49 | public struct CodableVoid: Codable, Equatable {} 50 | -------------------------------------------------------------------------------- /core/data/tests/can_handle_unit_type/output.ts: -------------------------------------------------------------------------------- 1 | /** This struct has a unit field */ 2 | export interface StructHasVoidType { 3 | thisIsAUnit: undefined; 4 | } 5 | 6 | /** This enum has a variant associated with unit data */ 7 | export type EnumHasVoidType = 8 | | { type: "hasAUnit", content: undefined }; 9 | 10 | -------------------------------------------------------------------------------- /core/data/tests/can_override_types/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | #[serde(rename_all = "camelCase")] 3 | struct OverrideStruct { 4 | // These annotations are intentionally inconsistent across languages 5 | #[typeshare( 6 | swift(type = "Int"), 7 | typescript(readonly, type = "any | undefined"), 8 | kotlin(type = "Int"), go(type = "uint"), 9 | scala(type = "Short") 10 | )] 11 | field_to_override: String, 12 | } 13 | 14 | #[typeshare] 15 | #[serde(tag = "type", content = "content")] 16 | enum OverrideEnum { 17 | UnitVariant, 18 | TupleVariant(String), 19 | #[serde(rename_all = "camelCase")] 20 | AnonymousStructVariant { 21 | #[typeshare( 22 | swift(type = "Int"), 23 | typescript(readonly, type = "any | undefined"), 24 | kotlin(type = "Int"), go(type = "uint"), 25 | scala(type = "Short") 26 | )] 27 | field_to_override: String 28 | } 29 | } -------------------------------------------------------------------------------- /core/data/tests/can_override_types/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | @Serializable 7 | data class OverrideStruct ( 8 | val fieldToOverride: Int 9 | ) 10 | 11 | /// Generated type representing the anonymous struct variant `AnonymousStructVariant` of the `OverrideEnum` Rust enum 12 | @Serializable 13 | data class OverrideEnumAnonymousStructVariantInner ( 14 | val fieldToOverride: Int 15 | ) 16 | 17 | @Serializable 18 | sealed class OverrideEnum { 19 | @Serializable 20 | @SerialName("UnitVariant") 21 | object UnitVariant: OverrideEnum() 22 | @Serializable 23 | @SerialName("TupleVariant") 24 | data class TupleVariant(val content: String): OverrideEnum() 25 | @Serializable 26 | @SerialName("AnonymousStructVariant") 27 | data class AnonymousStructVariant(val content: OverrideEnumAnonymousStructVariantInner): OverrideEnum() 28 | } 29 | 30 | -------------------------------------------------------------------------------- /core/data/tests/can_override_types/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package onepassword { 4 | 5 | case class OverrideStruct ( 6 | fieldToOverride: Short 7 | ) 8 | 9 | // Generated type representing the anonymous struct variant `AnonymousStructVariant` of the `OverrideEnum` Rust enum 10 | case class OverrideEnumAnonymousStructVariantInner ( 11 | fieldToOverride: Short 12 | ) 13 | 14 | sealed trait OverrideEnum { 15 | def serialName: String 16 | } 17 | object OverrideEnum { 18 | case object UnitVariant extends OverrideEnum { 19 | val serialName: String = "UnitVariant" 20 | } 21 | case class TupleVariant(content: String) extends OverrideEnum { 22 | val serialName: String = "TupleVariant" 23 | } 24 | case class AnonymousStructVariant(content: OverrideEnumAnonymousStructVariantInner) extends OverrideEnum { 25 | val serialName: String = "AnonymousStructVariant" 26 | } 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /core/data/tests/can_override_types/output.ts: -------------------------------------------------------------------------------- 1 | export interface OverrideStruct { 2 | readonly fieldToOverride: any | undefined; 3 | } 4 | 5 | export type OverrideEnum = 6 | | { type: "UnitVariant", content?: undefined } 7 | | { type: "TupleVariant", content: string } 8 | | { type: "AnonymousStructVariant", content: { 9 | readonly fieldToOverride: any | undefined; 10 | }}; 11 | 12 | -------------------------------------------------------------------------------- /core/data/tests/can_recognize_types_inside_modules/input.rs: -------------------------------------------------------------------------------- 1 | mod a { 2 | #[typeshare] 3 | pub struct A { 4 | field: u32 5 | } 6 | mod b { 7 | mod c { 8 | #[typeshare] 9 | pub struct ABC { 10 | field: u32 11 | } 12 | } 13 | #[typeshare] 14 | pub struct AB { 15 | field: u32 16 | } 17 | } 18 | } 19 | 20 | #[typeshare] 21 | pub struct OutsideOfModules { 22 | field: u32 23 | } -------------------------------------------------------------------------------- /core/data/tests/can_recognize_types_inside_modules/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | type A struct { 6 | Field uint32 `json:"field"` 7 | } 8 | type AB struct { 9 | Field uint32 `json:"field"` 10 | } 11 | type ABC struct { 12 | Field uint32 `json:"field"` 13 | } 14 | type OutsideOfModules struct { 15 | Field uint32 `json:"field"` 16 | } 17 | -------------------------------------------------------------------------------- /core/data/tests/can_recognize_types_inside_modules/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | @Serializable 7 | data class A ( 8 | val field: UInt 9 | ) 10 | 11 | @Serializable 12 | data class AB ( 13 | val field: UInt 14 | ) 15 | 16 | @Serializable 17 | data class ABC ( 18 | val field: UInt 19 | ) 20 | 21 | @Serializable 22 | data class OutsideOfModules ( 23 | val field: UInt 24 | ) 25 | 26 | -------------------------------------------------------------------------------- /core/data/tests/can_recognize_types_inside_modules/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pydantic import BaseModel 4 | 5 | 6 | class A(BaseModel): 7 | field: int 8 | 9 | class AB(BaseModel): 10 | field: int 11 | 12 | class ABC(BaseModel): 13 | field: int 14 | 15 | class OutsideOfModules(BaseModel): 16 | field: int 17 | 18 | -------------------------------------------------------------------------------- /core/data/tests/can_recognize_types_inside_modules/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package object onepassword { 4 | 5 | type UByte = Byte 6 | type UShort = Short 7 | type UInt = Int 8 | type ULong = Int 9 | 10 | } 11 | package onepassword { 12 | 13 | case class A ( 14 | field: UInt 15 | ) 16 | 17 | case class AB ( 18 | field: UInt 19 | ) 20 | 21 | case class ABC ( 22 | field: UInt 23 | ) 24 | 25 | case class OutsideOfModules ( 26 | field: UInt 27 | ) 28 | 29 | } 30 | -------------------------------------------------------------------------------- /core/data/tests/can_recognize_types_inside_modules/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct A: Codable { 4 | public let field: UInt32 5 | 6 | public init(field: UInt32) { 7 | self.field = field 8 | } 9 | } 10 | 11 | public struct AB: Codable { 12 | public let field: UInt32 13 | 14 | public init(field: UInt32) { 15 | self.field = field 16 | } 17 | } 18 | 19 | public struct ABC: Codable { 20 | public let field: UInt32 21 | 22 | public init(field: UInt32) { 23 | self.field = field 24 | } 25 | } 26 | 27 | public struct OutsideOfModules: Codable { 28 | public let field: UInt32 29 | 30 | public init(field: UInt32) { 31 | self.field = field 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /core/data/tests/can_recognize_types_inside_modules/output.ts: -------------------------------------------------------------------------------- 1 | export interface A { 2 | field: number; 3 | } 4 | 5 | export interface AB { 6 | field: number; 7 | } 8 | 9 | export interface ABC { 10 | field: number; 11 | } 12 | 13 | export interface OutsideOfModules { 14 | field: number; 15 | } 16 | 17 | -------------------------------------------------------------------------------- /core/data/tests/const_enum_decorator/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | pub enum BestHockeyTeams { 3 | PittsburghPenguins, 4 | } 5 | 6 | #[typeshare(swift = "Equatable")] 7 | pub enum BestHockeyTeams1 { 8 | PittsburghPenguins, 9 | } 10 | 11 | #[typeshare(swift = "Equatable, Comparable, Hashable")] 12 | pub enum BestHockeyTeams2 { 13 | PittsburghPenguins, 14 | } 15 | 16 | #[typeshare(kotlin = "idk")] 17 | pub enum BestHockeyTeams3 { 18 | PittsburghPenguins, 19 | } 20 | #[typeshare(swift = "Equatable", swift = "Hashable")] 21 | pub enum BestHockeyTeams4 { 22 | PittsburghPenguins, 23 | } 24 | -------------------------------------------------------------------------------- /core/data/tests/const_enum_decorator/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public enum OPBestHockeyTeams: String, Codable { 4 | case pittsburghPenguins = "PittsburghPenguins" 5 | } 6 | 7 | public enum OPBestHockeyTeams1: String, Codable, Equatable { 8 | case pittsburghPenguins = "PittsburghPenguins" 9 | } 10 | 11 | public enum OPBestHockeyTeams2: String, Codable, Comparable, Equatable, Hashable { 12 | case pittsburghPenguins = "PittsburghPenguins" 13 | } 14 | 15 | public enum OPBestHockeyTeams3: String, Codable { 16 | case pittsburghPenguins = "PittsburghPenguins" 17 | } 18 | 19 | public enum OPBestHockeyTeams4: String, Codable, Equatable, Hashable { 20 | case pittsburghPenguins = "PittsburghPenguins" 21 | } 22 | -------------------------------------------------------------------------------- /core/data/tests/enum_is_properly_named_with_serde_overrides/input.rs: -------------------------------------------------------------------------------- 1 | /// This is a comment. 2 | /// Continued lovingly here 3 | #[typeshare] 4 | #[serde(rename_all = "camelCase")] 5 | pub enum Colors { 6 | Red = 0, 7 | Blue = 1, 8 | /// Green is a cool color 9 | #[serde(rename = "green-like")] 10 | Green = 2, 11 | } 12 | -------------------------------------------------------------------------------- /core/data/tests/enum_is_properly_named_with_serde_overrides/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | // This is a comment. 6 | // Continued lovingly here 7 | type Colors string 8 | const ( 9 | ColorsRed Colors = "red" 10 | ColorsBlue Colors = "blue" 11 | // Green is a cool color 12 | ColorsGreen Colors = "green-like" 13 | ) 14 | -------------------------------------------------------------------------------- /core/data/tests/enum_is_properly_named_with_serde_overrides/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | /// This is a comment. 7 | /// Continued lovingly here 8 | @Serializable 9 | enum class Colors(val string: String) { 10 | @SerialName("red") 11 | Red("red"), 12 | @SerialName("blue") 13 | Blue("blue"), 14 | /// Green is a cool color 15 | @SerialName("green-like") 16 | Green("green-like"), 17 | } 18 | 19 | -------------------------------------------------------------------------------- /core/data/tests/enum_is_properly_named_with_serde_overrides/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from enum import Enum 4 | 5 | 6 | class Colors(str, Enum): 7 | """ 8 | This is a comment. 9 | Continued lovingly here 10 | """ 11 | RED = "red" 12 | BLUE = "blue" 13 | GREEN = "green-like" 14 | """ 15 | Green is a cool color 16 | """ 17 | -------------------------------------------------------------------------------- /core/data/tests/enum_is_properly_named_with_serde_overrides/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package onepassword { 4 | 5 | // This is a comment. 6 | // Continued lovingly here 7 | sealed trait Colors { 8 | def serialName: String 9 | } 10 | object Colors { 11 | case object Red extends Colors { 12 | val serialName: String = "red" 13 | } 14 | case object Blue extends Colors { 15 | val serialName: String = "blue" 16 | } 17 | // Green is a cool color 18 | case object Green extends Colors { 19 | val serialName: String = "green-like" 20 | } 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /core/data/tests/enum_is_properly_named_with_serde_overrides/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// This is a comment. 4 | /// Continued lovingly here 5 | public enum Colors: String, Codable { 6 | case red 7 | case blue 8 | /// Green is a cool color 9 | case green = "green-like" 10 | } 11 | -------------------------------------------------------------------------------- /core/data/tests/enum_is_properly_named_with_serde_overrides/output.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This is a comment. 3 | * Continued lovingly here 4 | */ 5 | export enum Colors { 6 | Red = "red", 7 | Blue = "blue", 8 | /** Green is a cool color */ 9 | Green = "green-like", 10 | } 11 | 12 | -------------------------------------------------------------------------------- /core/data/tests/excluded_by_target_os/output.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A struct with no target_os. Should be generated when 3 | * we use --target-os. 4 | */ 5 | export interface AlwaysAccept { 6 | } 7 | 8 | export interface DefinedTwice { 9 | field1: string; 10 | } 11 | 12 | export interface Excluded { 13 | } 14 | 15 | export interface ManyStruct { 16 | } 17 | 18 | export interface MultipleTargets { 19 | } 20 | 21 | export interface NestedNotTarget1 { 22 | } 23 | 24 | export interface OtherExcluded { 25 | } 26 | 27 | export enum AlwaysAcceptEnum { 28 | Variant1 = "Variant1", 29 | Variant2 = "Variant2", 30 | } 31 | 32 | export enum SomeEnum { 33 | } 34 | 35 | export type TestEnum = 36 | | { type: "Variant1", content?: undefined } 37 | | { type: "Variant5", content?: undefined } 38 | | { type: "Variant7", content: { 39 | field1: string; 40 | }} 41 | | { type: "Variant8", content?: undefined } 42 | | { type: "Variant9", content: { 43 | field2: string; 44 | }}; 45 | 46 | -------------------------------------------------------------------------------- /core/data/tests/excluded_by_target_os_full_module/input.rs: -------------------------------------------------------------------------------- 1 | #![cfg(feature = "online")] 2 | #![allow(dead_code)] 3 | #![cfg(any(target_os = "android", feature = "testing"))] 4 | #![cfg(target_os = "wasm32")] 5 | 6 | #[typeshare] 7 | pub struct IgnoredUnlessAndroid; 8 | -------------------------------------------------------------------------------- /core/data/tests/excluded_by_target_os_full_module/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | -------------------------------------------------------------------------------- /core/data/tests/generate_types/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | pub struct CustomType {} 3 | 4 | #[typeshare] 5 | pub struct Types { 6 | pub s: String, 7 | pub static_s: &'static str, 8 | pub int8: i8, 9 | pub float: f32, 10 | pub double: f64, 11 | pub array: Vec, 12 | pub fixed_length_array: [String; 4], 13 | pub dictionary: HashMap, 14 | pub optional_dictionary: Option>, 15 | pub custom_type: CustomType, 16 | } 17 | -------------------------------------------------------------------------------- /core/data/tests/generate_types/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | type CustomType struct { 6 | } 7 | type Types struct { 8 | S string `json:"s"` 9 | StaticS string `json:"static_s"` 10 | Int8 int `json:"int8"` 11 | Float float32 `json:"float"` 12 | Double float64 `json:"double"` 13 | Array []string `json:"array"` 14 | FixedLengthArray [4]string `json:"fixed_length_array"` 15 | Dictionary map[string]int `json:"dictionary"` 16 | OptionalDictionary *map[string]int `json:"optional_dictionary,omitempty"` 17 | CustomType CustomType `json:"custom_type"` 18 | } 19 | -------------------------------------------------------------------------------- /core/data/tests/generate_types/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | @Serializable 7 | object CustomType 8 | 9 | @Serializable 10 | data class Types ( 11 | val s: String, 12 | val static_s: String, 13 | val int8: Byte, 14 | val float: Float, 15 | val double: Double, 16 | val array: List, 17 | val fixed_length_array: List, 18 | val dictionary: HashMap, 19 | val optional_dictionary: HashMap? = null, 20 | val custom_type: CustomType 21 | ) 22 | 23 | -------------------------------------------------------------------------------- /core/data/tests/generate_types/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pydantic import BaseModel, ConfigDict, Field 4 | from typing import Dict, List, Optional 5 | 6 | 7 | class CustomType(BaseModel): 8 | pass 9 | class Types(BaseModel): 10 | model_config = ConfigDict(populate_by_name=True) 11 | 12 | s: str 13 | static_s: str 14 | int_8: int = Field(alias="int8") 15 | float: float 16 | double: float 17 | array: List[str] 18 | fixed_length_array: List[str] 19 | dictionary: Dict[str, int] 20 | optional_dictionary: Optional[Dict[str, int]] = Field(default=None) 21 | custom_type: CustomType 22 | 23 | -------------------------------------------------------------------------------- /core/data/tests/generate_types/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package onepassword { 4 | 5 | class CustomType extends Serializable 6 | 7 | case class Types ( 8 | s: String, 9 | static_s: String, 10 | int8: Byte, 11 | float: Float, 12 | double: Double, 13 | array: Vector[String], 14 | fixed_length_array: Vector[String], 15 | dictionary: Map[String, Int], 16 | optional_dictionary: Option[Map[String, Int]] = None, 17 | custom_type: CustomType 18 | ) 19 | 20 | } 21 | -------------------------------------------------------------------------------- /core/data/tests/generate_types/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct CustomType: Codable { 4 | public init() {} 5 | } 6 | 7 | public struct Types: Codable { 8 | public let s: String 9 | public let static_s: String 10 | public let int8: Int8 11 | public let float: Float 12 | public let double: Double 13 | public let array: [String] 14 | public let fixed_length_array: [String] 15 | public let dictionary: [String: Int32] 16 | public let optional_dictionary: [String: Int32]? 17 | public let custom_type: CustomType 18 | 19 | public init(s: String, static_s: String, int8: Int8, float: Float, double: Double, array: [String], fixed_length_array: [String], dictionary: [String: Int32], optional_dictionary: [String: Int32]?, custom_type: CustomType) { 20 | self.s = s 21 | self.static_s = static_s 22 | self.int8 = int8 23 | self.float = float 24 | self.double = double 25 | self.array = array 26 | self.fixed_length_array = fixed_length_array 27 | self.dictionary = dictionary 28 | self.optional_dictionary = optional_dictionary 29 | self.custom_type = custom_type 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /core/data/tests/generate_types/output.ts: -------------------------------------------------------------------------------- 1 | export interface CustomType { 2 | } 3 | 4 | export interface Types { 5 | s: string; 6 | static_s: string; 7 | int8: number; 8 | float: number; 9 | double: number; 10 | array: string[]; 11 | fixed_length_array: [string, string, string, string]; 12 | dictionary: Record; 13 | optional_dictionary?: Record; 14 | custom_type: CustomType; 15 | } 16 | 17 | -------------------------------------------------------------------------------- /core/data/tests/generate_types_with_keywords/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | pub struct catch { 3 | pub default: String, 4 | pub case: String, 5 | } 6 | 7 | #[typeshare] 8 | pub enum throws { 9 | case, 10 | default, 11 | } 12 | 13 | #[typeshare] 14 | #[serde(tag = "type", content = "content")] 15 | pub enum switch { 16 | default(catch), 17 | } 18 | -------------------------------------------------------------------------------- /core/data/tests/generate_types_with_keywords/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct `catch`: Codable { 4 | public let `default`: String 5 | public let `case`: String 6 | 7 | public init(default: String, case: String) { 8 | self.default = `default` 9 | self.case = `case` 10 | } 11 | } 12 | 13 | public enum `switch`: Codable { 14 | case `default`(`catch`) 15 | 16 | enum CodingKeys: String, CodingKey, Codable { 17 | case `default` 18 | } 19 | 20 | private enum ContainerCodingKeys: String, CodingKey { 21 | case type, content 22 | } 23 | 24 | public init(from decoder: Decoder) throws { 25 | let container = try decoder.container(keyedBy: ContainerCodingKeys.self) 26 | if let type = try? container.decode(CodingKeys.self, forKey: .type) { 27 | switch type { 28 | case .default: 29 | if let content = try? container.decode(`catch`.self, forKey: .content) { 30 | self = .default(content) 31 | return 32 | } 33 | } 34 | } 35 | throw DecodingError.typeMismatch(`switch`.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for `switch`")) 36 | } 37 | 38 | public func encode(to encoder: Encoder) throws { 39 | var container = encoder.container(keyedBy: ContainerCodingKeys.self) 40 | switch self { 41 | case .default(let content): 42 | try container.encode(CodingKeys.default, forKey: .type) 43 | try container.encode(content, forKey: .content) 44 | } 45 | } 46 | } 47 | 48 | public enum `throws`: String, Codable { 49 | case `case` 50 | case `default` 51 | } 52 | -------------------------------------------------------------------------------- /core/data/tests/generates_configured_generic_constraints/input.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1Password/typeshare/8c8041c37ab8887981a3c37133c736f424653d88/core/data/tests/generates_configured_generic_constraints/input.rs -------------------------------------------------------------------------------- /core/data/tests/generates_configured_generic_constraints/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | -------------------------------------------------------------------------------- /core/data/tests/generates_empty_structs_and_initializers/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | pub struct MyEmptyStruct {} 3 | -------------------------------------------------------------------------------- /core/data/tests/generates_empty_structs_and_initializers/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | type MyEmptyStruct struct { 6 | } 7 | -------------------------------------------------------------------------------- /core/data/tests/generates_empty_structs_and_initializers/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | @Serializable 7 | object MyEmptyStruct 8 | 9 | -------------------------------------------------------------------------------- /core/data/tests/generates_empty_structs_and_initializers/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pydantic import BaseModel 4 | 5 | 6 | class MyEmptyStruct(BaseModel): 7 | pass 8 | -------------------------------------------------------------------------------- /core/data/tests/generates_empty_structs_and_initializers/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package onepassword { 4 | 5 | class MyEmptyStruct extends Serializable 6 | 7 | } 8 | -------------------------------------------------------------------------------- /core/data/tests/generates_empty_structs_and_initializers/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct MyEmptyStruct: Codable { 4 | public init() {} 5 | } 6 | -------------------------------------------------------------------------------- /core/data/tests/generates_empty_structs_and_initializers/output.ts: -------------------------------------------------------------------------------- 1 | export interface MyEmptyStruct { 2 | } 3 | 4 | -------------------------------------------------------------------------------- /core/data/tests/generic_struct_with_constraints_and_decorators/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare( 2 | swift = "Equatable, Identifiable", 3 | swiftGenericConstraints = "T: Equatable & SomeThingElse, V: Equatable" 4 | )] 5 | pub struct Button { 6 | /// Label of the button 7 | pub label: I, 8 | /// Accessibility label if it needed to be different than label 9 | pub accessibility_label: Option, 10 | /// Optional tooltips that provide extra explanation for a button 11 | pub tooltip: Option, 12 | /// Button action if there one 13 | pub action: Option, 14 | /// Icon if there is one 15 | pub icon: Option, 16 | /// Button state 17 | pub state: ButtonState, 18 | /// Button Mode 19 | pub style: ButtonStyle, 20 | } 21 | 22 | #[typeshare] 23 | pub struct ButtonState; 24 | 25 | #[typeshare] 26 | pub struct ButtonStyle; 27 | -------------------------------------------------------------------------------- /core/data/tests/generic_struct_with_constraints_and_decorators/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct ButtonState: Codable { 4 | public init() {} 5 | } 6 | 7 | public struct ButtonStyle: Codable { 8 | public init() {} 9 | } 10 | 11 | public struct Button: Codable, Equatable, Identifiable { 12 | /// Label of the button 13 | public let label: I 14 | /// Accessibility label if it needed to be different than label 15 | public let accessibility_label: String? 16 | /// Optional tooltips that provide extra explanation for a button 17 | public let tooltip: String? 18 | /// Button action if there one 19 | public let action: T? 20 | /// Icon if there is one 21 | public let icon: V? 22 | /// Button state 23 | public let state: ButtonState 24 | /// Button Mode 25 | public let style: ButtonStyle 26 | 27 | public init(label: I, accessibility_label: String?, tooltip: String?, action: T?, icon: V?, state: ButtonState, style: ButtonStyle) { 28 | self.label = label 29 | self.accessibility_label = accessibility_label 30 | self.tooltip = tooltip 31 | self.action = action 32 | self.icon = icon 33 | self.state = state 34 | self.style = style 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /core/data/tests/kebab_case_rename/input.rs: -------------------------------------------------------------------------------- 1 | /// This is a comment. 2 | #[typeshare] 3 | #[serde(rename_all = "camelCase")] 4 | pub struct Things { 5 | pub bla: String, 6 | #[serde(rename = "label")] 7 | pub some_label: Option, 8 | #[serde(rename = "label-left")] 9 | pub label_left: Option, 10 | } 11 | -------------------------------------------------------------------------------- /core/data/tests/kebab_case_rename/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | // This is a comment. 6 | type Things struct { 7 | Bla string `json:"bla"` 8 | SomeLabel *string `json:"label,omitempty"` 9 | LabelLeft *string `json:"label-left,omitempty"` 10 | } 11 | -------------------------------------------------------------------------------- /core/data/tests/kebab_case_rename/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | /// This is a comment. 7 | @Serializable 8 | data class Things ( 9 | @SerialName("bla") 10 | val bla: String, 11 | @SerialName("label") 12 | val label: String? = null, 13 | @SerialName("label-left") 14 | val label_left: String? = null 15 | ) 16 | 17 | -------------------------------------------------------------------------------- /core/data/tests/kebab_case_rename/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pydantic import BaseModel, ConfigDict, Field 4 | from typing import Optional 5 | 6 | 7 | class Things(BaseModel): 8 | """ 9 | This is a comment. 10 | """ 11 | model_config = ConfigDict(populate_by_name=True) 12 | 13 | bla: str 14 | some_label: Optional[str] = Field(alias="label", default=None) 15 | label_left: Optional[str] = Field(alias="label-left", default=None) 16 | 17 | -------------------------------------------------------------------------------- /core/data/tests/kebab_case_rename/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package onepassword { 4 | 5 | // This is a comment. 6 | case class Things ( 7 | bla: String, 8 | label: Option[String] = None, 9 | label_left: Option[String] = None 10 | ) 11 | 12 | } 13 | -------------------------------------------------------------------------------- /core/data/tests/kebab_case_rename/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// This is a comment. 4 | public struct Things: Codable { 5 | public let bla: String 6 | public let label: String? 7 | public let label_left: String? 8 | 9 | enum CodingKeys: String, CodingKey, Codable { 10 | case bla, 11 | label, 12 | label_left = "label-left" 13 | } 14 | 15 | public init(bla: String, label: String?, label_left: String?) { 16 | self.bla = bla 17 | self.label = label 18 | self.label_left = label_left 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /core/data/tests/kebab_case_rename/output.ts: -------------------------------------------------------------------------------- 1 | /** This is a comment. */ 2 | export interface Things { 3 | bla: string; 4 | label?: string; 5 | "label-left"?: string; 6 | } 7 | 8 | -------------------------------------------------------------------------------- /core/data/tests/orders_types/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | #[serde(rename_all = "camelCase")] 3 | pub struct E { 4 | depends_on: D, 5 | } 6 | 7 | #[typeshare] 8 | #[serde(rename_all = "camelCase")] 9 | pub struct D { 10 | depends_on: C, 11 | also_depends_on: Option, 12 | } 13 | 14 | #[typeshare] 15 | #[serde(rename_all = "camelCase")] 16 | pub struct C { 17 | depends_on: B 18 | } 19 | 20 | #[typeshare] 21 | #[serde(rename_all = "camelCase")] 22 | pub struct B { 23 | depends_on: A, 24 | } 25 | 26 | #[typeshare] 27 | #[serde(rename_all = "camelCase")] 28 | pub struct A { 29 | field: u32 30 | } 31 | 32 | -------------------------------------------------------------------------------- /core/data/tests/orders_types/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | type A struct { 6 | Field uint32 `json:"field"` 7 | } 8 | type B struct { 9 | DependsOn A `json:"dependsOn"` 10 | } 11 | type C struct { 12 | DependsOn B `json:"dependsOn"` 13 | } 14 | type E struct { 15 | DependsOn D `json:"dependsOn"` 16 | } 17 | type D struct { 18 | DependsOn C `json:"dependsOn"` 19 | AlsoDependsOn *E `json:"alsoDependsOn,omitempty"` 20 | } 21 | -------------------------------------------------------------------------------- /core/data/tests/orders_types/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | @Serializable 7 | data class A ( 8 | val field: UInt 9 | ) 10 | 11 | @Serializable 12 | data class B ( 13 | val dependsOn: A 14 | ) 15 | 16 | @Serializable 17 | data class C ( 18 | val dependsOn: B 19 | ) 20 | 21 | @Serializable 22 | data class E ( 23 | val dependsOn: D 24 | ) 25 | 26 | @Serializable 27 | data class D ( 28 | val dependsOn: C, 29 | val alsoDependsOn: E? = null 30 | ) 31 | 32 | -------------------------------------------------------------------------------- /core/data/tests/orders_types/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pydantic import BaseModel, ConfigDict, Field 4 | from typing import Optional 5 | 6 | 7 | class A(BaseModel): 8 | field: int 9 | 10 | class B(BaseModel): 11 | model_config = ConfigDict(populate_by_name=True) 12 | 13 | depends_on: A = Field(alias="dependsOn") 14 | 15 | class C(BaseModel): 16 | model_config = ConfigDict(populate_by_name=True) 17 | 18 | depends_on: B = Field(alias="dependsOn") 19 | 20 | class E(BaseModel): 21 | model_config = ConfigDict(populate_by_name=True) 22 | 23 | depends_on: D = Field(alias="dependsOn") 24 | 25 | class D(BaseModel): 26 | model_config = ConfigDict(populate_by_name=True) 27 | 28 | depends_on: C = Field(alias="dependsOn") 29 | also_depends_on: Optional[E] = Field(alias="alsoDependsOn", default=None) 30 | 31 | -------------------------------------------------------------------------------- /core/data/tests/orders_types/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct A: Codable { 4 | public let field: UInt32 5 | 6 | public init(field: UInt32) { 7 | self.field = field 8 | } 9 | } 10 | 11 | public struct B: Codable { 12 | public let dependsOn: A 13 | 14 | public init(dependsOn: A) { 15 | self.dependsOn = dependsOn 16 | } 17 | } 18 | 19 | public struct C: Codable { 20 | public let dependsOn: B 21 | 22 | public init(dependsOn: B) { 23 | self.dependsOn = dependsOn 24 | } 25 | } 26 | 27 | public struct E: Codable { 28 | public let dependsOn: D 29 | 30 | public init(dependsOn: D) { 31 | self.dependsOn = dependsOn 32 | } 33 | } 34 | 35 | public struct D: Codable { 36 | public let dependsOn: C 37 | public let alsoDependsOn: E? 38 | 39 | public init(dependsOn: C, alsoDependsOn: E?) { 40 | self.dependsOn = dependsOn 41 | self.alsoDependsOn = alsoDependsOn 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /core/data/tests/recursive_enum_decorator/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | #[serde(tag = "type", content = "content", rename_all = "camelCase")] 3 | pub enum Options { 4 | Red(bool), 5 | Banana(String), 6 | Vermont(Options), 7 | } 8 | 9 | #[typeshare] 10 | #[serde(tag = "type", content = "content", rename_all = "camelCase")] 11 | pub enum MoreOptions { 12 | News(bool), 13 | Exactly { config: String }, 14 | Built { top: MoreOptions }, 15 | } 16 | -------------------------------------------------------------------------------- /core/data/tests/recursive_enum_decorator/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | /// Generated type representing the anonymous struct variant `Exactly` of the `MoreOptions` Rust enum 7 | @Serializable 8 | data class MoreOptionsExactlyInner ( 9 | val config: String 10 | ) 11 | 12 | /// Generated type representing the anonymous struct variant `Built` of the `MoreOptions` Rust enum 13 | @Serializable 14 | data class MoreOptionsBuiltInner ( 15 | val top: MoreOptions 16 | ) 17 | 18 | @Serializable 19 | sealed class MoreOptions { 20 | @Serializable 21 | @SerialName("news") 22 | data class News(val content: Boolean): MoreOptions() 23 | @Serializable 24 | @SerialName("exactly") 25 | data class Exactly(val content: MoreOptionsExactlyInner): MoreOptions() 26 | @Serializable 27 | @SerialName("built") 28 | data class Built(val content: MoreOptionsBuiltInner): MoreOptions() 29 | } 30 | 31 | @Serializable 32 | sealed class Options { 33 | @Serializable 34 | @SerialName("red") 35 | data class Red(val content: Boolean): Options() 36 | @Serializable 37 | @SerialName("banana") 38 | data class Banana(val content: String): Options() 39 | @Serializable 40 | @SerialName("vermont") 41 | data class Vermont(val content: Options): Options() 42 | } 43 | 44 | -------------------------------------------------------------------------------- /core/data/tests/recursive_enum_decorator/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from enum import Enum 4 | from pydantic import BaseModel 5 | from typing import Literal, Union 6 | 7 | 8 | class MoreOptionsExactlyInner(BaseModel): 9 | """ 10 | Generated type representing the anonymous struct variant `Exactly` of the `MoreOptions` Rust enum 11 | """ 12 | config: str 13 | 14 | class MoreOptionsBuiltInner(BaseModel): 15 | """ 16 | Generated type representing the anonymous struct variant `Built` of the `MoreOptions` Rust enum 17 | """ 18 | top: MoreOptions 19 | 20 | class MoreOptionsTypes(str, Enum): 21 | NEWS = "news" 22 | EXACTLY = "exactly" 23 | BUILT = "built" 24 | 25 | class MoreOptionsNews(BaseModel): 26 | type: Literal[MoreOptionsTypes.NEWS] = MoreOptionsTypes.NEWS 27 | content: bool 28 | 29 | class MoreOptionsExactly(BaseModel): 30 | type: Literal[MoreOptionsTypes.EXACTLY] = MoreOptionsTypes.EXACTLY 31 | content: MoreOptionsExactlyInner 32 | 33 | class MoreOptionsBuilt(BaseModel): 34 | type: Literal[MoreOptionsTypes.BUILT] = MoreOptionsTypes.BUILT 35 | content: MoreOptionsBuiltInner 36 | 37 | MoreOptions = Union[MoreOptionsNews, MoreOptionsExactly, MoreOptionsBuilt] 38 | class OptionsTypes(str, Enum): 39 | RED = "red" 40 | BANANA = "banana" 41 | VERMONT = "vermont" 42 | 43 | class OptionsRed(BaseModel): 44 | type: Literal[OptionsTypes.RED] = OptionsTypes.RED 45 | content: bool 46 | 47 | class OptionsBanana(BaseModel): 48 | type: Literal[OptionsTypes.BANANA] = OptionsTypes.BANANA 49 | content: str 50 | 51 | class OptionsVermont(BaseModel): 52 | type: Literal[OptionsTypes.VERMONT] = OptionsTypes.VERMONT 53 | content: Options 54 | 55 | Options = Union[OptionsRed, OptionsBanana, OptionsVermont] 56 | -------------------------------------------------------------------------------- /core/data/tests/recursive_enum_decorator/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package onepassword { 4 | 5 | // Generated type representing the anonymous struct variant `Exactly` of the `MoreOptions` Rust enum 6 | case class MoreOptionsExactlyInner ( 7 | config: String 8 | ) 9 | 10 | // Generated type representing the anonymous struct variant `Built` of the `MoreOptions` Rust enum 11 | case class MoreOptionsBuiltInner ( 12 | top: MoreOptions 13 | ) 14 | 15 | sealed trait MoreOptions { 16 | def serialName: String 17 | } 18 | object MoreOptions { 19 | case class News(content: Boolean) extends MoreOptions { 20 | val serialName: String = "news" 21 | } 22 | case class Exactly(content: MoreOptionsExactlyInner) extends MoreOptions { 23 | val serialName: String = "exactly" 24 | } 25 | case class Built(content: MoreOptionsBuiltInner) extends MoreOptions { 26 | val serialName: String = "built" 27 | } 28 | } 29 | 30 | sealed trait Options { 31 | def serialName: String 32 | } 33 | object Options { 34 | case class Red(content: Boolean) extends Options { 35 | val serialName: String = "red" 36 | } 37 | case class Banana(content: String) extends Options { 38 | val serialName: String = "banana" 39 | } 40 | case class Vermont(content: Options) extends Options { 41 | val serialName: String = "vermont" 42 | } 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /core/data/tests/recursive_enum_decorator/output.ts: -------------------------------------------------------------------------------- 1 | export type MoreOptions = 2 | | { type: "news", content: boolean } 3 | | { type: "exactly", content: { 4 | config: string; 5 | }} 6 | | { type: "built", content: { 7 | top: MoreOptions; 8 | }}; 9 | 10 | export type Options = 11 | | { type: "red", content: boolean } 12 | | { type: "banana", content: string } 13 | | { type: "vermont", content: Options }; 14 | 15 | -------------------------------------------------------------------------------- /core/data/tests/resolves_qualified_type/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | struct QualifiedTypes { 3 | unqualified: String, 4 | qualified: std::string::String, 5 | qualified_vec: Vec, 6 | qualified_hashmap: HashMap, 7 | qualified_optional: Option, 8 | qualfied_optional_hashmap_vec: Option>> 9 | } -------------------------------------------------------------------------------- /core/data/tests/resolves_qualified_type/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | type QualifiedTypes struct { 6 | Unqualified string `json:"unqualified"` 7 | Qualified string `json:"qualified"` 8 | QualifiedVec []string `json:"qualified_vec"` 9 | QualifiedHashmap map[string]string `json:"qualified_hashmap"` 10 | QualifiedOptional *string `json:"qualified_optional,omitempty"` 11 | QualfiedOptionalHashmapVec *map[string][]string `json:"qualfied_optional_hashmap_vec,omitempty"` 12 | } 13 | -------------------------------------------------------------------------------- /core/data/tests/resolves_qualified_type/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | @Serializable 7 | data class QualifiedTypes ( 8 | val unqualified: String, 9 | val qualified: String, 10 | val qualified_vec: List, 11 | val qualified_hashmap: HashMap, 12 | val qualified_optional: String? = null, 13 | val qualfied_optional_hashmap_vec: HashMap>? = null 14 | ) 15 | 16 | -------------------------------------------------------------------------------- /core/data/tests/resolves_qualified_type/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pydantic import BaseModel, Field 4 | from typing import Dict, List, Optional 5 | 6 | 7 | class QualifiedTypes(BaseModel): 8 | unqualified: str 9 | qualified: str 10 | qualified_vec: List[str] 11 | qualified_hashmap: Dict[str, str] 12 | qualified_optional: Optional[str] = Field(default=None) 13 | qualfied_optional_hashmap_vec: Optional[Dict[str, List[str]]] = Field(default=None) 14 | 15 | -------------------------------------------------------------------------------- /core/data/tests/resolves_qualified_type/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package onepassword { 4 | 5 | case class QualifiedTypes ( 6 | unqualified: String, 7 | qualified: String, 8 | qualified_vec: Vector[String], 9 | qualified_hashmap: Map[String, String], 10 | qualified_optional: Option[String] = None, 11 | qualfied_optional_hashmap_vec: Option[Map[String, Vector[String]]] = None 12 | ) 13 | 14 | } 15 | -------------------------------------------------------------------------------- /core/data/tests/resolves_qualified_type/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct CoreQualifiedTypes: Codable { 4 | public let unqualified: String 5 | public let qualified: String 6 | public let qualified_vec: [String] 7 | public let qualified_hashmap: [String: String] 8 | public let qualified_optional: String? 9 | public let qualfied_optional_hashmap_vec: [String: [String]]? 10 | 11 | public init(unqualified: String, qualified: String, qualified_vec: [String], qualified_hashmap: [String: String], qualified_optional: String?, qualfied_optional_hashmap_vec: [String: [String]]?) { 12 | self.unqualified = unqualified 13 | self.qualified = qualified 14 | self.qualified_vec = qualified_vec 15 | self.qualified_hashmap = qualified_hashmap 16 | self.qualified_optional = qualified_optional 17 | self.qualfied_optional_hashmap_vec = qualfied_optional_hashmap_vec 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /core/data/tests/resolves_qualified_type/output.ts: -------------------------------------------------------------------------------- 1 | export interface QualifiedTypes { 2 | unqualified: string; 3 | qualified: string; 4 | qualified_vec: string[]; 5 | qualified_hashmap: Record; 6 | qualified_optional?: string; 7 | qualfied_optional_hashmap_vec?: Record; 8 | } 9 | 10 | -------------------------------------------------------------------------------- /core/data/tests/serde_rename_references/input.rs: -------------------------------------------------------------------------------- 1 | //! Test references to a type that has been renamed via serde(rename) 2 | //! 3 | 4 | #[derive(Serialize)] 5 | #[serde(rename = "SomethingFoo")] 6 | #[typeshare] 7 | pub enum Foo { 8 | A, 9 | } 10 | 11 | #[derive(Serialize)] 12 | #[typeshare] 13 | #[serde(tag = "type", content = "value")] 14 | pub enum Parent { 15 | B(Foo), 16 | } 17 | 18 | #[derive(Serialize)] 19 | #[typeshare] 20 | pub struct Test { 21 | field1: Foo, 22 | field2: Option, 23 | } 24 | 25 | #[derive(Serialize)] 26 | #[typeshare] 27 | pub type AliasTest = Vec; 28 | -------------------------------------------------------------------------------- /core/data/tests/serde_rename_references/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | type AliasTest []SomethingFoo 6 | 7 | type Test struct { 8 | Field1 SomethingFoo `json:"field1"` 9 | Field2 *SomethingFoo `json:"field2,omitempty"` 10 | } 11 | type Foo string 12 | const ( 13 | FooA Foo = "A" 14 | ) 15 | type ParentTypes string 16 | const ( 17 | ParentTypeVariantB ParentTypes = "B" 18 | ) 19 | type Parent struct{ 20 | Type ParentTypes `json:"type"` 21 | value interface{} 22 | } 23 | 24 | func (p *Parent) UnmarshalJSON(data []byte) error { 25 | var enum struct { 26 | Tag ParentTypes `json:"type"` 27 | Content json.RawMessage `json:"value"` 28 | } 29 | if err := json.Unmarshal(data, &enum); err != nil { 30 | return err 31 | } 32 | 33 | p.Type = enum.Tag 34 | switch p.Type { 35 | case ParentTypeVariantB: 36 | var res SomethingFoo 37 | p.value = &res 38 | 39 | } 40 | if err := json.Unmarshal(enum.Content, &p.value); err != nil { 41 | return err 42 | } 43 | 44 | return nil 45 | } 46 | 47 | func (p Parent) MarshalJSON() ([]byte, error) { 48 | var enum struct { 49 | Tag ParentTypes `json:"type"` 50 | Content interface{} `json:"value,omitempty"` 51 | } 52 | enum.Tag = p.Type 53 | enum.Content = p.value 54 | return json.Marshal(enum) 55 | } 56 | 57 | func (p Parent) B() SomethingFoo { 58 | res, _ := p.value.(*SomethingFoo) 59 | return *res 60 | } 61 | 62 | func NewParentTypeVariantB(content SomethingFoo) Parent { 63 | return Parent{ 64 | Type: ParentTypeVariantB, 65 | value: &content, 66 | } 67 | } 68 | 69 | -------------------------------------------------------------------------------- /core/data/tests/serde_rename_references/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | typealias AliasTest = List 7 | 8 | @Serializable 9 | data class Test ( 10 | val field1: SomethingFoo, 11 | val field2: SomethingFoo? = null 12 | ) 13 | 14 | @Serializable 15 | enum class SomethingFoo(val string: String) { 16 | @SerialName("A") 17 | A("A"), 18 | } 19 | 20 | @Serializable 21 | sealed class Parent { 22 | @Serializable 23 | @SerialName("B") 24 | data class B(val value: SomethingFoo): Parent() 25 | } 26 | 27 | -------------------------------------------------------------------------------- /core/data/tests/serde_rename_references/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package object onepassword { 4 | 5 | type AliasTest = Vector[SomethingFoo] 6 | 7 | } 8 | package onepassword { 9 | 10 | case class Test ( 11 | field1: SomethingFoo, 12 | field2: Option[SomethingFoo] = None 13 | ) 14 | 15 | sealed trait SomethingFoo { 16 | def serialName: String 17 | } 18 | object SomethingFoo { 19 | case object A extends SomethingFoo { 20 | val serialName: String = "A" 21 | } 22 | } 23 | 24 | sealed trait Parent { 25 | def serialName: String 26 | } 27 | object Parent { 28 | case class B(value: SomethingFoo) extends Parent { 29 | val serialName: String = "B" 30 | } 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /core/data/tests/serde_rename_references/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public typealias AliasTest = [SomethingFoo] 4 | 5 | public struct Test: Codable { 6 | public let field1: SomethingFoo 7 | public let field2: SomethingFoo? 8 | 9 | public init(field1: SomethingFoo, field2: SomethingFoo?) { 10 | self.field1 = field1 11 | self.field2 = field2 12 | } 13 | } 14 | 15 | public enum SomethingFoo: String, Codable { 16 | case a = "A" 17 | } 18 | 19 | public enum Parent: Codable { 20 | case b(SomethingFoo) 21 | 22 | enum CodingKeys: String, CodingKey, Codable { 23 | case b = "B" 24 | } 25 | 26 | private enum ContainerCodingKeys: String, CodingKey { 27 | case type, value 28 | } 29 | 30 | public init(from decoder: Decoder) throws { 31 | let container = try decoder.container(keyedBy: ContainerCodingKeys.self) 32 | if let type = try? container.decode(CodingKeys.self, forKey: .type) { 33 | switch type { 34 | case .b: 35 | if let content = try? container.decode(SomethingFoo.self, forKey: .value) { 36 | self = .b(content) 37 | return 38 | } 39 | } 40 | } 41 | throw DecodingError.typeMismatch(Parent.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for Parent")) 42 | } 43 | 44 | public func encode(to encoder: Encoder) throws { 45 | var container = encoder.container(keyedBy: ContainerCodingKeys.self) 46 | switch self { 47 | case .b(let content): 48 | try container.encode(CodingKeys.b, forKey: .type) 49 | try container.encode(content, forKey: .value) 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /core/data/tests/serde_rename_references/output.ts: -------------------------------------------------------------------------------- 1 | export type AliasTest = SomethingFoo[]; 2 | 3 | export interface Test { 4 | field1: SomethingFoo; 5 | field2?: SomethingFoo; 6 | } 7 | 8 | export enum SomethingFoo { 9 | A = "A", 10 | } 11 | 12 | export type Parent = 13 | | { type: "B", value: SomethingFoo }; 14 | 15 | -------------------------------------------------------------------------------- /core/data/tests/serialize_anonymous_field_as/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | #[derive(Serialize, Debug)] 3 | #[serde(tag = "type", content = "content")] 4 | pub enum SomeEnum { 5 | /// The associated String contains some opaque context 6 | Context(#[typeshare(serialized_as = "String")] SomeOtherType), 7 | Other(i32), 8 | } 9 | -------------------------------------------------------------------------------- /core/data/tests/serialize_anonymous_field_as/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | @Serializable 7 | sealed class SomeEnum { 8 | /// The associated String contains some opaque context 9 | @Serializable 10 | @SerialName("Context") 11 | data class Context(val content: String): SomeEnum() 12 | @Serializable 13 | @SerialName("Other") 14 | data class Other(val content: Int): SomeEnum() 15 | } 16 | 17 | -------------------------------------------------------------------------------- /core/data/tests/serialize_anonymous_field_as/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from enum import Enum 4 | from pydantic import BaseModel 5 | from typing import Literal, Union 6 | 7 | 8 | class SomeEnumTypes(str, Enum): 9 | CONTEXT = "Context" 10 | OTHER = "Other" 11 | 12 | class SomeEnumContext(BaseModel): 13 | """ 14 | The associated String contains some opaque context 15 | """ 16 | type: Literal[SomeEnumTypes.CONTEXT] = SomeEnumTypes.CONTEXT 17 | content: str 18 | 19 | class SomeEnumOther(BaseModel): 20 | type: Literal[SomeEnumTypes.OTHER] = SomeEnumTypes.OTHER 21 | content: int 22 | 23 | SomeEnum = Union[SomeEnumContext, SomeEnumOther] 24 | -------------------------------------------------------------------------------- /core/data/tests/serialize_anonymous_field_as/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package onepassword { 4 | 5 | sealed trait SomeEnum { 6 | def serialName: String 7 | } 8 | object SomeEnum { 9 | // The associated String contains some opaque context 10 | case class Context(content: String) extends SomeEnum { 11 | val serialName: String = "Context" 12 | } 13 | case class Other(content: Int) extends SomeEnum { 14 | val serialName: String = "Other" 15 | } 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /core/data/tests/serialize_anonymous_field_as/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public enum SomeEnum: Codable { 4 | /// The associated String contains some opaque context 5 | case context(String) 6 | case other(Int32) 7 | 8 | enum CodingKeys: String, CodingKey, Codable { 9 | case context = "Context", 10 | other = "Other" 11 | } 12 | 13 | private enum ContainerCodingKeys: String, CodingKey { 14 | case type, content 15 | } 16 | 17 | public init(from decoder: Decoder) throws { 18 | let container = try decoder.container(keyedBy: ContainerCodingKeys.self) 19 | if let type = try? container.decode(CodingKeys.self, forKey: .type) { 20 | switch type { 21 | case .context: 22 | if let content = try? container.decode(String.self, forKey: .content) { 23 | self = .context(content) 24 | return 25 | } 26 | case .other: 27 | if let content = try? container.decode(Int32.self, forKey: .content) { 28 | self = .other(content) 29 | return 30 | } 31 | } 32 | } 33 | throw DecodingError.typeMismatch(SomeEnum.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for SomeEnum")) 34 | } 35 | 36 | public func encode(to encoder: Encoder) throws { 37 | var container = encoder.container(keyedBy: ContainerCodingKeys.self) 38 | switch self { 39 | case .context(let content): 40 | try container.encode(CodingKeys.context, forKey: .type) 41 | try container.encode(content, forKey: .content) 42 | case .other(let content): 43 | try container.encode(CodingKeys.other, forKey: .type) 44 | try container.encode(content, forKey: .content) 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /core/data/tests/serialize_anonymous_field_as/output.ts: -------------------------------------------------------------------------------- 1 | export type SomeEnum = 2 | /** The associated String contains some opaque context */ 3 | | { type: "Context", content: string } 4 | | { type: "Other", content: number }; 5 | 6 | -------------------------------------------------------------------------------- /core/data/tests/serialize_field_as/input.rs: -------------------------------------------------------------------------------- 1 | #[derive(Serialize, Deserialize, Debug)] 2 | pub(super) struct Context { 3 | pub urls: Vec, 4 | pub apps: Vec, 5 | } 6 | 7 | #[typeshare] 8 | #[derive(Serialize, Deserialize, Debug)] 9 | pub struct EditItemViewModelSaveRequest { 10 | #[typeshare(serialized_as = "String")] 11 | pub(super) context: Context, 12 | 13 | pub values: Vec, 14 | pub fill_action: Option, 15 | } 16 | -------------------------------------------------------------------------------- /core/data/tests/serialize_field_as/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | type EditItemViewModelSaveRequest struct { 6 | Context string `json:"context"` 7 | Values []EditItemSaveValue `json:"values"` 8 | FillAction *AutoFillItemActionRequest `json:"fill_action,omitempty"` 9 | } 10 | -------------------------------------------------------------------------------- /core/data/tests/serialize_field_as/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | @Serializable 7 | data class EditItemViewModelSaveRequest ( 8 | val context: String, 9 | val values: List, 10 | val fill_action: AutoFillItemActionRequest? = null 11 | ) 12 | 13 | -------------------------------------------------------------------------------- /core/data/tests/serialize_field_as/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pydantic import BaseModel, Field 4 | from typing import List, Optional 5 | 6 | 7 | class EditItemViewModelSaveRequest(BaseModel): 8 | context: str 9 | values: List[EditItemSaveValue] 10 | fill_action: Optional[AutoFillItemActionRequest] = Field(default=None) 11 | 12 | -------------------------------------------------------------------------------- /core/data/tests/serialize_field_as/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package onepassword { 4 | 5 | case class EditItemViewModelSaveRequest ( 6 | context: String, 7 | values: Vector[EditItemSaveValue], 8 | fill_action: Option[AutoFillItemActionRequest] = None 9 | ) 10 | 11 | } 12 | -------------------------------------------------------------------------------- /core/data/tests/serialize_field_as/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct EditItemViewModelSaveRequest: Codable { 4 | public let context: String 5 | public let values: [EditItemSaveValue] 6 | public let fill_action: AutoFillItemActionRequest? 7 | 8 | public init(context: String, values: [EditItemSaveValue], fill_action: AutoFillItemActionRequest?) { 9 | self.context = context 10 | self.values = values 11 | self.fill_action = fill_action 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /core/data/tests/serialize_field_as/output.ts: -------------------------------------------------------------------------------- 1 | export interface EditItemViewModelSaveRequest { 2 | context: string; 3 | values: EditItemSaveValue[]; 4 | fill_action?: AutoFillItemActionRequest; 5 | } 6 | 7 | -------------------------------------------------------------------------------- /core/data/tests/serialize_type_alias/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | type AlsoString = String; 3 | 4 | #[typeshare(serialized_as = "String")] 5 | struct Uuid(String); 6 | 7 | #[typeshare] 8 | /// Unique identifier for an Account 9 | type AccountUuid = Uuid; 10 | 11 | #[typeshare(serialized_as = "String")] 12 | type ItemUuid = Uuid; 13 | -------------------------------------------------------------------------------- /core/data/tests/serialize_type_alias/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | type Uuid string 6 | 7 | // Unique identifier for an Account 8 | type AccountUuid Uuid 9 | 10 | type AlsoString string 11 | 12 | type ItemUuid string 13 | 14 | -------------------------------------------------------------------------------- /core/data/tests/serialize_type_alias/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | typealias Uuid = String 7 | 8 | /// Unique identifier for an Account 9 | typealias AccountUuid = Uuid 10 | 11 | typealias AlsoString = String 12 | 13 | typealias ItemUuid = String 14 | 15 | -------------------------------------------------------------------------------- /core/data/tests/serialize_type_alias/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | 4 | 5 | 6 | Uuid = str 7 | 8 | AccountUuid = Uuid 9 | 10 | """ 11 | Unique identifier for an Account 12 | """ 13 | AlsoString = str 14 | 15 | ItemUuid = str 16 | 17 | -------------------------------------------------------------------------------- /core/data/tests/serialize_type_alias/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package object onepassword { 4 | 5 | // Unique identifier for an Account 6 | type AccountUuid = Uuid 7 | 8 | type AlsoString = String 9 | 10 | type ItemUuid = String 11 | 12 | type Uuid = String 13 | 14 | } 15 | -------------------------------------------------------------------------------- /core/data/tests/serialize_type_alias/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public typealias Uuid = String 4 | 5 | /// Unique identifier for an Account 6 | public typealias AccountUuid = Uuid 7 | 8 | public typealias AlsoString = String 9 | 10 | public typealias ItemUuid = String 11 | -------------------------------------------------------------------------------- /core/data/tests/serialize_type_alias/output.ts: -------------------------------------------------------------------------------- 1 | export type Uuid = string; 2 | 3 | /** Unique identifier for an Account */ 4 | export type AccountUuid = Uuid; 5 | 6 | export type AlsoString = string; 7 | 8 | export type ItemUuid = string; 9 | 10 | -------------------------------------------------------------------------------- /core/data/tests/smart_pointers/input.rs: -------------------------------------------------------------------------------- 1 | /// This is a comment. 2 | #[typeshare] 3 | #[serde(tag = "type", content = "content")] 4 | pub enum BoxyColors { 5 | Red, 6 | Blue, 7 | Green(Box), 8 | } 9 | 10 | /// This is a comment. 11 | #[typeshare] 12 | #[serde(tag = "type", content = "content")] 13 | pub struct ArcyColors { 14 | pub red: Weak, 15 | pub blue: ArcWeak, 16 | pub green: Arc>, 17 | } 18 | 19 | /// This is a comment. 20 | #[typeshare] 21 | #[serde(tag = "type", content = "content")] 22 | pub struct MutexyColors { 23 | pub blue: Mutex>, 24 | pub green: Mutex, 25 | } 26 | 27 | /// This is a comment. 28 | #[typeshare] 29 | #[serde(tag = "type", content = "content")] 30 | pub struct RcyColors { 31 | pub red: RcWeak, 32 | pub blue: Rc>, 33 | pub green: Rc, 34 | } 35 | 36 | /// This is a comment. 37 | #[typeshare] 38 | #[serde(tag = "type", content = "content")] 39 | pub struct CellyColors { 40 | pub red: Cell, 41 | pub blue: RefCell>, 42 | } 43 | 44 | /// This is a comment. 45 | #[typeshare] 46 | #[serde(tag = "type", content = "content")] 47 | pub struct LockyColors { 48 | pub red: RwLock, 49 | } 50 | 51 | /// This is a comment. 52 | #[typeshare] 53 | #[serde(tag = "type", content = "content")] 54 | pub struct CowyColors<'a> { 55 | pub lifetime: Cow<'a, str>, 56 | } 57 | -------------------------------------------------------------------------------- /core/data/tests/smart_pointers/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | /// This is a comment. 7 | @Serializable 8 | data class ArcyColors ( 9 | val red: UByte, 10 | val blue: String, 11 | val green: List 12 | ) 13 | 14 | /// This is a comment. 15 | @Serializable 16 | data class CellyColors ( 17 | val red: String, 18 | val blue: List 19 | ) 20 | 21 | /// This is a comment. 22 | @Serializable 23 | data class CowyColors ( 24 | val lifetime: String 25 | ) 26 | 27 | /// This is a comment. 28 | @Serializable 29 | data class LockyColors ( 30 | val red: String 31 | ) 32 | 33 | /// This is a comment. 34 | @Serializable 35 | data class MutexyColors ( 36 | val blue: List, 37 | val green: String 38 | ) 39 | 40 | /// This is a comment. 41 | @Serializable 42 | data class RcyColors ( 43 | val red: String, 44 | val blue: List, 45 | val green: String 46 | ) 47 | 48 | /// This is a comment. 49 | @Serializable 50 | sealed class BoxyColors { 51 | @Serializable 52 | @SerialName("Red") 53 | object Red: BoxyColors() 54 | @Serializable 55 | @SerialName("Blue") 56 | object Blue: BoxyColors() 57 | @Serializable 58 | @SerialName("Green") 59 | data class Green(val content: String): BoxyColors() 60 | } 61 | 62 | -------------------------------------------------------------------------------- /core/data/tests/smart_pointers/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from enum import Enum 4 | from pydantic import BaseModel 5 | from typing import List, Literal, Union 6 | 7 | 8 | class ArcyColors(BaseModel): 9 | """ 10 | This is a comment. 11 | """ 12 | red: int 13 | blue: str 14 | green: List[str] 15 | 16 | class CellyColors(BaseModel): 17 | """ 18 | This is a comment. 19 | """ 20 | red: str 21 | blue: List[str] 22 | 23 | class CowyColors(BaseModel): 24 | """ 25 | This is a comment. 26 | """ 27 | lifetime: str 28 | 29 | class LockyColors(BaseModel): 30 | """ 31 | This is a comment. 32 | """ 33 | red: str 34 | 35 | class MutexyColors(BaseModel): 36 | """ 37 | This is a comment. 38 | """ 39 | blue: List[str] 40 | green: str 41 | 42 | class RcyColors(BaseModel): 43 | """ 44 | This is a comment. 45 | """ 46 | red: str 47 | blue: List[str] 48 | green: str 49 | 50 | class BoxyColorsTypes(str, Enum): 51 | RED = "Red" 52 | BLUE = "Blue" 53 | GREEN = "Green" 54 | 55 | class BoxyColorsRed(BaseModel): 56 | type: Literal[BoxyColorsTypes.RED] = BoxyColorsTypes.RED 57 | 58 | class BoxyColorsBlue(BaseModel): 59 | type: Literal[BoxyColorsTypes.BLUE] = BoxyColorsTypes.BLUE 60 | 61 | class BoxyColorsGreen(BaseModel): 62 | type: Literal[BoxyColorsTypes.GREEN] = BoxyColorsTypes.GREEN 63 | content: str 64 | 65 | # This is a comment. 66 | BoxyColors = Union[BoxyColorsRed, BoxyColorsBlue, BoxyColorsGreen] 67 | -------------------------------------------------------------------------------- /core/data/tests/smart_pointers/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package object onepassword { 4 | 5 | type UByte = Byte 6 | type UShort = Short 7 | type UInt = Int 8 | type ULong = Int 9 | 10 | } 11 | package onepassword { 12 | 13 | // This is a comment. 14 | case class ArcyColors ( 15 | red: UByte, 16 | blue: String, 17 | green: Vector[String] 18 | ) 19 | 20 | // This is a comment. 21 | case class CellyColors ( 22 | red: String, 23 | blue: Vector[String] 24 | ) 25 | 26 | // This is a comment. 27 | case class CowyColors ( 28 | lifetime: String 29 | ) 30 | 31 | // This is a comment. 32 | case class LockyColors ( 33 | red: String 34 | ) 35 | 36 | // This is a comment. 37 | case class MutexyColors ( 38 | blue: Vector[String], 39 | green: String 40 | ) 41 | 42 | // This is a comment. 43 | case class RcyColors ( 44 | red: String, 45 | blue: Vector[String], 46 | green: String 47 | ) 48 | 49 | // This is a comment. 50 | sealed trait BoxyColors { 51 | def serialName: String 52 | } 53 | object BoxyColors { 54 | case object Red extends BoxyColors { 55 | val serialName: String = "Red" 56 | } 57 | case object Blue extends BoxyColors { 58 | val serialName: String = "Blue" 59 | } 60 | case class Green(content: String) extends BoxyColors { 61 | val serialName: String = "Green" 62 | } 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /core/data/tests/smart_pointers/output.ts: -------------------------------------------------------------------------------- 1 | /** This is a comment. */ 2 | export interface ArcyColors { 3 | red: number; 4 | blue: string; 5 | green: string[]; 6 | } 7 | 8 | /** This is a comment. */ 9 | export interface CellyColors { 10 | red: string; 11 | blue: string[]; 12 | } 13 | 14 | /** This is a comment. */ 15 | export interface CowyColors { 16 | lifetime: string; 17 | } 18 | 19 | /** This is a comment. */ 20 | export interface LockyColors { 21 | red: string; 22 | } 23 | 24 | /** This is a comment. */ 25 | export interface MutexyColors { 26 | blue: string[]; 27 | green: string; 28 | } 29 | 30 | /** This is a comment. */ 31 | export interface RcyColors { 32 | red: string; 33 | blue: string[]; 34 | green: string; 35 | } 36 | 37 | /** This is a comment. */ 38 | export type BoxyColors = 39 | | { type: "Red", content?: undefined } 40 | | { type: "Blue", content?: undefined } 41 | | { type: "Green", content: string }; 42 | 43 | -------------------------------------------------------------------------------- /core/data/tests/struct_decorator/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | pub struct BestHockeyTeams { 3 | PittsburghPenguins: u32, 4 | Lies: String, 5 | } 6 | #[typeshare(swift = "Equatable")] 7 | pub struct BestHockeyTeams1 { 8 | PittsburghPenguins: u32, 9 | Lies: String, 10 | } 11 | 12 | #[typeshare(swift = "Equatable, Codable, Comparable, Hashable")] 13 | pub struct BestHockeyTeams2 { 14 | PittsburghPenguins: u32, 15 | Lies: String, 16 | } 17 | 18 | #[typeshare(redacted)] 19 | pub struct BestHockeyTeams3 { 20 | PittsburghPenguins: u32, 21 | Lies: String, 22 | } 23 | 24 | #[typeshare(swift = "Equatable", swift = "Hashable")] 25 | pub struct BestHockeyTeams4 { 26 | PittsburghPenguins: u32, 27 | Lies: String, 28 | } 29 | 30 | #[typeshare(kotlin = "JvmInline", redacted)] 31 | pub struct BestHockeyTeams5(String); 32 | -------------------------------------------------------------------------------- /core/data/tests/struct_decorator/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | @Serializable 7 | @JvmInline 8 | value class BestHockeyTeams5( 9 | private val value: String 10 | ) { 11 | fun unwrap() = value 12 | 13 | override fun toString(): String = "***" 14 | } 15 | 16 | @Serializable 17 | data class BestHockeyTeams ( 18 | val PittsburghPenguins: UInt, 19 | val Lies: String 20 | ) 21 | 22 | @Serializable 23 | data class BestHockeyTeams1 ( 24 | val PittsburghPenguins: UInt, 25 | val Lies: String 26 | ) 27 | 28 | @Serializable 29 | data class BestHockeyTeams2 ( 30 | val PittsburghPenguins: UInt, 31 | val Lies: String 32 | ) 33 | 34 | @Serializable 35 | data class BestHockeyTeams3 ( 36 | val PittsburghPenguins: UInt, 37 | val Lies: String 38 | ) { 39 | override fun toString(): String = "BestHockeyTeams3" 40 | } 41 | 42 | @Serializable 43 | data class BestHockeyTeams4 ( 44 | val PittsburghPenguins: UInt, 45 | val Lies: String 46 | ) 47 | 48 | -------------------------------------------------------------------------------- /core/data/tests/struct_decorator/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public typealias OPBestHockeyTeams5 = String 4 | 5 | public struct OPBestHockeyTeams: Codable { 6 | public let PittsburghPenguins: UInt32 7 | public let Lies: String 8 | 9 | public init(PittsburghPenguins: UInt32, Lies: String) { 10 | self.PittsburghPenguins = PittsburghPenguins 11 | self.Lies = Lies 12 | } 13 | } 14 | 15 | public struct OPBestHockeyTeams1: Codable, Equatable { 16 | public let PittsburghPenguins: UInt32 17 | public let Lies: String 18 | 19 | public init(PittsburghPenguins: UInt32, Lies: String) { 20 | self.PittsburghPenguins = PittsburghPenguins 21 | self.Lies = Lies 22 | } 23 | } 24 | 25 | public struct OPBestHockeyTeams2: Codable, Comparable, Equatable, Hashable { 26 | public let PittsburghPenguins: UInt32 27 | public let Lies: String 28 | 29 | public init(PittsburghPenguins: UInt32, Lies: String) { 30 | self.PittsburghPenguins = PittsburghPenguins 31 | self.Lies = Lies 32 | } 33 | } 34 | 35 | public struct OPBestHockeyTeams3: Codable { 36 | public let PittsburghPenguins: UInt32 37 | public let Lies: String 38 | 39 | public init(PittsburghPenguins: UInt32, Lies: String) { 40 | self.PittsburghPenguins = PittsburghPenguins 41 | self.Lies = Lies 42 | } 43 | } 44 | 45 | public struct OPBestHockeyTeams4: Codable, Equatable, Hashable { 46 | public let PittsburghPenguins: UInt32 47 | public let Lies: String 48 | 49 | public init(PittsburghPenguins: UInt32, Lies: String) { 50 | self.PittsburghPenguins = PittsburghPenguins 51 | self.Lies = Lies 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /core/data/tests/test_algebraic_enum_case_name_support/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | pub struct ItemDetailsFieldValue {} 3 | 4 | #[typeshare] 5 | #[serde(rename_all = "camelCase", tag = "type", content = "content")] 6 | pub enum AdvancedColors { 7 | String(String), 8 | Number(i32), 9 | #[serde(rename = "number-array")] 10 | NumberArray(Vec), 11 | #[serde(rename = "reallyCoolType")] 12 | ReallyCoolType(ItemDetailsFieldValue), 13 | } 14 | -------------------------------------------------------------------------------- /core/data/tests/test_algebraic_enum_case_name_support/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | @Serializable 7 | object ItemDetailsFieldValue 8 | 9 | @Serializable 10 | sealed class AdvancedColors { 11 | @Serializable 12 | @SerialName("string") 13 | data class String(val content: String): AdvancedColors() 14 | @Serializable 15 | @SerialName("number") 16 | data class Number(val content: Int): AdvancedColors() 17 | @Serializable 18 | @SerialName("number-array") 19 | data class NumberArray(val content: List): AdvancedColors() 20 | @Serializable 21 | @SerialName("reallyCoolType") 22 | data class ReallyCoolType(val content: ItemDetailsFieldValue): AdvancedColors() 23 | } 24 | 25 | -------------------------------------------------------------------------------- /core/data/tests/test_algebraic_enum_case_name_support/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from enum import Enum 4 | from pydantic import BaseModel 5 | from typing import List, Literal, Union 6 | 7 | 8 | class ItemDetailsFieldValue(BaseModel): 9 | pass 10 | class AdvancedColorsTypes(str, Enum): 11 | STRING = "string" 12 | NUMBER = "number" 13 | NUMBER_ARRAY = "number-array" 14 | REALLY_COOL_TYPE = "reallyCoolType" 15 | 16 | class AdvancedColorsString(BaseModel): 17 | type: Literal[AdvancedColorsTypes.STRING] = AdvancedColorsTypes.STRING 18 | content: str 19 | 20 | class AdvancedColorsNumber(BaseModel): 21 | type: Literal[AdvancedColorsTypes.NUMBER] = AdvancedColorsTypes.NUMBER 22 | content: int 23 | 24 | class AdvancedColorsNumberArray(BaseModel): 25 | type: Literal[AdvancedColorsTypes.NUMBER_ARRAY] = AdvancedColorsTypes.NUMBER_ARRAY 26 | content: List[int] 27 | 28 | class AdvancedColorsReallyCoolType(BaseModel): 29 | type: Literal[AdvancedColorsTypes.REALLY_COOL_TYPE] = AdvancedColorsTypes.REALLY_COOL_TYPE 30 | content: ItemDetailsFieldValue 31 | 32 | AdvancedColors = Union[AdvancedColorsString, AdvancedColorsNumber, AdvancedColorsNumberArray, AdvancedColorsReallyCoolType] 33 | -------------------------------------------------------------------------------- /core/data/tests/test_algebraic_enum_case_name_support/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package onepassword { 4 | 5 | class ItemDetailsFieldValue extends Serializable 6 | 7 | sealed trait AdvancedColors { 8 | def serialName: String 9 | } 10 | object AdvancedColors { 11 | case class String(content: String) extends AdvancedColors { 12 | val serialName: String = "string" 13 | } 14 | case class Number(content: Int) extends AdvancedColors { 15 | val serialName: String = "number" 16 | } 17 | case class NumberArray(content: Vector[Int]) extends AdvancedColors { 18 | val serialName: String = "number-array" 19 | } 20 | case class ReallyCoolType(content: ItemDetailsFieldValue) extends AdvancedColors { 21 | val serialName: String = "reallyCoolType" 22 | } 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /core/data/tests/test_algebraic_enum_case_name_support/output.ts: -------------------------------------------------------------------------------- 1 | export interface ItemDetailsFieldValue { 2 | } 3 | 4 | export type AdvancedColors = 5 | | { type: "string", content: string } 6 | | { type: "number", content: number } 7 | | { type: "number-array", content: number[] } 8 | | { type: "reallyCoolType", content: ItemDetailsFieldValue }; 9 | 10 | -------------------------------------------------------------------------------- /core/data/tests/test_custom_serialize_deserialize_functions/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | #[serde(rename_all = "camelCase")] 3 | pub struct Foo { 4 | pub time: time::OffsetDateTime, 5 | pub time2: time::OffsetDateTime, 6 | pub time3: time::OffsetDateTime, 7 | pub bytes: Vec, 8 | pub bytes2: Vec 9 | } 10 | 11 | #[typeshare] 12 | #[serde(rename_all = "camelCase")] 13 | pub struct TwoFoo { 14 | pub time: time::OffsetDateTime, 15 | pub bytes: Vec, 16 | } 17 | -------------------------------------------------------------------------------- /core/data/tests/test_custom_serialize_deserialize_functions/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import ( 4 | "encoding/json" 5 | "time" 6 | ) 7 | 8 | type Foo struct { 9 | Time time.Time `json:"time"` 10 | Time2 time.Time `json:"time2"` 11 | Time3 time.Time `json:"time3"` 12 | Bytes []byte `json:"bytes"` 13 | Bytes2 []byte `json:"bytes2"` 14 | } 15 | type TwoFoo struct { 16 | Time time.Time `json:"time"` 17 | Bytes []byte `json:"bytes"` 18 | } 19 | -------------------------------------------------------------------------------- /core/data/tests/test_custom_serialize_deserialize_functions/output.ts: -------------------------------------------------------------------------------- 1 | export interface Foo { 2 | time: Date; 3 | time2: Date; 4 | time3: Date; 5 | bytes: Uint8Array; 6 | bytes2: Uint8Array; 7 | } 8 | 9 | export interface TwoFoo { 10 | time: Date; 11 | bytes: Uint8Array; 12 | } 13 | 14 | /** 15 | * Custom JSON reviver and replacer functions for dynamic data transformation 16 | * ReviverFunc is used during JSON parsing to detect and transform specific data structures 17 | * ReplacerFunc is used during JSON serialization to modify certain values before stringifying. 18 | * These functions allow for flexible encoding and decoding of data, ensuring that complex types are properly handled when converting between TS objects and JSON 19 | */ 20 | export const ReviverFunc = (key: string, value: unknown): unknown => { 21 | if (typeof value === "string" && /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z$/.test(value) && (key === "time" || key === "time2" || key === "time3")) { 22 | return new Date(value); 23 | } 24 | if (Array.isArray(value) && value.every(v => Number.isInteger(v) && v >= 0 && v <= 255) && value.length > 0) { 25 | return new Uint8Array(value); 26 | } 27 | return value; 28 | }; 29 | 30 | export const ReplacerFunc = (key: string, value: unknown): unknown => { 31 | if (value instanceof Date) { 32 | return value.toISOString(); 33 | } 34 | if (value instanceof Uint8Array) { 35 | return Array.from(value); 36 | } 37 | return value; 38 | }; 39 | -------------------------------------------------------------------------------- /core/data/tests/test_default_decorators/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(swift = "Equatable")] 2 | struct EmptyType {} -------------------------------------------------------------------------------- /core/data/tests/test_default_decorators/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct EmptyType: Codable, Sendable, Identifiable, Equatable { 4 | public init() {} 5 | } 6 | -------------------------------------------------------------------------------- /core/data/tests/test_default_generic_constraints/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | struct GenericType { 3 | key: K, 4 | value: V 5 | } 6 | 7 | #[typeshare] 8 | #[serde(tag = "type", content = "content")] 9 | enum GenericEnum { 10 | Variant { 11 | key: K, 12 | value: V 13 | } 14 | } -------------------------------------------------------------------------------- /core/data/tests/test_generate_char/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | struct MyType { 3 | field: char, 4 | } 5 | -------------------------------------------------------------------------------- /core/data/tests/test_generate_char/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | type MyType struct { 6 | Field rune `json:"field"` 7 | } 8 | -------------------------------------------------------------------------------- /core/data/tests/test_generate_char/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | @Serializable 7 | data class MyType ( 8 | val field: String 9 | ) 10 | 11 | -------------------------------------------------------------------------------- /core/data/tests/test_generate_char/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pydantic import BaseModel 4 | 5 | 6 | class MyType(BaseModel): 7 | field: str 8 | 9 | -------------------------------------------------------------------------------- /core/data/tests/test_generate_char/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package onepassword { 4 | 5 | case class MyType ( 6 | field: String 7 | ) 8 | 9 | } 10 | -------------------------------------------------------------------------------- /core/data/tests/test_generate_char/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct MyType: Codable { 4 | public let field: Unicode.Scalar 5 | 6 | public init(field: Unicode.Scalar) { 7 | self.field = field 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /core/data/tests/test_generate_char/output.ts: -------------------------------------------------------------------------------- 1 | export interface MyType { 2 | field: string; 3 | } 4 | 5 | -------------------------------------------------------------------------------- /core/data/tests/test_i54_u53_type/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | #[serde(default, rename_all = "camelCase")] 3 | pub struct Foo { 4 | pub a: I54, 5 | pub b: U53, 6 | } 7 | -------------------------------------------------------------------------------- /core/data/tests/test_i54_u53_type/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | type Foo struct { 6 | A int64 `json:"a"` 7 | B uint64 `json:"b"` 8 | } 9 | -------------------------------------------------------------------------------- /core/data/tests/test_i54_u53_type/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | @Serializable 7 | data class Foo ( 8 | val a: Long, 9 | val b: ULong 10 | ) 11 | 12 | -------------------------------------------------------------------------------- /core/data/tests/test_i54_u53_type/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pydantic import BaseModel 4 | 5 | 6 | class Foo(BaseModel): 7 | a: int 8 | b: int 9 | 10 | -------------------------------------------------------------------------------- /core/data/tests/test_i54_u53_type/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package object onepassword { 4 | 5 | type UByte = Byte 6 | type UShort = Short 7 | type UInt = Int 8 | type ULong = Int 9 | 10 | } 11 | package onepassword { 12 | 13 | case class Foo ( 14 | a: Long, 15 | b: ULong 16 | ) 17 | 18 | } 19 | -------------------------------------------------------------------------------- /core/data/tests/test_i54_u53_type/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct Foo: Codable { 4 | public let a: Int64 5 | public let b: UInt64 6 | 7 | public init(a: Int64, b: UInt64) { 8 | self.a = a 9 | self.b = b 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /core/data/tests/test_i54_u53_type/output.ts: -------------------------------------------------------------------------------- 1 | export interface Foo { 2 | a: number; 3 | b: number; 4 | } 5 | 6 | -------------------------------------------------------------------------------- /core/data/tests/test_optional_type_alias/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | pub type OptionalU32 = Option; 3 | 4 | #[typeshare] 5 | pub struct OptionalU16(Option); 6 | 7 | #[typeshare] 8 | pub struct FooBar { 9 | foo: OptionalU32, 10 | bar: OptionalU16, 11 | } 12 | -------------------------------------------------------------------------------- /core/data/tests/test_optional_type_alias/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | type OptionalU16 *int 6 | 7 | type OptionalU32 *uint32 8 | 9 | type FooBar struct { 10 | Foo OptionalU32 `json:"foo"` 11 | Bar OptionalU16 `json:"bar"` 12 | } 13 | -------------------------------------------------------------------------------- /core/data/tests/test_optional_type_alias/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | typealias OptionalU16 = UShort? 7 | 8 | typealias OptionalU32 = UInt? 9 | 10 | @Serializable 11 | data class FooBar ( 12 | val foo: OptionalU32, 13 | val bar: OptionalU16 14 | ) 15 | 16 | -------------------------------------------------------------------------------- /core/data/tests/test_optional_type_alias/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pydantic import BaseModel 4 | from typing import Optional 5 | 6 | 7 | OptionalU16 = Optional[int] 8 | 9 | OptionalU32 = Optional[int] 10 | 11 | class FooBar(BaseModel): 12 | foo: OptionalU32 13 | bar: OptionalU16 14 | 15 | -------------------------------------------------------------------------------- /core/data/tests/test_optional_type_alias/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package object onepassword { 4 | 5 | type UByte = Byte 6 | type UShort = Short 7 | type UInt = Int 8 | type ULong = Int 9 | 10 | type OptionalU16 = Option[UShort] 11 | 12 | type OptionalU32 = Option[UInt] 13 | 14 | } 15 | package onepassword { 16 | 17 | case class FooBar ( 18 | foo: OptionalU32, 19 | bar: OptionalU16 20 | ) 21 | 22 | } 23 | -------------------------------------------------------------------------------- /core/data/tests/test_optional_type_alias/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public typealias OptionalU16 = UInt16? 4 | 5 | public typealias OptionalU32 = UInt32? 6 | 7 | public struct FooBar: Codable { 8 | public let foo: OptionalU32 9 | public let bar: OptionalU16 10 | 11 | public init(foo: OptionalU32, bar: OptionalU16) { 12 | self.foo = foo 13 | self.bar = bar 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /core/data/tests/test_optional_type_alias/output.ts: -------------------------------------------------------------------------------- 1 | export type OptionalU16 = number | undefined; 2 | 3 | export type OptionalU32 = number | undefined; 4 | 5 | export interface FooBar { 6 | foo: OptionalU32; 7 | bar: OptionalU16; 8 | } 9 | 10 | -------------------------------------------------------------------------------- /core/data/tests/test_serde_default_struct/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | #[serde(rename_all = "camelCase")] 3 | pub struct Foo { 4 | #[serde(default)] 5 | pub bar: bool, 6 | } 7 | -------------------------------------------------------------------------------- /core/data/tests/test_serde_default_struct/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | type Foo struct { 6 | Bar *bool `json:"bar,omitempty"` 7 | } 8 | -------------------------------------------------------------------------------- /core/data/tests/test_serde_default_struct/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | @Serializable 7 | data class Foo ( 8 | val bar: Boolean? = null 9 | ) 10 | 11 | -------------------------------------------------------------------------------- /core/data/tests/test_serde_default_struct/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pydantic import BaseModel, Field 4 | from typing import Optional 5 | 6 | 7 | class Foo(BaseModel): 8 | bar: Optional[bool] = Field(default=None) 9 | 10 | -------------------------------------------------------------------------------- /core/data/tests/test_serde_default_struct/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package onepassword { 4 | 5 | case class Foo ( 6 | bar: Boolean = _ 7 | ) 8 | 9 | } 10 | -------------------------------------------------------------------------------- /core/data/tests/test_serde_default_struct/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct Foo: Codable { 4 | public let bar: Bool? 5 | 6 | public init(bar: Bool?) { 7 | self.bar = bar 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /core/data/tests/test_serde_default_struct/output.ts: -------------------------------------------------------------------------------- 1 | export interface Foo { 2 | bar?: boolean; 3 | } 4 | 5 | -------------------------------------------------------------------------------- /core/data/tests/test_serde_iso8601/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | #[serde(rename_all = "camelCase")] 3 | pub struct Foo { 4 | pub time: DateTime, 5 | } 6 | -------------------------------------------------------------------------------- /core/data/tests/test_serde_iso8601/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | type Foo struct { 6 | Time string `json:"time"` 7 | } 8 | -------------------------------------------------------------------------------- /core/data/tests/test_serde_iso8601/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | @Serializable 7 | data class Foo ( 8 | val time: String 9 | ) 10 | 11 | -------------------------------------------------------------------------------- /core/data/tests/test_serde_iso8601/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from datetime import datetime 4 | from pydantic import BaseModel, BeforeValidator, PlainSerializer 5 | from typing import Annotated 6 | 7 | 8 | def serialize_datetime_data(utc_time: datetime) -> str: 9 | return utc_time.strftime("%Y-%m-%dT%H:%M:%S.%fZ") 10 | 11 | def parse_rfc3339(date_str: str) -> datetime: 12 | date_formats = [ 13 | "%Y-%m-%dT%H:%M:%SZ", 14 | "%Y-%m-%dT%H:%M:%S.%fZ" 15 | ] 16 | 17 | for fmt in date_formats: 18 | try: 19 | return datetime.strptime(date_str, fmt) 20 | except ValueError: 21 | continue 22 | 23 | raise ValueError(f"Invalid RFC 3339 date format: {date_str}") 24 | 25 | class Foo(BaseModel): 26 | time: Annotated[datetime, BeforeValidator(parse_rfc3339), PlainSerializer(serialize_datetime_data)] 27 | 28 | -------------------------------------------------------------------------------- /core/data/tests/test_serde_iso8601/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package onepassword { 4 | 5 | case class Foo ( 6 | time: String 7 | ) 8 | 9 | } 10 | -------------------------------------------------------------------------------- /core/data/tests/test_serde_iso8601/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct Foo: Codable { 4 | public let time: Date 5 | 6 | public init(time: Date) { 7 | self.time = time 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /core/data/tests/test_serde_iso8601/output.ts: -------------------------------------------------------------------------------- 1 | export interface Foo { 2 | time: string; 3 | } 4 | 5 | -------------------------------------------------------------------------------- /core/data/tests/test_serde_url/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | #[serde(rename_all = "camelCase")] 3 | pub struct Foo { 4 | pub url: url::Url, 5 | } 6 | -------------------------------------------------------------------------------- /core/data/tests/test_serde_url/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | type Foo struct { 6 | URL string `json:"url"` 7 | } 8 | -------------------------------------------------------------------------------- /core/data/tests/test_serde_url/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | @Serializable 7 | data class Foo ( 8 | val url: String 9 | ) 10 | 11 | -------------------------------------------------------------------------------- /core/data/tests/test_serde_url/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pydantic import BaseModel 4 | from pydantic.networks import AnyUrl 5 | 6 | 7 | class Foo(BaseModel): 8 | url: AnyUrl 9 | 10 | -------------------------------------------------------------------------------- /core/data/tests/test_serde_url/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package onepassword { 4 | 5 | case class Foo ( 6 | url: String 7 | ) 8 | 9 | } 10 | -------------------------------------------------------------------------------- /core/data/tests/test_serde_url/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct Foo: Codable { 4 | public let url: String 5 | 6 | public init(url: String) { 7 | self.url = url 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /core/data/tests/test_serde_url/output.ts: -------------------------------------------------------------------------------- 1 | export interface Foo { 2 | url: string; 3 | } 4 | 5 | -------------------------------------------------------------------------------- /core/data/tests/test_serialized_as/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(serialized_as = "String")] 2 | pub struct ItemId { 3 | inner: i64, 4 | } 5 | 6 | /// Options that you could pick 7 | #[typeshare(serialized_as = "String")] 8 | pub enum Options { 9 | /// Affirmative Response 10 | Yes, 11 | No, 12 | Maybe, 13 | /// Sends a string along 14 | Cool(String), 15 | } 16 | -------------------------------------------------------------------------------- /core/data/tests/test_serialized_as/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | type ItemId string 6 | 7 | // Options that you could pick 8 | type Options string 9 | 10 | -------------------------------------------------------------------------------- /core/data/tests/test_serialized_as/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | typealias ItemId = String 7 | 8 | /// Options that you could pick 9 | typealias Options = String 10 | 11 | -------------------------------------------------------------------------------- /core/data/tests/test_serialized_as/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | 4 | 5 | 6 | ItemId = str 7 | 8 | Options = str 9 | 10 | """ 11 | Options that you could pick 12 | """ 13 | -------------------------------------------------------------------------------- /core/data/tests/test_serialized_as/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package object onepassword { 4 | 5 | type ItemId = String 6 | 7 | // Options that you could pick 8 | type Options = String 9 | 10 | } 11 | -------------------------------------------------------------------------------- /core/data/tests/test_serialized_as/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public typealias OPItemId = String 4 | 5 | /// Options that you could pick 6 | public typealias OPOptions = String 7 | -------------------------------------------------------------------------------- /core/data/tests/test_serialized_as/output.ts: -------------------------------------------------------------------------------- 1 | export type ItemId = string; 2 | 3 | /** Options that you could pick */ 4 | export type Options = string; 5 | 6 | -------------------------------------------------------------------------------- /core/data/tests/test_serialized_as_tuple/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare(serialized_as = "String")] 2 | pub struct ItemId(i64); 3 | -------------------------------------------------------------------------------- /core/data/tests/test_serialized_as_tuple/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | type ItemID string 6 | 7 | -------------------------------------------------------------------------------- /core/data/tests/test_serialized_as_tuple/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | typealias ItemId = String 7 | 8 | -------------------------------------------------------------------------------- /core/data/tests/test_serialized_as_tuple/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | 4 | 5 | 6 | ItemId = str 7 | 8 | -------------------------------------------------------------------------------- /core/data/tests/test_serialized_as_tuple/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package object onepassword { 4 | 5 | type ItemId = String 6 | 7 | } 8 | -------------------------------------------------------------------------------- /core/data/tests/test_serialized_as_tuple/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public typealias OPItemId = String 4 | -------------------------------------------------------------------------------- /core/data/tests/test_serialized_as_tuple/output.ts: -------------------------------------------------------------------------------- 1 | export type ItemId = string; 2 | 3 | -------------------------------------------------------------------------------- /core/data/tests/test_simple_enum_case_name_support/input.rs: -------------------------------------------------------------------------------- 1 | /// This is a comment. 2 | #[typeshare] 3 | #[serde(rename_all = "camelCase")] 4 | pub enum Colors { 5 | Red, 6 | #[serde(rename = "blue-ish")] 7 | Blue, 8 | #[serde(rename = "Green")] 9 | Green, 10 | } 11 | -------------------------------------------------------------------------------- /core/data/tests/test_simple_enum_case_name_support/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | // This is a comment. 6 | type Colors string 7 | const ( 8 | ColorsRed Colors = "red" 9 | ColorsBlue Colors = "blue-ish" 10 | ColorsGreen Colors = "Green" 11 | ) 12 | -------------------------------------------------------------------------------- /core/data/tests/test_simple_enum_case_name_support/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | /// This is a comment. 7 | @Serializable 8 | enum class Colors(val string: String) { 9 | @SerialName("red") 10 | Red("red"), 11 | @SerialName("blue-ish") 12 | Blue("blue-ish"), 13 | @SerialName("Green") 14 | Green("Green"), 15 | } 16 | 17 | -------------------------------------------------------------------------------- /core/data/tests/test_simple_enum_case_name_support/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from enum import Enum 4 | 5 | 6 | class Colors(str, Enum): 7 | """ 8 | This is a comment. 9 | """ 10 | RED = "red" 11 | BLUE = "blue-ish" 12 | GREEN = "Green" 13 | -------------------------------------------------------------------------------- /core/data/tests/test_simple_enum_case_name_support/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package onepassword { 4 | 5 | // This is a comment. 6 | sealed trait Colors { 7 | def serialName: String 8 | } 9 | object Colors { 10 | case object Red extends Colors { 11 | val serialName: String = "red" 12 | } 13 | case object Blue extends Colors { 14 | val serialName: String = "blue-ish" 15 | } 16 | case object Green extends Colors { 17 | val serialName: String = "Green" 18 | } 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /core/data/tests/test_simple_enum_case_name_support/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// This is a comment. 4 | public enum Colors: String, Codable { 5 | case red 6 | case blue = "blue-ish" 7 | case green = "Green" 8 | } 9 | -------------------------------------------------------------------------------- /core/data/tests/test_simple_enum_case_name_support/output.ts: -------------------------------------------------------------------------------- 1 | /** This is a comment. */ 2 | export enum Colors { 3 | Red = "red", 4 | Blue = "blue-ish", 5 | Green = "Green", 6 | } 7 | 8 | -------------------------------------------------------------------------------- /core/data/tests/test_type_alias/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | pub struct Bar(String); 3 | 4 | #[typeshare] 5 | pub struct Foo { 6 | bar: Bar, 7 | } 8 | -------------------------------------------------------------------------------- /core/data/tests/test_type_alias/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | type Bar string 6 | 7 | type Foo struct { 8 | Bar Bar `json:"bar"` 9 | } 10 | -------------------------------------------------------------------------------- /core/data/tests/test_type_alias/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | typealias Bar = String 7 | 8 | @Serializable 9 | data class Foo ( 10 | val bar: Bar 11 | ) 12 | 13 | -------------------------------------------------------------------------------- /core/data/tests/test_type_alias/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pydantic import BaseModel 4 | 5 | 6 | Bar = str 7 | 8 | class Foo(BaseModel): 9 | bar: Bar 10 | 11 | -------------------------------------------------------------------------------- /core/data/tests/test_type_alias/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package object onepassword { 4 | 5 | type Bar = String 6 | 7 | } 8 | package onepassword { 9 | 10 | case class Foo ( 11 | bar: Bar 12 | ) 13 | 14 | } 15 | -------------------------------------------------------------------------------- /core/data/tests/test_type_alias/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public typealias OPBar = String 4 | 5 | public struct OPFoo: Codable { 6 | public let bar: OPBar 7 | 8 | public init(bar: OPBar) { 9 | self.bar = bar 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /core/data/tests/test_type_alias/output.ts: -------------------------------------------------------------------------------- 1 | export type Bar = string; 2 | 3 | export interface Foo { 4 | bar: Bar; 5 | } 6 | 7 | -------------------------------------------------------------------------------- /core/data/tests/uppercase_go_acronyms/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | pub struct AccountId(String); 3 | 4 | #[typeshare] 5 | pub struct Foo { 6 | pub id: String, 7 | pub id_with_suffix: String, 8 | pub prefix_with_id: String, 9 | pub identity: String, 10 | pub lowercase_input_url: String, 11 | pub uppercase_type: AccountId, 12 | } 13 | 14 | #[typeshare] 15 | #[serde(tag = "type", content = "content")] 16 | pub enum Bar { 17 | Id(String), 18 | } 19 | -------------------------------------------------------------------------------- /core/data/tests/uppercase_go_acronyms/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | type AccountID string 6 | 7 | type Foo struct { 8 | ID string `json:"id"` 9 | IDWithSuffix string `json:"id_with_suffix"` 10 | PrefixWithID string `json:"prefix_with_id"` 11 | Identity string `json:"identity"` 12 | LowercaseInputURL string `json:"lowercase_input_url"` 13 | UppercaseType AccountID `json:"uppercase_type"` 14 | } 15 | type BarTypes string 16 | const ( 17 | BarTypeVariantID BarTypes = "Id" 18 | ) 19 | type Bar struct{ 20 | Type BarTypes `json:"type"` 21 | content interface{} 22 | } 23 | 24 | func (b *Bar) UnmarshalJSON(data []byte) error { 25 | var enum struct { 26 | Tag BarTypes `json:"type"` 27 | Content json.RawMessage `json:"content"` 28 | } 29 | if err := json.Unmarshal(data, &enum); err != nil { 30 | return err 31 | } 32 | 33 | b.Type = enum.Tag 34 | switch b.Type { 35 | case BarTypeVariantID: 36 | var res string 37 | b.content = &res 38 | 39 | } 40 | if err := json.Unmarshal(enum.Content, &b.content); err != nil { 41 | return err 42 | } 43 | 44 | return nil 45 | } 46 | 47 | func (b Bar) MarshalJSON() ([]byte, error) { 48 | var enum struct { 49 | Tag BarTypes `json:"type"` 50 | Content interface{} `json:"content,omitempty"` 51 | } 52 | enum.Tag = b.Type 53 | enum.Content = b.content 54 | return json.Marshal(enum) 55 | } 56 | 57 | func (b Bar) ID() string { 58 | res, _ := b.content.(*string) 59 | return *res 60 | } 61 | 62 | func NewBarTypeVariantID(content string) Bar { 63 | return Bar{ 64 | Type: BarTypeVariantID, 65 | content: &content, 66 | } 67 | } 68 | 69 | -------------------------------------------------------------------------------- /core/data/tests/use_correct_decoded_variable_name/input.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | pub struct MyEmptyStruct {} 3 | -------------------------------------------------------------------------------- /core/data/tests/use_correct_decoded_variable_name/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | type MyEmptyStruct struct { 6 | } 7 | -------------------------------------------------------------------------------- /core/data/tests/use_correct_decoded_variable_name/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | @Serializable 7 | object MyEmptyStruct 8 | 9 | -------------------------------------------------------------------------------- /core/data/tests/use_correct_decoded_variable_name/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pydantic import BaseModel 4 | 5 | 6 | class MyEmptyStruct(BaseModel): 7 | pass 8 | -------------------------------------------------------------------------------- /core/data/tests/use_correct_decoded_variable_name/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package onepassword { 4 | 5 | class MyEmptyStruct extends Serializable 6 | 7 | } 8 | -------------------------------------------------------------------------------- /core/data/tests/use_correct_decoded_variable_name/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct MyEmptyStruct: Codable { 4 | public init() {} 5 | } 6 | -------------------------------------------------------------------------------- /core/data/tests/use_correct_decoded_variable_name/output.ts: -------------------------------------------------------------------------------- 1 | export interface MyEmptyStruct { 2 | } 3 | 4 | -------------------------------------------------------------------------------- /core/data/tests/use_correct_integer_types/input.rs: -------------------------------------------------------------------------------- 1 | /// This is a comment. 2 | #[typeshare] 3 | pub struct Foo { 4 | pub a: i8, 5 | pub b: i16, 6 | pub c: i32, 7 | pub e: u8, 8 | pub f: u16, 9 | pub g: u32, 10 | } 11 | -------------------------------------------------------------------------------- /core/data/tests/use_correct_integer_types/output.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import "encoding/json" 4 | 5 | // This is a comment. 6 | type Foo struct { 7 | A int `json:"a"` 8 | B int `json:"b"` 9 | C int `json:"c"` 10 | E int `json:"e"` 11 | F int `json:"f"` 12 | G uint32 `json:"g"` 13 | } 14 | -------------------------------------------------------------------------------- /core/data/tests/use_correct_integer_types/output.kt: -------------------------------------------------------------------------------- 1 | package com.agilebits.onepassword 2 | 3 | import kotlinx.serialization.Serializable 4 | import kotlinx.serialization.SerialName 5 | 6 | /// This is a comment. 7 | @Serializable 8 | data class Foo ( 9 | val a: Byte, 10 | val b: Short, 11 | val c: Int, 12 | val e: UByte, 13 | val f: UShort, 14 | val g: UInt 15 | ) 16 | 17 | -------------------------------------------------------------------------------- /core/data/tests/use_correct_integer_types/output.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pydantic import BaseModel 4 | 5 | 6 | class Foo(BaseModel): 7 | """ 8 | This is a comment. 9 | """ 10 | a: int 11 | b: int 12 | c: int 13 | e: int 14 | f: int 15 | g: int 16 | 17 | -------------------------------------------------------------------------------- /core/data/tests/use_correct_integer_types/output.scala: -------------------------------------------------------------------------------- 1 | package com.agilebits 2 | 3 | package object onepassword { 4 | 5 | type UByte = Byte 6 | type UShort = Short 7 | type UInt = Int 8 | type ULong = Int 9 | 10 | } 11 | package onepassword { 12 | 13 | // This is a comment. 14 | case class Foo ( 15 | a: Byte, 16 | b: Short, 17 | c: Int, 18 | e: UByte, 19 | f: UShort, 20 | g: UInt 21 | ) 22 | 23 | } 24 | -------------------------------------------------------------------------------- /core/data/tests/use_correct_integer_types/output.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// This is a comment. 4 | public struct Foo: Codable { 5 | public let a: Int8 6 | public let b: Int16 7 | public let c: Int32 8 | public let e: UInt8 9 | public let f: UInt16 10 | public let g: UInt32 11 | 12 | public init(a: Int8, b: Int16, c: Int32, e: UInt8, f: UInt16, g: UInt32) { 13 | self.a = a 14 | self.b = b 15 | self.c = c 16 | self.e = e 17 | self.f = f 18 | self.g = g 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /core/data/tests/use_correct_integer_types/output.ts: -------------------------------------------------------------------------------- 1 | /** This is a comment. */ 2 | export interface Foo { 3 | a: number; 4 | b: number; 5 | c: number; 6 | e: number; 7 | f: number; 8 | g: number; 9 | } 10 | 11 | -------------------------------------------------------------------------------- /core/rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "stable" 3 | components = ["clippy"] 4 | profile = "default" 5 | -------------------------------------------------------------------------------- /core/src/context.rs: -------------------------------------------------------------------------------- 1 | //! Context types for parsing. 2 | //! 3 | use crate::language::CrateName; 4 | use std::path::PathBuf; 5 | 6 | /// Context for parsing rust source files. 7 | #[derive(Default)] 8 | pub struct ParseContext<'a> { 9 | /// Types to ignore 10 | pub ignored_types: Vec<&'a str>, 11 | /// Multi file output enabled. 12 | pub multi_file: bool, 13 | /// `target_os` filtering. 14 | pub target_os: Vec, 15 | } 16 | 17 | /// Parsing context for a single rust source file. 18 | pub struct ParseFileContext { 19 | /// Source code content 20 | pub source_code: String, 21 | /// Name of the crate this file belongs to. 22 | pub crate_name: CrateName, 23 | /// File name. 24 | pub file_name: String, 25 | /// Full path to the source file. 26 | pub file_path: PathBuf, 27 | } 28 | -------------------------------------------------------------------------------- /core/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! The core library for typeshare. 2 | //! Contains the parser and language converters. 3 | use thiserror::Error; 4 | 5 | pub mod context; 6 | /// Implementations for each language converter 7 | pub mod language; 8 | /// Parsing Rust code into a format the `language` modules can understand 9 | pub mod parser; 10 | pub mod reconcile; 11 | mod rename; 12 | /// Codifying Rust types and how they convert to various languages. 13 | pub mod rust_types; 14 | mod target_os_check; 15 | mod topsort; 16 | mod visitors; 17 | 18 | pub use rename::RenameExt; 19 | 20 | #[derive(Debug, Error)] 21 | #[allow(missing_docs)] 22 | pub enum ProcessInputError { 23 | #[error("a parsing error occurred: {0}")] 24 | ParseError(#[from] parser::ParseError), 25 | #[error("a type generation error occurred: {0}")] 26 | IoError(#[from] std::io::Error), 27 | } 28 | 29 | #[derive(Debug, Error)] 30 | /// Errors during file generation. 31 | pub enum GenerationError { 32 | /// The post generation step failed. 33 | #[error("Post generation failed: {0}")] 34 | PostGeneration(String), 35 | } 36 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | book 2 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # The Official Typeshare Book 2 | 3 | Your all-in-one resource for all things Typeshare! Learn about how to use it, how it works internally, and how to contribute to it! -------------------------------------------------------------------------------- /docs/book.toml: -------------------------------------------------------------------------------- 1 | [book] 2 | authors = ["Jane Lewis", "Josh Rampersad", "Darrell Roberts"] 3 | language = "en" 4 | multilingual = false 5 | src = "src" 6 | title = "The Typeshare Book" 7 | -------------------------------------------------------------------------------- /docs/src/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | - [Overview](./overview.md) 4 | - [Installation](./installation.md) 5 | - [Usage](./usage/usage.md) 6 | - [Annotations](./usage/annotations.md) 7 | - [Configuration](./usage/configuration.md) 8 | - [Target OS](./usage/target_os.md) 9 | - [Contributing](./contributing.md) 10 | -------------------------------------------------------------------------------- /docs/src/contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing to Typeshare 2 | 3 | Thank you! If you would like to contribute to the project, go to [the GitHub repository](https://github.com/1Password/typeshare). There, you can open issues to report bugs and request features. 4 | 5 | If you want to contribute code, please send a [GitHub Pull Request](https://github.com/1Password/typeshare/pull/new/master) to the repository with a clear list of your changes and the reasons for the changes. Before contributing, you should probably familiarize yourself with the internal documentation, if you haven't already. Make sure to look through the READMEs for each part of Typeshare you plan to contribute to, and double-check the Rust documentation on `docs.rs` if you want to know more about the API. And feel free to open an issue if you want to ask the 1Password team directly, or if the documentation is unclear. 6 | 7 | For larger changes, please open an RFC issue first in order to discuss the broader impacts of the proposed change with the other maintainers. -------------------------------------------------------------------------------- /docs/src/installation.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | The easiest way to install the Typeshare CLI is with `cargo`. Just run the following command: 4 | ``` 5 | cargo install typeshare-cli 6 | ``` 7 | 8 | Once you have the CLI installed, you then need to annotate the rust types that you want to generate FFI definitions for. In order to be able to use the `#[typeshare]` annotation, you will need to add `typeshare` as a dependency to your project's `Cargo.toml`. 9 | 10 | ```toml 11 | # Cargo.toml 12 | 13 | [dependencies] 14 | typeshare = "1.0.0" # Use whichever version is the most recent 15 | ``` 16 | -------------------------------------------------------------------------------- /docs/src/overview.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | Typeshare is a tool for generating type definitions in other languages based on type definitions in Rust. Specifically, Typeshare is useful for FFI where types are passed as fully serialized blobs, and then decoded on the other side. 4 | 5 | Typeshare was originally developed as an internal tool at [1Password](1password.com), but has been released as an open-source crate that you can use and contribute to. 6 | 7 | This guide describes how to install and use Typeshare effectively. -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "flake-utils": { 4 | "inputs": { 5 | "systems": "systems" 6 | }, 7 | "locked": { 8 | "lastModified": 1710146030, 9 | "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", 10 | "owner": "numtide", 11 | "repo": "flake-utils", 12 | "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", 13 | "type": "github" 14 | }, 15 | "original": { 16 | "owner": "numtide", 17 | "repo": "flake-utils", 18 | "type": "github" 19 | } 20 | }, 21 | "nixpkgs": { 22 | "locked": { 23 | "lastModified": 1714906307, 24 | "narHash": "sha256-UlRZtrCnhPFSJlDQE7M0eyhgvuuHBTe1eJ9N9AQlJQ0=", 25 | "owner": "NixOS", 26 | "repo": "nixpkgs", 27 | "rev": "25865a40d14b3f9cf19f19b924e2ab4069b09588", 28 | "type": "github" 29 | }, 30 | "original": { 31 | "id": "nixpkgs", 32 | "ref": "nixos-unstable", 33 | "type": "indirect" 34 | } 35 | }, 36 | "root": { 37 | "inputs": { 38 | "flake-utils": "flake-utils", 39 | "nixpkgs": "nixpkgs" 40 | } 41 | }, 42 | "systems": { 43 | "locked": { 44 | "lastModified": 1681028828, 45 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 46 | "owner": "nix-systems", 47 | "repo": "default", 48 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 49 | "type": "github" 50 | }, 51 | "original": { 52 | "owner": "nix-systems", 53 | "repo": "default", 54 | "type": "github" 55 | } 56 | } 57 | }, 58 | "root": "root", 59 | "version": 7 60 | } 61 | -------------------------------------------------------------------------------- /lib/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "typeshare" 3 | version = "1.0.4" 4 | edition = "2021" 5 | license = "MIT OR Apache-2.0" 6 | readme = "../README.md" 7 | description = "Seamlessly share type definitions across multiple languages for FFI interoperability" 8 | repository = "https://github.com/1Password/typeshare" 9 | 10 | [dependencies] 11 | chrono = { version = "0.4", default-features = false, features = [ 12 | "clock", 13 | "std", 14 | ] } 15 | serde = { version = "1", features = ["derive"] } 16 | serde_json = "1" 17 | typeshare-annotation = { path = "../annotation", version = "1.0.4" } 18 | 19 | [features] 20 | default = ["wasmbind"] 21 | wasmbind = ["chrono/wasmbind"] 22 | -------------------------------------------------------------------------------- /lib/README.md: -------------------------------------------------------------------------------- 1 | # typeshare-lib 2 | 3 | Library-level code providing helpers for interacting with types generated by typeshare. 4 | -------------------------------------------------------------------------------- /lib/rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "stable" 3 | components = ["clippy"] 4 | profile = "default" 5 | -------------------------------------------------------------------------------- /lib/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Types and functions for code that defines and/or uses `#[typeshare]` 2 | //! types. 3 | 4 | pub use typeshare_annotation::typeshare; 5 | 6 | mod integer; 7 | pub use integer::{usize_from_u53_saturated, I54, U53}; 8 | 9 | // TODO: Expose and use this module's functionality. 10 | #[allow(dead_code)] 11 | mod json_date; 12 | -------------------------------------------------------------------------------- /rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "stable" 3 | components = ["clippy"] 4 | profile = "default" 5 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | input 2 | out 3 | -------------------------------------------------------------------------------- /tests/data/determinism-base.rs: -------------------------------------------------------------------------------- 1 | #[typeshare] 2 | pub struct CustomType {} 3 | 4 | #[typeshare] 5 | pub struct Types { 6 | pub s: String, 7 | pub static_s: &'static str, 8 | pub int8: i8, 9 | pub float: f32, 10 | pub double: f64, 11 | pub array: Vec, 12 | pub fixed_length_array: [String; 4], 13 | pub dictionary: HashMap, 14 | pub optional_dictionary: Option>, 15 | pub custom_type: CustomType, 16 | } 17 | -------------------------------------------------------------------------------- /tests/justfile: -------------------------------------------------------------------------------- 1 | determinism_qty := '100' 2 | 3 | all: determinism 4 | 5 | generate-determinism-files: 6 | #!/bin/sh 7 | mkdir -p input 8 | for i in $(seq 1 {{determinism_qty}}); do 9 | cat data/determinism-base.rs | sd '(struct )(\w+)' "\${1}\${2}$i" > "input/input$i.rs" 10 | done 11 | determinism: clean generate-determinism-files 12 | mkdir -p out 13 | cargo run -p typeshare-cli -- -l typescript -o "out/output1.ts" input 14 | cargo run -p typeshare-cli -- -l typescript -o "out/output2.ts" input 15 | diff -q out/*.ts 16 | 17 | clean: 18 | rm -rf out 19 | rm -rf input 20 | --------------------------------------------------------------------------------