@tailor-platform/sdk 2.1.0 → 2.3.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 +199 -0
- package/{dist/cli/index.mjs → bin/tailor.mjs} +1 -1
- package/dist/application-BZfk4HKm.mjs +3 -0
- package/dist/{application-D77KJFKD.mjs → application-F-nl107y.mjs} +121 -27
- package/dist/application-F-nl107y.mjs.map +1 -0
- package/dist/cli/commands/deploy/tailordb/index.d.mts +2 -1
- package/dist/cli/commands/deploy/types.d.mts +2 -1
- package/dist/cli/commands/tailordb/migrate/diff-calculator.d.mts +52 -22
- package/dist/cli/commands/tailordb/migrate/file-state.d.mts +1 -0
- package/dist/cli/commands/tailordb/migrate/generate.d.mts +6 -0
- package/dist/cli/commands/tailordb/migrate/rename-detection.d.mts +22 -0
- package/dist/cli/commands/tailordb/migrate/schema-checks.d.mts +2 -2
- package/dist/cli/commands/tailordb/migrate/snapshot-types.d.mts +9 -2
- package/dist/cli/commands/tailordb/migrate/snapshot.d.mts +30 -9
- package/dist/cli/lib.d.mts +4 -4
- package/dist/cli/lib.mjs +3 -482
- package/dist/cli/lib.mjs.map +1 -1
- package/dist/cli/main.mjs +1151 -208
- package/dist/cli/main.mjs.map +1 -1
- package/dist/cli/ts-hook.mjs +52 -7
- package/dist/completion/zsh-worker.zsh +167 -4
- package/dist/configure/index.d.mts +3 -3
- package/dist/configure/index.mjs +90 -23
- package/dist/configure/index.mjs.map +1 -1
- package/dist/configure/services/index.d.mts +3 -2
- package/dist/configure/services/tailordb/index.d.mts +2 -1
- package/dist/configure/services/tailordb/schema.d.mts +46 -46
- package/dist/configure/services/tailordb/types.d.mts +30 -4
- package/dist/configure/services/workflow/index.d.mts +2 -2
- package/dist/configure/services/workflow/wait-point.d.mts +72 -13
- package/dist/{crashreport-B5LqCTfF.mjs → crashreport-CIIfLnoO.mjs} +2 -2
- package/dist/{crashreport-B5LqCTfF.mjs.map → crashreport-CIIfLnoO.mjs.map} +1 -1
- package/dist/{crashreport-eI7ty7ok.mjs → crashreport-CINZ5dVN.mjs} +1 -1
- package/dist/errors-BVb6vYGy.mjs +89 -0
- package/dist/errors-BVb6vYGy.mjs.map +1 -0
- package/dist/kysely/index.d.mts +53 -5
- package/dist/kysely/index.mjs +7 -2
- package/dist/kysely/index.mjs.map +1 -1
- package/dist/{logger-CXQq9YIp.mjs → logger-DSdExfor.mjs} +83 -42
- package/dist/logger-DSdExfor.mjs.map +1 -0
- package/dist/plugin/builtin/seed/index.mjs +1 -1
- package/dist/{register-ts-hook-BU18uU44.mjs → register-ts-hook-ClI226n2.mjs} +3541 -703
- package/dist/register-ts-hook-ClI226n2.mjs.map +1 -0
- package/dist/schema--xYWRGfe.mjs.map +1 -1
- package/dist/seed/index.d.mts +52 -3
- package/dist/seed/index.mjs +200 -44
- package/dist/seed/index.mjs.map +1 -1
- package/dist/{seed-B-yckgQY.mjs → seed-xqM9WIHP.mjs} +8 -8
- package/dist/seed-xqM9WIHP.mjs.map +1 -0
- package/dist/{service-k1xy_A5G.mjs → service-C_WpbKHu.mjs} +39 -5
- package/dist/service-C_WpbKHu.mjs.map +1 -0
- package/dist/service-D1RCdzIL.mjs +3 -0
- package/dist/{service-B5WynBHQ.mjs → service-hZskxZmg.mjs} +3 -3
- package/dist/{service-B5WynBHQ.mjs.map → service-hZskxZmg.mjs.map} +1 -1
- package/dist/{service_pb-D5--My_M.mjs → service_pb-BEWj1pOV.mjs} +2 -2
- package/dist/{service_pb-D5--My_M.mjs.map → service_pb-BEWj1pOV.mjs.map} +1 -1
- package/dist/{service_pb-i8CmnQP4.mjs → service_pb-BjlhvK9E.mjs} +1 -1
- package/dist/utils/test/index.d.mts +6 -3
- package/dist/utils/test/index.mjs +25 -13
- package/dist/utils/test/index.mjs.map +1 -1
- package/dist/vitest/index.d.mts +2 -1
- package/dist/vitest/index.mjs +167 -3
- package/dist/vitest/index.mjs.map +1 -1
- package/dist/vitest/mocks/workflow.d.mts +13 -1
- package/dist/vitest/pglite-kysely.d.mts +43 -0
- package/dist/wait-point-invoker-__oE88_P.mjs +148 -0
- package/dist/wait-point-invoker-__oE88_P.mjs.map +1 -0
- package/dist/wait-point-registry-TL99zotw.mjs +47 -0
- package/dist/wait-point-registry-TL99zotw.mjs.map +1 -0
- package/dist/{workspace_resource_pb-DXnO2AT-.mjs → workspace_resource_pb-HNIL_Vfj.mjs} +10 -2
- package/dist/{workspace_resource_pb-DXnO2AT-.mjs.map → workspace_resource_pb-HNIL_Vfj.mjs.map} +1 -1
- package/docs/cli/setup.md +14 -1
- package/docs/cli/tailordb.md +96 -28
- package/docs/cli-reference.md +15 -12
- package/docs/configuration.md +1 -1
- package/docs/github-actions.md +73 -28
- package/docs/migration/v2.md +55 -1
- package/docs/plugin/custom.md +48 -48
- package/docs/plugin/index.md +24 -24
- package/docs/services/auth.md +10 -10
- package/docs/services/executor.md +1 -1
- package/docs/services/resolver.md +2 -2
- package/docs/services/tailordb-migration.md +485 -84
- package/docs/services/tailordb.md +28 -28
- package/docs/services/workflow.md +52 -2
- package/docs/testing.md +14 -0
- package/package.json +12 -7
- package/dist/application-Af1zIqSI.mjs +0 -3
- package/dist/application-D77KJFKD.mjs.map +0 -1
- package/dist/errors-D7583Zz7.mjs +0 -58
- package/dist/errors-D7583Zz7.mjs.map +0 -1
- package/dist/logger-CXQq9YIp.mjs.map +0 -1
- package/dist/register-ts-hook-BU18uU44.mjs.map +0 -1
- package/dist/seed-B-yckgQY.mjs.map +0 -1
- package/dist/service-M7OYziQP.mjs +0 -3
- package/dist/service-k1xy_A5G.mjs.map +0 -1
- package/dist/test-env-key-D7UkZp99.mjs +0 -75
- package/dist/test-env-key-D7UkZp99.mjs.map +0 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { IsAutoFilledDBField, IsReadOnlyDBField } from "./tailordb/types.mjs";
|
|
1
2
|
import { AuthConnectionConfig, AuthConnectionOAuth2Config } from "../../types/auth-connection.generated.mjs";
|
|
2
3
|
import { BuiltinIdP, IDToken, IdProvider, OAuth2ClientInput, OIDC, SAML, SCIMAttribute, SCIMAttributeMapping, SCIMAuthorization, SCIMConfig, SCIMResource, TenantProvider } from "../../types/auth.generated.mjs";
|
|
3
4
|
import { AuthConfig, AuthConnectionTokenResult, AuthExternalConfig, AuthOwnConfig, AuthServiceInput, BeforeLoginClaims, BeforeLoginHookArgs, DefinedAuth, FederatedIdentity, FederatedIdentityClaims, FederatedIdentityProvider, OAuth2ClientGrantType, SCIMAttributeType, UserAttributeKey, UserAttributeListKey, UserAttributes, UsernameFieldKey, ValueOperand } from "./auth/types.mjs";
|
|
@@ -29,7 +30,7 @@ import { Trigger } from "./executor/trigger/index.mjs";
|
|
|
29
30
|
import { createExecutor } from "./executor/executor.mjs";
|
|
30
31
|
import "./executor/index.mjs";
|
|
31
32
|
import { defineWorkflowExecutionPolicies, defineWorkflowExecutionPolicy } from "./workflow/execution-policy.mjs";
|
|
32
|
-
import { WaitPointInstance, createWaitPoint, createWaitPoints } from "./workflow/wait-point.mjs";
|
|
33
|
+
import { ParameterizedWaitPointInstance, WaitPointInstance, createWaitPoint, createWaitPoints } from "./workflow/wait-point.mjs";
|
|
33
34
|
import "./workflow/index.mjs";
|
|
34
35
|
import { defineStaticWebSite } from "./staticwebsite/index.mjs";
|
|
35
36
|
import { defineAIGateway } from "./aigateway/index.mjs";
|
|
@@ -37,4 +38,4 @@ import { defineIdp } from "./idp/index.mjs";
|
|
|
37
38
|
import { defineSecretManager } from "./secrets/index.mjs";
|
|
38
39
|
import { HttpAdapter, HttpAdapterGraphQLQuery, HttpAdapterGraphQLRequest, HttpAdapterGraphQLResponse, HttpAdapterInput, HttpAdapterInputFn, HttpAdapterOutputFn, HttpAdapterRequest, HttpAdapterResponse, HttpAdapterTypedDocumentNode, createHttpAdapter } from "./http-adapter/http-adapter.mjs";
|
|
39
40
|
import "./http-adapter/index.mjs";
|
|
40
|
-
export { type AIGatewayConfig, AuthAccessTokenArgs, AuthAccessTokenIssuedArgs, AuthAccessTokenRefreshedArgs, AuthAccessTokenRevokedArgs, AuthAccessTokenTrigger, type AuthConfig, type AuthConnectionConfig, type AuthConnectionOAuth2Config, type AuthConnectionTokenResult, type AuthExternalConfig, type AuthOwnConfig, type AuthServiceInput, type BeforeLoginClaims, type BeforeLoginHookArgs, type BuiltinIdP, type ConcurrencyPolicy, type DefinedAuth, type ExecutionPolicyConcurrency, type ExecutionPolicyDefInput, type ExecutionPolicyExactInstance, type ExecutionPolicyGroupOptions, type ExecutionPolicyInstance, type ExecutionPolicyWildcardInstance, type ExecutorServiceConfig, type ExecutorServiceInput, type FederatedIdentity, type FederatedIdentityClaims, type FederatedIdentityProvider, FunctionOperation, GqlOperation, HttpAdapter, HttpAdapterGraphQLQuery, HttpAdapterGraphQLRequest, HttpAdapterGraphQLResponse, HttpAdapterInput, HttpAdapterInputFn, HttpAdapterOutputFn, HttpAdapterRequest, HttpAdapterResponse, HttpAdapterTypedDocumentNode, type IDToken, type IdPConfig, type IdPEmailConfig, type IdPExternalConfig, type IdPGqlOperations, type IdPGqlOperationsInput as IdPGqlOperationsConfig, type IdPPermission, type IdPPermissionCondition, type IdProvider as IdProviderConfig, IdpUserArgs, IdpUserCreatedArgs, IdpUserDeletedArgs, IdpUserTrigger, IdpUserUpdatedArgs, IncomingWebhookArgs, IncomingWebhookRequest, IncomingWebhookResponse, IncomingWebhookResponseConfig, IncomingWebhookTrigger, IncomingWebhookTriggerOptions, type OAuth2ClientInput as OAuth2Client, type OAuth2ClientGrantType, type OIDC, Operation, type PermissionCondition, type QueryType, RecordCreatedArgs, RecordDeletedArgs, RecordUpdatedArgs, type ResolvedExecutionPolicyInstance, type Resolver, ResolverExecutedArgs, ResolverExecutedTrigger, type ResolverExternalConfig, type ResolverPermission, type ResolverPermissionCondition, type ResolverPermissionPolicy, type ResolverServiceConfig, type ResolverServiceInput, type RetryPolicy, type SAML, type SCIMAttribute, type SCIMAttributeMapping, type SCIMAttributeType, type SCIMAuthorization, type SCIMConfig, type SCIMResource, ScheduleArgs, ScheduleTrigger, type SecretsConfig, type StaticWebsiteConfig, type TailorAnyDBField, type TailorAnyDBType, type TailorDBField, type TailorDBInstance, TailorDBTrigger, type TailorDBType, type TailorTypeGqlPermission, type TailorTypePermission, type TenantProvider as TenantProviderConfig, Trigger, type UserAttributeKey, type UserAttributeListKey, type UserAttributes, type UsernameFieldKey, type ValueOperand, WaitPointInstance, WebhookOperation, Workflow, WorkflowConfig, WorkflowExecutionArgs, WorkflowExecutionCompletedArgs, WorkflowExecutionResumedArgs, WorkflowExecutionRetriedArgs, WorkflowExecutionStartedArgs, WorkflowExecutionTrigger, WorkflowExecutionWaitResolvedArgs, WorkflowExecutionWaitStartedArgs, WorkflowJob, WorkflowJobContext, WorkflowJobExecutionArgs, WorkflowJobExecutionCompletedArgs, WorkflowJobExecutionStartedArgs, WorkflowJobExecutionTrigger, WorkflowJobExecutionWaitResolvedArgs, WorkflowJobExecutionWaitStartedArgs, WorkflowOperation, type WorkflowServiceConfig, type WorkflowServiceInput, authAccessTokenIssuedTrigger, authAccessTokenRefreshedTrigger, authAccessTokenRevokedTrigger, authAccessTokenTrigger, createExecutor, createHttpAdapter, createResolver, createWaitPoint, createWaitPoints, createWorkflow, createWorkflowJob, db, defineAIGateway, defineAuth, defineIdp, defineSecretManager, defineStaticWebSite, defineWorkflowExecutionPolicies, defineWorkflowExecutionPolicy, idpUserCreatedTrigger, idpUserDeletedTrigger, idpUserTrigger, idpUserUpdatedTrigger, incomingWebhookTrigger, recordCreatedTrigger, recordDeletedTrigger, recordTrigger, recordUpdatedTrigger, resolverExecutedTrigger, scheduleTrigger, unsafeAllowAllGqlPermission, unsafeAllowAllIdPPermission, unsafeAllowAllTypePermission, workflowExecutionCompletedTrigger, workflowExecutionResumedTrigger, workflowExecutionRetriedTrigger, workflowExecutionStartedTrigger, workflowExecutionTrigger, workflowExecutionWaitResolvedTrigger, workflowExecutionWaitStartedTrigger, workflowJobExecutionCompletedTrigger, workflowJobExecutionStartedTrigger, workflowJobExecutionTrigger, workflowJobExecutionWaitResolvedTrigger, workflowJobExecutionWaitStartedTrigger };
|
|
41
|
+
export { type AIGatewayConfig, AuthAccessTokenArgs, AuthAccessTokenIssuedArgs, AuthAccessTokenRefreshedArgs, AuthAccessTokenRevokedArgs, AuthAccessTokenTrigger, type AuthConfig, type AuthConnectionConfig, type AuthConnectionOAuth2Config, type AuthConnectionTokenResult, type AuthExternalConfig, type AuthOwnConfig, type AuthServiceInput, type BeforeLoginClaims, type BeforeLoginHookArgs, type BuiltinIdP, type ConcurrencyPolicy, type DefinedAuth, type ExecutionPolicyConcurrency, type ExecutionPolicyDefInput, type ExecutionPolicyExactInstance, type ExecutionPolicyGroupOptions, type ExecutionPolicyInstance, type ExecutionPolicyWildcardInstance, type ExecutorServiceConfig, type ExecutorServiceInput, type FederatedIdentity, type FederatedIdentityClaims, type FederatedIdentityProvider, FunctionOperation, GqlOperation, HttpAdapter, HttpAdapterGraphQLQuery, HttpAdapterGraphQLRequest, HttpAdapterGraphQLResponse, HttpAdapterInput, HttpAdapterInputFn, HttpAdapterOutputFn, HttpAdapterRequest, HttpAdapterResponse, HttpAdapterTypedDocumentNode, type IDToken, type IdPConfig, type IdPEmailConfig, type IdPExternalConfig, type IdPGqlOperations, type IdPGqlOperationsInput as IdPGqlOperationsConfig, type IdPPermission, type IdPPermissionCondition, type IdProvider as IdProviderConfig, IdpUserArgs, IdpUserCreatedArgs, IdpUserDeletedArgs, IdpUserTrigger, IdpUserUpdatedArgs, IncomingWebhookArgs, IncomingWebhookRequest, IncomingWebhookResponse, IncomingWebhookResponseConfig, IncomingWebhookTrigger, IncomingWebhookTriggerOptions, type IsAutoFilledDBField, type IsReadOnlyDBField, type OAuth2ClientInput as OAuth2Client, type OAuth2ClientGrantType, type OIDC, Operation, ParameterizedWaitPointInstance, type PermissionCondition, type QueryType, RecordCreatedArgs, RecordDeletedArgs, RecordUpdatedArgs, type ResolvedExecutionPolicyInstance, type Resolver, ResolverExecutedArgs, ResolverExecutedTrigger, type ResolverExternalConfig, type ResolverPermission, type ResolverPermissionCondition, type ResolverPermissionPolicy, type ResolverServiceConfig, type ResolverServiceInput, type RetryPolicy, type SAML, type SCIMAttribute, type SCIMAttributeMapping, type SCIMAttributeType, type SCIMAuthorization, type SCIMConfig, type SCIMResource, ScheduleArgs, ScheduleTrigger, type SecretsConfig, type StaticWebsiteConfig, type TailorAnyDBField, type TailorAnyDBType, type TailorDBField, type TailorDBInstance, TailorDBTrigger, type TailorDBType, type TailorTypeGqlPermission, type TailorTypePermission, type TenantProvider as TenantProviderConfig, Trigger, type UserAttributeKey, type UserAttributeListKey, type UserAttributes, type UsernameFieldKey, type ValueOperand, WaitPointInstance, WebhookOperation, Workflow, WorkflowConfig, WorkflowExecutionArgs, WorkflowExecutionCompletedArgs, WorkflowExecutionResumedArgs, WorkflowExecutionRetriedArgs, WorkflowExecutionStartedArgs, WorkflowExecutionTrigger, WorkflowExecutionWaitResolvedArgs, WorkflowExecutionWaitStartedArgs, WorkflowJob, WorkflowJobContext, WorkflowJobExecutionArgs, WorkflowJobExecutionCompletedArgs, WorkflowJobExecutionStartedArgs, WorkflowJobExecutionTrigger, WorkflowJobExecutionWaitResolvedArgs, WorkflowJobExecutionWaitStartedArgs, WorkflowOperation, type WorkflowServiceConfig, type WorkflowServiceInput, authAccessTokenIssuedTrigger, authAccessTokenRefreshedTrigger, authAccessTokenRevokedTrigger, authAccessTokenTrigger, createExecutor, createHttpAdapter, createResolver, createWaitPoint, createWaitPoints, createWorkflow, createWorkflowJob, db, defineAIGateway, defineAuth, defineIdp, defineSecretManager, defineStaticWebSite, defineWorkflowExecutionPolicies, defineWorkflowExecutionPolicy, idpUserCreatedTrigger, idpUserDeletedTrigger, idpUserTrigger, idpUserUpdatedTrigger, incomingWebhookTrigger, recordCreatedTrigger, recordDeletedTrigger, recordTrigger, recordUpdatedTrigger, resolverExecutedTrigger, scheduleTrigger, unsafeAllowAllGqlPermission, unsafeAllowAllIdPPermission, unsafeAllowAllTypePermission, workflowExecutionCompletedTrigger, workflowExecutionResumedTrigger, workflowExecutionRetriedTrigger, workflowExecutionStartedTrigger, workflowExecutionTrigger, workflowExecutionWaitResolvedTrigger, workflowExecutionWaitStartedTrigger, workflowJobExecutionCompletedTrigger, workflowJobExecutionStartedTrigger, workflowJobExecutionTrigger, workflowJobExecutionWaitResolvedTrigger, workflowJobExecutionWaitStartedTrigger };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { IsAutoFilledDBField, IsReadOnlyDBField } from "./types.mjs";
|
|
1
2
|
import { PermissionCondition, TailorTypeGqlPermission, TailorTypePermission, unsafeAllowAllGqlPermission, unsafeAllowAllTypePermission } from "./permission.mjs";
|
|
2
3
|
import { TailorAnyDBField, TailorAnyDBType, TailorDBField, TailorDBInstance, TailorDBType, db } from "./schema.mjs";
|
|
3
|
-
export { type PermissionCondition, type TailorAnyDBField, type TailorAnyDBType, type TailorDBField, type TailorDBInstance, type TailorDBType, type TailorTypeGqlPermission, type TailorTypePermission, db, unsafeAllowAllGqlPermission, unsafeAllowAllTypePermission };
|
|
4
|
+
export { type IsAutoFilledDBField, type IsReadOnlyDBField, type PermissionCondition, type TailorAnyDBField, type TailorAnyDBType, type TailorDBField, type TailorDBInstance, type TailorDBType, type TailorTypeGqlPermission, type TailorTypePermission, db, unsafeAllowAllGqlPermission, unsafeAllowAllTypePermission };
|
|
@@ -123,39 +123,39 @@ type WithDBTypeMetadata<Defined extends DefinedDBTypeMetadata, Key extends keyof
|
|
|
123
123
|
type DBTypeDuplicateInputGuard<Defined extends DefinedDBTypeMetadata, Key extends keyof DefinedDBTypeMetadata, Input, Message extends string> = IsAny<Defined> extends true ? Input : Defined extends Record<Key, unknown> ? TypeLevelError<Message> : Input;
|
|
124
124
|
type DBTypeDuplicateRestGuard<Defined extends DefinedDBTypeMetadata, Key extends keyof DefinedDBTypeMetadata, Input extends unknown[], Message extends string> = IsAny<Defined> extends true ? Input : Defined extends Record<Key, unknown> ? [TypeLevelError<Message>, ...TypeLevelError<Message>[]] : Input;
|
|
125
125
|
type FileKeyConflictError<Fields extends Record<string, TailorAnyDBField>, User extends object> = Partial<Record<keyof output<TailorDBType<Fields, User>> & string, TypeLevelError<"file keys cannot use existing field names">>>;
|
|
126
|
-
type DBFieldDescriptionFn<Defined extends DefinedDBFieldMetadata, Output
|
|
127
|
-
type DBFieldRelationFn<Defined extends DefinedDBFieldMetadata, Output
|
|
128
|
-
<S extends RelationType, T extends TailorAnyDBType>(config: RelationConfig<S, T>): TailorDBField<WithDBFieldRelation<Defined, S>, Output>;
|
|
129
|
-
<S extends RelationSelfConfig>(config: S): TailorDBField<WithDBFieldRelation<Defined, S>, Output>;
|
|
126
|
+
type DBFieldDescriptionFn<Defined extends DefinedDBFieldMetadata, Output, Nested extends Record<string, TailorAnyDBField>> = (description: string) => TailorDBField<WithDBFieldDescription<Defined>, Output, Nested>;
|
|
127
|
+
type DBFieldRelationFn<Defined extends DefinedDBFieldMetadata, Output, Nested extends Record<string, TailorAnyDBField>> = {
|
|
128
|
+
<S extends RelationType, T extends TailorAnyDBType>(config: RelationConfig<S, T>): TailorDBField<WithDBFieldRelation<Defined, S>, Output, Nested>;
|
|
129
|
+
<S extends RelationSelfConfig>(config: S): TailorDBField<WithDBFieldRelation<Defined, S>, Output, Nested>;
|
|
130
130
|
};
|
|
131
|
-
type DBFieldIndexFn<Defined extends DefinedDBFieldMetadata, Output
|
|
132
|
-
type DBFieldUniqueFn<Defined extends DefinedDBFieldMetadata, Output
|
|
133
|
-
type DBFieldVectorFn<Defined extends DefinedDBFieldMetadata, Output
|
|
134
|
-
type DBFieldHooksFn<Defined extends DefinedDBFieldMetadata, Output
|
|
131
|
+
type DBFieldIndexFn<Defined extends DefinedDBFieldMetadata, Output, Nested extends Record<string, TailorAnyDBField>> = () => TailorDBField<WithDBFieldIndex<Defined>, Output, Nested>;
|
|
132
|
+
type DBFieldUniqueFn<Defined extends DefinedDBFieldMetadata, Output, Nested extends Record<string, TailorAnyDBField>> = () => TailorDBField<WithDBFieldUnique<Defined>, Output, Nested>;
|
|
133
|
+
type DBFieldVectorFn<Defined extends DefinedDBFieldMetadata, Output, Nested extends Record<string, TailorAnyDBField>> = () => TailorDBField<WithDBFieldVector<Defined>, Output, Nested>;
|
|
134
|
+
type DBFieldHooksFn<Defined extends DefinedDBFieldMetadata, Output, Nested extends Record<string, TailorAnyDBField>> = <const H extends Hook<Output, Defined extends {
|
|
135
135
|
default: true;
|
|
136
|
-
} ? Output | null | undefined : Output>>(hooks: H) => TailorDBField<WithDBFieldHooks<Defined, H>, Output>;
|
|
137
|
-
type DBFieldValidateFn<Defined extends DefinedDBFieldMetadata, Output
|
|
138
|
-
type DBFieldSerialFn<Defined extends DefinedDBFieldMetadata, Output
|
|
139
|
-
type DBFieldDescriptionMethod<Defined extends DefinedDBFieldMetadata, Output
|
|
136
|
+
} ? Output | null | undefined : Output>>(hooks: H) => TailorDBField<WithDBFieldHooks<Defined, H>, Output, Nested>;
|
|
137
|
+
type DBFieldValidateFn<Defined extends DefinedDBFieldMetadata, Output, Nested extends Record<string, TailorAnyDBField>> = (...validate: FieldValidateInput<Output>[]) => TailorDBField<WithDBFieldValidate<Defined>, Output, Nested>;
|
|
138
|
+
type DBFieldSerialFn<Defined extends DefinedDBFieldMetadata, Output, Nested extends Record<string, TailorAnyDBField>> = (config: SerialConfig<Defined["type"] & ("integer" | "string")>) => TailorDBField<WithDBFieldSerial<Defined>, Output, Nested>;
|
|
139
|
+
type DBFieldDescriptionMethod<Defined extends DefinedDBFieldMetadata, Output, Nested extends Record<string, TailorAnyDBField>> = IsAny<Defined> extends true ? DBFieldDescriptionFn<Defined, Output, Nested> : Defined extends {
|
|
140
140
|
description: unknown;
|
|
141
|
-
} ? TypeLevelError<".description() has already been set"> : DBFieldDescriptionFn<Defined, Output>;
|
|
142
|
-
type DBFieldRelationMethod<Defined extends DefinedDBFieldMetadata, Output
|
|
141
|
+
} ? TypeLevelError<".description() has already been set"> : DBFieldDescriptionFn<Defined, Output, Nested>;
|
|
142
|
+
type DBFieldRelationMethod<Defined extends DefinedDBFieldMetadata, Output, Nested extends Record<string, TailorAnyDBField>> = IsAny<Defined> extends true ? DBFieldRelationFn<Defined, Output, Nested> : Defined extends {
|
|
143
143
|
relation: unknown;
|
|
144
|
-
} ? TypeLevelError<".relation() has already been set"> : DBFieldRelationFn<Defined, Output>;
|
|
144
|
+
} ? TypeLevelError<".relation() has already been set"> : DBFieldRelationFn<Defined, Output, Nested>;
|
|
145
145
|
type DBFieldArrayCheck<A extends boolean, Ok, Msg extends string> = A extends true ? TypeLevelError<Msg> : Ok;
|
|
146
|
-
type DBFieldIndexMethod<Defined extends DefinedDBFieldMetadata, Output
|
|
146
|
+
type DBFieldIndexMethod<Defined extends DefinedDBFieldMetadata, Output, Nested extends Record<string, TailorAnyDBField>> = IsAny<Defined> extends true ? DBFieldIndexFn<Defined, Output, Nested> : Defined extends {
|
|
147
147
|
index: unknown;
|
|
148
|
-
} ? TypeLevelError<".index() has already been set"> : DBFieldArrayCheck<Defined["array"], DBFieldIndexFn<Defined, Output>, "index cannot be set on array fields">;
|
|
149
|
-
type DBFieldUniqueMethod<Defined extends DefinedDBFieldMetadata, Output
|
|
148
|
+
} ? TypeLevelError<".index() has already been set"> : DBFieldArrayCheck<Defined["array"], DBFieldIndexFn<Defined, Output, Nested>, "index cannot be set on array fields">;
|
|
149
|
+
type DBFieldUniqueMethod<Defined extends DefinedDBFieldMetadata, Output, Nested extends Record<string, TailorAnyDBField>> = IsAny<Defined> extends true ? DBFieldUniqueFn<Defined, Output, Nested> : Defined extends {
|
|
150
150
|
unique: unknown;
|
|
151
|
-
} ? TypeLevelError<".unique() has already been set"> : DBFieldArrayCheck<Defined["array"], DBFieldUniqueFn<Defined, Output>, "unique cannot be set on array fields">;
|
|
152
|
-
type DBFieldVectorMethod<Defined extends DefinedDBFieldMetadata, Output
|
|
151
|
+
} ? TypeLevelError<".unique() has already been set"> : DBFieldArrayCheck<Defined["array"], DBFieldUniqueFn<Defined, Output, Nested>, "unique cannot be set on array fields">;
|
|
152
|
+
type DBFieldVectorMethod<Defined extends DefinedDBFieldMetadata, Output, Nested extends Record<string, TailorAnyDBField>> = IsAny<Defined> extends true ? DBFieldVectorFn<Defined, Output, Nested> : Defined extends {
|
|
153
153
|
vector: unknown;
|
|
154
154
|
} ? TypeLevelError<".vector() has already been set"> : Defined extends {
|
|
155
155
|
type: "string";
|
|
156
156
|
array: false;
|
|
157
|
-
} ? DBFieldVectorFn<Defined, Output> : TypeLevelError<"vector can only be set on non-array string fields">;
|
|
158
|
-
type DBFieldHooksMethod<Defined extends DefinedDBFieldMetadata, Output
|
|
157
|
+
} ? DBFieldVectorFn<Defined, Output, Nested> : TypeLevelError<"vector can only be set on non-array string fields">;
|
|
158
|
+
type DBFieldHooksMethod<Defined extends DefinedDBFieldMetadata, Output, Nested extends Record<string, TailorAnyDBField>> = IsAny<Defined> extends true ? DBFieldHooksFn<Defined, Output, Nested> : Defined extends {
|
|
159
159
|
serial: true;
|
|
160
160
|
hooks: {
|
|
161
161
|
create: false;
|
|
@@ -165,35 +165,35 @@ type DBFieldHooksMethod<Defined extends DefinedDBFieldMetadata, Output> = IsAny<
|
|
|
165
165
|
hooks: unknown;
|
|
166
166
|
} ? TypeLevelError<".hooks() has already been set"> : Defined extends {
|
|
167
167
|
type: "nested";
|
|
168
|
-
} ? TypeLevelError<"hooks cannot be set on nested type fields"> : DBFieldHooksFn<Defined, Output>;
|
|
169
|
-
type DBFieldValidateMethod<Defined extends DefinedDBFieldMetadata, Output
|
|
168
|
+
} ? TypeLevelError<"hooks cannot be set on nested type fields"> : DBFieldHooksFn<Defined, Output, Nested>;
|
|
169
|
+
type DBFieldValidateMethod<Defined extends DefinedDBFieldMetadata, Output, Nested extends Record<string, TailorAnyDBField>> = IsAny<Defined> extends true ? DBFieldValidateFn<Defined, Output, Nested> : Defined extends {
|
|
170
170
|
validate: unknown;
|
|
171
|
-
} ? TypeLevelError<".validate() has already been set"> : DBFieldValidateFn<Defined, Output>;
|
|
172
|
-
type DBFieldSerialMethod<Defined extends DefinedDBFieldMetadata, Output
|
|
171
|
+
} ? TypeLevelError<".validate() has already been set"> : DBFieldValidateFn<Defined, Output, Nested>;
|
|
172
|
+
type DBFieldSerialMethod<Defined extends DefinedDBFieldMetadata, Output, Nested extends Record<string, TailorAnyDBField>> = IsAny<Defined> extends true ? DBFieldSerialFn<Defined, Output, Nested> : Defined extends {
|
|
173
173
|
serial: true;
|
|
174
174
|
} ? TypeLevelError<".serial() has already been set"> : Defined extends {
|
|
175
175
|
serial: false;
|
|
176
176
|
} ? TypeLevelError<"serial cannot be set after hooks"> : IsAny<Output> extends true ? Defined extends {
|
|
177
177
|
type: "integer" | "string";
|
|
178
178
|
array: false;
|
|
179
|
-
} ? DBFieldSerialFn<Defined, Output> : TypeLevelError<"serial can only be set on non-array integer or string fields"> : null extends Output ? TypeLevelError<"serial can only be set on non-array integer or string fields"> : Defined extends {
|
|
179
|
+
} ? DBFieldSerialFn<Defined, Output, Nested> : TypeLevelError<"serial can only be set on non-array integer or string fields"> : null extends Output ? TypeLevelError<"serial can only be set on non-array integer or string fields"> : Defined extends {
|
|
180
180
|
type: "integer" | "string";
|
|
181
181
|
array: false;
|
|
182
|
-
} ? DBFieldSerialFn<Defined, Output> : TypeLevelError<"serial can only be set on non-array integer or string fields">;
|
|
183
|
-
type DBFieldDefaultFn<Defined extends DefinedDBFieldMetadata, Output
|
|
184
|
-
type DBFieldDefaultMethod<Defined extends DefinedDBFieldMetadata, Output
|
|
182
|
+
} ? DBFieldSerialFn<Defined, Output, Nested> : TypeLevelError<"serial can only be set on non-array integer or string fields">;
|
|
183
|
+
type DBFieldDefaultFn<Defined extends DefinedDBFieldMetadata, Output, Nested extends Record<string, TailorAnyDBField>> = (value: Output extends null ? NonNullable<Output> : Output) => TailorDBField<WithDBFieldDefault<Defined>, Output, Nested>;
|
|
184
|
+
type DBFieldDefaultMethod<Defined extends DefinedDBFieldMetadata, Output, Nested extends Record<string, TailorAnyDBField>> = IsAny<Defined> extends true ? DBFieldDefaultFn<Defined, Output, Nested> : Defined extends {
|
|
185
185
|
default: unknown;
|
|
186
186
|
} ? TypeLevelError<".default() has already been set"> : Defined extends {
|
|
187
187
|
type: "nested";
|
|
188
188
|
} ? TypeLevelError<"default cannot be set on nested type fields"> : Defined extends {
|
|
189
189
|
serial: true;
|
|
190
|
-
} ? TypeLevelError<"default cannot be set on serial fields"> : null extends Output ? TypeLevelError<"default cannot be set on optional fields"> : DBFieldDefaultFn<Defined, Output>;
|
|
190
|
+
} ? TypeLevelError<"default cannot be set on serial fields"> : null extends Output ? TypeLevelError<"default cannot be set on optional fields"> : DBFieldDefaultFn<Defined, Output, Nested>;
|
|
191
191
|
/**
|
|
192
192
|
* Full TailorDBField interface with builder methods.
|
|
193
193
|
* Extends the minimal structural interface from types/ with fluent API methods.
|
|
194
194
|
*/
|
|
195
|
-
interface TailorDBField<Defined extends DefinedDBFieldMetadata = DefinedDBFieldMetadata, Output = any> extends Omit<TailorDBField$1<Defined, Output>, "fields"> {
|
|
196
|
-
readonly fields:
|
|
195
|
+
interface TailorDBField<Defined extends DefinedDBFieldMetadata = DefinedDBFieldMetadata, Output = any, Nested extends Record<string, TailorAnyDBField> = Record<string, TailorAnyDBField>> extends Omit<TailorDBField$1<Defined, Output, Nested>, "fields"> {
|
|
196
|
+
readonly fields: Nested;
|
|
197
197
|
_metadata: DBFieldMetadata;
|
|
198
198
|
/**
|
|
199
199
|
* Parse and validate a value against this field's validation rules
|
|
@@ -207,23 +207,23 @@ interface TailorDBField<Defined extends DefinedDBFieldMetadata = DefinedDBFieldM
|
|
|
207
207
|
/**
|
|
208
208
|
* Set a description for the field
|
|
209
209
|
*/
|
|
210
|
-
description: DBFieldDescriptionMethod<Defined, Output>;
|
|
210
|
+
description: DBFieldDescriptionMethod<Defined, Output, Nested>;
|
|
211
211
|
/**
|
|
212
212
|
* Define a relation to another type.
|
|
213
213
|
*/
|
|
214
|
-
relation: DBFieldRelationMethod<Defined, Output>;
|
|
214
|
+
relation: DBFieldRelationMethod<Defined, Output, Nested>;
|
|
215
215
|
/**
|
|
216
216
|
* Add an index to the field
|
|
217
217
|
*/
|
|
218
|
-
index: DBFieldIndexMethod<Defined, Output>;
|
|
218
|
+
index: DBFieldIndexMethod<Defined, Output, Nested>;
|
|
219
219
|
/**
|
|
220
220
|
* Make the field unique (also adds an index)
|
|
221
221
|
*/
|
|
222
|
-
unique: DBFieldUniqueMethod<Defined, Output>;
|
|
222
|
+
unique: DBFieldUniqueMethod<Defined, Output, Nested>;
|
|
223
223
|
/**
|
|
224
224
|
* Enable vector search on the field (string type only)
|
|
225
225
|
*/
|
|
226
|
-
vector: DBFieldVectorMethod<Defined, Output>;
|
|
226
|
+
vector: DBFieldVectorMethod<Defined, Output, Nested>;
|
|
227
227
|
/**
|
|
228
228
|
* Set a default value for the field on create. When the field is required,
|
|
229
229
|
* this makes it optional in the Create input — the default fills in when
|
|
@@ -231,11 +231,11 @@ interface TailorDBField<Defined extends DefinedDBFieldMetadata = DefinedDBFieldM
|
|
|
231
231
|
*
|
|
232
232
|
* For datetime/date/time fields, pass `"now"` to use the operation timestamp.
|
|
233
233
|
*/
|
|
234
|
-
default: DBFieldDefaultMethod<Defined, Output>;
|
|
234
|
+
default: DBFieldDefaultMethod<Defined, Output, Nested>;
|
|
235
235
|
/**
|
|
236
236
|
* Add hooks for create/update operations on this field.
|
|
237
237
|
*/
|
|
238
|
-
hooks: DBFieldHooksMethod<Defined, Output>;
|
|
238
|
+
hooks: DBFieldHooksMethod<Defined, Output, Nested>;
|
|
239
239
|
/**
|
|
240
240
|
* Add validation functions to the field.
|
|
241
241
|
*
|
|
@@ -243,16 +243,16 @@ interface TailorDBField<Defined extends DefinedDBFieldMetadata = DefinedDBFieldM
|
|
|
243
243
|
* built-in type validation; they are skipped when built-in validation
|
|
244
244
|
* fails. For array fields, `value` is the complete array.
|
|
245
245
|
*/
|
|
246
|
-
validate: DBFieldValidateMethod<Defined, Output>;
|
|
246
|
+
validate: DBFieldValidateMethod<Defined, Output, Nested>;
|
|
247
247
|
/**
|
|
248
248
|
* Configure serial/auto-increment behavior
|
|
249
249
|
*/
|
|
250
|
-
serial: DBFieldSerialMethod<Defined, Output>;
|
|
250
|
+
serial: DBFieldSerialMethod<Defined, Output, Nested>;
|
|
251
251
|
/**
|
|
252
252
|
* Clone the field with optional overrides for field options.
|
|
253
253
|
* The `array` option cannot change on fields with custom validation.
|
|
254
254
|
*/
|
|
255
|
-
clone<const NewOpt extends DBFieldCloneOptions<Defined>>(options?: NewOpt): TailorDBField<WithDBFieldCloneOptions<Defined, NewOpt>, DBFieldCloneOutput<Output, NewOpt
|
|
255
|
+
clone<const NewOpt extends DBFieldCloneOptions<Defined>>(options?: NewOpt): TailorDBField<WithDBFieldCloneOptions<Defined, NewOpt>, DBFieldCloneOutput<Output, NewOpt>, Nested>;
|
|
256
256
|
}
|
|
257
257
|
/**
|
|
258
258
|
* Full TailorDBType interface with builder methods.
|
|
@@ -404,7 +404,7 @@ declare function object<const F extends Record<string, TailorAnyDBField> & Exclu
|
|
|
404
404
|
array: Opt extends {
|
|
405
405
|
array: true;
|
|
406
406
|
} ? true : false;
|
|
407
|
-
}, FieldOutput<InferFieldsOutput<F>, Opt
|
|
407
|
+
}, FieldOutput<InferFieldsOutput<F>, Opt>, F>;
|
|
408
408
|
declare const idField: TailorDBFieldInstance<"uuid", FieldOptions, string>;
|
|
409
409
|
type idField = typeof idField;
|
|
410
410
|
type DBTable<F extends {
|
|
@@ -470,7 +470,7 @@ declare const db: {
|
|
|
470
470
|
* });
|
|
471
471
|
*/
|
|
472
472
|
timestamps: () => {
|
|
473
|
-
createdAt: TailorDBField<WithDBFieldDescription<WithDBFieldDefault<DBFieldDefined<"datetime", FieldOptions>>>, string | Date
|
|
473
|
+
createdAt: TailorDBField<WithDBFieldDescription<WithDBFieldDefault<DBFieldDefined<"datetime", FieldOptions>>>, string | Date, Record<string, TailorAnyDBField>>;
|
|
474
474
|
updatedAt: TailorDBField<WithDBFieldDescription<WithDBFieldHooks<WithDBFieldDefault<DBFieldDefined<"datetime", FieldOptions>>, {
|
|
475
475
|
readonly update: ({ input, now }: {
|
|
476
476
|
input: string | Date | null;
|
|
@@ -478,7 +478,7 @@ declare const db: {
|
|
|
478
478
|
invoker: TailorPrincipal | null;
|
|
479
479
|
now: Date;
|
|
480
480
|
}) => string | Date;
|
|
481
|
-
}>>, string | Date
|
|
481
|
+
}>>, string | Date, Record<string, TailorAnyDBField>>;
|
|
482
482
|
};
|
|
483
483
|
};
|
|
484
484
|
};
|
|
@@ -76,11 +76,11 @@ interface TailorDBTypeMetadata {
|
|
|
76
76
|
* The full interface with builder methods (relation, index, unique, hooks, validate, etc.)
|
|
77
77
|
* is defined in configure/services/tailordb/schema.ts.
|
|
78
78
|
*/
|
|
79
|
-
interface TailorDBField<Defined extends DefinedDBFieldMetadata = DefinedDBFieldMetadata, Output = any> extends Omit<TailorField<Defined, Output, DBFieldMetadata, Defined["type"]>, "fields"> {
|
|
80
|
-
readonly fields:
|
|
79
|
+
interface TailorDBField<Defined extends DefinedDBFieldMetadata = DefinedDBFieldMetadata, Output = any, Nested extends Record<string, TailorAnyDBField> = Record<string, TailorAnyDBField>> extends Omit<TailorField<Defined, Output, DBFieldMetadata, Defined["type"]>, "fields"> {
|
|
80
|
+
readonly fields: Nested;
|
|
81
81
|
readonly rawRelation: Readonly<RawRelationConfig> | undefined;
|
|
82
82
|
}
|
|
83
|
-
type TailorAnyDBField = TailorDBField<any, any>;
|
|
83
|
+
type TailorAnyDBField = TailorDBField<any, any, any>;
|
|
84
84
|
/**
|
|
85
85
|
* Minimal structural interface for TailorDBType.
|
|
86
86
|
* Defines only the properties needed by parser, plugin, cli, and types layers.
|
|
@@ -134,6 +134,32 @@ type TypeHook<F extends Record<string, TailorAnyDBField>> = {
|
|
|
134
134
|
create?: TypeCreateHookFn<F>;
|
|
135
135
|
update?: TypeUpdateHookFn<F>;
|
|
136
136
|
};
|
|
137
|
+
/**
|
|
138
|
+
* `true` when callers can never write this field — a field defined with `.serial()`,
|
|
139
|
+
* whose value the platform assigns.
|
|
140
|
+
*
|
|
141
|
+
* Use this to keep such fields out of create and update inputs derived from a field
|
|
142
|
+
* collection. `output<F>` alone cannot express it: the field reads back as
|
|
143
|
+
* non-nullable even though the caller never writes it.
|
|
144
|
+
*/
|
|
145
|
+
type IsReadOnlyDBField<F extends TailorAnyDBField> = F["_defined"] extends {
|
|
146
|
+
serial: true;
|
|
147
|
+
} ? true : false;
|
|
148
|
+
/**
|
|
149
|
+
* `true` when callers may omit this field on create and the platform fills it in — a
|
|
150
|
+
* field defined with `.default()` or `.hooks({ create })`.
|
|
151
|
+
*
|
|
152
|
+
* Use this to make such fields optional in create inputs derived from a field
|
|
153
|
+
* collection. `output<F>` alone cannot express it: the field reads back as
|
|
154
|
+
* non-nullable once created, yet supplying it on create is optional.
|
|
155
|
+
*/
|
|
156
|
+
type IsAutoFilledDBField<F extends TailorAnyDBField> = F["_defined"] extends {
|
|
157
|
+
default: true;
|
|
158
|
+
} | {
|
|
159
|
+
hooks: {
|
|
160
|
+
create: true;
|
|
161
|
+
};
|
|
162
|
+
} ? true : false;
|
|
137
163
|
type ExcludeNestedDBFields<T extends Record<string, TailorAnyDBField>> = { [K in keyof T]: T[K] extends TailorDBField<{
|
|
138
164
|
type: "nested";
|
|
139
165
|
array: boolean;
|
|
@@ -195,4 +221,4 @@ type TailorDBServiceInput = {
|
|
|
195
221
|
[namespace: string]: TailorDBServiceConfigInput | TailorDBExternalConfig;
|
|
196
222
|
};
|
|
197
223
|
//#endregion
|
|
198
|
-
export { DBFieldMetadata, DefinedDBFieldMetadata, ExcludeDefaultedDBFields, ExcludeHookedDBFields, ExcludeNestedDBFields, GqlOperationsConfig, Hook, IndexDef, PluginAttachment, RawRelationConfig, RelationType, SerialConfig, TailorAnyDBField, TailorAnyDBType, TailorDBExternalConfig, TailorDBField, TailorDBInstance, TailorDBServiceInput, TailorDBType, TailorDBTypeMetadata, TypeFeatures, TypeHook, TypeValidateFn };
|
|
224
|
+
export { DBFieldMetadata, DefinedDBFieldMetadata, ExcludeDefaultedDBFields, ExcludeHookedDBFields, ExcludeNestedDBFields, GqlOperationsConfig, Hook, IndexDef, IsAutoFilledDBField, IsReadOnlyDBField, PluginAttachment, RawRelationConfig, RelationType, SerialConfig, TailorAnyDBField, TailorAnyDBType, TailorDBExternalConfig, TailorDBField, TailorDBInstance, TailorDBServiceInput, TailorDBType, TailorDBTypeMetadata, TypeFeatures, TypeHook, TypeValidateFn };
|
|
@@ -4,6 +4,6 @@ import { ConcurrencyPolicy, RetryPolicy } from "../../../types/workflow.generate
|
|
|
4
4
|
import { WorkflowJob, WorkflowJobContext, createWorkflowJob } from "./job.mjs";
|
|
5
5
|
import { Workflow, WorkflowConfig, createWorkflow } from "./workflow.mjs";
|
|
6
6
|
import { defineWorkflowExecutionPolicies, defineWorkflowExecutionPolicy } from "./execution-policy.mjs";
|
|
7
|
-
import { WaitPointInstance, createWaitPoint, createWaitPoints } from "./wait-point.mjs";
|
|
7
|
+
import { ParameterizedWaitPointInstance, WaitPointInstance, createWaitPoint, createWaitPoints } from "./wait-point.mjs";
|
|
8
8
|
import "./types.mjs";
|
|
9
|
-
export { type ConcurrencyPolicy, type ExecutionPolicyConcurrency, type ExecutionPolicyDefInput, type ExecutionPolicyExactInstance, type ExecutionPolicyGroupOptions, type ExecutionPolicyInstance, type ExecutionPolicyWildcardInstance, type ResolvedExecutionPolicyInstance, type RetryPolicy, WaitPointInstance, Workflow, WorkflowConfig, WorkflowJob, WorkflowJobContext, type WorkflowServiceConfig, type WorkflowServiceInput, createWaitPoint, createWaitPoints, createWorkflow, createWorkflowJob, defineWorkflowExecutionPolicies, defineWorkflowExecutionPolicy };
|
|
9
|
+
export { type ConcurrencyPolicy, type ExecutionPolicyConcurrency, type ExecutionPolicyDefInput, type ExecutionPolicyExactInstance, type ExecutionPolicyGroupOptions, type ExecutionPolicyInstance, type ExecutionPolicyWildcardInstance, ParameterizedWaitPointInstance, type ResolvedExecutionPolicyInstance, type RetryPolicy, WaitPointInstance, Workflow, WorkflowConfig, WorkflowJob, WorkflowJobContext, type WorkflowServiceConfig, type WorkflowServiceInput, createWaitPoint, createWaitPoints, createWorkflow, createWorkflowJob, defineWorkflowExecutionPolicies, defineWorkflowExecutionPolicy };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { JsonCompatible, TypeLevelError } from "../../../types/helpers.mjs";
|
|
1
|
+
import { JsonCompatible, Prettify, TypeLevelError } from "../../../types/helpers.mjs";
|
|
2
2
|
//#region src/configure/services/workflow/wait-point.d.ts
|
|
3
3
|
/**
|
|
4
4
|
* A single wait point instance with typed `.wait()` and `.resolve()` methods.
|
|
@@ -14,24 +14,79 @@ interface WaitPointInstance<Payload = undefined, Result = undefined> {
|
|
|
14
14
|
resolve: (executionId: string, callback: (payload: [Payload] extends [undefined] ? undefined : Payload) => Result | Promise<Result>) => Promise<void>;
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
17
|
+
* A wait point whose key carries `$params`, so the runtime key is built per call.
|
|
18
|
+
*
|
|
19
|
+
* `.with(params)` substitutes the params into the declared key and returns the
|
|
20
|
+
* same two-method surface as an unparameterized wait point.
|
|
21
|
+
*/
|
|
22
|
+
interface ParameterizedWaitPointInstance<Params extends object, Payload = undefined, Result = undefined> {
|
|
23
|
+
/**
|
|
24
|
+
* Bind runtime values to the key's `$params`.
|
|
25
|
+
* @param params - One value per `$param` in the declared key
|
|
26
|
+
* @returns A wait point bound to the resulting key
|
|
27
|
+
* @throws If a param value is empty, contains characters outside `[a-z0-9-]`,
|
|
28
|
+
* starts or ends with `-`, or makes the resulting key exceed 63 characters
|
|
29
|
+
*/
|
|
30
|
+
with(params: Params): WaitPointInstance<Payload, Result>;
|
|
31
|
+
}
|
|
32
|
+
type NonEmptyString = `${string & {}}${string}`;
|
|
33
|
+
type KeySegments<Key extends string> = Key extends `${infer Head}-${infer Tail}` ? Head | KeySegments<Tail> : Key;
|
|
34
|
+
type KeySegmentList<Key extends string> = Key extends `${infer Head}-${infer Tail}` ? [Head, ...KeySegmentList<Tail>] : [Key];
|
|
35
|
+
type ParamSegments<Key extends string> = Extract<KeySegments<Key>, `$${NonEmptyString}`>;
|
|
36
|
+
type ParamName<Segment extends string> = Segment extends `$${infer Name}` ? Name : never;
|
|
37
|
+
type KeyParams<Key extends string> = [ParamSegments<Key>] extends [never] ? undefined : Prettify<{ [Name in ParamName<ParamSegments<Key>>]: string; }>;
|
|
38
|
+
type HasLiteralSegment<Segments extends readonly string[]> = Segments extends readonly [infer Head extends string, ...infer Tail extends readonly string[]] ? Head extends `$${string}` ? HasLiteralSegment<Tail> : true : false;
|
|
39
|
+
type HasDuplicateParam<Segments extends readonly string[]> = Segments extends readonly [infer Head extends string, ...infer Tail extends readonly string[]] ? Head extends `$${string}` ? Head extends Tail[number] ? true : HasDuplicateParam<Tail> : HasDuplicateParam<Tail> : false;
|
|
40
|
+
/**
|
|
41
|
+
* Resolves to `Instance` when both `Payload` and `Result` are JsonValue-compatible,
|
|
19
42
|
* or to a type-level error that surfaces at the call site.
|
|
20
43
|
*/
|
|
21
|
-
type
|
|
44
|
+
type ValidatedWaitPoint<Payload, Result, Instance> = [null] extends [Payload] ? TypeLevelError<"Payload cannot be null at the top level"> : [undefined] extends [Result] ? TypeLevelError<"Result cannot be (or include) undefined (resolve callback must return a value)"> : [Payload] extends [undefined] ? [Result] extends [JsonCompatible<Result>] ? Instance : TypeLevelError<"Result must be JsonValue-compatible (plain objects/arrays; no class instances or functions)"> : [undefined] extends [Payload] ? TypeLevelError<"Payload cannot include undefined at the top level"> : [Payload] extends [JsonCompatible<Payload>] ? [Result] extends [JsonCompatible<Result>] ? Instance : TypeLevelError<"Result must be JsonValue-compatible (plain objects/arrays; no class instances or functions)"> : TypeLevelError<"Payload must be JsonValue-compatible (plain objects/arrays; no class instances or functions)">;
|
|
45
|
+
/**
|
|
46
|
+
* The type produced by `define<Payload, Result>()` (the no-key form inside `createWaitPoints`).
|
|
47
|
+
*/
|
|
48
|
+
type WaitPointDef<Payload, Result> = ValidatedWaitPoint<Payload, Result, WaitPointInstance<Payload, Result>>;
|
|
49
|
+
/**
|
|
50
|
+
* The type produced by `define(key)<Payload, Result>()`. Keys containing
|
|
51
|
+
* `$params` resolve to a {@link ParameterizedWaitPointInstance}; plain keys
|
|
52
|
+
* resolve to a {@link WaitPointInstance}, so the same call shape covers both.
|
|
53
|
+
*/
|
|
54
|
+
type WaitPointKeyDef<Key extends string, Payload, Result> = string extends Key ? TypeLevelError<"Wait point key must be a string literal"> : HasDuplicateParam<KeySegmentList<Key>> extends true ? TypeLevelError<"Wait point key repeats a $param name"> : HasLiteralSegment<KeySegmentList<Key>> extends false ? TypeLevelError<"Wait point key needs at least one literal segment alongside its $params"> : [KeyParams<Key>] extends [undefined] ? ValidatedWaitPoint<Payload, Result, WaitPointInstance<Payload, Result>> : KeyParams<Key> extends (infer Params extends object) ? ValidatedWaitPoint<Payload, Result, ParameterizedWaitPointInstance<Params, Payload, Result>> : never;
|
|
55
|
+
/**
|
|
56
|
+
* The factory returned when a key is passed before the type arguments.
|
|
57
|
+
* Calling it yields the wait point the key describes.
|
|
58
|
+
*/
|
|
59
|
+
type WaitPointFactory<Key extends string> = <Payload = undefined, Result = undefined>() => WaitPointKeyDef<Key, Payload, Result>;
|
|
22
60
|
/**
|
|
23
61
|
* The `define` function passed to the `createWaitPoints` builder callback.
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
62
|
+
*
|
|
63
|
+
* Called with no arguments, the property name becomes the key. Called with a
|
|
64
|
+
* key, that key is used verbatim — and any `$params` in it become the argument
|
|
65
|
+
* of `.with()`. The key comes first so TypeScript can infer it as a literal;
|
|
66
|
+
* `Payload` / `Result` follow on the returned factory.
|
|
27
67
|
*
|
|
28
68
|
* JSON validation is encoded in the return type rather than in type-parameter
|
|
29
69
|
* constraints, because tsgo rejects self-referential constraints like
|
|
30
70
|
* `Payload extends JsonCompatible<Payload>` as circular.
|
|
31
71
|
*/
|
|
32
|
-
type DefineFn =
|
|
72
|
+
type DefineFn = {
|
|
73
|
+
<Payload = undefined, Result = undefined>(): WaitPointDef<Payload, Result>;
|
|
74
|
+
/**
|
|
75
|
+
* Use a key of your own instead of the property name — the only way to give
|
|
76
|
+
* a key `$params`, since the key has to be read as a literal type and giving
|
|
77
|
+
* `Payload` / `Result` explicitly would stop that.
|
|
78
|
+
* @param key - The wait point key
|
|
79
|
+
* @returns A factory taking the type arguments
|
|
80
|
+
*/
|
|
81
|
+
for<const Key extends string>(key: Key): WaitPointFactory<Key>;
|
|
82
|
+
};
|
|
33
83
|
/**
|
|
34
|
-
* Create a single typed wait point with
|
|
84
|
+
* Create a single typed wait point with a fixed key.
|
|
85
|
+
*
|
|
86
|
+
* The key must match `[a-z0-9-]` (3-63 characters, starting and ending with
|
|
87
|
+
* `[a-z0-9]`), which `deploy` reports on. For a key with `$params`, use
|
|
88
|
+
* {@link createWaitPoints}: binding params needs the key inferred as a literal
|
|
89
|
+
* type, which only its `define` offers.
|
|
35
90
|
*
|
|
36
91
|
* `Payload` and `Result` must be JsonValue-compatible.
|
|
37
92
|
* Functions and objects with a `toJSON` method are rejected at the type level;
|
|
@@ -46,7 +101,9 @@ type DefineFn = <Payload = undefined, Result = undefined>() => WaitPointDef<Payl
|
|
|
46
101
|
declare function createWaitPoint<Payload = undefined, Result = undefined>(key: string): WaitPointDef<Payload, Result>;
|
|
47
102
|
/**
|
|
48
103
|
* Create a group of typed wait points for human-in-the-loop workflows.
|
|
49
|
-
* Property names become the wait point keys
|
|
104
|
+
* Property names become the wait point keys, so they must match
|
|
105
|
+
* `[a-z0-9-]`, which `deploy` reports on — pass an explicit key to `define`
|
|
106
|
+
* when they do not.
|
|
50
107
|
*
|
|
51
108
|
* The return type is the same as the builder's return type, so JSDoc on each
|
|
52
109
|
* property is preserved and visible in IDE autocompletion.
|
|
@@ -60,13 +117,15 @@ declare function createWaitPoint<Payload = undefined, Result = undefined>(key: s
|
|
|
60
117
|
* export const waitPoints = createWaitPoints(define => ({
|
|
61
118
|
* // Preceding JSDoc on this property is shown in IDE autocompletion
|
|
62
119
|
* approval: define<{ message: string }, { approved: boolean }>(),
|
|
120
|
+
* // A key with $params is bound per call through `.with()`
|
|
121
|
+
* lineApproval: define.for("line-approval-$lineId")<{ message: string }, { approved: boolean }>(),
|
|
63
122
|
* }));
|
|
64
123
|
*
|
|
65
|
-
* // IDE shows the JSDoc when typing `waitPoints.`
|
|
66
124
|
* await waitPoints.approval.wait({ message: "Please approve" });
|
|
125
|
+
* await waitPoints.lineApproval.with({ lineId: line.id }).wait({ message: "Please approve" });
|
|
67
126
|
*
|
|
68
127
|
* // For 2-level access, use destructured export with JSDoc attached to the export itself.
|
|
69
128
|
*/
|
|
70
|
-
declare function createWaitPoints<T extends Record<string, WaitPointInstance<any, any>>>(builder: (define: DefineFn) => T): T;
|
|
129
|
+
declare function createWaitPoints<T extends Record<string, WaitPointInstance<any, any> | ParameterizedWaitPointInstance<any, any, any>>>(builder: (define: DefineFn) => T): T;
|
|
71
130
|
//#endregion
|
|
72
|
-
export { WaitPointInstance, createWaitPoint, createWaitPoints };
|
|
131
|
+
export { ParameterizedWaitPointInstance, WaitPointInstance, createWaitPoint, createWaitPoints };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as logger } from "./logger-
|
|
1
|
+
import { n as logger } from "./logger-DSdExfor.mjs";
|
|
2
2
|
import { t as readPackageJson } from "./package-json-8b0O9TlX.mjs";
|
|
3
3
|
import { n as userAgentFromVersion } from "./user-agent-Bgsszb5I.mjs";
|
|
4
4
|
import { r as writeSecretFile, t as ensureSecretDir } from "./secret-file-C3J4Gy8r.mjs";
|
|
@@ -420,4 +420,4 @@ function initCrashReporting() {
|
|
|
420
420
|
|
|
421
421
|
//#endregion
|
|
422
422
|
export { JSON_FOOTER_MARKER as a, CRASH_LOG_EXTENSION as i, reportCrash as n, parseCrashReportConfig as o, sendCrashReport as r, initCrashReporting as t };
|
|
423
|
-
//# sourceMappingURL=crashreport-
|
|
423
|
+
//# sourceMappingURL=crashreport-CIIfLnoO.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crashreport-B5LqCTfF.mjs","names":[],"sources":["../src/cli/crashreport/config.ts","../src/cli/crashreport/writer.ts","../src/cli/crashreport/sender.ts","../src/cli/crashreport/sanitize.ts","../src/cli/crashreport/report.ts","../src/cli/crashreport/index.ts"],"sourcesContent":["import * as path from \"pathe\";\nimport { isCI } from \"std-env\";\nimport { xdgConfig } from \"xdg-basedir\";\n\nexport interface CrashReportConfig {\n readonly localEnabled: boolean;\n readonly remoteEnabled: boolean;\n readonly localDir: string;\n}\n\n/**\n * Parse crash report configuration from environment variables.\n * Local crash log writing is enabled by default (opt-out via TAILOR_CRASH_REPORTS_LOCAL=off).\n * Remote sending is disabled by default (opt-in via TAILOR_CRASH_REPORTS_REMOTE=on).\n * Both are auto-disabled in CI environments.\n * @returns Crash report configuration\n */\nexport function parseCrashReportConfig(): CrashReportConfig {\n if (isCI) {\n return {\n localEnabled: false,\n remoteEnabled: false,\n localDir: \"\",\n };\n }\n\n const localEnabled = (process.env.TAILOR_CRASH_REPORTS_LOCAL ?? \"on\").toLowerCase() !== \"off\";\n const remoteEnabled = (process.env.TAILOR_CRASH_REPORTS_REMOTE ?? \"off\").toLowerCase() === \"on\";\n const localDir = xdgConfig ? path.join(xdgConfig, \"tailor-platform\", \"crash-reports\") : \"\";\n\n return {\n localEnabled: localEnabled && localDir !== \"\",\n remoteEnabled,\n localDir,\n };\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"pathe\";\nimport { ensureSecretDir, writeSecretFile } from \"#/cli/shared/secret-file\";\nimport type { CrashReport } from \"./report\";\n\nconst MAX_CRASH_FILES = 10;\n\n/** Marker line that separates human-readable content from the JSON footer. */\nexport const JSON_FOOTER_MARKER = \"--- JSON ---\";\n\n/** File extension for crash log files. */\nexport const CRASH_LOG_EXTENSION = \".crash.log\";\n\n/**\n * Format a CrashReport as human-readable text for local crash log files.\n * @param report - Crash report to format\n * @returns Formatted text content\n */\nexport function formatCrashReport(report: CrashReport): string {\n const lines = [\n `Crash Report: ${report.id}`,\n `Timestamp: ${report.timestamp}`,\n `Error Type: ${report.errorType}`,\n \"\",\n \"--- Environment ---\",\n `SDK Version: ${report.sdkVersion}`,\n `Node Version: ${report.nodeVersion}`,\n `OS: ${report.osPlatform} ${report.osRelease}`,\n `Arch: ${report.arch}`,\n \"\",\n \"--- Command ---\",\n `Command: ${report.command}`,\n `Arguments: ${JSON.stringify(report.argv)}`,\n \"\",\n \"--- Error ---\",\n `Name: ${report.errorName}`,\n `Message: ${report.errorMessage}`,\n \"\",\n \"--- Stack Trace ---\",\n report.stackTrace || \"(no stack trace available)\",\n \"\",\n JSON_FOOTER_MARKER,\n JSON.stringify(report),\n \"\",\n ];\n return lines.join(\"\\n\");\n}\n\n/**\n * Generate a filename for a crash log file.\n * Format: {timestamp}-{shortId}.crash.log\n * @param report - Crash report to generate filename for\n * @returns Filename string\n */\nfunction generateFilename(report: CrashReport): string {\n const safeTimestamp = report.timestamp.replace(/[:.]/g, \"-\");\n const shortId = report.id.slice(0, 8);\n return `${safeTimestamp}-${shortId}${CRASH_LOG_EXTENSION}`;\n}\n\n/**\n * Remove old crash log files, keeping only the most recent ones.\n * @param dir - Crash log directory\n */\nfunction cleanupOldFiles(dir: string): void {\n try {\n const files = fs\n .readdirSync(dir)\n .filter((f) => f.endsWith(CRASH_LOG_EXTENSION))\n .toSorted()\n .toReversed();\n\n for (const file of files.slice(MAX_CRASH_FILES)) {\n fs.unlinkSync(path.join(dir, file));\n }\n } catch {\n // Best-effort cleanup, ignore errors\n }\n}\n\n/**\n * Write a crash report to a local file.\n * Creates the directory if it doesn't exist. Keeps only the last 10 crash files.\n * Never throws - returns the file path on success or undefined on failure.\n * @param report - Crash report to write\n * @param dir - Directory to write the crash log file to\n * @returns File path on success, undefined on failure\n */\nexport function writeCrashReport(report: CrashReport, dir: string): string | undefined {\n try {\n ensureSecretDir(dir);\n\n const filename = generateFilename(report);\n const filePath = path.join(dir, filename);\n const content = formatCrashReport(report);\n\n writeSecretFile(filePath, content);\n cleanupOldFiles(dir);\n\n return filePath;\n } catch {\n return undefined;\n }\n}\n","import type { CrashReport } from \"./report\";\n\nconst SEND_TIMEOUT_MS = 5000;\nconst PRODUCTION_ENDPOINT = \"https://sdk-error-tracking-926vh9t4cl.erp.dev/query\";\n\nconst SUBMIT_MUTATION = `\nmutation SubmitCrashReport(\n $id: String!\n $timestamp: String!\n $sdkVersion: String!\n $nodeVersion: String!\n $osPlatform: String!\n $osRelease: String!\n $arch: String!\n $command: String!\n $argv: [String]\n $errorName: String!\n $errorMessage: String!\n $stackTrace: String\n $errorType: String!\n $userId: String\n $userEmail: String\n) {\n submitCrashReport(\n id: $id\n timestamp: $timestamp\n sdkVersion: $sdkVersion\n nodeVersion: $nodeVersion\n osPlatform: $osPlatform\n osRelease: $osRelease\n arch: $arch\n command: $command\n argv: $argv\n errorName: $errorName\n errorMessage: $errorMessage\n stackTrace: $stackTrace\n errorType: $errorType\n userId: $userId\n userEmail: $userEmail\n ) {\n success\n }\n}`;\n\n/**\n * Send a crash report to the remote endpoint via GraphQL mutation.\n * Best-effort: never throws, returns boolean success.\n * @param report - Crash report to send\n * @param ua - User-Agent header value\n * @returns true if the request succeeded, false otherwise\n */\nexport async function sendCrashReport(report: CrashReport, ua: string): Promise<boolean> {\n try {\n const endpoint = process.env.TAILOR_CRASH_REPORT_ENDPOINT || PRODUCTION_ENDPOINT;\n const response = await fetch(endpoint, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"User-Agent\": ua,\n },\n body: JSON.stringify({\n query: SUBMIT_MUTATION,\n variables: report,\n }),\n signal: AbortSignal.timeout(SEND_TIMEOUT_MS),\n });\n\n if (!response.ok) return false;\n\n const data = (await response.json()) as {\n errors?: unknown[];\n data?: { submitCrashReport: { success: boolean } };\n };\n if (data.errors?.length) return false;\n return data.data?.submitCrashReport.success === true;\n } catch {\n return false;\n }\n}\n","import * as os from \"node:os\";\n\nconst HOME_DIR = os.homedir();\n\n// Patterns for sanitization (global variants for use with .replace())\nconst UUID_PATTERN = /\\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\\b/gi;\nconst LONG_HEX_PATTERN = /\\b[0-9a-fA-F]{32,}\\b/g;\nconst EMAIL_PATTERN = /\\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}\\b/g;\nconst ABSOLUTE_PATH_PATTERN = /(?:\\/(?:[\\w.@\\- ]+\\/)+[\\w.@\\- ]+)/g;\nconst WINDOWS_PATH_PATTERN = /(?:[A-Za-z]:\\\\(?:[\\w.@\\- ]+\\\\)+[\\w.@\\- ]+)/g;\nconst URL_QUERY_PATTERN = /[?&][^?\\s]*/g;\n\n// Non-global variants for single-match .test() calls (avoids lastIndex state issues)\nconst EMAIL_TEST_PATTERN = /\\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}\\b/;\nconst WINDOWS_DRIVE_TEST_PATTERN = /^[A-Za-z]:\\\\/;\n\n// SDK package path marker for relative paths\nconst SDK_PACKAGE_MARKER = \"packages/sdk/\";\n\nfunction lastSegment(filePath: string, separator: string): string {\n return filePath.split(separator).pop() ?? filePath;\n}\n\n/**\n * Sanitize a stack trace by replacing absolute paths with relative SDK paths.\n * External paths are replaced with `<external>/filename.ext`.\n * Home directories are replaced with `~/<redacted>/`.\n * @param stack - Raw stack trace string\n * @returns Sanitized stack trace\n */\nexport function sanitizeStackTrace(stack: string): string {\n // V8 stack traces start with \"ErrorType: message\\n at ...\".\n // The error message may span multiple lines before the first \" at \" frame.\n // Apply message sanitization to all message lines so secrets embedded in\n // multiline error messages are redacted consistently with errorMessage.\n const firstFrameIndex = stack.search(/\\n\\s+at /);\n let result: string;\n if (firstFrameIndex !== -1) {\n result = sanitizeMessage(stack.slice(0, firstFrameIndex)) + stack.slice(firstFrameIndex);\n } else {\n result = sanitizeMessage(stack);\n }\n\n result = result.replace(ABSOLUTE_PATH_PATTERN, (match) => {\n const sdkIndex = match.indexOf(SDK_PACKAGE_MARKER);\n if (sdkIndex !== -1) {\n return match.slice(sdkIndex);\n }\n\n if (match.startsWith(HOME_DIR)) {\n return `~/<redacted>/${lastSegment(match, \"/\")}`;\n }\n\n return `<external>/${lastSegment(match, \"/\")}`;\n });\n result = result.replace(WINDOWS_PATH_PATTERN, (match) => {\n const normalized = match.replace(/\\\\/g, \"/\");\n const sdkIndex = normalized.indexOf(SDK_PACKAGE_MARKER);\n if (sdkIndex !== -1) {\n return normalized.slice(sdkIndex);\n }\n return `<external>/${lastSegment(match, \"\\\\\")}`;\n });\n return result;\n}\n\n/**\n * Sanitize an error message by redacting sensitive information.\n * Redacts: UUIDs, long hex tokens, email addresses, absolute paths, URL query strings.\n * @param message - Raw error message\n * @returns Sanitized error message\n */\nexport function sanitizeMessage(message: string): string {\n let result = message;\n // Strip serialized request/response bodies that may contain secrets\n result = result.replace(/\\nRequest:\\s*[\\s\\S]*$/, \"\\nRequest: <redacted>\");\n result = result.replace(UUID_PATTERN, \"<uuid>\");\n result = result.replace(LONG_HEX_PATTERN, \"<redacted>\");\n result = result.replace(EMAIL_PATTERN, \"<email>\");\n result = result.replace(URL_QUERY_PATTERN, \"?<redacted>\");\n result = result.replace(ABSOLUTE_PATH_PATTERN, (match) => `<path>/${lastSegment(match, \"/\")}`);\n result = result.replace(WINDOWS_PATH_PATTERN, (match) => `<path>/${lastSegment(match, \"\\\\\")}`);\n\n return result;\n}\n\n/**\n * Sanitize process.argv by keeping command/subcommand names and redacting\n * values of sensitive flags.\n * @param argv - Raw process.argv array\n * @returns Sanitized argv array\n */\nexport function sanitizeArgv(argv: string[]): string[] {\n const result: string[] = [];\n let redactNext = false;\n\n for (const arg of argv) {\n if (redactNext) {\n // If the next token is itself a flag, treat it as a new flag rather\n // than consuming it as the previous flag's value. This avoids leaking\n // the *next* flag's value (e.g., `--verbose --workspace-id secret`\n // would otherwise expose `secret`).\n if (!arg.startsWith(\"-\")) {\n result.push(\"<redacted>\");\n redactNext = false;\n continue;\n }\n redactNext = false;\n }\n\n if (arg.startsWith(\"-\")) {\n // --flag=value: keep flag name, redact value\n const eqIndex = arg.indexOf(\"=\");\n if (eqIndex !== -1) {\n result.push(`${arg.slice(0, eqIndex)}=<redacted>`);\n continue;\n }\n\n // --flag / -f: keep flag name, redact next arg as its value\n result.push(arg);\n redactNext = true;\n continue;\n }\n\n // Redact absolute paths\n if (arg.startsWith(\"/\") && arg.includes(\"/\", 1)) {\n result.push(\"<path>\");\n continue;\n }\n\n // Redact Windows-style absolute paths\n if (WINDOWS_DRIVE_TEST_PATTERN.test(arg)) {\n result.push(\"<path>\");\n continue;\n }\n\n // Redact email addresses\n if (EMAIL_TEST_PATTERN.test(arg)) {\n result.push(\"<email>\");\n continue;\n }\n\n result.push(arg);\n }\n\n return result;\n}\n","import * as crypto from \"node:crypto\";\nimport * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport { parseYAML } from \"confbox\";\nimport * as path from \"pathe\";\nimport { xdgConfig } from \"xdg-basedir\";\nimport { sanitizeArgv, sanitizeMessage, sanitizeStackTrace } from \"./sanitize\";\n\nexport type ErrorType = \"uncaughtException\" | \"unhandledRejection\" | \"handledError\";\n\nexport interface CrashReport {\n id: string;\n timestamp: string;\n sdkVersion: string;\n nodeVersion: string;\n osPlatform: string;\n osRelease: string;\n arch: string;\n command: string;\n argv: string[];\n errorName: string;\n errorMessage: string;\n stackTrace: string;\n errorType: ErrorType;\n userId: string | null;\n userEmail: string | null;\n}\n\ninterface BuildCrashReportOptions {\n error: unknown;\n sdkVersion: string;\n errorType: ErrorType;\n}\n\n// Maximum subcommand depth to keep (e.g., \"tailordb migrate generate\" = 3 tokens).\n// Positional arguments beyond this are potentially sensitive user input.\n// Accepted trade-off: plain-text positional args that don't match known patterns\n// (UUIDs, hex tokens, emails, paths) pass through to `command` and `argv`.\n// Full redaction would require embedding the CLI command tree here, which is fragile.\nconst MAX_COMMAND_TOKENS = 3;\n\n/**\n * Parse the command name from process.argv.\n * Extracts up to MAX_COMMAND_TOKENS non-flag arguments after the script name.\n * @returns Parsed command string\n */\nfunction parseCommand(): string {\n const args = process.argv.slice(2);\n const commandParts: string[] = [];\n for (const arg of args) {\n if (arg.startsWith(\"-\") || commandParts.length >= MAX_COMMAND_TOKENS) break;\n commandParts.push(arg);\n }\n return commandParts.join(\" \") || \"<unknown>\";\n}\n\n/**\n * Build a CrashReport data structure from an error and context.\n * All sensitive data is sanitized before inclusion.\n * @param options - Error, SDK version, and crash type\n * @returns Sanitized crash report\n */\nexport function buildCrashReport(options: BuildCrashReportOptions): CrashReport {\n const { error, sdkVersion, errorType } = options;\n\n const isError = error instanceof Error;\n const rawMessage = isError ? error.message : String(error);\n const rawStack = isError && error.stack ? error.stack : \"\";\n const errorName = isError ? error.name : \"UnknownError\";\n\n const currentUser = readCurrentUser();\n\n return {\n id: crypto.randomUUID(),\n timestamp: new Date().toISOString(),\n sdkVersion,\n nodeVersion: process.version,\n osPlatform: process.platform,\n osRelease: os.release(),\n arch: process.arch,\n command: sanitizeMessage(parseCommand()),\n argv: sanitizeArgv(process.argv),\n errorName,\n errorMessage: sanitizeMessage(rawMessage),\n stackTrace: sanitizeStackTrace(rawStack),\n errorType,\n userId: currentUser?.id ?? null,\n userEmail: currentUser?.email ?? null,\n };\n}\n\ntype CurrentUser = {\n id: string;\n email: string | null;\n};\n\n/**\n * Read current_user from Tailor Platform config without side effects.\n * Unlike readPlatformConfig(), this never triggers migration or logs warnings.\n * @returns The current user ID and email, or null if unavailable\n */\nfunction readCurrentUser(): CurrentUser | null {\n try {\n if (!xdgConfig) return null;\n const configPath = path.join(xdgConfig, \"tailor-platform\", \"config.yaml\");\n if (!fs.existsSync(configPath)) return null;\n const raw = parseYAML(fs.readFileSync(configPath, \"utf-8\")) as {\n current_user?: string | null;\n users?: Record<string, { email?: unknown } | undefined>;\n };\n // parseYAML returns null for empty documents\n // oxlint-disable-next-line typescript/no-unnecessary-condition\n const currentUser = raw?.current_user ?? null;\n if (!currentUser) return null;\n const email = raw.users?.[currentUser]?.email;\n return {\n id: currentUser,\n email: typeof email === \"string\" ? email : legacyEmail(currentUser),\n };\n } catch {\n return null;\n }\n}\n\nfunction legacyEmail(user: string): string | null {\n return user.includes(\"@\") ? user : null;\n}\n","import { logger } from \"#/cli/shared/logger\";\nimport { readPackageJson } from \"#/cli/shared/package-json\";\nimport { userAgentFromVersion } from \"#/cli/shared/user-agent\";\nimport { parseCrashReportConfig } from \"./config\";\nimport { buildCrashReport, type ErrorType } from \"./report\";\nimport { sendCrashReport } from \"./sender\";\nimport { writeCrashReport } from \"./writer\";\n\n/**\n * Report an unexpected crash. Writes a local crash log file and optionally\n * sends the report to a remote endpoint. Displays a user-facing message\n * with the crash log path and a command to submit the report.\n *\n * Never throws - all errors are silently caught.\n * @param error - The error that caused the crash\n * @param errorType - How the error was caught\n */\nexport async function reportCrash(error: unknown, errorType: ErrorType): Promise<void> {\n try {\n const config = parseCrashReportConfig();\n if (!config.localEnabled && !config.remoteEnabled) return;\n\n const packageJson = await readPackageJson();\n const sdkVersion = packageJson.version ?? \"unknown\";\n\n const report = buildCrashReport({ error, sdkVersion, errorType });\n\n if (config.localEnabled) {\n const filePath = writeCrashReport(report, config.localDir);\n if (filePath) {\n logger.log(\n [\n \"\",\n \"An unexpected error occurred. A crash report has been saved to:\",\n ` ${filePath}`,\n \"\",\n \"To submit this report:\",\n ` tailor crashreport send --file \"${filePath}\"`,\n ].join(\"\\n\"),\n );\n }\n }\n\n if (config.remoteEnabled) {\n const ua = userAgentFromVersion(sdkVersion);\n await sendCrashReport(report, ua);\n }\n } catch {\n // Never throw from crash reporting\n }\n}\n\n/**\n * Register global uncaughtException and unhandledRejection handlers.\n * These catch errors outside the normal cleanup flow (e.g., during\n * argument parsing). Should be called once at CLI startup before runMain.\n */\nexport function initCrashReporting(): void {\n const config = parseCrashReportConfig();\n if (!config.localEnabled && !config.remoteEnabled) return;\n\n const handleFatal = (error: unknown, errorType: ErrorType) => {\n const message = error instanceof Error ? error.message : String(error);\n logger.error(message);\n void reportCrash(error, errorType).finally(() => {\n process.exit(1);\n });\n };\n\n process.on(\"uncaughtException\", (error) => handleFatal(error, \"uncaughtException\"));\n process.on(\"unhandledRejection\", (reason) => handleFatal(reason, \"unhandledRejection\"));\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"crashreport-CIIfLnoO.mjs","names":[],"sources":["../src/cli/crashreport/config.ts","../src/cli/crashreport/writer.ts","../src/cli/crashreport/sender.ts","../src/cli/crashreport/sanitize.ts","../src/cli/crashreport/report.ts","../src/cli/crashreport/index.ts"],"sourcesContent":["import * as path from \"pathe\";\nimport { isCI } from \"std-env\";\nimport { xdgConfig } from \"xdg-basedir\";\n\nexport interface CrashReportConfig {\n readonly localEnabled: boolean;\n readonly remoteEnabled: boolean;\n readonly localDir: string;\n}\n\n/**\n * Parse crash report configuration from environment variables.\n * Local crash log writing is enabled by default (opt-out via TAILOR_CRASH_REPORTS_LOCAL=off).\n * Remote sending is disabled by default (opt-in via TAILOR_CRASH_REPORTS_REMOTE=on).\n * Both are auto-disabled in CI environments.\n * @returns Crash report configuration\n */\nexport function parseCrashReportConfig(): CrashReportConfig {\n if (isCI) {\n return {\n localEnabled: false,\n remoteEnabled: false,\n localDir: \"\",\n };\n }\n\n const localEnabled = (process.env.TAILOR_CRASH_REPORTS_LOCAL ?? \"on\").toLowerCase() !== \"off\";\n const remoteEnabled = (process.env.TAILOR_CRASH_REPORTS_REMOTE ?? \"off\").toLowerCase() === \"on\";\n const localDir = xdgConfig ? path.join(xdgConfig, \"tailor-platform\", \"crash-reports\") : \"\";\n\n return {\n localEnabled: localEnabled && localDir !== \"\",\n remoteEnabled,\n localDir,\n };\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"pathe\";\nimport { ensureSecretDir, writeSecretFile } from \"#/cli/shared/secret-file\";\nimport type { CrashReport } from \"./report\";\n\nconst MAX_CRASH_FILES = 10;\n\n/** Marker line that separates human-readable content from the JSON footer. */\nexport const JSON_FOOTER_MARKER = \"--- JSON ---\";\n\n/** File extension for crash log files. */\nexport const CRASH_LOG_EXTENSION = \".crash.log\";\n\n/**\n * Format a CrashReport as human-readable text for local crash log files.\n * @param report - Crash report to format\n * @returns Formatted text content\n */\nexport function formatCrashReport(report: CrashReport): string {\n const lines = [\n `Crash Report: ${report.id}`,\n `Timestamp: ${report.timestamp}`,\n `Error Type: ${report.errorType}`,\n \"\",\n \"--- Environment ---\",\n `SDK Version: ${report.sdkVersion}`,\n `Node Version: ${report.nodeVersion}`,\n `OS: ${report.osPlatform} ${report.osRelease}`,\n `Arch: ${report.arch}`,\n \"\",\n \"--- Command ---\",\n `Command: ${report.command}`,\n `Arguments: ${JSON.stringify(report.argv)}`,\n \"\",\n \"--- Error ---\",\n `Name: ${report.errorName}`,\n `Message: ${report.errorMessage}`,\n \"\",\n \"--- Stack Trace ---\",\n report.stackTrace || \"(no stack trace available)\",\n \"\",\n JSON_FOOTER_MARKER,\n JSON.stringify(report),\n \"\",\n ];\n return lines.join(\"\\n\");\n}\n\n/**\n * Generate a filename for a crash log file.\n * Format: {timestamp}-{shortId}.crash.log\n * @param report - Crash report to generate filename for\n * @returns Filename string\n */\nfunction generateFilename(report: CrashReport): string {\n const safeTimestamp = report.timestamp.replace(/[:.]/g, \"-\");\n const shortId = report.id.slice(0, 8);\n return `${safeTimestamp}-${shortId}${CRASH_LOG_EXTENSION}`;\n}\n\n/**\n * Remove old crash log files, keeping only the most recent ones.\n * @param dir - Crash log directory\n */\nfunction cleanupOldFiles(dir: string): void {\n try {\n const files = fs\n .readdirSync(dir)\n .filter((f) => f.endsWith(CRASH_LOG_EXTENSION))\n .toSorted()\n .toReversed();\n\n for (const file of files.slice(MAX_CRASH_FILES)) {\n fs.unlinkSync(path.join(dir, file));\n }\n } catch {\n // Best-effort cleanup, ignore errors\n }\n}\n\n/**\n * Write a crash report to a local file.\n * Creates the directory if it doesn't exist. Keeps only the last 10 crash files.\n * Never throws - returns the file path on success or undefined on failure.\n * @param report - Crash report to write\n * @param dir - Directory to write the crash log file to\n * @returns File path on success, undefined on failure\n */\nexport function writeCrashReport(report: CrashReport, dir: string): string | undefined {\n try {\n ensureSecretDir(dir);\n\n const filename = generateFilename(report);\n const filePath = path.join(dir, filename);\n const content = formatCrashReport(report);\n\n writeSecretFile(filePath, content);\n cleanupOldFiles(dir);\n\n return filePath;\n } catch {\n return undefined;\n }\n}\n","import type { CrashReport } from \"./report\";\n\nconst SEND_TIMEOUT_MS = 5000;\nconst PRODUCTION_ENDPOINT = \"https://sdk-error-tracking-926vh9t4cl.erp.dev/query\";\n\nconst SUBMIT_MUTATION = `\nmutation SubmitCrashReport(\n $id: String!\n $timestamp: String!\n $sdkVersion: String!\n $nodeVersion: String!\n $osPlatform: String!\n $osRelease: String!\n $arch: String!\n $command: String!\n $argv: [String]\n $errorName: String!\n $errorMessage: String!\n $stackTrace: String\n $errorType: String!\n $userId: String\n $userEmail: String\n) {\n submitCrashReport(\n id: $id\n timestamp: $timestamp\n sdkVersion: $sdkVersion\n nodeVersion: $nodeVersion\n osPlatform: $osPlatform\n osRelease: $osRelease\n arch: $arch\n command: $command\n argv: $argv\n errorName: $errorName\n errorMessage: $errorMessage\n stackTrace: $stackTrace\n errorType: $errorType\n userId: $userId\n userEmail: $userEmail\n ) {\n success\n }\n}`;\n\n/**\n * Send a crash report to the remote endpoint via GraphQL mutation.\n * Best-effort: never throws, returns boolean success.\n * @param report - Crash report to send\n * @param ua - User-Agent header value\n * @returns true if the request succeeded, false otherwise\n */\nexport async function sendCrashReport(report: CrashReport, ua: string): Promise<boolean> {\n try {\n const endpoint = process.env.TAILOR_CRASH_REPORT_ENDPOINT || PRODUCTION_ENDPOINT;\n const response = await fetch(endpoint, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"User-Agent\": ua,\n },\n body: JSON.stringify({\n query: SUBMIT_MUTATION,\n variables: report,\n }),\n signal: AbortSignal.timeout(SEND_TIMEOUT_MS),\n });\n\n if (!response.ok) return false;\n\n const data = (await response.json()) as {\n errors?: unknown[];\n data?: { submitCrashReport: { success: boolean } };\n };\n if (data.errors?.length) return false;\n return data.data?.submitCrashReport.success === true;\n } catch {\n return false;\n }\n}\n","import * as os from \"node:os\";\n\nconst HOME_DIR = os.homedir();\n\n// Patterns for sanitization (global variants for use with .replace())\nconst UUID_PATTERN = /\\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\\b/gi;\nconst LONG_HEX_PATTERN = /\\b[0-9a-fA-F]{32,}\\b/g;\nconst EMAIL_PATTERN = /\\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}\\b/g;\nconst ABSOLUTE_PATH_PATTERN = /(?:\\/(?:[\\w.@\\- ]+\\/)+[\\w.@\\- ]+)/g;\nconst WINDOWS_PATH_PATTERN = /(?:[A-Za-z]:\\\\(?:[\\w.@\\- ]+\\\\)+[\\w.@\\- ]+)/g;\nconst URL_QUERY_PATTERN = /[?&][^?\\s]*/g;\n\n// Non-global variants for single-match .test() calls (avoids lastIndex state issues)\nconst EMAIL_TEST_PATTERN = /\\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}\\b/;\nconst WINDOWS_DRIVE_TEST_PATTERN = /^[A-Za-z]:\\\\/;\n\n// SDK package path marker for relative paths\nconst SDK_PACKAGE_MARKER = \"packages/sdk/\";\n\nfunction lastSegment(filePath: string, separator: string): string {\n return filePath.split(separator).pop() ?? filePath;\n}\n\n/**\n * Sanitize a stack trace by replacing absolute paths with relative SDK paths.\n * External paths are replaced with `<external>/filename.ext`.\n * Home directories are replaced with `~/<redacted>/`.\n * @param stack - Raw stack trace string\n * @returns Sanitized stack trace\n */\nexport function sanitizeStackTrace(stack: string): string {\n // V8 stack traces start with \"ErrorType: message\\n at ...\".\n // The error message may span multiple lines before the first \" at \" frame.\n // Apply message sanitization to all message lines so secrets embedded in\n // multiline error messages are redacted consistently with errorMessage.\n const firstFrameIndex = stack.search(/\\n\\s+at /);\n let result: string;\n if (firstFrameIndex !== -1) {\n result = sanitizeMessage(stack.slice(0, firstFrameIndex)) + stack.slice(firstFrameIndex);\n } else {\n result = sanitizeMessage(stack);\n }\n\n result = result.replace(ABSOLUTE_PATH_PATTERN, (match) => {\n const sdkIndex = match.indexOf(SDK_PACKAGE_MARKER);\n if (sdkIndex !== -1) {\n return match.slice(sdkIndex);\n }\n\n if (match.startsWith(HOME_DIR)) {\n return `~/<redacted>/${lastSegment(match, \"/\")}`;\n }\n\n return `<external>/${lastSegment(match, \"/\")}`;\n });\n result = result.replace(WINDOWS_PATH_PATTERN, (match) => {\n const normalized = match.replace(/\\\\/g, \"/\");\n const sdkIndex = normalized.indexOf(SDK_PACKAGE_MARKER);\n if (sdkIndex !== -1) {\n return normalized.slice(sdkIndex);\n }\n return `<external>/${lastSegment(match, \"\\\\\")}`;\n });\n return result;\n}\n\n/**\n * Sanitize an error message by redacting sensitive information.\n * Redacts: UUIDs, long hex tokens, email addresses, absolute paths, URL query strings.\n * @param message - Raw error message\n * @returns Sanitized error message\n */\nexport function sanitizeMessage(message: string): string {\n let result = message;\n // Strip serialized request/response bodies that may contain secrets\n result = result.replace(/\\nRequest:\\s*[\\s\\S]*$/, \"\\nRequest: <redacted>\");\n result = result.replace(UUID_PATTERN, \"<uuid>\");\n result = result.replace(LONG_HEX_PATTERN, \"<redacted>\");\n result = result.replace(EMAIL_PATTERN, \"<email>\");\n result = result.replace(URL_QUERY_PATTERN, \"?<redacted>\");\n result = result.replace(ABSOLUTE_PATH_PATTERN, (match) => `<path>/${lastSegment(match, \"/\")}`);\n result = result.replace(WINDOWS_PATH_PATTERN, (match) => `<path>/${lastSegment(match, \"\\\\\")}`);\n\n return result;\n}\n\n/**\n * Sanitize process.argv by keeping command/subcommand names and redacting\n * values of sensitive flags.\n * @param argv - Raw process.argv array\n * @returns Sanitized argv array\n */\nexport function sanitizeArgv(argv: string[]): string[] {\n const result: string[] = [];\n let redactNext = false;\n\n for (const arg of argv) {\n if (redactNext) {\n // If the next token is itself a flag, treat it as a new flag rather\n // than consuming it as the previous flag's value. This avoids leaking\n // the *next* flag's value (e.g., `--verbose --workspace-id secret`\n // would otherwise expose `secret`).\n if (!arg.startsWith(\"-\")) {\n result.push(\"<redacted>\");\n redactNext = false;\n continue;\n }\n redactNext = false;\n }\n\n if (arg.startsWith(\"-\")) {\n // --flag=value: keep flag name, redact value\n const eqIndex = arg.indexOf(\"=\");\n if (eqIndex !== -1) {\n result.push(`${arg.slice(0, eqIndex)}=<redacted>`);\n continue;\n }\n\n // --flag / -f: keep flag name, redact next arg as its value\n result.push(arg);\n redactNext = true;\n continue;\n }\n\n // Redact absolute paths\n if (arg.startsWith(\"/\") && arg.includes(\"/\", 1)) {\n result.push(\"<path>\");\n continue;\n }\n\n // Redact Windows-style absolute paths\n if (WINDOWS_DRIVE_TEST_PATTERN.test(arg)) {\n result.push(\"<path>\");\n continue;\n }\n\n // Redact email addresses\n if (EMAIL_TEST_PATTERN.test(arg)) {\n result.push(\"<email>\");\n continue;\n }\n\n result.push(arg);\n }\n\n return result;\n}\n","import * as crypto from \"node:crypto\";\nimport * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport { parseYAML } from \"confbox\";\nimport * as path from \"pathe\";\nimport { xdgConfig } from \"xdg-basedir\";\nimport { sanitizeArgv, sanitizeMessage, sanitizeStackTrace } from \"./sanitize\";\n\nexport type ErrorType = \"uncaughtException\" | \"unhandledRejection\" | \"handledError\";\n\nexport interface CrashReport {\n id: string;\n timestamp: string;\n sdkVersion: string;\n nodeVersion: string;\n osPlatform: string;\n osRelease: string;\n arch: string;\n command: string;\n argv: string[];\n errorName: string;\n errorMessage: string;\n stackTrace: string;\n errorType: ErrorType;\n userId: string | null;\n userEmail: string | null;\n}\n\ninterface BuildCrashReportOptions {\n error: unknown;\n sdkVersion: string;\n errorType: ErrorType;\n}\n\n// Maximum subcommand depth to keep (e.g., \"tailordb migrate generate\" = 3 tokens).\n// Positional arguments beyond this are potentially sensitive user input.\n// Accepted trade-off: plain-text positional args that don't match known patterns\n// (UUIDs, hex tokens, emails, paths) pass through to `command` and `argv`.\n// Full redaction would require embedding the CLI command tree here, which is fragile.\nconst MAX_COMMAND_TOKENS = 3;\n\n/**\n * Parse the command name from process.argv.\n * Extracts up to MAX_COMMAND_TOKENS non-flag arguments after the script name.\n * @returns Parsed command string\n */\nfunction parseCommand(): string {\n const args = process.argv.slice(2);\n const commandParts: string[] = [];\n for (const arg of args) {\n if (arg.startsWith(\"-\") || commandParts.length >= MAX_COMMAND_TOKENS) break;\n commandParts.push(arg);\n }\n return commandParts.join(\" \") || \"<unknown>\";\n}\n\n/**\n * Build a CrashReport data structure from an error and context.\n * All sensitive data is sanitized before inclusion.\n * @param options - Error, SDK version, and crash type\n * @returns Sanitized crash report\n */\nexport function buildCrashReport(options: BuildCrashReportOptions): CrashReport {\n const { error, sdkVersion, errorType } = options;\n\n const isError = error instanceof Error;\n const rawMessage = isError ? error.message : String(error);\n const rawStack = isError && error.stack ? error.stack : \"\";\n const errorName = isError ? error.name : \"UnknownError\";\n\n const currentUser = readCurrentUser();\n\n return {\n id: crypto.randomUUID(),\n timestamp: new Date().toISOString(),\n sdkVersion,\n nodeVersion: process.version,\n osPlatform: process.platform,\n osRelease: os.release(),\n arch: process.arch,\n command: sanitizeMessage(parseCommand()),\n argv: sanitizeArgv(process.argv),\n errorName,\n errorMessage: sanitizeMessage(rawMessage),\n stackTrace: sanitizeStackTrace(rawStack),\n errorType,\n userId: currentUser?.id ?? null,\n userEmail: currentUser?.email ?? null,\n };\n}\n\ntype CurrentUser = {\n id: string;\n email: string | null;\n};\n\n/**\n * Read current_user from Tailor Platform config without side effects.\n * Unlike readPlatformConfig(), this never triggers migration or logs warnings.\n * @returns The current user ID and email, or null if unavailable\n */\nfunction readCurrentUser(): CurrentUser | null {\n try {\n if (!xdgConfig) return null;\n const configPath = path.join(xdgConfig, \"tailor-platform\", \"config.yaml\");\n if (!fs.existsSync(configPath)) return null;\n const raw = parseYAML(fs.readFileSync(configPath, \"utf-8\")) as {\n current_user?: string | null;\n users?: Record<string, { email?: unknown } | undefined>;\n };\n // parseYAML returns null for empty documents\n // oxlint-disable-next-line typescript/no-unnecessary-condition\n const currentUser = raw?.current_user ?? null;\n if (!currentUser) return null;\n const email = raw.users?.[currentUser]?.email;\n return {\n id: currentUser,\n email: typeof email === \"string\" ? email : legacyEmail(currentUser),\n };\n } catch {\n return null;\n }\n}\n\nfunction legacyEmail(user: string): string | null {\n return user.includes(\"@\") ? user : null;\n}\n","import { logger } from \"#/cli/shared/logger\";\nimport { readPackageJson } from \"#/cli/shared/package-json\";\nimport { userAgentFromVersion } from \"#/cli/shared/user-agent\";\nimport { parseCrashReportConfig } from \"./config\";\nimport { buildCrashReport, type ErrorType } from \"./report\";\nimport { sendCrashReport } from \"./sender\";\nimport { writeCrashReport } from \"./writer\";\n\n/**\n * Report an unexpected crash. Writes a local crash log file and optionally\n * sends the report to a remote endpoint. Displays a user-facing message\n * with the crash log path and a command to submit the report.\n *\n * Never throws - all errors are silently caught.\n * @param error - The error that caused the crash\n * @param errorType - How the error was caught\n */\nexport async function reportCrash(error: unknown, errorType: ErrorType): Promise<void> {\n try {\n const config = parseCrashReportConfig();\n if (!config.localEnabled && !config.remoteEnabled) return;\n\n const packageJson = await readPackageJson();\n const sdkVersion = packageJson.version ?? \"unknown\";\n\n const report = buildCrashReport({ error, sdkVersion, errorType });\n\n if (config.localEnabled) {\n const filePath = writeCrashReport(report, config.localDir);\n if (filePath) {\n logger.log(\n [\n \"\",\n \"An unexpected error occurred. A crash report has been saved to:\",\n ` ${filePath}`,\n \"\",\n \"To submit this report:\",\n ` tailor crashreport send --file \"${filePath}\"`,\n ].join(\"\\n\"),\n );\n }\n }\n\n if (config.remoteEnabled) {\n const ua = userAgentFromVersion(sdkVersion);\n await sendCrashReport(report, ua);\n }\n } catch {\n // Never throw from crash reporting\n }\n}\n\n/**\n * Register global uncaughtException and unhandledRejection handlers.\n * These catch errors outside the normal cleanup flow (e.g., during\n * argument parsing). Should be called once at CLI startup before runMain.\n */\nexport function initCrashReporting(): void {\n const config = parseCrashReportConfig();\n if (!config.localEnabled && !config.remoteEnabled) return;\n\n const handleFatal = (error: unknown, errorType: ErrorType) => {\n const message = error instanceof Error ? error.message : String(error);\n logger.error(message);\n void reportCrash(error, errorType).finally(() => {\n process.exit(1);\n });\n };\n\n process.on(\"uncaughtException\", (error) => handleFatal(error, \"uncaughtException\"));\n process.on(\"unhandledRejection\", (reason) => handleFatal(reason, \"unhandledRejection\"));\n}\n"],"mappings":"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"}
|