From d209e83f0107d28b8ed70169e4b597cafce90a54 Mon Sep 17 00:00:00 2001 From: Maxim Date: Mon, 17 Feb 2025 08:35:23 -0800 Subject: [PATCH 1/2] fix(cubejs-server-core): fix schema caching in SQL API with DAP on (#9204) --- .../src/core/CompilerApi.js | 49 ++++-- .../birdbox-fixtures/rbac/cube.js | 22 +++ .../rbac/model/cubes/line_items.js | 6 + .../__snapshots__/smoke-rbac.test.ts.snap | 150 ++++++++++++++++++ .../cubejs-testing/test/smoke-rbac.test.ts | 22 +++ yarn.lock | 63 +++++++- 6 files changed, 294 insertions(+), 18 deletions(-) diff --git a/packages/cubejs-server-core/src/core/CompilerApi.js b/packages/cubejs-server-core/src/core/CompilerApi.js index 45ae80dc68375..1e7fd4e4bcb53 100644 --- a/packages/cubejs-server-core/src/core/CompilerApi.js +++ b/packages/cubejs-server-core/src/core/CompilerApi.js @@ -1,7 +1,7 @@ import crypto from 'crypto'; import R from 'ramda'; import { createQuery, compile, queryClass, PreAggregations, QueryFactory } from '@cubejs-backend/schema-compiler'; -import { v4 as uuidv4 } from 'uuid'; +import { v4 as uuidv4, parse as uuidParse, stringify as uuidStringify } from 'uuid'; import { NativeInstance } from '@cubejs-backend/native'; export class CompilerApi { @@ -428,7 +428,7 @@ export class CompilerApi { const { cubeEvaluator } = compilers; if (!cubeEvaluator.isRbacEnabled()) { - return cubes; + return { cubes, visibilityMaskHash: null }; } for (const cube of cubes) { @@ -481,23 +481,38 @@ export class CompilerApi { }); }; - return cubes - .map((cube) => ({ - config: { - ...cube.config, - measures: cube.config.measures?.map(visibilityPatcherForCube(cube)), - dimensions: cube.config.dimensions?.map(visibilityPatcherForCube(cube)), - segments: cube.config.segments?.map(visibilityPatcherForCube(cube)), - hierarchies: cube.config.hierarchies?.map(visibilityPatcherForCube(cube)), - }, - })); + const visibiliyMask = JSON.stringify(isMemberVisibleInContext, Object.keys(isMemberVisibleInContext).sort()); + // This hash will be returned along the modified meta config and can be used + // to distinguish between different "schema versions" after DAP visibility is applied + const visibilityMaskHash = crypto.createHash('sha256').update(visibiliyMask).digest('hex'); + + return { + cubes: cubes + .map((cube) => ({ + config: { + ...cube.config, + measures: cube.config.measures?.map(visibilityPatcherForCube(cube)), + dimensions: cube.config.dimensions?.map(visibilityPatcherForCube(cube)), + segments: cube.config.segments?.map(visibilityPatcherForCube(cube)), + hierarchies: cube.config.hierarchies?.map(visibilityPatcherForCube(cube)), + }, + })), + visibilityMaskHash + }; + } + + mixInVisibilityMaskHash(compilerId, visibilityMaskHash) { + const uuidBytes = uuidParse(compilerId); + const hashBytes = Buffer.from(visibilityMaskHash, 'hex'); + return uuidv4({ random: crypto.createHash('sha256').update(uuidBytes).update(hashBytes).digest() + .subarray(0, 16) }); } async metaConfig(requestContext, options = {}) { const { includeCompilerId, ...restOptions } = options; const compilers = await this.getCompilers(restOptions); const { cubes } = compilers.metaTransformer; - const patchedCubes = await this.patchVisibilityByAccessPolicy( + const { visibilityMaskHash, cubes: patchedCubes } = await this.patchVisibilityByAccessPolicy( compilers, requestContext, cubes @@ -505,7 +520,11 @@ export class CompilerApi { if (includeCompilerId) { return { cubes: patchedCubes, - compilerId: compilers.compilerId, + // This compilerId is primarily used by the cubejs-backend-native or caching purposes. + // By default it doesn't account for member visibility changes introduced above by DAP. + // Here we're modifying the originila compilerId in a way that it's distinct for + // distinct schema versions while still being a valid UUID. + compilerId: visibilityMaskHash ? this.mixInVisibilityMaskHash(compilers.compilerId, visibilityMaskHash) : compilers.compilerId, }; } return patchedCubes; @@ -513,7 +532,7 @@ export class CompilerApi { async metaConfigExtended(requestContext, options) { const compilers = await this.getCompilers(options); - const patchedCubes = await this.patchVisibilityByAccessPolicy( + const { cubes: patchedCubes } = await this.patchVisibilityByAccessPolicy( compilers, requestContext, compilers.metaTransformer?.cubes diff --git a/packages/cubejs-testing/birdbox-fixtures/rbac/cube.js b/packages/cubejs-testing/birdbox-fixtures/rbac/cube.js index e7c82f455e36f..6f50f842c97de 100644 --- a/packages/cubejs-testing/birdbox-fixtures/rbac/cube.js +++ b/packages/cubejs-testing/birdbox-fixtures/rbac/cube.js @@ -1,5 +1,6 @@ module.exports = { contextToRoles: async (context) => context.securityContext.auth?.roles || [], + canSwitchSqlUser: async () => true, checkSqlAuth: async (req, user, password) => { if (user === 'admin') { if (password && password !== 'admin_password') { @@ -64,6 +65,27 @@ module.exports = { }, }; } + if (user === 'restricted') { + if (password && password !== 'restricted_password') { + throw new Error(`Password doesn't match for ${user}`); + } + return { + password, + superuser: false, + securityContext: { + auth: { + username: 'default', + userAttributes: { + region: 'CA', + city: 'San Francisco', + canHaveAdmin: true, + minDefaultId: 20000, + }, + roles: ['restricted'], + }, + }, + }; + } throw new Error(`User "${user}" doesn't exist`); } }; diff --git a/packages/cubejs-testing/birdbox-fixtures/rbac/model/cubes/line_items.js b/packages/cubejs-testing/birdbox-fixtures/rbac/model/cubes/line_items.js index 7013052b0169e..8d35089fdbc43 100644 --- a/packages/cubejs-testing/birdbox-fixtures/rbac/model/cubes/line_items.js +++ b/packages/cubejs-testing/birdbox-fixtures/rbac/model/cubes/line_items.js @@ -60,6 +60,12 @@ cube('line_items', { excludes: ['count', 'price', 'price_dim'], }, }, + { + role: 'restricted', + memberLevel: { + excludes: ['count', 'price', 'price_dim'], + }, + }, { role: 'admin', conditions: [ diff --git a/packages/cubejs-testing/test/__snapshots__/smoke-rbac.test.ts.snap b/packages/cubejs-testing/test/__snapshots__/smoke-rbac.test.ts.snap index b4a7ce5537530..645cd46bdd9ae 100644 --- a/packages/cubejs-testing/test/__snapshots__/smoke-rbac.test.ts.snap +++ b/packages/cubejs-testing/test/__snapshots__/smoke-rbac.test.ts.snap @@ -770,3 +770,153 @@ Array [ `; exports[`Cube RBAC Engine RBAC via SQL API manager SELECT * from line_items: line_items_manager 1`] = `Array []`; + +exports[`Cube RBAC Engine RBAC via SQL changing users Switching user should allow more members to be visible: line_items 1`] = ` +Array [ + Object { + "__cubeJoinField": null, + "__user": null, + "count": "1", + "created_at": 2018-10-23T07:54:39.000Z, + "price": 267, + "quantity": 2, + }, + Object { + "__cubeJoinField": null, + "__user": null, + "count": "1", + "created_at": 2018-01-01T13:50:20.000Z, + "price": 263, + "quantity": 7, + }, + Object { + "__cubeJoinField": null, + "__user": null, + "count": "1", + "created_at": 2017-05-13T21:23:08.000Z, + "price": 180, + "quantity": 8, + }, + Object { + "__cubeJoinField": null, + "__user": null, + "count": "1", + "created_at": 2018-04-10T22:51:15.000Z, + "price": 169, + "quantity": 6, + }, + Object { + "__cubeJoinField": null, + "__user": null, + "count": "1", + "created_at": 2017-07-16T15:00:34.000Z, + "price": 156, + "quantity": 1, + }, + Object { + "__cubeJoinField": null, + "__user": null, + "count": "1", + "created_at": 2019-05-23T04:25:27.000Z, + "price": 36, + "quantity": 5, + }, + Object { + "__cubeJoinField": null, + "__user": null, + "count": "1", + "created_at": 2018-09-29T20:29:30.000Z, + "price": 245, + "quantity": 4, + }, + Object { + "__cubeJoinField": null, + "__user": null, + "count": "1", + "created_at": 2019-04-17T03:32:54.000Z, + "price": 232, + "quantity": 8, + }, + Object { + "__cubeJoinField": null, + "__user": null, + "count": "1", + "created_at": 2019-11-15T18:22:17.000Z, + "price": 63, + "quantity": 8, + }, + Object { + "__cubeJoinField": null, + "__user": null, + "count": "1", + "created_at": 2019-12-16T08:09:36.000Z, + "price": 68, + "quantity": 6, + }, +] +`; + +exports[`Cube RBAC Engine RBAC via SQL changing users Switching user should allow more members to be visible: line_items_default 1`] = ` +Array [ + Object { + "__cubeJoinField": null, + "__user": null, + "created_at": 2018-10-23T07:54:39.000Z, + "quantity": 2, + }, + Object { + "__cubeJoinField": null, + "__user": null, + "created_at": 2018-01-01T13:50:20.000Z, + "quantity": 7, + }, + Object { + "__cubeJoinField": null, + "__user": null, + "created_at": 2017-05-13T21:23:08.000Z, + "quantity": 8, + }, + Object { + "__cubeJoinField": null, + "__user": null, + "created_at": 2018-04-10T22:51:15.000Z, + "quantity": 6, + }, + Object { + "__cubeJoinField": null, + "__user": null, + "created_at": 2017-07-16T15:00:34.000Z, + "quantity": 1, + }, + Object { + "__cubeJoinField": null, + "__user": null, + "created_at": 2019-05-23T04:25:27.000Z, + "quantity": 5, + }, + Object { + "__cubeJoinField": null, + "__user": null, + "created_at": 2018-09-29T20:29:30.000Z, + "quantity": 4, + }, + Object { + "__cubeJoinField": null, + "__user": null, + "created_at": 2019-04-17T03:32:54.000Z, + "quantity": 8, + }, + Object { + "__cubeJoinField": null, + "__user": null, + "created_at": 2019-11-15T18:22:17.000Z, + "quantity": 8, + }, + Object { + "__cubeJoinField": null, + "__user": null, + "created_at": 2019-12-16T08:09:36.000Z, + "quantity": 6, + }, +] +`; diff --git a/packages/cubejs-testing/test/smoke-rbac.test.ts b/packages/cubejs-testing/test/smoke-rbac.test.ts index f318711932a8c..2d825ebf77609 100644 --- a/packages/cubejs-testing/test/smoke-rbac.test.ts +++ b/packages/cubejs-testing/test/smoke-rbac.test.ts @@ -198,6 +198,28 @@ describe('Cube RBAC Engine', () => { }); }); + describe('RBAC via SQL changing users', () => { + let connection: PgClient; + + beforeAll(async () => { + connection = await createPostgresClient('restricted', 'restricted_password'); + }); + + afterAll(async () => { + await connection.end(); + }, JEST_AFTER_ALL_DEFAULT_TIMEOUT); + + test('Switching user should allow more members to be visible', async () => { + const resDefault = await connection.query('SELECT * FROM line_items limit 10'); + expect(resDefault.rows).toMatchSnapshot('line_items_default'); + + await connection.query('SET USER=admin'); + + const resAdmin = await connection.query('SELECT * FROM line_items limit 10'); + expect(resAdmin.rows).toMatchSnapshot('line_items'); + }); + }); + describe('RBAC via REST API', () => { let client: CubeApi; let defaultClient: CubeApi; diff --git a/yarn.lock b/yarn.lock index e1fcc9fb89c53..6cb127ff844b5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5306,6 +5306,18 @@ uuid "9.0.0" winston "3.8.2" +"@cubejs-backend/linter@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@cubejs-backend/linter/-/linter-1.2.4.tgz#b38551ada107d94a3a12bb3f82e582ef6e184096" + integrity sha512-V150xWxBgRptCO4GAdZTuCwY7+FoxlJ1rBYM379LLEX8sLFC4NG0AN8S3vy0YSaUaC3P07ne3CrEILIJLt0JAg== + dependencies: + "@typescript-eslint/eslint-plugin" "^6.12.0" + "@typescript-eslint/parser" "^6.12.0" + eslint "^8.54.0" + eslint-config-airbnb-base "^14.2.1" + eslint-plugin-import "^2.22.1" + eslint-plugin-node "^9.2.0" + "@cubejs-backend/shared@0.33.20": version "0.33.20" resolved "https://registry.yarnpkg.com/@cubejs-backend/shared/-/shared-0.33.20.tgz#3d9fa60041599cca9fe4c04df05daa4b8ab8675f" @@ -5326,6 +5338,26 @@ throttle-debounce "^3.0.1" uuid "^8.3.2" +"@cubejs-backend/shared@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@cubejs-backend/shared/-/shared-1.2.4.tgz#dcdc8a0537cfe9df97f3502bea983204634fbdfd" + integrity sha512-C/BA0ogCRhhtYwYyQkhXTTKLIUtJ1020aybbQ9tbKtlkrd3ab+a166jmtlAD5kDeoIhB08DgMTQjaQGDYh3gBg== + dependencies: + "@oclif/color" "^0.1.2" + bytes "^3.1.0" + cli-progress "^3.9.0" + cross-spawn "^7.0.3" + decompress "^4.2.1" + env-var "^6.3.0" + fs-extra "^9.1.0" + http-proxy-agent "^4.0.1" + moment-range "^4.0.1" + moment-timezone "^0.5.46" + node-fetch "^2.6.1" + shelljs "^0.8.5" + throttle-debounce "^3.0.1" + uuid "^8.3.2" + "@cubejs-infra/post-installer@^0.0.7": version "0.0.7" resolved "https://registry.yarnpkg.com/@cubejs-infra/post-installer/-/post-installer-0.0.7.tgz#a28d2d03e5b7b69a64020d75194a7078cf911d2d" @@ -27218,7 +27250,16 @@ string-length@^5.0.1: char-regex "^2.0.0" strip-ansi "^7.0.1" -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -27316,7 +27357,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -27344,6 +27385,13 @@ strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.0, strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -29543,7 +29591,7 @@ workerpool@^9.2.0: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-9.2.0.tgz#f74427cbb61234708332ed8ab9cbf56dcb1c4371" integrity sha512-PKZqBOCo6CYkVOwAxWxQaSF2Fvb5Iv2fCeTP7buyWI2GiynWr46NcXSgK/idoV6e60dgCBfgYc+Un3HMvmqP8w== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -29569,6 +29617,15 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From 2dd9a4a5ba0f178e304befc476609fc30ada8975 Mon Sep 17 00:00:00 2001 From: Konstantin Burkalev Date: Mon, 17 Feb 2025 20:42:54 +0200 Subject: [PATCH 2/2] =?UTF-8?q?feat(schema-compiler):=20Boost=20models=20t?= =?UTF-8?q?ranspilation=2010-13x=20times=20(using=20SWC=20instead=20of?= =?UTF-8?q?=C2=A0Babel)=20(#9225)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Init proj structure * implement transpilers * add transpilers crate to backend native * prepare transpile_js native implementation * export transpileJs from backend native * removed workerpool & sync pkg versions * update transpileJsFile with native impl use * add new() to all transpilers * remove unused * fix tests * polish transpilers, add support for error reporter * setup CI for cubetranspilers testing * derive default for TransformMetaData * move deserializer into thread closure * Revert "remove unused" This reverts commit 4491f6bdcae3fa0f66fceaff61e9b03368c43ad5. * return back previous transpilationWorkerThreads flow * Update CI to run tests for all cases: old, threads, native * some improvements * move tests to a separate folder --- .github/workflows/push.yml | 16 + packages/cubejs-backend-native/Cargo.lock | 1652 +++++++++++- packages/cubejs-backend-native/Cargo.toml | 8 +- packages/cubejs-backend-native/js/index.ts | 22 + packages/cubejs-backend-native/src/lib.rs | 1 + .../cubejs-backend-native/src/node_export.rs | 3 + .../cubejs-backend-native/src/transpilers.rs | 91 + packages/cubejs-backend-shared/src/env.ts | 4 + packages/cubejs-jdbc-driver/package.json | 2 +- .../src/compiler/DataSchemaCompiler.js | 81 +- .../src/compiler/ErrorReporter.ts | 10 +- .../compiler/transpilers/transpiler_worker.ts | 8 +- .../test/unit/transpilers.test.ts | 2 +- rust/cubeorchestrator/Cargo.lock | 10 +- rust/cubeorchestrator/Cargo.toml | 2 +- rust/cubestore/package.json | 4 +- rust/cubetranspilers/.gitignore | 3 + rust/cubetranspilers/Cargo.lock | 2347 +++++++++++++++++ rust/cubetranspilers/Cargo.toml | 14 + rust/cubetranspilers/rust-toolchain.toml | 4 + rust/cubetranspilers/rustfmt.toml | 1 + .../src/check_dup_prop_transpiler.rs | 107 + .../src/cube_prop_ctx_transpiler.rs | 397 +++ rust/cubetranspilers/src/error_reporter.rs | 45 + .../src/import_export_transpiler.rs | 356 +++ rust/cubetranspilers/src/lib.rs | 156 ++ .../src/validation_transpiler.rs | 70 + .../tests/check_dup_prop_test.rs | 273 ++ rust/cubetranspilers/tests/common/mod.rs | 33 + .../tests/cube_prop_ctx_test.rs | 947 +++++++ .../tests/import_export_test.rs | 430 +++ rust/cubetranspilers/tests/validation_test.rs | 99 + 32 files changed, 7053 insertions(+), 145 deletions(-) create mode 100644 packages/cubejs-backend-native/src/transpilers.rs create mode 100644 rust/cubetranspilers/.gitignore create mode 100644 rust/cubetranspilers/Cargo.lock create mode 100644 rust/cubetranspilers/Cargo.toml create mode 100644 rust/cubetranspilers/rust-toolchain.toml create mode 100644 rust/cubetranspilers/rustfmt.toml create mode 100644 rust/cubetranspilers/src/check_dup_prop_transpiler.rs create mode 100644 rust/cubetranspilers/src/cube_prop_ctx_transpiler.rs create mode 100644 rust/cubetranspilers/src/error_reporter.rs create mode 100644 rust/cubetranspilers/src/import_export_transpiler.rs create mode 100644 rust/cubetranspilers/src/lib.rs create mode 100644 rust/cubetranspilers/src/validation_transpiler.rs create mode 100644 rust/cubetranspilers/tests/check_dup_prop_test.rs create mode 100644 rust/cubetranspilers/tests/common/mod.rs create mode 100644 rust/cubetranspilers/tests/cube_prop_ctx_test.rs create mode 100644 rust/cubetranspilers/tests/import_export_test.rs create mode 100644 rust/cubetranspilers/tests/validation_test.rs diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index bfe45fa6b168e..308ffd39a00dd 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -13,6 +13,7 @@ on: - 'rust/cubeorchestrator/**' - 'rust/cubeshared/**' - 'rust/cubesqlplanner/**' + - 'rust/cubetranspilers/**' - '.eslintrc.js' - '.prettierrc' - 'package.json' @@ -32,6 +33,7 @@ on: - 'rust/cubeorchestrator/**' - 'rust/cubeshared/**' - 'rust/cubesqlplanner/**' + - 'rust/cubetranspilers/**' - '.eslintrc.js' - '.prettierrc' - 'package.json' @@ -55,10 +57,15 @@ jobs: node-version: [20.x, 22.x] python-version: [3.11] transpile-worker-threads: [false, true] + transpile-native: [false, true] + exclude: + - transpile-worker-threads: true + transpile-native: true fail-fast: false env: CUBEJS_TRANSPILATION_WORKER_THREADS: ${{ matrix.transpile-worker-threads }} + CUBEJS_TRANSPILATION_NATIVE: ${{ matrix.transpile-native }} steps: - id: get-tag-out run: echo "$OUT" @@ -133,6 +140,9 @@ jobs: - name: Cargo test cubeshared run: | cargo test --manifest-path rust/cubeshared/Cargo.toml -j 1 + - name: Cargo test cubetranspilers + run: | + cargo test --manifest-path rust/cubetranspilers/Cargo.toml -j 1 # - name: Cargo test cubesql # run: | # cargo test --manifest-path rust/cubesql/Cargo.toml -j 1 @@ -196,6 +206,9 @@ jobs: - name: Cargo fmt cubeshared run: | cargo fmt --manifest-path rust/cubeshared/Cargo.toml -- --check + - name: Cargo fmt cubetranspilers + run: | + cargo fmt --manifest-path rust/cubetranspilers/Cargo.toml -- --check # - name: Cargo fmt cubesql # run: | # cargo fmt --manifest-path rust/cubesql/Cargo.toml -- --check @@ -263,6 +276,9 @@ jobs: - name: Cargo build cubeshared run: | cargo build --manifest-path rust/cubeshared/Cargo.toml -j 4 + - name: Cargo build cubetranspilers + run: | + cargo build --manifest-path rust/cubetranspilers/Cargo.toml -j 4 # - name: Cargo build cubesql # run: | # cargo build --manifest-path rust/cubesql/Cargo.toml -j 4 diff --git a/packages/cubejs-backend-native/Cargo.lock b/packages/cubejs-backend-native/Cargo.lock index 5cd459688e993..3e505689905ca 100644 --- a/packages/cubejs-backend-native/Cargo.lock +++ b/packages/cubejs-backend-native/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "Inflector" @@ -95,11 +95,20 @@ dependencies = [ "libc", ] +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" [[package]] name = "arc-swap" @@ -144,6 +153,24 @@ dependencies = [ "serde_json", ] +[[package]] +name = "ascii" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16" + +[[package]] +name = "ast_node" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91fb5864e2f5bf9fd9797b94b2dfd1554d4c3092b535008b27d7e15c86675a2f" +dependencies = [ + "proc-macro2", + "quote", + "swc_macros_common", + "syn 2.0.90", +] + [[package]] name = "async-channel" version = "2.1.1" @@ -298,6 +325,24 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64-simd" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "781dd20c3aff0bd194fe7d2a977dd92f21c173891f3a03b677359e5fa457e5d5" +dependencies = [ + "simd-abstraction", +] + +[[package]] +name = "better_scoped_tls" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50fd297a11c709be8348aec039c8b91de16075d2b2bdaee1bd562c0875993664" +dependencies = [ + "scoped-tls", +] + [[package]] name = "bigdecimal" version = "0.4.2" @@ -328,9 +373,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" [[package]] name = "bitvec" @@ -432,9 +477,12 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" +dependencies = [ + "allocator-api2", +] [[package]] name = "bytecheck" @@ -442,8 +490,20 @@ version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6372023ac861f6e6dc89c8344a8f398fb42aaba2b5dbc649ca0c0e9dbcb627" dependencies = [ - "bytecheck_derive", - "ptr_meta", + "bytecheck_derive 0.6.11", + "ptr_meta 0.1.4", + "simdutf8", +] + +[[package]] +name = "bytecheck" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50690fb3370fb9fe3550372746084c46f2ac8c9685c583d2be10eefd89d3d1a3" +dependencies = [ + "bytecheck_derive 0.8.1", + "ptr_meta 0.3.0", + "rancor", "simdutf8", ] @@ -458,6 +518,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "bytecheck_derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efb7846e0cb180355c2dec69e721edafa36919850f1a9f52ffba4ebc0393cb71" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "byteorder" version = "1.5.0" @@ -470,14 +541,70 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +[[package]] +name = "camino" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" +dependencies = [ + "camino", + "cargo-platform", + "semver 1.0.23", + "serde", + "serde_json", + "thiserror 1.0.69", +] + +[[package]] +name = "cargo_metadata" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8769706aad5d996120af43197bf46ef6ad0fda35216b4505f926a365a232d924" +dependencies = [ + "camino", + "cargo-platform", + "semver 1.0.23", + "serde", + "serde_json", + "thiserror 2.0.11", +] + +[[package]] +name = "castaway" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0abae9be0aaf9ea96a3b1b8b1b55c602ca751eba1b1500220cea4ecbafe7c0d5" +dependencies = [ + "rustversion", +] + [[package]] name = "cc" -version = "1.1.5" +version = "1.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "324c74f2155653c90b04f25b2a47a8a631360cb908f92a772695f430c7e31052" +checksum = "0c3d1b2e905a3a7b00a6141adb0e4c0bb941d11caf55349d863942a1cc44e3c9" dependencies = [ "jobserver", "libc", + "shlex", ] [[package]] @@ -585,6 +712,19 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "compact_str" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f86b9c4c00838774a6d902ef931eff7470720c51d90c2e32cfe15dc304737b3f" +dependencies = [ + "castaway", + "cfg-if", + "itoa", + "ryu", + "static_assertions", +] + [[package]] name = "concurrent-queue" version = "2.4.0" @@ -648,7 +788,7 @@ version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.8.0", "crossterm_winapi", "libc", "parking_lot", @@ -737,6 +877,7 @@ dependencies = [ "cubeorchestrator", "cubesql", "cubesqlplanner", + "cubetranspilers", "findshlibs", "futures", "http-body-util", @@ -817,7 +958,7 @@ dependencies = [ "futures", "futures-core", "futures-util", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "indexmap 1.9.3", "itertools 0.10.5", "log", @@ -865,6 +1006,55 @@ dependencies = [ "tokio", ] +[[package]] +name = "cubetranspilers" +version = "0.1.0" +dependencies = [ + "anyhow", + "indexmap 2.7.1", + "regex", + "serde", + "serde_json", + "swc_core", + "swc_ecma_codegen", + "swc_ecma_parser", +] + +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.90", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.90", +] + [[package]] name = "data-encoding" version = "2.6.0" @@ -963,6 +1153,59 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "debugid" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" +dependencies = [ + "serde", + "uuid 1.6.1", +] + +[[package]] +name = "derive_builder" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" +dependencies = [ + "derive_builder_core", + "syn 2.0.90", +] + +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + +[[package]] +name = "difference" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" + [[package]] name = "digest" version = "0.10.7" @@ -974,6 +1217,17 @@ dependencies = [ "subtle", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "egg" version = "0.9.5" @@ -992,15 +1246,15 @@ dependencies = [ "smallvec", "symbol_table", "symbolic_expressions", - "thiserror 1.0.50", + "thiserror 1.0.69", "vectorize", ] [[package]] name = "either" -version = "1.9.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "env_logger" @@ -1086,7 +1340,7 @@ checksum = "86b428b715fdbdd1c364b84573b5fdc0f84f8e423661b9f398735278bc7f2b6a" dependencies = [ "bitflags 1.3.2", "smallvec", - "thiserror 1.0.50", + "thiserror 1.0.69", ] [[package]] @@ -1096,7 +1350,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dac53e22462d78c16d64a1cd22371b54cc3fe94aa15e7886a2fa6e5d1ab8640" dependencies = [ "bitflags 1.3.2", - "rustc_version", + "rustc_version 0.4.1", ] [[package]] @@ -1124,6 +1378,17 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "from_variant" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d7ccf961415e7aa17ef93dcb6c2441faaa8e768abe09e659b908089546f74c5" +dependencies = [ + "proc-macro2", + "swc_macros_common", + "syn 2.0.90", +] + [[package]] name = "funty" version = "2.0.0" @@ -1255,6 +1520,12 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +[[package]] +name = "glob" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" + [[package]] name = "globset" version = "0.4.13" @@ -1297,14 +1568,20 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash 0.8.11", "allocator-api2", ] +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" + [[package]] name = "heck" version = "0.3.3" @@ -1320,6 +1597,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -1350,6 +1633,20 @@ dependencies = [ "digest", ] +[[package]] +name = "hstr" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a26def229ea95a8709dad32868d975d0dd40235bd2ce82920e4a8fe692b5e0" +dependencies = [ + "hashbrown 0.14.5", + "new_debug_unreachable", + "once_cell", + "phf", + "rustc-hash 1.1.0", + "triomphe", +] + [[package]] name = "http" version = "1.1.0" @@ -1478,83 +1775,236 @@ dependencies = [ ] [[package]] -name = "idna" -version = "0.5.0" +name = "icu_collections" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "displaydoc", + "yoke", + "zerofrom", + "zerovec", ] [[package]] -name = "ignore" -version = "0.4.20" +name = "icu_locid" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" dependencies = [ - "globset", - "lazy_static", - "log", - "memchr", - "regex", - "same-file", - "thread_local", - "walkdir", - "winapi-util", + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", ] [[package]] -name = "indexmap" -version = "1.9.3" +name = "icu_locid_transform" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" dependencies = [ - "autocfg", - "hashbrown 0.12.3", - "serde", + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", ] [[package]] -name = "indexmap" -version = "2.4.0" +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" dependencies = [ - "equivalent", - "hashbrown 0.14.3", + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", ] [[package]] -name = "indoc" -version = "2.0.4" +name = "icu_normalizer_data" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" [[package]] -name = "instant" -version = "0.1.12" +name = "icu_properties" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" dependencies = [ - "cfg-if", + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", ] [[package]] -name = "integer-encoding" -version = "1.1.7" +name = "icu_properties_data" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48dc51180a9b377fd75814d0cc02199c20f8e99433d6762f650d39cdbbd3b56f" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" [[package]] -name = "ipnet" -version = "2.9.0" +name = "icu_provider" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] [[package]] -name = "is-terminal" -version = "0.4.9" +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "if_chain" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" + +[[package]] +name = "ignore" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492" +dependencies = [ + "globset", + "lazy_static", + "log", + "memchr", + "regex", + "same-file", + "thread_local", + "walkdir", + "winapi-util", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +dependencies = [ + "equivalent", + "hashbrown 0.15.2", +] + +[[package]] +name = "indoc" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8" + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "integer-encoding" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48dc51180a9b377fd75814d0cc02199c20f8e99433d6762f650d39cdbbd3b56f" + +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + +[[package]] +name = "is-macro" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d57a3e447e24c22647738e4607f1df1e0ec6f72e16182c4cd199f647cdfb0e4" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "is-terminal" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ @@ -1677,9 +2127,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.151" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libloading" @@ -1703,6 +2153,12 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +[[package]] +name = "litemap" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" + [[package]] name = "lock_api" version = "0.4.11" @@ -1736,7 +2192,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2994eeba8ed550fd9b47a0b38f0242bc3344e496483c6180b69139cc2fa5d1d7" dependencies = [ - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] @@ -1759,6 +2215,15 @@ dependencies = [ "libc", ] +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + [[package]] name = "matchit" version = "0.7.3" @@ -1796,6 +2261,31 @@ dependencies = [ "autocfg", ] +[[package]] +name = "miette" +version = "7.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a955165f87b37fd1862df2a59547ac542c77ef6d17c666f619d1ad22dd89484" +dependencies = [ + "cfg-if", + "miette-derive", + "owo-colors", + "textwrap", + "thiserror 1.0.69", + "unicode-width", +] + +[[package]] +name = "miette-derive" +version = "7.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf45bf44ab49be92fd1227a3be6fc6f617f1a337c06af54981048574d8783147" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "mime" version = "0.3.17" @@ -1864,6 +2354,26 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "munge" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64142d38c84badf60abf06ff9bd80ad2174306a5b11bd4706535090a30a419df" +dependencies = [ + "munge_macro", +] + +[[package]] +name = "munge_macro" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bb5c1d8184f13f7d0ccbeeca0def2f9a181bce2624302793005f5ca8aa62e5e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "nativebridge" version = "0.1.0" @@ -1886,7 +2396,7 @@ dependencies = [ "libloading", "neon-macros", "once_cell", - "semver", + "semver 1.0.23", "send_wrapper", "smallvec", "tokio", @@ -1903,6 +2413,22 @@ dependencies = [ "syn-mid", ] +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + [[package]] name = "num" version = "0.4.1" @@ -1926,6 +2452,7 @@ dependencies = [ "autocfg", "num-integer", "num-traits", + "serde", ] [[package]] @@ -2022,6 +2549,24 @@ dependencies = [ "num-traits", ] +[[package]] +name = "outref" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f222829ae9293e33a9f5e9f440c6760a3d450a64affe1846486b140db81c1f4" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "owo-colors" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb37767f6569cd834a413442455e0f066d0d522de8630436e2a1761d9726ba56" + [[package]] name = "parking" version = "2.2.0" @@ -2109,7 +2654,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae9cee2a55a544be8b89dc6848072af97a20f2422603c10865be2a42b580fff5" dependencies = [ "memchr", - "thiserror 1.0.50", + "thiserror 1.0.69", "ucd-trie", ] @@ -2166,6 +2711,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ + "phf_macros", "phf_shared", ] @@ -2189,6 +2735,19 @@ dependencies = [ "rand", ] +[[package]] +name = "phf_macros" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "phf_shared" version = "0.11.2" @@ -2286,6 +2845,16 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "pretty_assertions" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" +dependencies = [ + "diff", + "yansi", +] + [[package]] name = "proc-macro-crate" version = "2.0.1" @@ -2328,13 +2897,31 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "psm" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200b9ff220857e53e184257720a14553b2f4aa02577d2ed9842d45d4b9654810" +dependencies = [ + "cc", +] + [[package]] name = "ptr_meta" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" dependencies = [ - "ptr_meta_derive", + "ptr_meta_derive 0.1.4", +] + +[[package]] +name = "ptr_meta" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe9e76f66d3f9606f44e45598d155cb13ecf09f4a28199e48daf8c8fc937ea90" +dependencies = [ + "ptr_meta_derive 0.3.0", ] [[package]] @@ -2348,6 +2935,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "ptr_meta_derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca414edb151b4c8d125c12566ab0d74dc9cdba36fb80eb7b848c15f495fd32d1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "pyo3" version = "0.20.0" @@ -2444,9 +3042,9 @@ dependencies = [ "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash", + "rustc-hash 1.1.0", "rustls", - "thiserror 1.0.50", + "thiserror 1.0.69", "tokio", "tracing", ] @@ -2460,10 +3058,10 @@ dependencies = [ "bytes", "rand", "ring", - "rustc-hash", + "rustc-hash 1.1.0", "rustls", "slab", - "thiserror 1.0.50", + "thiserror 1.0.69", "tinyvec", "tracing", ] @@ -2496,6 +3094,15 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" +[[package]] +name = "rancor" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf5f7161924b9d1cea0e4cabc97c372cea92b5f927fc13c6bca67157a0ad947" +dependencies = [ + "ptr_meta 0.3.0", +] + [[package]] name = "rand" version = "0.8.5" @@ -2537,25 +3144,34 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.2" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata", - "regex-syntax 0.8.2", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", ] [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax 0.8.5", ] [[package]] @@ -2566,9 +3182,15 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "relative-path" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" [[package]] name = "rend" @@ -2576,7 +3198,16 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2571463863a6bd50c32f94402933f03457a3fbaf697a707c5be741e459f08fd" dependencies = [ - "bytecheck", + "bytecheck 0.6.11", +] + +[[package]] +name = "rend" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a35e8a6bf28cd121053a66aa2e6a2e3eaffad4a60012179f0e864aa5ffeff215" +dependencies = [ + "bytecheck 0.8.1", ] [[package]] @@ -2633,7 +3264,7 @@ dependencies = [ "http", "reqwest", "serde", - "thiserror 1.0.50", + "thiserror 1.0.69", "tower-service", ] @@ -2658,16 +3289,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0200c8230b013893c0b2d6213d6ec64ed2b9be2e0e016682b7224ff82cff5c58" dependencies = [ "bitvec", - "bytecheck", + "bytecheck 0.6.11", "hashbrown 0.12.3", - "ptr_meta", - "rend", - "rkyv_derive", + "ptr_meta 0.1.4", + "rend 0.4.1", + "rkyv_derive 0.7.42", "seahash", "tinyvec", "uuid 1.6.1", ] +[[package]] +name = "rkyv" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e147371c75553e1e2fcdb483944a8540b8438c31426279553b9a8182a9b7b65" +dependencies = [ + "bytecheck 0.8.1", + "bytes", + "hashbrown 0.15.2", + "indexmap 2.7.1", + "munge", + "ptr_meta 0.3.0", + "rancor", + "rend 0.5.2", + "rkyv_derive 0.8.10", + "tinyvec", + "uuid 1.6.1", +] + [[package]] name = "rkyv_derive" version = "0.7.42" @@ -2679,6 +3329,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "rkyv_derive" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "246b40ac189af6c675d124b802e8ef6d5246c53e17367ce9501f8f66a81abb7a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "rust_decimal" version = "1.33.1" @@ -2691,7 +3352,7 @@ dependencies = [ "num-traits", "postgres", "rand", - "rkyv", + "rkyv 0.7.42", "serde", "serde_json", ] @@ -2709,12 +3370,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "semver", + "semver 1.0.23", ] [[package]] @@ -2723,7 +3399,7 @@ version = "0.38.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.8.0", "errno", "libc", "linux-raw-sys", @@ -2773,9 +3449,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" [[package]] name = "ryu" @@ -2783,6 +3459,12 @@ version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +[[package]] +name = "ryu-js" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad97d4ce1560a5e27cec89519dc8300d1aa6035b099821261c651486a19e44d5" + [[package]] name = "same-file" version = "1.0.6" @@ -2798,6 +3480,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ece8e78b2f38ec51c51f5d475df0a7187ba5111b2a28bdc761ee05b075d40a71" +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "scopeguard" version = "1.2.0" @@ -2816,11 +3504,29 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e388332cd64eb80cd595a00941baf513caffae8dce9cfd0467fc9c66397dade6" +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + [[package]] name = "semver" version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +dependencies = [ + "serde", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "send_wrapper" @@ -2830,18 +3536,18 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.215" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.215" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", @@ -2850,11 +3556,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.133" +version = "1.0.138" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" dependencies = [ - "indexmap 2.4.0", + "indexmap 2.7.1", "itoa", "memchr", "ryu", @@ -2911,6 +3617,21 @@ dependencies = [ "digest", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -2920,6 +3641,15 @@ dependencies = [ "libc", ] +[[package]] +name = "simd-abstraction" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cadb29c57caadc51ff8346233b5cec1d240b68ce55cf1afc764818791876987" +dependencies = [ + "outref", +] + [[package]] name = "simdutf8" version = "0.1.4" @@ -2960,6 +3690,17 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +[[package]] +name = "smartstring" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29" +dependencies = [ + "autocfg", + "static_assertions", + "version_check", +] + [[package]] name = "snap" version = "1.1.1" @@ -2976,6 +3717,25 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "sourcemap" +version = "9.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27c4ea7042fd1a155ad95335b5d505ab00d5124ea0332a06c8390d200bb1a76a" +dependencies = [ + "base64-simd", + "bitvec", + "data-encoding", + "debugid", + "if_chain", + "rustc-hash 1.1.0", + "rustc_version 0.2.3", + "serde", + "serde_json", + "unicode-id-start", + "url", +] + [[package]] name = "spin" version = "0.9.8" @@ -2990,12 +3750,43 @@ dependencies = [ "log", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "stacker" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d08feb8f695b465baed819b03c128dc23f57a694510ab1f06c77f763975685e" +dependencies = [ + "cc", + "cfg-if", + "libc", + "psm", + "windows-sys 0.52.0", +] + [[package]] name = "static_assertions" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "string_enum" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9fe66b8ee349846ce2f9557a26b8f1e74843c4a13fb381f9a3d73617a5f956a" +dependencies = [ + "proc-macro2", + "quote", + "swc_macros_common", + "syn 2.0.90", +] + [[package]] name = "stringprep" version = "0.1.4" @@ -3007,6 +3798,12 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "strum" version = "0.23.0" @@ -3051,6 +3848,367 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +[[package]] +name = "swc_allocator" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a1f988452cab8c4e25776e5a855ba088cdb38fbe9714f9b9d2a6ff345824858" +dependencies = [ + "bumpalo", + "hashbrown 0.14.5", + "ptr_meta 0.3.0", + "rustc-hash 2.1.1", + "triomphe", +] + +[[package]] +name = "swc_atoms" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c24077f986f0bc1c07823f850f688dd9be91b186efdb03fe1d52f7c2f2a4a346" +dependencies = [ + "bytecheck 0.8.1", + "hstr", + "once_cell", + "rancor", + "rkyv 0.8.10", + "rustc-hash 2.1.1", + "serde", +] + +[[package]] +name = "swc_common" +version = "6.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7327d132e85f8a50e0a9e2458a7b44726b2db2f7f9c8b8a556f07f359c42a461" +dependencies = [ + "anyhow", + "ast_node", + "better_scoped_tls", + "bytecheck 0.8.1", + "cfg-if", + "either", + "from_variant", + "new_debug_unreachable", + "num-bigint", + "once_cell", + "parking_lot", + "rancor", + "rkyv 0.8.10", + "rustc-hash 2.1.1", + "serde", + "siphasher", + "sourcemap", + "swc_allocator", + "swc_atoms", + "swc_eq_ignore_macros", + "swc_visit", + "termcolor", + "tracing", + "unicode-width", + "url", +] + +[[package]] +name = "swc_core" +version = "13.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94c8a27be20f13eb5b27e623b0d9ef486d861066b5f725e23ed38ca0e560dcca" +dependencies = [ + "once_cell", + "swc_allocator", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_transforms_base", + "swc_ecma_transforms_testing", + "swc_ecma_visit", + "swc_plugin", + "swc_plugin_macro", + "swc_plugin_proxy", + "vergen", +] + +[[package]] +name = "swc_ecma_ast" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbd513dab5fb1181e66ac34c4c959e9e8824d8d2c8bd50f698f5f2943794c0cc" +dependencies = [ + "bitflags 2.8.0", + "bytecheck 0.8.1", + "is-macro", + "num-bigint", + "phf", + "rancor", + "rkyv 0.8.10", + "scoped-tls", + "string_enum", + "swc_atoms", + "swc_common", + "swc_visit", + "unicode-id-start", +] + +[[package]] +name = "swc_ecma_codegen" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa6bdce26d910981128bc709a997292a5d1c98d54a9832154a1083d1adb6fdd7" +dependencies = [ + "ascii", + "compact_str", + "memchr", + "num-bigint", + "once_cell", + "regex", + "rustc-hash 2.1.1", + "serde", + "sourcemap", + "swc_allocator", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_codegen_macros", + "tracing", +] + +[[package]] +name = "swc_ecma_codegen_macros" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f9a42f479a6475647e248fa9750982c87cd985e19d1016a1fc18a70682305d1" +dependencies = [ + "proc-macro2", + "quote", + "swc_macros_common", + "syn 2.0.90", +] + +[[package]] +name = "swc_ecma_parser" +version = "8.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a359eaebed82e5e13e1004d1e4003931b66d8b8edab8884f3d02ed827df7530" +dependencies = [ + "either", + "new_debug_unreachable", + "num-bigint", + "num-traits", + "phf", + "rustc-hash 2.1.1", + "serde", + "smallvec", + "smartstring", + "stacker", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "tracing", + "typed-arena", +] + +[[package]] +name = "swc_ecma_testing" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46f1b2d6510edc0f54f0856c2e776b5673c3df8088dd0bda8d97ba197d054133" +dependencies = [ + "anyhow", + "hex", + "sha2", + "testing", + "tracing", +] + +[[package]] +name = "swc_ecma_transforms_base" +version = "9.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b696e003dd095ae8b8dba00f601040f756273c9af0fd67cb1c57115785cb5ec" +dependencies = [ + "better_scoped_tls", + "bitflags 2.8.0", + "indexmap 2.7.1", + "once_cell", + "phf", + "rustc-hash 2.1.1", + "serde", + "smallvec", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_parser", + "swc_ecma_utils", + "swc_ecma_visit", + "swc_parallel", + "tracing", +] + +[[package]] +name = "swc_ecma_transforms_testing" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f1ad440cfdcafabcc4ab8bb01df2d1a488f65cdad8dc85de821f66ebcedca55" +dependencies = [ + "ansi_term", + "anyhow", + "base64 0.21.5", + "hex", + "serde", + "serde_json", + "sha2", + "sourcemap", + "swc_allocator", + "swc_common", + "swc_ecma_ast", + "swc_ecma_codegen", + "swc_ecma_parser", + "swc_ecma_testing", + "swc_ecma_transforms_base", + "swc_ecma_utils", + "swc_ecma_visit", + "tempfile", + "testing", +] + +[[package]] +name = "swc_ecma_utils" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c217edaa22c98537e09ed3189e723feed3d889eeb7e02a0b3d48cbb91ba7e4" +dependencies = [ + "indexmap 2.7.1", + "num_cpus", + "once_cell", + "rustc-hash 2.1.1", + "ryu-js", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_visit", + "swc_parallel", + "tracing", + "unicode-id", +] + +[[package]] +name = "swc_ecma_visit" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a32fb2902c01f9b4615605a4a3e67e0c928bd3b9f2182e764f1c9fe4130965cf" +dependencies = [ + "new_debug_unreachable", + "num-bigint", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_visit", + "tracing", +] + +[[package]] +name = "swc_eq_ignore_macros" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e96e15288bf385ab85eb83cff7f9e2d834348da58d0a31b33bdb572e66ee413e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "swc_error_reporters" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed21ea887faeb0dab190838d2331ed187f2a74d185c9fe7044d5092900a83d29" +dependencies = [ + "anyhow", + "miette", + "once_cell", + "parking_lot", + "swc_common", +] + +[[package]] +name = "swc_macros_common" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a509f56fca05b39ba6c15f3e58636c3924c78347d63853632ed2ffcb6f5a0ac7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "swc_parallel" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5f75f1094d69174ef628e3665fff0f81d58e9f568802e3c90d332c72b0b6026" +dependencies = [ + "once_cell", +] + +[[package]] +name = "swc_plugin" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b45099a38ed45528bef939d0eac1a0c1347749d0c67d3dd744d545316c5fd05" +dependencies = [ + "once_cell", +] + +[[package]] +name = "swc_plugin_macro" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0917ccfdcd3fa6cf41bdacef2388702a3b274f9ea708d930e1e8db37c7c3e1c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "swc_plugin_proxy" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e8ae3974157b2939ada468ffec7932358f2f567abb6c237204dd603e52ffff" +dependencies = [ + "better_scoped_tls", + "bytecheck 0.8.1", + "rancor", + "rkyv 0.8.10", + "rustc-hash 2.1.1", + "swc_common", + "swc_ecma_ast", + "swc_trace_macro", + "tracing", +] + +[[package]] +name = "swc_trace_macro" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c78717a841565df57f811376a3d19c9156091c55175e12d378f3a522de70cef" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "swc_visit" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9138b6a36bbe76dd6753c4c0794f7e26480ea757bee499738bedbbb3ae3ec5f3" +dependencies = [ + "either", + "new_debug_unreachable", +] + [[package]] name = "symbol_table" version = "0.2.0" @@ -3125,6 +4283,17 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "tap" version = "1.0.1" @@ -3166,13 +4335,70 @@ dependencies = [ "unic-segment", ] +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "testing" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60326bf11ba23afed0b731866c6e8b709d516554dc813bb3a91f8a273f22f333" +dependencies = [ + "ansi_term", + "cargo_metadata 0.18.1", + "difference", + "once_cell", + "pretty_assertions", + "regex", + "rustc-hash 2.1.1", + "serde", + "serde_json", + "swc_common", + "swc_error_reporters", + "testing_macros", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "testing_macros" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2d27bf245b90a80d5aa231133418ae7db98f032855ce5292e12071ab29c4b26" +dependencies = [ + "anyhow", + "glob", + "once_cell", + "proc-macro2", + "quote", + "regex", + "relative-path", + "syn 2.0.90", +] + +[[package]] +name = "textwrap" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" +dependencies = [ + "unicode-linebreak", + "unicode-width", +] + [[package]] name = "thiserror" -version = "1.0.50" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl 1.0.50", + "thiserror-impl 1.0.69", ] [[package]] @@ -3186,9 +4412,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", @@ -3238,6 +4464,16 @@ dependencies = [ "threadpool", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -3371,7 +4607,7 @@ version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" dependencies = [ - "indexmap 2.4.0", + "indexmap 2.7.1", "toml_datetime", "winnow", ] @@ -3434,6 +4670,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "triomphe" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef8f7726da4807b58ea5c96fdc122f80702030edc33b35aff9190a51148ccc85" +dependencies = [ + "serde", + "stable_deref_trait", ] [[package]] @@ -3456,11 +4732,17 @@ dependencies = [ "log", "rand", "sha1", - "thiserror 1.0.50", + "thiserror 1.0.69", "url", "utf-8", ] +[[package]] +name = "typed-arena" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" + [[package]] name = "typenum" version = "1.17.0" @@ -3547,12 +4829,30 @@ version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" +[[package]] +name = "unicode-id" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10103c57044730945224467c09f71a4db0071c123a0648cc3e818913bde6b561" + +[[package]] +name = "unicode-id-start" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f322b60f6b9736017344fa0635d64be2f458fbc04eef65f6be22976dd1ffd5b" + [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "unicode-linebreak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" + [[package]] name = "unicode-normalization" version = "0.1.22" @@ -3588,9 +4888,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.0" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", @@ -3603,6 +4903,18 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "uuid" version = "0.8.2" @@ -3622,6 +4934,12 @@ dependencies = [ "serde", ] +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + [[package]] name = "vectorize" version = "0.2.0" @@ -3631,6 +4949,31 @@ dependencies = [ "serde", ] +[[package]] +name = "vergen" +version = "9.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0d2f179f8075b805a43a2a21728a46f0cc2921b3c58695b28fa8817e103cd9a" +dependencies = [ + "anyhow", + "cargo_metadata 0.19.1", + "derive_builder", + "regex", + "rustversion", + "vergen-lib", +] + +[[package]] +name = "vergen-lib" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b07e6010c0f3e59fcb164e0163834597da68d1f864e2b8ca49f74de01e9c166" +dependencies = [ + "anyhow", + "derive_builder", + "rustversion", +] + [[package]] name = "version_check" version = "0.9.4" @@ -3948,6 +5291,18 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "wyz" version = "0.5.1" @@ -3957,6 +5312,36 @@ dependencies = [ "tap", ] +[[package]] +name = "yansi" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" + +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", + "synstructure", +] + [[package]] name = "zerocopy" version = "0.7.32" @@ -3977,12 +5362,55 @@ dependencies = [ "syn 2.0.90", ] +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", + "synstructure", +] + [[package]] name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "zstd" version = "0.11.2+zstd.1.5.2" diff --git a/packages/cubejs-backend-native/Cargo.toml b/packages/cubejs-backend-native/Cargo.toml index 37ddb4094c1c1..d0c33ff5fac01 100644 --- a/packages/cubejs-backend-native/Cargo.toml +++ b/packages/cubejs-backend-native/Cargo.toml @@ -18,6 +18,7 @@ crate-type = ["cdylib", "lib"] [dependencies] cubesqlplanner = { path = "../../rust/cubesqlplanner/cubesqlplanner" } cubeorchestrator = { path = "../../rust/cubeorchestrator" } +cubetranspilers = { path = "../../rust/cubetranspilers" } cubenativeutils = { path = "../../rust/cubenativeutils" } cubesql = { path = "../../rust/cubesql/cubesql" } anyhow = "1.0" @@ -36,8 +37,11 @@ minijinja = { version = "1", features = ["json", "loader"] } once_cell = "1.10" # python pyo3 = { version = "0.20.0", features = [], optional = true } -pyo3-asyncio = { version = "0.20.0", features = ["tokio-runtime", "attributes"], optional = true } -serde = { version = "1.0.209", features = ["derive"] } +pyo3-asyncio = { version = "0.20.0", features = [ + "tokio-runtime", + "attributes", +], optional = true } +serde = { version = "1.0.217", features = ["derive"] } serde_json = "1.0.127" simple_logger = "1.7.0" tokio = { version = "1", features = ["full", "rt"] } diff --git a/packages/cubejs-backend-native/js/index.ts b/packages/cubejs-backend-native/js/index.ts index f6c54477f463f..bd15636e85684 100644 --- a/packages/cubejs-backend-native/js/index.ts +++ b/packages/cubejs-backend-native/js/index.ts @@ -101,6 +101,22 @@ export type SQLInterfaceOptions = { gatewayPort?: number, }; +export interface TransformConfig { + fileName: string; + transpilers: string[]; + metaData?: { + cubeNames: string[]; + cubeSymbols: Record>; + contextSymbols: Record; + } +} + +export interface TransformResponse { + code: string; + errors: string[]; + warnings: string[]; +} + export type DBResponsePrimitive = null | boolean | @@ -405,6 +421,12 @@ export const getFinalQueryResultMulti = (transformDataArr: Object[], rows: any[] return native.getFinalQueryResultMulti(transformDataArr, rows, responseData); }; +export const transpileJs = async (content: String, metadata: TransformConfig): Promise => { + const native = loadNative(); + + return native.transpileJs(content, metadata); +}; + export interface PyConfiguration { repositoryFactory?: (ctx: unknown) => Promise, logger?: (msg: string, params: Record) => void, diff --git a/packages/cubejs-backend-native/src/lib.rs b/packages/cubejs-backend-native/src/lib.rs index 60104692c697f..516db7b1c5af8 100644 --- a/packages/cubejs-backend-native/src/lib.rs +++ b/packages/cubejs-backend-native/src/lib.rs @@ -17,6 +17,7 @@ pub mod orchestrator; pub mod python; pub mod stream; pub mod template; +pub mod transpilers; pub mod transport; pub mod utils; diff --git a/packages/cubejs-backend-native/src/node_export.rs b/packages/cubejs-backend-native/src/node_export.rs index 802076279c47d..b34d00c646ef1 100644 --- a/packages/cubejs-backend-native/src/node_export.rs +++ b/packages/cubejs-backend-native/src/node_export.rs @@ -510,6 +510,9 @@ pub fn register_module_exports( //========= sql orchestrator exports ================= crate::orchestrator::register_module(&mut cx)?; + //========= transpilers exports ================= + crate::transpilers::register_module(&mut cx)?; + crate::template::template_register_module(&mut cx)?; #[cfg(feature = "python")] diff --git a/packages/cubejs-backend-native/src/transpilers.rs b/packages/cubejs-backend-native/src/transpilers.rs new file mode 100644 index 0000000000000..3d423926adf6d --- /dev/null +++ b/packages/cubejs-backend-native/src/transpilers.rs @@ -0,0 +1,91 @@ +use crate::node_obj_deserializer::JsValueDeserializer; +use crate::node_obj_serializer::NodeObjSerializer; +use anyhow::anyhow; +use cubetranspilers::{run_transpilers, TransformConfig, Transpilers}; +use neon::context::{Context, FunctionContext, ModuleContext}; +use neon::prelude::{JsPromise, JsResult, JsValue, NeonResult}; +use neon::types::JsString; +use serde::Deserialize; +use std::collections::{HashMap, HashSet}; +use std::sync::RwLock; + +#[derive(Deserialize, Default, Clone, Debug)] +#[serde(rename_all = "camelCase")] +pub struct TransformMetaData { + pub cube_names: HashSet, + pub cube_symbols: HashMap>, + pub context_symbols: HashMap, +} + +#[derive(Deserialize, Clone, Debug)] +#[serde(rename_all = "camelCase")] +pub struct TransformRequestConfig { + pub file_name: String, + pub transpilers: Vec, + pub meta_data: Option, +} + +static METADATA_CACHE: RwLock> = RwLock::new(None); + +pub fn register_module(cx: &mut ModuleContext) -> NeonResult<()> { + cx.export_function("transpileJs", transpile_js)?; + + Ok(()) +} + +pub fn transpile_js(mut cx: FunctionContext) -> JsResult { + let content = cx.argument::(0)?.value(&mut cx); + let transform_data_js_object = cx.argument::(1)?; + let deserializer = JsValueDeserializer::new(&mut cx, transform_data_js_object); + let transform_request_config = TransformRequestConfig::deserialize(deserializer); + + let promise = cx + .task(move || { + let transform_config: TransformConfig = match transform_request_config { + Ok(data) => match data.meta_data { + Some(meta_data) => { + let mut config_lock = METADATA_CACHE.write().unwrap(); + let cache = TransformMetaData { + cube_names: meta_data.cube_names, + cube_symbols: meta_data.cube_symbols, + context_symbols: meta_data.context_symbols, + }; + let cfg = TransformConfig { + file_name: data.file_name, + transpilers: data.transpilers, + cube_names: cache.cube_names.clone(), + cube_symbols: cache.cube_symbols.clone(), + context_symbols: cache.context_symbols.clone(), + }; + *config_lock = Some(cache); + cfg + } + None => { + let cache = METADATA_CACHE.read().unwrap().clone().unwrap_or_default(); + TransformConfig { + file_name: data.file_name, + transpilers: data.transpilers, + cube_names: cache.cube_names.clone(), + cube_symbols: cache.cube_symbols.clone(), + context_symbols: cache.context_symbols.clone(), + } + } + }, + Err(err) => return Err(anyhow!("Failed to deserialize input data: {}", err)), + }; + + run_transpilers(content, transform_config) + }) + .promise(move |mut cx, res| match res { + Ok(result) => { + let obj = match NodeObjSerializer::serialize(&result, &mut cx) { + Ok(data) => data, + Err(err) => return cx.throw_error(err.to_string()), + }; + Ok(obj) + } + Err(err) => cx.throw_error(err.to_string()), + }); + + Ok(promise) +} diff --git a/packages/cubejs-backend-shared/src/env.ts b/packages/cubejs-backend-shared/src/env.ts index 2f8760f412c35..f6df8bd4bf933 100644 --- a/packages/cubejs-backend-shared/src/env.ts +++ b/packages/cubejs-backend-shared/src/env.ts @@ -229,6 +229,10 @@ const variables: Record any> = { transpilationWorkerThreadsCount: () => get('CUBEJS_TRANSPILATION_WORKER_THREADS_COUNT') .default('0') .asInt(), + // This one takes precedence over CUBEJS_TRANSPILATION_WORKER_THREADS + transpilationNative: () => get('CUBEJS_TRANSPILATION_NATIVE') + .default('false') + .asBoolStrict(), /** **************************************************************** * Common db options * diff --git a/packages/cubejs-jdbc-driver/package.json b/packages/cubejs-jdbc-driver/package.json index 33319f5e63f69..d44800d09c518 100644 --- a/packages/cubejs-jdbc-driver/package.json +++ b/packages/cubejs-jdbc-driver/package.json @@ -44,7 +44,7 @@ }, "devDependencies": { "@cubejs-backend/linter": "1.2.5", - "@cubejs-backend/shared": "1.2.4", + "@cubejs-backend/shared": "1.2.5", "@types/generic-pool": "^3.1.9", "@types/node": "^18", "@types/sqlstring": "^2.3.0", diff --git a/packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js b/packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js index cd087329b9dfd..181ad13f97419 100644 --- a/packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js +++ b/packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.js @@ -9,8 +9,10 @@ import R from 'ramda'; import workerpool from 'workerpool'; import { getEnv, isNativeSupported } from '@cubejs-backend/shared'; +import { transpileJs } from '@cubejs-backend/native'; import { UserError } from './UserError'; import { ErrorReporter } from './ErrorReporter'; +import { CONTEXT_SYMBOLS } from './CubeSymbols'; const NATIVE_IS_SUPPORTED = isNativeSupported(); @@ -93,7 +95,10 @@ export class DataSchemaCompiler { const errorsReport = new ErrorReporter(null, [], this.errorReport); this.errorsReport = errorsReport; - if (getEnv('transpilationWorkerThreads')) { + const transpilationWorkerThreads = getEnv('transpilationWorkerThreads'); + const transpilationNative = getEnv('transpilationNative'); + + if (!transpilationNative && transpilationWorkerThreads) { const wc = getEnv('transpilationWorkerThreadsCount'); this.workerPool = workerpool.pool( path.join(__dirname, 'transpilers/transpiler_worker'), @@ -103,9 +108,11 @@ export class DataSchemaCompiler { const transpile = async () => { let cubeNames; - let cubeSymbolsNames; + let cubeSymbols; + let transpilerNames; + let results; - if (getEnv('transpilationWorkerThreads')) { + if (transpilationNative || transpilationWorkerThreads) { cubeNames = Object.keys(this.cubeDictionary.byId); // We need only cubes and all its member names for transpiling. // Cubes doesn't change during transpiling, but are changed during compilation phase, @@ -113,7 +120,8 @@ export class DataSchemaCompiler { // Communication between main and worker threads uses // The structured clone algorithm (@see https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm) // which doesn't allow passing any function objects, so we need to sanitize the symbols. - cubeSymbolsNames = Object.fromEntries( + // Communication with native backend also involves deserialization. + cubeSymbols = Object.fromEntries( Object.entries(this.cubeSymbols.symbols) .map( ([key, value]) => [key, Object.fromEntries( @@ -121,8 +129,27 @@ export class DataSchemaCompiler { )], ), ); + + // Transpilers are the same for all files within phase. + transpilerNames = this.transpilers.map(t => t.constructor.name); + } + + if (transpilationNative) { + // Warming up swc compiler cache + const dummyFile = { + fileName: 'dummy.js', + content: ';', + }; + + await this.transpileJsFile(dummyFile, errorsReport, { cubeNames, cubeSymbols, transpilerNames, contextSymbols: CONTEXT_SYMBOLS }); + + results = await Promise.all(toCompile.map(f => this.transpileFile(f, errorsReport, { transpilerNames }))); + } else if (transpilationWorkerThreads) { + results = await Promise.all(toCompile.map(f => this.transpileFile(f, errorsReport, { cubeNames, cubeSymbols, transpilerNames }))); + } else { + results = await Promise.all(toCompile.map(f => this.transpileFile(f, errorsReport, {}))); } - const results = await Promise.all(toCompile.map(f => this.transpileFile(f, errorsReport, { cubeNames, cubeSymbolsNames }))); + return results.filter(f => !!f); }; @@ -138,9 +165,19 @@ export class DataSchemaCompiler { contextCompilers: this.contextCompilers, })) .then(() => { - if (this.workerPool) { + if (transpilationNative) { + // Clean up cache + const dummyFile = { + fileName: 'terminate.js', + content: ';', + }; + + return this.transpileJsFile(dummyFile, errorsReport, { cubeNames: [], cubeSymbols: {}, transpilerNames: [], contextSymbols: {} }); + } else if (transpilationWorkerThreads && this.workerPool) { this.workerPool.terminate(); } + + return Promise.resolve(); }); } @@ -182,15 +219,35 @@ export class DataSchemaCompiler { } } - async transpileJsFile(file, errorsReport, { cubeNames, cubeSymbolsNames }) { + async transpileJsFile(file, errorsReport, { cubeNames, cubeSymbols, contextSymbols, transpilerNames }) { try { - if (getEnv('transpilationWorkerThreads')) { + if (getEnv('transpilationNative')) { + const reqData = { + fileName: file.fileName, + transpilers: transpilerNames, + ...(cubeNames && { + metaData: { + cubeNames, + cubeSymbols, + contextSymbols, + }, + }), + }; + + errorsReport.inFile(file); + const res = await transpileJs(file.content, reqData); + errorsReport.addErrors(res.errors); + errorsReport.addWarnings(res.warnings); + errorsReport.exitFile(); + + return Object.assign({}, file, { content: res.code }); + } else if (getEnv('transpilationWorkerThreads')) { const data = { fileName: file.fileName, content: file.content, - transpilers: this.transpilers.map(t => t.constructor.name), + transpilers: transpilerNames, cubeNames, - cubeSymbolsNames, + cubeSymbols, }; const res = await this.workerPool.exec('transpile', [data]); @@ -208,11 +265,11 @@ export class DataSchemaCompiler { }, ); + errorsReport.inFile(file); this.transpilers.forEach((t) => { - errorsReport.inFile(file); babelTraverse(ast, t.traverseObject(errorsReport)); - errorsReport.exitFile(); }); + errorsReport.exitFile(); const content = babelGenerator(ast, {}, file.content).code; return Object.assign({}, file, { content }); diff --git a/packages/cubejs-schema-compiler/src/compiler/ErrorReporter.ts b/packages/cubejs-schema-compiler/src/compiler/ErrorReporter.ts index bf48792f4a3ab..5e89c2ca1acb0 100644 --- a/packages/cubejs-schema-compiler/src/compiler/ErrorReporter.ts +++ b/packages/cubejs-schema-compiler/src/compiler/ErrorReporter.ts @@ -108,7 +108,7 @@ export class ErrorReporter { } public error(e: any, fileName?: any, lineNumber?: any, position?: any) { - const message = `${this.context.length ? `${this.context.join(' -> ')}: ` : ''}${e instanceof UserError ? e.message : (e.stack || e)}`; + const message = `${this.context.length ? `${this.context.join(' -> ')}: ` : ''}${e.message ? e.message : (e.stack || e)}`; if (this.rootReporter().errors.find(m => (m.message || m) === message)) { return; } @@ -141,16 +141,16 @@ export class ErrorReporter { return this.rootReporter().errors; } - public addErrors(errors: CompilerErrorInterface[]) { - this.rootReporter().errors.push(...errors); + public addErrors(errors: any[]) { + errors.forEach((e: any) => { this.error(e); }); } public getWarnings() { return this.rootReporter().warnings; } - public addWarnings(warnings: SyntaxErrorInterface[]) { - this.rootReporter().warnings.push(...warnings); + public addWarnings(warnings: any[]) { + warnings.forEach((w: any) => { this.warning(w); }); } protected rootReporter(): ErrorReporter { diff --git a/packages/cubejs-schema-compiler/src/compiler/transpilers/transpiler_worker.ts b/packages/cubejs-schema-compiler/src/compiler/transpilers/transpiler_worker.ts index 0d5d87ffc9f46..93c1c142744f0 100644 --- a/packages/cubejs-schema-compiler/src/compiler/transpilers/transpiler_worker.ts +++ b/packages/cubejs-schema-compiler/src/compiler/transpilers/transpiler_worker.ts @@ -16,7 +16,7 @@ type TransferContent = { content: string; transpilers: string[]; cubeNames: string[]; - cubeSymbolsNames: Record>; + cubeSymbols: Record>; }; const cubeDictionary = new LightweightNodeCubeDictionary(); @@ -32,7 +32,7 @@ const transpilers = { const transpile = (data: TransferContent) => { cubeDictionary.setCubeNames(data.cubeNames); - cubeSymbols.setSymbols(data.cubeSymbolsNames); + cubeSymbols.setSymbols(data.cubeSymbols); const ast = parse( data.content, @@ -43,15 +43,15 @@ const transpile = (data: TransferContent) => { }, ); + errorsReport.inFile(data); data.transpilers.forEach(transpilerName => { if (transpilers[transpilerName]) { - errorsReport.inFile(data); babelTraverse(ast, transpilers[transpilerName].traverseObject(errorsReport)); - errorsReport.exitFile(); } else { throw new Error(`Transpiler ${transpilerName} not supported`); } }); + errorsReport.exitFile(); const content = babelGenerator(ast, {}, data.content).code; diff --git a/packages/cubejs-schema-compiler/test/unit/transpilers.test.ts b/packages/cubejs-schema-compiler/test/unit/transpilers.test.ts index 56a53ee3d0a37..30e48a8a2eeb0 100644 --- a/packages/cubejs-schema-compiler/test/unit/transpilers.test.ts +++ b/packages/cubejs-schema-compiler/test/unit/transpilers.test.ts @@ -27,7 +27,7 @@ describe('Transpilers', () => { throw new Error('Compile should thrown an error'); } catch (e: any) { - expect(e.message).toMatch(/Duplicate property parsing test1 in main.js/); + expect(e.message).toMatch(/Duplicate property parsing test1/); } }); diff --git a/rust/cubeorchestrator/Cargo.lock b/rust/cubeorchestrator/Cargo.lock index f4a1156cfff88..35a40dd365fed 100644 --- a/rust/cubeorchestrator/Cargo.lock +++ b/rust/cubeorchestrator/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -341,18 +341,18 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.215" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.215" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", diff --git a/rust/cubeorchestrator/Cargo.toml b/rust/cubeorchestrator/Cargo.toml index 0605d4608ae08..140932619d253 100644 --- a/rust/cubeorchestrator/Cargo.toml +++ b/rust/cubeorchestrator/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] chrono = { version = "0.4.31", features = ["serde"] } cubeshared = { path = "../cubeshared" } -serde = { version = "1.0.215", features = ["derive"] } +serde = { version = "1.0.217", features = ["derive"] } serde_json = "1.0.133" anyhow = "1.0" itertools = "0.13.0" diff --git a/rust/cubestore/package.json b/rust/cubestore/package.json index 1096bf92660ad..311443507d022 100644 --- a/rust/cubestore/package.json +++ b/rust/cubestore/package.json @@ -27,7 +27,7 @@ "author": "Cube Dev, Inc.", "license": "Apache-2.0", "devDependencies": { - "@cubejs-backend/linter": "1.2.4", + "@cubejs-backend/linter": "1.2.5", "@types/jest": "^27", "@types/node": "^12", "jest": "^27", @@ -37,7 +37,7 @@ "access": "public" }, "dependencies": { - "@cubejs-backend/shared": "1.2.4", + "@cubejs-backend/shared": "1.2.5", "@octokit/core": "^3.2.5", "source-map-support": "^0.5.19" }, diff --git a/rust/cubetranspilers/.gitignore b/rust/cubetranspilers/.gitignore new file mode 100644 index 0000000000000..2a0a960cb1ec5 --- /dev/null +++ b/rust/cubetranspilers/.gitignore @@ -0,0 +1,3 @@ +/target +/.idea +.vscode diff --git a/rust/cubetranspilers/Cargo.lock b/rust/cubetranspilers/Cargo.lock new file mode 100644 index 0000000000000..96877ea25973c --- /dev/null +++ b/rust/cubetranspilers/Cargo.lock @@ -0,0 +1,2347 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "anyhow" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" + +[[package]] +name = "ascii" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16" + +[[package]] +name = "ast_node" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91fb5864e2f5bf9fd9797b94b2dfd1554d4c3092b535008b27d7e15c86675a2f" +dependencies = [ + "proc-macro2", + "quote", + "swc_macros_common", + "syn", +] + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64-simd" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "781dd20c3aff0bd194fe7d2a977dd92f21c173891f3a03b677359e5fa457e5d5" +dependencies = [ + "simd-abstraction", +] + +[[package]] +name = "better_scoped_tls" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50fd297a11c709be8348aec039c8b91de16075d2b2bdaee1bd562c0875993664" +dependencies = [ + "scoped-tls", +] + +[[package]] +name = "bitflags" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" +dependencies = [ + "allocator-api2", +] + +[[package]] +name = "bytecheck" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50690fb3370fb9fe3550372746084c46f2ac8c9685c583d2be10eefd89d3d1a3" +dependencies = [ + "bytecheck_derive", + "ptr_meta", + "rancor", + "simdutf8", +] + +[[package]] +name = "bytecheck_derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efb7846e0cb180355c2dec69e721edafa36919850f1a9f52ffba4ebc0393cb71" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "bytes" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9" + +[[package]] +name = "camino" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" +dependencies = [ + "camino", + "cargo-platform", + "semver 1.0.25", + "serde", + "serde_json", + "thiserror 1.0.69", +] + +[[package]] +name = "cargo_metadata" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8769706aad5d996120af43197bf46ef6ad0fda35216b4505f926a365a232d924" +dependencies = [ + "camino", + "cargo-platform", + "semver 1.0.25", + "serde", + "serde_json", + "thiserror 2.0.11", +] + +[[package]] +name = "castaway" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0abae9be0aaf9ea96a3b1b8b1b55c602ca751eba1b1500220cea4ecbafe7c0d5" +dependencies = [ + "rustversion", +] + +[[package]] +name = "cc" +version = "1.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c3d1b2e905a3a7b00a6141adb0e4c0bb941d11caf55349d863942a1cc44e3c9" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "compact_str" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f86b9c4c00838774a6d902ef931eff7470720c51d90c2e32cfe15dc304737b3f" +dependencies = [ + "castaway", + "cfg-if", + "itoa", + "ryu", + "static_assertions", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "cubetranspilers" +version = "0.1.0" +dependencies = [ + "anyhow", + "indexmap", + "regex", + "serde", + "serde_json", + "swc_core", + "swc_ecma_codegen", + "swc_ecma_parser", +] + +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "data-encoding" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010" + +[[package]] +name = "debugid" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" +dependencies = [ + "serde", + "uuid", +] + +[[package]] +name = "derive_builder" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" +dependencies = [ + "derive_builder_core", + "syn", +] + +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + +[[package]] +name = "difference" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "from_variant" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d7ccf961415e7aa17ef93dcb6c2441faaa8e768abe09e659b908089546f74c5" +dependencies = [ + "proc-macro2", + "swc_macros_common", + "syn", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +dependencies = [ + "cfg-if", + "libc", + "wasi", + "windows-targets", +] + +[[package]] +name = "glob" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hstr" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a26def229ea95a8709dad32868d975d0dd40235bd2ce82920e4a8fe692b5e0" +dependencies = [ + "hashbrown 0.14.5", + "new_debug_unreachable", + "once_cell", + "phf", + "rustc-hash 1.1.0", + "triomphe", +] + +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "if_chain" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" + +[[package]] +name = "indexmap" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +dependencies = [ + "equivalent", + "hashbrown 0.15.2", +] + +[[package]] +name = "is-macro" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d57a3e447e24c22647738e4607f1df1e0ec6f72e16182c4cd199f647cdfb0e4" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.169" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "litemap" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "miette" +version = "7.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a955165f87b37fd1862df2a59547ac542c77ef6d17c666f619d1ad22dd89484" +dependencies = [ + "cfg-if", + "miette-derive", + "owo-colors", + "textwrap", + "thiserror 1.0.69", + "unicode-width", +] + +[[package]] +name = "miette-derive" +version = "7.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf45bf44ab49be92fd1227a3be6fc6f617f1a337c06af54981048574d8783147" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "munge" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64142d38c84badf60abf06ff9bd80ad2174306a5b11bd4706535090a30a419df" +dependencies = [ + "munge_macro", +] + +[[package]] +name = "munge_macro" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bb5c1d8184f13f7d0ccbeeca0def2f9a181bce2624302793005f5ca8aa62e5e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", + "serde", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" + +[[package]] +name = "outref" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f222829ae9293e33a9f5e9f440c6760a3d450a64affe1846486b140db81c1f4" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "owo-colors" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb37767f6569cd834a413442455e0f066d0d522de8630436e2a1761d9726ba56" + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "phf" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +dependencies = [ + "phf_macros", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" +dependencies = [ + "phf_shared", + "rand", +] + +[[package]] +name = "phf_macros" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "phf_shared" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +dependencies = [ + "siphasher 1.0.1", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pretty_assertions" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" +dependencies = [ + "diff", + "yansi", +] + +[[package]] +name = "proc-macro2" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "psm" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200b9ff220857e53e184257720a14553b2f4aa02577d2ed9842d45d4b9654810" +dependencies = [ + "cc", +] + +[[package]] +name = "ptr_meta" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe9e76f66d3f9606f44e45598d155cb13ecf09f4a28199e48daf8c8fc937ea90" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca414edb151b4c8d125c12566ab0d74dc9cdba36fb80eb7b848c15f495fd32d1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "quote" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rancor" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf5f7161924b9d1cea0e4cabc97c372cea92b5f927fc13c6bca67157a0ad947" +dependencies = [ + "ptr_meta", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "redox_syscall" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "relative-path" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" + +[[package]] +name = "rend" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a35e8a6bf28cd121053a66aa2e6a2e3eaffad4a60012179f0e864aa5ffeff215" +dependencies = [ + "bytecheck", +] + +[[package]] +name = "rkyv" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e147371c75553e1e2fcdb483944a8540b8438c31426279553b9a8182a9b7b65" +dependencies = [ + "bytecheck", + "bytes", + "hashbrown 0.15.2", + "indexmap", + "munge", + "ptr_meta", + "rancor", + "rend", + "rkyv_derive", + "tinyvec", + "uuid", +] + +[[package]] +name = "rkyv_derive" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "246b40ac189af6c675d124b802e8ef6d5246c53e17367ce9501f8f66a81abb7a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "rustversion" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" + +[[package]] +name = "ryu" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" + +[[package]] +name = "ryu-js" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad97d4ce1560a5e27cec89519dc8300d1aa6035b099821261c651486a19e44d5" + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" +dependencies = [ + "serde", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "serde" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.138" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "simd-abstraction" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cadb29c57caadc51ff8346233b5cec1d240b68ce55cf1afc764818791876987" +dependencies = [ + "outref", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "smartstring" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29" +dependencies = [ + "autocfg", + "static_assertions", + "version_check", +] + +[[package]] +name = "sourcemap" +version = "9.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27c4ea7042fd1a155ad95335b5d505ab00d5124ea0332a06c8390d200bb1a76a" +dependencies = [ + "base64-simd", + "bitvec", + "data-encoding", + "debugid", + "if_chain", + "rustc-hash 1.1.0", + "rustc_version", + "serde", + "serde_json", + "unicode-id-start", + "url", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "stacker" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d08feb8f695b465baed819b03c128dc23f57a694510ab1f06c77f763975685e" +dependencies = [ + "cc", + "cfg-if", + "libc", + "psm", + "windows-sys", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "string_enum" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9fe66b8ee349846ce2f9557a26b8f1e74843c4a13fb381f9a3d73617a5f956a" +dependencies = [ + "proc-macro2", + "quote", + "swc_macros_common", + "syn", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "swc_allocator" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a1f988452cab8c4e25776e5a855ba088cdb38fbe9714f9b9d2a6ff345824858" +dependencies = [ + "bumpalo", + "hashbrown 0.14.5", + "ptr_meta", + "rustc-hash 2.1.1", + "triomphe", +] + +[[package]] +name = "swc_atoms" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c24077f986f0bc1c07823f850f688dd9be91b186efdb03fe1d52f7c2f2a4a346" +dependencies = [ + "bytecheck", + "hstr", + "once_cell", + "rancor", + "rkyv", + "rustc-hash 2.1.1", + "serde", +] + +[[package]] +name = "swc_common" +version = "6.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7327d132e85f8a50e0a9e2458a7b44726b2db2f7f9c8b8a556f07f359c42a461" +dependencies = [ + "anyhow", + "ast_node", + "better_scoped_tls", + "bytecheck", + "cfg-if", + "either", + "from_variant", + "new_debug_unreachable", + "num-bigint", + "once_cell", + "parking_lot", + "rancor", + "rkyv", + "rustc-hash 2.1.1", + "serde", + "siphasher 0.3.11", + "sourcemap", + "swc_allocator", + "swc_atoms", + "swc_eq_ignore_macros", + "swc_visit", + "termcolor", + "tracing", + "unicode-width", + "url", +] + +[[package]] +name = "swc_core" +version = "13.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94c8a27be20f13eb5b27e623b0d9ef486d861066b5f725e23ed38ca0e560dcca" +dependencies = [ + "once_cell", + "swc_allocator", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_transforms_base", + "swc_ecma_transforms_testing", + "swc_ecma_visit", + "swc_plugin", + "swc_plugin_macro", + "swc_plugin_proxy", + "vergen", +] + +[[package]] +name = "swc_ecma_ast" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbd513dab5fb1181e66ac34c4c959e9e8824d8d2c8bd50f698f5f2943794c0cc" +dependencies = [ + "bitflags", + "bytecheck", + "is-macro", + "num-bigint", + "phf", + "rancor", + "rkyv", + "scoped-tls", + "string_enum", + "swc_atoms", + "swc_common", + "swc_visit", + "unicode-id-start", +] + +[[package]] +name = "swc_ecma_codegen" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa6bdce26d910981128bc709a997292a5d1c98d54a9832154a1083d1adb6fdd7" +dependencies = [ + "ascii", + "compact_str", + "memchr", + "num-bigint", + "once_cell", + "regex", + "rustc-hash 2.1.1", + "serde", + "sourcemap", + "swc_allocator", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_codegen_macros", + "tracing", +] + +[[package]] +name = "swc_ecma_codegen_macros" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f9a42f479a6475647e248fa9750982c87cd985e19d1016a1fc18a70682305d1" +dependencies = [ + "proc-macro2", + "quote", + "swc_macros_common", + "syn", +] + +[[package]] +name = "swc_ecma_parser" +version = "8.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a359eaebed82e5e13e1004d1e4003931b66d8b8edab8884f3d02ed827df7530" +dependencies = [ + "either", + "new_debug_unreachable", + "num-bigint", + "num-traits", + "phf", + "rustc-hash 2.1.1", + "serde", + "smallvec", + "smartstring", + "stacker", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "tracing", + "typed-arena", +] + +[[package]] +name = "swc_ecma_testing" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46f1b2d6510edc0f54f0856c2e776b5673c3df8088dd0bda8d97ba197d054133" +dependencies = [ + "anyhow", + "hex", + "sha2", + "testing", + "tracing", +] + +[[package]] +name = "swc_ecma_transforms_base" +version = "9.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b696e003dd095ae8b8dba00f601040f756273c9af0fd67cb1c57115785cb5ec" +dependencies = [ + "better_scoped_tls", + "bitflags", + "indexmap", + "once_cell", + "phf", + "rustc-hash 2.1.1", + "serde", + "smallvec", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_parser", + "swc_ecma_utils", + "swc_ecma_visit", + "swc_parallel", + "tracing", +] + +[[package]] +name = "swc_ecma_transforms_testing" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f1ad440cfdcafabcc4ab8bb01df2d1a488f65cdad8dc85de821f66ebcedca55" +dependencies = [ + "ansi_term", + "anyhow", + "base64", + "hex", + "serde", + "serde_json", + "sha2", + "sourcemap", + "swc_allocator", + "swc_common", + "swc_ecma_ast", + "swc_ecma_codegen", + "swc_ecma_parser", + "swc_ecma_testing", + "swc_ecma_transforms_base", + "swc_ecma_utils", + "swc_ecma_visit", + "tempfile", + "testing", +] + +[[package]] +name = "swc_ecma_utils" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c217edaa22c98537e09ed3189e723feed3d889eeb7e02a0b3d48cbb91ba7e4" +dependencies = [ + "indexmap", + "num_cpus", + "once_cell", + "rustc-hash 2.1.1", + "ryu-js", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_visit", + "swc_parallel", + "tracing", + "unicode-id", +] + +[[package]] +name = "swc_ecma_visit" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a32fb2902c01f9b4615605a4a3e67e0c928bd3b9f2182e764f1c9fe4130965cf" +dependencies = [ + "new_debug_unreachable", + "num-bigint", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_visit", + "tracing", +] + +[[package]] +name = "swc_eq_ignore_macros" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e96e15288bf385ab85eb83cff7f9e2d834348da58d0a31b33bdb572e66ee413e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "swc_error_reporters" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed21ea887faeb0dab190838d2331ed187f2a74d185c9fe7044d5092900a83d29" +dependencies = [ + "anyhow", + "miette", + "once_cell", + "parking_lot", + "swc_common", +] + +[[package]] +name = "swc_macros_common" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a509f56fca05b39ba6c15f3e58636c3924c78347d63853632ed2ffcb6f5a0ac7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "swc_parallel" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5f75f1094d69174ef628e3665fff0f81d58e9f568802e3c90d332c72b0b6026" +dependencies = [ + "once_cell", +] + +[[package]] +name = "swc_plugin" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b45099a38ed45528bef939d0eac1a0c1347749d0c67d3dd744d545316c5fd05" +dependencies = [ + "once_cell", +] + +[[package]] +name = "swc_plugin_macro" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0917ccfdcd3fa6cf41bdacef2388702a3b274f9ea708d930e1e8db37c7c3e1c6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "swc_plugin_proxy" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e8ae3974157b2939ada468ffec7932358f2f567abb6c237204dd603e52ffff" +dependencies = [ + "better_scoped_tls", + "bytecheck", + "rancor", + "rkyv", + "rustc-hash 2.1.1", + "swc_common", + "swc_ecma_ast", + "swc_trace_macro", + "tracing", +] + +[[package]] +name = "swc_trace_macro" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c78717a841565df57f811376a3d19c9156091c55175e12d378f3a522de70cef" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "swc_visit" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9138b6a36bbe76dd6753c4c0794f7e26480ea757bee499738bedbbb3ae3ec5f3" +dependencies = [ + "either", + "new_debug_unreachable", +] + +[[package]] +name = "syn" +version = "2.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tempfile" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c246215d7d24f48ae091a2902398798e05d978b24315d6efbc00ede9a8bb91" +dependencies = [ + "cfg-if", + "fastrand", + "getrandom", + "once_cell", + "rustix", + "windows-sys", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "testing" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60326bf11ba23afed0b731866c6e8b709d516554dc813bb3a91f8a273f22f333" +dependencies = [ + "ansi_term", + "cargo_metadata 0.18.1", + "difference", + "once_cell", + "pretty_assertions", + "regex", + "rustc-hash 2.1.1", + "serde", + "serde_json", + "swc_common", + "swc_error_reporters", + "testing_macros", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "testing_macros" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2d27bf245b90a80d5aa231133418ae7db98f032855ce5292e12071ab29c4b26" +dependencies = [ + "anyhow", + "glob", + "once_cell", + "proc-macro2", + "quote", + "regex", + "relative-path", + "syn", +] + +[[package]] +name = "textwrap" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" +dependencies = [ + "unicode-linebreak", + "unicode-width", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" +dependencies = [ + "thiserror-impl 2.0.11", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "triomphe" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef8f7726da4807b58ea5c96fdc122f80702030edc33b35aff9190a51148ccc85" +dependencies = [ + "serde", + "stable_deref_trait", +] + +[[package]] +name = "typed-arena" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-id" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10103c57044730945224467c09f71a4db0071c123a0648cc3e818913bde6b561" + +[[package]] +name = "unicode-id-start" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f322b60f6b9736017344fa0635d64be2f458fbc04eef65f6be22976dd1ffd5b" + +[[package]] +name = "unicode-ident" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" + +[[package]] +name = "unicode-linebreak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "url" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "uuid" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced87ca4be083373936a67f8de945faa23b6b42384bd5b64434850802c6dccd0" + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "vergen" +version = "9.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0d2f179f8075b805a43a2a21728a46f0cc2921b3c58695b28fa8817e103cd9a" +dependencies = [ + "anyhow", + "cargo_metadata 0.19.1", + "derive_builder", + "regex", + "rustversion", + "vergen-lib", +] + +[[package]] +name = "vergen-lib" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b07e6010c0f3e59fcb164e0163834597da68d1f864e2b8ca49f74de01e9c166" +dependencies = [ + "anyhow", + "derive_builder", + "rustversion", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.13.3+wasi-0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "wit-bindgen-rt" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +dependencies = [ + "bitflags", +] + +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "yansi" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" + +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/rust/cubetranspilers/Cargo.toml b/rust/cubetranspilers/Cargo.toml new file mode 100644 index 0000000000000..10355a38201f4 --- /dev/null +++ b/rust/cubetranspilers/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "cubetranspilers" +version = "0.1.0" +edition = "2021" + +[dependencies] +indexmap = "2.7.1" +regex = "1.11.1" +serde = { version = "1.0.217", features = ["derive"] } +serde_json = "1.0.138" +swc_core = { version = "13.3.*", features = ["ecma_plugin_transform"] } +swc_ecma_parser = "8.0.1" +swc_ecma_codegen = "6.1.0" +anyhow = "1.0.95" diff --git a/rust/cubetranspilers/rust-toolchain.toml b/rust/cubetranspilers/rust-toolchain.toml new file mode 100644 index 0000000000000..d9f5179de3d93 --- /dev/null +++ b/rust/cubetranspilers/rust-toolchain.toml @@ -0,0 +1,4 @@ +[toolchain] +channel = "1.84.1" +components = ["rustfmt", "clippy"] +profile = "minimal" diff --git a/rust/cubetranspilers/rustfmt.toml b/rust/cubetranspilers/rustfmt.toml new file mode 100644 index 0000000000000..0912ea72b3bf8 --- /dev/null +++ b/rust/cubetranspilers/rustfmt.toml @@ -0,0 +1 @@ +#imports_granularity = "Crate" diff --git a/rust/cubetranspilers/src/check_dup_prop_transpiler.rs b/rust/cubetranspilers/src/check_dup_prop_transpiler.rs new file mode 100644 index 0000000000000..a13b09275ed72 --- /dev/null +++ b/rust/cubetranspilers/src/check_dup_prop_transpiler.rs @@ -0,0 +1,107 @@ +use std::collections::HashSet; + +use swc_core::common::errors::Handler; +use swc_core::common::{BytePos, Span, DUMMY_SP}; +use swc_core::ecma::visit::VisitMutWith; +use swc_core::{ + ecma::{ast::*, visit::VisitMut}, + plugin::proxies::PluginSourceMapProxy, +}; + +pub struct CheckDupPropTransformVisitor<'a> { + pub(crate) source_map: Option, + handler: &'a Handler, +} + +impl<'a> CheckDupPropTransformVisitor<'a> { + pub fn new(source_map: Option, handler: &'a Handler) -> Self { + CheckDupPropTransformVisitor { + source_map, + handler, + } + } + + fn emit_error(&mut self, span: Span, message: &str) { + self.handler + .struct_span_err(span, &self.format_msg(span, message)) + .emit(); + } + + fn format_msg(&self, span: Span, message: &str) -> String { + if let Some(ref sm) = self.source_map { + if let Some(source_file) = sm.source_file.get() { + let loc = source_file.lookup_line(span.lo()).unwrap_or(0); + let column = span.lo() - source_file.line_begin_pos(BytePos(loc as u32)); + format!( + "{}. Found in {}:{}:{}", + message, + source_file.name, + loc + 1, + column.0, + ) + } else { + message.to_string() + } + } else { + message.to_string() + } + } + + fn compile_key(&self, key: &PropName) -> Option { + match key { + PropName::Ident(ident) => Some(ident.sym.to_string()), + PropName::Str(s) => Some(s.value.to_string()), + _ => None, + } + } + + fn check_object_expr(&mut self, obj: &ObjectLit) { + let mut unique = HashSet::new(); + + for prop_or_spread in obj.props.iter() { + if let PropOrSpread::Prop(prop_box) = prop_or_spread { + if let Prop::KeyValue(kv) = &**prop_box { + if let Expr::Object(ref inner_obj) = *kv.value { + self.check_object_expr(inner_obj); + } + if let Some(key_name) = self.compile_key(&kv.key) { + if unique.contains(&key_name) { + let span = match &kv.key { + PropName::Ident(ident) => ident.span, + PropName::Str(s) => s.span, + _ => DUMMY_SP, + }; + self.emit_error( + span, + &format!("Duplicate property parsing {}", key_name), + ); + } else { + unique.insert(key_name); + } + } + } + } + } + } +} + +impl VisitMut for CheckDupPropTransformVisitor<'_> { + // Implement necessary visit_mut_* methods for actual custom transform. + // A comprehensive list of possible visitor methods can be found here: + // https://rustdoc.swc.rs/swc_ecma_visit/trait.VisitMut.html + + fn visit_mut_call_expr(&mut self, call_expr: &mut CallExpr) { + if let Callee::Expr(callee_expr) = &call_expr.callee { + if let Expr::Ident(ident) = &**callee_expr { + if ident.sym == *"cube" || ident.sym == *"view" { + for arg in call_expr.args.iter() { + if let Expr::Object(ref obj_lit) = *arg.expr { + self.check_object_expr(obj_lit); + } + } + } + } + } + call_expr.visit_mut_children_with(self) + } +} diff --git a/rust/cubetranspilers/src/cube_prop_ctx_transpiler.rs b/rust/cubetranspilers/src/cube_prop_ctx_transpiler.rs new file mode 100644 index 0000000000000..b6e18b712f680 --- /dev/null +++ b/rust/cubetranspilers/src/cube_prop_ctx_transpiler.rs @@ -0,0 +1,397 @@ +use indexmap::IndexSet; +use regex::Regex; +use std::collections::{HashMap, HashSet}; +use std::sync::LazyLock; +use swc_core::atoms::Atom; +use swc_core::common::errors::Handler; +use swc_core::common::{BytePos, Span, SyntaxContext, DUMMY_SP}; +use swc_core::ecma::visit::{Visit, VisitMutWith, VisitWith}; + +use swc_core::{ + ecma::{ast::*, visit::VisitMut}, + plugin::proxies::PluginSourceMapProxy, +}; + +static CURRENT_CUBE_CONSTANTS: [&str; 2] = ["CUBE", "TABLE"]; + +static TRANSPILLED_FIELDS_PATTERNS: LazyLock> = LazyLock::new(|| { + let patterns = [ + r"sql$", + r"(sqlTable|sql_table)$", + r"^measures\.[_a-zA-Z][_a-zA-Z0-9]*\.(drillMemberReferences|drillMembers|drill_members)$", + r"^measures\.[_a-zA-Z][_a-zA-Z0-9]*\.(orderBy|order_by)\.[0-9]+\.sql$", + r"^measures\.[_a-zA-Z][_a-zA-Z0-9]*\.(timeShift|time_shift)\.[0-9]+\.(timeDimension|time_dimension)$", + r"^measures\.[_a-zA-Z][_a-zA-Z0-9]*\.(reduceBy|reduce_by|groupBy|group_by|addGroupBy|add_group_by)$", + r"^dimensions\.[_a-zA-Z][_a-zA-Z0-9]*\.(reduceBy|reduce_by|groupBy|group_by|addGroupBy|add_group_by)$", + r"^(preAggregations|pre_aggregations)\.[_a-zA-Z][_a-zA-Z0-9]*\.indexes\.[_a-zA-Z][_a-zA-Z0-9]*\.columns$", + r"^(preAggregations|pre_aggregations)\.[_a-zA-Z][_a-zA-Z0-9]*\.(timeDimensionReference|timeDimension|time_dimension|segments|dimensions|measures|rollups|segmentReferences|dimensionReferences|measureReferences|rollupReferences)$", + r"^(preAggregations|pre_aggregations)\.[_a-zA-Z][_a-zA-Z0-9]*\.(timeDimensions|time_dimensions)\.\d+\.dimension$", + r"^(preAggregations|pre_aggregations)\.[_a-zA-Z][_a-zA-Z0-9]*\.(outputColumnTypes|output_column_types)\.\d+\.member$", + r"^contextMembers$", + r"^includes$", + r"^excludes$", + r"^hierarchies\.[_a-zA-Z][_a-zA-Z0-9]*\.levels$", + r"^cubes\.[0-9]+\.(joinPath|join_path)$", + r"^(accessPolicy|access_policy)\.[0-9]+\.(rowLevel|row_level)\.filters\.[0-9]+.*\.member$", + r"^(accessPolicy|access_policy)\.[0-9]+\.(rowLevel|row_level)\.filters\.[0-9]+.*\.values$", + r"^(accessPolicy|access_policy)\.[0-9]+\.conditions.[0-9]+\.if$", + ]; + patterns + .iter() + .map(|pat| Regex::new(pat).expect("Invalid regex pattern")) + .collect() +}); + +static TRANSPILLED_FIELDS: LazyLock> = LazyLock::new(|| { + let re_extract = Regex::new(r".*?([_a-zA-Z|][_a-zA-Z0-9|]*)([^_a-zA-Z0-9|]*)$").unwrap(); + let mut set = HashSet::new(); + + for regex in TRANSPILLED_FIELDS_PATTERNS.iter() { + let pat_str = regex.as_str(); + if let Some(caps) = re_extract.captures(pat_str) { + if let Some(m) = caps.get(1) { + let fields_str = m.as_str(); + for field in fields_str.split('|') { + set.insert(field.to_string()); + } + } + } + } + set +}); + +pub struct CubePropTransformVisitor<'a> { + pub(crate) cube_names: HashSet, + pub(crate) cube_symbols: HashMap>, + pub(crate) context_symbols: HashMap, + pub(crate) source_map: Option, + handler: &'a Handler, +} + +impl<'a> CubePropTransformVisitor<'a> { + pub fn new( + cube_names: HashSet, + cube_symbols: HashMap>, + context_symbols: HashMap, + source_map: Option, + handler: &'a Handler, + ) -> Self { + CubePropTransformVisitor { + source_map, + cube_names, + cube_symbols, + context_symbols, + handler, + } + } + + fn emit_error(&self, span: Span, message: &str) { + self.handler + .struct_span_err(span, &self.format_msg(span, message)) + .emit(); + } + + fn format_msg(&self, span: Span, message: &str) -> String { + if let Some(ref sm) = self.source_map { + if let Some(source_file) = sm.source_file.get() { + let loc = source_file.lookup_line(span.lo()).unwrap_or(0); + let column = span.lo() - source_file.line_begin_pos(BytePos(loc as u32)); + format!( + "{}. Found in {}:{}:{}", + message, + source_file.name, + loc + 1, + column.0, + ) + } else { + message.to_string() + } + } else { + message.to_string() + } + } + + fn resolve_cube(&self, name: &str) -> bool { + self.cube_names.contains(name) + } + + fn is_current_cube(&self, name: &str) -> bool { + CURRENT_CUBE_CONSTANTS.contains(&name) + } + + fn resolve_symbol(&self, cube_name: &str, name: &str, span: Span) -> bool { + if name == "USER_CONTEXT" { + self.emit_error( + span, + "Support for USER_CONTEXT was removed, please migrate to SECURITY_CONTEXT", + ); + return true; + } + + if self.context_symbols.contains_key(name) { + return true; + } + + let key = if self.is_current_cube(name) { + cube_name + } else { + name + }; + + match self.cube_symbols.get(key) { + Some(_cube) => true, + None => match self.cube_symbols.get(cube_name) { + Some(cube) => cube.get(name).copied().unwrap_or(false), + None => false, + }, + } + } + + fn sql_and_references_field_visitor<'b>( + &'b mut self, + cube_name: Option, + ) -> SqlAndReferencesFieldVisitor<'b, 'a> + where + 'a: 'b, + { + SqlAndReferencesFieldVisitor { + cube_name, + parent: self, + path_stack: Vec::new(), + } + } + + fn known_identifiers_inject_visitor<'b>( + &'b mut self, + field: String, + ) -> KnownIdentifiersInjectVisitor<'b, 'a> + where + 'a: 'b, + { + KnownIdentifiersInjectVisitor { + field, + parent: self, + } + } + + /// Converts the property value (Prop::KeyValue) to an arrow function whose parameters + /// are unique identifiers collected from the source expression. + fn transform_object_property(&mut self, prop: &mut Prop, resolve: &dyn Fn(&str) -> bool) { + if let Prop::KeyValue(ref mut kv) = prop { + if let Some(new_expr) = self.replace_value_with_arrow_function(resolve, &kv.value) { + kv.value = Box::new(new_expr); + } + } + } + + /// Collects identifiers from the expression and returns ArrowExpr, + /// where the parameters are the collected identifiers and the body is the original expression. + fn replace_value_with_arrow_function( + &mut self, + resolve: &dyn Fn(&str) -> bool, + expr: &Expr, + ) -> Option { + let mut collector = CollectIdentifiersVisitor { + identifiers: IndexSet::new(), + resolve, + }; + expr.visit_with(&mut collector); + let params: Vec = collector + .identifiers + .into_iter() + .map(|(sym, ctxt)| { + Pat::Ident(BindingIdent { + id: Ident::new(sym, DUMMY_SP, ctxt), + type_ann: None, + }) + }) + .collect(); + let body_expr = match expr { + Expr::Arrow(arrow_expr) => arrow_expr.body.clone(), + _ => Box::new(BlockStmtOrExpr::Expr(Box::new((*expr).clone()))), + }; + let arrow = ArrowExpr { + span: DUMMY_SP, + params, + body: body_expr, + is_async: false, + is_generator: false, + type_params: None, + return_type: None, + ctxt: SyntaxContext::empty(), + }; + Some(Expr::Arrow(arrow)) + } +} + +impl VisitMut for CubePropTransformVisitor<'_> { + // Implement necessary visit_mut_* methods for actual custom transform. + // A comprehensive list of possible visitor methods can be found here: + // https://rustdoc.swc.rs/swc_ecma_visit/trait.VisitMut.html + + fn visit_mut_call_expr(&mut self, call_expr: &mut CallExpr) { + if let Callee::Expr(callee) = &call_expr.callee { + if let Expr::Ident(ident) = &**callee { + let callee_name = ident.sym.to_string(); + let args_len = call_expr.args.len(); + if args_len > 0 { + if callee_name == "cube" || callee_name == "view" { + if args_len != 2 { + self.emit_error( + call_expr.span, + &format!( + "Incorrect number of arguments to {}() function", + callee_name + ), + ); + return; + } + let cube_name_opt: Option = { + let first_arg = &call_expr.args[0].expr; + match &**first_arg { + Expr::Lit(Lit::Str(s)) => Some(s.value.to_string()), + Expr::Tpl(tpl) => { + if !tpl.quasis.is_empty() { + tpl.quasis[0].cooked.as_ref().map(|c| c.clone().to_string()) + } else { + None + } + } + _ => None, + } + }; + if let Some(last_arg) = call_expr.args.last_mut() { + { + let mut sql_visitor = + self.sql_and_references_field_visitor(cube_name_opt.clone()); + last_arg.visit_mut_with(&mut sql_visitor); + } + { + let mut known_visitor = + self.known_identifiers_inject_visitor("extends".to_string()); + last_arg.visit_mut_with(&mut known_visitor); + } + } + } else if callee_name == "context" { + if let Some(last_arg) = call_expr.args.last_mut() { + let mut sql_visitor = { + let self_ref = &mut *self; + self_ref.sql_and_references_field_visitor(None) + }; + + last_arg.expr.visit_mut_with(&mut sql_visitor); + } + } + } + } + } + call_expr.visit_mut_children_with(self) + } +} + +pub struct SqlAndReferencesFieldVisitor<'b, 'a: 'b> { + pub cube_name: Option, + pub parent: &'b mut CubePropTransformVisitor<'a>, + pub path_stack: Vec, +} + +impl SqlAndReferencesFieldVisitor<'_, '_> { + fn current_path(&self) -> String { + self.path_stack.join(".") + } +} + +impl VisitMut for SqlAndReferencesFieldVisitor<'_, '_> { + fn visit_mut_prop(&mut self, prop: &mut Prop) { + let mut added = false; + if let Prop::KeyValue(ref kv) = prop { + if let PropName::Ident(ref ident) = kv.key { + let key_name = ident.sym.to_string(); + self.path_stack.push(key_name.clone()); + added = true; + if TRANSPILLED_FIELDS.contains(&key_name) { + let full_path = self.current_path(); + for pattern in TRANSPILLED_FIELDS_PATTERNS.iter() { + if pattern.is_match(&full_path) { + let parent_ptr = self.parent as *mut CubePropTransformVisitor; + let resolve = |n: &str| unsafe { + (*parent_ptr).resolve_symbol( + self.cube_name.as_deref().unwrap_or(""), + n, + DUMMY_SP, + ) || (*parent_ptr).is_current_cube(n) + }; + self.parent.transform_object_property(prop, &resolve); + self.path_stack.pop(); + return; + } + } + } + } + } + prop.visit_mut_children_with(self); + + if !self.path_stack.is_empty() && added { + self.path_stack.pop(); + } + } + + fn visit_mut_array_lit(&mut self, arr: &mut ArrayLit) { + for (idx, el) in arr.elems.iter_mut().enumerate() { + if let Some(el) = el { + self.path_stack.push(idx.to_string()); + el.visit_mut_children_with(self); + self.path_stack.pop(); + } + } + } +} + +pub struct KnownIdentifiersInjectVisitor<'b, 'a: 'b> { + pub field: String, + pub parent: &'b mut CubePropTransformVisitor<'a>, +} + +impl VisitMut for KnownIdentifiersInjectVisitor<'_, '_> { + fn visit_mut_prop(&mut self, prop: &mut Prop) { + let ident_name = match &prop { + Prop::Shorthand(ident) => ident.sym.clone().to_string(), + Prop::KeyValue(key_value_prop) => match &key_value_prop.key { + PropName::Ident(ident_name) => ident_name.sym.clone().to_string(), + PropName::Str(str) => str.value.clone().to_string(), + _ => "".to_string(), + }, + _ => "".to_string(), + }; + + if ident_name.contains(&self.field) { + let parent_ptr = self.parent as *mut CubePropTransformVisitor; + let resolve = move |n: &str| unsafe { (*parent_ptr).resolve_cube(n) }; + self.parent.transform_object_property(prop, &resolve); + } + + prop.visit_mut_children_with(self) + } +} + +pub struct CollectIdentifiersVisitor<'a> { + pub identifiers: IndexSet<(Atom, SyntaxContext)>, + pub resolve: &'a dyn Fn(&str) -> bool, +} + +impl Visit for CollectIdentifiersVisitor<'_> { + fn visit_ident(&mut self, ident: &Ident) { + if (self.resolve)(&ident.sym) { + self.identifiers.insert((ident.sym.clone(), ident.ctxt)); + } + } + + fn visit_member_expr(&mut self, member: &MemberExpr) { + member.obj.visit_with(self); + match &member.prop { + MemberProp::Ident(_ident_name) => member.prop.visit_with(self), + MemberProp::PrivateName(_private_name) => {} + MemberProp::Computed(_computed_prop_name) => member.prop.visit_with(self), + }; + } +} diff --git a/rust/cubetranspilers/src/error_reporter.rs b/rust/cubetranspilers/src/error_reporter.rs new file mode 100644 index 0000000000000..eef3581c9cfc0 --- /dev/null +++ b/rust/cubetranspilers/src/error_reporter.rs @@ -0,0 +1,45 @@ +use std::sync::{Arc, Mutex}; + +use swc_core::common::errors::{DiagnosticBuilder, Emitter}; + +pub struct ErrorReporter { + pub errors: Arc>>, + pub warnings: Arc>>, +} + +impl ErrorReporter { + pub fn new(errors: Arc>>, warnings: Arc>>) -> Self { + ErrorReporter { errors, warnings } + } +} + +impl Default for ErrorReporter { + fn default() -> Self { + ErrorReporter { + errors: Arc::new(Mutex::new(Vec::new())), + warnings: Arc::new(Mutex::new(Vec::new())), + } + } +} + +impl Emitter for ErrorReporter { + fn emit(&mut self, diagnostic: &DiagnosticBuilder) { + match diagnostic.diagnostic.level { + swc_core::common::errors::Level::Bug + | swc_core::common::errors::Level::Fatal + | swc_core::common::errors::Level::PhaseFatal + | swc_core::common::errors::Level::Error => { + let mut errors = self.errors.lock().unwrap(); + errors.push(diagnostic.message()); + } + swc_core::common::errors::Level::Warning + | swc_core::common::errors::Level::Note + | swc_core::common::errors::Level::Help + | swc_core::common::errors::Level::Cancelled + | swc_core::common::errors::Level::FailureNote => { + let mut warnings = self.warnings.lock().unwrap(); + warnings.push(diagnostic.message()); + } + } + } +} diff --git a/rust/cubetranspilers/src/import_export_transpiler.rs b/rust/cubetranspilers/src/import_export_transpiler.rs new file mode 100644 index 0000000000000..b63f4182fcf98 --- /dev/null +++ b/rust/cubetranspilers/src/import_export_transpiler.rs @@ -0,0 +1,356 @@ +use swc_core::common::errors::Handler; +use swc_core::common::BytePos; +use swc_core::common::{Span, SyntaxContext, DUMMY_SP}; +use swc_core::ecma::visit::{noop_visit_mut_type, VisitMutWith}; +use swc_core::{ + ecma::{ast::*, visit::VisitMut}, + plugin::proxies::PluginSourceMapProxy, +}; + +pub struct ImportExportTransformVisitor<'a> { + pub(crate) source_map: Option, + handler: &'a Handler, +} + +impl<'a> ImportExportTransformVisitor<'a> { + pub fn new(source_map: Option, handler: &'a Handler) -> Self { + ImportExportTransformVisitor { + source_map, + handler, + } + } + + fn emit_error(&self, span: Span, message: &str) { + self.handler + .struct_span_err(span, &self.format_msg(span, message)) + .emit(); + } + + fn format_msg(&self, span: Span, message: &str) -> String { + if let Some(ref sm) = self.source_map { + if let Some(source_file) = sm.source_file.get() { + let loc = source_file.lookup_line(span.lo()).unwrap_or(0); + let column = span.lo() - source_file.line_begin_pos(BytePos(loc as u32)); + format!( + "{}. Found in {}:{}:{}", + message, + source_file.name, + loc + 1, + column.0, + ) + } else { + message.to_string() + } + } else { + message.to_string() + } + } +} + +impl VisitMut for ImportExportTransformVisitor<'_> { + // Implement necessary visit_mut_* methods for actual custom transform. + // A comprehensive list of possible visitor methods can be found here: + // https://rustdoc.swc.rs/swc_ecma_visit/trait.VisitMut.html + + // We don't need to do anything besides imports here + noop_visit_mut_type!(); + + // Can't use visit_mut_module_item for cases when we need to replace + // the item with multiple statements + fn visit_mut_module(&mut self, module: &mut Module) { + let mut new_body = Vec::with_capacity(module.body.len()); + + for mut item in module.body.drain(..) { + self.visit_mut_module_item(&mut item); + + match &item { + ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(export_decl)) => { + let decl = export_decl.decl.clone(); + let stmt_decl = ModuleItem::Stmt(Stmt::Decl(decl.clone())); + + let mut ids = vec![]; + + match decl { + Decl::Var(var_decl) => { + for var_declarator in var_decl.decls.iter() { + if let Pat::Ident(BindingIdent { id, .. }) = &var_declarator.name { + ids.push(id.clone()); + } + } + } + Decl::Fn(fn_decl) => { + ids.push(fn_decl.ident.clone()); + } + Decl::Class(class_decl) => { + ids.push(class_decl.ident.clone()); + } + _ => {} + } + + let props: Vec = ids + .iter() + .map(|ident| { + PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { + key: PropName::Ident(IdentName::from(ident.sym.clone())), + value: Box::new(Expr::Ident(ident.clone())), + }))) + }) + .collect(); + + let add_export_call = Expr::Call(CallExpr { + span: DUMMY_SP, + callee: Callee::Expr(Box::new(Expr::Ident(Ident::new( + "addExport".into(), + DUMMY_SP, + SyntaxContext::empty(), + )))), + args: vec![ExprOrSpread { + spread: None, + expr: Box::new(Expr::Object(ObjectLit { + span: DUMMY_SP, + props, + })), + }], + type_args: None, + ctxt: SyntaxContext::empty(), + }); + + let stmt_add_export = ModuleItem::Stmt(Stmt::Expr(ExprStmt { + span: DUMMY_SP, + expr: Box::new(add_export_call), + })); + + new_body.extend(vec![stmt_decl, stmt_add_export]); + } + _ => new_body.push(item), + } + } + + module.body = new_body; + } + + fn visit_mut_module_item(&mut self, item: &mut ModuleItem) { + if let ModuleItem::ModuleDecl(decl) = item { + match decl { + ModuleDecl::Import(import_decl) => { + let require_call = Expr::Call(CallExpr { + span: DUMMY_SP, + callee: Callee::Expr(Box::new(Expr::Ident(Ident::new( + "require".into(), + DUMMY_SP, + SyntaxContext::empty(), + )))), + args: vec![ExprOrSpread { + spread: None, + expr: Box::new(Expr::Lit(Lit::Str(*import_decl.src.clone()))), + }], + type_args: None, + ctxt: SyntaxContext::empty(), + }); + + let mut var_decls = Vec::with_capacity(import_decl.specifiers.len()); + + for spec in &import_decl.specifiers { + match spec { + ImportSpecifier::Named(named) => { + let local_ident = named.local.clone(); + let init_expr = if let Some(imported) = &named.imported { + match imported { + ModuleExportName::Ident(id) => Expr::Member(MemberExpr { + span: DUMMY_SP, + obj: Box::new(require_call.clone()), + prop: MemberProp::Ident(IdentName { + span: DUMMY_SP, + sym: id.sym.clone(), + }), + }), + ModuleExportName::Str(s) => Expr::Member(MemberExpr { + span: DUMMY_SP, + obj: Box::new(require_call.clone()), + prop: MemberProp::Computed(ComputedPropName { + span: DUMMY_SP, + expr: Box::new(Expr::Lit(Lit::Str(s.clone()))), + }), + }), + } + } else { + Expr::Member(MemberExpr { + span: DUMMY_SP, + obj: Box::new(require_call.clone()), + prop: MemberProp::Ident(IdentName { + span: DUMMY_SP, + sym: local_ident.sym.clone(), + }), + }) + }; + + let var_decl = VarDeclarator { + span: DUMMY_SP, + name: Pat::Ident(BindingIdent { + id: local_ident, + type_ann: None, + }), + init: Some(Box::new(init_expr)), + definite: false, + }; + var_decls.push(var_decl); + } + ImportSpecifier::Default(default) => { + let local_ident = default.local.clone(); + let var_decl = VarDeclarator { + span: DUMMY_SP, + name: Pat::Ident(BindingIdent { + id: local_ident, + type_ann: None, + }), + init: Some(Box::new(require_call.clone())), + definite: false, + }; + var_decls.push(var_decl); + } + ImportSpecifier::Namespace(star_as) => { + self.emit_error(star_as.span, "Namespace import not supported"); + } + } + } + + *item = ModuleItem::Stmt(Stmt::Decl(Decl::Var(Box::new(VarDecl { + span: DUMMY_SP, + kind: VarDeclKind::Const, + declare: false, + decls: var_decls, + ctxt: SyntaxContext::empty(), + })))); + } + ModuleDecl::ExportNamed(export_named) => { + // For named exports we collect object properties for each specifier + let mut props = Vec::with_capacity(export_named.specifiers.len()); + for spec in &export_named.specifiers { + match spec { + ExportSpecifier::Named(named_spec) => { + // Cases like `export { foo as bar }` + let key = if let Some(exported) = &named_spec.exported { + match exported { + ModuleExportName::Ident(id) => PropName::Ident(IdentName { + span: DUMMY_SP, + sym: id.sym.clone(), + }), + ModuleExportName::Str(s) => PropName::Str(s.clone()), + } + } else { + match &named_spec.orig { + ModuleExportName::Ident(id) => PropName::Ident(IdentName { + span: DUMMY_SP, + sym: id.sym.clone(), + }), + ModuleExportName::Str(s) => PropName::Str(s.clone()), + } + }; + let value_expr = match &named_spec.orig { + ModuleExportName::Ident(id) => Expr::Ident(id.clone()), + ModuleExportName::Str(s) => Expr::Lit(Lit::Str(s.clone())), + }; + let prop = + PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { + key, + value: Box::new(value_expr), + }))); + props.push(prop); + } + ExportSpecifier::Namespace(_export_namespace_specifier) => { + self.emit_error( + export_named.span, + "Unsupported export specifier: Named Namespace", + ); + } + ExportSpecifier::Default(_export_default_specifier) => { + self.emit_error( + export_named.span, + "Unsupported export specifier: Named Default", + ); + } + } + } + let obj_expr = Expr::Object(ObjectLit { + span: DUMMY_SP, + props, + }); + let add_export_call = Expr::Call(CallExpr { + span: DUMMY_SP, + callee: Callee::Expr(Box::new(Expr::Ident(Ident::new( + "addExport".into(), + DUMMY_SP, + SyntaxContext::empty(), + )))), + args: vec![ExprOrSpread { + spread: None, + expr: Box::new(obj_expr), + }], + type_args: None, + ctxt: SyntaxContext::empty(), + }); + + *item = ModuleItem::Stmt(Stmt::Expr(ExprStmt { + span: DUMMY_SP, + expr: Box::new(add_export_call), + })); + } + ModuleDecl::ExportDefaultDecl(export_default) => { + let decl_expr: Expr = match &export_default.decl { + DefaultDecl::Fn(expr) => Expr::Fn(FnExpr::from(expr.function.clone())), + DefaultDecl::Class(expr) => { + Expr::Class(ClassExpr::from(expr.class.clone())) + } + DefaultDecl::TsInterfaceDecl(tsdecl) => { + self.emit_error(tsdecl.span, "Unsupported default export declaration"); + // Return null as fallback + Expr::Lit(Lit::Null(Null { span: DUMMY_SP })) + } + }; + let set_export_call = Expr::Call(CallExpr { + span: DUMMY_SP, + callee: Callee::Expr(Box::new(Expr::Ident(Ident::new( + "setExport".into(), + DUMMY_SP, + SyntaxContext::empty(), + )))), + args: vec![ExprOrSpread { + spread: None, + expr: Box::new(decl_expr), + }], + type_args: None, + ctxt: SyntaxContext::empty(), + }); + *item = ModuleItem::Stmt(Stmt::Expr(ExprStmt { + span: DUMMY_SP, + expr: Box::new(set_export_call), + })); + } + ModuleDecl::ExportDefaultExpr(export_default) => { + let decl_expr: Expr = *export_default.expr.clone(); + let set_export_call = Expr::Call(CallExpr { + span: DUMMY_SP, + callee: Callee::Expr(Box::new(Expr::Ident(Ident::new( + "setExport".into(), + DUMMY_SP, + SyntaxContext::empty(), + )))), + args: vec![ExprOrSpread { + spread: None, + expr: Box::new(decl_expr), + }], + type_args: None, + ctxt: SyntaxContext::empty(), + }); + *item = ModuleItem::Stmt(Stmt::Expr(ExprStmt { + span: DUMMY_SP, + expr: Box::new(set_export_call), + })); + } + _ => {} + } + } + + item.visit_mut_children_with(self) + } +} diff --git a/rust/cubetranspilers/src/lib.rs b/rust/cubetranspilers/src/lib.rs new file mode 100644 index 0000000000000..e45f3b65f2ee6 --- /dev/null +++ b/rust/cubetranspilers/src/lib.rs @@ -0,0 +1,156 @@ +use crate::check_dup_prop_transpiler::CheckDupPropTransformVisitor; +use crate::cube_prop_ctx_transpiler::CubePropTransformVisitor; +use crate::import_export_transpiler::ImportExportTransformVisitor; +use crate::validation_transpiler::ValidationTransformVisitor; +use anyhow::{anyhow, Result}; +use error_reporter::ErrorReporter; +use serde::{Deserialize, Serialize}; +use std::collections::{HashMap, HashSet}; +use std::sync::{Arc, Mutex}; +use swc_core::common::errors::{Handler, HandlerFlags}; +use swc_core::common::input::StringInput; +use swc_core::common::sync::{Lrc, OnceCell}; +use swc_core::common::{FileName, SourceMap}; +use swc_core::ecma::ast::{EsVersion, Program}; +use swc_core::ecma::visit::VisitMutWith; +use swc_core::plugin::proxies::PluginSourceMapProxy; +use swc_ecma_codegen::Config; +use swc_ecma_codegen::{text_writer::JsWriter, Emitter as CodeEmitter}; +use swc_ecma_parser::lexer::Lexer; +use swc_ecma_parser::{Parser, Syntax}; + +pub mod check_dup_prop_transpiler; +pub mod cube_prop_ctx_transpiler; +pub mod error_reporter; +pub mod import_export_transpiler; +pub mod validation_transpiler; + +#[derive(Deserialize, Clone, Debug)] +pub enum Transpilers { + CubeCheckDuplicatePropTranspiler, + CubePropContextTranspiler, + ImportExportTranspiler, + ValidationTranspiler, +} + +#[derive(Deserialize, Clone, Debug, Default)] +#[serde(rename_all = "camelCase")] +pub struct TransformConfig { + pub file_name: String, + pub transpilers: Vec, + pub cube_names: HashSet, + pub cube_symbols: HashMap>, + pub context_symbols: HashMap, +} + +#[derive(Serialize, Clone, Debug)] +#[serde(rename_all = "camelCase")] +pub struct TransformResult { + pub code: String, + pub errors: Vec, + pub warnings: Vec, +} + +pub fn run_transpilers( + sources: String, + transform_config: TransformConfig, +) -> Result { + let sm: Lrc = Default::default(); + let sf = sm.new_source_file( + Arc::new(FileName::Custom(transform_config.file_name)), + sources, + ); + + let lexer = Lexer::new( + Syntax::Es(Default::default()), + EsVersion::Es2015, + StringInput::from(&*sf), + None, + ); + let mut parser = Parser::new_from(lexer); + + let mut program = match parser.parse_program() { + Ok(v) => v, + Err(_err) => return Err(anyhow!("Failed to parse the JS code")), + }; + + let sm_cell = OnceCell::new(); + sm_cell + .set(sf.clone()) + .map_err(|_err| anyhow!("Failed to init OnceCell with source file"))?; + + let plugin_source_map = PluginSourceMapProxy { + source_file: sm_cell, + }; + + let errors = Arc::new(Mutex::new(Vec::new())); + let warnings = Arc::new(Mutex::new(Vec::new())); + + let reporter = Box::new(ErrorReporter::new(errors.clone(), warnings.clone())); + let handler = Handler::with_emitter_and_flags( + reporter, + HandlerFlags { + can_emit_warnings: true, + ..Default::default() + }, + ); + + transform_config + .transpilers + .into_iter() + .for_each(|transpiler| match transpiler { + Transpilers::CubeCheckDuplicatePropTranspiler => { + let mut visitor = + CheckDupPropTransformVisitor::new(Some(plugin_source_map.clone()), &handler); + program.visit_mut_with(&mut visitor); + } + Transpilers::CubePropContextTranspiler => { + let mut visitor = CubePropTransformVisitor::new( + transform_config.cube_names.clone(), + transform_config.cube_symbols.clone(), + transform_config.context_symbols.clone(), + Some(plugin_source_map.clone()), + &handler, + ); + program.visit_mut_with(&mut visitor); + } + Transpilers::ImportExportTranspiler => { + let mut visitor = + ImportExportTransformVisitor::new(Some(plugin_source_map.clone()), &handler); + program.visit_mut_with(&mut visitor); + } + Transpilers::ValidationTranspiler => { + let mut visitor = + ValidationTransformVisitor::new(Some(plugin_source_map.clone()), &handler); + program.visit_mut_with(&mut visitor); + } + }); + + let output_code = generate_code(&program, &sm)?; + let errors = errors.lock().unwrap().clone(); + let warnings = warnings.lock().unwrap().clone(); + + Ok(TransformResult { + code: output_code, + errors, + warnings, + }) +} + +pub fn generate_code(program: &Program, sm: &Lrc) -> Result { + let mut buf = vec![]; + { + let mut emitter = CodeEmitter { + cfg: Config::default().with_target(EsVersion::Es2015), + comments: None, + wr: JsWriter::new(sm.clone(), "\n", &mut buf, None), + cm: sm.clone(), + }; + emitter + .emit_program(program) + .map_err(|err| anyhow!("Failed to generate code: {}", err))?; + } + + let code = String::from_utf8(buf).map_err(|err| anyhow!("Invalid UTF8: {}", err))?; + Ok(code) +} diff --git a/rust/cubetranspilers/src/validation_transpiler.rs b/rust/cubetranspilers/src/validation_transpiler.rs new file mode 100644 index 0000000000000..8670c792175c6 --- /dev/null +++ b/rust/cubetranspilers/src/validation_transpiler.rs @@ -0,0 +1,70 @@ +use swc_core::common::errors::Handler; +use swc_core::common::BytePos; +use swc_core::common::Span; +use swc_core::ecma::visit::noop_visit_mut_type; +use swc_core::plugin::proxies::PluginSourceMapProxy; +use swc_core::{ + atoms::JsWord, + ecma::{ast::*, visit::VisitMut}, +}; + +pub struct ValidationTransformVisitor<'a> { + pub(crate) source_map: Option, + handler: &'a Handler, +} + +impl<'a> ValidationTransformVisitor<'a> { + pub fn new(source_map: Option, handler: &'a Handler) -> Self { + ValidationTransformVisitor { + source_map, + handler, + } + } + + fn emit_warn(&self, span: Span, message: &str) { + self.handler + .struct_span_warn(span, &self.format_msg(span, message)) + .emit(); + } + + fn format_msg(&self, span: Span, message: &str) -> String { + if let Some(ref sm) = self.source_map { + if let Some(source_file) = sm.source_file.get() { + let loc = source_file.lookup_line(span.lo()).unwrap_or(0); + let column = span.lo() - source_file.line_begin_pos(BytePos(loc as u32)); + format!( + "{}. Found in {}:{}:{}", + message, + source_file.name, + loc + 1, + column.0, + ) + } else { + message.to_string() + } + } else { + message.to_string() + } + } +} + +impl VisitMut for ValidationTransformVisitor<'_> { + // Implement necessary visit_mut_* methods for actual custom transform. + // A comprehensive list of possible visitor methods can be found here: + // https://rustdoc.swc.rs/swc_ecma_visit/trait.VisitMut.html + + // We don't need to do anything besides checking identifiers here + noop_visit_mut_type!(); + + fn visit_mut_ident(&mut self, ident: &mut Ident) { + let uc_id: JsWord = "USER_CONTEXT".into(); + if ident.sym == uc_id { + self.emit_warn( + ident.span, + "Support for USER_CONTEXT was removed, please migrate to SECURITY_CONTEXT", + ); + // TODO: How to report the errors? + // @see https://rustdoc.swc.rs/swc_common/errors/struct.Handler.html + } + } +} diff --git a/rust/cubetranspilers/tests/check_dup_prop_test.rs b/rust/cubetranspilers/tests/check_dup_prop_test.rs new file mode 100644 index 0000000000000..6900153a898f8 --- /dev/null +++ b/rust/cubetranspilers/tests/check_dup_prop_test.rs @@ -0,0 +1,273 @@ +mod common; + +// Recommended strategy to test plugin's transform is verify +// the Visitor's behavior, instead of trying to run `process_transform` with mocks +// unless explicitly required to do so. + +use std::sync::{Arc, Mutex}; + +use common::TestEmitter; +use cubetranspilers::check_dup_prop_transpiler::*; +use swc_core::ecma::ast::{EsVersion, Program}; +use swc_core::{ + common::{ + errors::{Handler, HandlerFlags}, + sync::Lrc, + FileName, SourceMap, + }, + ecma::visit::VisitMutWith, +}; +use swc_ecma_parser::{lexer::Lexer, Parser, StringInput, Syntax}; + +#[test] +fn test_errors_for_duplicates_first_level() { + let cm: Lrc = Default::default(); + let diagnostics = Arc::new(Mutex::new(Vec::new())); + let emitter = Box::new(TestEmitter { + diagnostics: diagnostics.clone(), + }); + let handler = Handler::with_emitter_and_flags( + emitter, + HandlerFlags { + can_emit_warnings: true, + ..Default::default() + }, + ); + + let js_code = r#" + cube(`cube1`, { + sql: `SELECT * FROM table`, + + dimensions: { + id: { + sql: `id`, + type: `number`, + primary_key: true, + }, + created_at: { + sql: `created_at`, + type: `time`, + }, + dim1Number: { + sql: `dim1Number`, + type: `number`, + }, + dim2Number: { + sql: `dim2Number`, + type: `number`, + }, + }, + + dimensions: { + dim2Number: { + sql: `dim2Number`, + type: `number`, + }, + }, + + measures: { + count: { + type: `count`, + sql: `id`, + }, + measureDim1: { + sql: `dim1Number`, + type: + `max`, + }, + measureDim2: { + sql: `dim1Number`, + type: `min`, + }, + }, + }); + "#; + + let fm = cm.new_source_file( + Arc::new(FileName::Custom("input.js".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Es(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the JS code"); + + let mut visitor = CheckDupPropTransformVisitor::new(None, &handler); + program.visit_mut_with(&mut visitor); + + let diags = diagnostics.lock().unwrap(); + let msgs: Vec<_> = diags + .iter() + .filter(|msg| msg.contains("Duplicate property")) + .collect(); + assert!(msgs.len() == 1, "Should emit errors",); +} + +#[test] +fn test_errors_for_duplicates_deep_level() { + let cm: Lrc = Default::default(); + let diagnostics = Arc::new(Mutex::new(Vec::new())); + let emitter = Box::new(TestEmitter { + diagnostics: diagnostics.clone(), + }); + let handler = Handler::with_emitter_and_flags( + emitter, + HandlerFlags { + can_emit_warnings: true, + ..Default::default() + }, + ); + + let js_code = r#" + cube(`cube1`, { + sql: `SELECT * FROM table`, + + dimensions: { + id: { + sql: `id`, + type: `number`, + primary_key: true, + }, + created_at: { + sql: `created_at`, + type: `time`, + }, + dim1Number: { + sql: `dim1Number`, + type: `number`, + }, + dim1Number: { + sql: `dim2Number`, + type: `number`, + }, + }, + + dimensions: { + dim2Number: { + sql: `dim2Number`, + type: `number`, + }, + }, + + measures: { + count: { + type: `count`, + sql: `id`, + }, + measureDim1: { + sql: `dim1Number`, + type: + `max`, + }, + measureDim1: { + sql: `dim1Number`, + type: `min`, + }, + }, + }); + "#; + + let fm = cm.new_source_file( + Arc::new(FileName::Custom("input.js".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Es(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the JS code"); + + let mut visitor = CheckDupPropTransformVisitor::new(None, &handler); + program.visit_mut_with(&mut visitor); + + let diags = diagnostics.lock().unwrap(); + let msgs: Vec<_> = diags + .iter() + .filter(|msg| msg.contains("Duplicate property")) + .collect(); + assert!(msgs.len() == 3, "Should emit errors",); +} + +#[test] +fn test_no_errors() { + let cm: Lrc = Default::default(); + let diagnostics = Arc::new(Mutex::new(Vec::new())); + let emitter = Box::new(TestEmitter { + diagnostics: diagnostics.clone(), + }); + let handler = Handler::with_emitter_and_flags( + emitter, + HandlerFlags { + can_emit_warnings: true, + ..Default::default() + }, + ); + + let js_code = r#" + cube(`cube1`, { + sql: `SELECT * FROM table`, + + dimensions: { + id: { + sql: `id`, + type: `number`, + primary_key: true, + }, + created_at: { + sql: `created_at`, + type: `time`, + }, + dim1Number: { + sql: `dim1Number`, + type: `number`, + }, + dim2Number: { + sql: `dim2Number`, + type: `number`, + }, + }, + + measures: { + count: { + type: `count`, + sql: `id`, + }, + measureDim1: { + sql: `dim1Number`, + type: + `max`, + }, + measureDim2: { + sql: `dim1Number`, + type: `min`, + }, + }, + }); + "#; + + let fm = cm.new_source_file( + Arc::new(FileName::Custom("input.js".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Es(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the JS code"); + + let mut visitor = CheckDupPropTransformVisitor::new(None, &handler); + program.visit_mut_with(&mut visitor); + + let diags = diagnostics.lock().unwrap(); + assert!(diags.is_empty(), "Should not emit errors",); +} diff --git a/rust/cubetranspilers/tests/common/mod.rs b/rust/cubetranspilers/tests/common/mod.rs new file mode 100644 index 0000000000000..097812a17b55f --- /dev/null +++ b/rust/cubetranspilers/tests/common/mod.rs @@ -0,0 +1,33 @@ +use std::sync::{Arc, Arc as Lrc, Mutex}; +use swc_core::common::errors::{DiagnosticBuilder, Emitter}; +use swc_core::common::SourceMap; +use swc_core::ecma::ast::Program; +use swc_ecma_codegen::text_writer::JsWriter; +use swc_ecma_codegen::{Config, Emitter as CodeEmitter}; + +pub struct TestEmitter { + pub diagnostics: Arc>>, +} + +impl Emitter for TestEmitter { + fn emit(&mut self, diagnostic: &DiagnosticBuilder) { + let mut diags = self.diagnostics.lock().unwrap(); + diags.push(diagnostic.message()); + } +} + +pub fn generate_code(program: &Program, cm: &Lrc) -> String { + let mut buf = vec![]; + { + let mut emitter = CodeEmitter { + cfg: Config::default(), + comments: None, + wr: JsWriter::new(cm.clone(), "\n", &mut buf, None), + cm: cm.clone(), + }; + emitter + .emit_program(program) + .expect("Failed to generate code"); + } + String::from_utf8(buf).expect("Invalid UTF8") +} diff --git a/rust/cubetranspilers/tests/cube_prop_ctx_test.rs b/rust/cubetranspilers/tests/cube_prop_ctx_test.rs new file mode 100644 index 0000000000000..4fe0b3d992905 --- /dev/null +++ b/rust/cubetranspilers/tests/cube_prop_ctx_test.rs @@ -0,0 +1,947 @@ +mod common; + +// Recommended strategy to test plugin's transform is verify +// the Visitor's behavior, instead of trying to run `process_transform` with mocks +// unless explicitly required to do so. + +use std::collections::{HashMap, HashSet}; +use std::sync::{Arc, LazyLock, Mutex}; + +use common::{generate_code, TestEmitter}; +use cubetranspilers::cube_prop_ctx_transpiler::*; +use swc_core::ecma::ast::{EsVersion, Program}; +use swc_core::{ + common::{ + errors::{Handler, HandlerFlags}, + sync::Lrc, + FileName, SourceMap, + }, + ecma::visit::VisitMutWith, +}; +use swc_ecma_parser::{lexer::Lexer, Parser, StringInput, Syntax}; + +static CONTEXT_SYMBOLS: LazyLock> = LazyLock::new(|| { + let mut map = HashMap::new(); + map.insert( + "SECURITY_CONTEXT".to_string(), + "securityContext".to_string(), + ); + map.insert( + "security_context".to_string(), + "securityContext".to_string(), + ); + map.insert("securityContext".to_string(), "securityContext".to_string()); + map.insert("FILTER_PARAMS".to_string(), "filterParams".to_string()); + map.insert("FILTER_GROUP".to_string(), "filterGroup".to_string()); + map.insert("SQL_UTILS".to_string(), "sqlUtils".to_string()); + map +}); + +#[test] +fn test_incorrect_args_to_cube() { + let cm: Lrc = Default::default(); + let diagnostics = Arc::new(Mutex::new(Vec::new())); + let emitter = Box::new(TestEmitter { + diagnostics: diagnostics.clone(), + }); + let handler = Handler::with_emitter_and_flags( + emitter, + HandlerFlags { + can_emit_warnings: true, + ..Default::default() + }, + ); + + let js_code = r#" + cube(`cube1`, { sql: `xxx` }, 25); + "#; + + let fm = cm.new_source_file( + Arc::new(FileName::Custom("input.js".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Es(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the JS code"); + + let mut visitor = CubePropTransformVisitor::new( + HashSet::new(), + HashMap::new(), + HashMap::new(), + None, + &handler, + ); + program.visit_mut_with(&mut visitor); + + let _output_code = generate_code(&program, &cm); + let diags = diagnostics.lock().unwrap(); + let msgs: Vec<_> = diags + .iter() + .filter(|msg| msg.contains("Incorrect number of arguments")) + .collect(); + assert!(msgs.len() > 0, "Should emit errors",); +} + +#[test] +fn test_simple_transform() { + let cm: Lrc = Default::default(); + let diagnostics = Arc::new(Mutex::new(Vec::new())); + let emitter = Box::new(TestEmitter { + diagnostics: diagnostics.clone(), + }); + let handler = Handler::with_emitter_and_flags( + emitter, + HandlerFlags { + can_emit_warnings: true, + ..Default::default() + }, + ); + + let js_code = r#" + cube(`cube1`, { + sql: `SELECT * FROM table`, + + dimensions: { + id: { + sql: `id`, + type: `number`, + primary_key: true, + }, + created_at: { + sql: `created_at`, + type: `time`, + }, + dim1Number: { + sql: `dim1Number`, + type: `number`, + }, + dim2Number: { + sql: `dim2Number`, + type: `number`, + }, + }, + + measures: { + count: { + type: `count`, + sql: `id`, + }, + measureDim1: { + sql: `dim1Number`, + type: + `max`, + }, + measureDim2: { + sql: `dim1Number`, + type: `min`, + }, + }, + }); + "#; + // Should generate + // cube(`cube1`, { + // sql: () => `SELECT * + // FROM table`, + // dimensions: { + // id: { + // sql: () => `id`, + // type: `number`, + // primary_key: true + // }, + // created_at: { + // sql: () => `created_at`, + // type: `time` + // }, + // dim1Number: { + // sql: () => `dim1Number`, + // type: `number` + // }, + // dim2Number: { + // sql: () => `dim2Number`, + // type: `number` + // } + // }, + // measures: { + // count: { + // type: `count`, + // sql: () => `id` + // }, + // measureDim1: { + // sql: () => `dim1Number`, + // type: `max` + // }, + // measureDim2: { + // sql: () => `dim1Number`, + // type: `min` + // } + // } + // }); + + let fm = cm.new_source_file( + Arc::new(FileName::Custom("input.js".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Es(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the JS code"); + + let mut visitor = CubePropTransformVisitor::new( + HashSet::new(), + HashMap::new(), + HashMap::new(), + None, + &handler, + ); + program.visit_mut_with(&mut visitor); + + let output_code = generate_code(&program, &cm); + + assert!( + output_code.contains("sql: ()=>`"), + "Output code should contain arrow function for *.sql, got:\n{}", + output_code + ); + let diags = diagnostics.lock().unwrap(); + assert!( + diags.is_empty(), + "Should not emit errors, got: {:?}", + *diags + ); +} + +#[test] +fn test_complicated_transform_1st_stage() { + let cm: Lrc = Default::default(); + let diagnostics = Arc::new(Mutex::new(Vec::new())); + let emitter = Box::new(TestEmitter { + diagnostics: diagnostics.clone(), + }); + let handler = Handler::with_emitter_and_flags( + emitter, + HandlerFlags { + can_emit_warnings: true, + ..Default::default() + }, + ); + + let js_code = r#" + cube(`Orders`, { + sql: ` + SELECT * + FROM public.orders + WHERE ${FILTER_GROUP( + FILTER_PARAMS.Orders.status.filter('status') + )} + `, + preAggregations: { + main_test_range: { + measures: [count, rolling_count_month], + dimensions: [status], + timeDimension: createdAt, + granularity: `day`, + partitionGranularity: `month`, + refreshKey: { + every: `1 day`, + }, + buildRangeStart: { + sql: `SELECT '2021-01-01'::DATE` + }, + build_range_end: { + sql: `SELECT '2021-12-31'::DATE` + } + + } + }, + measures: { + division_error_test: { + sql: `CASE WHEN ${zero_sum} = 0 THEN 1 ELSE 1/${zero_sum} end`, + type: `sum` + }, + zero_sum: { + sql: `id`, + type: `sum` + }, + rolling_count_month: { + sql: `id`, + type: `count`, + rollingWindow: { + trailing: `1 month`, + }, + }, + count: { + type: `count`, + drillMembers: [id, createdAt], + meta: { + test: 1 + } + }, + countShipped: { + type: `count`, + filters: [{ + sql: `${CUBE}.status = 'shipped'` + }], + drillMembers: [id, createdAt] + }, + maxDate: { + type: `max`, + sql: `${CUBE.completedAt}`, + } + }, + dimensions: { + id: { + sql: `id`, + type: `number`, + primaryKey: true, + shown: true + }, + status: { + sql: `status`, + type: `string` + }, + createdAt: { + sql: `created_at`, + type: `time` + }, + completedAt: { + sql: `completed_at`, + type: `time` + }, + test_boolean: { + sql: `CASE WHEN status = 'completed' THEN TRUE ELSE FALSE END`, + type: `boolean` + }, + localTime: { + type: 'time', + sql: SQL_UTILS.convertTz(`completed_at`) + }, + localYear: { + type: 'number', + sql: `EXTRACT(year from ${SQL_UTILS.convertTz('completed_at')})` + }, + }, + segments: { + status_completed: { + sql: `${CUBE}.status = 'completed'` + } + }, + accessPolicy: [ + { + role: "*", + rowLevel: { + allowAll: true, + }, + }, + { + role: 'admin', + conditions: [ + { + if: `true`, + }, + ], + rowLevel: { + filters: [ + { + member: `${CUBE}.id`, + operator: 'equals', + values: [`1`, `2`, `3`], + }, + ], + }, + memberLevel: { + includes: `*`, + excludes: [`localTime`, `completedAt`], + }, + }, + ] + }); + "#; + // Should generate + // cube(`Orders`, { + // sql: (FILTER_GROUP, FILTER_PARAMS) => ` + // SELECT * + // FROM public.orders + // WHERE ${FILTER_GROUP(FILTER_PARAMS.Orders.status.filter('status'))} + // `, + // preAggregations: { + // main_test_range: { + // measures: () => [count, rolling_count_month], + // dimensions: () => [status], + // timeDimension: () => createdAt, + // granularity: `day`, + // partitionGranularity: `month`, + // refreshKey: { + // every: `1 day`, + // }, + // buildRangeStart: { + // sql: () => `SELECT '2021-01-01'::DATE`, + // }, + // build_range_end: { + // sql: () => `SELECT '2021-12-31'::DATE`, + // }, + // }, + // }, + // measures: { + // division_error_test: { + // sql: () => `CASE WHEN ${zero_sum} = 0 THEN 1 ELSE 1/${zero_sum} end`, + // type: `sum`, + // }, + // zero_sum: { + // sql: () => `id`, + // type: `sum`, + // }, + // rolling_count_month: { + // sql: () => `id`, + // type: `count`, + // rollingWindow: { + // trailing: `1 month`, + // }, + // }, + // count: { + // type: `count`, + // drillMembers: () => [id, createdAt], + // meta: { + // test: 1, + // }, + // }, + // countShipped: { + // type: `count`, + // filters: [{ + // sql: CUBE => `${CUBE}.status = 'shipped'`, + // }], + // drillMembers: () => [id, createdAt], + // }, + // maxDate: { + // type: `max`, + // sql: CUBE => `${CUBE.completedAt}`, + // }, + // }, + // dimensions: { + // id: { + // sql: () => `id`, + // type: `number`, + // primaryKey: true, + // shown: true, + // }, + // status: { + // sql: () => `status`, + // type: `string`, + // }, + // createdAt: { + // sql: () => `created_at`, + // type: `time`, + // }, + // completedAt: { + // sql: () => `completed_at`, + // type: `time`, + // }, + // test_boolean: { + // sql: () => `CASE WHEN status = 'completed' THEN TRUE ELSE FALSE END`, + // type: `boolean`, + // }, + // localTime: { + // type: 'time', + // sql: SQL_UTILS => SQL_UTILS.convertTz(`completed_at`), + // }, + // localYear: { + // type: 'number', + // sql: SQL_UTILS => `EXTRACT(year from ${SQL_UTILS.convertTz('completed_at')})`, + // }, + // }, + // segments: { + // status_completed: { + // sql: CUBE => `${CUBE}.status = 'completed'`, + // }, + // }, + // accessPolicy: [{ + // role: "*", + // rowLevel: { + // allowAll: true + // } + // }, + // { + // role: 'admin', + // conditions: [{ + // if: () => `true` + // }], + // rowLevel: { + // filters: [{ + // member: CUBE => `${CUBE}.id`, + // operator: 'equals', + // values: () => [`1`, `2`, `3`] + // }] + // }, + // memberLevel: { + // includes: `*`, + // excludes: [`localTime`, `completedAt`] + // } + // }] + // }); + + let fm = cm.new_source_file( + Arc::new(FileName::Custom("input.js".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Es(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the JS code"); + + let mut visitor = CubePropTransformVisitor::new( + HashSet::new(), + HashMap::new(), + CONTEXT_SYMBOLS.clone(), + None, + &handler, + ); + + program.visit_mut_with(&mut visitor); + + let output_code = generate_code(&program, &cm); + + assert!( + output_code.contains("sql: ()=>`"), + "Output code should contain arrow function for *.sql, got:\n{}", + output_code + ); + assert!( + output_code.contains("sql: (FILTER_GROUP, FILTER_PARAMS)=>`"), + "Output code should contain `sql` arrow function with (FILTER_GROUP, FILTER_PARAMS), got:\n{}", + output_code + ); + assert!( + output_code.contains("measures: ()=>["), + "Output code should contain arrow function for preAggregations.measures, got:\n{}", + output_code + ); + assert!( + output_code.contains("dimensions: ()=>["), + "Output code should contain arrow function for preAggregations.dimensions, got:\n{}", + output_code + ); + assert!( + output_code.contains("timeDimension: ()=>"), + "Output code should contain arrow function for preAggregations.timeDimension, got:\n{}", + output_code + ); + assert!( + output_code.contains("drillMembers: ()=>["), + "Output code should contain arrow function for measure.drillMembers, got:\n{}", + output_code + ); + assert!( + output_code.contains("sql: (CUBE)=>`${CUBE}.status = 'shipped'`"), + "Output code should contain arrow function with CUBE as parameter for *.sql, got:\n{}", + output_code + ); + assert!( + output_code.contains("sql: (SQL_UTILS)=>SQL_UTILS.convertTz(`completed_at`)"), + "Output code should contain arrow function with SQL_UTILS as parameter for *.sql, got:\n{}", + output_code + ); + assert!( + output_code.contains("if: ()=>`true`"), + "Output code should contain arrow function for acl if condition, got:\n{}", + output_code + ); + assert!( + output_code.contains("member: (CUBE)=>`${CUBE}.id`"), + "Output code should contain arrow function for acl rowlevel filters member, got:\n{}", + output_code + ); + assert!( + output_code.contains("values: ()=>["), + "Output code should contain arrow function for acl rowlevel filters values, got:\n{}", + output_code + ); + let diags = diagnostics.lock().unwrap(); + assert!( + diags.is_empty(), + "Should not emit errors, got: {:?}", + *diags + ); +} + +#[test] +fn test_complicated_transform_2nd_stage() { + let cm: Lrc = Default::default(); + let diagnostics = Arc::new(Mutex::new(Vec::new())); + let emitter = Box::new(TestEmitter { + diagnostics: diagnostics.clone(), + }); + let handler = Handler::with_emitter_and_flags( + emitter, + HandlerFlags { + can_emit_warnings: true, + ..Default::default() + }, + ); + + let js_code = r#" + cube(`Orders`, { + sql: (FILTER_GROUP, FILTER_PARAMS) => ` + SELECT * + FROM public.orders + WHERE ${FILTER_GROUP(FILTER_PARAMS.Orders.status.filter('status'))} + `, + preAggregations: { + main_test_range: { + measures: () => [count, rolling_count_month], + dimensions: () => [status], + timeDimension: () => createdAt, + granularity: `day`, + partitionGranularity: `month`, + refreshKey: { + every: `1 day` + }, + buildRangeStart: { + sql: () => `SELECT '2021-01-01'::DATE` + }, + build_range_end: { + sql: () => `SELECT '2021-12-31'::DATE` + } + } + }, + measures: { + division_error_test: { + sql: () => `CASE WHEN ${zero_sum} = 0 THEN 1 ELSE 1/${zero_sum} end`, + type: `sum` + }, + zero_sum: { + sql: () => `id`, + type: `sum` + }, + rolling_count_month: { + sql: () => `id`, + type: `count`, + rollingWindow: { + trailing: `1 month` + } + }, + count: { + type: `count`, + drillMembers: () => [id, createdAt], + meta: { + test: 1 + } + }, + countShipped: { + type: `count`, + filters: [{ + sql: CUBE => `${CUBE}.status = 'shipped'` + }], + drillMembers: () => [id, createdAt] + }, + maxDate: { + type: `max`, + sql: CUBE => `${CUBE.completedAt}` + } + }, + dimensions: { + id: { + sql: () => `id`, + type: `number`, + primaryKey: true, + shown: true + }, + status: { + sql: () => `status`, + type: `string` + }, + createdAt: { + sql: () => `created_at`, + type: `time` + }, + completedAt: { + sql: () => `completed_at`, + type: `time` + }, + test_boolean: { + sql: () => `CASE WHEN status = 'completed' THEN TRUE ELSE FALSE END`, + type: `boolean` + }, + localTime: { + type: 'time', + sql: SQL_UTILS => SQL_UTILS.convertTz(`completed_at`) + }, + localYear: { + type: 'number', + sql: SQL_UTILS => `EXTRACT(year from ${SQL_UTILS.convertTz('completed_at')})` + } + }, + segments: { + status_completed: { + sql: CUBE => `${CUBE}.status = 'completed'` + } + }, + accessPolicy: [{ + role: "*", + rowLevel: { + allowAll: true + } + }, + { + role: 'admin', + conditions: [{ + if: () => `true` + }], + rowLevel: { + filters: [{ + member: CUBE => `${CUBE}.id`, + operator: 'equals', + values: () => [`1`, `2`, `3`] + }] + }, + memberLevel: { + includes: `*`, + excludes: [`localTime`, `completedAt`] + } + }] + }); + "#; + // Should generate + // cube(`Orders`, { + // sql: (FILTER_GROUP, FILTER_PARAMS) => ` + // SELECT * + // FROM public.orders + // WHERE ${FILTER_GROUP(FILTER_PARAMS.Orders.status.filter('status'))} + // `, + // preAggregations: { + // main_test_range: { + // measures: (count, rolling_count_month) => [count, rolling_count_month], + // dimensions: status => [status], + // timeDimension: createdAt => createdAt, + // granularity: `day`, + // partitionGranularity: `month`, + // refreshKey: { + // every: `1 day` + // }, + // buildRangeStart: { + // sql: () => `SELECT '2021-01-01'::DATE` + // }, + // build_range_end: { + // sql: () => `SELECT '2021-12-31'::DATE` + // } + // } + // }, + // measures: { + // division_error_test: { + // sql: zero_sum => `CASE WHEN ${zero_sum} = 0 THEN 1 ELSE 1/${zero_sum} end`, + // type: `sum` + // }, + // zero_sum: { + // sql: () => `id`, + // type: `sum` + // }, + // rolling_count_month: { + // sql: () => `id`, + // type: `count`, + // rollingWindow: { + // trailing: `1 month` + // } + // }, + // count: { + // type: `count`, + // drillMembers: (id, createdAt) => [id, createdAt], + // meta: { + // test: 1 + // } + // }, + // countShipped: { + // type: `count`, + // filters: [{ + // sql: CUBE => `${CUBE}.status = 'shipped'` + // }], + // drillMembers: (id, createdAt) => [id, createdAt] + // }, + // maxDate: { + // type: `max`, + // sql: CUBE => `${CUBE.completedAt}` + // } + // }, + // dimensions: { + // id: { + // sql: () => `id`, + // type: `number`, + // primaryKey: true, + // shown: true + // }, + // status: { + // sql: () => `status`, + // type: `string` + // }, + // createdAt: { + // sql: () => `created_at`, + // type: `time` + // }, + // completedAt: { + // sql: () => `completed_at`, + // type: `time` + // }, + // test_boolean: { + // sql: () => `CASE WHEN status = 'completed' THEN TRUE ELSE FALSE END`, + // type: `boolean` + // }, + // localTime: { + // type: 'time', + // sql: SQL_UTILS => SQL_UTILS.convertTz(`completed_at`) + // }, + // localYear: { + // type: 'number', + // sql: SQL_UTILS => `EXTRACT(year from ${SQL_UTILS.convertTz('completed_at')})` + // } + // }, + // segments: { + // status_completed: { + // sql: CUBE => `${CUBE}.status = 'completed'` + // } + // }, + // accessPolicy: [{ + // role: "*", + // rowLevel: { + // allowAll: true + // } + // }, + // { + // role: 'admin', + // conditions: [{ + // if: () => `true` + // }], + // rowLevel: { + // filters: [{ + // member: CUBE => `${CUBE}.id`, + // operator: 'equals', + // values: () => [`1`, `2`, `3`] + // }] + // }, + // memberLevel: { + // includes: `*`, + // excludes: [`localTime`, `completedAt`] + // } + // }] + // }); + + let fm = cm.new_source_file( + Arc::new(FileName::Custom("input.js".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Es(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the JS code"); + let mut cube_names = HashSet::new(); + cube_names.insert("Orders".to_string()); + let mut cube_symbols = HashMap::>::new(); + let mut orders_cube_symbols = HashMap::new(); + orders_cube_symbols.insert("division_error_test".to_string(), true); + orders_cube_symbols.insert("zero_sum".to_string(), true); + orders_cube_symbols.insert("rolling_count_month".to_string(), true); + orders_cube_symbols.insert("count".to_string(), true); + orders_cube_symbols.insert("countShipped".to_string(), true); + orders_cube_symbols.insert("id".to_string(), true); + orders_cube_symbols.insert("status".to_string(), true); + orders_cube_symbols.insert("createdAt".to_string(), true); + orders_cube_symbols.insert("completedAt".to_string(), true); + orders_cube_symbols.insert("test_boolean".to_string(), true); + orders_cube_symbols.insert("localTime".to_string(), true); + orders_cube_symbols.insert("localYear".to_string(), true); + orders_cube_symbols.insert("status_completed".to_string(), true); + orders_cube_symbols.insert("main_test_range".to_string(), true); + cube_symbols.insert("Orders".to_string(), orders_cube_symbols); + + let mut visitor = CubePropTransformVisitor::new( + cube_names, + cube_symbols, + CONTEXT_SYMBOLS.clone(), + None, + &handler, + ); + program.visit_mut_with(&mut visitor); + + let output_code = generate_code(&program, &cm); + + assert!( + output_code.contains("sql: ()=>`"), + "Output code should contain arrow function for *.sql, got:\n{}", + output_code + ); + assert!( + output_code + .contains("sql: (zero_sum)=>`CASE WHEN ${zero_sum} = 0 THEN 1 ELSE 1/${zero_sum} end`"), + "Output code should contain arrow function for sql() with local member as param, got:\n{}", + output_code + ); + assert!( + output_code.contains("sql: (FILTER_GROUP, FILTER_PARAMS)=>`"), + "Output code should contain `sql` arrow function with (FILTER_GROUP, FILTER_PARAMS), got:\n{}", + output_code + ); + assert!( + output_code.contains("measures: (count, rolling_count_month)=>["), + "Output code should contain arrow function for preAggregations.measures, got:\n{}", + output_code + ); + assert!( + output_code.contains("dimensions: (status)=>["), + "Output code should contain arrow function for preAggregations.dimensions, got:\n{}", + output_code + ); + assert!( + output_code.contains("timeDimension: (createdAt)=>createdAt"), + "Output code should contain arrow function for preAggregations.timeDimension, got:\n{}", + output_code + ); + assert!( + output_code.contains("drillMembers: (id, createdAt)=>["), + "Output code should contain arrow function for measure.drillMembers, got:\n{}", + output_code + ); + assert!( + output_code.contains("sql: (CUBE)=>`${CUBE}.status = 'shipped'`"), + "Output code should contain arrow function with CUBE as parameter for *.sql, got:\n{}", + output_code + ); + assert!( + output_code.contains("sql: (SQL_UTILS)=>SQL_UTILS.convertTz(`completed_at`)"), + "Output code should contain arrow function with SQL_UTILS as parameter for *.sql, got:\n{}", + output_code + ); + assert!( + output_code.contains("if: ()=>`true`"), + "Output code should contain arrow function for acl if condition, got:\n{}", + output_code + ); + assert!( + output_code.contains("member: (CUBE)=>`${CUBE}.id`"), + "Output code should contain arrow function for acl rowlevel filters member, got:\n{}", + output_code + ); + assert!( + output_code.contains("values: ()=>["), + "Output code should contain arrow function for acl rowlevel filters values, got:\n{}", + output_code + ); + let diags = diagnostics.lock().unwrap(); + assert!( + diags.is_empty(), + "Should not emit errors, got: {:?}", + *diags + ); +} diff --git a/rust/cubetranspilers/tests/import_export_test.rs b/rust/cubetranspilers/tests/import_export_test.rs new file mode 100644 index 0000000000000..c936dc4a4ce63 --- /dev/null +++ b/rust/cubetranspilers/tests/import_export_test.rs @@ -0,0 +1,430 @@ +mod common; + +// Recommended strategy to test plugin's transform is verify +// the Visitor's behavior, instead of trying to run `process_transform` with mocks +// unless explicitly required to do so. + +use std::sync::{Arc, Mutex}; + +use common::{generate_code, TestEmitter}; +use cubetranspilers::import_export_transpiler::*; +use swc_core::ecma::ast::{EsVersion, Program}; +use swc_core::{ + common::{ + errors::{Handler, HandlerFlags}, + sync::Lrc, + FileName, SourceMap, + }, + ecma::visit::VisitMutWith, +}; +use swc_ecma_parser::{lexer::Lexer, Parser, StringInput, Syntax}; + +#[test] +fn test_export_default_declaration() { + let cm: Lrc = Default::default(); + let diagnostics = Arc::new(Mutex::new(Vec::new())); + let emitter = Box::new(TestEmitter { + diagnostics: diagnostics.clone(), + }); + let handler = Handler::with_emitter_and_flags( + emitter, + HandlerFlags { + can_emit_warnings: true, + ..Default::default() + }, + ); + + let js_code = r#" + export default function exp() { console.log('exported function'); }; + "#; + + let fm = cm.new_source_file( + Arc::new(FileName::Custom("input.js".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Es(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the JS code"); + + let mut visitor = ImportExportTransformVisitor::new(None, &handler); + program.visit_mut_with(&mut visitor); + + let output_code = generate_code(&program, &cm); + + assert!( + output_code.contains("setExport(function()"), + "Output code should contain setExport call, got:\n{}", + output_code + ); + assert!( + output_code.contains("console.log('exported function')"), + "Output code should contain func body, got:\n{}", + output_code + ); + let diags = diagnostics.lock().unwrap(); + assert!( + diags.is_empty(), + "Should not emit errors, got: {:?}", + *diags + ); +} + +#[test] +fn test_export_default_expression() { + let cm: Lrc = Default::default(); + let diagnostics = Arc::new(Mutex::new(Vec::new())); + let emitter = Box::new(TestEmitter { + diagnostics: diagnostics.clone(), + }); + let handler = Handler::with_emitter_and_flags( + emitter, + HandlerFlags { + can_emit_warnings: true, + ..Default::default() + }, + ); + + let js_code = r#" + let myVar = 5; + export default myVar; + "#; + + let fm = cm.new_source_file( + Arc::new(FileName::Custom("input.js".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Es(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the JS code"); + + let mut visitor = ImportExportTransformVisitor::new(None, &handler); + program.visit_mut_with(&mut visitor); + + let output_code = generate_code(&program, &cm); + + assert!( + output_code.contains("setExport(myVar)"), + "Output code should contain setExport call, got:\n{}", + output_code + ); + let diags = diagnostics.lock().unwrap(); + assert!( + diags.is_empty(), + "Should not emit errors, got: {:?}", + *diags + ); +} + +#[test] +fn test_export_const_expression() { + let cm: Lrc = Default::default(); + let diagnostics = Arc::new(Mutex::new(Vec::new())); + let emitter = Box::new(TestEmitter { + diagnostics: diagnostics.clone(), + }); + let handler = Handler::with_emitter_and_flags( + emitter, + HandlerFlags { + can_emit_warnings: true, + ..Default::default() + }, + ); + + let js_code = r#" + export const sql = (input) => intput + 5; + export const a1 = 5, a2 = ()=>111, a3 = (inputA3)=>inputA3+"Done"; + "#; + + let fm = cm.new_source_file( + Arc::new(FileName::Custom("input.js".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Es(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the JS code"); + + let mut visitor = ImportExportTransformVisitor::new(None, &handler); + program.visit_mut_with(&mut visitor); + + let output_code = generate_code(&program, &cm); + + assert!( + output_code.contains("const sql = (input)=>intput + 5;"), + "Output code should contain original single const definition, got:\n{}", + output_code + ); + assert!( + output_code.contains("addExport({\n sql: sql\n})"), + "Output code should contain addExport call, got:\n{}", + output_code + ); + assert!( + output_code.contains("const a1 = 5, a2 = ()=>111, a3 = (inputA3)=>inputA3 + \"Done\""), + "Output code should contain original multiple const definitions, got:\n{}", + output_code + ); + assert!( + output_code.contains("addExport({\n a1: a1,\n a2: a2,\n a3: a3\n})"), + "Output code should contain addExport call, got:\n{}", + output_code + ); + + let diags = diagnostics.lock().unwrap(); + assert!( + diags.is_empty(), + "Should not emit errors, got: {:?}", + *diags + ); +} + +#[test] +fn test_import_named_default() { + let cm: Lrc = Default::default(); + let diagnostics = Arc::new(Mutex::new(Vec::new())); + let emitter = Box::new(TestEmitter { + diagnostics: diagnostics.clone(), + }); + let handler = Handler::with_emitter_and_flags( + emitter, + HandlerFlags { + can_emit_warnings: true, + ..Default::default() + }, + ); + + let js_code = r#" + import def, { foo, bar as baz } from "module"; + "#; + // Should generate + // const def = require("module"), foo = require("module").foo, baz = require("module").bar; + // + + let fm = cm.new_source_file( + Arc::new(FileName::Custom("import.js".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Es(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the JS code"); + + let mut visitor = ImportExportTransformVisitor::new(None, &handler); + program.visit_mut_with(&mut visitor); + + let output_code = generate_code(&program, &cm); + assert!( + output_code.contains("const"), + "Output code should contain a const declaration, got:\n{}", + output_code + ); + assert!( + output_code.contains("def = require(\"module\")"), + "Output code should contain 'def', got:\n{}", + output_code + ); + assert!( + output_code.contains("foo = require(\"module\").foo"), + "Output code should contain 'foo', got:\n{}", + output_code + ); + assert!( + output_code.contains("baz = require(\"module\").bar"), + "Output code should contain 'baz', got:\n{}", + output_code + ); + let diags = diagnostics.lock().unwrap(); + assert!( + diags.is_empty(), + "Should not emit errors, got: {:?}", + *diags + ); +} + +#[test] +fn test_namespace_import() { + let cm: Lrc = Default::default(); + let diagnostics = Arc::new(Mutex::new(Vec::new())); + let emitter = Box::new(TestEmitter { + diagnostics: diagnostics.clone(), + }); + let handler = Handler::with_emitter_and_flags( + emitter, + HandlerFlags { + can_emit_warnings: true, + ..Default::default() + }, + ); + + let js_code = r#" + import * as ns from "module"; + "#; + + let fm = cm.new_source_file( + Arc::new(FileName::Custom("ns_import.js".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Es(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the JS code"); + + let mut visitor = ImportExportTransformVisitor::new(None, &handler); + program.visit_mut_with(&mut visitor); + + let diags = diagnostics.lock().unwrap(); + let errors: Vec<_> = diags + .iter() + .filter(|msg| msg.contains("Namespace import not supported")) + .collect(); + assert!( + !errors.is_empty(), + "Expected error for namespace import, got diagnostics: {:?}", + *diags + ); +} + +#[test] +fn test_export_named() { + let cm: Lrc = Default::default(); + let diagnostics = Arc::new(Mutex::new(Vec::new())); + let emitter = Box::new(TestEmitter { + diagnostics: diagnostics.clone(), + }); + let handler = Handler::with_emitter_and_flags( + emitter, + HandlerFlags { + can_emit_warnings: true, + ..Default::default() + }, + ); + + let js_code = r#" + export { foo, bar as baz }; + "#; + // Should generate: + // addExport({ + // foo: foo, + // baz: bar + // }); + + let fm = cm.new_source_file( + Arc::new(FileName::Custom("export_named.js".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Es(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the JS code"); + + let mut visitor = ImportExportTransformVisitor::new(None, &handler); + program.visit_mut_with(&mut visitor); + + let output_code = generate_code(&program, &cm); + assert!( + output_code.contains("addExport"), + "Output code should contain addExport call, got:\n{}", + output_code + ); + assert!( + output_code.contains("foo: foo"), + "Output code should contain 'foo', got:\n{}", + output_code + ); + assert!( + output_code.contains("baz: bar"), + "Output code should contain 'baz', got:\n{}", + output_code + ); + let diags = diagnostics.lock().unwrap(); + assert!( + diags.is_empty(), + "Should not emit errors, got: {:?}", + *diags + ); +} + +#[test] +fn test_export_default_ts_interface() { + let cm: Lrc = Default::default(); + let diagnostics = Arc::new(Mutex::new(Vec::new())); + let emitter = Box::new(TestEmitter { + diagnostics: diagnostics.clone(), + }); + let handler = Handler::with_emitter_and_flags( + emitter, + HandlerFlags { + can_emit_warnings: true, + ..Default::default() + }, + ); + + let js_code = r#" + export default interface Foo {} + "#; + + let fm = cm.new_source_file( + Arc::new(FileName::Custom("export_default_ts_interface.ts".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Typescript(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the TS code"); + + let mut visitor = ImportExportTransformVisitor::new(None, &handler); + program.visit_mut_with(&mut visitor); + + let output_code = generate_code(&program, &cm); + // When exporting a TS interface, setExport is called with null as a fallback. + assert!( + output_code.contains("setExport"), + "Output code should contain setExport call, got:\n{}", + output_code + ); + assert!( + output_code.contains("null"), + "Output code should contain 'null' fallback, got:\n{}", + output_code + ); + let diags = diagnostics.lock().unwrap(); + let errors: Vec<_> = diags + .iter() + .filter(|msg| msg.contains("Unsupported default export declaration")) + .collect(); + assert!( + !errors.is_empty(), + "Expected error for TS interface default export, got diagnostics: {:?}", + *diags + ); +} diff --git a/rust/cubetranspilers/tests/validation_test.rs b/rust/cubetranspilers/tests/validation_test.rs new file mode 100644 index 0000000000000..c635f8e14d7f3 --- /dev/null +++ b/rust/cubetranspilers/tests/validation_test.rs @@ -0,0 +1,99 @@ +mod common; + +// Recommended strategy to test plugin's transform is verify +// the Visitor's behavior, instead of trying to run `process_transform` with mocks +// unless explicitly required to do so. + +use std::sync::{Arc, Mutex}; + +use common::TestEmitter; +use cubetranspilers::validation_transpiler::*; +use swc_core::ecma::ast::{EsVersion, Program}; +use swc_core::{ + common::{ + errors::{Handler, HandlerFlags}, + sync::Lrc, + FileName, SourceMap, + }, + ecma::visit::VisitMutWith, +}; +use swc_ecma_parser::{lexer::Lexer, Parser, StringInput, Syntax}; + +#[test] +fn test_warning_for_user_context() { + let cm: Lrc = Default::default(); + let diagnostics = Arc::new(Mutex::new(Vec::new())); + let emitter = Box::new(TestEmitter { + diagnostics: diagnostics.clone(), + }); + let handler = Handler::with_emitter_and_flags( + emitter, + HandlerFlags { + can_emit_warnings: true, + ..Default::default() + }, + ); + + let js_code = "USER_CONTEXT.something;"; + + let fm = cm.new_source_file( + Arc::new(FileName::Custom("input.js".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Es(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the JS code"); + + let mut visitor = ValidationTransformVisitor::new(None, &handler); + program.visit_mut_with(&mut visitor); + + let diags = diagnostics.lock().unwrap(); + assert!( + diags + .iter() + .any(|msg| msg.contains("Support for USER_CONTEXT was removed")), + "Should emit warning", + ); +} + +#[test] +fn test_no_warnings() { + let cm: Lrc = Default::default(); + let diagnostics = Arc::new(Mutex::new(Vec::new())); + let emitter = Box::new(TestEmitter { + diagnostics: diagnostics.clone(), + }); + let handler = Handler::with_emitter_and_flags( + emitter, + HandlerFlags { + can_emit_warnings: true, + ..Default::default() + }, + ); + + let js_code = "SECURITY_CONTEXT.something; let someOtherVar = 5;"; + + let fm = cm.new_source_file( + Arc::new(FileName::Custom("input.js".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Es(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the JS code"); + + let mut visitor = ValidationTransformVisitor::new(None, &handler); + program.visit_mut_with(&mut visitor); + + let diags = diagnostics.lock().unwrap(); + assert!(diags.is_empty(), "Should not emit warning",); +}