├── .nvmrc ├── .node-version ├── packages └── boostest │ ├── .yarnrc.yml │ ├── rustfmt.toml │ ├── npm │ ├── darwin-arm64 │ │ ├── README.md │ │ └── package.json │ ├── darwin-x64 │ │ ├── README.md │ │ └── package.json │ ├── linux-x64-gnu │ │ ├── README.md │ │ └── package.json │ ├── win32-x64-msvc │ │ ├── README.md │ │ └── package.json │ └── publish.sh │ ├── .hogenpmrc │ ├── build.rs │ ├── .cargo │ └── config.toml │ ├── __test__ │ └── index.spec.mjs │ ├── .npmignore │ ├── Cargo.toml │ ├── tsconfig.json │ ├── move_nodes.sh │ ├── src │ └── lib.rs │ ├── index.d.ts │ ├── package.json │ ├── .gitignore │ └── bin │ └── cli.ts ├── apps ├── example │ ├── .gitignore │ ├── src │ │ ├── types │ │ │ ├── export_named_decl.ts │ │ │ ├── export_default_interface_with_decl.ts │ │ │ ├── export_default_interface.ts │ │ │ ├── export_default_named_decl.ts │ │ │ ├── export_named_decl_interface.ts │ │ │ ├── export_default_class_with_decl.ts │ │ │ ├── export_default_class.ts │ │ │ ├── export_named_decl_class.ts │ │ │ ├── mix.ts │ │ │ ├── class_obj.ts │ │ │ └── deepfiles │ │ │ │ └── lib │ │ │ │ ├── chips.ts │ │ │ │ ├── comp_type_alias.ts │ │ │ │ ├── comp_interface.ts │ │ │ │ └── comp_class.ts │ │ ├── invest │ │ │ ├── sendgrid │ │ │ │ └── mail.ts │ │ │ ├── axios │ │ │ │ └── http.ts │ │ │ └── express │ │ │ │ └── express.ts │ │ ├── handlefiles │ │ │ └── nestedExample.ts │ │ └── example.ts │ ├── boostest.setting.json │ ├── tsconfig.json │ └── package.json └── test │ ├── src │ ├── types │ │ ├── common_pipe.ts │ │ ├── export_filename_main_file │ │ │ ├── literal.js │ │ │ └── literal.d.ts │ │ ├── export_d_main_file │ │ │ └── index.d.ts │ │ ├── export_decl.ts │ │ ├── export_main_file │ │ │ └── index.ts │ │ ├── common.ts │ │ ├── export_named_decl.ts │ │ ├── invets │ │ │ └── invest_type.ts │ │ ├── pattern │ │ │ ├── accessor_class.ts │ │ │ ├── arg_obj_class.ts │ │ │ └── arg_obj_class2.ts │ │ ├── ts_types │ │ │ ├── index.ts │ │ │ ├── index_signature.ts │ │ │ ├── utils.ts │ │ │ ├── constructor_signature.ts │ │ │ ├── union.ts │ │ │ ├── call_signature.ts │ │ │ ├── intersection.ts │ │ │ ├── zod.ts │ │ │ ├── nested.ts │ │ │ ├── literal.ts │ │ │ ├── built_in_class.ts │ │ │ ├── generics.ts │ │ │ └── ts_type_literal.ts │ │ ├── export_default_interface_with_decl.ts │ │ ├── export_default_interface.ts │ │ ├── export_default_named_decl.ts │ │ ├── export_named_decl_interface.ts │ │ ├── export_rename.ts │ │ ├── mix_default_normal │ │ │ ├── mix_class2.ts │ │ │ ├── mix_interface2.ts │ │ │ ├── mix_ts_alias2.ts │ │ │ ├── mix_class.ts │ │ │ ├── mix_ts_alias.ts │ │ │ └── mix_interface.ts │ │ ├── export_default_class_with_decl.ts │ │ ├── export_default_class.ts │ │ ├── export_named_decl_class.ts │ │ ├── mix.ts │ │ ├── deepfiles │ │ │ └── lib │ │ │ │ ├── chips.ts │ │ │ │ ├── comp_type_alias.ts │ │ │ │ ├── comp_interface.ts │ │ │ │ └── comp_class.ts │ │ └── nested_prop_class.ts │ ├── direct_path │ │ ├── boostest_output │ │ │ └── boostestTsTypeLiteralString.ts │ │ ├── direct_path.ts │ │ ├── direct_path.spec.ts │ │ └── __snapshots__ │ │ │ └── direct_path.spec.ts.snap │ └── tests │ │ ├── common_js │ │ ├── __snapshots__ │ │ │ └── common_js.spec.ts.snap │ │ └── common_js.spec.ts │ │ ├── index_signature │ │ ├── __snapshots__ │ │ │ └── index_signature.spec.ts.snap │ │ └── index_signature.spec.ts │ │ ├── _invest │ │ ├── invest.spec.ts │ │ └── __snapshots__ │ │ │ └── invest.spec.ts.snap │ │ ├── zod │ │ ├── __snapshots__ │ │ │ └── zod.spec.ts.snap │ │ └── zod.spec.ts │ │ ├── outer_packages │ │ ├── __snapshots__ │ │ │ └── outer_packages.spec.ts.snap │ │ └── outer_packages.spec.ts │ │ ├── union │ │ ├── __snapshots__ │ │ │ └── union.spec.ts.snap │ │ └── union.spec.ts │ │ ├── call_signature │ │ ├── __snapshots__ │ │ │ └── call_signature.spec.ts.snap │ │ └── call_signature.spec.ts │ │ ├── insersection │ │ ├── __snapshots__ │ │ │ └── intersection.spec.ts.snap │ │ └── intersection.spec.ts │ │ ├── renamed │ │ ├── __snapshots__ │ │ │ └── renamed.spec.ts.snap │ │ └── renamed.spec.ts │ │ ├── nestes_type │ │ ├── nested_type.spec.ts │ │ └── __snapshots__ │ │ │ └── nested_type.spec.ts.snap │ │ ├── built_in │ │ └── builtIn.spec.ts │ │ ├── sandbox.ts │ │ ├── standard │ │ ├── standard.spec.ts │ │ └── __snapshots__ │ │ │ └── standard.spec.ts.snap │ │ ├── main_file_import │ │ ├── main_file_import.spec.ts │ │ └── __snapshots__ │ │ │ └── main_file_import.spec.ts.snap │ │ ├── outpout_test.sspec.ts │ │ ├── generics │ │ ├── generics.spec.ts │ │ └── __snapshots__ │ │ │ └── generics.spec.ts.snap │ │ ├── class │ │ ├── __snapshots__ │ │ │ └── class.spec.ts.snap │ │ └── class.spec.ts │ │ ├── not_ref_types │ │ ├── __snapshots__ │ │ │ └── notRefTypes.spec.ts.snap │ │ └── notRefTypes.spec.ts │ │ ├── utils.ts │ │ ├── literal │ │ ├── __snapshots__ │ │ │ └── literal.spec.ts.snap │ │ └── literal.spec.ts │ │ └── various_export_impot │ │ └── various_export_import.spec.ts │ ├── .gitignore │ ├── boostest.setting.json │ ├── jest.config.js │ ├── boostest.setting.json.bak │ ├── tsconfig.json │ └── package.json ├── pnpm-workspace.yaml ├── rust-toolchain.toml ├── crates └── boostest │ ├── src │ ├── boostest_manager.rs │ ├── boostest_resolver │ │ ├── resolver.rs │ │ ├── main_target_resolver.rs │ │ └── resolver │ │ │ └── tsserver_resolver.rs │ ├── boostest_bundler.rs │ ├── boostest_generator │ │ ├── template │ │ │ ├── default.ts │ │ │ ├── tsTypeAlias.ts │ │ │ └── tsTypeLiteralAlias.ts │ │ └── fallback_func_builder.rs │ ├── boostest_resolver.rs │ ├── boostest_utils.rs │ ├── boostest_generator.rs │ ├── boostest_manager │ │ ├── task.rs │ │ └── target_detector.rs │ ├── boostest_utils │ │ ├── napi.rs │ │ ├── module_resolver.rs │ │ ├── id_name.rs │ │ ├── typescript_lib.rs │ │ ├── file_utils.rs │ │ └── buf.rs │ └── boostest_bundler │ │ └── output_main_generator.rs │ └── Cargo.toml ├── .cargo └── config.toml ├── .gitignore ├── package.json ├── Cargo.toml ├── LICENSE.md ├── justfile └── .github └── workflows └── CI.yml /.nvmrc: -------------------------------------------------------------------------------- 1 | v20.13.1 -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | v20.13.1 -------------------------------------------------------------------------------- /packages/boostest/.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules -------------------------------------------------------------------------------- /apps/example/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | node_modules/ 3 | 4 | src/**/*_test_data.ts -------------------------------------------------------------------------------- /packages/boostest/rustfmt.toml: -------------------------------------------------------------------------------- 1 | tab_spaces = 2 2 | edition = "2021" 3 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'apps/*' 3 | - 'packages/*' 4 | -------------------------------------------------------------------------------- /packages/boostest/npm/darwin-arm64/README.md: -------------------------------------------------------------------------------- 1 | # `boostest.darwin-arm64.node` 2 | -------------------------------------------------------------------------------- /rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "1.82.0" 3 | profile = "default" 4 | -------------------------------------------------------------------------------- /crates/boostest/src/boostest_manager.rs: -------------------------------------------------------------------------------- 1 | pub mod target_detector; 2 | pub mod task; 3 | -------------------------------------------------------------------------------- /apps/test/src/types/common_pipe.ts: -------------------------------------------------------------------------------- 1 | import * as Hoge from "./common"; 2 | 3 | export = Hoge; 4 | -------------------------------------------------------------------------------- /apps/test/src/types/export_filename_main_file/literal.js: -------------------------------------------------------------------------------- 1 | export const LiteralTypeAlias = {}; 2 | -------------------------------------------------------------------------------- /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.x86_64-unknown-linux-gnu] 2 | linker = "x86_64-unknown-linux-gnu-gcc" 3 | -------------------------------------------------------------------------------- /packages/boostest/.hogenpmrc: -------------------------------------------------------------------------------- 1 | scope @masato-dev 2 | @masato-dev:registry=https://registry.npmjs.org/ 3 | -------------------------------------------------------------------------------- /crates/boostest/src/boostest_resolver/resolver.rs: -------------------------------------------------------------------------------- 1 | pub mod oxc_resolver; 2 | pub mod tsserver_resolver; 3 | -------------------------------------------------------------------------------- /apps/test/src/types/export_d_main_file/index.d.ts: -------------------------------------------------------------------------------- 1 | export { LiteralTypeAlias } from "../ts_types/literal"; 2 | -------------------------------------------------------------------------------- /apps/test/src/types/export_decl.ts: -------------------------------------------------------------------------------- 1 | export type { ComplexChipsType } from './deepfiles/lib/comp_type_alias'; 2 | -------------------------------------------------------------------------------- /apps/test/src/types/export_main_file/index.ts: -------------------------------------------------------------------------------- 1 | export type { LiteralTypeAlias } from "../ts_types/literal"; 2 | -------------------------------------------------------------------------------- /packages/boostest/build.rs: -------------------------------------------------------------------------------- 1 | extern crate napi_build; 2 | 3 | fn main() { 4 | napi_build::setup(); 5 | } 6 | -------------------------------------------------------------------------------- /apps/test/src/types/common.ts: -------------------------------------------------------------------------------- 1 | type Hoge = { 2 | id: number; 3 | name: string; 4 | }; 5 | 6 | export = Hoge; 7 | -------------------------------------------------------------------------------- /apps/test/src/types/export_filename_main_file/literal.d.ts: -------------------------------------------------------------------------------- 1 | export { LiteralTypeAlias } from "../ts_types/literal"; 2 | -------------------------------------------------------------------------------- /packages/boostest/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.x86_64-pc-windows-msvc] 2 | rustflags = ["-C", "target-feature=+crt-static"] -------------------------------------------------------------------------------- /crates/boostest/src/boostest_bundler.rs: -------------------------------------------------------------------------------- 1 | pub mod output; 2 | pub mod output_generator; 3 | pub mod output_main_generator; 4 | 5 | -------------------------------------------------------------------------------- /crates/boostest/src/boostest_generator/template/default.ts: -------------------------------------------------------------------------------- 1 | export function boostestDefaultTemplate() { 2 | return {}; 3 | } 4 | -------------------------------------------------------------------------------- /apps/test/src/types/export_named_decl.ts: -------------------------------------------------------------------------------- 1 | export type { ComplexChipsType as ExportNamedDecl } from './deepfiles/lib/comp_type_alias'; 2 | -------------------------------------------------------------------------------- /packages/boostest/npm/darwin-x64/README.md: -------------------------------------------------------------------------------- 1 | # `boostest-darwin-x64` 2 | 3 | This is the **x86_64-apple-darwin** binary for `boostest` 4 | -------------------------------------------------------------------------------- /apps/example/src/types/export_named_decl.ts: -------------------------------------------------------------------------------- 1 | export type { ComplexChipsType as ExportNamedDecl } from './deepfiles/lib/comp_type_alias'; 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | debug/ 4 | target/ 5 | 6 | node_modules/ 7 | 8 | .DS_Store 9 | -------------------------------------------------------------------------------- /packages/boostest/npm/linux-x64-gnu/README.md: -------------------------------------------------------------------------------- 1 | # `boostest-linux-x64-gnu` 2 | 3 | This is the **x86_64-unknown-linux-gnu** binary for `boostest` 4 | -------------------------------------------------------------------------------- /packages/boostest/npm/win32-x64-msvc/README.md: -------------------------------------------------------------------------------- 1 | # `boostest-win32-x64-msvc` 2 | 3 | This is the **x86_64-pc-windows-msvc** binary for `boostest` 4 | -------------------------------------------------------------------------------- /apps/test/src/types/invets/invest_type.ts: -------------------------------------------------------------------------------- 1 | import { type TSAliasStringUnionType } from "../ts_types/union"; 2 | 3 | export type Hoge = TSAliasStringUnionType; 4 | -------------------------------------------------------------------------------- /apps/test/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | node_modules/ 3 | 4 | src/**/*_test_data.ts 5 | src/**/*_boostest.ts 6 | src/tests/*/boostest_output/ 7 | src/tests/boostest_output/ 8 | 9 | -------------------------------------------------------------------------------- /apps/test/src/direct_path/boostest_output/boostestTsTypeLiteralString.ts: -------------------------------------------------------------------------------- 1 | export function boostestTsTypeLiteralString() { 2 | return "test string data"; 3 | } 4 | -------------------------------------------------------------------------------- /crates/boostest/src/boostest_resolver.rs: -------------------------------------------------------------------------------- 1 | pub mod main_target_resolver; 2 | pub mod resolver; 3 | pub mod target; 4 | pub mod target_resolver; 5 | pub mod visit_mut; 6 | 7 | -------------------------------------------------------------------------------- /apps/test/src/types/pattern/accessor_class.ts: -------------------------------------------------------------------------------- 1 | export class AccessorClass { 2 | constructor(public name: string, private age: number, protected readonly readonlyAge: number) {} 3 | } 4 | -------------------------------------------------------------------------------- /crates/boostest/src/boostest_generator/template/tsTypeAlias.ts: -------------------------------------------------------------------------------- 1 | export function boostestTSTypeAliasTemplate() { 2 | return { 3 | boostestKey: "boostestValue", 4 | }; 5 | } 6 | -------------------------------------------------------------------------------- /packages/boostest/__test__/index.spec.mjs: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | 3 | import { sum } from '../index.js' 4 | 5 | test('sum from native', (t) => { 6 | t.is(sum(1, 2), 3) 7 | }) 8 | -------------------------------------------------------------------------------- /apps/example/boostest.setting.json: -------------------------------------------------------------------------------- 1 | { 2 | "target_pattern": ["src/invest/**/*"], 3 | "name": "boostest", 4 | "out_file_name": "test_data", 5 | "tsconfig": "./tsconfig.json" 6 | } 7 | -------------------------------------------------------------------------------- /apps/example/src/invest/sendgrid/mail.ts: -------------------------------------------------------------------------------- 1 | import { ClientResponse } from '@sendgrid/mail'; 2 | 3 | const result = boostestSendGrid(); 4 | 5 | console.log('result', result); 6 | -------------------------------------------------------------------------------- /apps/test/src/types/ts_types/index.ts: -------------------------------------------------------------------------------- 1 | import { NestedType } from "./nested"; 2 | 3 | export * from "./union"; 4 | export * from "./nested"; 5 | export * from "./literal"; 6 | export * from "./zod"; 7 | -------------------------------------------------------------------------------- /apps/test/src/tests/common_js/__snapshots__/common_js.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Commonjs Tests CommonCjs matches snapshot 1`] = `"{"id":10,"name":"test string data"}"`; 4 | -------------------------------------------------------------------------------- /apps/test/src/tests/index_signature/__snapshots__/index_signature.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Index signature Tests IndexSignature matches snapshot 1`] = `"{"0":10,"key":10}"`; 4 | -------------------------------------------------------------------------------- /apps/test/src/types/ts_types/index_signature.ts: -------------------------------------------------------------------------------- 1 | export type IndexSignature = { 2 | [Str_Key: string]: number; 3 | [Num_Key: number]: number; 4 | 5 | // FIXME: symbol key 6 | [Symbol_Key: symbol]: boolean; 7 | }; 8 | -------------------------------------------------------------------------------- /apps/test/boostest.setting.json: -------------------------------------------------------------------------------- 1 | { 2 | "target_pattern": ["src/tests/**/*.spec.ts"], 3 | "name": "boostest", 4 | 5 | "tsconfig": "./tsconfig.json", 6 | 7 | "output": { 8 | "single": false 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /crates/boostest/src/boostest_generator/template/tsTypeLiteralAlias.ts: -------------------------------------------------------------------------------- 1 | export function boostestTSTypeAliasTemplate(args?: Partial): T { 2 | return { 3 | boostestKey: "boostestValue", 4 | ...args, 5 | } as T; 6 | } 7 | -------------------------------------------------------------------------------- /apps/test/src/types/ts_types/utils.ts: -------------------------------------------------------------------------------- 1 | export type RefType = { 2 | name: string; 3 | ver: number; 4 | age: number; 5 | }; 6 | 7 | export interface RefInterface { 8 | name: string; 9 | ver: number; 10 | age: number; 11 | } 12 | -------------------------------------------------------------------------------- /crates/boostest/src/boostest_utils.rs: -------------------------------------------------------------------------------- 1 | pub mod ast_utils; 2 | pub mod buf; 3 | pub mod file_utils; 4 | pub mod id_name; 5 | pub mod module_resolver; 6 | pub mod napi; 7 | pub mod setting; 8 | pub mod tsserver; 9 | pub mod typescript_lib; 10 | -------------------------------------------------------------------------------- /apps/test/src/types/export_default_interface_with_decl.ts: -------------------------------------------------------------------------------- 1 | import ComplexInterfaceChips from './deepfiles/lib/comp_interface'; 2 | 3 | export default interface ExportDefaultInterfaceWithDecl { 4 | name: string; 5 | chips: ComplexInterfaceChips; 6 | } 7 | -------------------------------------------------------------------------------- /apps/example/src/types/export_default_interface_with_decl.ts: -------------------------------------------------------------------------------- 1 | import ComplexInterfaceChips from './deepfiles/lib/comp_interface'; 2 | 3 | export default interface ExportDefaultInterfaceWithDecl { 4 | name: string; 5 | chips: ComplexInterfaceChips; 6 | } 7 | -------------------------------------------------------------------------------- /apps/test/src/types/export_default_interface.ts: -------------------------------------------------------------------------------- 1 | import ComplexInterfaceChips from './deepfiles/lib/comp_interface'; 2 | 3 | interface ExportDefaultInterface { 4 | name: string; 5 | chips: ComplexInterfaceChips; 6 | } 7 | 8 | export default ExportDefaultInterface; 9 | -------------------------------------------------------------------------------- /apps/example/src/types/export_default_interface.ts: -------------------------------------------------------------------------------- 1 | import ComplexInterfaceChips from './deepfiles/lib/comp_interface'; 2 | 3 | interface ExportDefaultInterface { 4 | name: string; 5 | chips: ComplexInterfaceChips; 6 | } 7 | 8 | export default ExportDefaultInterface; 9 | -------------------------------------------------------------------------------- /apps/example/src/invest/axios/http.ts: -------------------------------------------------------------------------------- 1 | import { FormDataVisitorHelpers, SerializerVisitor } from 'axios'; 2 | 3 | const formDataVisitorHelpers = boostestFormDataVisitorHelpers(); 4 | 5 | const responseType = boostestResponseType(); 6 | -------------------------------------------------------------------------------- /apps/test/src/direct_path/direct_path.ts: -------------------------------------------------------------------------------- 1 | import { TsTypeLiteralString } from "@/ts_types/ts_type_literal"; 2 | import { boostestTsTypeLiteralString } from "./boostest_output/boostestTsTypeLiteralString"; 3 | 4 | let string = boostestTsTypeLiteralString(); 5 | -------------------------------------------------------------------------------- /apps/test/src/types/export_default_named_decl.ts: -------------------------------------------------------------------------------- 1 | import ComplexInterfaceChips from './deepfiles/lib/comp_interface'; 2 | 3 | interface ExportDefaultNamedDecl { 4 | name: string; 5 | chips: ComplexInterfaceChips; 6 | } 7 | 8 | export type { ExportDefaultNamedDecl as default }; 9 | -------------------------------------------------------------------------------- /crates/boostest/src/boostest_generator.rs: -------------------------------------------------------------------------------- 1 | pub mod code_generator; 2 | pub mod extends_ast_builder; 3 | pub mod fallback_func_builder; 4 | pub mod get_arg; 5 | pub mod get_expression; 6 | pub mod handle_ts_signatures; 7 | pub mod test_data_factory; 8 | pub mod ts_type_alias_builder; 9 | -------------------------------------------------------------------------------- /apps/example/src/types/export_default_named_decl.ts: -------------------------------------------------------------------------------- 1 | import ComplexInterfaceChips from './deepfiles/lib/comp_interface'; 2 | 3 | interface ExportDefaultNamedDecl { 4 | name: string; 5 | chips: ComplexInterfaceChips; 6 | } 7 | 8 | export type { ExportDefaultNamedDecl as default }; 9 | -------------------------------------------------------------------------------- /packages/boostest/.npmignore: -------------------------------------------------------------------------------- 1 | target 2 | Cargo.lock 3 | .cargo 4 | .github 5 | # npm 6 | .eslintrc 7 | .prettierignore 8 | rustfmt.toml 9 | yarn.lock 10 | # *.node 11 | .yarn 12 | __test__ 13 | renovate.json 14 | 15 | .yarnrc.yml 16 | build.rs 17 | Cargo.toml 18 | bin/ 19 | npm/ 20 | -------------------------------------------------------------------------------- /apps/test/src/types/export_named_decl_interface.ts: -------------------------------------------------------------------------------- 1 | import ComplexInterfaceChips from './deepfiles/lib/comp_interface'; 2 | 3 | interface ExportNamedDeclInterface { 4 | name: string; 5 | chips: ComplexInterfaceChips; 6 | } 7 | 8 | export type { ExportNamedDeclInterface as AnoExportNamedDeclInterface }; 9 | -------------------------------------------------------------------------------- /apps/example/src/types/export_named_decl_interface.ts: -------------------------------------------------------------------------------- 1 | import ComplexInterfaceChips from './deepfiles/lib/comp_interface'; 2 | 3 | interface ExportNamedDeclInterface { 4 | name: string; 5 | chips: ComplexInterfaceChips; 6 | } 7 | 8 | export type { ExportNamedDeclInterface as AnoExportNamedDeclInterface }; 9 | -------------------------------------------------------------------------------- /apps/test/src/types/export_rename.ts: -------------------------------------------------------------------------------- 1 | import type { ComplexChipsType } from "./deepfiles/lib/comp_type_alias"; 2 | import RenamedNestedPropClass from "./nested_prop_class"; 3 | 4 | // WARN: constで代入するとtypeとして利用できない 5 | // export const RenamedNestedPropClass = ClassObj; 6 | export type RenamedComplexChipsType = ComplexChipsType; 7 | -------------------------------------------------------------------------------- /apps/test/src/tests/common_js/common_js.spec.ts: -------------------------------------------------------------------------------- 1 | import { runSnapshotTest } from "../utils"; 2 | 3 | import Hoge from "../../types/common"; 4 | import { boostestCommonCjs } from "./boostest_output/boostestCommonCjs"; 5 | 6 | describe("Commonjs Tests", () => { 7 | runSnapshotTest("CommonCjs", boostestCommonCjs()); 8 | }); 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "boostest-monorepo", 3 | "version": "0.1.1", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "MIT", 12 | "packageManager": "pnpm@9.1.1" 13 | } 14 | -------------------------------------------------------------------------------- /apps/test/src/tests/_invest/invest.spec.ts: -------------------------------------------------------------------------------- 1 | import { LiteralTypeAlias } from "@/ts_types"; 2 | import { runSnapshotTest } from "../utils"; 3 | import { boostestInvest } from "./boostest_output/boostestInvest"; 4 | 5 | // TODO: 6 | describe("Invest Tests", () => { 7 | runSnapshotTest("Invest", boostestInvest()); 8 | }); 9 | -------------------------------------------------------------------------------- /apps/test/src/types/mix_default_normal/mix_class2.ts: -------------------------------------------------------------------------------- 1 | export default class MixClassFirst2 { 2 | name: string; 3 | 4 | constructor(name: string) { 5 | this.name = name; 6 | } 7 | } 8 | 9 | export class MixClassSecond2 { 10 | name: string; 11 | 12 | constructor(name: string) { 13 | this.name = name; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /apps/test/src/types/mix_default_normal/mix_interface2.ts: -------------------------------------------------------------------------------- 1 | export type { ComplexChipsType as MixCompTSAlias } from '@/deepfiles/lib/comp_type_alias'; 2 | 3 | export default interface MixInterfaceFirst2 { 4 | name: 'MixInterfaceFirst2'; 5 | } 6 | 7 | export interface MixInterfaceSecond2 { 8 | name: 'MixInterfaceSecond2'; 9 | } 10 | -------------------------------------------------------------------------------- /apps/example/src/invest/express/express.ts: -------------------------------------------------------------------------------- 1 | import type { Request, Response, RequestHandler, RequestParamHandler } from 'express'; 2 | 3 | const req = boostestRequest(); 4 | const res = boostestResponse(); 5 | const handler = boostestHandler(); 6 | const paramHandler = boostestParamHandler(); 7 | -------------------------------------------------------------------------------- /apps/test/jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('jest').Config} */ 2 | const config = { 3 | verbose: true, 4 | testEnvironment: "node", 5 | testRegex: ".*\\.spec.ts$", 6 | preset: "ts-jest/presets/default-esm", 7 | transform: { 8 | "^.+\\.m?[tj]sx?$": ["ts-jest", { useESM: true }], 9 | }, 10 | }; 11 | export default config; 12 | -------------------------------------------------------------------------------- /apps/test/src/types/mix_default_normal/mix_ts_alias2.ts: -------------------------------------------------------------------------------- 1 | export type { ComplexChipsType as MixCompTSAlias } from '@/deepfiles/lib/comp_type_alias'; 2 | 3 | export type MixTSAliasFirst2 = { 4 | name: 'MixTSAliasFirst2'; 5 | }; 6 | 7 | type MixTSAliasSecond2 = { 8 | name: 'MixTSAliasSecond2'; 9 | }; 10 | 11 | export default MixTSAliasSecond2; 12 | -------------------------------------------------------------------------------- /apps/test/src/types/mix_default_normal/mix_class.ts: -------------------------------------------------------------------------------- 1 | class MixClassFirst { 2 | name: string; 3 | 4 | constructor(name: string) { 5 | this.name = name; 6 | } 7 | } 8 | 9 | export default MixClassFirst; 10 | 11 | export class MixClassSecond { 12 | name: string; 13 | 14 | constructor(name: string) { 15 | this.name = name; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /apps/test/src/tests/zod/__snapshots__/zod.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Invest Tests Invest object zod matches snapshot 1`] = `"{"username":"test string data","location":{"latitude":10,"longitude":10},"strings":{}}"`; 4 | 5 | exports[`Invest Tests Invest simple zod matches snapshot 1`] = `"{"username":"test string data"}"`; 6 | -------------------------------------------------------------------------------- /apps/test/src/types/mix_default_normal/mix_ts_alias.ts: -------------------------------------------------------------------------------- 1 | export type { ComplexChipsType as MixCompTSAlias } from '@/deepfiles/lib/comp_type_alias'; 2 | 3 | type MixTSAliasFirst = { 4 | name: 'MixTSAliasFirst'; 5 | }; 6 | 7 | type MixTSAliasSecond = { 8 | name: 'MixTsAliasSecond'; 9 | }; 10 | 11 | export type { MixTSAliasFirst }; 12 | export default MixTSAliasSecond; 13 | -------------------------------------------------------------------------------- /apps/example/src/types/export_default_class_with_decl.ts: -------------------------------------------------------------------------------- 1 | import ComplexInterfaceChips from './deepfiles/lib/comp_interface'; 2 | 3 | export default class ExportDefaultClassWithDecl { 4 | name: string; 5 | chips: ComplexInterfaceChips; 6 | 7 | constructor(name: string, chips: ComplexInterfaceChips) { 8 | this.name = name; 9 | this.chips = chips; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /apps/test/src/types/export_default_class_with_decl.ts: -------------------------------------------------------------------------------- 1 | import ComplexInterfaceChips from './deepfiles/lib/comp_interface'; 2 | 3 | export default class ExportDefaultClassWithDecl { 4 | name: string; 5 | chips: ComplexInterfaceChips; 6 | 7 | constructor(name: string, chips: ComplexInterfaceChips) { 8 | this.name = name; 9 | this.chips = chips; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /apps/test/src/types/ts_types/constructor_signature.ts: -------------------------------------------------------------------------------- 1 | class Person { 2 | constructor(public name: string) {} 3 | } 4 | 5 | export type ConstructorSignature = new (name: string) => Person; 6 | 7 | export type InnerConstructorSignature = { 8 | new (name: string): Person; 9 | }; 10 | 11 | export interface ConstructorSignatureInterface { 12 | new (name: string): Person; 13 | } 14 | -------------------------------------------------------------------------------- /apps/test/src/types/export_default_class.ts: -------------------------------------------------------------------------------- 1 | import ComplexInterfaceChips from './deepfiles/lib/comp_interface'; 2 | 3 | class ExportDefaultClass { 4 | name: string; 5 | chips: ComplexInterfaceChips; 6 | 7 | constructor(name: string, chips: ComplexInterfaceChips) { 8 | this.name = name; 9 | this.chips = chips; 10 | } 11 | } 12 | 13 | export default ExportDefaultClass; 14 | -------------------------------------------------------------------------------- /apps/example/src/types/export_default_class.ts: -------------------------------------------------------------------------------- 1 | import ComplexInterfaceChips from './deepfiles/lib/comp_interface'; 2 | 3 | class ExportDefaultClass { 4 | name: string; 5 | chips: ComplexInterfaceChips; 6 | 7 | constructor(name: string, chips: ComplexInterfaceChips) { 8 | this.name = name; 9 | this.chips = chips; 10 | } 11 | } 12 | 13 | export default ExportDefaultClass; 14 | -------------------------------------------------------------------------------- /apps/test/src/types/mix_default_normal/mix_interface.ts: -------------------------------------------------------------------------------- 1 | export type { ComplexChipsType as MixCompTSAlias } from '@/deepfiles/lib/comp_type_alias'; 2 | 3 | interface MixInterfaceFirst { 4 | name: 'MixInterfaceFirst'; 5 | } 6 | 7 | interface MixInterfaceSecond { 8 | name: 'MixInterfaceSecond'; 9 | } 10 | 11 | export type { MixInterfaceFirst }; 12 | export default MixInterfaceSecond; 13 | -------------------------------------------------------------------------------- /apps/test/boostest.setting.json.bak: -------------------------------------------------------------------------------- 1 | { 2 | "target_pattern": ["./src/tests/**/**/*.spec.ts"], 3 | "name": "boostest", 4 | 5 | "tsconfig": "./tsconfig.json", 6 | 7 | "output": { 8 | "single": false 9 | }, 10 | 11 | "initial_value": { 12 | "string": "changed initial value", 13 | "number": 500, 14 | "bigint": "556455199254740991n", 15 | "any": "any" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /apps/test/src/tests/index_signature/index_signature.spec.ts: -------------------------------------------------------------------------------- 1 | import { IndexSignature } from "../../types/ts_types/index_signature"; 2 | import { runSnapshotTest } from "../utils"; 3 | import { boostestIndexSignature } from "./boostest_output/boostestIndexSignature"; 4 | 5 | describe("Index signature Tests", () => { 6 | runSnapshotTest("IndexSignature", boostestIndexSignature()); 7 | }); 8 | -------------------------------------------------------------------------------- /apps/test/src/types/export_named_decl_class.ts: -------------------------------------------------------------------------------- 1 | import ComplexInterfaceChips from './deepfiles/lib/comp_interface'; 2 | 3 | class ExportNamedDeclClass { 4 | name: string; 5 | chips: ComplexInterfaceChips; 6 | 7 | constructor(name: string, chips: ComplexInterfaceChips) { 8 | this.name = name; 9 | this.chips = chips; 10 | } 11 | } 12 | 13 | export { ExportNamedDeclClass as AnoExportNamedDeclClass }; 14 | -------------------------------------------------------------------------------- /apps/example/src/types/export_named_decl_class.ts: -------------------------------------------------------------------------------- 1 | import ComplexInterfaceChips from './deepfiles/lib/comp_interface'; 2 | 3 | class ExportNamedDeclClass { 4 | name: string; 5 | chips: ComplexInterfaceChips; 6 | 7 | constructor(name: string, chips: ComplexInterfaceChips) { 8 | this.name = name; 9 | this.chips = chips; 10 | } 11 | } 12 | 13 | export { ExportNamedDeclClass as AnoExportNamedDeclClass }; 14 | -------------------------------------------------------------------------------- /apps/test/src/direct_path/direct_path.spec.ts: -------------------------------------------------------------------------------- 1 | import { expect } from "@jest/globals"; 2 | const fs = require("fs"); 3 | 4 | it.skip("boostest direct path output correctly", () => { 5 | try { 6 | const data = fs.readFileSync( 7 | "./src/direct_path/direct_path_test_data.ts", 8 | "utf-8", 9 | ); 10 | 11 | expect(data).toMatchSnapshot(); 12 | } catch (err) { 13 | console.log("err", err); 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /apps/example/src/types/mix.ts: -------------------------------------------------------------------------------- 1 | import ComplexInterfaceChips from './deepfiles/lib/comp_interface'; 2 | export type { ComplexChipsType as MixCompTSAlias } from './deepfiles/lib/comp_type_alias'; 3 | 4 | interface MixInterface { 5 | name: string; 6 | chips: ComplexInterfaceChips; 7 | } 8 | 9 | type MixTSAlias = { 10 | name: string; 11 | chips: ComplexInterfaceChips; 12 | }; 13 | 14 | export type { MixInterface as AnoMixInterface, MixTSAlias as default }; 15 | -------------------------------------------------------------------------------- /apps/test/src/tests/outer_packages/__snapshots__/outer_packages.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Outer package Tests Request matches snapshot 1`] = `"{"cache":{},"credentials":{},"destination":{},"headers":{},"integrity":"test string data","keepalive":false,"method":"test string data","mode":{},"redirect":{},"referrer":"test string data","referrerPolicy":{},"signal":{},"url":"test string data","clone":"() => {\\n return {};\\n }"}"`; 4 | -------------------------------------------------------------------------------- /apps/example/src/types/class_obj.ts: -------------------------------------------------------------------------------- 1 | import ComplexInterfaceChips from './deepfiles/lib/comp_interface'; 2 | 3 | class ClassObj { 4 | name: string; 5 | chips: ComplexInterfaceChips; 6 | anoChips: ComplexInterfaceChips; 7 | 8 | constructor({ name, chips }: { name: string; chips: ComplexInterfaceChips }, huga: { anoChips: ComplexInterfaceChips }) { 9 | this.name = name; 10 | this.chips = chips; 11 | this.anoChips = huga.anoChips; 12 | } 13 | } 14 | 15 | export default ClassObj; 16 | -------------------------------------------------------------------------------- /packages/boostest/npm/darwin-x64/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@boostest/boostest-darwin-x64", 3 | "version": "0.8.0", 4 | "publishConfig": { 5 | "registry": "https://registry.npmjs.org/", 6 | "access": "public" 7 | }, 8 | "os": [ 9 | "darwin" 10 | ], 11 | "cpu": [ 12 | "x64" 13 | ], 14 | "main": "boostest.darwin-x64.node", 15 | "files": [ 16 | "boostest.darwin-x64.node" 17 | ], 18 | "license": "MIT", 19 | "engines": { 20 | "node": ">= 10" 21 | } 22 | } -------------------------------------------------------------------------------- /apps/test/src/types/pattern/arg_obj_class.ts: -------------------------------------------------------------------------------- 1 | type ObjKey = { 2 | obj_name: string; 3 | obj_val: number; 4 | }; 5 | 6 | export class ArgObjClass { 7 | name: string; 8 | age: number; 9 | obj_key: ObjKey; 10 | obj_key2: ObjKey; 11 | 12 | constructor({ name, age }: { name: string; age: number }, { obj_key, obj_key2 }: { obj_key: ObjKey; obj_key2: ObjKey }) { 13 | this.name = name; 14 | this.age = age; 15 | this.obj_key = obj_key; 16 | this.obj_key2 = obj_key2; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /apps/test/src/types/pattern/arg_obj_class2.ts: -------------------------------------------------------------------------------- 1 | type ObjKey = { 2 | obj_name: string; 3 | obj_val: number; 4 | }; 5 | 6 | export class ArgObjClass2 { 7 | name: string; 8 | age: number; 9 | obj_key: ObjKey; 10 | obj_key2: ObjKey; 11 | 12 | constructor(hoge: { name: string; age: number }, { obj_key, obj_key2 }: { obj_key: ObjKey; obj_key2: ObjKey }) { 13 | this.name = hoge.name; 14 | this.age = hoge.age; 15 | this.obj_key = obj_key; 16 | this.obj_key2 = obj_key2; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/boostest/npm/darwin-arm64/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@boostest/boostest-darwin-arm64", 3 | "version": "0.8.0", 4 | "publishConfig": { 5 | "registry": "https://registry.npmjs.org/", 6 | "access": "public" 7 | }, 8 | "os": [ 9 | "darwin" 10 | ], 11 | "cpu": [ 12 | "arm64" 13 | ], 14 | "main": "boostest.darwin-arm64.node", 15 | "files": [ 16 | "boostest.darwin-arm64.node" 17 | ], 18 | "license": "MIT", 19 | "engines": { 20 | "node": ">= 10" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/boostest/npm/win32-x64-msvc/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@boostest/boostest-win32-x64-msvc", 3 | "version": "0.8.0", 4 | "publishConfig": { 5 | "registry": "https://registry.npmjs.org/", 6 | "access": "public" 7 | }, 8 | "os": [ 9 | "win32" 10 | ], 11 | "cpu": [ 12 | "x64" 13 | ], 14 | "main": "boostest.win32-x64-msvc.node", 15 | "files": [ 16 | "boostest.win32-x64-msvc.node" 17 | ], 18 | "license": "MIT", 19 | "engines": { 20 | "node": ">= 10" 21 | } 22 | } -------------------------------------------------------------------------------- /apps/test/src/types/mix.ts: -------------------------------------------------------------------------------- 1 | import ComplexClass from './deepfiles/lib/comp_class'; 2 | import ComplexInterfaceChips from './deepfiles/lib/comp_interface'; 3 | export type { ComplexChipsType as MixCompTSAlias } from './deepfiles/lib/comp_type_alias'; 4 | 5 | interface MixInterface { 6 | name: string; 7 | chips: ComplexInterfaceChips; 8 | } 9 | 10 | type MixTSAlias = { 11 | name: string; 12 | chips: ComplexInterfaceChips; 13 | }; 14 | 15 | export type { MixInterface as AnoMixInterface, MixTSAlias as default }; 16 | -------------------------------------------------------------------------------- /packages/boostest/npm/linux-x64-gnu/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@boostest/boostest-linux-x64-gnu", 3 | "version": "0.8.0", 4 | "publishConfig": { 5 | "registry": "https://registry.npmjs.org/", 6 | "access": "public" 7 | }, 8 | "os": [ 9 | "linux" 10 | ], 11 | "cpu": [ 12 | "x64" 13 | ], 14 | "main": "boostest.linux-x64-gnu.node", 15 | "files": [ 16 | "boostest.linux-x64-gnu.node" 17 | ], 18 | "license": "MIT", 19 | "engines": { 20 | "node": ">= 10" 21 | }, 22 | "libc": [ 23 | "glibc" 24 | ] 25 | } -------------------------------------------------------------------------------- /apps/test/src/tests/union/__snapshots__/union.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Union Tests TSAliasMixUnionObjType matches snapshot 1`] = `"{"ref_type":"A","type":"A"}"`; 4 | 5 | exports[`Union Tests TSAliasMixUnionType matches snapshot 1`] = `"true"`; 6 | 7 | exports[`Union Tests TSAliasStringUnionType matches snapshot 1`] = `""A""`; 8 | 9 | exports[`Union Tests TSInterfaceMixUnionType matches snapshot 1`] = `"{"type":"A"}"`; 10 | 11 | exports[`Union Tests TSInterfaceStringUnionType matches snapshot 1`] = `"{"type":"A"}"`; 12 | -------------------------------------------------------------------------------- /apps/test/src/types/ts_types/union.ts: -------------------------------------------------------------------------------- 1 | export type TSAliasStringUnionType = "A" | "B" | "C"; 2 | export type TSAliasMixUnionType = 3 | | 50000 4 | | "A" 5 | | 1 6 | | true 7 | | TSAliasStringUnionType; 8 | 9 | export type TSAliasMixUnionObjType = { 10 | ref_type: TSAliasMixUnionType; 11 | type: 50000 | "A" | 1 | true | TSAliasStringUnionType; 12 | }; 13 | 14 | export interface TSInterfaceStringUnionType { 15 | type: "A" | "B" | "C"; 16 | } 17 | export interface TSInterfaceMixUnionType { 18 | type: 50000 | "A" | 1 | true | TSAliasStringUnionType; 19 | } 20 | -------------------------------------------------------------------------------- /apps/example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "target": "ESNext", 5 | "module": "ESNext", 6 | "moduleResolution": "Node", 7 | "lib": ["ESNext", "DOM"], 8 | "noPropertyAccessFromIndexSignature": false, 9 | "isolatedModules": true, 10 | "esModuleInterop": true, 11 | "forceConsistentCasingInFileNames": true 12 | }, 13 | "ts-node": { 14 | "esm": true, 15 | "files": true, 16 | "transpileOnly": true, 17 | "experimentalResolver": true, 18 | "experimentalSpecifierResolution": "node" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /apps/example/src/handlefiles/nestedExample.ts: -------------------------------------------------------------------------------- 1 | import { User } from '../types/user'; 2 | import Job from '../types/job'; 3 | 4 | const userInterfaceTestData = boostestUser({ 5 | name: 'override_name', 6 | age: 42, 7 | }); 8 | const JobTypeTestData = boostestJOB({ 9 | name: 'override_name', 10 | salary: 100, 11 | }); 12 | 13 | console.log('\n\n------------------------'); 14 | console.log('userInterfaceMock', userInterfaceTestData); 15 | console.log('------------------------'); 16 | console.log('JobTypeMock', JobTypeTestData); 17 | console.log('------------------------'); 18 | -------------------------------------------------------------------------------- /packages/boostest/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | edition = "2021" 3 | name = "npm-boostest" 4 | version = "0.0.0" 5 | 6 | [lib] 7 | crate-type = ["cdylib"] 8 | 9 | [dependencies] 10 | # Default enable napi4 feature, see https://nodejs.org/api/n-api.html#node-api-version-matrix 11 | napi = { version = "2.12.2", default-features = false, features = ["napi4"] } 12 | napi-derive = "2.12.2" 13 | 14 | 15 | boostest = { path = "../../crates/boostest" } 16 | 17 | 18 | [build-dependencies] 19 | napi-build = "2.0.1" 20 | 21 | [profile.release] 22 | lto = true 23 | strip = "symbols" 24 | 25 | -------------------------------------------------------------------------------- /packages/boostest/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["bin/**/*"], 3 | "exclude": ["bin/*.js", "bin/*.mjs", "bin/*.cjs", "node_modules"], 4 | "compilerOptions": { 5 | "target": "ESNext", 6 | "module": "NodeNext", 7 | "moduleResolution": "NodeNext", 8 | "baseUrl": "./", 9 | "paths": { 10 | "@bin/*": ["bin/*"] 11 | }, 12 | "outDir": "dist", 13 | "types": ["node"], 14 | "allowJs": true, 15 | "checkJs": true, 16 | // "noEmit": true, 17 | "isolatedModules": true, 18 | "esModuleInterop": true, 19 | "forceConsistentCasingInFileNames": true, 20 | "strict": true, 21 | "skipLibCheck": true 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /apps/test/src/tests/call_signature/__snapshots__/call_signature.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Call Signature Tests CallSignature matches snapshot 1`] = `"(name, age) => { }"`; 4 | 5 | exports[`Call Signature Tests CallSignatureInterface matches snapshot 1`] = `"(name, age) => { }"`; 6 | 7 | exports[`Call Signature Tests MathOperations matches snapshot 1`] = `"{"add":"(a, b) => {\\n return 10;\\n }","multiply":"(a, b) => {\\n return 10;\\n }"}"`; 8 | 9 | exports[`Call Signature Tests SingleCallSignature matches snapshot 1`] = ` 10 | "(name, age) => { 11 | return null; 12 | }" 13 | `; 14 | -------------------------------------------------------------------------------- /packages/boostest/npm/publish.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # ディレクトリ名をリストとして定義 4 | directories=("darwin-arm64" "darwin-x64" "linux-x64-gnu" "win32-x64-msvc") 5 | 6 | # 現在のディレクトリを保存 7 | current_dir=$(pwd) 8 | 9 | # 各ディレクトリで `npm publish` を実行 10 | for dir in "${directories[@]}"; do 11 | if [ -d "$dir" ]; then 12 | echo "Publishing in $dir..." 13 | cd "$dir" || exit 14 | npm publish --access public 15 | if [ $? -ne 0 ]; then 16 | echo "Failed to publish in $dir" 17 | else 18 | echo "Successfully published in $dir" 19 | fi 20 | cd "$current_dir" || exit 21 | else 22 | echo "Directory $dir does not exist, skipping..." 23 | fi 24 | done 25 | -------------------------------------------------------------------------------- /apps/test/src/types/ts_types/call_signature.ts: -------------------------------------------------------------------------------- 1 | export type SingleCallSignature = (name: string, age: number) => null; 2 | 3 | export type CallSignature = { 4 | // NOTE: support first fucnction type only 5 | (name: string, age: number): void; 6 | (contents: string): string; 7 | (): void; 8 | 9 | // WARN: this is not working 10 | name: string; 11 | }; 12 | 13 | export type MathOperations = { 14 | add: (a: number, b: number) => number; 15 | multiply: (a: number, b: number) => number; 16 | }; 17 | 18 | export interface CallSignatureInterface { 19 | (name: string, age: number): void; 20 | (): void; 21 | 22 | // WARN: this is not working 23 | name: string; 24 | } 25 | -------------------------------------------------------------------------------- /apps/test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "target": "ESNext", 5 | "module": "ESNext", 6 | "moduleResolution": "Node", 7 | "lib": ["ESNext", "DOM"], 8 | "noPropertyAccessFromIndexSignature": false, 9 | "isolatedModules": true, 10 | "esModuleInterop": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "allowSyntheticDefaultImports": true, 13 | "paths": { 14 | "@/*": ["./src/types/*"] 15 | } 16 | }, 17 | "ts-node": { 18 | "esm": true, 19 | "files": true, 20 | "transpileOnly": true, 21 | "experimentalResolver": true, 22 | "experimentalSpecifierResolution": "node" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /apps/test/src/tests/insersection/__snapshots__/intersection.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Intersection Tests IntersectionClass matches snapshot 1`] = `"{"intersction_obj":{"name":"test string data","ver":10},"intersction_string":"hoga","nonNullable":"test string data"}"`; 4 | 5 | exports[`Intersection Tests IntersectionInterface matches snapshot 1`] = `"{"intersction_obj":{"name":"test string data","ver":10},"intersction_string":"hoga","nonNullable":"test string data"}"`; 6 | 7 | exports[`Intersection Tests IntersectionTypeAlias matches snapshot 1`] = `"{"intersction_obj":{"name":"test string data","ver":10},"intersction_string":"hoga","nonNullable":"test string data"}"`; 8 | -------------------------------------------------------------------------------- /apps/test/src/tests/renamed/__snapshots__/renamed.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Rename Tests RenamedComplexChipsType matches snapshot 1`] = `"{"name":"test string data","age":10,"sex":1,"short_name":"john","favorite":{"name":"Calbee Lightly Salted","price":120},"mostFav":{"name":"Pringles Sour Cream & Onion 😀","price":200},"func":"() => { }","undefinedKey":"undefined","anyKey":"any","nullKey":null,"optionalKey":"test string data","unknownKey":"undefined","thisKey":{},"conditionalKey":{"name":"Kettle Brand Sea Salt & Vinegar 日本語が入るとどう?🤔","price":250},"objectKey":{},"voidKey":null,"indexedKey":"test string data","intersectionKey":{"name":"Lay's Classic","price":130,"taste":"test string data"},"arrayKey":[]}"`; 4 | -------------------------------------------------------------------------------- /apps/test/src/tests/renamed/renamed.spec.ts: -------------------------------------------------------------------------------- 1 | import { runSnapshotTest } from "../utils"; 2 | 3 | import { 4 | // RenamedNestedPropClass, 5 | RenamedComplexChipsType, 6 | } from "../../types/export_rename"; 7 | // import { boostestRenamedNestedPropClass } from "./boostest_output/boostestRenamedNestedPropClass"; 8 | import { boostestRenamedComplexChipsType } from "./boostest_output/boostestRenamedComplexChipsType"; 9 | 10 | describe("Rename Tests", () => { 11 | // runSnapshotTest( 12 | // "RenamedNestedPropClass", 13 | // boostestRenamedNestedPropClass(), 14 | // ); 15 | 16 | runSnapshotTest( 17 | "RenamedComplexChipsType", 18 | boostestRenamedComplexChipsType(), 19 | ); 20 | }); 21 | -------------------------------------------------------------------------------- /packages/boostest/move_nodes.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | declare -A file_to_dir 4 | 5 | file_to_dir["boostest.darwin-arm64.node"]="npm/darwin-arm64" 6 | file_to_dir["boostest.darwin-x64.node"]="npm/darwin-x64" 7 | file_to_dir["boostest.linux-x64-gnu.node"]="npm/linux-x64-gnu" 8 | file_to_dir["boostest.win32-x64-msvc.node"]="npm/win32-x64-msvc" 9 | 10 | for file in "${!file_to_dir[@]}"; do 11 | target_dir="${file_to_dir[$file]}" 12 | 13 | if [ -d "$target_dir" ]; then 14 | if [ -f "$file" ]; then 15 | echo "Moving $file to $target_dir" 16 | mv "$file" "$target_dir" 17 | else 18 | echo "File $file does not exist, skipping..." 19 | fi 20 | else 21 | echo "Target directory $target_dir does not exist, skipping..." 22 | fi 23 | done 24 | -------------------------------------------------------------------------------- /apps/example/src/types/deepfiles/lib/chips.ts: -------------------------------------------------------------------------------- 1 | export interface PotatoChip { 2 | name: string; 3 | price: number; // 円 4 | } 5 | 6 | export interface CalbeeLightlySalted extends PotatoChip { 7 | name: 'Calbee Lightly Salted'; 8 | price: 120; 9 | } 10 | 11 | export interface KoikeyaPridePotato extends PotatoChip { 12 | name: 'Koikeya Pride Potato'; 13 | price: 150; 14 | } 15 | 16 | export interface PringlesSourCreamAndOnion extends PotatoChip { 17 | name: 'Pringles Sour Cream & Onion'; 18 | price: 200; 19 | } 20 | 21 | export interface KettleBrandSeaSaltAndVinegar extends PotatoChip { 22 | name: 'Kettle Brand Sea Salt & Vinegar'; 23 | price: 250; 24 | } 25 | 26 | export interface LayClassic extends PotatoChip { 27 | name: "Lay's Classic"; 28 | price: 130; 29 | } 30 | -------------------------------------------------------------------------------- /apps/test/src/types/deepfiles/lib/chips.ts: -------------------------------------------------------------------------------- 1 | export interface PotatoChip { 2 | name: string; 3 | price: number; 4 | } 5 | 6 | export interface CalbeeLightlySalted extends PotatoChip { 7 | name: "Calbee Lightly Salted"; 8 | price: 120; 9 | } 10 | 11 | export interface KoikeyaPridePotato extends PotatoChip { 12 | name: "Koikeya Pride Potato"; 13 | price: 150; 14 | } 15 | 16 | export interface PringlesSourCreamAndOnion extends PotatoChip { 17 | name: "Pringles Sour Cream & Onion 😀"; 18 | price: 200; 19 | } 20 | 21 | export interface KettleBrandSeaSaltAndVinegar extends PotatoChip { 22 | name: "Kettle Brand Sea Salt & Vinegar 日本語が入るとどう?🤔"; 23 | price: 250; 24 | } 25 | 26 | export interface LayClassic extends PotatoChip { 27 | name: "Lay's Classic"; 28 | price: 130; 29 | } 30 | -------------------------------------------------------------------------------- /apps/example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "version": "1.0.0", 4 | "description": "", 5 | "type": "module", 6 | "main": "index.js", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1", 9 | "demo": "node --no-warnings --loader ts-node/esm ./src/example.ts", 10 | "boostest:help": "boostest --help", 11 | "boostest:version": "boostest --version", 12 | "boostest": "boostest ./src/example.ts ./tsconfig.json", 13 | "start:boostest": "boostest" 14 | }, 15 | "keywords": [], 16 | "author": "", 17 | "dependencies": { 18 | "@sendgrid/mail": "^8.1.3", 19 | "@types/express": "^4.17.21", 20 | "axios": "^1.7.2", 21 | "@boostest/cli": "workspace:*", 22 | "express": "^4.19.2", 23 | "ts-node": "^10.9.2", 24 | "typescript": "^5.4.5" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /apps/test/src/tests/nestes_type/nested_type.spec.ts: -------------------------------------------------------------------------------- 1 | import { runSnapshotTest } from "../utils"; 2 | import { NestedType, NestedInterface } from "@/ts_types/nested"; 3 | import { NestedPropClass } from "../../types/nested_prop_class"; 4 | import { boostestNestedType } from "./boostest_output/boostestNestedType"; 5 | import { boostestNestedInterface } from "./boostest_output/boostestNestedInterface"; 6 | import { boostestNestedPropClass } from "./boostest_output/boostestNestedPropClass"; 7 | 8 | describe("Nested Type Tests", () => { 9 | runSnapshotTest("NestedType", boostestNestedType()); 10 | runSnapshotTest( 11 | "NestedInterface", 12 | boostestNestedInterface(), 13 | ); 14 | runSnapshotTest( 15 | "NestedPropClass", 16 | boostestNestedPropClass(), 17 | ); 18 | }); 19 | -------------------------------------------------------------------------------- /packages/boostest/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate napi_derive; 3 | 4 | use napi::*; 5 | 6 | use boostest::{generate, resolve_target, OutputCode, OutputOption, ResolvedResult}; 7 | use std::{collections::HashMap, path::Path}; 8 | 9 | #[napi] 10 | pub fn resolve( 11 | path: String, 12 | lib_file_path: String, 13 | ts_config_path: Option, 14 | ) -> ResolvedResult { 15 | let lib_file_path = Path::new(&lib_file_path); 16 | if let Some(ts_config_path) = ts_config_path { 17 | let ts_config_path = Path::new(&ts_config_path); 18 | return resolve_target(path, Some(ts_config_path), lib_file_path); 19 | } 20 | 21 | resolve_target(path, None, lib_file_path) 22 | } 23 | 24 | #[napi] 25 | pub fn generatetest(output: HashMap, output_option: OutputOption) { 26 | generate(output, output_option) 27 | } 28 | -------------------------------------------------------------------------------- /apps/test/src/tests/built_in/builtIn.spec.ts: -------------------------------------------------------------------------------- 1 | import { runSnapshotTest } from "../utils"; 2 | import { 3 | BuiltInClass, 4 | BuiltInInterface, 5 | BuiltInType, 6 | } from "@/ts_types/built_in_class"; 7 | import { boostestTSAliasBuiltInType } from "./boostest_output/boostestTSAliasBuiltInType"; 8 | import { boostestInterfaceBuiltInType } from "./boostest_output/boostestInterfaceBuiltInType"; 9 | import { boostestClassBuiltInType } from "./boostest_output/boostestClassBuiltInType"; 10 | 11 | describe("BuiltIn Tests", () => { 12 | runSnapshotTest( 13 | "type alias BuiltIn", 14 | boostestTSAliasBuiltInType(), 15 | ); 16 | runSnapshotTest( 17 | "interface BuiltIn", 18 | boostestInterfaceBuiltInType(), 19 | ); 20 | runSnapshotTest("class BuiltIn", boostestClassBuiltInType()); 21 | }); 22 | -------------------------------------------------------------------------------- /apps/test/src/types/ts_types/intersection.ts: -------------------------------------------------------------------------------- 1 | export type IntersectionTypeAlias = { 2 | // intersction: string & number; 3 | intersction_obj: { name: string } & { ver: number }; 4 | intersction_string: string & "hoga"; 5 | nonNullable: NonNullable; 6 | }; 7 | 8 | export type IntersectionInterface = { 9 | // intersction: string & number; 10 | intersction_obj: { name: string } & { ver: number }; 11 | intersction_string: string & "hoga"; 12 | nonNullable: NonNullable; 13 | }; 14 | 15 | export class IntersectionClass { 16 | constructor( 17 | // public intersction: string & {}, 18 | public intersction_obj: { name: string } & { ver: number }, 19 | public intersction_string: string & "hoga", 20 | public nonNullable: NonNullable, 21 | ) {} 22 | } 23 | -------------------------------------------------------------------------------- /crates/boostest/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "boostest" 3 | version = "0.1.0" 4 | 5 | edition.workspace = true 6 | homepage.workspace = true 7 | license.workspace = true 8 | repository.workspace = true 9 | 10 | 11 | [lints] 12 | workspace = true 13 | 14 | [dependencies] 15 | oxc = { workspace = true, features = ["semantic", "codegen"] } 16 | oxc_resolver = { workspace = true } 17 | anyhow = { workspace = true } 18 | globwalker = { workspace = true } 19 | serde = { workspace = true } 20 | serde_json = { workspace = true } 21 | colored = { workspace = true } 22 | regex = { workspace = true } 23 | ropey = { workspace = true } 24 | spinoff = { workspace = true } 25 | sha2 = { workspace = true } 26 | rayon = { workspace = true } 27 | 28 | napi = { workspace = true } 29 | napi-derive = { workspace = true } 30 | 31 | [dev-dependencies] 32 | tempfile = "3.13.0" 33 | -------------------------------------------------------------------------------- /apps/test/src/tests/sandbox.ts: -------------------------------------------------------------------------------- 1 | type main = 2 | ref_5450c7e54ff602814aefb578141612331188c886e2c092ce0b16692c10a90d0e; 3 | type ref_5450c7e54ff602814aefb578141612331188c886e2c092ce0b16692c10a90d0e = { 4 | regexp: ref_df316930e33dd8c70ce446a1269ebd0fc8c83648e97cba491329daddc19aef5e; 5 | }; 6 | interface ref_df316930e33dd8c70ce446a1269ebd0fc8c83648e97cba491329daddc19aef5e { 7 | exec( 8 | string: string, 9 | ): ref_23fa0c841a57bf38f7d312b179d4bf4f1ae9a2038b2283150dc322460f3c1535 | null; 10 | test(string: string): boolean; 11 | readonly source: string; 12 | readonly global: boolean; 13 | readonly ignoreCase: boolean; 14 | readonly multiline: boolean; 15 | lastIndex: number; 16 | compile(pattern: string, flags?: string): this; 17 | } 18 | interface ref_23fa0c841a57bf38f7d312b179d4bf4f1ae9a2038b2283150dc322460f3c1535 { 19 | index: number; 20 | input: string; 21 | 0: string; 22 | } 23 | -------------------------------------------------------------------------------- /apps/test/src/tests/standard/standard.spec.ts: -------------------------------------------------------------------------------- 1 | import { runSnapshotTest } from "../utils"; 2 | 3 | import { 4 | LiteralTypeAlias, 5 | LiteralTypeClass, 6 | LiteralTypeInterface, 7 | } from "../../types/ts_types/literal"; 8 | import { boostestLiteralAliasType } from "./boostest_output/boostestLiteralAliasType"; 9 | import { boostestLiteralInterfaceType } from "./boostest_output/boostestLiteralInterfaceType"; 10 | import { boostestLiteralTypeClass } from "./boostest_output/boostestLiteralTypeClass"; 11 | 12 | describe("Standard Tests", () => { 13 | runSnapshotTest( 14 | "LiteralTypeAlias", 15 | boostestLiteralAliasType(), 16 | ); 17 | runSnapshotTest( 18 | "LiteralTypeInterface", 19 | boostestLiteralInterfaceType(), 20 | ); 21 | 22 | runSnapshotTest( 23 | "LiteralTypeClass", 24 | boostestLiteralTypeClass(), 25 | ); 26 | }); 27 | -------------------------------------------------------------------------------- /apps/test/src/types/deepfiles/lib/comp_type_alias.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PotatoChip, 3 | CalbeeLightlySalted, 4 | KoikeyaPridePotato, 5 | PringlesSourCreamAndOnion, 6 | KettleBrandSeaSaltAndVinegar, 7 | LayClassic, 8 | } from "./chips"; 9 | 10 | export type ComplexChipsType = { 11 | name: string; 12 | age: number; 13 | sex: 1 | 2; 14 | short_name: "john" | "doe"; 15 | favorite: CalbeeLightlySalted | KoikeyaPridePotato; 16 | mostFav: PringlesSourCreamAndOnion; 17 | func: () => void; 18 | undefinedKey: undefined; 19 | anyKey: any; 20 | nullKey: null; 21 | optionalKey?: string; 22 | unknownKey: unknown; 23 | thisKey: ThisType; 24 | conditionalKey: CalbeeLightlySalted extends PotatoChip 25 | ? KettleBrandSeaSaltAndVinegar 26 | : false; 27 | objectKey: object; 28 | voidKey: void; 29 | indexedKey: PotatoChip["name"]; 30 | intersectionKey: LayClassic & { taste: string }; 31 | arrayKey: PotatoChip[]; 32 | }; 33 | -------------------------------------------------------------------------------- /apps/example/src/types/deepfiles/lib/comp_type_alias.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PotatoChip, 3 | CalbeeLightlySalted, 4 | KoikeyaPridePotato, 5 | PringlesSourCreamAndOnion, 6 | KettleBrandSeaSaltAndVinegar, 7 | LayClassic, 8 | } from "./chips"; 9 | 10 | export type ComplexChipsType = { 11 | name: string; 12 | age: number; 13 | sex: 1 | 2; 14 | short_name: "john" | "doe"; 15 | favorite: CalbeeLightlySalted | KoikeyaPridePotato; 16 | mostFav: PringlesSourCreamAndOnion; 17 | func: () => void; 18 | undefinedKey: undefined; 19 | anyKey: any; 20 | nullKey: null; 21 | optionalKey?: string; 22 | unknownKey: unknown; 23 | thisKey: ThisType; 24 | conditionalKey: CalbeeLightlySalted extends PotatoChip 25 | ? KettleBrandSeaSaltAndVinegar 26 | : false; 27 | objectKey: object; 28 | voidKey: void; 29 | indexedKey: PotatoChip["name"]; 30 | intersectionKey: LayClassic & { taste: string }; 31 | arrayKey: PotatoChip[]; 32 | }; 33 | -------------------------------------------------------------------------------- /apps/test/src/tests/insersection/intersection.spec.ts: -------------------------------------------------------------------------------- 1 | import { runSnapshotTest } from "../utils"; 2 | 3 | import { 4 | IntersectionTypeAlias, 5 | IntersectionInterface, 6 | IntersectionClass, 7 | } from "../../types/ts_types/intersection"; 8 | import { boostestIntersectionTypeAlias } from "./boostest_output/boostestIntersectionTypeAlias"; 9 | import { boostestIntersectionInterface } from "./boostest_output/boostestIntersectionInterface"; 10 | import { boostestIntersectionClass } from "./boostest_output/boostestIntersectionClass"; 11 | 12 | describe("Intersection Tests", () => { 13 | runSnapshotTest( 14 | "IntersectionTypeAlias", 15 | boostestIntersectionTypeAlias(), 16 | ); 17 | runSnapshotTest( 18 | "IntersectionInterface", 19 | boostestIntersectionInterface(), 20 | ); 21 | runSnapshotTest( 22 | "IntersectionClass", 23 | boostestIntersectionClass(), 24 | ); 25 | }); 26 | -------------------------------------------------------------------------------- /apps/example/src/types/deepfiles/lib/comp_interface.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PotatoChip, 3 | CalbeeLightlySalted, 4 | KoikeyaPridePotato, 5 | PringlesSourCreamAndOnion, 6 | KettleBrandSeaSaltAndVinegar, 7 | LayClassic, 8 | } from "./chips"; 9 | 10 | export default interface ComplexInterfaceChips { 11 | name: string; 12 | age: number; 13 | sex: 1 | 2; 14 | short_name: "john" | "doe"; 15 | favorite: CalbeeLightlySalted | KoikeyaPridePotato; 16 | mostFav: PringlesSourCreamAndOnion; 17 | func: () => void; 18 | undefinedKey: undefined; 19 | anyKey: any; 20 | nullKey: null; 21 | optionalKey?: string; 22 | unknownKey: unknown; 23 | thisKey: ThisType; 24 | conditionalKey: CalbeeLightlySalted extends PotatoChip 25 | ? KettleBrandSeaSaltAndVinegar 26 | : false; 27 | objectKey: object; 28 | voidKey: void; 29 | indexedKey: PotatoChip["name"]; 30 | intersectionKey: LayClassic & { taste: string }; 31 | arrayKey: PotatoChip[]; 32 | } 33 | -------------------------------------------------------------------------------- /apps/test/src/types/deepfiles/lib/comp_interface.ts: -------------------------------------------------------------------------------- 1 | import { 2 | PotatoChip, 3 | CalbeeLightlySalted, 4 | KoikeyaPridePotato, 5 | PringlesSourCreamAndOnion, 6 | KettleBrandSeaSaltAndVinegar, 7 | LayClassic, 8 | } from "./chips"; 9 | 10 | export default interface ComplexInterfaceChips { 11 | name: string; 12 | age: number; 13 | sex: 1 | 2; 14 | short_name: "john" | "doe"; 15 | favorite: CalbeeLightlySalted | KoikeyaPridePotato; 16 | mostFav: PringlesSourCreamAndOnion; 17 | func: () => void; 18 | undefinedKey: undefined; 19 | anyKey: any; 20 | nullKey: null; 21 | optionalKey?: string; 22 | unknownKey: unknown; 23 | thisKey: ThisType; 24 | conditionalKey: CalbeeLightlySalted extends PotatoChip 25 | ? KettleBrandSeaSaltAndVinegar 26 | : false; 27 | objectKey: object; 28 | voidKey: void; 29 | indexedKey: PotatoChip["name"]; 30 | intersectionKey: LayClassic & { taste: string }; 31 | arrayKey: PotatoChip[]; 32 | } 33 | -------------------------------------------------------------------------------- /apps/test/src/tests/zod/zod.spec.ts: -------------------------------------------------------------------------------- 1 | import { UserResponseSchema, userScheme, User } from "@/ts_types"; 2 | import { runSnapshotTest } from "../utils"; 3 | import { z } from "zod"; 4 | import { boostestZodUserSchemeType } from "./boostest_output/boostestZodUserSchemeType"; 5 | import { boostestZodUserType } from "./boostest_output/boostestZodUserType"; 6 | // import { boostestZodUserResponseSchemeType } from "./boostest_output/boostestZodUserResponseSchemeType"; 7 | 8 | type UserResponseSchemaType = z.infer; 9 | type UserSchemeType = z.infer; 10 | 11 | // TODO: 12 | describe("Invest Tests", () => { 13 | runSnapshotTest("Invest simple zod", boostestZodUserType()); 14 | runSnapshotTest( 15 | "Invest object zod", 16 | boostestZodUserSchemeType(), 17 | ); 18 | // TODO: 19 | // runSnapshotTest( 20 | // "Invest response zod", 21 | // boostestZodUserResponseSchemeType(), 22 | // ); 23 | }); 24 | -------------------------------------------------------------------------------- /apps/test/src/tests/main_file_import/main_file_import.spec.ts: -------------------------------------------------------------------------------- 1 | import { runSnapshotTest } from "../utils"; 2 | 3 | import { LiteralTypeAlias } from "@/export_main_file"; 4 | import { LiteralTypeAlias as DLiteralTypeAlias } from "@/export_d_main_file"; 5 | import type { LiteralTypeAlias as FileNameLiteralTypeAlias } from "@/export_filename_main_file/literal"; 6 | import { boostestIndexExort } from "./boostest_output/boostestIndexExort"; 7 | import { boostestDLiteralTypeAlias } from "./boostest_output/boostestDLiteralTypeAlias"; 8 | import { boostestFileNameLiteralTypeAlias } from "./boostest_output/boostestFileNameLiteralTypeAlias"; 9 | 10 | describe("main file import tests", () => { 11 | runSnapshotTest("IndexExport", boostestIndexExort()); 12 | runSnapshotTest( 13 | "DLiteralTypeAlias", 14 | boostestDLiteralTypeAlias(), 15 | ); 16 | runSnapshotTest( 17 | "FileNameLiteralTypeAlias", 18 | boostestFileNameLiteralTypeAlias(), 19 | ); 20 | }); 21 | -------------------------------------------------------------------------------- /apps/test/src/tests/outpout_test.sspec.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect } from "@jest/globals"; 2 | import path from "path"; 3 | const fs = require("fs"); 4 | 5 | function getFilesRecursively(dir: string): string[] { 6 | let results: string[] = []; 7 | const list = fs.readdirSync(dir); 8 | list.forEach((file) => { 9 | file = path.resolve(dir, file); 10 | const stat = fs.statSync(file); 11 | if (stat && stat.isDirectory()) { 12 | results = results.concat(getFilesRecursively(file)); 13 | } else { 14 | results.push(file); 15 | } 16 | }); 17 | return results; 18 | } 19 | 20 | describe("boostest all dir output correctly", () => { 21 | try { 22 | const files = getFilesRecursively("."); 23 | const testFiles = files.filter((file) => file.includes("_test_data")); 24 | 25 | testFiles.forEach((file) => { 26 | const data = fs.readFileSync(file, "utf-8"); 27 | test(`output correctly ${file}`, () => { 28 | expect(data).toMatchSnapshot(); 29 | }); 30 | }); 31 | } catch (err) { 32 | console.log("err", err); 33 | } 34 | }); 35 | -------------------------------------------------------------------------------- /apps/test/src/types/ts_types/zod.ts: -------------------------------------------------------------------------------- 1 | import { extendApi } from "@anatine/zod-openapi"; 2 | import { z } from "zod"; 3 | 4 | const UserObj = z.object({ 5 | username: z.string(), 6 | }); 7 | 8 | export type User = z.infer; 9 | 10 | export const userScheme = z.object({ 11 | username: z.string(), 12 | location: z.object({ 13 | latitude: z.number(), 14 | longitude: z.number(), 15 | }), 16 | strings: z.array(z.object({ value: z.string() })), 17 | }); 18 | 19 | export const UserResponseSchema = extendApi( 20 | z.array( 21 | z.object({ 22 | id: extendApi(z.number().min(1), { 23 | description: "ID", 24 | example: 123, 25 | format: "int64", 26 | }), 27 | name: extendApi(z.string().max(64).nullable(), { 28 | description: "Name", 29 | example: "HeyShohei", 30 | }), 31 | URL: extendApi(z.string().nullable(), { 32 | description: "image Url", 33 | example: "https://example.com/images/main.jpg", 34 | }), 35 | }), 36 | ), 37 | { 38 | description: "UserResponse", 39 | }, 40 | ); 41 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = ["crates/boostest"] 3 | 4 | exclude = ["packages/boostest"] 5 | resolver = "2" 6 | 7 | [workspace.package] 8 | edition = "2021" 9 | homepage = "https://hoge.rs/" 10 | license = "MIT" 11 | repository = "https://github.com/hoge" 12 | 13 | [workspace.lints.rust] 14 | [workspace.lints.clippy] 15 | 16 | 17 | [workspace.dependencies] 18 | 19 | oxc = { version = "0.38.0", features = ["sourcemap", "sourcemap_concurrent"] } 20 | oxc_resolver = { version = "3.0.3", features = ["package_json_raw_json_api"] } 21 | 22 | clap = { version = "4.4.7", features = ["derive", "env"] } 23 | regex = "1.10.4" 24 | globwalker = "0.9.0" 25 | colored = "2" 26 | rayon = "1.10.0" 27 | 28 | self_cell = "1.0.4" 29 | smallvec = "1.13.2" 30 | anyhow = "1.0" 31 | 32 | serde = { version = "1.0", features = ["derive"] } 33 | serde_json = "1.0" 34 | ropey = "1.6.1" 35 | 36 | boostest = { version = "0.0.1", path = "./crates/boostest" } 37 | spinoff = "0.8.0" 38 | 39 | sha2 = "0.10" 40 | 41 | 42 | napi = { version = "2.12.2", default-features = false, features = ["napi4"] } 43 | napi-derive = "2.12.2" 44 | -------------------------------------------------------------------------------- /apps/test/src/tests/generics/generics.spec.ts: -------------------------------------------------------------------------------- 1 | import { runSnapshotTest } from "../utils"; 2 | 3 | import { 4 | InngerPropGeneric, 5 | GenericsTypeAlias, 6 | GenericsInterface, 7 | GenericsClass, 8 | } from "../../types/ts_types/generics"; 9 | import { RefType } from "../../types/ts_types/utils"; 10 | import { boostestGenericsAliasType } from "./boostest_output/boostestGenericsAliasType"; 11 | import { boostestGeneric } from "./boostest_output/boostestGeneric"; 12 | import { boostestGenericsInterfaceType } from "./boostest_output/boostestGenericsInterfaceType"; 13 | import { boostestGenericsTypeClass } from "./boostest_output/boostestGenericsTypeClass"; 14 | 15 | describe("Generics Tests", () => { 16 | runSnapshotTest( 17 | "GenericsTypeAlias", 18 | boostestGenericsAliasType(), 19 | ); 20 | runSnapshotTest("Generic", boostestGeneric>()); 21 | runSnapshotTest( 22 | "GenericsInterface", 23 | boostestGenericsInterfaceType(), 24 | ); 25 | runSnapshotTest("GenericsClass", boostestGenericsTypeClass()); 26 | }); 27 | -------------------------------------------------------------------------------- /packages/boostest/index.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | 4 | /* auto-generated by NAPI-RS */ 5 | 6 | export const enum TargetType { 7 | Class = 0, 8 | TSInterface = 1, 9 | TSTypeAlias = 2, 10 | Variable = 3, 11 | Function = 4, 12 | TSModule = 5, 13 | ImportAll = 6 14 | } 15 | export interface OutputCode { 16 | code: string 17 | targetType: TargetType 18 | path: string 19 | } 20 | export interface DefaultValueOption { 21 | number: number 22 | string: string 23 | bigint: string 24 | any: string 25 | undefined: string 26 | boolean: boolean 27 | null: string 28 | } 29 | export interface OutputOption { 30 | single: boolean 31 | projectRootPath?: string 32 | defaultValueOption: DefaultValueOption 33 | } 34 | export interface ResolvedResult { 35 | outputCode?: Record 36 | outputOption: OutputOption 37 | } 38 | export declare function resolve(path: string, libFilePath: string, tsConfigPath?: string | undefined | null): ResolvedResult 39 | export declare function generatetest(output: Record, outputOption: OutputOption): void 40 | -------------------------------------------------------------------------------- /apps/test/src/tests/call_signature/call_signature.spec.ts: -------------------------------------------------------------------------------- 1 | import { runSnapshotTest } from "../utils"; 2 | 3 | import { 4 | CallSignature, 5 | MathOperations, 6 | SingleCallSignature, 7 | CallSignatureInterface, 8 | } from "../../types/ts_types/call_signature"; 9 | import { boostestCallSignature } from "./boostest_output/boostestCallSignature"; 10 | import { boostestCallSignatureInterface } from "./boostest_output/boostestCallSignatureInterface"; 11 | import { boostestSingleCallSignature } from "./boostest_output/boostestSingleCallSignature"; 12 | import { boostestMathOperations } from "./boostest_output/boostestMathOperations"; 13 | 14 | describe("Call Signature Tests", () => { 15 | runSnapshotTest("CallSignature", boostestCallSignature()); 16 | 17 | runSnapshotTest( 18 | "CallSignatureInterface", 19 | boostestCallSignatureInterface(), 20 | ); 21 | 22 | runSnapshotTest( 23 | "SingleCallSignature", 24 | boostestSingleCallSignature(), 25 | ); 26 | 27 | runSnapshotTest("MathOperations", boostestMathOperations()); 28 | }); 29 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) MasatoDev 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 | -------------------------------------------------------------------------------- /crates/boostest/src/boostest_manager/task.rs: -------------------------------------------------------------------------------- 1 | use crate::boostest_generator::code_generator::CodeGenerator; 2 | use crate::boostest_utils::napi::OutputCode; 3 | use crate::OutputOption; 4 | 5 | use anyhow::Result; 6 | use std::fs::File; 7 | use std::io::prelude::*; 8 | use std::path::PathBuf; 9 | use std::sync::Arc; 10 | 11 | pub fn handle_main_task( 12 | output_option_arc: Arc, 13 | func_name: &str, 14 | output: &OutputCode, 15 | output_dir_path: PathBuf, 16 | ) -> Result<()> { 17 | let OutputCode { code, .. } = output; 18 | 19 | let file_path = output_dir_path.join(format!("{}{}", func_name, ".ts")); // srcディレクトリ内のgreeting.ts 20 | let mut f: File = File::create(&file_path)?; 21 | 22 | let allocator = oxc::allocator::Allocator::default(); 23 | 24 | let mut code_generator = CodeGenerator::new( 25 | output_option_arc.clone(), 26 | &allocator, 27 | func_name, 28 | "", 29 | code, 30 | None, 31 | ); 32 | 33 | code_generator.generate(); 34 | 35 | if let Some(code) = code_generator.code { 36 | f.write_all(code.as_bytes())?; 37 | } 38 | Ok(()) 39 | } 40 | -------------------------------------------------------------------------------- /apps/test/src/types/deepfiles/lib/comp_class.ts: -------------------------------------------------------------------------------- 1 | import { PotatoChip, CalbeeLightlySalted, KoikeyaPridePotato, PringlesSourCreamAndOnion, KettleBrandSeaSaltAndVinegar, LayClassic } from './chips'; 2 | 3 | export default class ComplexClass { 4 | name: string; 5 | calbeeLightlySalted: CalbeeLightlySalted; 6 | koikeyaPridePotato: KoikeyaPridePotato; 7 | pringlesSourCreamAndOnion: PringlesSourCreamAndOnion; 8 | kettleBrandSeaSaltAndVinegar: KettleBrandSeaSaltAndVinegar; 9 | layClassic: LayClassic; 10 | chips: PotatoChip[]; 11 | 12 | constructor( 13 | name: string, 14 | calbeeLightlySalted: CalbeeLightlySalted, 15 | koikeyaPridePotato: KoikeyaPridePotato, 16 | pringlesSourCreamAndOnion: PringlesSourCreamAndOnion, 17 | kettleBrandSeaSaltAndVinegar: KettleBrandSeaSaltAndVinegar, 18 | layClassic: LayClassic, 19 | chips: PotatoChip[] 20 | ) { 21 | this.name = name; 22 | this.calbeeLightlySalted = calbeeLightlySalted; 23 | this.koikeyaPridePotato = koikeyaPridePotato; 24 | this.pringlesSourCreamAndOnion = pringlesSourCreamAndOnion; 25 | this.kettleBrandSeaSaltAndVinegar = kettleBrandSeaSaltAndVinegar; 26 | this.layClassic = layClassic; 27 | this.chips = chips; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /apps/example/src/types/deepfiles/lib/comp_class.ts: -------------------------------------------------------------------------------- 1 | import { PotatoChip, CalbeeLightlySalted, KoikeyaPridePotato, PringlesSourCreamAndOnion, KettleBrandSeaSaltAndVinegar, LayClassic } from './chips'; 2 | 3 | export default class ComplexClass { 4 | name: string; 5 | calbeeLightlySalted: CalbeeLightlySalted; 6 | koikeyaPridePotato: KoikeyaPridePotato; 7 | pringlesSourCreamAndOnion: PringlesSourCreamAndOnion; 8 | kettleBrandSeaSaltAndVinegar: KettleBrandSeaSaltAndVinegar; 9 | layClassic: LayClassic; 10 | chips: PotatoChip[]; 11 | 12 | constructor( 13 | name: string, 14 | calbeeLightlySalted: CalbeeLightlySalted, 15 | koikeyaPridePotato: KoikeyaPridePotato, 16 | pringlesSourCreamAndOnion: PringlesSourCreamAndOnion, 17 | kettleBrandSeaSaltAndVinegar: KettleBrandSeaSaltAndVinegar, 18 | layClassic: LayClassic, 19 | chips: PotatoChip[] 20 | ) { 21 | this.name = name; 22 | this.calbeeLightlySalted = calbeeLightlySalted; 23 | this.koikeyaPridePotato = koikeyaPridePotato; 24 | this.pringlesSourCreamAndOnion = pringlesSourCreamAndOnion; 25 | this.kettleBrandSeaSaltAndVinegar = kettleBrandSeaSaltAndVinegar; 26 | this.layClassic = layClassic; 27 | this.chips = chips; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /apps/test/src/tests/class/__snapshots__/class.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Class Tests ArgObjClass matches snapshot 1`] = `"{"name":"test string data","age":10,"obj_key":{"obj_name":"test string data","obj_val":10},"obj_key2":{"obj_name":"test string data","obj_val":10}}"`; 4 | 5 | exports[`Class Tests ArgObjClass2 matches snapshot 1`] = `"{"name":"test string data","age":10,"obj_key":{"obj_name":"test string data","obj_val":10},"obj_key2":{"obj_name":"test string data","obj_val":10}}"`; 6 | 7 | exports[`Class Tests ConstructorSignature matches snapshot 1`] = ` 8 | "class ref_fde1c265eff56bba551d380c5ad4c0ad3670f2b5509a2ff5fb00a368f9444abc { 9 | name; 10 | constructor(name) { 11 | this.name = name; 12 | } 13 | }" 14 | `; 15 | 16 | exports[`Class Tests ConstructorSignatureInterface matches snapshot 1`] = ` 17 | "class ref_fde1c265eff56bba551d380c5ad4c0ad3670f2b5509a2ff5fb00a368f9444abc { 18 | name; 19 | constructor(name) { 20 | this.name = name; 21 | } 22 | }" 23 | `; 24 | 25 | exports[`Class Tests InnerConstructorSignature matches snapshot 1`] = ` 26 | "class ref_fde1c265eff56bba551d380c5ad4c0ad3670f2b5509a2ff5fb00a368f9444abc { 27 | name; 28 | constructor(name) { 29 | this.name = name; 30 | } 31 | }" 32 | `; 33 | -------------------------------------------------------------------------------- /apps/test/src/tests/nestes_type/__snapshots__/nested_type.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Nested Type Tests NestedInterface matches snapshot 1`] = `"{"a":10,"b":"test string data","c":{"d":false,"e":{"f":10,"g":"test string data","h":{"i":10,"j":{"k":false,"l":[]}}},"m":{"n":[],"o":"test string data"}},"p":{"q":{"r":10},"s":{"t":false,"u":{"v":10,"w":"test string data"}}},"x":[],"literalType":"option1","mixedType":{"a":10,"b":"test string data"},"conditionalType":"active","extended":{"id":10,"info":{"description":"test string data","tags":[],"settings":{"mode":"auto","level":1,"extras":{"feature":false,"nestedRef":{"name":"NestedRefType","deep":{"name":"deeptype"}}}}}}}"`; 4 | 5 | exports[`Nested Type Tests NestedPropClass matches snapshot 1`] = `"{"a":10,"b":"test string data","k":false}"`; 6 | 7 | exports[`Nested Type Tests NestedType matches snapshot 1`] = `"{"a":10,"b":"test string data","c":{"d":false,"e":{"f":10,"g":"test string data","h":{"i":10,"j":{"k":false,"l":[]}}},"m":{"n":[],"o":"test string data"}},"p":{"q":{"r":10},"s":{"t":false,"u":{"v":10,"w":"test string data"}}},"x":[],"literalType":"option1","mixedType":{"a":10,"b":"test string data"},"conditionalType":"active","extended":{"id":10,"info":{"description":"test string data","tags":[],"settings":{"mode":"auto","level":1,"extras":{"feature":false,"nestedRef":{"name":"NestedRefType","deep":{"name":"deeptype"}}}}}}}"`; 8 | -------------------------------------------------------------------------------- /apps/test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test", 3 | "version": "1.0.0", 4 | "description": "", 5 | "type": "module", 6 | "main": "index.js", 7 | "scripts": { 8 | "boostest": "boostest", 9 | "boostest:init": "boostest init", 10 | "boostest:help": "boostest --help", 11 | "boostest:version": "boostest --version", 12 | "boostest:cli:nofile": "boostest hoeghoge -t hogege", 13 | "boostest:cli:failed": "boostest hoeghoge hogege", 14 | "boostest:cli:tsconfig": "boostest -t tsconfig.json", 15 | "boostest:cli": "boostest src/**/*.spec.ts -t tsconfig.json", 16 | "boostest:direct": "boostest src/direct_path/direct_path.ts", 17 | "boostest:direct:tsx": "boostest src/**/*.tsx", 18 | "test": "jest --config ./jest.config.js", 19 | "snapshot": "jest --config ./jest.config.js --updateSnapshot", 20 | "build": "rolldown -c" 21 | }, 22 | "keywords": [], 23 | "author": "", 24 | "dependencies": { 25 | "@anatine/zod-openapi": "^2.2.6", 26 | "@boostest/cli": "workspace:*", 27 | "@sendgrid/mail": "^8.1.3", 28 | "@types/express": "^4.17.21", 29 | "axios": "^1.7.2", 30 | "express": "^4.19.2", 31 | "jest": "^29.7.0", 32 | "ts-node": "^10.9.2", 33 | "typescript": "^5.5.3", 34 | "zod": "^3.24.1" 35 | }, 36 | "devDependencies": { 37 | "@jest/globals": "^29.7.0", 38 | "@types/jest": "^29.5.12", 39 | "rolldown": "nightly", 40 | "ts-jest": "^29.1.5" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /apps/test/src/tests/class/class.spec.ts: -------------------------------------------------------------------------------- 1 | import { runSnapshotTest } from "../utils"; 2 | import { ArgObjClass } from "../../types/pattern/arg_obj_class"; 3 | import { ArgObjClass2 } from "../../types/pattern/arg_obj_class2"; 4 | import { 5 | ConstructorSignature, 6 | InnerConstructorSignature, 7 | ConstructorSignatureInterface, 8 | } from "../../types/ts_types/constructor_signature"; 9 | import { boostestArgObjClass } from "./boostest_output/boostestArgObjClass"; 10 | import { boostestArgObjClass2 } from "./boostest_output/boostestArgObjClass2"; 11 | import { boostestConstructorSignature } from "./boostest_output/boostestConstructorSignature"; 12 | import { boostestInnerConstructorSignature } from "./boostest_output/boostestInnerConstructorSignature"; 13 | import { boostestConstructorSignatureInterface } from "./boostest_output/boostestConstructorSignatureInterface"; 14 | 15 | describe("Class Tests", () => { 16 | runSnapshotTest("ArgObjClass", boostestArgObjClass()); 17 | runSnapshotTest("ArgObjClass2", boostestArgObjClass2()); 18 | 19 | runSnapshotTest( 20 | "ConstructorSignature", 21 | boostestConstructorSignature(), 22 | ); 23 | runSnapshotTest( 24 | "InnerConstructorSignature", 25 | boostestInnerConstructorSignature(), 26 | ); 27 | runSnapshotTest( 28 | "ConstructorSignatureInterface", 29 | boostestConstructorSignatureInterface(), 30 | ); 31 | }); 32 | -------------------------------------------------------------------------------- /apps/test/src/tests/_invest/__snapshots__/invest.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Invest Tests Invest matches snapshot 1`] = `"{"stringLiteral":"test string data","numberLiteral":10,"bigintLiteral":"9007199254740991n","booleanLiteral":false,"nullLiteral":null,"undefinedId":"undefined","anyLiteral":"any","unknownLiteral":"undefined","objectLiteral":{},"voidLiteral":null,"functionLiteral":"() => { }","arrayLiteral":[],"referenceLiteral":{"name":"test string data","ver":10,"age":10},"unionType":"test string data","conditionalType":false,"tsLiteralString":"string","tsLiteralNumber":20,"tsBigInt":"10000000000000n","tsLiteralBoolean":true,"tsNullLiteral":null,"tsObject":{},"tsArray":[],"symbolLiteral":"Symbol()","tsTuple":["test string data",10,"any",{"name":"test string data","ver":10,"age":10},{"name":"test string data","ver":10}],"tsNamedTuple":["test string data",10,{"name":"test string data","ver":10,"age":10},{"name":"test string data","ver":10}],"intersectionType":{"name":"test string data","ver":10,"age":10},"keyof":"name","indexAccessor":"test string data","constructorType":"class ref_876fd03c9f43781a5f603af02cb0fcd8b9abb9384aa60b4674d20fe6b0e6c465 {\\n name;\\n ver;\\n constructor(name, ver) {\\n this.name = name;\\n this.ver = ver;\\n }\\n}","classType":"class ref_876fd03c9f43781a5f603af02cb0fcd8b9abb9384aa60b4674d20fe6b0e6c465 {\\n name;\\n ver;\\n constructor(name, ver) {\\n this.name = name;\\n this.ver = ver;\\n }\\n}"}"`; 4 | -------------------------------------------------------------------------------- /apps/test/src/tests/outer_packages/outer_packages.spec.ts: -------------------------------------------------------------------------------- 1 | import { runSnapshotTest } from "../utils"; 2 | 3 | import { FormDataVisitorHelpers, SerializerVisitor } from "axios"; 4 | import type { 5 | Request, 6 | Response, 7 | RequestHandler, 8 | RequestParamHandler, 9 | } from "express"; 10 | import { ClientResponse } from "@sendgrid/mail"; 11 | import { boostestRequest } from "./boostest_output/boostestRequest"; 12 | // import { boostestResponse } from "./boostest_output/boostestResponse"; 13 | // import { boostestHandler } from "./boostest_output/boostestHandler"; 14 | // import { boostestParamHandler } from "./boostest_output/boostestParamHandler"; 15 | // import { boostestResponseType } from "./boostest_output/boostestResponseType"; 16 | // import { boostestFormDataVisitorHelpers } from "./boostest_output/boostestFormDataVisitorHelpers"; 17 | // 18 | describe("Outer package Tests", () => { 19 | // runSnapshotTest( 20 | // "FormDataVisitorHelpers", 21 | // boostestFormDataVisitorHelpers(), 22 | // ); 23 | // runSnapshotTest( 24 | // "SerializerVisitor", 25 | // boostestResponseType(), 26 | // ); 27 | 28 | runSnapshotTest("Request", boostestRequest()); 29 | // runSnapshotTest("Response", boostestResponse()); 30 | // runSnapshotTest("RequestHandler", boostestHandler()); 31 | // runSnapshotTest( 32 | // "RequestParamHandler", 33 | // boostestParamHandler(), 34 | // ); 35 | 36 | // runSnapshotTest("ClientResponse", boostestSendGrid()); 37 | }); 38 | -------------------------------------------------------------------------------- /apps/test/src/tests/union/union.spec.ts: -------------------------------------------------------------------------------- 1 | import { runSnapshotTest } from "../utils"; 2 | 3 | /** 4 | * 5 | * 6 | * Union type 7 | * 8 | * 9 | */ 10 | import { 11 | TSAliasMixUnionObjType, 12 | TSAliasMixUnionType, 13 | TSAliasStringUnionType, 14 | TSInterfaceMixUnionType, 15 | TSInterfaceStringUnionType, 16 | } from "../../types/ts_types/union"; 17 | import { boostestTSAliasMixUnionType } from "./boostest_output/boostestTSAliasMixUnionType"; 18 | import { boostestTSAliasStringUnionType } from "./boostest_output/boostestTSAliasStringUnionType"; 19 | import { boostestTSInterfaceMixUnionType } from "./boostest_output/boostestTSInterfaceMixUnionType"; 20 | import { boostestTSInterfaceStringUnionType } from "./boostest_output/boostestTSInterfaceStringUnionType"; 21 | import { boostestTSAliasMixUnionObjType } from "./boostest_output/boostestTSAliasMixUnionObjType"; 22 | 23 | describe("Union Tests", () => { 24 | runSnapshotTest( 25 | "TSAliasMixUnionType", 26 | boostestTSAliasMixUnionType(), 27 | ); 28 | 29 | runSnapshotTest( 30 | "TSAliasStringUnionType", 31 | boostestTSAliasStringUnionType(), 32 | ); 33 | 34 | runSnapshotTest( 35 | "TSInterfaceMixUnionType", 36 | boostestTSInterfaceMixUnionType({ type: "A" }), 37 | ); 38 | 39 | runSnapshotTest( 40 | "TSInterfaceStringUnionType", 41 | boostestTSInterfaceStringUnionType({ 42 | type: "A", 43 | }), 44 | ); 45 | 46 | runSnapshotTest( 47 | "TSAliasMixUnionObjType", 48 | boostestTSAliasMixUnionObjType({ 49 | ref_type: "A", 50 | type: "A", 51 | }), 52 | ); 53 | }); 54 | -------------------------------------------------------------------------------- /crates/boostest/src/boostest_utils/napi.rs: -------------------------------------------------------------------------------- 1 | use std::{collections::HashMap, path::PathBuf}; 2 | 3 | #[napi()] 4 | #[derive(Debug, PartialEq)] 5 | pub enum TargetType { 6 | Class, 7 | TSInterface, 8 | TSTypeAlias, 9 | Variable, 10 | Function, 11 | TSModule, 12 | ImportAll, 13 | } 14 | 15 | #[napi(object)] 16 | #[derive(Debug)] 17 | pub struct OutputCode { 18 | pub code: String, 19 | pub target_type: TargetType, 20 | pub path: String, 21 | } 22 | 23 | #[napi(object)] 24 | #[derive(Debug, Clone)] 25 | pub struct DefaultValueOption { 26 | pub number: f64, 27 | pub string: String, 28 | pub bigint: String, 29 | pub any: String, 30 | 31 | // unused props 32 | pub undefined: String, 33 | pub boolean: bool, 34 | pub null: String, 35 | } 36 | 37 | impl Default for DefaultValueOption { 38 | fn default() -> Self { 39 | Self::new() 40 | } 41 | } 42 | 43 | impl DefaultValueOption { 44 | pub fn new() -> Self { 45 | Self { 46 | boolean: true, 47 | number: 10.0, 48 | string: "test string data".to_string(), 49 | undefined: "undefined".to_string(), 50 | null: "null".to_string(), 51 | bigint: "9007199254740991n".to_string(), 52 | any: "any".to_string(), 53 | } 54 | } 55 | } 56 | 57 | #[napi(object)] 58 | #[derive(Debug, Clone)] 59 | pub struct OutputOption { 60 | pub single: bool, 61 | pub project_root_path: Option, 62 | pub default_value_option: DefaultValueOption, 63 | } 64 | 65 | #[napi(object)] 66 | #[derive(Debug)] 67 | pub struct ResolvedResult { 68 | pub output_code: Option>, 69 | pub output_option: OutputOption, 70 | } 71 | -------------------------------------------------------------------------------- /crates/boostest/src/boostest_utils/module_resolver.rs: -------------------------------------------------------------------------------- 1 | use anyhow::{anyhow, Result}; 2 | use oxc_resolver::{Resolution, ResolveOptions, Resolver, TsconfigOptions, TsconfigReferences}; 3 | use std::path::{Path, PathBuf}; 4 | 5 | pub fn resolve_specifier( 6 | path: &Option, 7 | specifier: &str, 8 | ts_config_path: &Option, 9 | ) -> Result { 10 | if let Some(path) = path { 11 | let tsconfig = ts_config_path 12 | .as_ref() 13 | .map(|ts_config_path| TsconfigOptions { 14 | config_file: PathBuf::from(ts_config_path), 15 | references: TsconfigReferences::Auto, 16 | }); 17 | 18 | let next_file_stem = path.file_stem().ok_or(anyhow!("next file is not found"))?; 19 | let next_file_name = next_file_stem.to_string_lossy(); 20 | let fallback_file_name = match next_file_name.ends_with(".d") { 21 | true => format!("{}{}", next_file_name, ".ts"), 22 | false => format!("{}{}", next_file_name, ".d.ts"), 23 | }; 24 | 25 | let options = ResolveOptions { 26 | extensions: vec![".d.ts".into(), ".ts".into(), ".tsx".into(), ".js".into()], 27 | main_files: vec!["index".into(), fallback_file_name], 28 | main_fields: vec!["types".into()], 29 | condition_names: vec!["types".into()], 30 | builtin_modules: true, 31 | 32 | tsconfig, 33 | ..ResolveOptions::default() 34 | }; 35 | 36 | match Resolver::new(options).resolve(path, specifier) { 37 | Err(error) => Err(anyhow!("module resolution error: {:?}", error)), 38 | Ok(resolution) => Ok(resolution), 39 | } 40 | } else { 41 | Err(anyhow!("module resolution error")) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /crates/boostest/src/boostest_utils/id_name.rs: -------------------------------------------------------------------------------- 1 | use oxc::span::Span; 2 | use sha2::{Digest, Sha256}; 3 | /* 4 | 5 | type Hoge ={name: string, ref: Ref} 6 | type Ref = {name: RefAnother} 7 | 8 | // parent_key: none 9 | // target_name: Hoge 10 | // key_name: ref 11 | // id: Ref 12 | -> Hoge_ref_Ref 13 | 14 | // parent_key: Hoge_ref 15 | // target_name: Ref 16 | // key_name: name 17 | // id: RefAnother 18 | -> Hoge_ref_Ref_name_RefAnother 19 | */ 20 | pub fn get_parent_key_name( 21 | parent_key_name: Option, 22 | key_name: Option, 23 | target_name: String, 24 | ) -> String { 25 | // Hoge 26 | // Ref 27 | let mut ref_name = target_name; 28 | 29 | // Hoge (unexist parent_key_name) 30 | // Hoge_ref_Ref 31 | if let Some(k_name) = parent_key_name { 32 | ref_name = format!("{}_{}", k_name, ref_name); 33 | } 34 | 35 | // Hoge_ref 36 | // Hoge_ref_Ref_name 37 | if let Some(k_name) = key_name { 38 | ref_name = format!("{}_{}", ref_name, k_name); 39 | } 40 | 41 | ref_name 42 | } 43 | 44 | pub fn get_decl_name(parent_key_name: Option, function_name: String, id: String) -> String { 45 | let mut name = id; 46 | 47 | if let Some(k_name) = parent_key_name { 48 | name = format!("{}_{}", k_name, name); 49 | } else { 50 | name = format!("{}_{}", function_name, name); 51 | } 52 | 53 | name 54 | } 55 | 56 | pub fn get_id_with_hash(file_path: String, span: Span) -> String { 57 | // ハッシュ計算 58 | let mut hasher = Sha256::new(); 59 | hasher.update(file_path); 60 | hasher.update(span.start.to_le_bytes()); // u32をバイト列に変換して追加 61 | hasher.update(span.end.to_le_bytes()); 62 | let hash_result = hasher.finalize(); 63 | 64 | // ハッシュ結果を16進文字列に変換 65 | let hash_hex = format!("{:x}", hash_result); 66 | 67 | // プレフィックスを付与して返す 68 | format!("{}_{}", "ref", hash_hex) 69 | } 70 | -------------------------------------------------------------------------------- /packages/boostest/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@boostest/cli", 3 | "version": "0.8.0", 4 | "description": "Boostest is a tool that generates test code from type definitions.", 5 | "main": "index.js", 6 | "types": "index.d.ts", 7 | "publishConfig": { 8 | "registry": "https://registry.npmjs.org/", 9 | "access": "public" 10 | }, 11 | "bin": { 12 | "boostest": "./dist/cli.js" 13 | }, 14 | "napi": { 15 | "name": "boostest", 16 | "triples": { 17 | "additional": [ 18 | "darwin-arm64" 19 | ], 20 | "package": { 21 | "name": "boostest" 22 | } 23 | } 24 | }, 25 | "devDependencies": { 26 | "@napi-rs/cli": "^2.18.4", 27 | "ava": "^6.0.1" 28 | }, 29 | "ava": { 30 | "timeout": "3m" 31 | }, 32 | "engines": { 33 | "node": ">= 10" 34 | }, 35 | "scripts": { 36 | "artifacts": "napi artifacts", 37 | "build": "napi build --platform --release --js-package-name @boostest/boostest", 38 | "build:debug": "napi build --platform", 39 | "test": "ava", 40 | "universal": "napi universal", 41 | "version": "napi version", 42 | "type-check": "tsc --noEmit", 43 | "bin:build": "tsc" 44 | }, 45 | "dependencies": { 46 | "@types/node": "^20.14.8", 47 | "@types/yargs": "^17.0.32", 48 | "build": "^0.1.4", 49 | "typescript": "^5.4.5", 50 | "yargs": "^17.7.2" 51 | }, 52 | "optionalDependencies": { 53 | "@boostest/boostest-win32-x64-msvc": "0.8.0", 54 | "@boostest/boostest-darwin-x64": "0.8.0", 55 | "@boostest/boostest-linux-x64-gnu": "0.8.0", 56 | "@boostest/boostest-darwin-arm64": "0.8.0" 57 | }, 58 | "author": "MasatoDev", 59 | "license": "MIT", 60 | "keywords": [ 61 | "test", 62 | "test date", 63 | "mock", 64 | "code generator", 65 | "test framework", 66 | "test code", 67 | "command", 68 | "tool", 69 | "generator", 70 | "debug" 71 | ] 72 | } 73 | -------------------------------------------------------------------------------- /apps/test/src/types/nested_prop_class.ts: -------------------------------------------------------------------------------- 1 | import ComplexInterfaceChips from "./deepfiles/lib/comp_interface"; 2 | 3 | type NestedRefType = { 4 | name: "NestedRefType"; 5 | }; 6 | 7 | class ClassObj { 8 | anoChips: ComplexInterfaceChips; 9 | 10 | constructor(huga: { anoChips: ComplexInterfaceChips }) { 11 | this.anoChips = huga.anoChips; 12 | } 13 | } 14 | 15 | export default ClassObj; 16 | 17 | export class NestedPropClass { 18 | a: number; 19 | b: string; 20 | k: boolean; 21 | 22 | constructor(huga: { 23 | a: number; 24 | b: string; 25 | c: { 26 | d: boolean; 27 | e: { 28 | f: number; 29 | g: string; 30 | h: { 31 | i: number; 32 | j: { 33 | k: boolean; 34 | l: string[]; 35 | }; 36 | }; 37 | }; 38 | m: { 39 | n: number[]; 40 | o: string; 41 | }; 42 | }; 43 | p: { 44 | q: { 45 | r: number; 46 | }; 47 | s: { 48 | t: boolean; 49 | u: { 50 | v: number; 51 | w: string; 52 | }; 53 | }; 54 | }; 55 | x: (number | string)[]; 56 | // y: Record; 57 | 58 | // Addition of type literals 59 | literalType: "option1" | "option2" | "option3"; 60 | mixedType: { a: number } & { b: string }; // Intersection type 61 | conditionalType: 62 | | "active" 63 | | "inactive" 64 | | { status: "pending"; detail: string }; 65 | 66 | extended: { 67 | id: number; 68 | info: { 69 | description: string; 70 | tags: ("tag1" | "tag2" | "tag3")[]; // Array of literal types 71 | settings: { 72 | mode: "auto" | "manual"; 73 | level: 1 | 2 | 3; // Literal type (specific numbers) 74 | extras?: { 75 | feature: true | false; 76 | nestedRef: NestedRefType; 77 | }; 78 | }; 79 | }; 80 | }; 81 | }) { 82 | this.a = huga.a; 83 | this.b = huga.b; 84 | this.k = huga.c.e.h.j.k; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /apps/example/src/example.ts: -------------------------------------------------------------------------------- 1 | import AnoExportDefaultInterface from './types/export_default_interface'; 2 | import AnoExportDefaultClass from './types/export_default_class'; 3 | import ExportDefaultClassWithDecl from './types/export_default_class_with_decl'; 4 | import ExportDefaultClass from './types/export_default_class'; 5 | import { ExportNamedDecl } from './types/export_named_decl'; 6 | import ExportDefaultNamedDecl from './types/export_default_named_decl'; 7 | import { AnoExportNamedDeclInterface } from './types/export_named_decl_interface'; 8 | import { AnoExportNamedDeclClass } from './types/export_named_decl_class'; 9 | import Mix, { MixCompTSAlias } from './types/mix'; 10 | import ClassObj from './types/class_obj'; 11 | 12 | const anoExportAnoDefaultInterface = boostestAnoExportDefaultInterface({ 13 | name: 'overridden', 14 | }); 15 | // const AnoexportDefaultClass = boostestAnoExportDefaultClass(AnoExportDefaultClass); 16 | // const exportDefaultClass = boostestExportDefaultClass(ExportDefaultClass); 17 | // const exportDefaultClassWithDecl = boostestExportDefaultClassWithDecl(ExportDefaultClassWithDecl); 18 | // const exportNamedDecl = boostestExportNamedDecl(); 19 | // const exportDefaultNamedDecl = boostestExportDefaultNamedDecl(); 20 | // const exportNamedDeclInterface = boostestExportNamedDeclInterface(); 21 | // const exportNamedDeclClass = boostestAnoExportNamedDeclClass(AnoExportNamedDeclClass); 22 | // const mix = boostestAnoMixInterface({name:'mix'}); 23 | // const mixCompTSAlias = boostestMixCompTSAlias({name:'mixCompTSAlias'}); 24 | // const classsObj = boostestClassObj(ClassObj); 25 | 26 | // const values = [ 27 | // anoExportAnoDefaultInterface, 28 | // AnoexportDefaultClass, 29 | // exportDefaultClass, 30 | // exportDefaultClassWithDecl, 31 | // exportNamedDecl, 32 | // exportDefaultNamedDecl, 33 | // exportNamedDeclInterface, 34 | // exportNamedDeclClass, 35 | // mix, 36 | // mixCompTSAlias, 37 | // ]; 38 | 39 | // for (const value of values) { 40 | // // valueがオブジェクトの場合はJSON.stringify()で文字列に変換 41 | // const output = typeof value === 'object' ? JSON.stringify(value, null, 2) : value; 42 | // console.log(`result: ${output}\n`); 43 | // } 44 | -------------------------------------------------------------------------------- /justfile: -------------------------------------------------------------------------------- 1 | set windows-shell := ["powershell"] 2 | set shell := ["bash", "-cu"] 3 | 4 | _default: 5 | just --list -u 6 | 7 | setup: 8 | pnpm install 9 | pnpm --filter test install 10 | pnpm --filter example install 11 | echo "✅ Setup complete!" 12 | 13 | debug_build: 14 | pnpm --filter @boostest/cli build:debug 15 | pnpm --filter @boostest/cli bin:build 16 | 17 | debug: 18 | just debug_build 19 | pnpm --filter test boostest 20 | 21 | snapshot: 22 | just debug_build 23 | pnpm --filter test boostest:direct 24 | pnpm --filter test boostest 25 | pnpm --filter test snapshot 26 | 27 | test: 28 | just debug_build 29 | pnpm --filter test boostest:direct 30 | pnpm --filter test boostest 31 | pnpm --filter test test 32 | 33 | init: 34 | just debug_build 35 | pnpm --filter test boostest:init 36 | 37 | cli: 38 | just debug_build 39 | pnpm --filter test boostest:version 40 | pnpm --filter test boostest:help 41 | pnpm --filter test boostest:cli:nofile 42 | pnpm --filter test boostest:cli:failed 43 | pnpm --filter test boostest:cli:tsconfig 44 | pnpm --filter test boostest:cli 45 | 46 | 47 | 48 | 49 | 50 | # FOR PRODUCTION 51 | build: 52 | pnpm --filter @boostest/cli build 53 | pnpm --filter @boostest/cli bin:build 54 | build_release: 55 | pnpm --filter @boostest/cli build --target x86_64-apple-darwin 56 | pnpm --filter @boostest/cli build --target aarch64-apple-darwin 57 | pnpm --filter @boostest/cli build --target x86_64-pc-windows-msvc 58 | pnpm --filter @boostest/cli build --target x86_64-unknown-linux-gnu 59 | 60 | pnpm --filter @boostest/cli build --target aarch64-unknown-linux-gnu 61 | pnpm --filter @boostest/cli build --target riscv64gc-unknown-linux-gnu 62 | pnpm --filter @boostest/cli bin:build 63 | 64 | pre_release_boostest: 65 | # cd packages/boostest 66 | npm version patch 67 | pnpm prepublishOnly 68 | # npm version minor 69 | # npm version preminor 70 | # npm version prerelease 71 | cl: 72 | pnpm --filter @boostest/cli bin:build 73 | pnpm --filter example start:boostest 74 | 75 | # failed now 76 | # pnpm --filter @boostest/cli build --target s390x-unknown-linux-gnu 77 | 78 | 79 | # # win 80 | # cargo install cargo-xwin 81 | # rustup target add x86_64-pc-windows-msvc 82 | 83 | # # mac 84 | # sudo apt update 85 | # sudo apt install snapd 86 | # sudo snap install zig --beta --classic 87 | # 88 | 89 | ## on MAC [x86] 90 | # https://github.com/messense/homebrew-macos-cross-toolchains 91 | # brew tap messense/macos-cross-toolchains 92 | # brew install x86_64-unknown-linux-gnu 93 | -------------------------------------------------------------------------------- /crates/boostest/src/boostest_utils/typescript_lib.rs: -------------------------------------------------------------------------------- 1 | use std::io::Read; 2 | use std::{fs, path::Path}; 3 | 4 | use oxc::allocator::{Allocator, Vec as AllocVec}; 5 | use oxc::ast::ast::Statement; 6 | use oxc::ast::VisitMut; 7 | use oxc::codegen::Codegen; 8 | use oxc::parser::Parser; 9 | use oxc::span::SourceType; 10 | 11 | pub fn get_typescript_lib_code(default_lib_file_path: &Path) -> String { 12 | let mut typescript_lib_files = Vec::new(); 13 | if let Some(parent_dir_path) = default_lib_file_path.parent() { 14 | if let Ok(lib_files) = fs::read_dir(parent_dir_path) { 15 | for entry in lib_files.into_iter().flatten() { 16 | let path = entry.path(); 17 | 18 | if path.is_file() { 19 | if let Some(file_name) = path.file_name() { 20 | let file_name_str = file_name.to_string_lossy(); 21 | if file_name_str.starts_with("lib.es5.d.ts") { 22 | typescript_lib_files.push(path); 23 | } 24 | } 25 | } 26 | } 27 | } 28 | } 29 | 30 | let mut combined_code = String::new(); 31 | for file_path in typescript_lib_files { 32 | if let Ok(mut file) = fs::File::open(&file_path) { 33 | let mut contents = String::new(); 34 | if file.read_to_string(&mut contents).is_ok() { 35 | combined_code.push_str(&contents); 36 | combined_code.push('\n'); // ファイル間に改行を追加 37 | } 38 | } 39 | } 40 | 41 | CleanupVisitor::new().cleanup(&combined_code) 42 | } 43 | 44 | struct CleanupVisitor {} 45 | 46 | impl CleanupVisitor { 47 | fn new() -> Self { 48 | Self {} 49 | } 50 | 51 | fn cleanup(&mut self, code: &str) -> String { 52 | let source_type = SourceType::ts(); 53 | let allocator = Allocator::default(); 54 | let source_text_parser = Parser::new(&allocator, code, source_type); 55 | let mut program = source_text_parser.parse().program; 56 | self.visit_program(&mut program); 57 | program.comments = AllocVec::new_in(&allocator); 58 | 59 | let code = Codegen::new().build(&program).code; 60 | code 61 | } 62 | } 63 | 64 | impl<'a> VisitMut<'a> for CleanupVisitor { 65 | fn visit_statements(&mut self, it: &mut AllocVec<'a, Statement<'a>>) { 66 | it.retain(|stmt| { 67 | let result: bool = match stmt { 68 | Statement::ImportDeclaration(_) => false, 69 | Statement::TSImportEqualsDeclaration(_) => false, 70 | _ => true, 71 | }; 72 | result 73 | }); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /crates/boostest/src/boostest_resolver/main_target_resolver.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use rayon::prelude::*; 3 | use std::sync::{Arc, Mutex}; 4 | 5 | use crate::boostest_utils::tsserver::TSServerCache; 6 | use crate::Setting; 7 | 8 | use super::target::{MainTarget, ResolvedDefinitions, Target}; 9 | use super::target_resolver::TargetResolver; 10 | 11 | pub fn main_targets_resolve( 12 | main_targets: &Vec>>, 13 | setting: Arc, 14 | tsserver_cache: Arc>, 15 | ) { 16 | main_targets.par_iter().for_each(|main_target| { 17 | let cloned_main_target = main_target.clone(); 18 | let cloned_tsserver_cache = tsserver_cache.clone(); 19 | let cloned_setting = setting.clone(); 20 | 21 | main_target_resolve(cloned_main_target, cloned_setting, cloned_tsserver_cache); 22 | }); 23 | } 24 | 25 | fn main_target_resolve( 26 | main_target: Arc>, 27 | setting: Arc, 28 | tsserver_cache: Arc>, 29 | ) { 30 | let main_target = main_target.lock().unwrap(); 31 | let cloned_resolved_definitions = main_target.resolved_definitions.clone(); 32 | let cloned_target = main_target.target.clone(); 33 | 34 | TargetResolver::new(cloned_target, cloned_resolved_definitions.clone()) 35 | .resolve(setting.clone(), tsserver_cache.clone()); 36 | 37 | main_target 38 | .target 39 | .lock() 40 | .unwrap() 41 | .ref_properties 42 | .par_iter() 43 | .for_each(|prop| { 44 | if let Err(e) = property_target_resolve( 45 | prop.clone(), 46 | cloned_resolved_definitions.clone(), 47 | setting.clone(), 48 | tsserver_cache.clone(), 49 | ) { 50 | println!("[Error] main_target_resolve: {}", e); 51 | } 52 | }); 53 | } 54 | 55 | fn property_target_resolve( 56 | target: Arc>, 57 | resolved_definitions: Arc>, 58 | setting: Arc, 59 | tsserver_cache: Arc>, 60 | ) -> Result<()> { 61 | TargetResolver::new(target.clone(), resolved_definitions.clone()) 62 | .resolve(setting.clone(), tsserver_cache.clone()); 63 | 64 | target 65 | .lock() 66 | .unwrap() 67 | .ref_properties 68 | .par_iter() 69 | .for_each(|prop| { 70 | if let Err(e) = property_target_resolve( 71 | prop.clone(), 72 | resolved_definitions.clone(), 73 | setting.clone(), 74 | tsserver_cache.clone(), 75 | ) { 76 | println!("[Error] property_target_resolve: {}", e); 77 | } 78 | }); 79 | 80 | Ok(()) 81 | } 82 | -------------------------------------------------------------------------------- /apps/test/src/types/ts_types/nested.ts: -------------------------------------------------------------------------------- 1 | type DeepType = { 2 | name: "deeptype"; 3 | }; 4 | 5 | type NestedRefType = { 6 | name: "NestedRefType"; 7 | deep: DeepType; 8 | }; 9 | 10 | export type NestedType = { 11 | a: number; 12 | b: string; 13 | c: { 14 | d: boolean; 15 | e: { 16 | f: number; 17 | g: string; 18 | h: { 19 | i: number; 20 | j: { 21 | k: boolean; 22 | l: string[]; 23 | }; 24 | }; 25 | }; 26 | m: { 27 | n: number[]; 28 | o: string; 29 | }; 30 | }; 31 | p: { 32 | q: { 33 | r: number; 34 | }; 35 | s: { 36 | t: boolean; 37 | u: { 38 | v: number; 39 | w: string; 40 | }; 41 | }; 42 | }; 43 | x: (number | string)[]; 44 | // y: Record; 45 | 46 | // Addition of type literals 47 | literalType: "option1" | "option2" | "option3"; 48 | mixedType: { a: number } & { b: string }; // Intersection type 49 | conditionalType: 50 | | "active" 51 | | "inactive" 52 | | { status: "pending"; detail: string }; 53 | 54 | extended: { 55 | id: number; 56 | info: { 57 | description: string; 58 | tags: ("tag1" | "tag2" | "tag3")[]; // Array of literal types 59 | settings: { 60 | mode: "auto" | "manual"; 61 | level: 1 | 2 | 3; // Literal type (specific numbers) 62 | extras?: { 63 | feature: true | false; 64 | nestedRef: NestedRefType; 65 | }; 66 | }; 67 | }; 68 | }; 69 | }; 70 | 71 | export type NestedInterface = { 72 | a: number; 73 | b: string; 74 | c: { 75 | d: boolean; 76 | e: { 77 | f: number; 78 | g: string; 79 | h: { 80 | i: number; 81 | j: { 82 | k: boolean; 83 | l: string[]; 84 | }; 85 | }; 86 | }; 87 | m: { 88 | n: number[]; 89 | o: string; 90 | }; 91 | }; 92 | p: { 93 | q: { 94 | r: number; 95 | }; 96 | s: { 97 | t: boolean; 98 | u: { 99 | v: number; 100 | w: string; 101 | }; 102 | }; 103 | }; 104 | x: (number | string)[]; 105 | // y: Record; 106 | 107 | // Addition of type literals 108 | literalType: "option1" | "option2" | "option3"; 109 | mixedType: { a: number } & { b: string }; // Intersection type 110 | conditionalType: 111 | | "active" 112 | | "inactive" 113 | | { status: "pending"; detail: string }; 114 | 115 | extended: { 116 | id: number; 117 | info: { 118 | description: string; 119 | tags: ("tag1" | "tag2" | "tag3")[]; // Array of literal types 120 | settings: { 121 | mode: "auto" | "manual"; 122 | level: 1 | 2 | 3; // Literal type (specific numbers) 123 | extras?: { 124 | feature: true | false; 125 | nestedRef: NestedRefType; 126 | }; 127 | }; 128 | }; 129 | }; 130 | }; 131 | -------------------------------------------------------------------------------- /crates/boostest/src/boostest_generator/fallback_func_builder.rs: -------------------------------------------------------------------------------- 1 | use oxc::{ 2 | allocator::Allocator, 3 | ast::{ 4 | ast::{Declaration, Program, Statement}, 5 | AstBuilder, VisitMut, 6 | }, 7 | codegen::Codegen, 8 | parser::Parser, 9 | span::{SourceType, Span}, 10 | }; 11 | 12 | use oxc::allocator; 13 | 14 | const SPAN: Span = Span::new(0, 0); 15 | 16 | pub struct FallbackMockData { 17 | pub mock_func_name: String, 18 | pub key_name: Option, 19 | } 20 | 21 | pub struct FallbackFuncBuilder<'a> { 22 | mock_data: FallbackMockData, 23 | ast_builder: AstBuilder<'a>, 24 | } 25 | 26 | impl<'a> FallbackFuncBuilder<'a> { 27 | pub fn new(allocator: &'a Allocator, mock_func_name: String, key_name: Option) -> Self { 28 | let ast_builder = AstBuilder::new(allocator); 29 | 30 | let mock_data = FallbackMockData { 31 | mock_func_name, 32 | key_name, 33 | }; 34 | 35 | Self { 36 | ast_builder, 37 | mock_data, 38 | } 39 | } 40 | 41 | pub fn generate_code(&mut self, source_type: SourceType) -> String { 42 | let bytes = include_bytes!("./template/default.ts"); 43 | let source_code = std::str::from_utf8(bytes).unwrap(); 44 | let parser = Parser::new(self.ast_builder.allocator, source_code, source_type); 45 | let program = &mut parser.parse().program; 46 | 47 | self.visit_program(program); 48 | 49 | Codegen::new().build(program).code 50 | } 51 | } 52 | 53 | impl<'a> VisitMut<'a> for FallbackFuncBuilder<'a> { 54 | fn visit_program(&mut self, program: &mut Program<'a>) { 55 | self.visit_statements(&mut program.body); 56 | } 57 | 58 | fn visit_statements(&mut self, stmts: &mut allocator::Vec<'_, Statement<'a>>) { 59 | for stmt in stmts.iter_mut() { 60 | match stmt { 61 | Statement::ExportNamedDeclaration(export) => { 62 | if let Some(decl) = &mut export.declaration { 63 | self.visit_declaration(decl); 64 | } 65 | } 66 | _ => {} 67 | } 68 | } 69 | } 70 | 71 | fn visit_declaration(&mut self, decl: &mut Declaration<'a>) { 72 | match decl { 73 | Declaration::FunctionDeclaration(func) => { 74 | if let Some(id) = &mut func.id { 75 | if id.name.to_string() == "boostestDefaultTemplate" { 76 | let new_name = match &self.mock_data.key_name { 77 | Some(key_name) => { 78 | format!("{}_{}", key_name, self.mock_data.mock_func_name) 79 | } 80 | None => self.mock_data.mock_func_name.clone(), 81 | }; 82 | 83 | let name = self.ast_builder.atom(&new_name); 84 | let new_binding = self.ast_builder.binding_identifier(SPAN, name); 85 | 86 | let _ = std::mem::replace(id, new_binding); 87 | } 88 | } 89 | } 90 | _ => {} 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /apps/test/src/tests/not_ref_types/__snapshots__/notRefTypes.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`not ref types(direct) Tests Direct Promise matches snapshot 1`] = `"{"name":"test string data","age":10}"`; 4 | 5 | exports[`not ref types(direct) Tests Direct any matches snapshot 1`] = `""any""`; 6 | 7 | exports[`not ref types(direct) Tests Direct array matches snapshot 1`] = `"[]"`; 8 | 9 | exports[`not ref types(direct) Tests Direct bigint matches snapshot 1`] = `""9007199254740991n""`; 10 | 11 | exports[`not ref types(direct) Tests Direct boolean matches snapshot 1`] = `"false"`; 12 | 13 | exports[`not ref types(direct) Tests Direct class matches snapshot 1`] = ` 14 | "class ref_876fd03c9f43781a5f603af02cb0fcd8b9abb9384aa60b4674d20fe6b0e6c465 { 15 | name; 16 | ver; 17 | constructor(name, ver) { 18 | this.name = name; 19 | this.ver = ver; 20 | } 21 | }" 22 | `; 23 | 24 | exports[`not ref types(direct) Tests Direct conditional matches snapshot 1`] = `"false"`; 25 | 26 | exports[`not ref types(direct) Tests Direct constructor matches snapshot 1`] = ` 27 | "class ref_876fd03c9f43781a5f603af02cb0fcd8b9abb9384aa60b4674d20fe6b0e6c465 { 28 | name; 29 | ver; 30 | constructor(name, ver) { 31 | this.name = name; 32 | this.ver = ver; 33 | } 34 | }" 35 | `; 36 | 37 | exports[`not ref types(direct) Tests Direct function matches snapshot 1`] = ` 38 | "(arg) => { 39 | return { 40 | name: "test string data", 41 | ver: 10, 42 | age: 10 43 | }; 44 | }" 45 | `; 46 | 47 | exports[`not ref types(direct) Tests Direct index accessor matches snapshot 1`] = `""test string data""`; 48 | 49 | exports[`not ref types(direct) Tests Direct intersection matches snapshot 1`] = `"{"name":"test string data","ver":10,"age":10}"`; 50 | 51 | exports[`not ref types(direct) Tests Direct keyof matches snapshot 1`] = `""name""`; 52 | 53 | exports[`not ref types(direct) Tests Direct named tuple matches snapshot 1`] = `"["test string data",10,{"name":"test string data","ver":10,"age":10},{"name":"test string data","ver":10,"age":10}]"`; 54 | 55 | exports[`not ref types(direct) Tests Direct null matches snapshot 1`] = `"null"`; 56 | 57 | exports[`not ref types(direct) Tests Direct number matches snapshot 1`] = `"10"`; 58 | 59 | exports[`not ref types(direct) Tests Direct object matches snapshot 1`] = `"{}"`; 60 | 61 | exports[`not ref types(direct) Tests Direct reference matches snapshot 1`] = `"{"name":"test string data","ver":10,"age":10}"`; 62 | 63 | exports[`not ref types(direct) Tests Direct string matches snapshot 1`] = `""test string data""`; 64 | 65 | exports[`not ref types(direct) Tests Direct symbol matches snapshot 1`] = `"Symbol()"`; 66 | 67 | exports[`not ref types(direct) Tests Direct tuple matches snapshot 1`] = `"["test string data",10,"any",{"name":"test string data","ver":10,"age":10},{"name":"test string data","ver":10,"age":10}]"`; 68 | 69 | exports[`not ref types(direct) Tests Direct undefined matches snapshot 1`] = `""undefined""`; 70 | 71 | exports[`not ref types(direct) Tests Direct union matches snapshot 1`] = `""test string data""`; 72 | 73 | exports[`not ref types(direct) Tests Direct unknown matches snapshot 1`] = `""undefined""`; 74 | 75 | exports[`not ref types(direct) Tests Direct void matches snapshot 1`] = `"null"`; 76 | -------------------------------------------------------------------------------- /apps/test/src/tests/utils.ts: -------------------------------------------------------------------------------- 1 | export const runSnapshotTest = (name: string, value: any) => { 2 | if (typeof value === "function" || typeof value === "symbol") { 3 | test(`${name} matches snapshot`, () => { 4 | expect(value.toString()).toMatchSnapshot(); 5 | }); 6 | return; 7 | } 8 | 9 | test(`${name} matches snapshot`, async () => { 10 | const str = await stringifySafely(value); 11 | expect(str).toMatchSnapshot(); 12 | }); 13 | }; 14 | 15 | export const failedTest = (name: string) => { 16 | test(`${name} matches snapshot`, () => { 17 | expect(true).toBe(false); 18 | }); 19 | }; 20 | 21 | // Promiseを再帰的に解決して返すヘルパー関数 22 | async function resolvePromises(obj: any, seen = new WeakMap()) { 23 | if (obj && typeof obj === "object") { 24 | if (seen.has(obj)) { 25 | return obj; // 循環参照の場合そのまま返す(または[Circular]扱い) 26 | } 27 | seen.set(obj, obj); 28 | 29 | // Promise の場合は解決する 30 | if (typeof obj.then === "function" && typeof obj.catch === "function") { 31 | obj = await obj; 32 | } 33 | 34 | // 解決後もオブジェクトであれば、再帰的にプロパティを処理 35 | if (obj && typeof obj === "object") { 36 | for (const [k, v] of Object.entries(obj)) { 37 | obj[k] = await resolvePromises(v, seen); 38 | } 39 | } 40 | } 41 | return obj; 42 | } 43 | 44 | async function stringifySafely(obj) { 45 | // まずPromiseを全て解決する 46 | const resolved = await resolvePromises(obj); 47 | 48 | const seen = new WeakSet(); 49 | 50 | function replacer(key, value) { 51 | // 循環参照のチェック 52 | if (typeof value === "object" && value !== null) { 53 | if (seen.has(value)) { 54 | return "[Circular]"; 55 | } 56 | seen.add(value); 57 | } 58 | 59 | // undefined の処理 60 | if (typeof value === "undefined") { 61 | return "undefined"; 62 | } 63 | 64 | // 関数の処理 65 | if (typeof value === "function") { 66 | return value.toString(); 67 | } 68 | 69 | // シンボルの処理 70 | if (typeof value === "symbol") { 71 | return value.toString(); 72 | } 73 | 74 | // ビッグイントの処理 75 | if (typeof value === "bigint") { 76 | return value.toString() + "n"; 77 | } 78 | 79 | // 数値の特殊値の処理 80 | if (typeof value === "number") { 81 | if (Number.isNaN(value)) { 82 | return "NaN"; 83 | } 84 | if (!Number.isFinite(value)) { 85 | return value > 0 ? "Infinity" : "-Infinity"; 86 | } 87 | if (Object.is(value, -0)) { 88 | return "-0"; 89 | } 90 | } 91 | 92 | // 正規表現の処理 93 | if (value instanceof RegExp) { 94 | return value.toString(); 95 | } 96 | 97 | // 日付の処理 98 | if (value instanceof Date) { 99 | return { 100 | dataType: "Date", 101 | value: value.toISOString(), 102 | }; 103 | } 104 | 105 | // エラーオブジェクトの処理 106 | if (value instanceof Error) { 107 | return { 108 | name: value.name, 109 | message: value.message, 110 | stack: value.stack, 111 | }; 112 | } 113 | 114 | // Map の処理 115 | if (value instanceof Map) { 116 | return { 117 | dataType: "Map", 118 | value: Array.from(value.entries()), 119 | }; 120 | } 121 | 122 | // Set の処理 123 | if (value instanceof Set) { 124 | return { 125 | dataType: "Set", 126 | value: Array.from(value), 127 | }; 128 | } 129 | 130 | return value; 131 | } 132 | 133 | return JSON.stringify(resolved, replacer); 134 | } 135 | -------------------------------------------------------------------------------- /apps/test/src/tests/literal/__snapshots__/literal.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Literal Type Tests TsLiteralArrayUnionType matches snapshot 1`] = `"[]"`; 4 | 5 | exports[`Literal Type Tests TsLiteralBooleanUnionType matches snapshot 1`] = `"false"`; 6 | 7 | exports[`Literal Type Tests TsLiteralFunctionUnionType matches snapshot 1`] = ` 8 | "(x) => { 9 | return 10; 10 | }" 11 | `; 12 | 13 | exports[`Literal Type Tests TsLiteralNumberUnionType matches snapshot 1`] = `"1"`; 14 | 15 | exports[`Literal Type Tests TsLiteralObjectUnionType matches snapshot 1`] = `"{"type":"A"}"`; 16 | 17 | exports[`Literal Type Tests TsLiteralTypeStringUnionType matches snapshot 1`] = `""A""`; 18 | 19 | exports[`Literal Type Tests TsTypeLiteralAlias matches snapshot 1`] = `"{"literalString":"test string data","literalLiteralString":"string","literalStringUnion":"A","literalNumber":10,"literalLiteralNumber":42,"literalNumberUnion":1,"literalBoolean":false,"literalLiteralBoolean":true,"literalBooleanUnion":false,"literalNull":null,"literalUndefined":"undefined","literalArray":[],"literalLiteralArray":[1,2,3],"literalArrayUnion":[],"literalObject":{},"literalLiteralObject":{"name":"test string data","age":10},"literalObjectUnion":{"type":"A"},"literalFunction":"() => { }","literalLiteralFunction":"() => { }","literalFunctionUnion":"(x) => {\\n return \\"test string data\\";\\n }","literalBigInt":"9007199254740991n","literalLiteralBigInt":"123n","literalBigIntUnion":"1n","literalSymbol":"Symbol()"}"`; 20 | 21 | exports[`Literal Type Tests TsTypeLiteralArray matches snapshot 1`] = `"[]"`; 22 | 23 | exports[`Literal Type Tests TsTypeLiteralBoolean matches snapshot 1`] = `"false"`; 24 | 25 | exports[`Literal Type Tests TsTypeLiteralFunction matches snapshot 1`] = `"() => { }"`; 26 | 27 | exports[`Literal Type Tests TsTypeLiteralInterface matches snapshot 1`] = `"{"literalString":"test string data","literalLiteralString":"string","literalStringUnion":"A","literalNumber":10,"literalLiteralNumber":42,"literalNumberUnion":1,"literalBoolean":false,"literalLiteralBoolean":true,"literalBooleanUnion":false,"literalNull":null,"literalUndefined":"undefined","literalArray":[],"literalLiteralArray":[1,2,3],"literalArrayUnion":[],"literalObject":{},"literalLiteralObject":{"name":"test string data","age":10},"literalObjectUnion":{"type":"A"},"literalFunction":"() => { }","literalLiteralFunction":"() => { }","literalFunctionUnion":"(x) => {\\n return \\"test string data\\";\\n }","literalBigInt":"9007199254740991n","literalLiteralBigInt":"123n","literalBigIntUnion":"1n","literalSymbol":"Symbol()"}"`; 28 | 29 | exports[`Literal Type Tests TsTypeLiteralLiteralArrayType matches snapshot 1`] = `"[1,2,3]"`; 30 | 31 | exports[`Literal Type Tests TsTypeLiteralLiteralBooleanType matches snapshot 1`] = `"true"`; 32 | 33 | exports[`Literal Type Tests TsTypeLiteralLiteralFunctionType matches snapshot 1`] = `"() => { }"`; 34 | 35 | exports[`Literal Type Tests TsTypeLiteralLiteralNumberType matches snapshot 1`] = `"42"`; 36 | 37 | exports[`Literal Type Tests TsTypeLiteralLiteralObjectType matches snapshot 1`] = `"{"name":"test string data","age":10}"`; 38 | 39 | exports[`Literal Type Tests TsTypeLiteralLiteralTypeString matches snapshot 1`] = `""string""`; 40 | 41 | exports[`Literal Type Tests TsTypeLiteralNull matches snapshot 1`] = `"null"`; 42 | 43 | exports[`Literal Type Tests TsTypeLiteralNumber matches snapshot 1`] = `"10"`; 44 | 45 | exports[`Literal Type Tests TsTypeLiteralObject matches snapshot 1`] = `"{}"`; 46 | 47 | exports[`Literal Type Tests TsTypeLiteralString matches snapshot 1`] = `""test string data""`; 48 | 49 | exports[`Literal Type Tests TsTypeLiteralSymbol matches snapshot 1`] = `"Symbol()"`; 50 | 51 | exports[`Literal Type Tests TsTypeLiteralUndefined matches snapshot 1`] = `""undefined""`; 52 | -------------------------------------------------------------------------------- /crates/boostest/src/boostest_manager/target_detector.rs: -------------------------------------------------------------------------------- 1 | use std::path::{Path, PathBuf}; 2 | use std::sync::{Arc, Mutex}; 3 | 4 | use oxc::ast::ast::{CallExpression, Expression}; 5 | use oxc::ast::visit::walk_mut::walk_call_expression; 6 | use oxc::ast::{AstKind, Visit, VisitMut}; 7 | use oxc::parser::Parser; 8 | use oxc::semantic::SemanticBuilder; 9 | use oxc::span::{SourceType, Span}; 10 | 11 | use crate::boostest_resolver::target::{MainTarget, TargetReference}; 12 | use crate::boostest_utils::file_utils; 13 | 14 | pub struct TargetDetector { 15 | pattern: String, 16 | pub main_targets: Vec>>, 17 | temp_target_file_path: PathBuf, 18 | } 19 | 20 | impl TargetDetector { 21 | pub fn new(pattern: String) -> Self { 22 | Self { 23 | pattern, 24 | main_targets: Vec::new(), 25 | temp_target_file_path: PathBuf::new(), 26 | } 27 | } 28 | 29 | pub fn detect(&mut self, target_file_path: &Path) { 30 | self.temp_target_file_path = target_file_path.to_path_buf(); 31 | let target_source = file_utils::read(target_file_path).unwrap_or_default(); 32 | 33 | let source_type = SourceType::ts(); 34 | let allocator = oxc::allocator::Allocator::default(); 35 | 36 | let parser = Parser::new(&allocator, &target_source, source_type); 37 | let mut program = parser.parse().program; 38 | 39 | self.visit_statements(&mut program.body); 40 | 41 | // let ret = Parser::new(&allocator, &target_source, source_type).parse(); 42 | // let semantic_ret = SemanticBuilder::new().build(&ret.program); 43 | 44 | // for node in semantic_ret.semantic.nodes() { 45 | // if let AstKind::CallExpression(call_expr) = node.kind() { 46 | // let function_name = match &call_expr.callee { 47 | // Expression::Identifier(ident) => ident.name.clone().into_string(), 48 | // _ => String::new(), 49 | // }; 50 | // 51 | // println!("function_name: {}", function_name); 52 | // 53 | // let pattern = &self.pattern; 54 | // 55 | // // add target function to mock ast loader 56 | // if function_name.contains(pattern) { 57 | // self.add_main_target(function_name, call_expr); 58 | // } 59 | // } 60 | // } 61 | } 62 | 63 | fn add_main_target(&mut self, mock_func_name: String, expr: &CallExpression) { 64 | let mut main_target = MainTarget::new( 65 | mock_func_name, 66 | None, 67 | TargetReference { 68 | file_path: self.temp_target_file_path.clone(), 69 | span: Span::default(), 70 | target_supplement: None, 71 | }, 72 | TargetReference { 73 | file_path: self.temp_target_file_path.clone(), 74 | span: expr.span, 75 | target_supplement: None, 76 | }, 77 | ); 78 | 79 | main_target.visit_call_expression(expr); 80 | 81 | self.main_targets.push(Arc::new(Mutex::new(main_target))); 82 | } 83 | } 84 | impl<'a> VisitMut<'a> for TargetDetector { 85 | fn visit_call_expression(&mut self, call_expr: &mut CallExpression) { 86 | let function_name = match &call_expr.callee { 87 | Expression::Identifier(ident) => ident.name.clone().into_string(), 88 | _ => String::new(), 89 | }; 90 | 91 | let pattern = &self.pattern; 92 | 93 | // add target function to mock ast loader 94 | if function_name.contains(pattern) { 95 | self.add_main_target(function_name, call_expr); 96 | } 97 | 98 | walk_call_expression(self, call_expr); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /crates/boostest/src/boostest_resolver/resolver/tsserver_resolver.rs: -------------------------------------------------------------------------------- 1 | use anyhow::{anyhow, Result}; 2 | use colored::*; 3 | use oxc::parser::Parser; 4 | use oxc::span::SourceType; 5 | use std::path::PathBuf; 6 | use std::sync::{Arc, Mutex}; 7 | 8 | use oxc::ast::VisitMut; 9 | 10 | use crate::boostest_resolver::visit_mut::TargetResolver; 11 | use crate::boostest_utils::buf::{source_text_from_span, utf16_span_to_utf8_span}; 12 | use crate::boostest_utils::file_utils; 13 | use crate::boostest_utils::tsserver::{tsserver, TSServerCache}; 14 | 15 | pub fn resolve_target_ast_with_tsserver( 16 | target_resolver: &mut TargetResolver, 17 | project_root_path: &Option, 18 | depth: u8, 19 | ts_server_cache: Arc>, 20 | ) -> Result<()> { 21 | let target_file_path = target_resolver 22 | .target 23 | .lock() 24 | .unwrap() 25 | .target_reference 26 | .file_path 27 | .clone(); 28 | 29 | if depth > 10 { 30 | println!( 31 | "{}", 32 | format!( 33 | "module resolution depth is too deep on tsserver: {} of {}", 34 | target_resolver.target.lock().unwrap().name, 35 | target_file_path.to_str().unwrap_or("unknown file") 36 | ) 37 | .red() 38 | ); 39 | return Ok(()); 40 | } 41 | 42 | // clean up 43 | target_resolver.temp_renamed_var_decl_span = None; 44 | if target_resolver.resolved() { 45 | return Ok(()); 46 | }; 47 | 48 | let absolute_path = target_file_path.canonicalize().unwrap(); 49 | target_resolver.temp_current_read_file_path = absolute_path.clone(); 50 | 51 | if let Some(project_root_path) = project_root_path { 52 | let target = target_resolver.target.lock().unwrap(); 53 | let name = target.name.clone(); 54 | let span = target.target_reference.span; 55 | drop(target); 56 | 57 | target_resolver.skip_id_check = true; 58 | 59 | if let Some(result) = tsserver( 60 | project_root_path, 61 | &absolute_path, 62 | span, 63 | &name, 64 | ts_server_cache.clone(), 65 | ) { 66 | let mut target_source_text = String::new(); 67 | 68 | for (target_file_path, result_span) in result.iter() { 69 | let target_source = file_utils::read(target_file_path).unwrap_or_default(); 70 | 71 | let utf8_span = utf16_span_to_utf8_span(*result_span, &target_source); 72 | 73 | // NOTE: 対象ファイルから定義元のspanを取得 74 | // それをsouce_textとしてast visitするため完全なファイルではない 75 | // 抽出位置からのspanとなるため、抽出地点のSPANを加えられるよう一時保存する 76 | target_resolver.read_file_span = Some(utf8_span); 77 | target_resolver.temp_current_read_file_path = target_file_path.clone(); 78 | 79 | target_source_text.push_str(source_text_from_span(*result_span, &target_source)); 80 | } 81 | 82 | let source_type = SourceType::ts(); 83 | let allocator = oxc::allocator::Allocator::default(); 84 | let parser = Parser::new(&allocator, &target_source_text, source_type); 85 | let mut program = parser.parse().program; 86 | 87 | target_resolver.visit_statements(&mut program.body); 88 | 89 | if let Some(span) = target_resolver.temp_renamed_var_decl_span { 90 | let mut target = target_resolver.target.lock().unwrap(); 91 | target.target_reference.span = span; 92 | target.target_reference.file_path = target_file_path.clone(); 93 | drop(target); 94 | resolve_target_ast_with_tsserver( 95 | target_resolver, 96 | &Some(project_root_path.clone()), 97 | depth + 1, 98 | ts_server_cache.clone(), 99 | )?; 100 | } 101 | } else { 102 | return Err(anyhow!("ファイル読み込みでエラー")); 103 | } 104 | } 105 | Ok(()) 106 | } 107 | -------------------------------------------------------------------------------- /crates/boostest/src/boostest_utils/file_utils.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use globwalker::glob; 3 | use std::path::{Path, PathBuf}; 4 | 5 | use std::collections::HashMap; 6 | use std::ffi::OsStr; 7 | use std::fs::{self, File}; 8 | use std::io::{self, prelude::*}; 9 | 10 | pub fn read(path: &Path) -> io::Result { 11 | let mut f = File::open(path)?; 12 | let mut s = String::new(); 13 | match f.read_to_string(&mut s) { 14 | Ok(_) => Ok(s), 15 | Err(e) => Err(e), 16 | } 17 | } 18 | 19 | pub fn read_matching_files( 20 | patterns: &Vec, 21 | output_dir_name: &str, 22 | ) -> anyhow::Result> { 23 | let mut contents: HashMap = HashMap::new(); 24 | 25 | for pattern in patterns { 26 | let result_glob = glob(pattern)?; 27 | 28 | for entry in result_glob { 29 | let dir_entry = entry?; 30 | let path = dir_entry.path().to_path_buf(); 31 | 32 | if let Some(parent) = path.parent() { 33 | if parent.file_name() == Some(OsStr::new(output_dir_name)) { 34 | continue; 35 | } 36 | } 37 | if path.is_file() { 38 | contents.insert(path.clone(), fs::read_to_string(path)?); 39 | } 40 | } 41 | } 42 | 43 | Ok(contents) 44 | } 45 | 46 | /** 47 | * Normalize and resolve the path. 48 | * parent: "hoge/a/b/c", relative: "../../d/e/f" => "hoge/a/d/e/f" 49 | */ 50 | pub fn normalize_and_resolve_path(parent: &Path, relative: &Path) -> Result { 51 | let combined_path = parent.join(relative); 52 | let resolved_path = combined_path 53 | .components() 54 | .fold(PathBuf::new(), |mut acc, comp| { 55 | match comp { 56 | std::path::Component::ParentDir => { 57 | acc.pop(); 58 | } 59 | std::path::Component::CurDir => {} 60 | other => acc.push(other), 61 | } 62 | acc 63 | }); 64 | 65 | if resolved_path.is_absolute() { 66 | Ok(resolved_path) 67 | } else { 68 | Err("The resolved path is not absolute.".to_string()) 69 | } 70 | } 71 | 72 | fn reset_and_create_directory(dir_path: PathBuf, clean_only: bool) -> Result<()> { 73 | // if exists, remove all files and directories 74 | if dir_path.exists() { 75 | for entry in fs::read_dir(dir_path.clone())? { 76 | let entry = entry?; 77 | let entry_path = entry.path(); 78 | 79 | if entry_path.is_dir() { 80 | fs::remove_dir_all(entry_path)?; 81 | } else { 82 | fs::remove_file(entry_path)?; 83 | } 84 | } 85 | 86 | if clean_only { 87 | fs::remove_dir(dir_path)?; 88 | return Ok(()); 89 | } 90 | } else { 91 | if clean_only { 92 | return Ok(()); 93 | } 94 | 95 | // if not exists, create directory 96 | fs::create_dir_all(dir_path)?; 97 | } 98 | 99 | Ok(()) 100 | } 101 | 102 | pub fn handle_reset_and_create_files(path: &str, clean_only: bool) -> Result { 103 | let path = Path::new(&path); 104 | let canonical_path = path.canonicalize(); 105 | 106 | if let Ok(canonical_path) = canonical_path { 107 | let parent_path = match canonical_path.is_dir() { 108 | true => Some(canonical_path.as_path()), 109 | false => canonical_path.parent(), 110 | }; 111 | 112 | if let Some(parent_path) = parent_path { 113 | let dir_path = parent_path.join("boostest_output"); 114 | 115 | match reset_and_create_directory(dir_path.clone(), clean_only) { 116 | Ok(_) => { 117 | return Ok(dir_path); 118 | } 119 | Err(e) => { 120 | return Err(e.to_string()); 121 | } 122 | }; 123 | }; 124 | } 125 | 126 | Err("Failed to prepare output files.".to_string()) 127 | } 128 | -------------------------------------------------------------------------------- /apps/test/src/tests/generics/__snapshots__/generics.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Generics Tests Generic matches snapshot 1`] = `"{"name":{"name":"test string data","ver":10,"age":10}}"`; 4 | 5 | exports[`Generics Tests GenericsClass matches snapshot 1`] = `"{"innserGenericInitializer":{"name":"test string data","innerGeneric":{"name":"test string data","ver":10,"age":10},"innerGenericLiteral":"inner generic string"},"mapperType":{"en":"test string data","fr":"test string data","it":"test string data","es":"test string data"},"keyOfMapperType":{"name":"test string data","ver":10,"age":10},"butterflyWithGenerics":{"en":"test string data","fr":"test string data","it":"test string data","es":"test string data"},"nonNullable":"test string data","nestedPartial":{"childPartial":{"name":"test string data","ver":10,"age":10}},"partial":{"name":"test string data","ver":10,"age":10},"required":{"name":"test string data","ver":10,"age":10},"readonly":{"name":"test string data","ver":10,"age":10},"extract":"D","extractRefUnion":"en","exclude":"B","onDirectRefUnionType":"fr","array":[],"pick":{"name":"test string data"},"pickMulti":{"ver":10,"age":10},"omit":{"ver":10,"age":10},"record":{"en":"test string data","fr":"test string data","it":"test string data","es":"test string data"},"parameters":["test string data",10],"returnType":{"name":"test string data","ver":10,"age":10},"instanceType":{"name":"test string data","ver":10},"constructorParameters":["test string data",10],"promise":{"name":"test string data","ver":10,"age":10}}"`; 6 | 7 | exports[`Generics Tests GenericsInterface matches snapshot 1`] = `"{"innserGenericInitializer":{"name":"test string data","innerGeneric":{"name":"test string data","ver":10,"age":10},"innerGenericLiteral":"inner generic string"},"mapperType":{"en":"test string data","fr":"test string data","it":"test string data","es":"test string data"},"keyOfMapperType":{"name":"test string data","ver":10,"age":10},"butterflyWithGenerics":{"en":"test string data","fr":"test string data","it":"test string data","es":"test string data"},"nonNullable":"test string data","nestedPartial":{"childPartial":{"name":"test string data","ver":10,"age":10}},"partial":{"name":"test string data","ver":10,"age":10},"required":{"name":"test string data","ver":10,"age":10},"readonly":{"name":"test string data","ver":10,"age":10},"extract":"D","extractRefUnion":"en","exclude":"B","onDirectRefUnionType":"fr","array":[],"pick":{"name":"test string data"},"pickMulti":{"ver":10,"age":10},"omit":{"ver":10,"age":10},"record":{"en":"test string data","fr":"test string data","it":"test string data","es":"test string data"},"parameters":["test string data",10],"returnType":{"name":"test string data","ver":10,"age":10},"instanceType":{"name":"test string data","ver":10},"constructorParameters":["test string data",10],"promise":{"name":"test string data","ver":10,"age":10}}"`; 8 | 9 | exports[`Generics Tests GenericsTypeAlias matches snapshot 1`] = `"{"mapperType":{"en":"test string data","fr":"test string data","it":"test string data","es":"test string data"},"keyOfMapperType":{"name":"test string data","ver":10,"age":10},"innserGenericInitializer":{"name":"test string data","innerGeneric":{"name":"test string data","ver":10,"age":10},"innerGenericLiteral":"inner generic string"},"butterflyWithGenerics":{"en":"test string data","fr":"test string data","it":"test string data","es":"test string data"},"nonNullable":"test string data","nestedPartial":{"childPartial":{"name":"test string data","ver":10,"age":10}},"partial":{"name":"test string data","ver":10,"age":10},"required":{"name":"test string data","ver":10,"age":10},"readonly":{"name":"test string data","ver":10,"age":10},"extract":"D","extractRefUnion":"en","exclude":"B","onDirectRefUnionType":"fr","array":[],"pick":{"name":"test string data"},"pickMulti":{"ver":10,"age":10},"omit":{"ver":10,"age":10},"record":{"en":"test string data","fr":"test string data","it":"test string data","es":"test string data"},"parameters":["test string data",10],"returnType":{"name":"test string data","ver":10,"age":10},"instanceType":{"name":"test string data","ver":10},"constructorParameters":["test string data",10],"promise":{"name":"test string data","ver":10,"age":10}}"`; 10 | -------------------------------------------------------------------------------- /apps/test/src/tests/not_ref_types/notRefTypes.spec.ts: -------------------------------------------------------------------------------- 1 | import { runSnapshotTest } from "../utils"; 2 | 3 | import { TsTypeLiteralLiteralObjectType } from "@/ts_types/ts_type_literal"; 4 | import { boostestDirectPromise } from "./boostest_output/boostestDirectPromise"; 5 | import { RefType, RefInterface } from "@/ts_types/utils"; 6 | import { Hoge } from "@/ts_types/literal"; 7 | import { boostestTuple } from "./boostest_output/boostestTuple"; 8 | import { boostestString } from "./boostest_output/boostestString"; 9 | import { boostestBoolean } from "./boostest_output/boostestBoolean"; 10 | import { boostestNumber } from "./boostest_output/boostestNumber"; 11 | import { boostestUnion } from "./boostest_output/boostestUnion"; 12 | import { boostestReference } from "./boostest_output/boostestReference"; 13 | import { boostestArray } from "./boostest_output/boostestArray"; 14 | import { boostestFunction } from "./boostest_output/boostestFunction"; 15 | import { boostestVoid } from "./boostest_output/boostestVoid"; 16 | import { boostestObject } from "./boostest_output/boostestObject"; 17 | import { boostestUnknown } from "./boostest_output/boostestUnknown"; 18 | import { boostestAny } from "./boostest_output/boostestAny"; 19 | import { boostestUndefined } from "./boostest_output/boostestUndefined"; 20 | import { boostestNull } from "./boostest_output/boostestNull"; 21 | import { boostestBigInt } from "./boostest_output/boostestBigInt"; 22 | import { boostestConditional } from "./boostest_output/boostestConditional"; 23 | import { boostestSymbol } from "./boostest_output/boostestSymbol"; 24 | import { boostestNamedTuple } from "./boostest_output/boostestNamedTuple"; 25 | import { boostestIntersection } from "./boostest_output/boostestIntersection"; 26 | import { boostestKeyof } from "./boostest_output/boostestKeyof"; 27 | import { boostestIndexAccessor } from "./boostest_output/boostestIndexAccessor"; 28 | import { boostestConstructor } from "./boostest_output/boostestConstructor"; 29 | import { boostestClass } from "./boostest_output/boostestClass"; 30 | 31 | describe("not ref types(direct) Tests", () => { 32 | runSnapshotTest( 33 | "Direct Promise", 34 | boostestDirectPromise>(), 35 | ); 36 | runSnapshotTest("Direct boolean", boostestBoolean()); 37 | runSnapshotTest("Direct string", boostestString()); 38 | runSnapshotTest("Direct number", boostestNumber()); 39 | runSnapshotTest("Direct bigint", boostestBigInt()); 40 | runSnapshotTest("Direct null", boostestNull()); 41 | runSnapshotTest("Direct undefined", boostestUndefined()); 42 | runSnapshotTest("Direct any", boostestAny()); 43 | runSnapshotTest("Direct unknown", boostestUnknown()); 44 | runSnapshotTest("Direct object", boostestObject()); 45 | runSnapshotTest("Direct void", boostestVoid()); 46 | runSnapshotTest( 47 | "Direct function", 48 | boostestFunction<(arg: RefType) => RefInterface>(), 49 | ); 50 | runSnapshotTest("Direct array", boostestArray()); 51 | runSnapshotTest("Direct reference", boostestReference()); 52 | runSnapshotTest("Direct union", boostestUnion()); 53 | runSnapshotTest( 54 | "Direct conditional", 55 | boostestConditional(), 56 | ); 57 | runSnapshotTest("Direct symbol", boostestSymbol()); 58 | runSnapshotTest( 59 | "Direct tuple", 60 | boostestTuple<[string, number, any, RefType, RefInterface]>(), 61 | ); 62 | runSnapshotTest( 63 | "Direct named tuple", 64 | boostestNamedTuple< 65 | [name: string, ver: number, ref: RefType, refInterface: RefInterface] 66 | >(), 67 | ); 68 | runSnapshotTest( 69 | "Direct intersection", 70 | boostestIntersection(), 71 | ); 72 | runSnapshotTest("Direct keyof", boostestKeyof()); 73 | runSnapshotTest( 74 | "Direct index accessor", 75 | boostestIndexAccessor(), 76 | ); 77 | runSnapshotTest( 78 | "Direct constructor", 79 | boostestConstructor Hoge>(), 80 | ); 81 | runSnapshotTest("Direct class", boostestClass()); 82 | }); 83 | -------------------------------------------------------------------------------- /packages/boostest/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.toptal.com/developers/gitignore/api/node 2 | # Edit at https://www.toptal.com/developers/gitignore?templates=node 3 | 4 | ### Node ### 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | lerna-debug.log* 12 | 13 | # Diagnostic reports (https://nodejs.org/api/report.html) 14 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 15 | 16 | # Runtime data 17 | pids 18 | *.pid 19 | *.seed 20 | *.pid.lock 21 | 22 | # Directory for instrumented libs generated by jscoverage/JSCover 23 | lib-cov 24 | 25 | # Coverage directory used by tools like istanbul 26 | coverage 27 | *.lcov 28 | 29 | # nyc test coverage 30 | .nyc_output 31 | 32 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 33 | .grunt 34 | 35 | # Bower dependency directory (https://bower.io/) 36 | bower_components 37 | 38 | # node-waf configuration 39 | .lock-wscript 40 | 41 | # Compiled binary addons (https://nodejs.org/api/addons.html) 42 | build/Release 43 | 44 | # Dependency directories 45 | node_modules/ 46 | jspm_packages/ 47 | 48 | # TypeScript v1 declaration files 49 | typings/ 50 | 51 | # TypeScript cache 52 | *.tsbuildinfo 53 | 54 | # Optional npm cache directory 55 | .npm 56 | 57 | # Optional eslint cache 58 | .eslintcache 59 | 60 | # Microbundle cache 61 | .rpt2_cache/ 62 | .rts2_cache_cjs/ 63 | .rts2_cache_es/ 64 | .rts2_cache_umd/ 65 | 66 | # Optional REPL history 67 | .node_repl_history 68 | 69 | # Output of 'npm pack' 70 | *.tgz 71 | 72 | # Yarn Integrity file 73 | .yarn-integrity 74 | 75 | # dotenv environment variables file 76 | .env 77 | .env.test 78 | 79 | # parcel-bundler cache (https://parceljs.org/) 80 | .cache 81 | 82 | # Next.js build output 83 | .next 84 | 85 | # Nuxt.js build / generate output 86 | .nuxt 87 | dist 88 | 89 | # Gatsby files 90 | .cache/ 91 | # Comment in the public line in if your project uses Gatsby and not Next.js 92 | # https://nextjs.org/blog/next-9-1#public-directory-support 93 | # public 94 | 95 | # vuepress build output 96 | .vuepress/dist 97 | 98 | # Serverless directories 99 | .serverless/ 100 | 101 | # FuseBox cache 102 | .fusebox/ 103 | 104 | # DynamoDB Local files 105 | .dynamodb/ 106 | 107 | # TernJS port file 108 | .tern-port 109 | 110 | # Stores VSCode versions used for testing VSCode extensions 111 | .vscode-test 112 | 113 | # End of https://www.toptal.com/developers/gitignore/api/node 114 | 115 | # Created by https://www.toptal.com/developers/gitignore/api/macos 116 | # Edit at https://www.toptal.com/developers/gitignore?templates=macos 117 | 118 | ### macOS ### 119 | # General 120 | .DS_Store 121 | .AppleDouble 122 | .LSOverride 123 | 124 | # Icon must end with two 125 | Icon 126 | 127 | 128 | # Thumbnails 129 | ._* 130 | 131 | # Files that might appear in the root of a volume 132 | .DocumentRevisions-V100 133 | .fseventsd 134 | .Spotlight-V100 135 | .TemporaryItems 136 | .Trashes 137 | .VolumeIcon.icns 138 | .com.apple.timemachine.donotpresent 139 | 140 | # Directories potentially created on remote AFP share 141 | .AppleDB 142 | .AppleDesktop 143 | Network Trash Folder 144 | Temporary Items 145 | .apdisk 146 | 147 | ### macOS Patch ### 148 | # iCloud generated files 149 | *.icloud 150 | 151 | # End of https://www.toptal.com/developers/gitignore/api/macos 152 | 153 | # Created by https://www.toptal.com/developers/gitignore/api/windows 154 | # Edit at https://www.toptal.com/developers/gitignore?templates=windows 155 | 156 | ### Windows ### 157 | # Windows thumbnail cache files 158 | Thumbs.db 159 | Thumbs.db:encryptable 160 | ehthumbs.db 161 | ehthumbs_vista.db 162 | 163 | # Dump file 164 | *.stackdump 165 | 166 | # Folder config file 167 | [Dd]esktop.ini 168 | 169 | # Recycle Bin used on file shares 170 | $RECYCLE.BIN/ 171 | 172 | # Windows Installer files 173 | *.cab 174 | *.msi 175 | *.msix 176 | *.msm 177 | *.msp 178 | 179 | # Windows shortcuts 180 | *.lnk 181 | 182 | # End of https://www.toptal.com/developers/gitignore/api/windows 183 | 184 | #Added by cargo 185 | 186 | /target 187 | Cargo.lock 188 | 189 | .pnp.* 190 | .yarn/* 191 | !.yarn/patches 192 | !.yarn/plugins 193 | !.yarn/releases 194 | !.yarn/sdks 195 | !.yarn/versions 196 | 197 | *.node 198 | -------------------------------------------------------------------------------- /apps/test/src/tests/standard/__snapshots__/standard.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Standard Tests LiteralTypeAlias matches snapshot 1`] = `"{"stringLiteral":"test string data","numberLiteral":10,"bigintLiteral":"9007199254740991n","booleanLiteral":false,"nullLiteral":null,"undefinedId":"undefined","anyLiteral":"any","unknownLiteral":"undefined","objectLiteral":{},"voidLiteral":null,"functionLiteral":"() => { }","arrayLiteral":[],"referenceLiteral":{"name":"test string data","ver":10,"age":10},"unionType":"test string data","conditionalType":false,"tsLiteralString":"string","tsLiteralNumber":20,"tsBigInt":"10000000000000n","tsLiteralBoolean":true,"tsNullLiteral":null,"tsObject":{},"tsArray":[],"symbolLiteral":"Symbol()","tsTuple":["test string data",10,"any",{"name":"test string data","ver":10,"age":10},{"name":"test string data","ver":10}],"tsNamedTuple":["test string data",10,{"name":"test string data","ver":10,"age":10},{"name":"test string data","ver":10}],"intersectionType":{"name":"test string data","ver":10,"age":10},"keyof":"name","indexAccessor":"test string data","constructorType":"class ref_876fd03c9f43781a5f603af02cb0fcd8b9abb9384aa60b4674d20fe6b0e6c465 {\\n name;\\n ver;\\n constructor(name, ver) {\\n this.name = name;\\n this.ver = ver;\\n }\\n}","classType":"class ref_876fd03c9f43781a5f603af02cb0fcd8b9abb9384aa60b4674d20fe6b0e6c465 {\\n name;\\n ver;\\n constructor(name, ver) {\\n this.name = name;\\n this.ver = ver;\\n }\\n}"}"`; 4 | 5 | exports[`Standard Tests LiteralTypeClass matches snapshot 1`] = `"{"stringLiteral":"test string data","numberLiteral":10,"bigintLiteral":"9007199254740991n","booleanLiteral":false,"nullLiteral":null,"undefinedId":"undefined","anyLiteral":"any","unknownLiteral":"undefined","objectLiteral":{},"voidLiteral":null,"functionLiteral":"() => { }","arrayLiteral":[],"referenceLiteral":{"name":"test string data","ver":10,"age":10},"unionType":"test string data","tsLiteralString":"string","tsLiteralNumber":20,"tsBigInt":"10000000000000n","tsLiteralBoolean":true,"tsNullLiteral":null,"tsObject":{},"tsArray":[],"symbolLiteral":"Symbol()","tsTuple":["test string data",10,"any",{"name":"test string data","ver":10,"age":10},{"name":"test string data","ver":10},"test string data"],"tsNamedTuple":["test string data",10,{"name":"test string data","ver":10,"age":10},{"name":"test string data","ver":10},10],"intersectionType":{"name":"test string data","ver":10,"age":10},"conditionalType":false,"keyof":"name","indexAccessor":"test string data","constructorType":"class ref_876fd03c9f43781a5f603af02cb0fcd8b9abb9384aa60b4674d20fe6b0e6c465 {\\n name;\\n ver;\\n constructor(name, ver) {\\n this.name = name;\\n this.ver = ver;\\n }\\n}","classType":"class ref_876fd03c9f43781a5f603af02cb0fcd8b9abb9384aa60b4674d20fe6b0e6c465 {\\n name;\\n ver;\\n constructor(name, ver) {\\n this.name = name;\\n this.ver = ver;\\n }\\n}"}"`; 6 | 7 | exports[`Standard Tests LiteralTypeInterface matches snapshot 1`] = `"{"stringLiteral":"test string data","numberLiteral":10,"bigintLiteral":"9007199254740991n","booleanLiteral":false,"nullLiteral":null,"undefinedId":"undefined","anyLiteral":"any","unknownLiteral":"undefined","objectLiteral":{},"voidLiteral":null,"functionLiteral":"() => { }","arrayLiteral":[],"referenceLiteral":{"name":"test string data","ver":10,"age":10},"unionType":"test string data","conditionalType":false,"tsLiteralString":"string","tsLiteralNumber":20,"tsBigInt":"10000000000000n","tsLiteralBoolean":true,"tsNullLiteral":null,"tsObject":{},"tsArray":[],"symbolLiteral":"Symbol()","tsTuple":["test string data",10,"any",{"name":"test string data","ver":10,"age":10},{"name":"test string data","ver":10}],"tsNamedTuple":["test string data",10,{"name":"test string data","ver":10,"age":10},{"name":"test string data","ver":10}],"intersectionType":{"name":"test string data","ver":10,"age":10},"keyof":"name","indexAccessor":"test string data","constructorType":"class ref_876fd03c9f43781a5f603af02cb0fcd8b9abb9384aa60b4674d20fe6b0e6c465 {\\n name;\\n ver;\\n constructor(name, ver) {\\n this.name = name;\\n this.ver = ver;\\n }\\n}","classType":"class ref_876fd03c9f43781a5f603af02cb0fcd8b9abb9384aa60b4674d20fe6b0e6c465 {\\n name;\\n ver;\\n constructor(name, ver) {\\n this.name = name;\\n this.ver = ver;\\n }\\n}"}"`; 8 | -------------------------------------------------------------------------------- /apps/test/src/tests/main_file_import/__snapshots__/main_file_import.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`main file import tests DLiteralTypeAlias matches snapshot 1`] = `"{"stringLiteral":"test string data","numberLiteral":10,"bigintLiteral":"9007199254740991n","booleanLiteral":false,"nullLiteral":null,"undefinedId":"undefined","anyLiteral":"any","unknownLiteral":"undefined","objectLiteral":{},"voidLiteral":null,"functionLiteral":"() => { }","arrayLiteral":[],"referenceLiteral":{"name":"test string data","ver":10,"age":10},"unionType":"test string data","conditionalType":false,"tsLiteralString":"string","tsLiteralNumber":20,"tsBigInt":"10000000000000n","tsLiteralBoolean":true,"tsNullLiteral":null,"tsObject":{},"tsArray":[],"symbolLiteral":"Symbol()","tsTuple":["test string data",10,"any",{"name":"test string data","ver":10,"age":10},{"name":"test string data","ver":10}],"tsNamedTuple":["test string data",10,{"name":"test string data","ver":10,"age":10},{"name":"test string data","ver":10}],"intersectionType":{"name":"test string data","ver":10,"age":10},"keyof":"name","indexAccessor":"test string data","constructorType":"class ref_876fd03c9f43781a5f603af02cb0fcd8b9abb9384aa60b4674d20fe6b0e6c465 {\\n name;\\n ver;\\n constructor(name, ver) {\\n this.name = name;\\n this.ver = ver;\\n }\\n}","classType":"class ref_876fd03c9f43781a5f603af02cb0fcd8b9abb9384aa60b4674d20fe6b0e6c465 {\\n name;\\n ver;\\n constructor(name, ver) {\\n this.name = name;\\n this.ver = ver;\\n }\\n}"}"`; 4 | 5 | exports[`main file import tests FileNameLiteralTypeAlias matches snapshot 1`] = `"{"stringLiteral":"test string data","numberLiteral":10,"bigintLiteral":"9007199254740991n","booleanLiteral":false,"nullLiteral":null,"undefinedId":"undefined","anyLiteral":"any","unknownLiteral":"undefined","objectLiteral":{},"voidLiteral":null,"functionLiteral":"() => { }","arrayLiteral":[],"referenceLiteral":{"name":"test string data","ver":10,"age":10},"unionType":"test string data","conditionalType":false,"tsLiteralString":"string","tsLiteralNumber":20,"tsBigInt":"10000000000000n","tsLiteralBoolean":true,"tsNullLiteral":null,"tsObject":{},"tsArray":[],"symbolLiteral":"Symbol()","tsTuple":["test string data",10,"any",{"name":"test string data","ver":10,"age":10},{"name":"test string data","ver":10}],"tsNamedTuple":["test string data",10,{"name":"test string data","ver":10,"age":10},{"name":"test string data","ver":10}],"intersectionType":{"name":"test string data","ver":10,"age":10},"keyof":"name","indexAccessor":"test string data","constructorType":"class ref_876fd03c9f43781a5f603af02cb0fcd8b9abb9384aa60b4674d20fe6b0e6c465 {\\n name;\\n ver;\\n constructor(name, ver) {\\n this.name = name;\\n this.ver = ver;\\n }\\n}","classType":"class ref_876fd03c9f43781a5f603af02cb0fcd8b9abb9384aa60b4674d20fe6b0e6c465 {\\n name;\\n ver;\\n constructor(name, ver) {\\n this.name = name;\\n this.ver = ver;\\n }\\n}"}"`; 6 | 7 | exports[`main file import tests IndexExport matches snapshot 1`] = `"{"stringLiteral":"test string data","numberLiteral":10,"bigintLiteral":"9007199254740991n","booleanLiteral":false,"nullLiteral":null,"undefinedId":"undefined","anyLiteral":"any","unknownLiteral":"undefined","objectLiteral":{},"voidLiteral":null,"functionLiteral":"() => { }","arrayLiteral":[],"referenceLiteral":{"name":"test string data","ver":10,"age":10},"unionType":"test string data","conditionalType":false,"tsLiteralString":"string","tsLiteralNumber":20,"tsBigInt":"10000000000000n","tsLiteralBoolean":true,"tsNullLiteral":null,"tsObject":{},"tsArray":[],"symbolLiteral":"Symbol()","tsTuple":["test string data",10,"any",{"name":"test string data","ver":10,"age":10},{"name":"test string data","ver":10}],"tsNamedTuple":["test string data",10,{"name":"test string data","ver":10,"age":10},{"name":"test string data","ver":10}],"intersectionType":{"name":"test string data","ver":10,"age":10},"keyof":"name","indexAccessor":"test string data","constructorType":"class ref_876fd03c9f43781a5f603af02cb0fcd8b9abb9384aa60b4674d20fe6b0e6c465 {\\n name;\\n ver;\\n constructor(name, ver) {\\n this.name = name;\\n this.ver = ver;\\n }\\n}","classType":"class ref_876fd03c9f43781a5f603af02cb0fcd8b9abb9384aa60b4674d20fe6b0e6c465 {\\n name;\\n ver;\\n constructor(name, ver) {\\n this.name = name;\\n this.ver = ver;\\n }\\n}"}"`; 8 | -------------------------------------------------------------------------------- /apps/test/src/types/ts_types/literal.ts: -------------------------------------------------------------------------------- 1 | import { RefType } from "@/ts_types/utils"; 2 | 3 | interface RefTypeInterface { 4 | name: string; 5 | ver: number; 6 | } 7 | 8 | export class Hoge { 9 | name: string; 10 | ver: number; 11 | constructor(name: string, ver: number) { 12 | this.name = name; 13 | this.ver = ver; 14 | } 15 | } 16 | 17 | export type LiteralTypeAlias = { 18 | stringLiteral: string; 19 | numberLiteral: number; 20 | bigintLiteral: bigint; 21 | booleanLiteral: boolean; 22 | nullLiteral: null; 23 | undefinedId: undefined; 24 | anyLiteral: any; 25 | unknownLiteral: unknown; 26 | // neverLiteral: never; 27 | objectLiteral: object; 28 | voidLiteral: void; 29 | functionLiteral: () => void; 30 | arrayLiteral: string[]; 31 | referenceLiteral: RefType; 32 | unionType: string | number; 33 | conditionalType: string extends number ? true : false; 34 | 35 | tsLiteralString: "string"; 36 | tsLiteralNumber: 20; 37 | tsBigInt: 10000000000000n; 38 | tsLiteralBoolean: true; 39 | tsNullLiteral: null; 40 | tsObject: {}; 41 | tsArray: []; 42 | 43 | symbolLiteral: symbol; 44 | tsTuple: [string, number, any, RefType, RefTypeInterface]; 45 | tsNamedTuple: [ 46 | name: string, 47 | ver: number, 48 | ref: RefType, 49 | refInterface: RefTypeInterface, 50 | ]; 51 | intersectionType: RefType & { name: string; age: number }; 52 | keyof: keyof RefType; 53 | indexAccessor: RefType["name"]; 54 | constructorType: abstract new (...args: any) => Hoge; 55 | classType: typeof Hoge; 56 | }; 57 | 58 | export type LiteralTypeInterface = { 59 | stringLiteral: string; 60 | numberLiteral: number; 61 | bigintLiteral: bigint; 62 | booleanLiteral: boolean; 63 | nullLiteral: null; 64 | undefinedId: undefined; 65 | anyLiteral: any; 66 | unknownLiteral: unknown; 67 | // neverLiteral: never; 68 | objectLiteral: object; 69 | voidLiteral: void; 70 | functionLiteral: () => void; 71 | arrayLiteral: string[]; 72 | referenceLiteral: RefType; 73 | unionType: string | number; 74 | conditionalType: string extends number ? true : false; 75 | 76 | tsLiteralString: "string"; 77 | tsLiteralNumber: 20; 78 | tsBigInt: 10000000000000n; 79 | tsLiteralBoolean: true; 80 | tsNullLiteral: null; 81 | tsObject: {}; 82 | tsArray: []; 83 | 84 | symbolLiteral: symbol; 85 | tsTuple: [string, number, any, RefType, RefTypeInterface]; 86 | tsNamedTuple: [ 87 | name: string, 88 | ver: number, 89 | ref: RefType, 90 | refInterface: RefTypeInterface, 91 | ]; 92 | intersectionType: RefType & RefTypeInterface & { name: string; age: number }; 93 | keyof: keyof RefType; 94 | indexAccessor: RefType["name"]; 95 | constructorType: abstract new (...args: any) => Hoge; 96 | classType: typeof Hoge; 97 | }; 98 | 99 | export class LiteralTypeClass { 100 | constructor( 101 | public stringLiteral: string, 102 | public numberLiteral: number, 103 | public bigintLiteral: bigint, 104 | public booleanLiteral: boolean, 105 | public nullLiteral: null, 106 | public undefinedId: undefined, 107 | public anyLiteral: any, 108 | public unknownLiteral: unknown, 109 | // public neverLiteral: never, 110 | public objectLiteral: object, 111 | public voidLiteral: void, 112 | public functionLiteral: () => void, 113 | public arrayLiteral: string[], 114 | public referenceLiteral: RefType, 115 | public unionType: string | number, 116 | 117 | public tsLiteralString: "string", 118 | public tsLiteralNumber: 20, 119 | public tsBigInt: 10000000000000n, 120 | public tsLiteralBoolean: true, 121 | public tsNullLiteral: null, 122 | public tsObject: {}, 123 | public tsArray: [], 124 | 125 | public symbolLiteral: symbol, 126 | public tsTuple: [string, number, any, RefType, RefTypeInterface, string], 127 | public tsNamedTuple: [ 128 | name: string, 129 | ver: number, 130 | ref: RefType, 131 | refInterface: RefTypeInterface, 132 | hello: number, 133 | ], 134 | public intersectionType: RefType & 135 | RefTypeInterface & { name: string; age: number }, 136 | public conditionalType: string extends number ? true : false, 137 | 138 | public keyof: keyof RefType, 139 | public indexAccessor: RefType["name"], 140 | public constructorType: abstract new (...args: any) => Hoge, 141 | public classType: typeof Hoge, 142 | ) {} 143 | } 144 | -------------------------------------------------------------------------------- /apps/test/src/types/ts_types/built_in_class.ts: -------------------------------------------------------------------------------- 1 | export type BuiltInType = { 2 | date: Date; 3 | set: Set; 4 | map: Map; 5 | array: Array; 6 | object: Object; 7 | string: String; 8 | number: Number; 9 | boolean: Boolean; 10 | symbol: Symbol; 11 | function: Function; 12 | regexp: RegExp; 13 | error: Error; 14 | promise: Promise; 15 | arrayBuffer: ArrayBuffer; 16 | dataView: DataView; 17 | int8Array: Int8Array; 18 | uint8Array: Uint8Array; 19 | uint8ClampedArray: Uint8ClampedArray; 20 | int16Array: Int16Array; 21 | uint16Array: Uint16Array; 22 | int32Array: Int32Array; 23 | uint32Array: Uint32Array; 24 | float32Array: Float32Array; 25 | float64Array: Float64Array; 26 | bigInt64Array: BigInt64Array; 27 | bigUint64Array: BigUint64Array; 28 | mapIterator: IterableIterator<[string, number]>; 29 | setIterator: IterableIterator; 30 | arrayIterator: IterableIterator; 31 | stringIterator: IterableIterator; 32 | sharedArrayBuffer: SharedArrayBuffer; 33 | atomics: Atomics; 34 | // TODO 35 | // webAssembly: typeof WebAssembly; 36 | // webAssemblyCompileError: WebAssembly.CompileError; 37 | // webAssemblyLinkError: WebAssembly.LinkError; 38 | // webAssemblyRuntimeError: WebAssembly.RuntimeError; 39 | // webAssemblyInstance: WebAssembly.Instance; 40 | // webAssemblyMemory: WebAssembly.Memory; 41 | // webAssemblyModule: WebAssembly.Module; 42 | }; 43 | 44 | export interface BuiltInInterface { 45 | date: Date; 46 | set: Set; 47 | map: Map; 48 | array: Array; 49 | object: Object; 50 | string: String; 51 | number: Number; 52 | boolean: Boolean; 53 | symbol: Symbol; 54 | function: Function; 55 | regexp: RegExp; 56 | error: Error; 57 | promise: Promise; 58 | arrayBuffer: ArrayBuffer; 59 | dataView: DataView; 60 | int8Array: Int8Array; 61 | uint8Array: Uint8Array; 62 | uint8ClampedArray: Uint8ClampedArray; 63 | int16Array: Int16Array; 64 | uint16Array: Uint16Array; 65 | int32Array: Int32Array; 66 | uint32Array: Uint32Array; 67 | float32Array: Float32Array; 68 | float64Array: Float64Array; 69 | bigInt64Array: BigInt64Array; 70 | bigUint64Array: BigUint64Array; 71 | mapIterator: IterableIterator<[string, number]>; 72 | setIterator: IterableIterator; 73 | arrayIterator: IterableIterator; 74 | stringIterator: IterableIterator; 75 | sharedArrayBuffer: SharedArrayBuffer; 76 | atomics: Atomics; 77 | // TODO 78 | // webAssembly: typeof WebAssembly; 79 | // webAssemblyCompileError: WebAssembly.CompileError; 80 | // webAssemblyLinkError: WebAssembly.LinkError; 81 | // webAssemblyRuntimeError: WebAssembly.RuntimeError; 82 | // webAssemblyInstance: WebAssembly.Instance; 83 | // webAssemblyMemory: WebAssembly.Memory; 84 | // webAssemblyModule: WebAssembly.Module; 85 | } 86 | 87 | export class BuiltInClass { 88 | constructor( 89 | public date: Date, 90 | public set: Set, 91 | public map: Map, 92 | public array: Array, 93 | public object: Object, 94 | public string: String, 95 | public number: Number, 96 | public boolean: Boolean, 97 | public symbol: Symbol, 98 | public function_class: Function, 99 | public regexp: RegExp, 100 | public error: Error, 101 | public promise: Promise, 102 | public arrayBuffer: ArrayBuffer, 103 | public dataView: DataView, 104 | public int8Array: Int8Array, 105 | public uint8Array: Uint8Array, 106 | public uint8ClampedArray: Uint8ClampedArray, 107 | // public int16Array: Int16Array, 108 | // public uint16Array: Uint16Array, 109 | // public int32Array: Int32Array, 110 | // public uint32Array: Uint32Array, 111 | // public float32Array: Float32Array, 112 | // public float64Array: Float64Array, 113 | // public bigInt64Array: BigInt64Array, 114 | // public bigUint64Array: BigUint64Array, 115 | public mapIterator: IterableIterator<[string, number]>, 116 | public setIterator: IterableIterator, 117 | public arrayIterator: IterableIterator, 118 | public stringIterator: IterableIterator, 119 | public sharedArrayBuffer: SharedArrayBuffer, 120 | public atomics: Atomics, 121 | 122 | // TODO 123 | // webAssembly: typeof WebAssembly; 124 | // webAssemblyCompileError: WebAssembly.CompileError; 125 | // webAssemblyLinkError: WebAssembly.LinkError; 126 | // webAssemblyRuntimeError: WebAssembly.RuntimeError; 127 | // webAssemblyInstance: WebAssembly.Instance; 128 | // webAssemblyMemory: WebAssembly.Memory; 129 | // webAssemblyModule: WebAssembly.Module; 130 | ) {} 131 | } 132 | -------------------------------------------------------------------------------- /.github/workflows/CI.yml: -------------------------------------------------------------------------------- 1 | # name: CI 2 | # env: 3 | # DEBUG: napi:* 4 | # APP_NAME: boostest 5 | # MACOSX_DEPLOYMENT_TARGET: '10.13' 6 | # permissions: 7 | # contents: write 8 | # id-token: write 9 | # 'on': 10 | # push: 11 | # branches: 12 | # - main 13 | # tags-ignore: 14 | # - '**' 15 | # paths-ignore: 16 | # - '**/*.md' 17 | # - LICENSE 18 | # - '**/*.gitignore' 19 | # - .editorconfig 20 | # - docs/** 21 | # pull_request: null 22 | # jobs: 23 | # build: 24 | # strategy: 25 | # fail-fast: false 26 | # matrix: 27 | # settings: 28 | # - host: macos-latest 29 | # target: x86_64-apple-darwin 30 | # build: pnpm --filter boostest build --target x86_64-apple-darwin 31 | # - host: windows-latest 32 | # build: pnpm --filter boostest build --target x86_64-pc-windows-msvc 33 | # target: x86_64-pc-windows-msvc 34 | # - host: ubuntu-latest 35 | # target: x86_64-unknown-linux-gnu 36 | # docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian 37 | # build: pnpm --filter boostest --target x86_64-unknown-linux-gnu 38 | # name: stable - ${{ matrix.settings.target }} - node@20 39 | # runs-on: ${{ matrix.settings.host }} 40 | # steps: 41 | # - uses: actions/checkout@v4 42 | # - name: setup pnpm 43 | # uses: pnpm/action-setup@v2 44 | # - name: Setup node 45 | # uses: actions/setup-node@v4 46 | # with: 47 | # node-version: 20 48 | # cache: pnpm 49 | # - name: Install 50 | # uses: dtolnay/rust-toolchain@stable 51 | # with: 52 | # toolchain: stable 53 | # targets: ${{ matrix.settings.target }} 54 | # - name: Cache cargo 55 | # uses: actions/cache@v4 56 | # with: 57 | # path: | 58 | # packages/boostest/.cargo/registry/index/ 59 | # packages/boostest/.cargo/registry/cache/ 60 | # packages/boostest/.cargo/git/db/ 61 | # packages/boostest/.napi-rs 62 | # packages/boostest/.cargo-cache 63 | # packages/boostest/target/ 64 | # key: ${{ matrix.settings.target }}-cargo-${{ matrix.settings.host }} 65 | # - uses: goto-bus-stop/setup-zig@v2 66 | # if: ${{ contains(matrix.settings.target, 'musl') }} 67 | # with: 68 | # version: 0.12.0 69 | # - name: Setup toolchain 70 | # run: ${{ matrix.settings.setup }} 71 | # if: ${{ matrix.settings.setup }} 72 | # shell: bash 73 | # - name: Install dependencies 74 | # run: pnpm install --no-frozen-lockfile 75 | # - name: Setup node x86 76 | # uses: actions/setup-node@v4 77 | # if: matrix.settings.target == 'i686-pc-windows-msvc' 78 | # with: 79 | # node-version: 20 80 | # cache: pnpm 81 | # architecture: x86 82 | # - name: Build 83 | # run: ${{ matrix.settings.build }} 84 | # shell: bash 85 | # - name: Upload artifact 86 | # uses: actions/upload-artifact@v4 87 | # with: 88 | # name: bindings-${{ matrix.settings.target }} 89 | # path: packages/boostest/${{ env.APP_NAME }}.*.node 90 | # if-no-files-found: error 91 | # publish: 92 | # name: Publish 93 | # runs-on: ubuntu-latest 94 | # needs: 95 | # - build 96 | # steps: 97 | # - uses: actions/checkout@v4 98 | # - name: setup pnpm 99 | # uses: pnpm/action-setup@v2 100 | # - name: Setup node 101 | # uses: actions/setup-node@v4 102 | # with: 103 | # node-version: 20 104 | # cache: pnpm 105 | # - name: Install dependencies 106 | # run: pnpm install --no-frozen-lockfile 107 | # - name: Download all artifacts 108 | # uses: actions/download-artifact@v4 109 | # with: 110 | # path: artifacts 111 | # - name: create npm dirs 112 | # run: pnpm --filter boostest napi create-npm-dirs 113 | # - name: Move artifacts 114 | # run: pnpm --filter boostest artifacts 115 | # - name: List packages 116 | # run: ls -R packages/boostest/npm 117 | # shell: bash 118 | # - name: Publish 119 | # run: | 120 | # npm config set provenance true 121 | # if git log -1 --pretty=%B | grep "^[0-9]\+\.[0-9]\+\.[0-9]\+$"; 122 | # then 123 | # echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc 124 | # npm publish --access public 125 | # elif git log -1 --pretty=%B | grep "^[0-9]\+\.[0-9]\+\.[0-9]\+"; 126 | # then 127 | # echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc 128 | # npm publish --tag next --access public 129 | # else 130 | # echo "Not a release, skipping publish" 131 | # fi 132 | # env: 133 | # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 134 | # NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 135 | -------------------------------------------------------------------------------- /apps/test/src/types/ts_types/generics.ts: -------------------------------------------------------------------------------- 1 | import { RefType } from "@/ts_types/utils"; 2 | 3 | class SimpleClass { 4 | name: string; 5 | ver: number; 6 | constructor(name: string, ver: number) { 7 | this.name = name; 8 | this.ver = ver; 9 | } 10 | } 11 | 12 | export type InngerGeneric = T; 13 | export type InngerPropGeneric = { 14 | name: T; 15 | }; 16 | 17 | type InnerGenericInitializer = { 18 | name: string; 19 | innerGeneric: InngerGeneric; 20 | innerGenericLiteral: InngerGeneric<"inner generic string">; 21 | }; 22 | 23 | type SystemSupportLanguage = "en" | "fr" | "it" | "es"; 24 | 25 | type Butterfly = { 26 | [key in SystemSupportLanguage]: string; 27 | }; 28 | 29 | type ButterflyWithGenerics = { 30 | [key in SystemSupportLanguage]: T; 31 | }; 32 | 33 | type KeyOfButterfly = { 34 | [key in keyof RefType]: RefType[key]; 35 | }; 36 | 37 | type OnDirectRefUnionType = T extends SystemSupportLanguage ? T : never; 38 | 39 | export type GenericsTypeAlias = { 40 | mapperType: Butterfly; 41 | keyOfMapperType: KeyOfButterfly; 42 | innserGenericInitializer: InnerGenericInitializer; 43 | butterflyWithGenerics: ButterflyWithGenerics; 44 | nonNullable: NonNullable; 45 | nestedPartial: { 46 | childPartial: Partial; 47 | }; 48 | partial: Partial; 49 | required: Required; 50 | readonly: Readonly; 51 | extract: Extract<"A" | "B" | "C" | "D" | "E", "D" | "E">; 52 | extractRefUnion: Extract; 53 | exclude: Exclude; 54 | onDirectRefUnionType: OnDirectRefUnionType<"fr">; 55 | array: Array; 56 | pick: Pick; 57 | pickMulti: Pick; 58 | omit: Omit; 59 | record: Record; 60 | parameters: Parameters<(name: string, age: number) => void>; 61 | returnType: ReturnType<() => RefType>; 62 | instanceType: InstanceType; 63 | constructorParameters: ConstructorParameters; 64 | promise: Promise; 65 | 66 | /**********************/ 67 | /******* TODO: *******/ 68 | /**********************/ 69 | 70 | // thisType: ThisType; 71 | }; 72 | 73 | type Grade = "A" | "B" | "C" | "D" | "E"; 74 | 75 | export type GenericsInterface = { 76 | innserGenericInitializer: InnerGenericInitializer; 77 | mapperType: Butterfly; 78 | keyOfMapperType: KeyOfButterfly; 79 | butterflyWithGenerics: ButterflyWithGenerics; 80 | nonNullable: NonNullable; 81 | nestedPartial: { 82 | childPartial: Partial; 83 | }; 84 | partial: Partial; 85 | required: Required; 86 | readonly: Readonly; 87 | extract: Extract<"A" | "B" | "C" | "D" | "E", "D" | "E">; 88 | extractRefUnion: Extract; 89 | exclude: Exclude; 90 | onDirectRefUnionType: OnDirectRefUnionType<"fr">; 91 | array: Array; 92 | pick: Pick; 93 | pickMulti: Pick; 94 | omit: Omit; 95 | record: Record; 96 | parameters: Parameters<(name: string, age: number) => void>; 97 | returnType: ReturnType<() => RefType>; 98 | instanceType: InstanceType; 99 | constructorParameters: ConstructorParameters; 100 | promise: Promise; 101 | 102 | /**********************/ 103 | /******* TODO: *******/ 104 | /**********************/ 105 | // thisType: ThisType; 106 | }; 107 | 108 | export class GenericsClass { 109 | constructor( 110 | public innserGenericInitializer: InnerGenericInitializer, 111 | public mapperType: Butterfly, 112 | public keyOfMapperType: KeyOfButterfly, 113 | public butterflyWithGenerics: ButterflyWithGenerics, 114 | public nonNullable: NonNullable, 115 | public nestedPartial: { 116 | childPartial: Partial; 117 | }, 118 | public partial: Partial, 119 | public required: Required, 120 | public readonly: Readonly, 121 | public extract: Extract<"A" | "B" | "C" | "D" | "E", "D" | "E">, 122 | public extractRefUnion: Extract, 123 | public exclude: Exclude, 124 | public onDirectRefUnionType: OnDirectRefUnionType<"fr">, 125 | public array: Array, 126 | public pick: Pick, 127 | public pickMulti: Pick, 128 | public omit: Omit, 129 | public record: Record, 130 | public parameters: Parameters<(name: string, age: number) => void>, 131 | public returnType: ReturnType<() => RefType>, 132 | public instanceType: InstanceType, 133 | public constructorParameters: ConstructorParameters, 134 | public promise: Promise, 135 | 136 | /**********************/ 137 | /******* TODO: *******/ 138 | /**********************/ 139 | // public thisType: ThisType, 140 | ) {} 141 | } 142 | -------------------------------------------------------------------------------- /packages/boostest/bin/cli.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { 4 | OutputCode, 5 | resolve, 6 | generatetest as generate, 7 | TargetType, 8 | } from "../index"; 9 | import { inferTsAlias } from "./inferTsAlias"; 10 | import yargs from "yargs"; 11 | import { hideBin } from "yargs/helpers"; 12 | import ts from "typescript"; 13 | import path from "path"; 14 | import fs from "fs"; 15 | 16 | const newFileName = "lib.es5.d.ts"; 17 | let defaultLibFilePath = ts.getDefaultLibFilePath({} as ts.CompilerOptions); 18 | // WARN: Maybe es5 or higher is needed. 19 | const libFilePath = path.join(path.dirname(defaultLibFilePath), newFileName); 20 | 21 | // const path = process.argv[2]; // 0: node, 1: スクリプト名, 2: 引数 22 | // if (path) { 23 | // boostest(path); 24 | // } else { 25 | // boostest(''); 26 | // } 27 | 28 | const initialSettingFile = ` 29 | { 30 | "target_pattern": ["src/**/*.ts"], 31 | "name": "boostest", 32 | "tsconfig": "./tsconfig.json", 33 | "output": { 34 | "single": true 35 | }, 36 | "initial_value": { 37 | "string": "init string value", 38 | "number": 10000, 39 | "bigint": "556455199254740991n", 40 | "any": "any value" 41 | } 42 | } 43 | `; 44 | 45 | type Output = Record; 46 | 47 | const infferTypes = (result: Output): Output => { 48 | let codeRecord: Output = {}; 49 | 50 | for (const [key, value] of Object.entries(result)) { 51 | let types; 52 | types = inferTsAlias(value.code); 53 | 54 | if (types) { 55 | codeRecord[key] = { 56 | code: types, 57 | path: value.path, 58 | targetType: value.targetType, 59 | }; 60 | } 61 | } 62 | 63 | return codeRecord; 64 | }; 65 | 66 | yargs(hideBin(process.argv)) 67 | .scriptName("") 68 | .usage("ex) boostest ./target_file_path.ts -t ./tsconfig.json") 69 | .option("tsconfig", { 70 | alias: "t", 71 | type: "string", 72 | description: "tsconfig.json path", 73 | }) 74 | .command( 75 | "init", 76 | "Create boostest.setting.json", 77 | () => {}, 78 | (argv) => { 79 | // boostest initコマンド時にboostest.setting.jsonを生成 80 | const fileName = "boostest.setting.json"; 81 | 82 | if (!fs.existsSync(fileName)) { 83 | fs.writeFileSync(fileName, initialSettingFile); 84 | 85 | console.log(`Created ${fileName}`); 86 | } else { 87 | console.log(`${fileName} already exists. Skipping creation.`); 88 | } 89 | }, 90 | ) 91 | .command( 92 | "* [target_file_path]", 93 | "", 94 | (yargs) => { 95 | return yargs.positional("target_file_path", { 96 | describe: "Path to the target files", 97 | type: "string", 98 | demandOption: false, 99 | }); 100 | }, 101 | (argv) => { 102 | var black = "\u001b[30m"; 103 | var red = "\u001b[31m"; 104 | var green = "\u001b[32m"; 105 | var yellow = "\u001b[33m"; 106 | var blue = "\u001b[34m"; 107 | var magenta = "\u001b[35m"; 108 | var cyan = "\u001b[36m"; 109 | var white = "\u001b[37m"; 110 | 111 | var reset = "\u001b[0m"; 112 | 113 | const path = argv.target_file_path; 114 | const tsconfig = argv.tsconfig; 115 | 116 | if (!path && !tsconfig) { 117 | console.log(blue + "arguments are not set." + reset); 118 | console.log(blue + "boostest with boostest.setting.json" + reset); 119 | let { outputCode, outputOption } = resolve("", libFilePath); 120 | if (outputCode) { 121 | const output = infferTypes(outputCode); 122 | generate(output, outputOption); 123 | } 124 | return; 125 | } 126 | 127 | if (!path && tsconfig) { 128 | console.log(blue + "target is not set." + reset); 129 | console.log( 130 | blue + `boostest with boostest.setting.json with ${tsconfig}` + reset, 131 | ); 132 | let { outputCode, outputOption } = resolve("", libFilePath, tsconfig); 133 | 134 | if (outputCode) { 135 | const output = infferTypes(outputCode); 136 | generate(output, outputOption); 137 | } 138 | return; 139 | } 140 | 141 | if (path && !tsconfig) { 142 | console.log(blue + `target file: ${path}` + reset); 143 | console.log(blue + "tsconfig is not set." + reset); 144 | console.log(blue + "boostest with boostest.setting.json" + reset); 145 | let { outputCode, outputOption } = resolve(path, libFilePath); 146 | 147 | if (outputCode) { 148 | const output = infferTypes(outputCode); 149 | generate(output, outputOption); 150 | } 151 | return; 152 | } 153 | 154 | if (path && tsconfig) { 155 | console.log(blue + `target file: ${path}` + reset); 156 | console.log(blue + `tsconfig: ${tsconfig}` + reset); 157 | let { outputCode, outputOption } = resolve(path, libFilePath, tsconfig); 158 | if (outputCode) { 159 | const output = infferTypes(outputCode); 160 | generate(output, outputOption); 161 | } 162 | 163 | return; 164 | } 165 | 166 | console.error( 167 | red + 168 | "Invalid arguments. Please check the usage with `--help`." + 169 | reset, 170 | ); 171 | }, 172 | ) 173 | .help("help") 174 | .parse(); 175 | -------------------------------------------------------------------------------- /apps/test/src/direct_path/__snapshots__/direct_path.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`boostest direct path output correctly 1`] = ` 4 | "function isNullOrUndefined(value) { 5 | return value === undefined || value === null; 6 | } 7 | function emptyObj(value) { 8 | if (isNullOrUndefined(value)) return false; 9 | return typeof value === "object" && Object.keys(value).length === 0; 10 | } 11 | function intersectionUtil(...args) { 12 | let values = args; 13 | // If it includes {}, filter out null and undefined, and also remove {} 14 | const includesEmptyObj = values.some((val) => emptyObj(val)); 15 | 16 | if (includesEmptyObj) { 17 | values = values.filter((val) => !isNullOrUndefined(val) && !emptyObj(val)); 18 | } 19 | 20 | if (values.length === 0) return null; 21 | // null or undefined cannot match, so treat as "never" (return null) 22 | if (values.some((val) => isNullOrUndefined(val))) { 23 | return null; 24 | } 25 | 26 | if (values.length === 1) return values[0]; 27 | 28 | const firstType = typeof values[0]; 29 | const isSameType = values.every((value) => typeof value === firstType); 30 | 31 | // Different types cannot be handled, so treat as "never" (return null) 32 | if (!isSameType) return null; 33 | 34 | if (firstType === "object" && values.every((value) => value !== null)) { 35 | return values.reduce((acc, value) => ({ ...acc, ...value }), {}); 36 | } 37 | 38 | return values[0]; 39 | } 40 | function ensureArray(input: T | T[]): T[] { 41 | return Array.isArray(input) ? input : [input]; 42 | } 43 | 44 | function arraysEqual(arr1: any, arr2: any) { 45 | if (!Array.isArray(arr1) || !Array.isArray(arr2)) return false; 46 | if (arr1.length !== arr2.length) return false; 47 | for (let i = 0; i < arr1.length; i++) { 48 | if (arr1[i] !== arr2[i]) return false; 49 | } 50 | return true; 51 | } 52 | 53 | function isAssignableTo(value: any, typeShape: any) { 54 | // プリミティブ型またはリテラル値のチェック 55 | if (typeof typeShape !== "object" || typeShape === null) { 56 | return ( 57 | value === typeShape || 58 | typeof value === typeShape || 59 | // WARN: Cannot compare different string types such as 'hoge', 'fuga' 60 | typeof value === typeof typeShape 61 | ); 62 | } 63 | 64 | // オブジェクト型のチェック 65 | if (typeof value !== "object" || value === null) { 66 | return false; 67 | } 68 | 69 | // ネストされたプロパティを再帰的にチェック 70 | return Object.keys(typeShape).every((key): boolean => { 71 | if (!(key in value)) return false; // プロパティが存在しない場合は false 72 | return isAssignableTo(value[key], typeShape[key]); 73 | }); 74 | } 75 | function extendsUtil( 76 | value: any, 77 | typeShape: any, 78 | trueVal: any, 79 | falseVal: any, 80 | isArray = false, 81 | ): any { 82 | const isValueArray = Array.isArray(value); 83 | const isTypeShapeArray = Array.isArray(typeShape); 84 | 85 | const arrayValue = ensureArray(value); 86 | const arrayTypeShape = ensureArray(typeShape); 87 | const arrayTrueVal = ensureArray(trueVal); 88 | const arrayFalseVal = ensureArray(falseVal); 89 | 90 | const tutn = arraysEqual(arrayValue, arrayTrueVal); // T extends U ? T : never 91 | const tunt = arraysEqual(arrayValue, arrayFalseVal); // T extends U ? never : T 92 | const tunu = arraysEqual(arrayTypeShape, arrayTrueVal); // T extends U ? never : U 93 | const tuun = arraysEqual(arrayTypeShape, arrayFalseVal); // T extends U ? U : never 94 | const otherVal = !tutn && !tunt && !tunu && !tuun; 95 | 96 | let resultArray: any[] = []; 97 | 98 | // ユニオン型の場合、配列の各要素をチェック 99 | if (isValueArray || isTypeShapeArray) { 100 | // Extract<"A"|"B"|"C", "A"|"B"> 101 | if (tutn) { 102 | resultArray = arrayValue.filter((val) => arrayTypeShape.includes(val)); 103 | } else if (tunt) { 104 | resultArray = arrayValue.filter((val) => !arrayTypeShape.includes(val)); 105 | } else if (tunu) { 106 | resultArray = arrayTypeShape.filter((val) => !arrayValue.includes(val)); 107 | } else if (tuun) { 108 | resultArray = arrayTypeShape.filter((val) => arrayValue.includes(val)); 109 | } 110 | 111 | if (otherVal) { 112 | if (resultArray.length === 0) { 113 | return falseVal; 114 | } else { 115 | return trueVal; 116 | } 117 | } 118 | 119 | return isArray ? resultArray : resultArray[0]; 120 | } 121 | 122 | return isAssignableTo(value, typeShape) ? trueVal : falseVal; 123 | } 124 | const isArray = false; 125 | 126 | function getFirstNonNullOrUndefined(arr: any[]): any { 127 | // Step 1: Filter out undefined and null values 128 | const filteredArray = arr.filter( 129 | (item) => item !== undefined && item !== null, 130 | ); 131 | 132 | // Step 2: Check if the filtered array is not empty 133 | if (filteredArray.length > 0) { 134 | // Step 3: Return the first element of the filtered array 135 | return filteredArray[0]; 136 | } else { 137 | // Step 4: Return the first undefined or null element from the original array 138 | return arr.find((item) => item === undefined || item === null); 139 | } 140 | } 141 | 142 | function getUnionValue(a: any, isArray = false) { 143 | return isArray ? a : getFirstNonNullOrUndefined(a); 144 | } 145 | export function boostestTsTypeLiteralString(isArray = false) { 146 | return "test string data"; 147 | } 148 | 149 | " 150 | `; 151 | -------------------------------------------------------------------------------- /apps/test/src/types/ts_types/ts_type_literal.ts: -------------------------------------------------------------------------------- 1 | export interface UseTSTypeLiteralInterface { 2 | literalString: TsTypeLiteralString; 3 | literalLiteralString: TsTypeLiteralLiteralTypeString; 4 | literalStringUnion: TsLiteralTypeStringUnionType; 5 | literalNumber: TsTypeLiteralNumber; 6 | literalLiteralNumber: TsTypeLiteralLiteralNumberType; 7 | literalNumberUnion: TsLiteralNumberUnionType; 8 | literalBoolean: TsTypeLiteralBoolean; 9 | literalLiteralBoolean: TsTypeLiteralLiteralBooleanType; 10 | literalBooleanUnion: TsLiteralBooleanUnionType; 11 | literalNull: TsTypeLiteralNull; 12 | literalUndefined: TsTypeLiteralUndefined; 13 | literalArray: TsTypeLiteralArray; 14 | literalLiteralArray: TsTypeLiteralLiteralArrayType; 15 | literalArrayUnion: TsLiteralArrayUnionType; 16 | literalObject: TsTypeLiteralObject; 17 | literalLiteralObject: TsTypeLiteralLiteralObjectType; 18 | literalObjectUnion: TsLiteralObjectUnionType; 19 | literalFunction: TsTypeLiteralFunction; 20 | literalLiteralFunction: TsTypeLiteralLiteralFunctionType; 21 | literalFunctionUnion: TsLiteralFunctionUnionType; 22 | literalBigInt: TsTypeLiteralBigInt; 23 | literalLiteralBigInt: TsTypeLiteralLiteralBigIntType; 24 | literalBigIntUnion: TsLiteralBigIntUnionType; 25 | literalSymbol: TsTypeLiteralSymbol; 26 | // literalLiteralSymbol: TsTypeLiteralLiteralSymbolType; 27 | } 28 | 29 | export type UseTSTypeLiteralAlias = { 30 | literalString: TsTypeLiteralString; 31 | literalLiteralString: TsTypeLiteralLiteralTypeString; 32 | literalStringUnion: TsLiteralTypeStringUnionType; 33 | literalNumber: TsTypeLiteralNumber; 34 | literalLiteralNumber: TsTypeLiteralLiteralNumberType; 35 | literalNumberUnion: TsLiteralNumberUnionType; 36 | literalBoolean: TsTypeLiteralBoolean; 37 | literalLiteralBoolean: TsTypeLiteralLiteralBooleanType; 38 | literalBooleanUnion: TsLiteralBooleanUnionType; 39 | literalNull: TsTypeLiteralNull; 40 | literalUndefined: TsTypeLiteralUndefined; 41 | literalArray: TsTypeLiteralArray; 42 | literalLiteralArray: TsTypeLiteralLiteralArrayType; 43 | literalArrayUnion: TsLiteralArrayUnionType; 44 | literalObject: TsTypeLiteralObject; 45 | literalLiteralObject: TsTypeLiteralLiteralObjectType; 46 | literalObjectUnion: TsLiteralObjectUnionType; 47 | literalFunction: TsTypeLiteralFunction; 48 | literalLiteralFunction: TsTypeLiteralLiteralFunctionType; 49 | literalFunctionUnion: TsLiteralFunctionUnionType; 50 | literalBigInt: TsTypeLiteralBigInt; 51 | literalLiteralBigInt: TsTypeLiteralLiteralBigIntType; 52 | literalBigIntUnion: TsLiteralBigIntUnionType; 53 | literalSymbol: TsTypeLiteralSymbol; 54 | // literalLiteralSymbol: TsTypeLiteralLiteralSymbolType; 55 | }; 56 | 57 | // String Literal Types 58 | export type TsTypeLiteralString = string; // General string type, can hold any string value 59 | export type TsTypeLiteralLiteralTypeString = "string"; // Specific string literal type, can only hold the value 'string' 60 | export type TsLiteralTypeStringUnionType = "A" | "B" | "C"; // Union of specific string literals, can hold 'A', 'B', or 'C' 61 | 62 | // Number Literal Types 63 | export type TsTypeLiteralNumber = number; // General number type, can hold any number value 64 | export type TsTypeLiteralLiteralNumberType = 42; // Specific number literal type, can only hold the value 42 65 | export type TsLiteralNumberUnionType = 1 | 2 | 3; // Union of specific number literals, can hold 1, 2, or 3 66 | 67 | // Boolean Literal Types 68 | export type TsTypeLiteralBoolean = boolean; // General boolean type, can hold true or false 69 | export type TsTypeLiteralLiteralBooleanType = true; // Specific boolean literal type, can only hold the value true 70 | export type TsLiteralBooleanUnionType = true | false; // Union of boolean literals, can hold true or false 71 | 72 | // Null Literal Type 73 | export type TsTypeLiteralNull = null; // Specific type for the null value 74 | 75 | // Undefined Literal Type 76 | export type TsTypeLiteralUndefined = undefined; // Specific type for the undefined value 77 | 78 | // Array Literal Types 79 | export type TsTypeLiteralArray = any[]; // General array type, can hold any array 80 | export type TsTypeLiteralLiteralArrayType = [1, 2, 3]; // Specific array literal type, can only hold the array [1, 2, 3] 81 | export type TsLiteralArrayUnionType = [] | [1] | [1, 2]; // Union of specific array literals, can hold [], [1], or [1, 2] 82 | 83 | // Object Literal Types 84 | export type TsTypeLiteralObject = object; // General object type, can hold any object 85 | export type TsTypeLiteralLiteralObjectType = { name: string; age: number }; // Specific object literal type, can only hold an object with name (string) and age (number) properties 86 | export type TsLiteralObjectUnionType = 87 | | { type: "A" } 88 | | { type: "B"; value: number }; // Union of specific object literals, can hold either { type: 'A' } or { type: 'B', value: number } 89 | 90 | // Function Literal Types 91 | export type TsTypeLiteralFunction = Function; // General function type, can hold any function 92 | export type TsTypeLiteralLiteralFunctionType = () => void; // Specific function literal type, can only hold a function that takes no arguments and returns void 93 | export type TsLiteralFunctionUnionType = 94 | | ((x: number) => number) 95 | | ((x: string) => string); // Union of specific function literals, can hold a function that takes a number and returns a number, or a function that takes a string and returns a string 96 | 97 | // Other Literal Types 98 | export type TsTypeLiteralBigInt = bigint; // General bigint type, can hold any bigint value 99 | export type TsTypeLiteralLiteralBigIntType = 123n; // Specific bigint literal type, can only hold the value 123n 100 | export type TsLiteralBigIntUnionType = 1n | 2n | 3n; // Union of specific bigint literals, can hold 1n, 2n, or 3n 101 | 102 | // Symbol Literal Type 103 | const mySymbol = Symbol("mySymbol"); 104 | export type TsTypeLiteralSymbol = symbol; // General symbol type, can hold any symbol value 105 | export type TsTypeLiteralLiteralSymbolType = typeof mySymbol; // Specific symbol literal type, can only hold the symbol mySymbol 106 | -------------------------------------------------------------------------------- /apps/test/src/tests/literal/literal.spec.ts: -------------------------------------------------------------------------------- 1 | import { runSnapshotTest, failedTest } from "../utils"; 2 | import { 3 | // string 4 | TsTypeLiteralString, 5 | TsTypeLiteralLiteralTypeString, 6 | TsLiteralTypeStringUnionType, 7 | 8 | // number 9 | TsTypeLiteralNumber, 10 | TsTypeLiteralLiteralNumberType, 11 | TsLiteralNumberUnionType, 12 | 13 | // boolean 14 | TsTypeLiteralBoolean, 15 | TsTypeLiteralLiteralBooleanType, 16 | TsLiteralBooleanUnionType, 17 | 18 | // null 19 | TsTypeLiteralNull, 20 | 21 | // undefined 22 | TsTypeLiteralUndefined, 23 | 24 | // Array 25 | TsTypeLiteralArray, 26 | TsTypeLiteralLiteralArrayType, 27 | TsLiteralArrayUnionType, 28 | 29 | // Object 30 | TsTypeLiteralObject, 31 | TsTypeLiteralLiteralObjectType, 32 | TsLiteralObjectUnionType, 33 | 34 | // Function 35 | TsTypeLiteralFunction, 36 | TsTypeLiteralLiteralFunctionType, 37 | TsLiteralFunctionUnionType, 38 | 39 | // Symbol 40 | TsTypeLiteralSymbol, 41 | TsTypeLiteralLiteralSymbolType, 42 | 43 | // use 44 | UseTSTypeLiteralAlias, 45 | UseTSTypeLiteralInterface, 46 | } from "@/ts_types/ts_type_literal"; 47 | import { boostestTsTypeLiteralString } from "./boostest_output/boostestTsTypeLiteralString"; 48 | import { boostestTsTypeLiteralLiteralTypeString } from "./boostest_output/boostestTsTypeLiteralLiteralTypeString"; 49 | import { boostestTsLiteralTypeStringUnionType } from "./boostest_output/boostestTsLiteralTypeStringUnionType"; 50 | import { boostestTsTypeLiteralNumber } from "./boostest_output/boostestTsTypeLiteralNumber"; 51 | import { boostestTsTypeLiteralLiteralNumberType } from "./boostest_output/boostestTsTypeLiteralLiteralNumberType"; 52 | import { boostestTsLiteralNumberUnionType } from "./boostest_output/boostestTsLiteralNumberUnionType"; 53 | import { boostestTsTypeLiteralBoolean } from "./boostest_output/boostestTsTypeLiteralBoolean"; 54 | import { boostestTsTypeLiteralLiteralBooleanType } from "./boostest_output/boostestTsTypeLiteralLiteralBooleanType"; 55 | import { boostestTsLiteralBooleanUnionType } from "./boostest_output/boostestTsLiteralBooleanUnionType"; 56 | import { boostestTsTypeLiteralNull } from "./boostest_output/boostestTsTypeLiteralNull"; 57 | import { boostestTsTypeLiteralUndefined } from "./boostest_output/boostestTsTypeLiteralUndefined"; 58 | import { boostestUseTSTypeLiteralInterface } from "./boostest_output/boostestUseTSTypeLiteralInterface"; 59 | import { boostestUseTSTypeLiteralAlias } from "./boostest_output/boostestUseTSTypeLiteralAlias"; 60 | import { boostestTsTypeLiteralSymbol } from "./boostest_output/boostestTsTypeLiteralSymbol"; 61 | import { boostestTsLiteralFunctionUnionType } from "./boostest_output/boostestTsLiteralFunctionUnionType"; 62 | import { boostestTsTypeLiteralLiteralFunctionType } from "./boostest_output/boostestTsTypeLiteralLiteralFunctionType"; 63 | import { boostestTsTypeLiteralFunction } from "./boostest_output/boostestTsTypeLiteralFunction"; 64 | import { boostestTsLiteralObjectUnionType } from "./boostest_output/boostestTsLiteralObjectUnionType"; 65 | import { boostestTsTypeLiteralLiteralObjectType } from "./boostest_output/boostestTsTypeLiteralLiteralObjectType"; 66 | import { boostestTsTypeLiteralObject } from "./boostest_output/boostestTsTypeLiteralObject"; 67 | import { boostestTsLiteralArrayUnionType } from "./boostest_output/boostestTsLiteralArrayUnionType"; 68 | import { boostestTsTypeLiteralLiteralArrayType } from "./boostest_output/boostestTsTypeLiteralLiteralArrayType"; 69 | import { boostestTsTypeLiteralArray } from "./boostest_output/boostestTsTypeLiteralArray"; 70 | 71 | describe("Literal Type Tests", () => { 72 | runSnapshotTest( 73 | "TsTypeLiteralString", 74 | boostestTsTypeLiteralString(), 75 | ); 76 | runSnapshotTest( 77 | "TsTypeLiteralLiteralTypeString", 78 | boostestTsTypeLiteralLiteralTypeString(), 79 | ); 80 | runSnapshotTest( 81 | "TsLiteralTypeStringUnionType", 82 | boostestTsLiteralTypeStringUnionType(), 83 | ); 84 | runSnapshotTest( 85 | "TsTypeLiteralNumber", 86 | boostestTsTypeLiteralNumber(), 87 | ); 88 | runSnapshotTest( 89 | "TsTypeLiteralLiteralNumberType", 90 | boostestTsTypeLiteralLiteralNumberType(), 91 | ); 92 | runSnapshotTest( 93 | "TsLiteralNumberUnionType", 94 | boostestTsLiteralNumberUnionType(), 95 | ); 96 | runSnapshotTest( 97 | "TsTypeLiteralBoolean", 98 | boostestTsTypeLiteralBoolean(), 99 | ); 100 | runSnapshotTest( 101 | "TsTypeLiteralLiteralBooleanType", 102 | boostestTsTypeLiteralLiteralBooleanType(), 103 | ); 104 | runSnapshotTest( 105 | "TsLiteralBooleanUnionType", 106 | boostestTsLiteralBooleanUnionType(), 107 | ); 108 | runSnapshotTest( 109 | "TsTypeLiteralNull", 110 | boostestTsTypeLiteralNull(), 111 | ); 112 | runSnapshotTest( 113 | "TsTypeLiteralUndefined", 114 | boostestTsTypeLiteralUndefined(), 115 | ); 116 | runSnapshotTest( 117 | "TsTypeLiteralArray", 118 | boostestTsTypeLiteralArray(), 119 | ); 120 | runSnapshotTest( 121 | "TsTypeLiteralLiteralArrayType", 122 | boostestTsTypeLiteralLiteralArrayType(), 123 | ); 124 | runSnapshotTest( 125 | "TsLiteralArrayUnionType", 126 | boostestTsLiteralArrayUnionType(), 127 | ); 128 | runSnapshotTest( 129 | "TsTypeLiteralObject", 130 | boostestTsTypeLiteralObject(), 131 | ); 132 | runSnapshotTest( 133 | "TsTypeLiteralLiteralObjectType", 134 | boostestTsTypeLiteralLiteralObjectType(), 135 | ); 136 | runSnapshotTest( 137 | "TsLiteralObjectUnionType", 138 | boostestTsLiteralObjectUnionType(), 139 | ); 140 | runSnapshotTest( 141 | "TsTypeLiteralFunction", 142 | boostestTsTypeLiteralFunction(), 143 | ); 144 | runSnapshotTest( 145 | "TsTypeLiteralLiteralFunctionType", 146 | boostestTsTypeLiteralLiteralFunctionType(), 147 | ); 148 | runSnapshotTest( 149 | "TsLiteralFunctionUnionType", 150 | boostestTsLiteralFunctionUnionType(), 151 | ); 152 | runSnapshotTest( 153 | "TsTypeLiteralSymbol", 154 | boostestTsTypeLiteralSymbol(), 155 | ); 156 | runSnapshotTest( 157 | "TsTypeLiteralAlias", 158 | boostestUseTSTypeLiteralAlias(), 159 | ); 160 | runSnapshotTest( 161 | "TsTypeLiteralInterface", 162 | boostestUseTSTypeLiteralInterface(), 163 | ); 164 | 165 | // failedTest("TsTypeLiteralLiteralSymbol"); 166 | }); 167 | -------------------------------------------------------------------------------- /apps/test/src/tests/various_export_impot/various_export_import.spec.ts: -------------------------------------------------------------------------------- 1 | import { runSnapshotTest } from "../utils"; 2 | 3 | import { ComplexChipsType } from "../../types/export_decl"; 4 | import AnoExportDefaultInterface from "../../types/export_default_interface"; 5 | import AnoExportDefaultClass from "../../types/export_default_class"; 6 | import ExportDefaultClass from "../../types/export_default_class"; 7 | import ExportDefaultClassWithDecl from "../../types/export_default_class_with_decl"; 8 | import { ExportNamedDecl } from "../../types/export_named_decl"; 9 | import ExportDefaultNamedDecl from "../../types/export_default_named_decl"; 10 | import { AnoExportNamedDeclInterface } from "../../types/export_named_decl_interface"; 11 | import { AnoExportNamedDeclClass } from "../../types/export_named_decl_class"; 12 | import Mix, { MixCompTSAlias } from "../../types/mix"; 13 | import MixInterfaceSecond, { 14 | MixInterfaceFirst, 15 | } from "../../types/mix_default_normal/mix_interface"; 16 | import MixInterfaceFirst2, { 17 | MixInterfaceSecond2, 18 | } from "../../types/mix_default_normal/mix_interface2"; 19 | import MixTSAliasSecond, { 20 | MixTSAliasFirst, 21 | } from "../../types/mix_default_normal/mix_ts_alias"; 22 | import MixTSAliasSecond2, { 23 | MixTSAliasFirst2, 24 | } from "../../types/mix_default_normal/mix_ts_alias2"; 25 | import MixClassFirst, { 26 | MixClassSecond, 27 | } from "../../types/mix_default_normal/mix_class"; 28 | import MixClassFirst2, { 29 | MixClassSecond2, 30 | } from "../../types/mix_default_normal/mix_class2"; 31 | import { AccessorClass } from "../../types/pattern/accessor_class"; 32 | import { Hoge } from "../../types/ts_types"; 33 | 34 | import { boostestComplexChipsType } from "./boostest_output/boostestComplexChipsType"; 35 | import { boostestAnoExportDefaultInterface } from "./boostest_output/boostestAnoExportDefaultInterface"; 36 | import { boostestAnoExportDefaultClass } from "./boostest_output/boostestAnoExportDefaultClass"; 37 | import { boostestExportDefaultClass } from "./boostest_output/boostestExportDefaultClass"; 38 | import { boostestExportDefaultClassWithDecl } from "./boostest_output/boostestExportDefaultClassWithDecl"; 39 | import { boostestExportNamedDecl } from "./boostest_output/boostestExportNamedDecl"; 40 | import { boostestExportDefaultNamedDecl } from "./boostest_output/boostestExportDefaultNamedDecl"; 41 | import { boostestExportNamedDeclInterface } from "./boostest_output/boostestExportNamedDeclInterface"; 42 | import { boostestAnoMixInterface } from "./boostest_output/boostestAnoMixInterface"; 43 | import { boostestMixCompTSAlias } from "./boostest_output/boostestMixCompTSAlias"; 44 | import { boostestMixInterfaceFirst } from "./boostest_output/boostestMixInterfaceFirst"; 45 | import { boostestMixInterfaceSecond } from "./boostest_output/boostestMixInterfaceSecond"; 46 | import { boostestMixInterfaceFirst2 } from "./boostest_output/boostestMixInterfaceFirst2"; 47 | import { boostestMixInterfaceSecond2 } from "./boostest_output/boostestMixInterfaceSecond2"; 48 | import { boostestMixTSAliasFirst } from "./boostest_output/boostestMixTSAliasFirst"; 49 | import { boostestMixTSAliasSecond } from "./boostest_output/boostestMixTSAliasSecond"; 50 | import { boostestMixTSAliasFirst2 } from "./boostest_output/boostestMixTSAliasFirst2"; 51 | import { boostestMixTSAliasSecond2 } from "./boostest_output/boostestMixTSAliasSecond2"; 52 | import { boostestMixClassFirst } from "./boostest_output/boostestMixClassFirst"; 53 | import { boostestMixClassSecond } from "./boostest_output/boostestMixClassSecond"; 54 | import { boostestMixClassFirst2 } from "./boostest_output/boostestMixClassFirst2"; 55 | import { boostestMixClassSecond2 } from "./boostest_output/boostestMixClassSecond2"; 56 | import { boostestAccessorClass } from "./boostest_output/boostestAccessorClass"; 57 | import { boostestAnoExportNamedDeclClass } from "./boostest_output/boostestAnoExportNamedDeclClass"; 58 | import { boostestAllExport } from "./boostest_output/boostestAllExport"; 59 | 60 | describe("Various Export Methods Tests", () => { 61 | runSnapshotTest( 62 | "ComplexChipsType", 63 | boostestComplexChipsType(), 64 | ); 65 | 66 | runSnapshotTest( 67 | "AnoExportDefaultInterface", 68 | boostestAnoExportDefaultInterface({ 69 | name: "overridden", 70 | }), 71 | ); 72 | 73 | runSnapshotTest( 74 | "AnoExportDefaultClass", 75 | boostestAnoExportDefaultClass(), 76 | ); 77 | 78 | runSnapshotTest( 79 | "ExportDefaultClass", 80 | boostestExportDefaultClass(), 81 | ); 82 | 83 | runSnapshotTest( 84 | "ExportDefaultClassWithDecl", 85 | boostestExportDefaultClassWithDecl(), 86 | ); 87 | 88 | runSnapshotTest( 89 | "ExportNamedDecl", 90 | boostestExportNamedDecl(), 91 | ); 92 | 93 | runSnapshotTest( 94 | "ExportDefaultNamedDecl", 95 | boostestExportDefaultNamedDecl(), 96 | ); 97 | 98 | runSnapshotTest( 99 | "AnoExportNamedDeclInterface", 100 | boostestExportNamedDeclInterface(), 101 | ); 102 | 103 | runSnapshotTest( 104 | "AnoExportNamedDeclClass", 105 | boostestAnoExportNamedDeclClass(), 106 | ); 107 | 108 | runSnapshotTest("Mix", boostestAnoMixInterface({ name: "mix" })); 109 | runSnapshotTest( 110 | "MixCompTSAlias", 111 | boostestMixCompTSAlias({ name: "mixCompTSAlias" }), 112 | ); 113 | 114 | runSnapshotTest( 115 | "MixInterfaceFirst", 116 | boostestMixInterfaceFirst(), 117 | ); 118 | runSnapshotTest( 119 | "MixInterfaceSecond", 120 | boostestMixInterfaceSecond(), 121 | ); 122 | 123 | runSnapshotTest( 124 | "MixInterfaceFirst2", 125 | boostestMixInterfaceFirst2(), 126 | ); 127 | runSnapshotTest( 128 | "MixInterfaceSecond2", 129 | boostestMixInterfaceSecond2(), 130 | ); 131 | 132 | runSnapshotTest( 133 | "MixTSAliasFirst", 134 | boostestMixTSAliasFirst(), 135 | ); 136 | runSnapshotTest( 137 | "MixTSAliasSecond", 138 | boostestMixTSAliasSecond(), 139 | ); 140 | 141 | runSnapshotTest( 142 | "MixTSAliasFirst2", 143 | boostestMixTSAliasFirst2(), 144 | ); 145 | runSnapshotTest( 146 | "MixTSAliasSecond2", 147 | boostestMixTSAliasSecond2(), 148 | ); 149 | 150 | runSnapshotTest("MixClassFirst", boostestMixClassFirst()); 151 | runSnapshotTest("MixClassSecond", boostestMixClassSecond()); 152 | 153 | runSnapshotTest("MixClassFirst2", boostestMixClassFirst2()); 154 | runSnapshotTest( 155 | "MixClassSecond2", 156 | boostestMixClassSecond2(), 157 | ); 158 | 159 | runSnapshotTest("AccessorClass", boostestAccessorClass()); 160 | runSnapshotTest("AllExport", boostestAllExport()); 161 | }); 162 | -------------------------------------------------------------------------------- /crates/boostest/src/boostest_utils/buf.rs: -------------------------------------------------------------------------------- 1 | use oxc::span::Span; 2 | use ropey::Rope; 3 | 4 | pub fn utf16_to_utf8_offset(rope: &Rope, utf16_offset: usize) -> usize { 5 | let mut utf8_offset = 0; 6 | let mut utf16_count = 0; 7 | 8 | for chunk in rope.chunks() { 9 | let chunk_utf16_len = chunk.encode_utf16().count(); 10 | if utf16_count + chunk_utf16_len > utf16_offset { 11 | for (_i, c) in chunk.chars().enumerate() { 12 | if utf16_count == utf16_offset { 13 | return utf8_offset; 14 | } 15 | utf16_count += c.len_utf16(); 16 | utf8_offset += c.len_utf8(); 17 | } 18 | } else { 19 | utf16_count += chunk_utf16_len; 20 | utf8_offset += chunk.len(); 21 | } 22 | } 23 | 24 | utf8_offset 25 | } 26 | 27 | pub fn source_text_from_span(span: Span, source_text: &str) -> &str { 28 | let rope = Rope::from_str(source_text); 29 | let start = utf16_to_utf8_offset(&rope, span.start as usize); 30 | let end = utf16_to_utf8_offset(&rope, span.end as usize); 31 | &source_text[start..end] 32 | } 33 | 34 | pub fn utf16_span_to_utf8_span(span: Span, source_text: &str) -> Span { 35 | let rope = Rope::from_str(source_text); 36 | let start = utf16_to_utf8_offset(&rope, span.start as usize); 37 | let end = utf16_to_utf8_offset(&rope, span.end as usize); 38 | Span::new(start as u32, end as u32) 39 | } 40 | 41 | #[cfg(test)] 42 | mod tests { 43 | use super::*; 44 | use oxc::span::Span; 45 | use ropey::Rope; 46 | 47 | #[test] 48 | fn test_utf16_to_utf8_offset() { 49 | let source_text = "hello 🌍 world!"; // 含むUTF-16とUTF-8で異なる文字 50 | let rope = Rope::from_str(source_text); 51 | 52 | // "🌍" はUTF-16で2コードユニット、UTF-8で4バイト 53 | assert_eq!(utf16_to_utf8_offset(&rope, 6), 6); // ' 'の位置 54 | assert_eq!(utf16_to_utf8_offset(&rope, 7), 7); // '🌍'の開始位置 55 | assert_eq!(utf16_to_utf8_offset(&rope, 8), 11); // '🌍'の終了位置 56 | assert_eq!(utf16_to_utf8_offset(&rope, 12), 15); // 'w'の位置 57 | } 58 | 59 | #[test] 60 | fn test_source_text_from_span() { 61 | let source_text = "hello 🌍 world!"; 62 | let span = Span::new(6, 11); // UTF-16で" 🌍"を表す範囲 63 | 64 | let result = source_text_from_span(span, source_text); 65 | 66 | assert_eq!(result, " 🌍"); 67 | } 68 | 69 | #[test] 70 | fn test_utf16_span_to_utf8_span() { 71 | let source_text = "hello 🌍 world!"; 72 | let utf16_span = Span::new(6, 11); // UTF-16で" 🌍"を表す範囲 73 | 74 | let utf8_span = utf16_span_to_utf8_span(utf16_span, source_text); 75 | 76 | assert_eq!(utf8_span.start, 6); // UTF-8での開始位置 77 | assert_eq!(utf8_span.end, 11); // UTF-8での終了位置 78 | } 79 | 80 | #[test] 81 | fn test_utf16_span_to_utf8_span_typescript() { 82 | // let bytes = include_bytes!("../../../../apps/test/src/types/ts_types/literal.ts"); 83 | // let source_code = std::str::from_utf8(bytes).unwrap(); 84 | 85 | let source_code = "import { RefType } from \"@/ts_types/utils\";\n\ninterface RefTypeInterface {\n name: string;\n ver: number;\n}\n\nexport class Hoge {\n name: string;\n ver: number;\n constructor(name: string, ver: number) {\n this.name = name;\n this.ver = ver;\n }\n}\n\nexport type LiteralTypeAlias = {\n stringLiteral: string;\n numberLiteral: number;\n bigintLiteral: bigint;\n booleanLiteral: boolean;\n nullLiteral: null;\n undefinedId: undefined;\n anyLiteral: any;\n unknownLiteral: unknown;\n // neverLiteral: never;\n objectLiteral: object;\n voidLiteral: void;\n functionLiteral: () => void;\n arrayLiteral: string[];\n referenceLiteral: RefType;\n unionType: string | number;\n conditionalType: string extends number ? true : false;\n\n tsLiteralString: \"string\";\n tsLiteralNumber: 20;\n tsBigInt: 10000000000000n;\n tsLiteralBoolean: true;\n tsNullLiteral: null;\n tsObject: {};\n tsArray: [];\n\n symbolLiteral: symbol;\n tsTuple: [string, number, any, RefType, RefTypeInterface];\n tsNamedTuple: [\n name: string,\n ver: number,\n ref: RefType,\n refInterface: RefTypeInterface,\n ];\n intersectionType: RefType & { name: string; age: number };\n keyof: keyof RefType;\n indexAccessor: RefType[\"name\"];\n constructorType: abstract new (...args: any) => Hoge;\n classType: typeof Hoge;\n};\n\nexport type LiteralTypeInterface = {\n stringLiteral: string;\n numberLiteral: number;\n bigintLiteral: bigint;\n booleanLiteral: boolean;\n nullLiteral: null;\n undefinedId: undefined;\n anyLiteral: any;\n unknownLiteral: unknown;\n // neverLiteral: never;\n objectLiteral: object;\n voidLiteral: void;\n functionLiteral: () => void;\n arrayLiteral: string[];\n referenceLiteral: RefType;\n unionType: string | number;\n conditionalType: string extends number ? true : false;\n\n tsLiteralString: \"string\";\n tsLiteralNumber: 20;\n tsBigInt: 10000000000000n;\n tsLiteralBoolean: true;\n tsNullLiteral: null;\n tsObject: {};\n tsArray: [];\n\n symbolLiteral: symbol;\n tsTuple: [string, number, any, RefType, RefTypeInterface];\n tsNamedTuple: [\n name: string,\n ver: number,\n ref: RefType,\n refInterface: RefTypeInterface,\n ];\n intersectionType: RefType & RefTypeInterface & { name: string; age: number };\n keyof: keyof RefType;\n indexAccessor: RefType[\"name\"];\n constructorType: abstract new (...args: any) => Hoge;\n classType: typeof Hoge;\n};\n\nexport class LiteralTypeClass {\n constructor(\n public stringLiteral: string,\n public numberLiteral: number,\n public bigintLiteral: bigint,\n public booleanLiteral: boolean,\n public nullLiteral: null,\n public undefinedId: undefined,\n public anyLiteral: any,\n public unknownLiteral: unknown,\n // public neverLiteral: never,\n public objectLiteral: object,\n public voidLiteral: void,\n public functionLiteral: () => void,\n public arrayLiteral: string[],\n public referenceLiteral: RefType,\n public unionType: string | number,\n\n public tsLiteralString: \"string\",\n public tsLiteralNumber: 20,\n public tsBigInt: 10000000000000n,\n public tsLiteralBoolean: true,\n public tsNullLiteral: null,\n public tsObject: {},\n public tsArray: [],\n\n public symbolLiteral: symbol,\n public tsTuple: [string, number, any, RefType, RefTypeInterface, string],\n public tsNamedTuple: [\n name: string,\n ver: number,\n ref: RefType,\n refInterface: RefTypeInterface,\n hello: number,\n ],\n public intersectionType: RefType &\n RefTypeInterface & { name: string; age: number },\n public conditionalType: string extends number ? true : false,\n\n public keyof: keyof RefType,\n public indexAccessor: RefType[\"name\"],\n public constructorType: abstract new (...args: any) => Hoge,\n public classType: typeof Hoge,\n ) {}\n}\n"; 86 | 87 | let utf16_span = Span::new(108, 249); 88 | let utf8_span = utf16_span_to_utf8_span(utf16_span, source_code); 89 | 90 | assert_eq!(utf8_span.start, 108); // UTF-8での開始位置 91 | assert_eq!(utf8_span.end, 249); // UTF-8での終了位置 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /crates/boostest/src/boostest_bundler/output_main_generator.rs: -------------------------------------------------------------------------------- 1 | use std::sync::{Arc, Mutex}; 2 | 3 | use oxc::allocator::{self, Allocator}; 4 | use oxc::ast::visit::walk_mut::{ 5 | walk_ts_type, walk_ts_type_name, walk_ts_type_parameter_instantiation, 6 | }; 7 | use oxc::codegen::Codegen; 8 | use oxc::parser::Parser; 9 | use oxc::span::{SourceType, Span, SPAN}; 10 | 11 | use crate::boostest_generator::extends_ast_builder::AstBuilderExt; 12 | use crate::boostest_resolver::target::ResolvedDefinitions; 13 | use oxc::ast::ast::{Statement, TSType, TSTypeName, TSTypeParameterDeclaration}; 14 | use oxc::ast::{AstBuilder, VisitMut}; 15 | 16 | use crate::boostest_utils::ast_utils::{calc_prop_span, ignore_ref_name}; 17 | use crate::boostest_utils::id_name::get_id_with_hash; 18 | 19 | pub struct OutputMainGenerator<'a> { 20 | pub resolved_definitions: Arc>, 21 | target_def_span: Span, 22 | target_file_path: String, 23 | 24 | source_text: &'a str, 25 | allocator: &'a Allocator, 26 | ast_builder: AstBuilder<'a>, 27 | source_type: SourceType, 28 | target_ts_type: Option>, 29 | 30 | renamed: bool, 31 | 32 | pub code: Option, 33 | } 34 | 35 | impl<'a, 'b: 'a> OutputMainGenerator<'a> { 36 | pub fn new( 37 | allocator: &'b Allocator, 38 | resolved_definitions: Arc>, 39 | target_def_span: Span, 40 | target_file_path: String, 41 | source_text: &'a str, 42 | ) -> Self { 43 | let ast_builder = AstBuilder::new(allocator); 44 | Self { 45 | resolved_definitions, 46 | source_text, 47 | target_file_path, 48 | target_def_span, 49 | allocator, 50 | renamed: false, 51 | target_ts_type: None, 52 | ast_builder, 53 | source_type: SourceType::ts(), 54 | code: None, 55 | } 56 | } 57 | 58 | pub fn generate(&mut self) { 59 | let parser = Parser::new(self.allocator, self.source_text, self.source_type); 60 | let mut program = parser.parse().program; 61 | 62 | self.visit_statements(&mut program.body); 63 | self.renamed = true; 64 | self.visit_statements(&mut program.body); 65 | 66 | if let Some(ts_type) = &mut self.target_ts_type { 67 | let none_ts_type_parameter_decl: Option< 68 | allocator::Box>, 69 | > = None; 70 | 71 | { 72 | let id = self.ast_builder.binding_identifier(Span::default(), "main"); 73 | let ts_type = self.ast_builder.move_ts_type(ts_type); 74 | 75 | let ts_decl = self.ast_builder.declaration_ts_type_alias( 76 | Span::default(), 77 | id, 78 | none_ts_type_parameter_decl, 79 | ts_type, 80 | false, 81 | ); 82 | let stmt = Statement::from(ts_decl); 83 | let mut statements = self.ast_builder.vec(); 84 | 85 | statements.push(stmt); 86 | 87 | program.body = statements; 88 | } 89 | } 90 | 91 | self.code = Some(Codegen::new().build(&program).code); 92 | } 93 | } 94 | 95 | impl<'a> VisitMut<'a> for OutputMainGenerator<'a> { 96 | fn visit_ts_type_parameter_instantiation( 97 | &mut self, 98 | it: &mut oxc::ast::ast::TSTypeParameterInstantiation<'a>, 99 | ) { 100 | if self.renamed { 101 | if let Some(first_type) = it.params.first_mut() { 102 | let ts_type = self.ast_builder.move_ts_type(first_type); 103 | self.target_ts_type = Some(ts_type); 104 | } 105 | } else { 106 | walk_ts_type_parameter_instantiation(self, it) 107 | } 108 | } 109 | 110 | fn visit_ts_type_name(&mut self, it: &mut TSTypeName<'a>) { 111 | let mut new_type_name = None; 112 | 113 | if let TSTypeName::IdentifierReference(identifier) = it { 114 | let id_name = identifier.name.clone(); 115 | if ignore_ref_name(&id_name) { 116 | return; 117 | } 118 | 119 | let span = calc_prop_span(identifier.span, Some(self.target_def_span)); 120 | let key_name = get_id_with_hash(self.target_file_path.clone(), span); 121 | let var_name = self 122 | .resolved_definitions 123 | .lock() 124 | .unwrap() 125 | .get_target_def_hash_name_with_key(&key_name, &id_name); 126 | 127 | let id_name = self.ast_builder.alloc_identifier_reference( 128 | Span::default(), 129 | var_name.unwrap_or(id_name.to_string()), 130 | ); 131 | 132 | new_type_name = Some(TSTypeName::IdentifierReference(id_name)); 133 | } 134 | 135 | if let Some(new_type_name) = new_type_name { 136 | *it = new_type_name; 137 | } 138 | 139 | if let TSTypeName::QualifiedName(qualified_name) = it { 140 | let span = calc_prop_span(qualified_name.right.span, Some(self.target_def_span)); 141 | let key_name = get_id_with_hash(self.target_file_path.clone(), span); 142 | let var_name = self 143 | .resolved_definitions 144 | .lock() 145 | .unwrap() 146 | .get_target_def_hash_name_with_key(&key_name, &qualified_name.left.to_string()); 147 | 148 | let id_name = self.ast_builder.alloc_identifier_reference( 149 | Span::default(), 150 | var_name.unwrap_or(qualified_name.left.to_string()), 151 | ); 152 | 153 | new_type_name = Some(TSTypeName::IdentifierReference(id_name)); 154 | if let Some(new_type_name) = new_type_name { 155 | qualified_name.left = new_type_name; 156 | } 157 | } 158 | 159 | walk_ts_type_name(self, it); 160 | } 161 | 162 | fn visit_ts_type(&mut self, it: &mut TSType<'a>) { 163 | let mut new_ts_type: Option = None; 164 | 165 | if let TSType::TSArrayType(ts_array_type) = it { 166 | let new_element_ts_type = self 167 | .ast_builder 168 | .move_ts_type(&mut ts_array_type.element_type); 169 | let new_name = self 170 | .ast_builder 171 | .ts_type_name_identifier_reference(SPAN, "Array"); 172 | let mut params = self.ast_builder.vec(); 173 | params.push(new_element_ts_type); 174 | let ts_type_parameter_instantiation = self 175 | .ast_builder 176 | .ts_type_parameter_instantiation(SPAN, params); 177 | 178 | new_ts_type = Some(self.ast_builder.ts_type_type_reference( 179 | SPAN, 180 | new_name, 181 | Some(ts_type_parameter_instantiation), 182 | )); 183 | }; 184 | 185 | if let Some(new_ts_type) = new_ts_type { 186 | *it = new_ts_type; 187 | } 188 | walk_ts_type(self, it); 189 | } 190 | } 191 | --------------------------------------------------------------------------------