@tailor-platform/sdk 1.76.1 → 1.78.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +60 -0
- package/dist/{application-BUfYmf0O.mjs → application-CUxVA7Fs.mjs} +378 -1679
- package/dist/application-CUxVA7Fs.mjs.map +1 -0
- package/dist/application-Dp_-ioiP.mjs +3 -0
- package/dist/cli/cache/bundle-cache.d.mts +2 -1
- package/dist/cli/cache/store.d.mts +1 -1
- package/dist/cli/commands/api/index.d.mts +1 -0
- package/dist/cli/commands/deploy/aigateway.d.mts +5 -1
- package/dist/cli/commands/deploy/application.d.mts +7 -1
- package/dist/cli/commands/deploy/apply-phases.d.mts +14 -1
- package/dist/cli/commands/deploy/auth.d.mts +5 -1
- package/dist/cli/commands/deploy/deploy.d.mts +13 -3
- package/dist/cli/commands/deploy/executor.d.mts +7 -1
- package/dist/cli/commands/deploy/function-registry.d.mts +5 -0
- package/dist/cli/commands/deploy/idp.d.mts +5 -1
- package/dist/cli/commands/deploy/resolver.d.mts +5 -1
- package/dist/cli/commands/deploy/secret-manager.d.mts +5 -1
- package/dist/cli/commands/deploy/staticwebsite.d.mts +5 -1
- package/dist/cli/commands/deploy/tailordb/index.d.mts +8 -1
- package/dist/cli/commands/deploy/types.d.mts +3 -1
- package/dist/cli/commands/deploy/workflow-execution-policy.d.mts +3 -1
- package/dist/cli/commands/deploy/workflow.d.mts +4 -1
- package/dist/cli/commands/executor/get.d.mts +0 -1
- package/dist/cli/commands/executor/jobs.d.mts +0 -1
- package/dist/cli/commands/executor/list.d.mts +0 -1
- package/dist/cli/commands/executor/transform.d.mts +1 -0
- package/dist/cli/commands/executor/trigger.d.mts +0 -1
- package/dist/cli/commands/executor/webhook.d.mts +0 -1
- package/dist/cli/commands/function/get.d.mts +0 -1
- package/dist/cli/commands/function/list.d.mts +0 -1
- package/dist/cli/commands/function/transform.d.mts +1 -0
- package/dist/cli/commands/generate/service.d.mts +5 -1
- package/dist/cli/commands/generate/types.d.mts +3 -1
- package/dist/cli/commands/machineuser/list.d.mts +0 -1
- package/dist/cli/commands/machineuser/token.d.mts +0 -1
- package/dist/cli/commands/oauth2client/get.d.mts +0 -1
- package/dist/cli/commands/oauth2client/list.d.mts +0 -1
- package/dist/cli/commands/oauth2client/transform.d.mts +1 -0
- package/dist/cli/commands/organization/folder/create.d.mts +0 -1
- package/dist/cli/commands/organization/folder/delete.d.mts +0 -1
- package/dist/cli/commands/organization/folder/get.d.mts +0 -1
- package/dist/cli/commands/organization/folder/list.d.mts +0 -1
- package/dist/cli/commands/organization/folder/update.d.mts +0 -1
- package/dist/cli/commands/organization/get.d.mts +0 -1
- package/dist/cli/commands/organization/list.d.mts +0 -1
- package/dist/cli/commands/organization/transform.d.mts +2 -0
- package/dist/cli/commands/organization/tree.d.mts +0 -1
- package/dist/cli/commands/organization/update.d.mts +0 -1
- package/dist/cli/commands/remove.d.mts +0 -1
- package/dist/cli/commands/show.d.mts +9 -4
- package/dist/cli/commands/tailordb/migrate/config.d.mts +0 -1
- package/dist/cli/commands/tailordb/migrate/diff-calculator.d.mts +0 -1
- package/dist/cli/commands/tailordb/migrate/generate.d.mts +0 -1
- package/dist/cli/commands/tailordb/migrate/snapshot.d.mts +1 -1
- package/dist/cli/commands/tailordb/truncate.d.mts +0 -1
- package/dist/cli/commands/workflow/executions.d.mts +0 -1
- package/dist/cli/commands/workflow/get.d.mts +2 -1
- package/dist/cli/commands/workflow/list.d.mts +0 -1
- package/dist/cli/commands/workflow/resume.d.mts +0 -1
- package/dist/cli/commands/workflow/start.d.mts +0 -1
- package/dist/cli/commands/workflow/status.d.mts +1 -0
- package/dist/cli/commands/workflow/transform.d.mts +1 -0
- package/dist/cli/commands/workflow/wait.d.mts +0 -1
- package/dist/cli/commands/workflow/waiter.d.mts +1 -1
- package/dist/cli/commands/workspace/app/health.d.mts +0 -1
- package/dist/cli/commands/workspace/app/list.d.mts +0 -1
- package/dist/cli/commands/workspace/app/transform.d.mts +2 -0
- package/dist/cli/commands/workspace/create.d.mts +3 -1
- package/dist/cli/commands/workspace/delete.d.mts +0 -1
- package/dist/cli/commands/workspace/get.d.mts +0 -1
- package/dist/cli/commands/workspace/list.d.mts +1 -1
- package/dist/cli/commands/workspace/restore.d.mts +0 -1
- package/dist/cli/commands/workspace/transform.d.mts +4 -0
- package/dist/cli/commands/workspace/user/invite.d.mts +0 -1
- package/dist/cli/commands/workspace/user/list.d.mts +0 -1
- package/dist/cli/commands/workspace/user/remove.d.mts +0 -1
- package/dist/cli/commands/workspace/user/transform.d.mts +1 -0
- package/dist/cli/commands/workspace/user/update.d.mts +0 -1
- package/dist/cli/index.d.mts +3 -1
- package/dist/cli/index.mjs +660 -56
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cli/lib.d.mts +4 -2
- package/dist/cli/lib.mjs +3 -3
- package/dist/cli/lib.mjs.map +1 -1
- package/dist/cli/query/index.d.mts +0 -1
- package/dist/cli/services/application.d.mts +12 -1
- package/dist/cli/services/auth/service.d.mts +2 -0
- package/dist/cli/services/executor/service.d.mts +1 -1
- package/dist/cli/services/http-adapter/bundler.d.mts +3 -1
- package/dist/cli/services/http-adapter/service.d.mts +2 -1
- package/dist/cli/services/resolver/service.d.mts +1 -1
- package/dist/cli/services/tailordb/service.d.mts +3 -1
- package/dist/cli/services/workflow/bundler.d.mts +2 -1
- package/dist/cli/services/workflow/service.d.mts +1 -1
- package/dist/cli/shared/args.d.mts +1 -1
- package/dist/cli/shared/client.d.mts +1 -1
- package/dist/cli/shared/config-loader.d.mts +0 -1
- package/dist/cli/shared/context.d.mts +2 -1
- package/dist/cli/shared/script-executor.d.mts +0 -1
- package/dist/cli/shared/seed-chunker.d.mts +7 -3
- package/dist/cli/shared/type-generator.d.mts +0 -1
- package/dist/cli/shared/workspace-name.d.mts +1 -0
- package/dist/cli/skills.mjs +1 -1
- package/dist/completion/zsh-worker.zsh +18 -1
- package/dist/configure/config/index.d.mts +0 -1
- package/dist/configure/config/types.d.mts +2 -2
- package/dist/configure/index.d.mts +2 -1
- package/dist/configure/index.mjs +248 -4
- package/dist/configure/index.mjs.map +1 -1
- package/dist/configure/services/aigateway/index.d.mts +0 -1
- package/dist/configure/services/aigateway/types.d.mts +0 -1
- package/dist/configure/services/auth/index.d.mts +0 -1
- package/dist/configure/services/auth/types.d.mts +14 -13
- package/dist/configure/services/executor/executor.d.mts +0 -1
- package/dist/configure/services/executor/index.d.mts +1 -0
- package/dist/configure/services/executor/operation.d.mts +1 -2
- package/dist/configure/services/executor/trigger/event.d.mts +0 -1
- package/dist/configure/services/executor/trigger/index.d.mts +0 -1
- package/dist/configure/services/executor/trigger/schedule.d.mts +0 -1
- package/dist/configure/services/executor/trigger/webhook.d.mts +0 -1
- package/dist/configure/services/http-adapter/http-adapter.d.mts +1 -2
- package/dist/configure/services/idp/index.d.mts +1 -5
- package/dist/configure/services/idp/permission.d.mts +4 -5
- package/dist/configure/services/idp/types.d.mts +0 -1
- package/dist/configure/services/index.d.mts +5 -0
- package/dist/configure/services/resolver/resolver.d.mts +0 -1
- package/dist/configure/services/resolver/types.d.mts +0 -1
- package/dist/configure/services/secrets/index.d.mts +0 -1
- package/dist/configure/services/secrets/types.d.mts +0 -1
- package/dist/configure/services/staticwebsite/index.d.mts +0 -1
- package/dist/configure/services/staticwebsite/types.d.mts +0 -1
- package/dist/configure/services/tailordb/permission.d.mts +4 -5
- package/dist/configure/services/tailordb/schema.d.mts +21 -8
- package/dist/configure/services/tailordb/types.d.mts +4 -5
- package/dist/configure/services/workflow/execution-policy.d.mts +0 -1
- package/dist/configure/services/workflow/execution-policy.types.d.mts +0 -1
- package/dist/configure/services/workflow/index.d.mts +1 -0
- package/dist/configure/services/workflow/job.d.mts +0 -1
- package/dist/configure/services/workflow/wait-point.d.mts +0 -1
- package/dist/configure/services/workflow/workflow.d.mts +0 -1
- package/dist/configure/types/field-runtime.d.mts +1 -1
- package/dist/configure/types/field.d.mts +1 -2
- package/dist/configure/types/field.types.d.mts +1 -2
- package/dist/configure/types/type.d.mts +1 -1
- package/dist/configure/user.d.mts +0 -1
- package/dist/{crashreport-ayWANEZ6.mjs → crashreport-BNWUM6Kf.mjs} +4 -3
- package/dist/{crashreport-ayWANEZ6.mjs.map → crashreport-BNWUM6Kf.mjs.map} +1 -1
- package/dist/{crashreport-Dy4ZzSkd.mjs → crashreport-BafWvjjX.mjs} +1 -1
- package/dist/errors-DVFS0AZk.mjs +100 -0
- package/dist/errors-DVFS0AZk.mjs.map +1 -0
- package/dist/{globals-CcU1ONiK.mjs → globals-CvizbGLY.mjs} +2 -2
- package/dist/{globals-CcU1ONiK.mjs.map → globals-CvizbGLY.mjs.map} +1 -1
- package/dist/kysely/index.d.mts +3 -4
- package/dist/{logger-BEiZZ3qT.mjs → logger-BwS4ppwO.mjs} +3 -3
- package/dist/logger-BwS4ppwO.mjs.map +1 -0
- package/dist/parser/service/auth/index.d.mts +1 -1
- package/dist/parser/service/auth/schema.d.mts +1 -0
- package/dist/parser/service/http-adapter/index.d.mts +1 -1
- package/dist/parser/service/idp/types.d.mts +1 -0
- package/dist/parser/service/tailordb/types.d.mts +0 -1
- package/dist/plugin/builtin/enum-constants/index.d.mts +0 -1
- package/dist/plugin/builtin/file-utils/index.d.mts +0 -1
- package/dist/plugin/builtin/kysely-type/index.d.mts +0 -1
- package/dist/plugin/builtin/seed/index.d.mts +0 -1
- package/dist/plugin/builtin/seed/index.mjs +1 -1
- package/dist/plugin/get-generated-type.d.mts +0 -1
- package/dist/plugin/manager.d.mts +3 -1
- package/dist/plugin/types.d.mts +0 -1
- package/dist/plugin/with-context.d.mts +0 -1
- package/dist/{registry-NfSW0BRo.mjs → registry-CYBRvfaU.mjs} +4 -49
- package/dist/registry-CYBRvfaU.mjs.map +1 -0
- package/dist/runtime/aigateway.d.mts +0 -2
- package/dist/runtime/authconnection.d.mts +0 -2
- package/dist/runtime/globals.d.mts +0 -1
- package/dist/runtime/index.d.mts +0 -1
- package/dist/runtime/types.d.mts +16 -7
- package/dist/{runtime-_vUgjiqT.mjs → runtime-BD2vYJFT.mjs} +2382 -1167
- package/dist/runtime-BD2vYJFT.mjs.map +1 -0
- package/dist/{schema-DrVyN-LP.mjs → schema-U6DxoZ8D.mjs} +204 -3
- package/dist/schema-U6DxoZ8D.mjs.map +1 -0
- package/dist/{secret-file-VSVGy1V0.mjs → secret-file-DBqZhjFQ.mjs} +2 -27
- package/dist/{secret-file-VSVGy1V0.mjs.map → secret-file-DBqZhjFQ.mjs.map} +1 -1
- package/dist/{secretmanager-Bd45j7an.mjs → secretmanager-IY4UvinW.mjs} +42 -9
- package/dist/secretmanager-IY4UvinW.mjs.map +1 -0
- package/dist/seed/index.d.mts +3 -2
- package/dist/{seed-fm0LeYP2.mjs → seed-DFFigL8V.mjs} +3 -13
- package/dist/seed-DFFigL8V.mjs.map +1 -0
- package/dist/service-CghpdV-9.mjs +3 -0
- package/dist/{service-DBFZQloR.mjs → service-Cp0I7ZFe.mjs} +3 -3
- package/dist/{service-DBFZQloR.mjs.map → service-Cp0I7ZFe.mjs.map} +1 -1
- package/dist/{service-BCRJ-3NV.mjs → service-D12iQGcS.mjs} +2 -2
- package/dist/{service-BCRJ-3NV.mjs.map → service-D12iQGcS.mjs.map} +1 -1
- package/dist/service_pb-BoLM0X4K.mjs +167 -0
- package/dist/service_pb-BoLM0X4K.mjs.map +1 -0
- package/dist/{service_pb-B2FF59sP.mjs → service_pb-r1T7kpJc.mjs} +1 -1
- package/dist/tailor-proto/src/tailor/v1/aigateway_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/aigateway_resource_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/application_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/application_resource_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/auth_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/auth_resource_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/events_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/events_resource_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/executor_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/executor_resource_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/function_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/function_registry_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/function_resource_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/http_adapter_resource_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/idp_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/idp_resource_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/metadata_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/metadata_resource_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/meter_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/pipeline_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/pipeline_resource_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/resource_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/secret_manager_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/secret_manager_resource_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/service_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/stateflow_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/stateflow_resource_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/staticwebsite_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/staticwebsite_resource_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/tailordb_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/tailordb_resource_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/telemetryrouter_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/telemetryrouter_resource_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/workflow_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/workflow_resource_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/workspace_pb.d.mts +0 -1
- package/dist/tailor-proto/src/tailor/v1/workspace_resource_pb.d.mts +0 -1
- package/dist/test-env-key-DuZycyWM.mjs +49 -0
- package/dist/test-env-key-DuZycyWM.mjs.map +1 -0
- package/dist/type-source-DH_LH20p.mjs +13 -0
- package/dist/type-source-DH_LH20p.mjs.map +1 -0
- package/dist/types/aigateway.generated.d.mts +5 -2
- package/dist/types/auth-connection.generated.d.mts +11 -5
- package/dist/types/auth.generated.d.mts +118 -85
- package/dist/types/executor.generated.d.mts +76 -84
- package/dist/types/helpers.d.mts +5 -5
- package/dist/types/http-adapter.generated.d.mts +11 -5
- package/dist/types/idp.generated.d.mts +536 -524
- package/dist/types/resolver.generated.d.mts +24 -10
- package/dist/types/staticwebsite.generated.d.mts +7 -3
- package/dist/types/tailordb.generated.d.mts +55 -29
- package/dist/types/workflow.generated.d.mts +9 -4
- package/dist/user-agent-DX2Jnw0-.mjs +28 -0
- package/dist/user-agent-DX2Jnw0-.mjs.map +1 -0
- package/dist/utils/test/index.d.mts +0 -1
- package/dist/utils/test/index.mjs +1 -1
- package/dist/utils/test/mock.d.mts +0 -1
- package/dist/vitest/environment.mjs +1 -1
- package/dist/vitest/index.d.mts +9 -9
- package/dist/vitest/index.mjs +600 -185
- package/dist/vitest/index.mjs.map +1 -1
- package/dist/vitest/mock-kysely.d.mts +0 -1
- package/dist/vitest/mock.d.mts +8 -8
- package/dist/vitest/mocks/aigateway.d.mts +16 -6
- package/dist/vitest/mocks/authconnection.d.mts +16 -6
- package/dist/vitest/mocks/file.d.mts +24 -6
- package/dist/vitest/mocks/iconv.d.mts +28 -4
- package/dist/vitest/mocks/idp.d.mts +26 -10
- package/dist/vitest/mocks/secretmanager.d.mts +16 -5
- package/dist/vitest/mocks/tailordb.d.mts +54 -10
- package/dist/vitest/mocks/workflow.d.mts +48 -11
- package/dist/vitest/setup.mjs +2 -2
- package/dist/{service_pb-B5w9rjPY.mjs → workspace_resource_pb-Db3fv68L.mjs} +57 -165
- package/dist/workspace_resource_pb-Db3fv68L.mjs.map +1 -0
- package/docs/cli/application.md +58 -11
- package/docs/cli/setup.md +1 -1
- package/docs/cli/workspace.md +6 -4
- package/docs/cli-reference.md +12 -8
- package/docs/runtime.md +3 -4
- package/docs/services/aigateway.md +2 -0
- package/docs/services/tailordb.md +52 -1
- package/docs/services/workflow.md +1 -1
- package/docs/testing.md +103 -89
- package/package.json +16 -16
- package/dist/application-BUfYmf0O.mjs.map +0 -1
- package/dist/application-DbvD5UUz.mjs +0 -3
- package/dist/cli/shared/trigger-context.d.mts +0 -1
- package/dist/errors-Dtf2WPaW.mjs +0 -42
- package/dist/errors-Dtf2WPaW.mjs.map +0 -1
- package/dist/field-runtime-9bfXBAOK.mjs +0 -183
- package/dist/field-runtime-9bfXBAOK.mjs.map +0 -1
- package/dist/job-D-PbD1P3.mjs +0 -55
- package/dist/job-D-PbD1P3.mjs.map +0 -1
- package/dist/logger-BEiZZ3qT.mjs.map +0 -1
- package/dist/registry-NfSW0BRo.mjs.map +0 -1
- package/dist/resource_pb-BRv7AMXK.mjs +0 -49
- package/dist/resource_pb-BRv7AMXK.mjs.map +0 -1
- package/dist/runtime-_vUgjiqT.mjs.map +0 -1
- package/dist/schema-DrVyN-LP.mjs.map +0 -1
- package/dist/secretmanager-Bd45j7an.mjs.map +0 -1
- package/dist/seed-fm0LeYP2.mjs.map +0 -1
- package/dist/service-CPMlIg3X.mjs +0 -3
- package/dist/service_pb-B5w9rjPY.mjs.map +0 -1
- package/dist/types-BwzB2okW.mjs +0 -199
- package/dist/types-BwzB2okW.mjs.map +0 -1
- package/dist/types-KlawuVKa.mjs +0 -4
|
@@ -1,32 +1,20 @@
|
|
|
1
1
|
import { n as isSdkBranded } from "./brand-Eo4pLXPJ.mjs";
|
|
2
|
-
import { i as PageDirection } from "./resource_pb-BRv7AMXK.mjs";
|
|
3
2
|
import { t as assertDefined } from "./assert-DBxo8jPo.mjs";
|
|
4
|
-
import { a as parseBoolean, n as logger, r as styles } from "./logger-
|
|
5
|
-
import { a as TailorFieldSchema, i as AuthInvokerSchema, n as ExecutorSchema, o as loadFilesWithIgnores, r as AuthConfigSchema, s as functionSchema, t as createExecutorService } from "./service-
|
|
6
|
-
import { n as enumConstantsPlugin, t as EnumConstantsGeneratorID } from "./enum-constants-j9QBF0cB.mjs";
|
|
3
|
+
import { a as parseBoolean, n as logger, r as styles } from "./logger-BwS4ppwO.mjs";
|
|
4
|
+
import { a as TailorFieldSchema, i as AuthInvokerSchema, n as ExecutorSchema, o as loadFilesWithIgnores, r as AuthConfigSchema, s as functionSchema, t as createExecutorService } from "./service-D12iQGcS.mjs";
|
|
7
5
|
import { t as multiline } from "./multiline-sfHpTZZK.mjs";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { n as seedPlugin, r as isPluginGeneratedType, t as SeedGeneratorID } from "./seed-fm0LeYP2.mjs";
|
|
11
|
-
import { t as readPackageJson } from "./package-json-8b0O9TlX.mjs";
|
|
12
|
-
import { i as userAgent, n as tightenSecretFilePermissions, r as writeSecretFile } from "./secret-file-VSVGy1V0.mjs";
|
|
13
|
-
import { t as createCLIError } from "./errors-Dtf2WPaW.mjs";
|
|
6
|
+
import { t as isPluginGeneratedType } from "./type-source-DH_LH20p.mjs";
|
|
7
|
+
import { t as userAgent } from "./user-agent-DX2Jnw0-.mjs";
|
|
14
8
|
import { builtinModules, createRequire } from "node:module";
|
|
15
|
-
import { arg } from "politty";
|
|
16
9
|
import { z } from "zod";
|
|
17
10
|
import { create } from "@bufbuild/protobuf";
|
|
18
11
|
import * as fs$1 from "node:fs";
|
|
19
12
|
import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
20
|
-
import { parseEnv } from "node:util";
|
|
21
13
|
import { MethodOptions_IdempotencyLevel } from "@bufbuild/protobuf/wkt";
|
|
22
14
|
import * as path from "pathe";
|
|
23
15
|
import { join, resolve } from "pathe";
|
|
24
16
|
import { pathToFileURL } from "node:url";
|
|
25
17
|
import * as os from "node:os";
|
|
26
|
-
import { parseTOML, parseYAML, stringifyYAML } from "confbox";
|
|
27
|
-
import { findUpSync } from "find-up-simple";
|
|
28
|
-
import { lt } from "semver";
|
|
29
|
-
import { xdgConfig } from "xdg-basedir";
|
|
30
18
|
import { OAuth2Client } from "@badgateway/oauth2-client";
|
|
31
19
|
import { Code, ConnectError, createClient } from "@connectrpc/connect";
|
|
32
20
|
import { getGlobalDispatcher } from "undici";
|
|
@@ -39,256 +27,6 @@ import { parseSync } from "oxc-parser";
|
|
|
39
27
|
import * as inflection from "inflection";
|
|
40
28
|
import * as globals from "globals";
|
|
41
29
|
|
|
42
|
-
//#region src/cli/shared/args.ts
|
|
43
|
-
const unitToMs = {
|
|
44
|
-
ms: 1,
|
|
45
|
-
s: 1e3,
|
|
46
|
-
m: 60 * 1e3
|
|
47
|
-
};
|
|
48
|
-
const durationPattern = /^(\d+)(ms|s|m)$/;
|
|
49
|
-
/**
|
|
50
|
-
* Schema for duration string validation (e.g., "3s", "500ms", "1m")
|
|
51
|
-
* Only validates format; use parseDuration() to convert to milliseconds
|
|
52
|
-
*/
|
|
53
|
-
const durationArg = z.string().refine((val) => durationPattern.test(val), { message: "Invalid duration format. Expected format: '3s', '500ms', '1m'" }).refine((val) => {
|
|
54
|
-
const match = val.match(durationPattern);
|
|
55
|
-
if (!match) return false;
|
|
56
|
-
const digits = match[1];
|
|
57
|
-
return digits !== void 0 && parseInt(digits, 10) > 0;
|
|
58
|
-
}, { message: "Duration must be greater than 0" });
|
|
59
|
-
/**
|
|
60
|
-
* Parse a validated duration string into milliseconds
|
|
61
|
-
* @param duration - Duration string (e.g., "3s", "500ms", "1m")
|
|
62
|
-
* @returns Duration in milliseconds
|
|
63
|
-
*/
|
|
64
|
-
function parseDuration(duration) {
|
|
65
|
-
const match = assertDefined(duration.match(durationPattern), `invalid duration format: ${duration}`);
|
|
66
|
-
const value = parseInt(assertDefined(match[1], "duration digits group missing"), 10);
|
|
67
|
-
const unit = assertDefined(match[2], "duration unit group missing");
|
|
68
|
-
return value * unitToMs[unit];
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Schema for positive integer validation (from string input)
|
|
72
|
-
* Transforms the string to a number
|
|
73
|
-
*/
|
|
74
|
-
const positiveIntArg = z.coerce.number().int().positive();
|
|
75
|
-
/**
|
|
76
|
-
* Schema for non-negative integer validation (from string input).
|
|
77
|
-
* Accepts 0 (used for `--limit 0` to disable the limit).
|
|
78
|
-
*/
|
|
79
|
-
const nonNegativeIntArg = z.coerce.number().int().nonnegative();
|
|
80
|
-
/**
|
|
81
|
-
* Schema for sort order (`asc` or `desc`).
|
|
82
|
-
*/
|
|
83
|
-
const orderArg = z.enum(["asc", "desc"]);
|
|
84
|
-
/**
|
|
85
|
-
* Translate a CLI `--order` value into the proto `PageDirection` enum.
|
|
86
|
-
* Returns `undefined` when the user did not specify an order so that
|
|
87
|
-
* callers can omit the field and fall back to the server default.
|
|
88
|
-
* @param order - Order string from CLI args (`"asc"` | `"desc"` | undefined)
|
|
89
|
-
* @returns PageDirection, or undefined when `order` is undefined
|
|
90
|
-
*/
|
|
91
|
-
function toPageDirection(order) {
|
|
92
|
-
if (order === void 0) return void 0;
|
|
93
|
-
return order === "asc" ? PageDirection.ASC : PageDirection.DESC;
|
|
94
|
-
}
|
|
95
|
-
function hasMachineUserFlag(argv) {
|
|
96
|
-
return argv.slice(0, argv.indexOf("--") === -1 ? argv.length : argv.indexOf("--")).some((token) => token === "-m" || token.startsWith("-m=") || token === "--machine-user" || token.startsWith("--machine-user=") || token === "--machineUser" || token.startsWith("--machineUser=") || token === "--machineuser" || token.startsWith("--machineuser="));
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Resolve whether a parsed machine user value came from an explicit CLI option or env fallback.
|
|
100
|
-
* @param machineUser - Parsed machine user value
|
|
101
|
-
* @param argv - Raw CLI argv, excluding the executable and script path
|
|
102
|
-
* @param options - Source resolution options
|
|
103
|
-
* @returns Machine user input source, or undefined when no value was parsed
|
|
104
|
-
*/
|
|
105
|
-
function resolveMachineUserInputSource(machineUser, argv = process.argv.slice(2), options = {}) {
|
|
106
|
-
if (machineUser === void 0) return void 0;
|
|
107
|
-
if (options.valueIsExplicit) return "option";
|
|
108
|
-
if (hasMachineUserFlag(argv)) return "option";
|
|
109
|
-
return process.env.TAILOR_PLATFORM_MACHINE_USER_NAME === machineUser ? "env" : "option";
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* Load env files from parsed arguments.
|
|
113
|
-
* Processes --env-file first, then --env-file-if-exists.
|
|
114
|
-
*
|
|
115
|
-
* Follows Node.js --env-file behavior:
|
|
116
|
-
* - Variables already set in the environment are NOT overwritten
|
|
117
|
-
* - Variables from later files override those from earlier files
|
|
118
|
-
* @param envFiles - Required env file path(s) that must exist
|
|
119
|
-
* @param envFilesIfExists - Optional env file path(s) that are loaded if they exist
|
|
120
|
-
*/
|
|
121
|
-
function loadEnvFiles(envFiles, envFilesIfExists) {
|
|
122
|
-
const originalEnvKeys = new Set(Object.keys(process.env));
|
|
123
|
-
const load = (files, required) => {
|
|
124
|
-
for (const file of [files ?? []].flat()) {
|
|
125
|
-
const envPath = path.resolve(process.cwd(), file);
|
|
126
|
-
if (!fs$1.existsSync(envPath)) {
|
|
127
|
-
if (required) throw new Error(`Environment file not found: ${envPath}`);
|
|
128
|
-
continue;
|
|
129
|
-
}
|
|
130
|
-
const parsed = parseEnv(fs$1.readFileSync(envPath, "utf-8"));
|
|
131
|
-
for (const [key, value] of Object.entries(parsed)) {
|
|
132
|
-
if (originalEnvKeys.has(key)) continue;
|
|
133
|
-
process.env[key] = value;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
};
|
|
137
|
-
load(envFiles, true);
|
|
138
|
-
load(envFilesIfExists, false);
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* Common arguments for all CLI commands
|
|
142
|
-
*
|
|
143
|
-
* NOTE: --env-file and --env-file-if-exists collide with Node.js flags due to a bug
|
|
144
|
-
* (https://github.com/nodejs/node/issues/54232). Node.js parses these even after the
|
|
145
|
-
* script path, causing warnings (twice due to tsx loader).
|
|
146
|
-
*/
|
|
147
|
-
const commonArgs = {
|
|
148
|
-
"env-file": arg(z.string().optional(), {
|
|
149
|
-
alias: "e",
|
|
150
|
-
description: "Path to the environment file (error if not found)",
|
|
151
|
-
completion: {
|
|
152
|
-
type: "file",
|
|
153
|
-
matcher: [".env.*", ".env"]
|
|
154
|
-
}
|
|
155
|
-
}),
|
|
156
|
-
"env-file-if-exists": arg(z.string().optional(), {
|
|
157
|
-
description: "Path to the environment file (ignored if not found)",
|
|
158
|
-
completion: {
|
|
159
|
-
type: "file",
|
|
160
|
-
matcher: [".env.*", ".env"]
|
|
161
|
-
},
|
|
162
|
-
effect: (_value, { args }) => {
|
|
163
|
-
loadEnvFiles(args["env-file"], args["env-file-if-exists"]);
|
|
164
|
-
}
|
|
165
|
-
}),
|
|
166
|
-
verbose: arg(z.boolean().default(false), {
|
|
167
|
-
description: "Enable verbose logging",
|
|
168
|
-
effect: (value) => {
|
|
169
|
-
verboseMode = value;
|
|
170
|
-
}
|
|
171
|
-
}),
|
|
172
|
-
json: arg(z.boolean().default(false), {
|
|
173
|
-
alias: "j",
|
|
174
|
-
description: "Output as JSON",
|
|
175
|
-
effect: (value) => {
|
|
176
|
-
logger.jsonMode = value;
|
|
177
|
-
}
|
|
178
|
-
})
|
|
179
|
-
};
|
|
180
|
-
/**
|
|
181
|
-
* Arguments for commands that require workspace context
|
|
182
|
-
*/
|
|
183
|
-
const workspaceArgs = {
|
|
184
|
-
"workspace-id": arg(z.string().optional(), {
|
|
185
|
-
alias: "w",
|
|
186
|
-
description: "Workspace ID",
|
|
187
|
-
env: "TAILOR_PLATFORM_WORKSPACE_ID",
|
|
188
|
-
completion: { type: "none" }
|
|
189
|
-
}),
|
|
190
|
-
profile: arg(z.string().optional(), {
|
|
191
|
-
alias: "p",
|
|
192
|
-
description: "Workspace profile",
|
|
193
|
-
env: "TAILOR_PLATFORM_PROFILE",
|
|
194
|
-
completion: { type: "none" }
|
|
195
|
-
})
|
|
196
|
-
};
|
|
197
|
-
/**
|
|
198
|
-
* Shared config arg for commands that accept a config file path
|
|
199
|
-
*/
|
|
200
|
-
const configArg = { config: arg(z.string().default("tailor.config.ts"), {
|
|
201
|
-
alias: "c",
|
|
202
|
-
description: "Path to SDK config file",
|
|
203
|
-
env: "TAILOR_PLATFORM_SDK_CONFIG_PATH",
|
|
204
|
-
completion: {
|
|
205
|
-
type: "file",
|
|
206
|
-
extensions: ["ts"]
|
|
207
|
-
}
|
|
208
|
-
}) };
|
|
209
|
-
/**
|
|
210
|
-
* Shared config arg for commands that accept one or more comma-separated config file paths
|
|
211
|
-
*/
|
|
212
|
-
const multiConfigArg = { config: arg(z.string().default("tailor.config.ts"), {
|
|
213
|
-
alias: "c",
|
|
214
|
-
description: "Path to SDK config file. Use comma-separated paths to deploy multiple apps together.",
|
|
215
|
-
env: "TAILOR_PLATFORM_SDK_CONFIG_PATH",
|
|
216
|
-
completion: {
|
|
217
|
-
type: "file",
|
|
218
|
-
extensions: ["ts"]
|
|
219
|
-
}
|
|
220
|
-
}) };
|
|
221
|
-
/**
|
|
222
|
-
* Arguments for commands that interact with deployed resources (includes config)
|
|
223
|
-
*/
|
|
224
|
-
const deploymentArgs = {
|
|
225
|
-
...workspaceArgs,
|
|
226
|
-
...configArg
|
|
227
|
-
};
|
|
228
|
-
/**
|
|
229
|
-
* Arguments for commands that require confirmation
|
|
230
|
-
*/
|
|
231
|
-
const confirmationArgs = { yes: arg(z.boolean().default(false), {
|
|
232
|
-
alias: "y",
|
|
233
|
-
description: "Skip confirmation prompts"
|
|
234
|
-
}) };
|
|
235
|
-
/**
|
|
236
|
-
* Arguments for commands that require organization context
|
|
237
|
-
*/
|
|
238
|
-
const organizationArgs = { "organization-id": arg(z.string(), {
|
|
239
|
-
alias: "o",
|
|
240
|
-
description: "Organization ID",
|
|
241
|
-
env: "TAILOR_PLATFORM_ORGANIZATION_ID",
|
|
242
|
-
completion: { type: "none" }
|
|
243
|
-
}) };
|
|
244
|
-
/**
|
|
245
|
-
* Arguments for list commands that accept `--order` / `--limit`. Sort
|
|
246
|
-
* order defaults to `desc` (newest first) because most callers want the
|
|
247
|
-
* latest items; pass `--order asc` to opt in to ascending order. The
|
|
248
|
-
* limit is unbounded by default so existing invocations keep returning
|
|
249
|
-
* every item; pass `--limit N` to cap the result size.
|
|
250
|
-
* @param defaultOrder - Default value for `--order` (defaults to `"desc"`)
|
|
251
|
-
* @returns Argument shape suitable for spreading into a command schema
|
|
252
|
-
*/
|
|
253
|
-
const paginationArgs = (defaultOrder = "desc") => ({
|
|
254
|
-
order: arg(orderArg.default(defaultOrder), { description: "Sort order (asc or desc)" }),
|
|
255
|
-
limit: arg(nonNegativeIntArg.optional(), {
|
|
256
|
-
alias: "l",
|
|
257
|
-
description: "Maximum number of items to return (0 or omit: unlimited)"
|
|
258
|
-
})
|
|
259
|
-
});
|
|
260
|
-
/**
|
|
261
|
-
* Arguments for time-series log list commands. Defaults to newest-first
|
|
262
|
-
* (`desc`) and a 50-item cap so that listing stays responsive on busy
|
|
263
|
-
* workspaces. Pass `--limit 0` to disable the cap and fetch all entries.
|
|
264
|
-
*/
|
|
265
|
-
const pagedLogArgs = {
|
|
266
|
-
order: arg(orderArg.default("desc"), { description: "Sort order (asc or desc)" }),
|
|
267
|
-
limit: arg(nonNegativeIntArg.default(50), {
|
|
268
|
-
alias: "l",
|
|
269
|
-
description: "Maximum number of items to return (0: unlimited)"
|
|
270
|
-
})
|
|
271
|
-
};
|
|
272
|
-
/**
|
|
273
|
-
* Arguments for commands that require folder context
|
|
274
|
-
*/
|
|
275
|
-
const folderArgs = { "folder-id": arg(z.string(), {
|
|
276
|
-
alias: "f",
|
|
277
|
-
description: "Folder ID",
|
|
278
|
-
env: "TAILOR_PLATFORM_FOLDER_ID",
|
|
279
|
-
completion: { type: "none" }
|
|
280
|
-
}) };
|
|
281
|
-
let verboseMode = false;
|
|
282
|
-
/**
|
|
283
|
-
* Returns whether verbose mode is enabled.
|
|
284
|
-
* Used by the global cleanup handler which doesn't have access to parsed args.
|
|
285
|
-
* @returns Whether verbose mode is enabled
|
|
286
|
-
*/
|
|
287
|
-
function isVerbose() {
|
|
288
|
-
return verboseMode;
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
//#endregion
|
|
292
30
|
//#region src/parser/app-config/log-level.ts
|
|
293
31
|
const LOG_LEVELS = [
|
|
294
32
|
"DEBUG",
|
|
@@ -301,110 +39,6 @@ function isLogLevel(value) {
|
|
|
301
39
|
return LOG_LEVELS.includes(value);
|
|
302
40
|
}
|
|
303
41
|
|
|
304
|
-
//#endregion
|
|
305
|
-
//#region src/parser/app-config/schema.ts
|
|
306
|
-
const envValueSchema = z.union([
|
|
307
|
-
z.string(),
|
|
308
|
-
z.number(),
|
|
309
|
-
z.boolean()
|
|
310
|
-
]);
|
|
311
|
-
const LogLevelSchema = z.enum(LOG_LEVELS);
|
|
312
|
-
const logLevelSchema = z.string().refine((value) => LogLevelSchema.safeParse(value.trim().toUpperCase()).success, { message: `'logLevel' must be one of: ${LOG_LEVELS.join(", ")}.` });
|
|
313
|
-
/**
|
|
314
|
-
* Structural validation schema for `defineConfig({...})`. Validates only
|
|
315
|
-
* top-level fields with platform-side constraints (notably `id`); fields
|
|
316
|
-
* that carry SDK builder objects (`auth`, `idp`, `db`, ...) are accepted
|
|
317
|
-
* as opaque values, since their internal shapes are validated by their
|
|
318
|
-
* own factory functions and parser-level schemas.
|
|
319
|
-
*
|
|
320
|
-
* The `id` is auto-managed by `deploy` and stored as a plain UUID. A
|
|
321
|
-
* label-compatible prefix is added at the metadata boundary, so user-facing
|
|
322
|
-
* configs only need to carry a UUID.
|
|
323
|
-
*/
|
|
324
|
-
const AppConfigSchema = z.object({
|
|
325
|
-
id: z.uuid({ message: "'id' must be a UUID." }).optional(),
|
|
326
|
-
name: z.string().min(1, { message: "'name' must be a non-empty string." }),
|
|
327
|
-
env: z.record(z.string(), envValueSchema).optional(),
|
|
328
|
-
cors: z.array(z.string()).optional(),
|
|
329
|
-
allowedIpAddresses: z.array(z.string()).optional(),
|
|
330
|
-
disableIntrospection: z.boolean().optional(),
|
|
331
|
-
inlineSourcemap: z.boolean().optional(),
|
|
332
|
-
logLevel: logLevelSchema.optional(),
|
|
333
|
-
db: z.unknown().optional(),
|
|
334
|
-
resolver: z.unknown().optional(),
|
|
335
|
-
idp: z.unknown().optional(),
|
|
336
|
-
auth: z.unknown().optional(),
|
|
337
|
-
executor: z.unknown().optional(),
|
|
338
|
-
workflow: z.unknown().optional(),
|
|
339
|
-
httpAdapter: z.unknown().optional(),
|
|
340
|
-
staticWebsites: z.unknown().optional(),
|
|
341
|
-
aiGateways: z.unknown().optional(),
|
|
342
|
-
secrets: z.unknown().optional()
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
//#endregion
|
|
346
|
-
//#region src/parser/generator-config/schema.ts
|
|
347
|
-
const DependencyKindSchema = z.enum([
|
|
348
|
-
"tailordb",
|
|
349
|
-
"resolver",
|
|
350
|
-
"executor"
|
|
351
|
-
]);
|
|
352
|
-
const KyselyTypeConfigSchema = z.tuple([z.literal("@tailor-platform/kysely-type"), z.object({ distPath: z.string() })]);
|
|
353
|
-
const SeedConfigSchema = z.tuple([z.literal("@tailor-platform/seed"), z.object({
|
|
354
|
-
distPath: z.string(),
|
|
355
|
-
machineUserName: z.string().optional(),
|
|
356
|
-
disableIdpUserSync: z.object({
|
|
357
|
-
userToIdp: z.boolean().optional(),
|
|
358
|
-
idpToUser: z.boolean().optional()
|
|
359
|
-
}).optional()
|
|
360
|
-
})]);
|
|
361
|
-
const EnumConstantsConfigSchema = z.tuple([z.literal("@tailor-platform/enum-constants"), z.object({ distPath: z.string() })]);
|
|
362
|
-
const FileUtilsConfigSchema = z.tuple([z.literal("@tailor-platform/file-utils"), z.object({ distPath: z.string() })]);
|
|
363
|
-
const CodeGeneratorSchema = z.object({
|
|
364
|
-
id: z.string(),
|
|
365
|
-
description: z.string(),
|
|
366
|
-
dependencies: z.array(DependencyKindSchema),
|
|
367
|
-
processType: z.function().optional(),
|
|
368
|
-
processResolver: z.function().optional(),
|
|
369
|
-
processExecutor: z.function().optional(),
|
|
370
|
-
processTailorDBNamespace: z.function().optional(),
|
|
371
|
-
processResolverNamespace: z.function().optional(),
|
|
372
|
-
aggregate: z.function({ output: z.any() })
|
|
373
|
-
});
|
|
374
|
-
const BaseGeneratorConfigSchema = z.union([
|
|
375
|
-
KyselyTypeConfigSchema,
|
|
376
|
-
SeedConfigSchema,
|
|
377
|
-
EnumConstantsConfigSchema,
|
|
378
|
-
FileUtilsConfigSchema,
|
|
379
|
-
CodeGeneratorSchema
|
|
380
|
-
]);
|
|
381
|
-
|
|
382
|
-
//#endregion
|
|
383
|
-
//#region src/parser/plugin-config/schema.ts
|
|
384
|
-
const PluginConfigSchema = z.object({
|
|
385
|
-
id: z.string(),
|
|
386
|
-
description: z.string(),
|
|
387
|
-
importPath: z.string().optional(),
|
|
388
|
-
pluginConfig: z.unknown().optional(),
|
|
389
|
-
typeConfigRequired: z.union([z.boolean(), functionSchema]).optional(),
|
|
390
|
-
onTypeLoaded: functionSchema.optional(),
|
|
391
|
-
onNamespaceLoaded: functionSchema.optional(),
|
|
392
|
-
onTailorDBReady: functionSchema.optional(),
|
|
393
|
-
onResolverReady: functionSchema.optional(),
|
|
394
|
-
onExecutorReady: functionSchema.optional()
|
|
395
|
-
}).passthrough().refine((p) => {
|
|
396
|
-
return !(p.onTypeLoaded || p.onNamespaceLoaded) || !!p.importPath;
|
|
397
|
-
}, { message: "importPath is required when plugin has definition-time hooks (onTypeLoaded/onNamespaceLoaded)" }).transform((plugin) => plugin);
|
|
398
|
-
|
|
399
|
-
//#endregion
|
|
400
|
-
//#region src/plugin/builtin/registry.ts
|
|
401
|
-
const builtinPlugins = /* @__PURE__ */ new Map([
|
|
402
|
-
[KyselyGeneratorID, (options) => kyselyTypePlugin(options)],
|
|
403
|
-
[SeedGeneratorID, (options) => seedPlugin(options)],
|
|
404
|
-
[EnumConstantsGeneratorID, (options) => enumConstantsPlugin(options)],
|
|
405
|
-
[FileUtilsGeneratorID, (options) => fileUtilsPlugin(options)]
|
|
406
|
-
]);
|
|
407
|
-
|
|
408
42
|
//#endregion
|
|
409
43
|
//#region src/cli/shared/apply-concurrency.ts
|
|
410
44
|
/**
|
|
@@ -547,7 +181,7 @@ function initOAuth2Client(config) {
|
|
|
547
181
|
*/
|
|
548
182
|
async function initOperatorClient(accessToken, config) {
|
|
549
183
|
const platformConfig = config ?? getPlatformConfigForToken(accessToken);
|
|
550
|
-
const [{ createTracingInterceptor }, { OperatorService }] = await Promise.all([import("./interceptor-D-q1rvRl.mjs"), import("./service_pb-
|
|
184
|
+
const [{ createTracingInterceptor }, { OperatorService }] = await Promise.all([import("./interceptor-D-q1rvRl.mjs"), import("./service_pb-r1T7kpJc.mjs")]);
|
|
551
185
|
const interceptors = [
|
|
552
186
|
await userAgentInterceptor(),
|
|
553
187
|
await bearerTokenInterceptor(accessToken),
|
|
@@ -600,9 +234,9 @@ async function bearerTokenInterceptor(accessToken) {
|
|
|
600
234
|
/**
|
|
601
235
|
* Create an interceptor that retries failed unary requests with backoff.
|
|
602
236
|
*
|
|
603
|
-
* Retries
|
|
604
|
-
* only for methods declared idempotent, up to 3 attempts
|
|
605
|
-
*
|
|
237
|
+
* Retries unary methods on `Unavailable`/`ResourceExhausted`, and `Internal`
|
|
238
|
+
* only for methods declared idempotent, up to 3 attempts. Workspace creation is
|
|
239
|
+
* excluded because it has no idempotency key and a lost response is ambiguous.
|
|
606
240
|
* As a targeted exception for the deploy/apply flow, a post-retry `AlreadyExists`
|
|
607
241
|
* from an allowlisted Create (see `RETRY_SAFE_CREATE_METHODS`) is treated as
|
|
608
242
|
* success, since it means a prior attempt already committed the resource
|
|
@@ -627,10 +261,10 @@ function retryInterceptor() {
|
|
|
627
261
|
logger.debug(`retry: ${req.method.name} returned AlreadyExists on attempt ${i + 1}; treating as success (prior attempt likely committed)`);
|
|
628
262
|
return synthesizeEmptyUnaryResponse(req);
|
|
629
263
|
}
|
|
630
|
-
const { reportCrash } = await import("./crashreport-
|
|
264
|
+
const { reportCrash } = await import("./crashreport-BafWvjjX.mjs");
|
|
631
265
|
await reportCrash(error, "handledError");
|
|
632
266
|
}
|
|
633
|
-
if (isRetirable(error, req.method.idempotency)) {
|
|
267
|
+
if (req.method.name !== "CreateWorkspace" && isRetirable(error, req.method.idempotency)) {
|
|
634
268
|
lastError = error;
|
|
635
269
|
logger.debug(`retry: ${req.method.name} attempt ${i + 1} failed with ${connectCodeName(error)}; retrying`);
|
|
636
270
|
continue;
|
|
@@ -1032,742 +666,6 @@ async function closeConnectionPool() {
|
|
|
1032
666
|
await getGlobalDispatcher().close();
|
|
1033
667
|
}
|
|
1034
668
|
|
|
1035
|
-
//#endregion
|
|
1036
|
-
//#region src/cli/shared/token-store.ts
|
|
1037
|
-
const SERVICE_NAME = "tailor-platform-cli";
|
|
1038
|
-
let entryClass;
|
|
1039
|
-
async function getEntryClass() {
|
|
1040
|
-
if (entryClass !== void 0) return entryClass;
|
|
1041
|
-
try {
|
|
1042
|
-
const mod = await import("@napi-rs/keyring");
|
|
1043
|
-
const probe = new mod.Entry(SERVICE_NAME, "__probe__");
|
|
1044
|
-
probe.setPassword("probe");
|
|
1045
|
-
probe.deletePassword();
|
|
1046
|
-
entryClass = mod.Entry;
|
|
1047
|
-
} catch {
|
|
1048
|
-
logger.warn("System keyring is not available. Tokens will be stored in the config file. Set TAILOR_PLATFORM_TOKEN environment variable for CI environments.");
|
|
1049
|
-
entryClass = false;
|
|
1050
|
-
}
|
|
1051
|
-
return entryClass;
|
|
1052
|
-
}
|
|
1053
|
-
/**
|
|
1054
|
-
* Check whether the OS keyring is available and functional.
|
|
1055
|
-
* @returns true if keyring is available
|
|
1056
|
-
*/
|
|
1057
|
-
async function isKeyringAvailable() {
|
|
1058
|
-
return await getEntryClass() !== false;
|
|
1059
|
-
}
|
|
1060
|
-
/**
|
|
1061
|
-
* Load tokens from the OS keyring for a given account.
|
|
1062
|
-
* @param account - User identifier (e.g. email or client ID)
|
|
1063
|
-
* @returns Token data or undefined if not found or keyring unavailable
|
|
1064
|
-
*/
|
|
1065
|
-
async function loadKeyringTokens(account) {
|
|
1066
|
-
const Entry = await getEntryClass();
|
|
1067
|
-
if (!Entry) return void 0;
|
|
1068
|
-
try {
|
|
1069
|
-
const raw = new Entry(SERVICE_NAME, account).getPassword();
|
|
1070
|
-
if (raw === null) return void 0;
|
|
1071
|
-
return JSON.parse(raw);
|
|
1072
|
-
} catch {
|
|
1073
|
-
return;
|
|
1074
|
-
}
|
|
1075
|
-
}
|
|
1076
|
-
/**
|
|
1077
|
-
* Save tokens to the OS keyring for a given account.
|
|
1078
|
-
* @param account - User identifier (e.g. email or client ID)
|
|
1079
|
-
* @param tokens - Token data to store
|
|
1080
|
-
*/
|
|
1081
|
-
async function saveKeyringTokens(account, tokens) {
|
|
1082
|
-
const Entry = await getEntryClass();
|
|
1083
|
-
if (!Entry) return;
|
|
1084
|
-
new Entry(SERVICE_NAME, account).setPassword(JSON.stringify(tokens));
|
|
1085
|
-
}
|
|
1086
|
-
/**
|
|
1087
|
-
* Delete tokens from the OS keyring for a given account.
|
|
1088
|
-
* @param account - User identifier (e.g. email or client ID)
|
|
1089
|
-
*/
|
|
1090
|
-
async function deleteKeyringTokens(account) {
|
|
1091
|
-
const Entry = await getEntryClass();
|
|
1092
|
-
if (!Entry) return;
|
|
1093
|
-
try {
|
|
1094
|
-
new Entry(SERVICE_NAME, account).deletePassword();
|
|
1095
|
-
} catch {}
|
|
1096
|
-
}
|
|
1097
|
-
|
|
1098
|
-
//#endregion
|
|
1099
|
-
//#region src/cli/shared/context.ts
|
|
1100
|
-
const pfProfileSchema = z.object({
|
|
1101
|
-
user: z.string(),
|
|
1102
|
-
workspace_id: z.string(),
|
|
1103
|
-
readonly: z.boolean().optional(),
|
|
1104
|
-
machine_user: z.string().optional(),
|
|
1105
|
-
machine_user_override: z.enum(["allow", "deny"]).optional(),
|
|
1106
|
-
platform_url: z.url().optional(),
|
|
1107
|
-
oauth2_client_id: z.string().optional(),
|
|
1108
|
-
console_url: z.url().optional()
|
|
1109
|
-
});
|
|
1110
|
-
const pfUserSchemaV1 = z.object({
|
|
1111
|
-
access_token: z.string(),
|
|
1112
|
-
refresh_token: z.string().optional(),
|
|
1113
|
-
token_expires_at: z.string()
|
|
1114
|
-
});
|
|
1115
|
-
const pfUserKeyringSchema = z.object({
|
|
1116
|
-
storage: z.literal("keyring"),
|
|
1117
|
-
token_expires_at: z.string()
|
|
1118
|
-
});
|
|
1119
|
-
const pfUserFileSchema = z.object({
|
|
1120
|
-
storage: z.literal("file"),
|
|
1121
|
-
token_expires_at: z.string(),
|
|
1122
|
-
access_token: z.string(),
|
|
1123
|
-
refresh_token: z.string().optional()
|
|
1124
|
-
});
|
|
1125
|
-
const pfUserSchemaV2 = z.discriminatedUnion("storage", [pfUserKeyringSchema, pfUserFileSchema]);
|
|
1126
|
-
const pfConfigSchemaV1 = z.object({
|
|
1127
|
-
version: z.literal(1),
|
|
1128
|
-
users: z.partialRecord(z.string(), pfUserSchemaV1),
|
|
1129
|
-
profiles: z.partialRecord(z.string(), pfProfileSchema),
|
|
1130
|
-
current_user: z.string().nullable()
|
|
1131
|
-
});
|
|
1132
|
-
const V2_CONFIG_VERSION = 2;
|
|
1133
|
-
const LATEST_CONFIG_VERSION = 3;
|
|
1134
|
-
const V2_MIN_SDK_VERSION = "1.29.0";
|
|
1135
|
-
const V3_MIN_SDK_VERSION = "1.70.0";
|
|
1136
|
-
const semverSchema = z.templateLiteral([
|
|
1137
|
-
z.number().int(),
|
|
1138
|
-
".",
|
|
1139
|
-
z.number().int(),
|
|
1140
|
-
".",
|
|
1141
|
-
z.number().int()
|
|
1142
|
-
]);
|
|
1143
|
-
const pfConfigSchema = z.object({
|
|
1144
|
-
version: z.union([z.literal(V2_CONFIG_VERSION), z.literal(LATEST_CONFIG_VERSION)]),
|
|
1145
|
-
min_sdk_version: semverSchema,
|
|
1146
|
-
latest_version: z.number().int().optional(),
|
|
1147
|
-
latest_min_sdk_version: semverSchema.optional(),
|
|
1148
|
-
users: z.partialRecord(z.string(), pfUserSchemaV2),
|
|
1149
|
-
profiles: z.partialRecord(z.string(), pfProfileSchema),
|
|
1150
|
-
current_user: z.string().nullable()
|
|
1151
|
-
});
|
|
1152
|
-
function platformConfigPath() {
|
|
1153
|
-
if (!xdgConfig) throw new Error("User home directory not found");
|
|
1154
|
-
return path.join(xdgConfig, "tailor-platform", "config.yaml");
|
|
1155
|
-
}
|
|
1156
|
-
/**
|
|
1157
|
-
* Convert stored profile platform fields to platform client settings.
|
|
1158
|
-
* @param profile - Profile platform settings
|
|
1159
|
-
* @returns Platform client settings
|
|
1160
|
-
*/
|
|
1161
|
-
function platformConfigFromProfile(profile) {
|
|
1162
|
-
const config = {
|
|
1163
|
-
...profile?.platform_url ? { platformUrl: profile.platform_url } : {},
|
|
1164
|
-
...profile?.oauth2_client_id ? { oauth2ClientId: profile.oauth2_client_id } : {},
|
|
1165
|
-
...profile?.console_url ? { consoleUrl: profile.console_url } : {}
|
|
1166
|
-
};
|
|
1167
|
-
return Object.keys(config).length > 0 ? config : void 0;
|
|
1168
|
-
}
|
|
1169
|
-
function platformUserKey(user, config) {
|
|
1170
|
-
const platformUrl = getPlatformBaseUrl(config);
|
|
1171
|
-
if (platformUrl === normalizeBaseUrl("https://api.tailor.tech")) return user;
|
|
1172
|
-
return `${platformUrl}|${user}`;
|
|
1173
|
-
}
|
|
1174
|
-
function canUseLegacyUserKey(platformUrl) {
|
|
1175
|
-
try {
|
|
1176
|
-
return getPlatformBaseUrl() === platformUrl;
|
|
1177
|
-
} catch {
|
|
1178
|
-
return false;
|
|
1179
|
-
}
|
|
1180
|
-
}
|
|
1181
|
-
function findUserEntry(config, user, platformConfig, opts = {}) {
|
|
1182
|
-
const userKey = platformUserKey(user, platformConfig);
|
|
1183
|
-
const userEntry = config.users[userKey];
|
|
1184
|
-
if (userEntry) return {
|
|
1185
|
-
userKey,
|
|
1186
|
-
userEntry
|
|
1187
|
-
};
|
|
1188
|
-
const platformUrl = getPlatformBaseUrl(platformConfig);
|
|
1189
|
-
if (userKey !== user && (opts.allowLegacyUserKey === false || !canUseLegacyUserKey(platformUrl))) return {
|
|
1190
|
-
userKey,
|
|
1191
|
-
userEntry
|
|
1192
|
-
};
|
|
1193
|
-
const legacyEntry = config.users[user];
|
|
1194
|
-
return legacyEntry ? {
|
|
1195
|
-
userKey: user,
|
|
1196
|
-
userEntry: legacyEntry
|
|
1197
|
-
} : {
|
|
1198
|
-
userKey,
|
|
1199
|
-
userEntry
|
|
1200
|
-
};
|
|
1201
|
-
}
|
|
1202
|
-
/**
|
|
1203
|
-
* Resolve the config user key that would be used for a user on the selected platform.
|
|
1204
|
-
* @param config - Platform config
|
|
1205
|
-
* @param user - User name
|
|
1206
|
-
* @param platformConfig - Optional platform connection settings
|
|
1207
|
-
* @param opts - Token lookup options
|
|
1208
|
-
* @returns Resolved config user key
|
|
1209
|
-
*/
|
|
1210
|
-
function resolveUserTokenKey(config, user, platformConfig, opts) {
|
|
1211
|
-
return findUserEntry(config, user, platformConfig, opts).userKey;
|
|
1212
|
-
}
|
|
1213
|
-
/**
|
|
1214
|
-
* Check whether tokens are registered for a user on the selected platform.
|
|
1215
|
-
* @param config - Platform config
|
|
1216
|
-
* @param user - User name
|
|
1217
|
-
* @param platformConfig - Optional platform connection settings
|
|
1218
|
-
* @param opts - Token lookup options
|
|
1219
|
-
* @returns True when the user has a registered token entry
|
|
1220
|
-
*/
|
|
1221
|
-
function hasUserTokenEntry(config, user, platformConfig, opts) {
|
|
1222
|
-
return findUserEntry(config, user, platformConfig, opts).userEntry !== void 0;
|
|
1223
|
-
}
|
|
1224
|
-
function hasUserKeyForName(users, user) {
|
|
1225
|
-
return users[user] !== void 0 || Object.keys(users).some((key) => key.endsWith(`|${user}`));
|
|
1226
|
-
}
|
|
1227
|
-
/**
|
|
1228
|
-
* Check whether any platform has tokens registered for a user.
|
|
1229
|
-
* @param config - Platform config
|
|
1230
|
-
* @param user - User name
|
|
1231
|
-
* @returns True when the user has a token entry for any platform
|
|
1232
|
-
*/
|
|
1233
|
-
function hasAnyUserTokenEntry(config, user) {
|
|
1234
|
-
return hasUserKeyForName(config.users, user);
|
|
1235
|
-
}
|
|
1236
|
-
function hasCurrentUserEntry(users, currentUser) {
|
|
1237
|
-
return hasUserKeyForName(users, currentUser);
|
|
1238
|
-
}
|
|
1239
|
-
/**
|
|
1240
|
-
* Migrate a v1 config to v2.
|
|
1241
|
-
* Tokens are kept in the config file (storage: "file") during migration.
|
|
1242
|
-
* They will be moved to the OS keyring on next login or token refresh.
|
|
1243
|
-
* @param v1Config - v1 configuration to migrate
|
|
1244
|
-
* @returns Migrated v2 configuration
|
|
1245
|
-
*/
|
|
1246
|
-
function migrateV1ToV2(v1Config) {
|
|
1247
|
-
const users = {};
|
|
1248
|
-
for (const [name, v1User] of Object.entries(v1Config.users)) {
|
|
1249
|
-
if (!v1User) continue;
|
|
1250
|
-
users[name] = {
|
|
1251
|
-
access_token: v1User.access_token,
|
|
1252
|
-
refresh_token: v1User.refresh_token,
|
|
1253
|
-
token_expires_at: v1User.token_expires_at,
|
|
1254
|
-
storage: "file"
|
|
1255
|
-
};
|
|
1256
|
-
}
|
|
1257
|
-
return {
|
|
1258
|
-
version: V2_CONFIG_VERSION,
|
|
1259
|
-
min_sdk_version: V2_MIN_SDK_VERSION,
|
|
1260
|
-
users,
|
|
1261
|
-
profiles: v1Config.profiles,
|
|
1262
|
-
current_user: v1Config.current_user
|
|
1263
|
-
};
|
|
1264
|
-
}
|
|
1265
|
-
async function warnIfNewerConfigAvailable(config) {
|
|
1266
|
-
if (!config.latest_min_sdk_version) return;
|
|
1267
|
-
if (lt((await readPackageJson()).version ?? "0.0.0", config.latest_min_sdk_version)) logger.warn(multiline`
|
|
1268
|
-
A newer config version (${String(config.latest_version)}) is available.
|
|
1269
|
-
Please update your SDK to >= ${config.latest_min_sdk_version}: pnpm update @tailor-platform/sdk
|
|
1270
|
-
`);
|
|
1271
|
-
}
|
|
1272
|
-
/**
|
|
1273
|
-
* Read Tailor Platform CLI configuration, migrating from tailorctl or v1 if necessary.
|
|
1274
|
-
* @returns Parsed platform configuration
|
|
1275
|
-
*/
|
|
1276
|
-
async function readPlatformConfig() {
|
|
1277
|
-
const configPath = platformConfigPath();
|
|
1278
|
-
if (!fs$1.existsSync(configPath)) {
|
|
1279
|
-
logger.warn(`Config not found at ${configPath}, migrating from tailorctl config...`);
|
|
1280
|
-
const tcConfig = readTailorctlConfig();
|
|
1281
|
-
const v1Config = tcConfig ? fromTailorctlConfig(tcConfig) : {
|
|
1282
|
-
version: 1,
|
|
1283
|
-
users: {},
|
|
1284
|
-
profiles: {},
|
|
1285
|
-
current_user: null
|
|
1286
|
-
};
|
|
1287
|
-
writePlatformConfig(v1Config);
|
|
1288
|
-
return migrateV1ToV2(v1Config);
|
|
1289
|
-
}
|
|
1290
|
-
const rawConfig = parseYAML(fs$1.readFileSync(configPath, "utf-8"));
|
|
1291
|
-
tightenSecretFilePermissions(configPath);
|
|
1292
|
-
const version = rawConfig != null && typeof rawConfig === "object" && "version" in rawConfig ? rawConfig.version : void 0;
|
|
1293
|
-
if (typeof version === "number" && version > LATEST_CONFIG_VERSION) {
|
|
1294
|
-
const minSdk = "min_sdk_version" in rawConfig ? String(rawConfig.min_sdk_version) : void 0;
|
|
1295
|
-
const updateHint = minSdk ? `Please update your SDK to >= ${minSdk}: pnpm update @tailor-platform/sdk` : "Please update your SDK: pnpm update @tailor-platform/sdk";
|
|
1296
|
-
throw new Error(multiline`
|
|
1297
|
-
Config file uses version ${String(version)}, but this SDK only supports up to version ${String(LATEST_CONFIG_VERSION)}.
|
|
1298
|
-
${updateHint}
|
|
1299
|
-
`);
|
|
1300
|
-
}
|
|
1301
|
-
const configResult = pfConfigSchema.safeParse(rawConfig);
|
|
1302
|
-
if (configResult.success) {
|
|
1303
|
-
await warnIfNewerConfigAvailable(configResult.data);
|
|
1304
|
-
return configResult.data;
|
|
1305
|
-
}
|
|
1306
|
-
const v1Result = pfConfigSchemaV1.safeParse(rawConfig);
|
|
1307
|
-
if (v1Result.success) return migrateV1ToV2(v1Result.data);
|
|
1308
|
-
throw new Error(multiline`
|
|
1309
|
-
Failed to parse config file at ${configPath}.
|
|
1310
|
-
The file may be corrupted or created by an incompatible SDK version.
|
|
1311
|
-
`);
|
|
1312
|
-
}
|
|
1313
|
-
function toV1ForDisk(config) {
|
|
1314
|
-
const users = {};
|
|
1315
|
-
for (const [name, entry] of Object.entries(config.users)) {
|
|
1316
|
-
if (!entry || entry.storage === "keyring") continue;
|
|
1317
|
-
users[name] = {
|
|
1318
|
-
access_token: entry.access_token,
|
|
1319
|
-
refresh_token: entry.refresh_token,
|
|
1320
|
-
token_expires_at: entry.token_expires_at
|
|
1321
|
-
};
|
|
1322
|
-
}
|
|
1323
|
-
const currentUser = config.current_user && hasCurrentUserEntry(users, config.current_user) ? config.current_user : null;
|
|
1324
|
-
return {
|
|
1325
|
-
version: 1,
|
|
1326
|
-
users,
|
|
1327
|
-
profiles: config.profiles,
|
|
1328
|
-
current_user: currentUser
|
|
1329
|
-
};
|
|
1330
|
-
}
|
|
1331
|
-
function hasProfilePlatformSettings(config) {
|
|
1332
|
-
return Object.values(config.profiles).some((profile) => profile?.platform_url !== void 0 || profile?.oauth2_client_id !== void 0 || profile?.console_url !== void 0);
|
|
1333
|
-
}
|
|
1334
|
-
function hasScopedUserKeys(config) {
|
|
1335
|
-
return Object.keys(config.users).some((userKey) => userKey.includes("|"));
|
|
1336
|
-
}
|
|
1337
|
-
function toLatestForDisk(config) {
|
|
1338
|
-
return {
|
|
1339
|
-
...config.version === 1 ? migrateV1ToV2(config) : config,
|
|
1340
|
-
version: LATEST_CONFIG_VERSION,
|
|
1341
|
-
min_sdk_version: V3_MIN_SDK_VERSION
|
|
1342
|
-
};
|
|
1343
|
-
}
|
|
1344
|
-
/**
|
|
1345
|
-
* Write Tailor Platform CLI configuration to disk.
|
|
1346
|
-
* By default, file-backed configs without newer fields are converted to V1 for
|
|
1347
|
-
* backward compatibility, so an older SDK can still read the file. Configs
|
|
1348
|
-
* containing a keyring user are kept in V2 or later because the keyring storage
|
|
1349
|
-
* variant is not representable in V1. Configs containing profile-level Platform
|
|
1350
|
-
* settings or platform-scoped user tokens are written in the latest
|
|
1351
|
-
* min-SDK-gated format because older SDKs would silently drop or misread those
|
|
1352
|
-
* settings.
|
|
1353
|
-
* Set TAILOR_USE_KEYRING to write the current in-memory format unconditionally.
|
|
1354
|
-
*
|
|
1355
|
-
* The config file may contain access/refresh tokens when the OS keyring is
|
|
1356
|
-
* unavailable, so it is written via {@link writeSecretFile} so other users
|
|
1357
|
-
* on the host cannot read it.
|
|
1358
|
-
* @param config - Platform configuration to write
|
|
1359
|
-
*/
|
|
1360
|
-
function writePlatformConfig(config) {
|
|
1361
|
-
const configPath = platformConfigPath();
|
|
1362
|
-
const hasKeyringUser = config.version !== 1 && Object.values(config.users).some((u) => u?.storage === "keyring");
|
|
1363
|
-
writeSecretFile(configPath, stringifyYAML(hasProfilePlatformSettings(config) || hasScopedUserKeys(config) ? toLatestForDisk(config) : config.version !== 1 && !process.env.TAILOR_USE_KEYRING && !hasKeyringUser ? toV1ForDisk(config) : config));
|
|
1364
|
-
}
|
|
1365
|
-
const tcContextConfigSchema = z.object({
|
|
1366
|
-
username: z.string().optional(),
|
|
1367
|
-
controlplaneaccesstoken: z.string().optional(),
|
|
1368
|
-
controlplanerefreshtoken: z.string().optional(),
|
|
1369
|
-
controlplanetokenexpiresat: z.string().optional(),
|
|
1370
|
-
workspaceid: z.string().optional()
|
|
1371
|
-
});
|
|
1372
|
-
const tcConfigSchema = z.object({ global: z.object({ context: z.string().optional() }).optional() }).catchall(tcContextConfigSchema.optional());
|
|
1373
|
-
function readTailorctlConfig() {
|
|
1374
|
-
const configPath = path.join(os.homedir(), ".tailorctl", "config");
|
|
1375
|
-
if (!fs$1.existsSync(configPath)) return;
|
|
1376
|
-
const rawConfig = parseTOML(fs$1.readFileSync(configPath, "utf-8"));
|
|
1377
|
-
return tcConfigSchema.parse(rawConfig);
|
|
1378
|
-
}
|
|
1379
|
-
function fromTailorctlConfig(config) {
|
|
1380
|
-
const users = {};
|
|
1381
|
-
const profiles = {};
|
|
1382
|
-
let currentUser = null;
|
|
1383
|
-
const currentContext = config.global?.context || "default";
|
|
1384
|
-
for (const [key, val] of Object.entries(config)) {
|
|
1385
|
-
if (key === "global") continue;
|
|
1386
|
-
const context = val;
|
|
1387
|
-
if (!context.username || !context.controlplaneaccesstoken || !context.controlplanerefreshtoken || !context.controlplanetokenexpiresat || !context.workspaceid) continue;
|
|
1388
|
-
if (key === currentContext) currentUser = context.username;
|
|
1389
|
-
profiles[key] = {
|
|
1390
|
-
user: context.username,
|
|
1391
|
-
workspace_id: context.workspaceid
|
|
1392
|
-
};
|
|
1393
|
-
const user = users[context.username];
|
|
1394
|
-
if (!user || new Date(user.token_expires_at) < new Date(context.controlplanetokenexpiresat)) users[context.username] = {
|
|
1395
|
-
access_token: context.controlplaneaccesstoken,
|
|
1396
|
-
refresh_token: context.controlplanerefreshtoken,
|
|
1397
|
-
token_expires_at: context.controlplanetokenexpiresat
|
|
1398
|
-
};
|
|
1399
|
-
}
|
|
1400
|
-
return {
|
|
1401
|
-
version: 1,
|
|
1402
|
-
users,
|
|
1403
|
-
profiles,
|
|
1404
|
-
current_user: currentUser
|
|
1405
|
-
};
|
|
1406
|
-
}
|
|
1407
|
-
function validateUUID(value, source) {
|
|
1408
|
-
const result = z.uuid().safeParse(value);
|
|
1409
|
-
if (!result.success) throw new Error(`Invalid value from ${source}: must be a valid UUID`);
|
|
1410
|
-
return result.data;
|
|
1411
|
-
}
|
|
1412
|
-
/**
|
|
1413
|
-
* Load workspace ID from command options, environment variables, or platform config.
|
|
1414
|
-
* In CLI context, env fallback is also handled by politty's arg env option.
|
|
1415
|
-
* Priority: opts/workspaceId > env/workspaceId > opts/profile > error
|
|
1416
|
-
* @param opts - Workspace and profile options
|
|
1417
|
-
* @returns Resolved workspace ID
|
|
1418
|
-
*/
|
|
1419
|
-
async function loadWorkspaceId(opts) {
|
|
1420
|
-
const profile = opts?.profile || process.env.TAILOR_PLATFORM_PROFILE;
|
|
1421
|
-
if (opts?.workspaceId) return validateUUID(opts.workspaceId, "--workspace-id option");
|
|
1422
|
-
if (process.env.TAILOR_PLATFORM_WORKSPACE_ID) return validateUUID(process.env.TAILOR_PLATFORM_WORKSPACE_ID, "TAILOR_PLATFORM_WORKSPACE_ID environment variable");
|
|
1423
|
-
if (profile) {
|
|
1424
|
-
const wsId = (await readPlatformConfig()).profiles[profile]?.workspace_id;
|
|
1425
|
-
if (!wsId) throw new Error(`Profile "${profile}" not found`);
|
|
1426
|
-
return validateUUID(wsId, `profile "${profile}"`);
|
|
1427
|
-
}
|
|
1428
|
-
throw new Error(multiline`
|
|
1429
|
-
Workspace ID not found.
|
|
1430
|
-
Please specify workspace ID via --workspace-id option or TAILOR_PLATFORM_WORKSPACE_ID environment variable.
|
|
1431
|
-
`);
|
|
1432
|
-
}
|
|
1433
|
-
/**
|
|
1434
|
-
* Load machine user name from command options, environment variables, or platform config.
|
|
1435
|
-
* In CLI context, env fallback is also handled by politty's arg env option.
|
|
1436
|
-
* Priority: opts/machineUser > env/TAILOR_PLATFORM_MACHINE_USER_NAME > opts/profile (profile default) > undefined.
|
|
1437
|
-
* An explicitly empty `opts.machineUser` is rejected with a CLIError (`MACHINE_USER_NAME_EMPTY`) rather than falling back to the env var or profile default.
|
|
1438
|
-
* When the active profile has `machine_user_override: "deny"`, an explicit value that differs from the profile's machine user throws a CLIError with code `PROFILE_MACHINE_USER_OVERRIDE_DENIED`.
|
|
1439
|
-
* @param opts - Machine user and profile options
|
|
1440
|
-
* @returns Resolved machine user name, or undefined if not set
|
|
1441
|
-
*/
|
|
1442
|
-
async function loadMachineUserName(opts) {
|
|
1443
|
-
if (opts?.machineUser === "") throw createCLIError({
|
|
1444
|
-
code: "MACHINE_USER_NAME_EMPTY",
|
|
1445
|
-
message: "Machine user name cannot be empty.",
|
|
1446
|
-
suggestion: "Pass a non-empty machine user name, or omit the option to use the environment variable or profile default."
|
|
1447
|
-
});
|
|
1448
|
-
const envMachineUser = process.env.TAILOR_PLATFORM_MACHINE_USER_NAME || void 0;
|
|
1449
|
-
const explicitMachineUser = opts?.machineUser ? {
|
|
1450
|
-
source: opts.machineUserSource ?? "option",
|
|
1451
|
-
value: opts.machineUser
|
|
1452
|
-
} : envMachineUser ? {
|
|
1453
|
-
source: "env",
|
|
1454
|
-
value: envMachineUser
|
|
1455
|
-
} : void 0;
|
|
1456
|
-
const explicit = explicitMachineUser?.value;
|
|
1457
|
-
const profile = opts?.profile || process.env.TAILOR_PLATFORM_PROFILE;
|
|
1458
|
-
if (!profile) return explicit;
|
|
1459
|
-
const entry = (await readPlatformConfig()).profiles[profile];
|
|
1460
|
-
if (!entry) {
|
|
1461
|
-
if (explicit) return explicit;
|
|
1462
|
-
throw new Error(`Profile "${profile}" not found`);
|
|
1463
|
-
}
|
|
1464
|
-
if (entry.machine_user && entry.machine_user_override === "deny") {
|
|
1465
|
-
if (explicit && explicit !== entry.machine_user) {
|
|
1466
|
-
const details = explicitMachineUser.source === "env" ? `The machine user is being set to "${explicit}" via the TAILOR_PLATFORM_MACHINE_USER_NAME environment variable, which conflicts with this profile's pinned machine user "${entry.machine_user}".` : `This profile fixes the machine user to "${entry.machine_user}" for application-data commands.`;
|
|
1467
|
-
throw createCLIError({
|
|
1468
|
-
code: "PROFILE_MACHINE_USER_OVERRIDE_DENIED",
|
|
1469
|
-
message: `Profile "${profile}" denies overriding the machine user.`,
|
|
1470
|
-
details,
|
|
1471
|
-
suggestion: `Omit the machine user option, unset TAILOR_PLATFORM_MACHINE_USER_NAME, or run 'tailor-sdk profile update ${profile} --machine-user-override allow'.`
|
|
1472
|
-
});
|
|
1473
|
-
}
|
|
1474
|
-
return entry.machine_user;
|
|
1475
|
-
}
|
|
1476
|
-
return explicit || entry.machine_user;
|
|
1477
|
-
}
|
|
1478
|
-
/**
|
|
1479
|
-
* Load access token from environment variables, command options, or platform config.
|
|
1480
|
-
* In CLI context, profile env fallback is also handled by politty's arg env option.
|
|
1481
|
-
* Priority: env/TAILOR_PLATFORM_TOKEN > env/TAILOR_TOKEN (deprecated) > opts/profile > env/profile > config/currentUser > error
|
|
1482
|
-
* @param opts - Profile options
|
|
1483
|
-
* @returns Resolved access token
|
|
1484
|
-
*/
|
|
1485
|
-
async function loadAccessToken(opts) {
|
|
1486
|
-
const profile = opts?.profile || process.env.TAILOR_PLATFORM_PROFILE;
|
|
1487
|
-
const envToken = process.env.TAILOR_PLATFORM_TOKEN ?? process.env.TAILOR_TOKEN;
|
|
1488
|
-
if (envToken && !process.env.TAILOR_PLATFORM_TOKEN) logger.warn("TAILOR_TOKEN is deprecated. Please use TAILOR_PLATFORM_TOKEN instead.");
|
|
1489
|
-
if (envToken) {
|
|
1490
|
-
rememberPlatformConfigForToken(envToken, await loadPlatformClientConfig({
|
|
1491
|
-
profile,
|
|
1492
|
-
allowMissingProfile: true
|
|
1493
|
-
}));
|
|
1494
|
-
return envToken;
|
|
1495
|
-
}
|
|
1496
|
-
const pfConfig = await readPlatformConfig();
|
|
1497
|
-
const profileEntry = profile ? pfConfig.profiles[profile] : void 0;
|
|
1498
|
-
if (profile && !profileEntry) throw new Error(`Profile "${profile}" not found`);
|
|
1499
|
-
const user = profileEntry?.user ?? pfConfig.current_user;
|
|
1500
|
-
if (!user) throw new Error(multiline`
|
|
1501
|
-
Tailor Platform token not found.
|
|
1502
|
-
Please specify token via TAILOR_PLATFORM_TOKEN environment variable or login using 'tailor-sdk login' command.
|
|
1503
|
-
`);
|
|
1504
|
-
return await fetchLatestToken(pfConfig, user, profileEntry ? platformConfigFromProfile(profileEntry) : void 0);
|
|
1505
|
-
}
|
|
1506
|
-
/**
|
|
1507
|
-
* Load platform connection settings from the active profile.
|
|
1508
|
-
* @param opts - Profile options
|
|
1509
|
-
* @returns Resolved platform connection settings, or undefined for the default environment
|
|
1510
|
-
*/
|
|
1511
|
-
async function loadPlatformClientConfig(opts) {
|
|
1512
|
-
const profile = opts?.profile || process.env.TAILOR_PLATFORM_PROFILE;
|
|
1513
|
-
if (!profile) return;
|
|
1514
|
-
let pfConfig;
|
|
1515
|
-
try {
|
|
1516
|
-
pfConfig = await readPlatformConfig();
|
|
1517
|
-
} catch (error) {
|
|
1518
|
-
if (opts?.allowMissingProfile) return;
|
|
1519
|
-
throw error;
|
|
1520
|
-
}
|
|
1521
|
-
const profileEntry = pfConfig.profiles[profile];
|
|
1522
|
-
if (!profileEntry) {
|
|
1523
|
-
if (opts?.allowMissingProfile) return;
|
|
1524
|
-
throw new Error(`Profile "${profile}" not found`);
|
|
1525
|
-
}
|
|
1526
|
-
return platformConfigFromProfile(profileEntry);
|
|
1527
|
-
}
|
|
1528
|
-
/**
|
|
1529
|
-
* Load the Tailor Platform Console base URL from environment variables or the active profile.
|
|
1530
|
-
* @param opts - Profile options
|
|
1531
|
-
* @returns Resolved Console base URL
|
|
1532
|
-
*/
|
|
1533
|
-
async function loadConsoleBaseUrl(opts) {
|
|
1534
|
-
return getConsoleBaseUrl(await loadPlatformClientConfig(opts));
|
|
1535
|
-
}
|
|
1536
|
-
/**
|
|
1537
|
-
* Resolve the actual token values for a user, reading from keyring or config as appropriate.
|
|
1538
|
-
* @param userEntry - User entry from the config
|
|
1539
|
-
* @param user - User identifier
|
|
1540
|
-
* @param label - User-facing identifier used in error messages
|
|
1541
|
-
* @returns Access token and optional refresh token
|
|
1542
|
-
*/
|
|
1543
|
-
async function resolveTokens(userEntry, user, label = user) {
|
|
1544
|
-
if (userEntry.storage === "keyring") {
|
|
1545
|
-
const tokens = await loadKeyringTokens(user);
|
|
1546
|
-
if (!tokens) throw new Error(multiline`
|
|
1547
|
-
Credentials not found in OS keyring for "${label}".
|
|
1548
|
-
Please run 'tailor-sdk login' and try again.
|
|
1549
|
-
`);
|
|
1550
|
-
return tokens;
|
|
1551
|
-
}
|
|
1552
|
-
return {
|
|
1553
|
-
accessToken: userEntry.access_token,
|
|
1554
|
-
refreshToken: userEntry.refresh_token
|
|
1555
|
-
};
|
|
1556
|
-
}
|
|
1557
|
-
/**
|
|
1558
|
-
* Save tokens for a user, writing to keyring or config as appropriate.
|
|
1559
|
-
* @param config - Platform config
|
|
1560
|
-
* @param user - User identifier
|
|
1561
|
-
* @param tokens - Token data to save
|
|
1562
|
-
* @param tokens.accessToken - Access token to persist
|
|
1563
|
-
* @param tokens.refreshToken - Refresh token to persist when available
|
|
1564
|
-
* @param expiresAt - Token expiration date
|
|
1565
|
-
* @param platformConfig - Optional platform connection settings
|
|
1566
|
-
*/
|
|
1567
|
-
async function saveUserTokens(config, user, tokens, expiresAt, platformConfig) {
|
|
1568
|
-
const userKey = platformUserKey(user, platformConfig);
|
|
1569
|
-
if (process.env.TAILOR_USE_KEYRING && await isKeyringAvailable()) {
|
|
1570
|
-
await saveKeyringTokens(userKey, tokens);
|
|
1571
|
-
config.users[userKey] = {
|
|
1572
|
-
token_expires_at: expiresAt,
|
|
1573
|
-
storage: "keyring"
|
|
1574
|
-
};
|
|
1575
|
-
} else config.users[userKey] = {
|
|
1576
|
-
access_token: tokens.accessToken,
|
|
1577
|
-
refresh_token: tokens.refreshToken,
|
|
1578
|
-
token_expires_at: expiresAt,
|
|
1579
|
-
storage: "file"
|
|
1580
|
-
};
|
|
1581
|
-
}
|
|
1582
|
-
/**
|
|
1583
|
-
* Delete tokens for a user from keyring if applicable.
|
|
1584
|
-
* @param config - Platform config
|
|
1585
|
-
* @param user - User identifier
|
|
1586
|
-
* @param platformConfig - Optional platform connection settings
|
|
1587
|
-
* @param opts - Token lookup options
|
|
1588
|
-
*/
|
|
1589
|
-
async function deleteUserTokens(config, user, platformConfig, opts) {
|
|
1590
|
-
const { userKey, userEntry } = findUserEntry(config, user, platformConfig, opts);
|
|
1591
|
-
if (userEntry?.storage === "keyring") await deleteKeyringTokens(userKey);
|
|
1592
|
-
delete config.users[userKey];
|
|
1593
|
-
}
|
|
1594
|
-
/**
|
|
1595
|
-
* Resolve stored tokens for a user on the selected platform.
|
|
1596
|
-
* @param config - Platform config
|
|
1597
|
-
* @param user - User name
|
|
1598
|
-
* @param platformConfig - Optional platform connection settings
|
|
1599
|
-
* @param opts - Token lookup options
|
|
1600
|
-
* @returns Stored user entry and token values, or undefined when the user is not logged in
|
|
1601
|
-
*/
|
|
1602
|
-
async function loadStoredUserTokens(config, user, platformConfig, opts) {
|
|
1603
|
-
const { userKey, userEntry } = findUserEntry(config, user, platformConfig, opts);
|
|
1604
|
-
if (!userEntry) return void 0;
|
|
1605
|
-
return {
|
|
1606
|
-
userEntry,
|
|
1607
|
-
...await resolveTokens(userEntry, userKey, user)
|
|
1608
|
-
};
|
|
1609
|
-
}
|
|
1610
|
-
/**
|
|
1611
|
-
* Fetch the latest access token, refreshing if necessary.
|
|
1612
|
-
* @param config - Platform config
|
|
1613
|
-
* @param user - User name
|
|
1614
|
-
* @param platformConfig - Optional platform connection settings
|
|
1615
|
-
* @returns Latest access token
|
|
1616
|
-
*/
|
|
1617
|
-
async function fetchLatestToken(config, user, platformConfig) {
|
|
1618
|
-
const { userKey, userEntry } = findUserEntry(config, user, platformConfig);
|
|
1619
|
-
if (!userEntry) throw new Error(multiline`
|
|
1620
|
-
User "${user}" not found.
|
|
1621
|
-
Please verify your user name and login using 'tailor-sdk login' command.
|
|
1622
|
-
`);
|
|
1623
|
-
const tokens = await resolveTokens(userEntry, userKey, user);
|
|
1624
|
-
if (new Date(userEntry.token_expires_at) > /* @__PURE__ */ new Date()) {
|
|
1625
|
-
rememberPlatformConfigForToken(tokens.accessToken, platformConfig);
|
|
1626
|
-
return tokens.accessToken;
|
|
1627
|
-
}
|
|
1628
|
-
if (!tokens.refreshToken) throw new Error(multiline`
|
|
1629
|
-
Token expired.
|
|
1630
|
-
Please run 'tailor-sdk login' and try again.
|
|
1631
|
-
`);
|
|
1632
|
-
const client = initOAuth2Client(platformConfig);
|
|
1633
|
-
let resp;
|
|
1634
|
-
try {
|
|
1635
|
-
resp = await client.refreshToken({
|
|
1636
|
-
accessToken: tokens.accessToken,
|
|
1637
|
-
refreshToken: tokens.refreshToken,
|
|
1638
|
-
expiresAt: Date.parse(userEntry.token_expires_at)
|
|
1639
|
-
});
|
|
1640
|
-
} catch {
|
|
1641
|
-
throw new Error(multiline`
|
|
1642
|
-
Failed to refresh token. Your session may have expired.
|
|
1643
|
-
Please run 'tailor-sdk login' and try again.
|
|
1644
|
-
`);
|
|
1645
|
-
}
|
|
1646
|
-
const newExpiresAt = new Date(assertDefined(resp.expiresAt, "token refresh response missing expiresAt")).toISOString();
|
|
1647
|
-
await saveUserTokens(config, user, {
|
|
1648
|
-
accessToken: resp.accessToken,
|
|
1649
|
-
refreshToken: resp.refreshToken ?? void 0
|
|
1650
|
-
}, newExpiresAt, platformConfig);
|
|
1651
|
-
if (userKey !== platformUserKey(user, platformConfig)) {
|
|
1652
|
-
if (userEntry.storage === "keyring") await deleteKeyringTokens(userKey);
|
|
1653
|
-
delete config.users[userKey];
|
|
1654
|
-
}
|
|
1655
|
-
writePlatformConfig(config);
|
|
1656
|
-
rememberPlatformConfigForToken(resp.accessToken, platformConfig);
|
|
1657
|
-
return resp.accessToken;
|
|
1658
|
-
}
|
|
1659
|
-
const DEFAULT_CONFIG_FILENAME = "tailor.config.ts";
|
|
1660
|
-
/**
|
|
1661
|
-
* Load config path from command options, environment variables, or search parent directories.
|
|
1662
|
-
* In CLI context, env fallback is also handled by politty's arg env option.
|
|
1663
|
-
* Priority: opts/config > env/config > search parent directories
|
|
1664
|
-
* @param configPath - Optional explicit config path
|
|
1665
|
-
* @returns Resolved config path or undefined
|
|
1666
|
-
*/
|
|
1667
|
-
function loadConfigPath(configPath) {
|
|
1668
|
-
if (configPath) return configPath;
|
|
1669
|
-
if (process.env.TAILOR_PLATFORM_SDK_CONFIG_PATH) return process.env.TAILOR_PLATFORM_SDK_CONFIG_PATH;
|
|
1670
|
-
return findUpSync(DEFAULT_CONFIG_FILENAME);
|
|
1671
|
-
}
|
|
1672
|
-
|
|
1673
|
-
//#endregion
|
|
1674
|
-
//#region src/cli/shared/mock.ts
|
|
1675
|
-
/**
|
|
1676
|
-
* Install a stub `globalThis.tailordb` so that user code loaded by the CLI
|
|
1677
|
-
* (e.g. via `createGetDB` in `@tailor-platform/sdk/kysely`) can reference
|
|
1678
|
-
* `tailordb.Client` without hitting a `ReferenceError`. The CLI never
|
|
1679
|
-
* actually executes the user code paths that issue queries, so a no-op
|
|
1680
|
-
* client suffices.
|
|
1681
|
-
*
|
|
1682
|
-
* Exposed as a function (rather than a top-level statement) so that
|
|
1683
|
-
* `package.json#sideEffects` can keep the file marked side-effect-free
|
|
1684
|
-
* without bundlers eliminating the install step.
|
|
1685
|
-
*/
|
|
1686
|
-
function installCliTailordbStub() {
|
|
1687
|
-
globalThis.tailordb = { Client: class {
|
|
1688
|
-
constructor(_config) {}
|
|
1689
|
-
async connect() {}
|
|
1690
|
-
async end() {}
|
|
1691
|
-
async queryObject() {
|
|
1692
|
-
return {};
|
|
1693
|
-
}
|
|
1694
|
-
} };
|
|
1695
|
-
}
|
|
1696
|
-
|
|
1697
|
-
//#endregion
|
|
1698
|
-
//#region src/cli/shared/config-loader.ts
|
|
1699
|
-
const GeneratorConfigSchema = CodeGeneratorSchema.brand("CodeGenerator");
|
|
1700
|
-
/**
|
|
1701
|
-
* Load Tailor configuration file and associated generators and plugins.
|
|
1702
|
-
* @param configPath - Optional explicit config path
|
|
1703
|
-
* @param options - Optional module import behavior.
|
|
1704
|
-
* @returns Loaded config, generators, plugins, and config path
|
|
1705
|
-
*/
|
|
1706
|
-
async function loadConfig(configPath, options = {}) {
|
|
1707
|
-
installCliTailordbStub();
|
|
1708
|
-
const foundPath = loadConfigPath(configPath);
|
|
1709
|
-
if (!foundPath) throw new Error("Configuration file not found: tailor.config.ts not found in current or parent directories");
|
|
1710
|
-
const resolvedPath = path.resolve(process.cwd(), foundPath);
|
|
1711
|
-
if (!fs$1.existsSync(resolvedPath)) throw new Error(`Configuration file not found: ${configPath}`);
|
|
1712
|
-
const configUrl = pathToFileURL(resolvedPath);
|
|
1713
|
-
if (options.importNonce) configUrl.searchParams.set("tailorImportNonce", options.importNonce);
|
|
1714
|
-
const configModule = await import(configUrl.href);
|
|
1715
|
-
if (!configModule || !configModule.default) throw new Error("Invalid Tailor config module: default export not found");
|
|
1716
|
-
const validated = AppConfigSchema.safeParse(configModule.default);
|
|
1717
|
-
if (!validated.success) {
|
|
1718
|
-
const issues = validated.error.issues.map((i) => ` - ${i.path.join(".") || "(root)"}: ${i.message}`).join("\n");
|
|
1719
|
-
throw new Error(`Invalid Tailor config in ${resolvedPath}:\n${issues}`);
|
|
1720
|
-
}
|
|
1721
|
-
const allGenerators = [];
|
|
1722
|
-
const allPlugins = [];
|
|
1723
|
-
for (const value of Object.values(configModule)) if (Array.isArray(value)) {
|
|
1724
|
-
const generatorParsed = value.reduce((acc, item) => {
|
|
1725
|
-
if (!acc.success) return acc;
|
|
1726
|
-
const baseResult = BaseGeneratorConfigSchema.safeParse(item);
|
|
1727
|
-
if (baseResult.success && Array.isArray(baseResult.data)) {
|
|
1728
|
-
const [id, options] = baseResult.data;
|
|
1729
|
-
const pluginFactory = builtinPlugins.get(id);
|
|
1730
|
-
if (pluginFactory) {
|
|
1731
|
-
acc.convertedPlugins.push(pluginFactory(options));
|
|
1732
|
-
return acc;
|
|
1733
|
-
}
|
|
1734
|
-
}
|
|
1735
|
-
const result = GeneratorConfigSchema.safeParse(item);
|
|
1736
|
-
if (result.success) acc.items.push(result.data);
|
|
1737
|
-
else acc.success = false;
|
|
1738
|
-
return acc;
|
|
1739
|
-
}, {
|
|
1740
|
-
success: true,
|
|
1741
|
-
items: [],
|
|
1742
|
-
convertedPlugins: []
|
|
1743
|
-
});
|
|
1744
|
-
if (generatorParsed.success && (generatorParsed.items.length > 0 || generatorParsed.convertedPlugins.length > 0)) {
|
|
1745
|
-
allGenerators.push(...generatorParsed.items);
|
|
1746
|
-
allPlugins.push(...generatorParsed.convertedPlugins);
|
|
1747
|
-
continue;
|
|
1748
|
-
}
|
|
1749
|
-
const pluginParsed = value.reduce((acc, item) => {
|
|
1750
|
-
if (!acc.success) return acc;
|
|
1751
|
-
const result = PluginConfigSchema.safeParse(item);
|
|
1752
|
-
if (result.success) acc.items.push(result.data);
|
|
1753
|
-
else acc.success = false;
|
|
1754
|
-
return acc;
|
|
1755
|
-
}, {
|
|
1756
|
-
success: true,
|
|
1757
|
-
items: []
|
|
1758
|
-
});
|
|
1759
|
-
if (pluginParsed.success && pluginParsed.items.length > 0) allPlugins.push(...pluginParsed.items);
|
|
1760
|
-
}
|
|
1761
|
-
return {
|
|
1762
|
-
config: {
|
|
1763
|
-
...configModule.default,
|
|
1764
|
-
path: resolvedPath
|
|
1765
|
-
},
|
|
1766
|
-
generators: allGenerators,
|
|
1767
|
-
plugins: allPlugins
|
|
1768
|
-
};
|
|
1769
|
-
}
|
|
1770
|
-
|
|
1771
669
|
//#endregion
|
|
1772
670
|
//#region src/cli/cache/hasher.ts
|
|
1773
671
|
/**
|
|
@@ -2508,100 +1406,20 @@ async function removeStaleEntryFiles(outputDir) {
|
|
|
2508
1406
|
await Promise.all(files.filter((file) => file.endsWith(".entry.js")).map((file) => fs.rm(path.join(outputDir, file), { force: true })));
|
|
2509
1407
|
}
|
|
2510
1408
|
|
|
2511
|
-
//#endregion
|
|
2512
|
-
//#region src/cli/shared/bundle-log-level.ts
|
|
2513
|
-
const INFO_LEVEL_CONSOLE_METHODS = [
|
|
2514
|
-
"console.info",
|
|
2515
|
-
"console.table",
|
|
2516
|
-
"console.dir",
|
|
2517
|
-
"console.dirxml",
|
|
2518
|
-
"console.count",
|
|
2519
|
-
"console.countReset",
|
|
2520
|
-
"console.time",
|
|
2521
|
-
"console.timeLog",
|
|
2522
|
-
"console.timeEnd",
|
|
2523
|
-
"console.group",
|
|
2524
|
-
"console.groupCollapsed",
|
|
2525
|
-
"console.groupEnd",
|
|
2526
|
-
"console.clear"
|
|
2527
|
-
];
|
|
2528
|
-
const DEBUG_LEVEL_CONSOLE_METHODS = [
|
|
2529
|
-
"console.debug",
|
|
2530
|
-
"console.log",
|
|
2531
|
-
"console.trace"
|
|
2532
|
-
];
|
|
2533
|
-
const WARN_LEVEL_CONSOLE_METHODS = ["console.warn"];
|
|
2534
|
-
const ERROR_LEVEL_CONSOLE_METHODS = ["console.error"];
|
|
2535
|
-
const MANUAL_PURE_FUNCTIONS_BY_LOG_LEVEL = {
|
|
2536
|
-
DEBUG: [],
|
|
2537
|
-
INFO: DEBUG_LEVEL_CONSOLE_METHODS,
|
|
2538
|
-
WARN: [...DEBUG_LEVEL_CONSOLE_METHODS, ...INFO_LEVEL_CONSOLE_METHODS],
|
|
2539
|
-
ERROR: [
|
|
2540
|
-
...DEBUG_LEVEL_CONSOLE_METHODS,
|
|
2541
|
-
...INFO_LEVEL_CONSOLE_METHODS,
|
|
2542
|
-
...WARN_LEVEL_CONSOLE_METHODS
|
|
2543
|
-
],
|
|
2544
|
-
SILENT: [
|
|
2545
|
-
...DEBUG_LEVEL_CONSOLE_METHODS,
|
|
2546
|
-
...INFO_LEVEL_CONSOLE_METHODS,
|
|
2547
|
-
...WARN_LEVEL_CONSOLE_METHODS,
|
|
2548
|
-
...ERROR_LEVEL_CONSOLE_METHODS
|
|
2549
|
-
]
|
|
2550
|
-
};
|
|
2551
|
-
function normalizeBundleLogLevel(value) {
|
|
2552
|
-
const normalized = value.trim().toUpperCase();
|
|
2553
|
-
return isLogLevel(normalized) ? normalized : void 0;
|
|
2554
|
-
}
|
|
2555
|
-
function resolveBundleLogLevel(configValue) {
|
|
2556
|
-
if (configValue === void 0) return "DEBUG";
|
|
2557
|
-
const resolved = normalizeBundleLogLevel(configValue);
|
|
2558
|
-
if (resolved) return resolved;
|
|
2559
|
-
throw new Error(`Invalid logLevel "${configValue}". Expected one of: ${LOG_LEVELS.join(", ")}`);
|
|
2560
|
-
}
|
|
2561
|
-
function manualPureFunctionsForLogLevel(logLevel) {
|
|
2562
|
-
return MANUAL_PURE_FUNCTIONS_BY_LOG_LEVEL[logLevel];
|
|
2563
|
-
}
|
|
2564
|
-
function createLogLevelTreeshakeOptions(logLevel) {
|
|
2565
|
-
const manualPureFunctions = manualPureFunctionsForLogLevel(logLevel);
|
|
2566
|
-
return manualPureFunctions.length > 0 ? { manualPureFunctions } : {};
|
|
2567
|
-
}
|
|
2568
|
-
|
|
2569
|
-
//#endregion
|
|
2570
|
-
//#region src/cli/shared/function-treeshake.ts
|
|
2571
|
-
const BASE_FUNCTION_TREESHAKE_OPTIONS = {
|
|
2572
|
-
moduleSideEffects: false,
|
|
2573
|
-
annotations: true,
|
|
2574
|
-
unknownGlobalSideEffects: false
|
|
2575
|
-
};
|
|
2576
|
-
function mergeFunctionTreeshakeOptions(fragments) {
|
|
2577
|
-
const merged = {};
|
|
2578
|
-
const manualPureFunctions = /* @__PURE__ */ new Set();
|
|
2579
|
-
for (const fragment of fragments) {
|
|
2580
|
-
Object.assign(merged, fragment);
|
|
2581
|
-
for (const name of fragment.manualPureFunctions ?? []) manualPureFunctions.add(name);
|
|
2582
|
-
}
|
|
2583
|
-
if (manualPureFunctions.size > 0) merged.manualPureFunctions = [...manualPureFunctions];
|
|
2584
|
-
else delete merged.manualPureFunctions;
|
|
2585
|
-
return merged;
|
|
2586
|
-
}
|
|
2587
|
-
function composeFunctionTreeshakeOptions(fragments = []) {
|
|
2588
|
-
return mergeFunctionTreeshakeOptions([BASE_FUNCTION_TREESHAKE_OPTIONS, ...fragments]);
|
|
2589
|
-
}
|
|
2590
|
-
|
|
2591
|
-
//#endregion
|
|
2592
|
-
//#region src/cli/shared/platform-bundle-plugin.ts
|
|
2593
|
-
const GATE = /(?<![\w$.])process\.env\.TAILOR_PLATFORM_BUNDLE\b/g;
|
|
2594
|
-
const platformBundleDefinePlugin = {
|
|
2595
|
-
name: "tailor-platform-bundle-define",
|
|
2596
|
-
transform(code) {
|
|
2597
|
-
if (!code.includes("process.env.TAILOR_PLATFORM_BUNDLE")) return null;
|
|
2598
|
-
return { code: code.replace(GATE, "true") };
|
|
2599
|
-
}
|
|
2600
|
-
};
|
|
2601
|
-
|
|
2602
1409
|
//#endregion
|
|
2603
1410
|
//#region src/cli/services/workflow/ast-utils.ts
|
|
2604
1411
|
/**
|
|
1412
|
+
* Read an import or export name from an OXC identifier or string-literal node.
|
|
1413
|
+
* @param node - Import/export name node
|
|
1414
|
+
* @returns Module binding name, or undefined for an unsupported node
|
|
1415
|
+
*/
|
|
1416
|
+
function getModuleExportName(node) {
|
|
1417
|
+
if (!node || typeof node !== "object") return void 0;
|
|
1418
|
+
const exportName = node;
|
|
1419
|
+
if (exportName.name) return exportName.name;
|
|
1420
|
+
return typeof exportName.value === "string" ? exportName.value : void 0;
|
|
1421
|
+
}
|
|
1422
|
+
/**
|
|
2605
1423
|
* Check if a module source is from the Tailor SDK package (including subpaths)
|
|
2606
1424
|
* @param source - Module source string
|
|
2607
1425
|
* @returns True if the source is from the Tailor SDK package
|
|
@@ -2644,7 +1462,7 @@ function getTriggerCallInfo(node, sourceText) {
|
|
|
2644
1462
|
const callee = callExpr.callee;
|
|
2645
1463
|
if (callee.type !== "MemberExpression") return null;
|
|
2646
1464
|
const memberExpr = callee;
|
|
2647
|
-
if (memberExpr.computed || memberExpr.
|
|
1465
|
+
if (memberExpr.computed || memberExpr.property.name !== "trigger" || memberExpr.object.type !== "Identifier") return null;
|
|
2648
1466
|
return {
|
|
2649
1467
|
identifierName: memberExpr.object.name,
|
|
2650
1468
|
callRange: {
|
|
@@ -2731,20 +1549,6 @@ function findStatementEnd(source, position) {
|
|
|
2731
1549
|
if (i < source.length && source[i] === "\n") i++;
|
|
2732
1550
|
return i;
|
|
2733
1551
|
}
|
|
2734
|
-
/**
|
|
2735
|
-
* Resolve a relative path from a base directory
|
|
2736
|
-
* Simple implementation that handles ./ and ../ prefixes
|
|
2737
|
-
* @param baseDir - Base directory
|
|
2738
|
-
* @param relativePath - Relative path to resolve
|
|
2739
|
-
* @returns Resolved absolute path
|
|
2740
|
-
*/
|
|
2741
|
-
function resolvePath(baseDir, relativePath) {
|
|
2742
|
-
const parts = relativePath.replace(/\\/g, "/").split("/");
|
|
2743
|
-
const baseParts = baseDir.replace(/\\/g, "/").split("/");
|
|
2744
|
-
for (const part of parts) if (part === ".") {} else if (part === "..") baseParts.pop();
|
|
2745
|
-
else baseParts.push(part);
|
|
2746
|
-
return baseParts.join("/");
|
|
2747
|
-
}
|
|
2748
1552
|
|
|
2749
1553
|
//#endregion
|
|
2750
1554
|
//#region src/cli/services/workflow/sdk-binding-collector.ts
|
|
@@ -2888,43 +1692,6 @@ function findAllJobs(program, _sourceText) {
|
|
|
2888
1692
|
walk(program);
|
|
2889
1693
|
return jobs;
|
|
2890
1694
|
}
|
|
2891
|
-
/**
|
|
2892
|
-
* Build a map from export name to job name from detected jobs
|
|
2893
|
-
* @param jobs - Detected job locations
|
|
2894
|
-
* @returns Map from export name to job name
|
|
2895
|
-
*/
|
|
2896
|
-
function buildJobNameMap(jobs) {
|
|
2897
|
-
const map = /* @__PURE__ */ new Map();
|
|
2898
|
-
for (const job of jobs) if (job.exportName) map.set(job.exportName, job.name);
|
|
2899
|
-
return map;
|
|
2900
|
-
}
|
|
2901
|
-
/**
|
|
2902
|
-
* Detect all .trigger() calls in the source code
|
|
2903
|
-
* Returns information about each trigger call for transformation
|
|
2904
|
-
* @param program - Parsed TypeScript program
|
|
2905
|
-
* @param sourceText - Source code text
|
|
2906
|
-
* @returns Detected trigger calls
|
|
2907
|
-
*/
|
|
2908
|
-
function detectTriggerCalls(program, sourceText) {
|
|
2909
|
-
const calls = [];
|
|
2910
|
-
function walk(node) {
|
|
2911
|
-
if (!node || typeof node !== "object") return;
|
|
2912
|
-
const triggerCall = getTriggerCallInfo(node, sourceText);
|
|
2913
|
-
if (triggerCall) calls.push({
|
|
2914
|
-
identifierName: triggerCall.identifierName,
|
|
2915
|
-
callRange: triggerCall.callRange,
|
|
2916
|
-
argsText: triggerCall.argsText,
|
|
2917
|
-
optionsText: triggerCall.optionsText
|
|
2918
|
-
});
|
|
2919
|
-
for (const key of Object.keys(node)) {
|
|
2920
|
-
const child = node[key];
|
|
2921
|
-
if (Array.isArray(child)) child.forEach((c) => walk(c));
|
|
2922
|
-
else if (child && typeof child === "object") walk(child);
|
|
2923
|
-
}
|
|
2924
|
-
}
|
|
2925
|
-
walk(program);
|
|
2926
|
-
return calls;
|
|
2927
|
-
}
|
|
2928
1695
|
|
|
2929
1696
|
//#endregion
|
|
2930
1697
|
//#region src/cli/services/workflow/workflow-detector.ts
|
|
@@ -2976,400 +1743,396 @@ function findAllWorkflows(program, _sourceText) {
|
|
|
2976
1743
|
walk(program);
|
|
2977
1744
|
return workflows;
|
|
2978
1745
|
}
|
|
1746
|
+
|
|
1747
|
+
//#endregion
|
|
1748
|
+
//#region src/cli/shared/trigger-context.ts
|
|
2979
1749
|
/**
|
|
2980
|
-
*
|
|
2981
|
-
* @param
|
|
2982
|
-
* @returns
|
|
2983
|
-
*/
|
|
2984
|
-
function buildWorkflowNameMap(workflows) {
|
|
2985
|
-
const map = /* @__PURE__ */ new Map();
|
|
2986
|
-
for (const workflow of workflows) if (workflow.exportName) map.set(workflow.exportName, workflow.name);
|
|
2987
|
-
return map;
|
|
2988
|
-
}
|
|
2989
|
-
/**
|
|
2990
|
-
* Detect default imports in a source file and return a map from local name to import source
|
|
2991
|
-
* @param program - Parsed TypeScript program
|
|
2992
|
-
* @returns Map from local name to import source
|
|
1750
|
+
* Normalize a source module path for trigger binding lookup.
|
|
1751
|
+
* @param filePath - Source file path or extensionless relative import path
|
|
1752
|
+
* @returns Absolute path without a JavaScript or TypeScript extension
|
|
2993
1753
|
*/
|
|
2994
|
-
function
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
1754
|
+
function normalizeFilePath(filePath) {
|
|
1755
|
+
return path.resolve(filePath.replace(/[?#].*$/, "")).replace(/\.(ts|mts|cts|js|mjs|cjs)$/, "");
|
|
1756
|
+
}
|
|
1757
|
+
function createModuleBindings(program, source) {
|
|
1758
|
+
const localBindings = /* @__PURE__ */ new Map();
|
|
1759
|
+
const exports = /* @__PURE__ */ new Map();
|
|
1760
|
+
for (const workflow of findAllWorkflows(program, source)) {
|
|
1761
|
+
const target = {
|
|
1762
|
+
kind: "workflow",
|
|
1763
|
+
name: workflow.name
|
|
1764
|
+
};
|
|
1765
|
+
if (workflow.exportName) localBindings.set(workflow.exportName, target);
|
|
1766
|
+
if (workflow.isDefaultExport) exports.set("default", target);
|
|
1767
|
+
}
|
|
1768
|
+
for (const job of findAllJobs(program, source)) if (job.exportName) localBindings.set(job.exportName, {
|
|
1769
|
+
kind: "job",
|
|
1770
|
+
name: job.name
|
|
1771
|
+
});
|
|
1772
|
+
for (const statement of program.body) {
|
|
1773
|
+
if (statement.type === "ExportDefaultDeclaration") {
|
|
1774
|
+
const declaration = statement.declaration;
|
|
1775
|
+
if (declaration?.type === "Identifier") {
|
|
1776
|
+
const target = localBindings.get(declaration.name);
|
|
1777
|
+
if (target) exports.set("default", target);
|
|
3006
1778
|
}
|
|
1779
|
+
continue;
|
|
3007
1780
|
}
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
1781
|
+
if (statement.type !== "ExportNamedDeclaration") continue;
|
|
1782
|
+
const declaration = statement.declaration;
|
|
1783
|
+
if (declaration?.type === "VariableDeclaration") for (const declarator of declaration.declarations) {
|
|
1784
|
+
const id = declarator.id;
|
|
1785
|
+
if (id?.type !== "Identifier") continue;
|
|
1786
|
+
const localName = id.name;
|
|
1787
|
+
const target = localBindings.get(localName);
|
|
1788
|
+
if (target) exports.set(localName, target);
|
|
1789
|
+
}
|
|
1790
|
+
if (statement.source) continue;
|
|
1791
|
+
for (const specifier of statement.specifiers ?? []) {
|
|
1792
|
+
const localName = getModuleExportName(specifier.local);
|
|
1793
|
+
const exportedName = getModuleExportName(specifier.exported);
|
|
1794
|
+
if (!localName || !exportedName) continue;
|
|
1795
|
+
const target = localBindings.get(localName);
|
|
1796
|
+
if (target) exports.set(exportedName, target);
|
|
3012
1797
|
}
|
|
3013
1798
|
}
|
|
3014
|
-
|
|
3015
|
-
|
|
1799
|
+
return {
|
|
1800
|
+
localBindings,
|
|
1801
|
+
exports
|
|
1802
|
+
};
|
|
1803
|
+
}
|
|
1804
|
+
/**
|
|
1805
|
+
* Build trigger context from configured workflow source files.
|
|
1806
|
+
* @param workflowConfig - Workflow file loading configuration
|
|
1807
|
+
* @param authNamespace - Auth service namespace used by workflow trigger options
|
|
1808
|
+
* @returns Module-local workflow and job binding metadata
|
|
1809
|
+
*/
|
|
1810
|
+
async function buildTriggerContext(workflowConfig, authNamespace) {
|
|
1811
|
+
const modules = /* @__PURE__ */ new Map();
|
|
1812
|
+
if (!workflowConfig) return {
|
|
1813
|
+
modules,
|
|
1814
|
+
authNamespace
|
|
1815
|
+
};
|
|
1816
|
+
for (const file of loadFilesWithIgnores(workflowConfig)) try {
|
|
1817
|
+
const source = await fs$1.promises.readFile(file, "utf-8");
|
|
1818
|
+
const { program } = parseSync("input.ts", source);
|
|
1819
|
+
modules.set(normalizeFilePath(file), createModuleBindings(program, source));
|
|
1820
|
+
} catch (error) {
|
|
1821
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1822
|
+
logger.warn(`Failed to process workflow file ${file}: ${errorMessage}`, { mode: "stream" });
|
|
1823
|
+
}
|
|
1824
|
+
return {
|
|
1825
|
+
modules,
|
|
1826
|
+
authNamespace
|
|
1827
|
+
};
|
|
1828
|
+
}
|
|
1829
|
+
function sortedTargets(bindings) {
|
|
1830
|
+
return [...bindings].toSorted(([a], [b]) => a.localeCompare(b)).map(([binding, target]) => [
|
|
1831
|
+
binding,
|
|
1832
|
+
target.kind,
|
|
1833
|
+
target.name
|
|
1834
|
+
]);
|
|
1835
|
+
}
|
|
1836
|
+
/**
|
|
1837
|
+
* Serialize trigger context to a deterministic cache input.
|
|
1838
|
+
* @param context - Trigger context to serialize
|
|
1839
|
+
* @returns Deterministic string, or an empty string when context is absent
|
|
1840
|
+
*/
|
|
1841
|
+
function serializeTriggerContext(context) {
|
|
1842
|
+
if (!context) return "";
|
|
1843
|
+
const modules = [...context.modules].toSorted(([a], [b]) => a.localeCompare(b)).map(([file, bindings]) => [
|
|
1844
|
+
file,
|
|
1845
|
+
sortedTargets(bindings.localBindings),
|
|
1846
|
+
sortedTargets(bindings.exports)
|
|
1847
|
+
]);
|
|
1848
|
+
return JSON.stringify(modules) + (context.authNamespace ?? "");
|
|
3016
1849
|
}
|
|
3017
1850
|
|
|
3018
1851
|
//#endregion
|
|
3019
1852
|
//#region src/cli/services/workflow/trigger-transformer.ts
|
|
3020
|
-
/**
|
|
3021
|
-
* Name of the injected runtime normalizer helper. Chosen to be unique enough
|
|
3022
|
-
* to avoid collisions with user code.
|
|
3023
|
-
*/
|
|
3024
1853
|
const NORMALIZER_IDENTIFIER = "__tailor_normalizeTriggerOptions";
|
|
3025
|
-
/**
|
|
3026
|
-
* Build the source text of the injected normalizer helper.
|
|
3027
|
-
*
|
|
3028
|
-
* Expands a plain-string `authInvoker` (machine user name) in the trigger
|
|
3029
|
-
* options to the object form `{ namespace, machineUserName }`; any other
|
|
3030
|
-
* options value passes through unchanged. The auth namespace is baked in at
|
|
3031
|
-
* bundle time.
|
|
3032
|
-
* @param authNamespace - Auth service namespace to embed
|
|
3033
|
-
* @returns Source line defining the helper
|
|
3034
|
-
*/
|
|
3035
1854
|
function buildNormalizerHelperSource(authNamespace) {
|
|
3036
1855
|
return `const ${NORMALIZER_IDENTIFIER} = (o) => o && typeof o.authInvoker === "string" ? { ...o, authInvoker: { namespace: ${JSON.stringify(authNamespace)}, machineUserName: o.authInvoker } } : o;\n`;
|
|
3037
1856
|
}
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
1857
|
+
function collectBindingNames(node, names) {
|
|
1858
|
+
if (!node || typeof node !== "object") return;
|
|
1859
|
+
switch (node.type) {
|
|
1860
|
+
case "Identifier":
|
|
1861
|
+
names.add(node.name);
|
|
1862
|
+
return;
|
|
1863
|
+
case "ObjectPattern":
|
|
1864
|
+
for (const property of node.properties) collectBindingNames(property.type === "RestElement" ? property.argument : property.value, names);
|
|
1865
|
+
return;
|
|
1866
|
+
case "ArrayPattern":
|
|
1867
|
+
for (const element of node.elements) collectBindingNames(element, names);
|
|
1868
|
+
return;
|
|
1869
|
+
case "AssignmentPattern":
|
|
1870
|
+
collectBindingNames(node.left, names);
|
|
1871
|
+
return;
|
|
1872
|
+
case "RestElement":
|
|
1873
|
+
collectBindingNames(node.argument, names);
|
|
1874
|
+
return;
|
|
1875
|
+
case "TSParameterProperty": collectBindingNames(node.parameter, names);
|
|
3054
1876
|
}
|
|
3055
|
-
return false;
|
|
3056
1877
|
}
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
if (names.size === 0) return /* @__PURE__ */ new Map();
|
|
3069
|
-
const counts = /* @__PURE__ */ new Map();
|
|
3070
|
-
const shadowDepth = /* @__PURE__ */ new Map();
|
|
3071
|
-
for (const name of names) {
|
|
3072
|
-
counts.set(name, 0);
|
|
3073
|
-
shadowDepth.set(name, 0);
|
|
1878
|
+
function declarationNode(statement) {
|
|
1879
|
+
return statement.type === "ExportNamedDeclaration" || statement.type === "ExportDefaultDeclaration" ? statement.declaration : statement;
|
|
1880
|
+
}
|
|
1881
|
+
function collectBlockBindings(statements, names) {
|
|
1882
|
+
for (const statement of statements) {
|
|
1883
|
+
const declaration = declarationNode(statement);
|
|
1884
|
+
if (!declaration) continue;
|
|
1885
|
+
if (declaration.type === "VariableDeclaration") {
|
|
1886
|
+
if (declaration.kind === "var") continue;
|
|
1887
|
+
for (const declarator of declaration.declarations) collectBindingNames(declarator.id, names);
|
|
1888
|
+
} else if (declaration.type === "FunctionDeclaration" || declaration.type === "ClassDeclaration") collectBindingNames(declaration.id, names);
|
|
3074
1889
|
}
|
|
3075
|
-
|
|
1890
|
+
}
|
|
1891
|
+
function collectFunctionVarBindings(root, names) {
|
|
1892
|
+
function walk(node) {
|
|
3076
1893
|
if (!node || typeof node !== "object") return;
|
|
3077
|
-
|
|
3078
|
-
if (
|
|
3079
|
-
const shadowedHere = [];
|
|
3080
|
-
if (nodeType === "FunctionDeclaration" || nodeType === "FunctionExpression" || nodeType === "ArrowFunctionExpression") {
|
|
3081
|
-
const params = node.params;
|
|
3082
|
-
if (params) {
|
|
3083
|
-
for (const name of names) if (params.some((p) => containsBindingName(p, name))) {
|
|
3084
|
-
shadowDepth.set(name, (shadowDepth.get(name) ?? 0) + 1);
|
|
3085
|
-
shadowedHere.push(name);
|
|
3086
|
-
}
|
|
3087
|
-
}
|
|
3088
|
-
}
|
|
3089
|
-
if (nodeType === "CatchClause") {
|
|
3090
|
-
const param = node.param;
|
|
3091
|
-
if (param) {
|
|
3092
|
-
for (const name of names) if (containsBindingName(param, name)) {
|
|
3093
|
-
shadowDepth.set(name, (shadowDepth.get(name) ?? 0) + 1);
|
|
3094
|
-
shadowedHere.push(name);
|
|
3095
|
-
}
|
|
3096
|
-
}
|
|
3097
|
-
}
|
|
3098
|
-
if (nodeType === "Identifier") {
|
|
3099
|
-
const identName = node.name;
|
|
3100
|
-
if (identName && names.has(identName) && (shadowDepth.get(identName) ?? 0) === 0) {
|
|
3101
|
-
const isMemberProperty = parentNode && parentNode.type === "MemberExpression" && parentKey === "property" && !parentNode.computed;
|
|
3102
|
-
const isObjectPropertyKey = parentNode && parentNode.type === "Property" && parentKey === "key" && !parentNode.shorthand && !parentNode.computed;
|
|
3103
|
-
if (!isMemberProperty && !isObjectPropertyKey) counts.set(identName, (counts.get(identName) ?? 0) + 1);
|
|
3104
|
-
}
|
|
3105
|
-
}
|
|
1894
|
+
if (node !== root && (node.type === "FunctionDeclaration" || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression" || node.type === "StaticBlock")) return;
|
|
1895
|
+
if (node.type === "VariableDeclaration" && node.kind === "var") for (const declarator of node.declarations) collectBindingNames(declarator.id, names);
|
|
3106
1896
|
for (const key of Object.keys(node)) {
|
|
1897
|
+
if (key === "parent") continue;
|
|
3107
1898
|
const child = node[key];
|
|
3108
|
-
if (Array.isArray(child)) child
|
|
3109
|
-
else if (child && typeof child === "object") walk(child
|
|
1899
|
+
if (Array.isArray(child)) for (const item of child) walk(item);
|
|
1900
|
+
else if (child && typeof child === "object") walk(child);
|
|
3110
1901
|
}
|
|
3111
|
-
for (const name of shadowedHere) shadowDepth.set(name, (shadowDepth.get(name) ?? 0) - 1);
|
|
3112
1902
|
}
|
|
3113
|
-
walk(
|
|
3114
|
-
return counts;
|
|
1903
|
+
walk(root);
|
|
3115
1904
|
}
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
if (defaultSpec.local.name !== localName) continue;
|
|
3137
|
-
if (specifiers.length === 1) return {
|
|
3138
|
-
start: importDecl.start,
|
|
3139
|
-
end: importDecl.end,
|
|
3140
|
-
isFullDeclaration: true
|
|
3141
|
-
};
|
|
3142
|
-
const braceIndex = source.indexOf("{", defaultSpec.end);
|
|
3143
|
-
if (braceIndex !== -1) return {
|
|
3144
|
-
start: defaultSpec.start,
|
|
3145
|
-
end: braceIndex,
|
|
3146
|
-
isFullDeclaration: false
|
|
3147
|
-
};
|
|
3148
|
-
return null;
|
|
3149
|
-
}
|
|
1905
|
+
function collectScopeBindings(node) {
|
|
1906
|
+
const names = /* @__PURE__ */ new Set();
|
|
1907
|
+
if (node.type === "FunctionDeclaration" || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression") {
|
|
1908
|
+
collectBindingNames(node.id, names);
|
|
1909
|
+
for (const parameter of node.params) collectBindingNames(parameter, names);
|
|
1910
|
+
collectFunctionVarBindings(node, names);
|
|
1911
|
+
return names;
|
|
1912
|
+
}
|
|
1913
|
+
if (node.type === "BlockStatement") {
|
|
1914
|
+
collectBlockBindings(node.body, names);
|
|
1915
|
+
return names;
|
|
1916
|
+
}
|
|
1917
|
+
if (node.type === "CatchClause") {
|
|
1918
|
+
collectBindingNames(node.param, names);
|
|
1919
|
+
return names;
|
|
1920
|
+
}
|
|
1921
|
+
if (node.type === "ForStatement" || node.type === "ForInStatement" || node.type === "ForOfStatement") {
|
|
1922
|
+
const declaration = node.init ?? node.left;
|
|
1923
|
+
if (declaration?.type === "VariableDeclaration" && declaration.kind !== "var") for (const declarator of declaration.declarations) collectBindingNames(declarator.id, names);
|
|
1924
|
+
return names;
|
|
3150
1925
|
}
|
|
3151
|
-
return null;
|
|
3152
1926
|
}
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
const calls = [];
|
|
3164
|
-
function walk(node) {
|
|
3165
|
-
if (!node || typeof node !== "object") return;
|
|
3166
|
-
const triggerCall = getTriggerCallInfo(node, sourceText);
|
|
3167
|
-
if (triggerCall) {
|
|
3168
|
-
const isWorkflow = workflowNames.has(triggerCall.identifierName);
|
|
3169
|
-
const isJob = jobNames.has(triggerCall.identifierName);
|
|
3170
|
-
if (isWorkflow) calls.push({
|
|
3171
|
-
kind: "workflow",
|
|
3172
|
-
identifierName: triggerCall.identifierName,
|
|
3173
|
-
callRange: triggerCall.callRange,
|
|
3174
|
-
argsText: triggerCall.argsText,
|
|
3175
|
-
optionsText: triggerCall.optionsText
|
|
3176
|
-
});
|
|
3177
|
-
else if (isJob) calls.push({
|
|
3178
|
-
kind: "job",
|
|
3179
|
-
identifierName: triggerCall.identifierName,
|
|
3180
|
-
callRange: triggerCall.callRange,
|
|
3181
|
-
argsText: triggerCall.argsText,
|
|
3182
|
-
optionsText: triggerCall.optionsText
|
|
3183
|
-
});
|
|
3184
|
-
}
|
|
1927
|
+
function addShadowedBindings(shadowedNames, bindings, targetNames) {
|
|
1928
|
+
if (!bindings) return shadowedNames;
|
|
1929
|
+
const relevantBindings = [...bindings].filter((name) => targetNames.has(name));
|
|
1930
|
+
return relevantBindings.length === 0 ? shadowedNames : /* @__PURE__ */ new Set([...shadowedNames, ...relevantBindings]);
|
|
1931
|
+
}
|
|
1932
|
+
function walkBindingAware(program, targetNames, visitor) {
|
|
1933
|
+
function walk(node, shadowedNames, parentNode, parentKey) {
|
|
1934
|
+
if (!node || typeof node !== "object" || node.type === "ImportDeclaration") return;
|
|
1935
|
+
const nestedShadowedNames = node.type === "Program" ? shadowedNames : addShadowedBindings(shadowedNames, collectScopeBindings(node), targetNames);
|
|
1936
|
+
visitor(node, nestedShadowedNames, parentNode, parentKey);
|
|
3185
1937
|
for (const key of Object.keys(node)) {
|
|
1938
|
+
if (key === "parent") continue;
|
|
3186
1939
|
const child = node[key];
|
|
3187
|
-
if (Array.isArray(child)) child
|
|
3188
|
-
else if (child && typeof child === "object") walk(child);
|
|
1940
|
+
if (Array.isArray(child)) for (const item of child) walk(item, nestedShadowedNames, node, key);
|
|
1941
|
+
else if (child && typeof child === "object") walk(child, nestedShadowedNames, node, key);
|
|
3189
1942
|
}
|
|
3190
1943
|
}
|
|
3191
|
-
walk(program);
|
|
1944
|
+
walk(program, /* @__PURE__ */ new Set());
|
|
1945
|
+
}
|
|
1946
|
+
function resolveRelativeImport(context, currentFilePath, importSource) {
|
|
1947
|
+
if (!importSource.startsWith(".")) return void 0;
|
|
1948
|
+
const currentDirectory = path.dirname(currentFilePath.replace(/[?#].*$/, ""));
|
|
1949
|
+
const modulePath = normalizeFilePath(path.resolve(currentDirectory, importSource));
|
|
1950
|
+
return context.modules.get(modulePath) ?? context.modules.get(path.join(modulePath, "index"));
|
|
1951
|
+
}
|
|
1952
|
+
function collectLocalTargets(program, context, currentFilePath) {
|
|
1953
|
+
const targets = /* @__PURE__ */ new Map();
|
|
1954
|
+
const currentModule = context.modules.get(normalizeFilePath(currentFilePath));
|
|
1955
|
+
if (currentModule) for (const [localName, target] of currentModule.localBindings) targets.set(localName, target);
|
|
1956
|
+
for (const statement of program.body) {
|
|
1957
|
+
if (statement.type !== "ImportDeclaration" || statement.importKind === "type") continue;
|
|
1958
|
+
const importSource = statement.source.value;
|
|
1959
|
+
if (typeof importSource !== "string") continue;
|
|
1960
|
+
const importedModule = resolveRelativeImport(context, currentFilePath, importSource);
|
|
1961
|
+
if (!importedModule) continue;
|
|
1962
|
+
for (const specifier of statement.specifiers) {
|
|
1963
|
+
if (specifier.type === "ImportNamespaceSpecifier") continue;
|
|
1964
|
+
if (specifier.type === "ImportSpecifier" && specifier.importKind === "type") continue;
|
|
1965
|
+
const importedName = specifier.type === "ImportDefaultSpecifier" ? "default" : getModuleExportName(specifier.imported);
|
|
1966
|
+
if (!importedName) continue;
|
|
1967
|
+
const target = importedModule.exports.get(importedName);
|
|
1968
|
+
if (!target) continue;
|
|
1969
|
+
targets.set(specifier.local.name, target);
|
|
1970
|
+
}
|
|
1971
|
+
}
|
|
1972
|
+
return targets;
|
|
1973
|
+
}
|
|
1974
|
+
function detectTriggerCallsWithTargets(program, sourceText, targets) {
|
|
1975
|
+
const calls = [];
|
|
1976
|
+
walkBindingAware(program, new Set(targets.keys()), (node, shadowedNames) => {
|
|
1977
|
+
const triggerCall = getTriggerCallInfo(node, sourceText);
|
|
1978
|
+
if (!triggerCall || shadowedNames.has(triggerCall.identifierName)) return;
|
|
1979
|
+
const target = targets.get(triggerCall.identifierName);
|
|
1980
|
+
if (target) calls.push({
|
|
1981
|
+
...triggerCall,
|
|
1982
|
+
kind: target.kind,
|
|
1983
|
+
targetName: target.name
|
|
1984
|
+
});
|
|
1985
|
+
});
|
|
3192
1986
|
return calls;
|
|
3193
1987
|
}
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
* @param workflowNameMap - Map from variable name to workflow name
|
|
3199
|
-
* @param jobNameMap - Map from variable name to job name
|
|
3200
|
-
* @param workflowFileMap - Map from file path (without extension) to workflow name for default exports
|
|
3201
|
-
* @param currentFilePath - Path of the current file being transformed (for resolving relative imports)
|
|
3202
|
-
* @param authNamespace - Auth service namespace used to expand string-literal `authInvoker` to object form
|
|
3203
|
-
* @returns Transformed source code with trigger calls rewritten
|
|
3204
|
-
*/
|
|
3205
|
-
function transformFunctionTriggers(source, workflowNameMap, jobNameMap, workflowFileMap, currentFilePath, authNamespace) {
|
|
1988
|
+
function detectResolvedTriggerCalls(program, sourceText, context, currentFilePath) {
|
|
1989
|
+
return detectTriggerCallsWithTargets(program, sourceText, collectLocalTargets(program, context, currentFilePath));
|
|
1990
|
+
}
|
|
1991
|
+
function transformFunctionTriggers(source, triggerContext, currentFilePath) {
|
|
3206
1992
|
const { program } = parseSync("input.ts", source);
|
|
3207
|
-
const
|
|
3208
|
-
const
|
|
3209
|
-
|
|
3210
|
-
const defaultImports = detectDefaultImports(program);
|
|
3211
|
-
const currentDir = currentFilePath.replace(/[/\\][^/\\]+$/, "");
|
|
3212
|
-
for (const [localName, importSource] of defaultImports) {
|
|
3213
|
-
if (!importSource.startsWith(".")) continue;
|
|
3214
|
-
const resolvedPath = resolvePath(currentDir, importSource).replace(/\.(ts|mts|cts|js|mjs|cjs)$/, "");
|
|
3215
|
-
const workflowName = workflowFileMap.get(resolvedPath);
|
|
3216
|
-
if (workflowName) {
|
|
3217
|
-
localWorkflowNameMap.set(localName, workflowName);
|
|
3218
|
-
workflowDefaultImportNames.add(localName);
|
|
3219
|
-
}
|
|
3220
|
-
}
|
|
3221
|
-
}
|
|
3222
|
-
const allTriggerCalls = detectExtendedTriggerCalls(program, source, new Set(localWorkflowNameMap.keys()), new Set(jobNameMap.keys()));
|
|
1993
|
+
const localTargets = collectLocalTargets(program, triggerContext, currentFilePath);
|
|
1994
|
+
const { authNamespace } = triggerContext;
|
|
1995
|
+
const allTriggerCalls = detectTriggerCallsWithTargets(program, source, localTargets);
|
|
3223
1996
|
const nestedTriggerCalls = [];
|
|
3224
1997
|
const triggerCalls = allTriggerCalls.filter((call) => {
|
|
3225
1998
|
const parent = allTriggerCalls.find((other) => other !== call && other.callRange.start <= call.callRange.start && call.callRange.end <= other.callRange.end);
|
|
3226
|
-
if (parent)
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
}
|
|
3233
|
-
return true;
|
|
1999
|
+
if (!parent) return true;
|
|
2000
|
+
nestedTriggerCalls.push({
|
|
2001
|
+
call,
|
|
2002
|
+
parent
|
|
2003
|
+
});
|
|
2004
|
+
return false;
|
|
3234
2005
|
});
|
|
3235
2006
|
for (const { call, parent } of nestedTriggerCalls) logger.warn(`Nested trigger call "${call.identifierName}.trigger(...)" inside "${parent.identifierName}.trigger(...)" cannot be converted. Move it to a separate statement and pass the result instead.`);
|
|
3236
2007
|
const replacements = [];
|
|
3237
2008
|
let needsNormalizerHelper = false;
|
|
3238
|
-
const
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
if (workflowName) {
|
|
2009
|
+
for (const call of triggerCalls) {
|
|
2010
|
+
let transformedCall;
|
|
2011
|
+
if (call.kind === "workflow") {
|
|
3242
2012
|
let optionsPart = "";
|
|
3243
2013
|
if (call.optionsText !== void 0) if (authNamespace) {
|
|
3244
2014
|
optionsPart = `, ${NORMALIZER_IDENTIFIER}(${call.optionsText})`;
|
|
3245
2015
|
needsNormalizerHelper = true;
|
|
3246
2016
|
} else optionsPart = `, ${call.optionsText}`;
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
start: call.callRange.start,
|
|
3250
|
-
end: call.callRange.end,
|
|
3251
|
-
text: transformedCall
|
|
3252
|
-
});
|
|
3253
|
-
transformedCallsPerIdentifier.set(call.identifierName, (transformedCallsPerIdentifier.get(call.identifierName) ?? 0) + 1);
|
|
3254
|
-
}
|
|
3255
|
-
} else {
|
|
3256
|
-
const jobName = jobNameMap.get(call.identifierName);
|
|
3257
|
-
if (jobName) {
|
|
2017
|
+
transformedCall = `tailor.workflow.triggerWorkflow(${JSON.stringify(call.targetName)}, ${call.argsText || "undefined"}${optionsPart})`;
|
|
2018
|
+
} else {
|
|
3258
2019
|
const optionsPart = call.optionsText !== void 0 ? `, ${call.optionsText}` : "";
|
|
3259
|
-
|
|
3260
|
-
replacements.push({
|
|
3261
|
-
start: call.callRange.start,
|
|
3262
|
-
end: call.callRange.end,
|
|
3263
|
-
text: transformedCall
|
|
3264
|
-
});
|
|
3265
|
-
transformedCallsPerIdentifier.set(call.identifierName, (transformedCallsPerIdentifier.get(call.identifierName) ?? 0) + 1);
|
|
3266
|
-
}
|
|
3267
|
-
}
|
|
3268
|
-
const refCounts = buildReferenceCountMap(program, workflowDefaultImportNames);
|
|
3269
|
-
for (const localName of workflowDefaultImportNames) {
|
|
3270
|
-
const transformedCount = transformedCallsPerIdentifier.get(localName) ?? 0;
|
|
3271
|
-
const refCount = refCounts.get(localName) ?? 0;
|
|
3272
|
-
if (refCount === 0 || transformedCount >= refCount) {
|
|
3273
|
-
const removal = findDefaultImportRemovalRange(program, localName, source);
|
|
3274
|
-
if (removal) replacements.push({
|
|
3275
|
-
start: removal.start,
|
|
3276
|
-
end: removal.isFullDeclaration ? findStatementEnd(source, removal.end) : removal.end,
|
|
3277
|
-
text: ""
|
|
3278
|
-
});
|
|
2020
|
+
transformedCall = `(async () => tailor.workflow.triggerJobFunction(${JSON.stringify(call.targetName)}, ${call.argsText || "undefined"}${optionsPart}))()`;
|
|
3279
2021
|
}
|
|
2022
|
+
replacements.push({
|
|
2023
|
+
start: call.callRange.start,
|
|
2024
|
+
end: call.callRange.end,
|
|
2025
|
+
text: transformedCall
|
|
2026
|
+
});
|
|
3280
2027
|
}
|
|
3281
2028
|
const transformed = applyReplacements(source, replacements);
|
|
3282
|
-
|
|
3283
|
-
return transformed;
|
|
3284
|
-
}
|
|
3285
|
-
|
|
3286
|
-
//#endregion
|
|
3287
|
-
//#region src/cli/shared/trigger-context.ts
|
|
3288
|
-
/**
|
|
3289
|
-
* Normalize a file path by removing extension and resolving to absolute path
|
|
3290
|
-
* @param filePath - File path to normalize
|
|
3291
|
-
* @returns Normalized absolute path without extension
|
|
3292
|
-
*/
|
|
3293
|
-
function normalizeFilePath(filePath) {
|
|
3294
|
-
const absolutePath = path.resolve(filePath);
|
|
3295
|
-
const ext = path.extname(absolutePath);
|
|
3296
|
-
return absolutePath.slice(0, -ext.length);
|
|
3297
|
-
}
|
|
3298
|
-
/**
|
|
3299
|
-
* Build trigger context from workflow configuration
|
|
3300
|
-
* Scans workflow files to collect workflow and job mappings
|
|
3301
|
-
* @param workflowConfig - Workflow file loading configuration
|
|
3302
|
-
* @param authNamespace - Auth service namespace (optional, used for string-literal authInvoker expansion)
|
|
3303
|
-
* @returns Trigger context built from workflow sources
|
|
3304
|
-
*/
|
|
3305
|
-
async function buildTriggerContext(workflowConfig, authNamespace) {
|
|
3306
|
-
const workflowNameMap = /* @__PURE__ */ new Map();
|
|
3307
|
-
const jobNameMap = /* @__PURE__ */ new Map();
|
|
3308
|
-
const workflowFileMap = /* @__PURE__ */ new Map();
|
|
3309
|
-
if (!workflowConfig) return {
|
|
3310
|
-
workflowNameMap,
|
|
3311
|
-
jobNameMap,
|
|
3312
|
-
workflowFileMap,
|
|
3313
|
-
authNamespace
|
|
3314
|
-
};
|
|
3315
|
-
const workflowFiles = loadFilesWithIgnores(workflowConfig);
|
|
3316
|
-
for (const file of workflowFiles) try {
|
|
3317
|
-
const source = await fs$1.promises.readFile(file, "utf-8");
|
|
3318
|
-
const { program } = parseSync("input.ts", source);
|
|
3319
|
-
const workflows = findAllWorkflows(program, source);
|
|
3320
|
-
const workflowMap = buildWorkflowNameMap(workflows);
|
|
3321
|
-
for (const [exportName, workflowName] of workflowMap) workflowNameMap.set(exportName, workflowName);
|
|
3322
|
-
for (const workflow of workflows) if (workflow.isDefaultExport) {
|
|
3323
|
-
const normalizedPath = normalizeFilePath(file);
|
|
3324
|
-
workflowFileMap.set(normalizedPath, workflow.name);
|
|
3325
|
-
}
|
|
3326
|
-
const jobMap = buildJobNameMap(findAllJobs(program, source));
|
|
3327
|
-
for (const [exportName, jobName] of jobMap) jobNameMap.set(exportName, jobName);
|
|
3328
|
-
} catch (error) {
|
|
3329
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
3330
|
-
logger.warn(`Failed to process workflow file ${file}: ${errorMessage}`, { mode: "stream" });
|
|
3331
|
-
continue;
|
|
3332
|
-
}
|
|
3333
|
-
return {
|
|
3334
|
-
workflowNameMap,
|
|
3335
|
-
jobNameMap,
|
|
3336
|
-
workflowFileMap,
|
|
3337
|
-
authNamespace
|
|
3338
|
-
};
|
|
3339
|
-
}
|
|
3340
|
-
function sortedMapToJson(m) {
|
|
3341
|
-
return JSON.stringify([...m.entries()].toSorted(([a], [b]) => a.localeCompare(b)));
|
|
2029
|
+
return needsNormalizerHelper && authNamespace ? buildNormalizerHelperSource(authNamespace) + transformed : transformed;
|
|
3342
2030
|
}
|
|
3343
|
-
/**
|
|
3344
|
-
* Serialize trigger context to a deterministic string for cache hashing.
|
|
3345
|
-
* Returns an empty string if no context is provided.
|
|
3346
|
-
* @param ctx - Trigger context to serialize
|
|
3347
|
-
* @returns Deterministic string representation
|
|
3348
|
-
*/
|
|
3349
|
-
function serializeTriggerContext(ctx) {
|
|
3350
|
-
if (!ctx) return "";
|
|
3351
|
-
return sortedMapToJson(ctx.workflowNameMap) + sortedMapToJson(ctx.jobNameMap) + sortedMapToJson(ctx.workflowFileMap) + (ctx.authNamespace ?? "");
|
|
3352
|
-
}
|
|
3353
|
-
/**
|
|
3354
|
-
* Create a rolldown plugin for transforming trigger calls
|
|
3355
|
-
* Returns undefined if no trigger context is provided
|
|
3356
|
-
* @param triggerContext - Trigger context to use for transformations
|
|
3357
|
-
* @returns Rolldown plugin or undefined when no context
|
|
3358
|
-
*/
|
|
3359
2031
|
function createTriggerTransformPlugin(triggerContext) {
|
|
3360
|
-
if (!triggerContext) return;
|
|
2032
|
+
if (!triggerContext) return void 0;
|
|
3361
2033
|
return {
|
|
3362
2034
|
name: "trigger-transform",
|
|
3363
2035
|
transform: {
|
|
3364
2036
|
filter: { id: { include: [/\.(ts|mts|cts|js|mjs|cjs)$/] } },
|
|
3365
2037
|
handler(code, id) {
|
|
3366
2038
|
if (!code.includes(".trigger(")) return null;
|
|
3367
|
-
return { code: transformFunctionTriggers(code, triggerContext
|
|
2039
|
+
return { code: transformFunctionTriggers(code, triggerContext, id) };
|
|
3368
2040
|
}
|
|
3369
2041
|
}
|
|
3370
2042
|
};
|
|
3371
2043
|
}
|
|
3372
2044
|
|
|
2045
|
+
//#endregion
|
|
2046
|
+
//#region src/cli/shared/bundle-log-level.ts
|
|
2047
|
+
const INFO_LEVEL_CONSOLE_METHODS = [
|
|
2048
|
+
"console.info",
|
|
2049
|
+
"console.table",
|
|
2050
|
+
"console.dir",
|
|
2051
|
+
"console.dirxml",
|
|
2052
|
+
"console.count",
|
|
2053
|
+
"console.countReset",
|
|
2054
|
+
"console.time",
|
|
2055
|
+
"console.timeLog",
|
|
2056
|
+
"console.timeEnd",
|
|
2057
|
+
"console.group",
|
|
2058
|
+
"console.groupCollapsed",
|
|
2059
|
+
"console.groupEnd",
|
|
2060
|
+
"console.clear"
|
|
2061
|
+
];
|
|
2062
|
+
const DEBUG_LEVEL_CONSOLE_METHODS = [
|
|
2063
|
+
"console.debug",
|
|
2064
|
+
"console.log",
|
|
2065
|
+
"console.trace"
|
|
2066
|
+
];
|
|
2067
|
+
const WARN_LEVEL_CONSOLE_METHODS = ["console.warn"];
|
|
2068
|
+
const ERROR_LEVEL_CONSOLE_METHODS = ["console.error"];
|
|
2069
|
+
const MANUAL_PURE_FUNCTIONS_BY_LOG_LEVEL = {
|
|
2070
|
+
DEBUG: [],
|
|
2071
|
+
INFO: DEBUG_LEVEL_CONSOLE_METHODS,
|
|
2072
|
+
WARN: [...DEBUG_LEVEL_CONSOLE_METHODS, ...INFO_LEVEL_CONSOLE_METHODS],
|
|
2073
|
+
ERROR: [
|
|
2074
|
+
...DEBUG_LEVEL_CONSOLE_METHODS,
|
|
2075
|
+
...INFO_LEVEL_CONSOLE_METHODS,
|
|
2076
|
+
...WARN_LEVEL_CONSOLE_METHODS
|
|
2077
|
+
],
|
|
2078
|
+
SILENT: [
|
|
2079
|
+
...DEBUG_LEVEL_CONSOLE_METHODS,
|
|
2080
|
+
...INFO_LEVEL_CONSOLE_METHODS,
|
|
2081
|
+
...WARN_LEVEL_CONSOLE_METHODS,
|
|
2082
|
+
...ERROR_LEVEL_CONSOLE_METHODS
|
|
2083
|
+
]
|
|
2084
|
+
};
|
|
2085
|
+
function normalizeBundleLogLevel(value) {
|
|
2086
|
+
const normalized = value.trim().toUpperCase();
|
|
2087
|
+
return isLogLevel(normalized) ? normalized : void 0;
|
|
2088
|
+
}
|
|
2089
|
+
function resolveBundleLogLevel(configValue) {
|
|
2090
|
+
if (configValue === void 0) return "DEBUG";
|
|
2091
|
+
const resolved = normalizeBundleLogLevel(configValue);
|
|
2092
|
+
if (resolved) return resolved;
|
|
2093
|
+
throw new Error(`Invalid logLevel "${configValue}". Expected one of: ${LOG_LEVELS.join(", ")}`);
|
|
2094
|
+
}
|
|
2095
|
+
function manualPureFunctionsForLogLevel(logLevel) {
|
|
2096
|
+
return MANUAL_PURE_FUNCTIONS_BY_LOG_LEVEL[logLevel];
|
|
2097
|
+
}
|
|
2098
|
+
function createLogLevelTreeshakeOptions(logLevel) {
|
|
2099
|
+
const manualPureFunctions = manualPureFunctionsForLogLevel(logLevel);
|
|
2100
|
+
return manualPureFunctions.length > 0 ? { manualPureFunctions } : {};
|
|
2101
|
+
}
|
|
2102
|
+
|
|
2103
|
+
//#endregion
|
|
2104
|
+
//#region src/cli/shared/function-treeshake.ts
|
|
2105
|
+
const BASE_FUNCTION_TREESHAKE_OPTIONS = {
|
|
2106
|
+
moduleSideEffects: false,
|
|
2107
|
+
annotations: true,
|
|
2108
|
+
unknownGlobalSideEffects: false
|
|
2109
|
+
};
|
|
2110
|
+
function mergeFunctionTreeshakeOptions(fragments) {
|
|
2111
|
+
const merged = {};
|
|
2112
|
+
const manualPureFunctions = /* @__PURE__ */ new Set();
|
|
2113
|
+
for (const fragment of fragments) {
|
|
2114
|
+
Object.assign(merged, fragment);
|
|
2115
|
+
for (const name of fragment.manualPureFunctions ?? []) manualPureFunctions.add(name);
|
|
2116
|
+
}
|
|
2117
|
+
if (manualPureFunctions.size > 0) merged.manualPureFunctions = [...manualPureFunctions];
|
|
2118
|
+
else delete merged.manualPureFunctions;
|
|
2119
|
+
return merged;
|
|
2120
|
+
}
|
|
2121
|
+
function composeFunctionTreeshakeOptions(fragments = []) {
|
|
2122
|
+
return mergeFunctionTreeshakeOptions([BASE_FUNCTION_TREESHAKE_OPTIONS, ...fragments]);
|
|
2123
|
+
}
|
|
2124
|
+
|
|
2125
|
+
//#endregion
|
|
2126
|
+
//#region src/cli/shared/platform-bundle-plugin.ts
|
|
2127
|
+
const GATE = /(?<![\w$.])process\.env\.TAILOR_PLATFORM_BUNDLE\b/g;
|
|
2128
|
+
const platformBundleDefinePlugin = {
|
|
2129
|
+
name: "tailor-platform-bundle-define",
|
|
2130
|
+
transform(code) {
|
|
2131
|
+
if (!code.includes("process.env.TAILOR_PLATFORM_BUNDLE")) return null;
|
|
2132
|
+
return { code: code.replace(GATE, "true") };
|
|
2133
|
+
}
|
|
2134
|
+
};
|
|
2135
|
+
|
|
3373
2136
|
//#endregion
|
|
3374
2137
|
//#region src/cli/services/auth/bundler.ts
|
|
3375
2138
|
/**
|
|
@@ -5723,36 +4486,15 @@ function assertUniqueResolverNames(resolvers, namespace) {
|
|
|
5723
4486
|
*/
|
|
5724
4487
|
function findVariableDeclarationsByName(program) {
|
|
5725
4488
|
const declarations = /* @__PURE__ */ new Map();
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
end: varDecl.end
|
|
5735
|
-
});
|
|
5736
|
-
}
|
|
5737
|
-
}
|
|
5738
|
-
if (nodeType === "ExportNamedDeclaration") {
|
|
5739
|
-
const exportDecl = node;
|
|
5740
|
-
const declaration = exportDecl.declaration;
|
|
5741
|
-
if (declaration?.type === "VariableDeclaration") {
|
|
5742
|
-
const varDecl = declaration;
|
|
5743
|
-
for (const decl of varDecl.declarations) if (decl.id.type === "Identifier" && decl.id.name) declarations.set(decl.id.name, {
|
|
5744
|
-
start: exportDecl.start,
|
|
5745
|
-
end: exportDecl.end
|
|
5746
|
-
});
|
|
5747
|
-
}
|
|
5748
|
-
}
|
|
5749
|
-
for (const key of Object.keys(node)) {
|
|
5750
|
-
const child = node[key];
|
|
5751
|
-
if (Array.isArray(child)) child.forEach((c) => walk(c));
|
|
5752
|
-
else if (child && typeof child === "object") walk(child);
|
|
5753
|
-
}
|
|
4489
|
+
for (const statement of program.body) {
|
|
4490
|
+
const declaration = statement.type === "ExportNamedDeclaration" ? statement.declaration : statement;
|
|
4491
|
+
if (declaration?.type !== "VariableDeclaration") continue;
|
|
4492
|
+
const variableDeclaration = declaration;
|
|
4493
|
+
for (const declarator of variableDeclaration.declarations) if (declarator.id.type === "Identifier") declarations.set(declarator.id.name, {
|
|
4494
|
+
start: statement.start,
|
|
4495
|
+
end: statement.end
|
|
4496
|
+
});
|
|
5754
4497
|
}
|
|
5755
|
-
walk(program);
|
|
5756
4498
|
return declarations;
|
|
5757
4499
|
}
|
|
5758
4500
|
/**
|
|
@@ -5779,48 +4521,32 @@ function findWorkflowDefaultExport(program) {
|
|
|
5779
4521
|
}
|
|
5780
4522
|
/**
|
|
5781
4523
|
* Transform workflow source code
|
|
5782
|
-
* - Transform .trigger() calls to tailor.workflow.triggerJobFunction()
|
|
5783
4524
|
* - Other jobs: remove entire variable declaration
|
|
5784
4525
|
* @param source - The source code to transform
|
|
5785
4526
|
* @param targetJobName - The name of the target job (from job config)
|
|
5786
4527
|
* @param targetJobExportName - The export name of the target job (optional, for enhanced detection)
|
|
5787
4528
|
* @param otherJobExportNames - Export names of other jobs to remove (optional, for enhanced detection)
|
|
5788
|
-
* @param allJobsMap - Map from export name to job name for trigger transformation (optional)
|
|
5789
4529
|
* @returns Transformed workflow source code
|
|
5790
4530
|
*/
|
|
5791
|
-
function transformWorkflowSource(source, targetJobName, targetJobExportName, otherJobExportNames
|
|
4531
|
+
function transformWorkflowSource(source, targetJobName, targetJobExportName, otherJobExportNames) {
|
|
5792
4532
|
const { program } = parseSync("input.ts", source);
|
|
5793
4533
|
const detectedJobs = findAllJobs(program, source);
|
|
5794
4534
|
if (!detectedJobs.some((j) => j.name === targetJobName)) return source;
|
|
5795
|
-
const jobNameMap = allJobsMap ?? buildJobNameMap(detectedJobs);
|
|
5796
4535
|
const allDeclarations = findVariableDeclarationsByName(program);
|
|
5797
|
-
const triggerCalls = detectTriggerCalls(program, source);
|
|
5798
4536
|
const replacements = [];
|
|
5799
|
-
const
|
|
5800
|
-
const isInsideRemovedRange = (pos) => {
|
|
5801
|
-
return removedRanges.some((r) => pos >= r.start && pos < r.end);
|
|
5802
|
-
};
|
|
5803
|
-
const isAlreadyMarkedForRemoval = (start) => {
|
|
5804
|
-
return removedRanges.some((r) => r.start === start);
|
|
5805
|
-
};
|
|
4537
|
+
const removedStarts = /* @__PURE__ */ new Set();
|
|
5806
4538
|
for (const job of detectedJobs) {
|
|
5807
4539
|
if (job.name === targetJobName) continue;
|
|
5808
|
-
if (job.statementRange && !
|
|
4540
|
+
if (job.statementRange && !removedStarts.has(job.statementRange.start)) {
|
|
5809
4541
|
const endPos = findStatementEnd(source, job.statementRange.end);
|
|
5810
|
-
|
|
5811
|
-
start: job.statementRange.start,
|
|
5812
|
-
end: endPos
|
|
5813
|
-
});
|
|
4542
|
+
removedStarts.add(job.statementRange.start);
|
|
5814
4543
|
replacements.push({
|
|
5815
4544
|
start: job.statementRange.start,
|
|
5816
4545
|
end: endPos,
|
|
5817
4546
|
text: ""
|
|
5818
4547
|
});
|
|
5819
4548
|
} else if (!job.statementRange) {
|
|
5820
|
-
|
|
5821
|
-
start: job.bodyValueRange.start,
|
|
5822
|
-
end: job.bodyValueRange.end
|
|
5823
|
-
});
|
|
4549
|
+
removedStarts.add(job.bodyValueRange.start);
|
|
5824
4550
|
replacements.push({
|
|
5825
4551
|
start: job.bodyValueRange.start,
|
|
5826
4552
|
end: job.bodyValueRange.end,
|
|
@@ -5831,12 +4557,9 @@ function transformWorkflowSource(source, targetJobName, targetJobExportName, oth
|
|
|
5831
4557
|
if (otherJobExportNames) for (const exportName of otherJobExportNames) {
|
|
5832
4558
|
if (exportName === targetJobExportName) continue;
|
|
5833
4559
|
const declRange = allDeclarations.get(exportName);
|
|
5834
|
-
if (declRange && !
|
|
4560
|
+
if (declRange && !removedStarts.has(declRange.start)) {
|
|
5835
4561
|
const endPos = findStatementEnd(source, declRange.end);
|
|
5836
|
-
|
|
5837
|
-
start: declRange.start,
|
|
5838
|
-
end: endPos
|
|
5839
|
-
});
|
|
4562
|
+
removedStarts.add(declRange.start);
|
|
5840
4563
|
replacements.push({
|
|
5841
4564
|
start: declRange.start,
|
|
5842
4565
|
end: endPos,
|
|
@@ -5845,31 +4568,15 @@ function transformWorkflowSource(source, targetJobName, targetJobExportName, oth
|
|
|
5845
4568
|
}
|
|
5846
4569
|
}
|
|
5847
4570
|
const workflowExport = findWorkflowDefaultExport(program);
|
|
5848
|
-
if (workflowExport && !
|
|
4571
|
+
if (workflowExport && !removedStarts.has(workflowExport.start)) {
|
|
5849
4572
|
const endPos = findStatementEnd(source, workflowExport.end);
|
|
5850
|
-
|
|
5851
|
-
start: workflowExport.start,
|
|
5852
|
-
end: endPos
|
|
5853
|
-
});
|
|
4573
|
+
removedStarts.add(workflowExport.start);
|
|
5854
4574
|
replacements.push({
|
|
5855
4575
|
start: workflowExport.start,
|
|
5856
4576
|
end: endPos,
|
|
5857
4577
|
text: ""
|
|
5858
4578
|
});
|
|
5859
4579
|
}
|
|
5860
|
-
for (const call of triggerCalls) {
|
|
5861
|
-
if (isInsideRemovedRange(call.callRange.start)) continue;
|
|
5862
|
-
const jobName = jobNameMap.get(call.identifierName);
|
|
5863
|
-
if (jobName) {
|
|
5864
|
-
const optionsPart = call.optionsText !== void 0 ? `, ${call.optionsText}` : "";
|
|
5865
|
-
const transformedCall = `(async () => tailor.workflow.triggerJobFunction("${jobName}", ${call.argsText || "undefined"}${optionsPart}))()`;
|
|
5866
|
-
replacements.push({
|
|
5867
|
-
start: call.callRange.start,
|
|
5868
|
-
end: call.callRange.end,
|
|
5869
|
-
text: transformedCall
|
|
5870
|
-
});
|
|
5871
|
-
}
|
|
5872
|
-
}
|
|
5873
4580
|
return applyReplacements(source, replacements);
|
|
5874
4581
|
}
|
|
5875
4582
|
|
|
@@ -5911,7 +4618,7 @@ async function bundleWorkflowJobs(allJobs, mainJobNames, env = {}, triggerContex
|
|
|
5911
4618
|
bundledCode: /* @__PURE__ */ new Map()
|
|
5912
4619
|
};
|
|
5913
4620
|
}
|
|
5914
|
-
const { usedJobs, mainJobDeps } = await filterUsedJobs(allJobs, mainJobNames);
|
|
4621
|
+
const { usedJobs, mainJobDeps } = await filterUsedJobs(allJobs, mainJobNames, triggerContext);
|
|
5915
4622
|
logger.newline();
|
|
5916
4623
|
logger.log(`Bundling ${styles.highlight(usedJobs.length.toString())} files for ${styles.info("\"workflow-job\"")}`);
|
|
5917
4624
|
const outputDir = path.resolve(getDistDir(), "workflow-jobs");
|
|
@@ -5945,9 +4652,10 @@ async function bundleWorkflowJobs(allJobs, mainJobNames, env = {}, triggerContex
|
|
|
5945
4652
|
* Also returns a map of mainJob -> all jobs it depends on (for metadata).
|
|
5946
4653
|
* @param allJobs - All available job infos
|
|
5947
4654
|
* @param mainJobNames - Names of main jobs
|
|
4655
|
+
* @param triggerContext - Module binding metadata for resolving trigger targets
|
|
5948
4656
|
* @returns Used jobs and main job dependency map
|
|
5949
4657
|
*/
|
|
5950
|
-
async function filterUsedJobs(allJobs, mainJobNames) {
|
|
4658
|
+
async function filterUsedJobs(allJobs, mainJobNames, triggerContext) {
|
|
5951
4659
|
if (allJobs.length === 0 || mainJobNames.length === 0) return {
|
|
5952
4660
|
usedJobs: [],
|
|
5953
4661
|
mainJobDeps: {}
|
|
@@ -5958,26 +4666,19 @@ async function filterUsedJobs(allJobs, mainJobNames) {
|
|
|
5958
4666
|
existing.push(job);
|
|
5959
4667
|
jobsBySourceFile.set(job.sourceFile, existing);
|
|
5960
4668
|
}
|
|
5961
|
-
const exportNameToJobName = /* @__PURE__ */ new Map();
|
|
5962
|
-
for (const job of allJobs) exportNameToJobName.set(job.exportName, job.name);
|
|
5963
4669
|
const dependencies = /* @__PURE__ */ new Map();
|
|
5964
4670
|
const fileResults = await Promise.all(Array.from(jobsBySourceFile.entries()).map(async ([sourceFile, jobs]) => {
|
|
5965
4671
|
try {
|
|
5966
4672
|
const source = await fs$1.promises.readFile(sourceFile, "utf-8");
|
|
5967
4673
|
const { program } = parseSync("input.ts", source);
|
|
5968
4674
|
const detectedJobs = findAllJobs(program, source);
|
|
5969
|
-
const
|
|
5970
|
-
for (const detected of detectedJobs) if (detected.exportName) localExportNameToJobName.set(detected.exportName, detected.name);
|
|
5971
|
-
const triggerCalls = detectTriggerCalls(program, source);
|
|
4675
|
+
const triggerCalls = detectResolvedTriggerCalls(program, source, triggerContext, sourceFile);
|
|
5972
4676
|
const jobDependencies = [];
|
|
5973
4677
|
for (const job of jobs) {
|
|
5974
4678
|
const detectedJob = detectedJobs.find((d) => d.name === job.name);
|
|
5975
4679
|
if (!detectedJob) continue;
|
|
5976
4680
|
const jobDeps = /* @__PURE__ */ new Set();
|
|
5977
|
-
for (const call of triggerCalls) if (call.callRange.start >= detectedJob.bodyValueRange.start && call.callRange.end <= detectedJob.bodyValueRange.end)
|
|
5978
|
-
const triggeredJobName = localExportNameToJobName.get(call.identifierName) || exportNameToJobName.get(call.identifierName);
|
|
5979
|
-
if (triggeredJobName) jobDeps.add(triggeredJobName);
|
|
5980
|
-
}
|
|
4681
|
+
for (const call of triggerCalls) if (call.kind === "job" && call.callRange.start >= detectedJob.bodyValueRange.start && call.callRange.end <= detectedJob.bodyValueRange.end) jobDeps.add(call.targetName);
|
|
5981
4682
|
if (jobDeps.size > 0) jobDependencies.push({
|
|
5982
4683
|
jobName: job.name,
|
|
5983
4684
|
deps: jobDeps
|
|
@@ -6038,10 +4739,8 @@ async function bundleSingleJob(job, allJobs, outputDir, tsconfig, env, triggerCo
|
|
|
6038
4739
|
}
|
|
6039
4740
|
`;
|
|
6040
4741
|
fs$1.writeFileSync(entryPath, entryContent);
|
|
6041
|
-
const otherJobExportNames = allJobs.filter((j) => j.name !== job.name).map((j) => j.exportName);
|
|
6042
|
-
const allJobsMap = /* @__PURE__ */ new Map();
|
|
6043
|
-
for (const j of allJobs) allJobsMap.set(j.exportName, j.name);
|
|
6044
4742
|
const resolvedSourceFile = safeRealpath(job.sourceFile);
|
|
4743
|
+
const otherJobExportNames = allJobs.filter((candidate) => candidate.name !== job.name && safeRealpath(candidate.sourceFile) === resolvedSourceFile).map((j) => j.exportName);
|
|
6045
4744
|
const plugins = [
|
|
6046
4745
|
{
|
|
6047
4746
|
name: "workflow-transform",
|
|
@@ -6050,8 +4749,8 @@ async function bundleSingleJob(job, allJobs, outputDir, tsconfig, env, triggerCo
|
|
|
6050
4749
|
handler(code, id) {
|
|
6051
4750
|
if (!code.includes("createWorkflowJob") && !code.includes("createWorkflow") && !code.includes(".trigger(")) return null;
|
|
6052
4751
|
let transformed = code;
|
|
6053
|
-
if (safeRealpath(id) === resolvedSourceFile) transformed = transformWorkflowSource(code, job.name, job.exportName, otherJobExportNames
|
|
6054
|
-
if (
|
|
4752
|
+
if (safeRealpath(id) === resolvedSourceFile) transformed = transformWorkflowSource(code, job.name, job.exportName, otherJobExportNames);
|
|
4753
|
+
if (transformed.includes(".trigger(")) transformed = transformFunctionTriggers(transformed, triggerContext, id);
|
|
6055
4754
|
if (transformed === code) return null;
|
|
6056
4755
|
return { code: transformed };
|
|
6057
4756
|
}
|
|
@@ -6846,5 +5545,5 @@ async function loadApplication(params) {
|
|
|
6846
5545
|
}
|
|
6847
5546
|
|
|
6848
5547
|
//#endregion
|
|
6849
|
-
export {
|
|
6850
|
-
//# sourceMappingURL=application-
|
|
5548
|
+
export { fetchAllTolerant as A, initOperatorClient as B, createBundleCache as C, closeConnectionPool as D, hashFile as E, getConsoleBaseUrl as F, byName as G, normalizeBaseUrl as H, getOAuth2ClientId as I, LOG_LEVELS as K, getOrNull as L, fetchPaged as M, fetchPlatformMachineUserToken as N, defaultPlatformBaseUrl as O, fetchUserInfo as P, getPlatformBaseUrl as R, hasGenerationHooks as S, hashContent as T, rememberPlatformConfigForToken as U, isDefaultPlatform as V, resolveStaticWebsiteUrls as W, platformBundleDefinePlugin as _, resolveInlineSourcemap as a, resolveBundleLogLevel as b, ResolverSchema as c, buildExecutorArgsExpr as d, buildResolverOperationHookExpr as f, stringifyFunction as g, TailorDBTypeSchema as h, resolverBundleKey as i, fetchMachineUserToken as j, fetchAll as k, HTTP_METHODS as l, assertUniqueTailorDBTypeNamesWithExternal as m, generatePluginFilesIfNeeded as n, WorkflowJobFunctionExecutionPolicySchema as o, assertUniqueLocalTailorDBTypeNames as p, loadApplication as r, WorkflowJobSchema as s, defineApplication as t, INVOKER_EXPR as u, composeFunctionTreeshakeOptions as v, getDistDir as w, getPluginGenerationDependencies as x, createLogLevelTreeshakeOptions as y, initOAuth2Client as z };
|
|
5549
|
+
//# sourceMappingURL=application-CUxVA7Fs.mjs.map
|