cvx-kit 0.1.8 → 0.1.11
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 +32 -0
- package/README.md +28 -28
- package/dist/agent-tools.d.mts +5 -5
- package/dist/agent-tools.mjs.map +1 -1
- package/dist/auth.d.mts +39 -289
- package/dist/auth.mjs.map +1 -1
- package/dist/components/approvals/_generated/api.d.mts +3 -4
- package/dist/components/approvals/_generated/api.mjs.map +1 -1
- package/dist/components/approvals/_generated/component.d.mts +1 -2
- package/dist/components/approvals/_generated/dataModel.d.mts +4 -5
- package/dist/components/approvals/_generated/server.d.mts +12 -13
- package/dist/components/approvals/_generated/server.mjs.map +1 -1
- package/dist/components/approvals/audit.d.mts +8 -8
- package/dist/components/approvals/audit.mjs +1 -1
- package/dist/components/approvals/audit.mjs.map +1 -1
- package/dist/components/approvals/client.d.mts +10 -10
- package/dist/components/approvals/client.mjs.map +1 -1
- package/dist/components/approvals/constants.d.mts +30 -30
- package/dist/components/approvals/constants.mjs.map +1 -1
- package/dist/components/approvals/convex.config.mjs.map +1 -1
- package/dist/components/approvals/decisions.d.mts +6 -6
- package/dist/components/approvals/decisions.mjs.map +1 -1
- package/dist/components/approvals/functions.d.mts +3 -3
- package/dist/components/approvals/functions.mjs.map +1 -1
- package/dist/components/approvals/health.d.mts +2 -2
- package/dist/components/approvals/health.mjs.map +1 -1
- package/dist/components/approvals/requests.d.mts +8 -8
- package/dist/components/approvals/requests.mjs.map +1 -1
- package/dist/components/approvals/validators.d.mts +29 -29
- package/dist/components/approvals/validators.mjs +1 -1
- package/dist/components/approvals/validators.mjs.map +1 -1
- package/dist/components/approvals/workflow.d.mts +3 -3
- package/dist/components/approvals/workflow.mjs.map +1 -1
- package/dist/components/approvals/workflow_steps.d.mts +15 -15
- package/dist/components/approvals/workflow_steps.mjs.map +1 -1
- package/dist/components/foundation/_generated/api.d.mts +3 -4
- package/dist/components/foundation/_generated/api.mjs.map +1 -1
- package/dist/components/foundation/_generated/component.d.mts +1 -2
- package/dist/components/foundation/_generated/dataModel.d.mts +4 -5
- package/dist/components/foundation/_generated/server.d.mts +12 -13
- package/dist/components/foundation/_generated/server.mjs.map +1 -1
- package/dist/components/foundation/client.d.mts +13 -13
- package/dist/components/foundation/client.mjs.map +1 -1
- package/dist/components/foundation/convex.config.mjs.map +1 -1
- package/dist/components/foundation/functions.d.mts +2 -2
- package/dist/components/foundation/functions.mjs.map +1 -1
- package/dist/components/foundation/modules/command/command.d.mts +14 -14
- package/dist/components/foundation/modules/command/command.mjs.map +1 -1
- package/dist/components/foundation/modules/command/lifecycle.d.mts +12 -13
- package/dist/components/foundation/modules/command/lifecycle.mjs.map +1 -1
- package/dist/components/foundation/modules/observability/observability.d.mts +4 -4
- package/dist/components/foundation/modules/observability/observability.mjs.map +1 -1
- package/dist/components/foundation/modules/query/query.d.mts +5 -5
- package/dist/components/foundation/modules/query/query.mjs.map +1 -1
- package/dist/components/foundation/operation.d.mts +5 -6
- package/dist/components/foundation/operation.mjs.map +1 -1
- package/dist/components/foundation/result.d.mts +6 -6
- package/dist/components/foundation/result.mjs.map +1 -1
- package/dist/components/foundation/telemetry.d.mts +2 -2
- package/dist/components/foundation/telemetry.mjs.map +1 -1
- package/dist/crud.d.mts +6 -5
- package/dist/crud.mjs.map +1 -1
- package/dist/effect.d.mts +3 -2
- package/dist/effect.mjs +1 -1
- package/dist/errors.d.mts +4 -4
- package/dist/errors.mjs.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/middleware.d.mts +2 -3
- package/dist/middleware.mjs.map +1 -1
- package/dist/modules/contracts/contract.d.mts +12 -13
- package/dist/modules/contracts/contract.mjs.map +1 -1
- package/dist/modules/contracts/convex.d.mts +3 -5
- package/dist/modules/contracts/convex.mjs.map +1 -1
- package/dist/modules/contracts/errors.d.mts +8 -9
- package/dist/modules/contracts/errors.mjs +1 -1
- package/dist/modules/contracts/errors.mjs.map +1 -1
- package/dist/modules/contracts/exposure.d.mts +13 -14
- package/dist/modules/contracts/exposure.mjs +1 -1
- package/dist/modules/contracts/exposure.mjs.map +1 -1
- package/dist/modules/contracts/idempotency.d.mts +15 -16
- package/dist/modules/contracts/idempotency.mjs +1 -1
- package/dist/modules/contracts/idempotency.mjs.map +1 -1
- package/dist/modules/contracts/standard.d.mts +2 -3
- package/dist/modules/contracts/standard.mjs.map +1 -1
- package/dist/modules/contracts/workflow.d.mts +26 -27
- package/dist/modules/contracts/workflow.mjs.map +1 -1
- package/dist/modules/effect/api-runtime.d.mts +10 -11
- package/dist/modules/effect/api-runtime.mjs +1 -1
- package/dist/modules/effect/api-runtime.mjs.map +1 -1
- package/dist/modules/effect/api-zod.d.mts +2 -3
- package/dist/modules/effect/api-zod.mjs.map +1 -1
- package/dist/modules/effect/api.d.mts +4 -5
- package/dist/modules/effect/api.mjs.map +1 -1
- package/dist/modules/effect/auth.d.mts +43 -0
- package/dist/modules/effect/auth.mjs +2 -0
- package/dist/modules/effect/auth.mjs.map +1 -0
- package/dist/modules/effect/client.d.mts +1 -1
- package/dist/modules/effect/client.mjs +1 -1
- package/dist/modules/effect/command.d.mts +4 -5
- package/dist/modules/effect/command.mjs +1 -1
- package/dist/modules/effect/command.mjs.map +1 -1
- package/dist/modules/effect/crud.d.mts +7 -8
- package/dist/modules/effect/crud.mjs +1 -1
- package/dist/modules/effect/crud.mjs.map +1 -1
- package/dist/modules/effect/errors.d.mts +1 -2
- package/dist/modules/effect/errors.mjs.map +1 -1
- package/dist/modules/effect/foundation.d.mts +3 -4
- package/dist/modules/effect/foundation.mjs.map +1 -1
- package/dist/modules/effect/idempotency.d.mts +2 -3
- package/dist/modules/effect/idempotency.mjs.map +1 -1
- package/dist/modules/effect/normalize.d.mts +2 -3
- package/dist/modules/effect/normalize.mjs.map +1 -1
- package/dist/modules/effect/operation.d.mts +17 -18
- package/dist/modules/effect/operation.mjs.map +1 -1
- package/dist/modules/effect/query.d.mts +3 -4
- package/dist/modules/effect/query.mjs +1 -1
- package/dist/modules/effect/query.mjs.map +1 -1
- package/dist/modules/effect/schema.d.mts +8 -9
- package/dist/modules/effect/schema.mjs.map +1 -1
- package/dist/modules/effect/workflow.d.mts +5 -6
- package/dist/modules/effect/workflow.mjs +1 -1
- package/dist/modules/effect/workflow.mjs.map +1 -1
- package/dist/oxlint/architecture.d.mts +6 -7
- package/dist/oxlint/architecture.mjs +1 -1
- package/dist/oxlint/architecture.mjs.map +1 -1
- package/dist/oxlint/ast.d.mts +22 -23
- package/dist/oxlint/ast.mjs +1 -1
- package/dist/oxlint/ast.mjs.map +1 -1
- package/dist/oxlint/ownership.d.mts +2 -3
- package/dist/oxlint/ownership.mjs +1 -1
- package/dist/oxlint/ownership.mjs.map +1 -1
- package/dist/oxlint.d.mts +4 -4
- package/dist/oxlint.mjs +1 -1
- package/dist/oxlint.mjs.map +1 -1
- package/dist/state-machine.d.mts +1 -2
- package/dist/state-machine.mjs.map +1 -1
- package/dist/tenancy.d.mts +6 -6
- package/dist/tenancy.mjs.map +1 -1
- package/dist/triggers.d.mts +6 -6
- package/dist/triggers.mjs.map +1 -1
- package/dist/webhooks.d.mts +5 -6
- package/dist/webhooks.mjs.map +1 -1
- package/dist/zod-table.d.mts +10 -10
- package/dist/zod-table.mjs.map +1 -1
- package/docs/auth.md +131 -1
- package/docs/effect.md +8 -2
- package/docs/llms.md +41 -20
- package/docs/oxlint.md +1 -1
- package/docs/upgrading.md +9 -1
- package/docs/zod-table.md +1 -1
- package/package.json +21 -15
- package/scripts/test-packed-auth.mjs +72 -0
- package/scripts/test-packed-effect.mjs +2 -1
- package/scripts/test-packed-ids.mjs +2 -2
- package/dist/node_modules/@standard-schema/spec/dist/index.d.mts +0 -79
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"operation.mjs","names":[],"sources":["../../../src/modules/effect/operation.ts"],"sourcesContent":["import type { Effect } from 'effect'\nimport type { ContractSchema, ContractInput, ContractOutput } from '../contracts/contract'\nimport type { ContractDecoderError, ContractDecoderRequirements } from './schema'\nimport type { AuditEntryInput } from '../../components/foundation/client'\n\n/** Ordinary failures are defects; only an explicit Effect supplies a typed error. */\nexport type CallbackError<Value> = Value extends (...arguments_: never[]) => infer Returned\n\t? CallbackError<Returned>\n\t: Value extends Effect.Effect<infer Success, infer Error, unknown>\n\t\t? Error | CallbackError<Success>\n\t\t: Value extends PromiseLike<infer Awaited>\n\t\t\t? CallbackError<Awaited>\n\t\t\t: Value extends readonly (infer Item)[]\n\t\t\t\t? CallbackError<Item>\n\t\t\t\t: Value extends { kind: 'execute'; complete?: infer Complete }\n\t\t\t\t\t? CallbackError<Complete>\n\t\t\t\t\t: never\n\nexport type CallbackRequirements<Value> = Value extends (...arguments_: never[]) => infer Returned\n\t? CallbackRequirements<Returned>\n\t: Value extends Effect.Effect<infer Success, unknown, infer Requirements>\n\t\t? Requirements | CallbackRequirements<Success>\n\t\t: Value extends PromiseLike<infer Awaited>\n\t\t\t? CallbackRequirements<Awaited>\n\t\t\t: Value extends readonly (infer Item)[]\n\t\t\t\t? CallbackRequirements<Item>\n\t\t\t\t: Value extends { kind: 'execute'; complete?: infer Complete }\n\t\t\t\t\t? CallbackRequirements<Complete>\n\t\t\t\t\t: never\n\nexport type EffectValue<Value> =\n\tValue extends Effect.Effect<infer Success, unknown, unknown>\n\t\t? EffectValue<Success>\n\t\t: Value extends PromiseLike<infer Awaited>\n\t\t\t? EffectValue<Awaited>\n\t\t\t: Value\n\ndeclare const checkedOperation: unique symbol\n/** Type-only evidence that the helper checked callbacks against the base context and schemas. */\nexport type CheckedEffectOperation<Context> = {\n\treadonly [checkedOperation]: {\n\t\tcontext: (context: Context) => void\n\t\terror: unknown\n\t\trequirements: unknown\n\t\tdefinition: unknown\n\t}\n}\ntype CheckedChannels<Context, Error, Requirements, Definition> = {\n\treadonly [checkedOperation]: {\n\t\tcontext: (context: Context) => void\n\t\terror: Error\n\t\trequirements: Requirements\n\t\tdefinition: Definition\n\t}\n}\n/** Named checked-definition boundary keeps the private evidence marker inside this module's declarations. */\nexport type CheckedEffectDefinition<\n\tContext,\n\tDefinition,\n\tError = never,\n\tRequirements = never,\n> = NoInfer<Omit<Definition, typeof checkedOperation>> &\n\tCheckedChannels<Context, Error, Requirements, Omit<Definition, typeof checkedOperation>>\n/** Reject stale helper evidence after callbacks or schemas are replaced. */\nexport type ValidatedEffectOperations<Operations> = {\n\t[Key in keyof Operations]: Operations[Key] extends {\n\t\treadonly [checkedOperation]: { definition: infer Definition }\n\t}\n\t\t? Operations[Key] extends Definition\n\t\t\t? Operations[Key]\n\t\t\t: never\n\t\t: never\n}\n/** Only middleware whose next contract captured a default policy can discharge its channels. */\nexport type UnwrappedDefaultError<Definition, Guard> = Definition extends { middleware: Function }\n\t? Definition extends CheckedChannels<never, infer Error, unknown, unknown>\n\t\t? Exclude<CallbackError<Guard>, Error>\n\t\t: CallbackError<Guard>\n\t: CallbackError<Guard>\nexport type UnwrappedDefaultRequirements<Definition, Guard> = Definition extends {\n\tmiddleware: Function\n}\n\t? Definition extends CheckedChannels<never, unknown, infer Requirements, unknown>\n\t\t? Exclude<CallbackRequirements<Guard>, Requirements>\n\t\t: CallbackRequirements<Guard>\n\t: CallbackRequirements<Guard>\nexport type EffectOperationArgument<Definition extends { input: ContractSchema }> = ContractInput<\n\tDefinition['input']\n>\nexport type EffectOperationInput<Definition extends { input: ContractSchema }> = ContractOutput<\n\tDefinition['input']\n>\nexport type EffectOperationHandlerResult<Definition extends { result: ContractSchema }> =\n\tContractInput<Definition['result']>\nexport type EffectOperationResult<Definition extends { result: ContractSchema }> = ContractOutput<\n\tDefinition['result']\n>\n\ntype Hook<Definition, Key extends PropertyKey> = Key extends keyof Definition\n\t? Definition[Key]\n\t: never\ntype Returned<Callback> = Callback extends (...arguments_: never[]) => infer Value ? Value : never\n/** A conditional wrapper must retain the unwrapped channels for its absent branch. */\ntype CoreValue<Definition> = [Returned<Hook<Definition, 'middleware'>>] extends [never]\n\t? Returned<Hook<Definition, 'handler'>> | Returned<Hook<Definition, 'guard'>>\n\t: undefined extends Hook<Definition, 'middleware'>\n\t\t?\n\t\t\t\t| Returned<Hook<Definition, 'handler'>>\n\t\t\t\t| Returned<Hook<Definition, 'guard'>>\n\t\t\t\t| Returned<Hook<Definition, 'middleware'>>\n\t\t: Returned<Hook<Definition, 'middleware'>>\ntype OutsideHooks = 'prepare' | 'audit' | 'checkPermission' | 'writeAudit'\nexport type EffectOperationError<Definition> =\n\t| ContractDecoderError<Hook<Definition, 'input'>>\n\t| ContractDecoderError<Hook<Definition, 'result'>>\n\t| ContractDecoderError<Hook<Definition, 'replayResult'>>\n\t| CallbackError<CoreValue<Definition>>\n\t| CallbackError<Definition[Extract<keyof Definition, OutsideHooks>]>\nexport type EffectOperationRequirements<Definition> =\n\t| ContractDecoderRequirements<Hook<Definition, 'input'>>\n\t| ContractDecoderRequirements<Hook<Definition, 'result'>>\n\t| ContractDecoderRequirements<Hook<Definition, 'replayResult'>>\n\t| CallbackRequirements<CoreValue<Definition>>\n\t| CallbackRequirements<Definition[Extract<keyof Definition, OutsideHooks>]>\n\ntype Supported<Value, Error = unknown, Requirements = unknown> =\n\t| Value\n\t| PromiseLike<Value>\n\t| Effect.Effect<Value, Error, Requirements>\nexport type EffectPreparation<Result, Error = never, Requirements = never> =\n\t| { kind: 'replay'; result: unknown }\n\t| { kind: 'execute'; complete?: (result: Result) => Supported<void, Error, Requirements> }\nexport type EffectMiddlewareInput<\n\tContext,\n\tInput,\n\tResult,\n\tExtension,\n\tError = never,\n\tRequirements = never,\n> = {\n\toperation: string\n\tcontext: Context\n\tcommand: Input\n\tinput: Input\n\tnext: keyof Extension extends never\n\t\t? (options?: { context?: Extension }) => Effect.Effect<Result, Error, Requirements>\n\t\t: (options: { context: Extension }) => Effect.Effect<Result, Error, Requirements>\n}\ntype Audit<Aggregates extends readonly string[]> = Omit<\n\tAuditEntryInput,\n\t'classification' | 'aggregate'\n> & {\n\taggregate: { type: Aggregates[number]; id: string }\n}\ntype OperationDefinition<\n\tContext,\n\tInput extends ContractSchema,\n\tOutput extends ContractSchema,\n\tExtension,\n\tAggregates extends readonly string[],\n\tHandler,\n\tGuard,\n\tPreparation,\n\tAuditResult,\n\tMiddleware,\n\tMetadata,\n\tBaseError,\n\tBaseRequirements,\n\tWire extends ContractSchema,\n\tReplay extends ContractSchema,\n> = {\n\tinput: Input\n\tresult: Output\n\thandler: (input: ContractOutput<Input>, context: Context & Extension) => Handler\n\tclassification?: string\n\tpermission?: string\n\tmetadata?: Metadata\n\taggregates?: Aggregates\n\treplayResult?: Replay & (ContractOutput<Replay> extends ContractOutput<Output> ? unknown : never)\n\twire?: { schema: Wire; project: (value: ContractOutput<Output>) => ContractInput<Wire> }\n\tguard?: (context: Context & Extension, input: ContractOutput<Input>) => Guard\n\tprepare?: (context: Context, input: ContractOutput<Input>) => Preparation\n\taudit?: (\n\t\tresolution: { command: ContractOutput<Input>; result: ContractOutput<Output> },\n\t\tcontext: Context,\n\t) => AuditResult\n} & (keyof Extension extends never\n\t? {\n\t\t\tmiddleware?: (\n\t\t\t\tinput: EffectMiddlewareInput<\n\t\t\t\t\tContext,\n\t\t\t\t\tContractOutput<Input>,\n\t\t\t\t\tContractInput<Output>,\n\t\t\t\t\tExtension,\n\t\t\t\t\tBaseError | CallbackError<Handler | Guard>,\n\t\t\t\t\tBaseRequirements | CallbackRequirements<Handler | Guard>\n\t\t\t\t>,\n\t\t\t) => Middleware\n\t\t}\n\t: {\n\t\t\tmiddleware: (\n\t\t\t\tinput: EffectMiddlewareInput<\n\t\t\t\t\tContext,\n\t\t\t\t\tContractOutput<Input>,\n\t\t\t\t\tContractInput<Output>,\n\t\t\t\t\tExtension,\n\t\t\t\t\tBaseError | CallbackError<Handler | Guard>,\n\t\t\t\t\tBaseRequirements | CallbackRequirements<Handler | Guard>\n\t\t\t\t>,\n\t\t\t) => Middleware\n\t\t})\n\n/**\n * Bind context once; middleware wraps the handler/guard channels and may discharge them.\n * Declare contextual guards/handlers before middleware, or annotate their parameters\n * and returned Effect channels when middleware comes first. TypeScript processes\n * context-sensitive object callbacks in declaration order.\n */\nexport function effectOperationFactory<\n\tContext,\n\tExtension extends Record<string, unknown> = Record<never, never>,\n\tBaseError = never,\n\tBaseRequirements = never,\n>() {\n\tfunction operation<\n\t\tconst Input extends ContractSchema,\n\t\tconst Output extends ContractSchema,\n\t\tHandler extends Supported<ContractInput<Output>>,\n\t\tGuard extends Supported<void> = never,\n\t\tPreparation extends Supported<EffectPreparation<ContractOutput<Output>, unknown, unknown>> =\n\t\t\tnever,\n\t\tconst Aggregates extends readonly string[] = readonly string[],\n\t\tAuditResult extends Supported<Audit<Aggregates> | null> = never,\n\t\tMiddleware extends Supported<ContractInput<Output>> = never,\n\t\tconst Metadata extends object = Record<never, never>,\n\t\t// Retain whether middleware is guaranteed, conditional, or omitted.\n\t\tconst Wire extends ContractSchema = ContractSchema,\n\t\tconst Replay extends ContractSchema = never,\n\t\tconst Definition extends object = object,\n\t>(\n\t\tdefinition: Definition &\n\t\t\tOperationDefinition<\n\t\t\t\tContext,\n\t\t\t\tInput,\n\t\t\t\tOutput,\n\t\t\t\tExtension,\n\t\t\t\tAggregates,\n\t\t\t\tHandler,\n\t\t\t\tGuard,\n\t\t\t\tPreparation,\n\t\t\t\tAuditResult,\n\t\t\t\tMiddleware,\n\t\t\t\tMetadata,\n\t\t\t\tBaseError,\n\t\t\t\tBaseRequirements,\n\t\t\t\tWire,\n\t\t\t\tReplay\n\t\t\t>,\n\t) {\n\t\t// SAFETY: the marker is type-only proof of the helper's checked callback contract.\n\t\treturn definition as CheckedEffectDefinition<\n\t\t\tContext,\n\t\t\ttypeof definition,\n\t\t\tBaseError,\n\t\t\tBaseRequirements\n\t\t>\n\t}\n\tfunction command<\n\t\tconst Input extends ContractSchema,\n\t\tconst Output extends ContractSchema,\n\t\tHandler extends Supported<ContractInput<Output>>,\n\t\tGuard extends Supported<void> = never,\n\t\tPreparation extends Supported<EffectPreparation<ContractOutput<Output>, unknown, unknown>> =\n\t\t\tnever,\n\t\tconst Aggregates extends readonly string[] = readonly string[],\n\t\tAuditResult extends Supported<Audit<Aggregates> | null> = never,\n\t\tMiddleware extends Supported<ContractInput<Output>> = never,\n\t\tconst Metadata extends object = Record<never, never>,\n\t\t// Retain whether middleware is guaranteed, conditional, or omitted.\n\t\tconst Wire extends ContractSchema = ContractSchema,\n\t\tconst Replay extends ContractSchema = never,\n\t\tconst Definition extends object = object,\n\t>(\n\t\tdefinition: Definition &\n\t\t\tOperationDefinition<\n\t\t\t\tContext,\n\t\t\t\tInput,\n\t\t\t\tOutput,\n\t\t\t\tExtension,\n\t\t\t\tAggregates,\n\t\t\t\tHandler,\n\t\t\t\tGuard,\n\t\t\t\tPreparation,\n\t\t\t\tAuditResult,\n\t\t\t\tMiddleware,\n\t\t\t\tMetadata,\n\t\t\t\tBaseError,\n\t\t\t\tBaseRequirements,\n\t\t\t\tWire,\n\t\t\t\tReplay\n\t\t\t> & {\n\t\t\t\tclassification: string\n\t\t\t\taudit: (\n\t\t\t\t\tresolution: { command: ContractOutput<Input>; result: ContractOutput<Output> },\n\t\t\t\t\tcontext: Context,\n\t\t\t\t) => AuditResult\n\t\t\t},\n\t) {\n\t\t// SAFETY: the marker is type-only proof of the helper's checked callback contract.\n\t\treturn definition as CheckedEffectDefinition<\n\t\t\tContext,\n\t\t\ttypeof definition,\n\t\t\tBaseError,\n\t\t\tBaseRequirements\n\t\t>\n\t}\n\tfunction query<\n\t\tconst Input extends ContractSchema,\n\t\tconst Output extends ContractSchema,\n\t\tHandler extends Supported<ContractInput<Output>>,\n\t\tGuard extends Supported<void> = never,\n\t\tMiddleware extends Supported<ContractInput<Output>> = never,\n\t\tconst Metadata extends object = Record<never, never>,\n\t\tconst Wire extends ContractSchema = ContractSchema,\n\t\tconst Replay extends ContractSchema = never,\n\t\tconst Definition extends object = object,\n\t>(\n\t\tdefinition: Definition &\n\t\t\tOperationDefinition<\n\t\t\t\tContext,\n\t\t\t\tInput,\n\t\t\t\tOutput,\n\t\t\t\tExtension,\n\t\t\t\treadonly string[],\n\t\t\t\tHandler,\n\t\t\t\tGuard,\n\t\t\t\tnever,\n\t\t\t\tnever,\n\t\t\t\tMiddleware,\n\t\t\t\tMetadata,\n\t\t\t\tBaseError,\n\t\t\t\tBaseRequirements,\n\t\t\t\tWire,\n\t\t\t\tReplay\n\t\t\t> & {\n\t\t\t\tprepare?: never\n\t\t\t\taudit?: never\n\t\t\t\taggregates?: never\n\t\t\t\treplayResult?: never\n\t\t\t},\n\t) {\n\t\t// SAFETY: the marker is type-only proof of the helper's checked callback contract.\n\t\treturn definition as CheckedEffectDefinition<\n\t\t\tContext,\n\t\t\ttypeof definition,\n\t\t\tBaseError,\n\t\t\tBaseRequirements\n\t\t>\n\t}\n\treturn { operation, command, query }\n}\n"],"mappings":"AA0NA,SAAgB,GAKZ,CACH,SAAS,EAgBR,EAkBC,CAED,OAAO,CAMR,CACA,SAAS,EAgBR,EAwBC,CAED,OAAO,CAMR,CACA,SAAS,EAWR,EAuBC,CAED,OAAO,CAMR,CACA,MAAO,CAAE,YAAW,UAAS,OAAM,CACpC"}
|
|
1
|
+
{"version":3,"file":"operation.mjs","names":["effectOperationFactory","operation","definition","command","query"],"sources":["../../../src/modules/effect/operation.ts"],"sourcesContent":["import type { Effect } from 'effect'\nimport type { ContractSchema, ContractInput, ContractOutput } from '../contracts/contract'\nimport type { ContractDecoderError, ContractDecoderRequirements } from './schema'\nimport type { AuditEntryInput } from '../../components/foundation/client'\n\n/** Ordinary failures are defects; only an explicit Effect supplies a typed error. */\nexport type CallbackError<Value> = Value extends (...arguments_: never[]) => infer Returned\n\t? CallbackError<Returned>\n\t: Value extends Effect.Effect<infer Success, infer Error, unknown>\n\t\t? Error | CallbackError<Success>\n\t\t: Value extends PromiseLike<infer Awaited>\n\t\t\t? CallbackError<Awaited>\n\t\t\t: Value extends readonly (infer Item)[]\n\t\t\t\t? CallbackError<Item>\n\t\t\t\t: Value extends { kind: 'execute'; complete?: infer Complete }\n\t\t\t\t\t? CallbackError<Complete>\n\t\t\t\t\t: never\n\nexport type CallbackRequirements<Value> = Value extends (...arguments_: never[]) => infer Returned\n\t? CallbackRequirements<Returned>\n\t: Value extends Effect.Effect<infer Success, unknown, infer Requirements>\n\t\t? Requirements | CallbackRequirements<Success>\n\t\t: Value extends PromiseLike<infer Awaited>\n\t\t\t? CallbackRequirements<Awaited>\n\t\t\t: Value extends readonly (infer Item)[]\n\t\t\t\t? CallbackRequirements<Item>\n\t\t\t\t: Value extends { kind: 'execute'; complete?: infer Complete }\n\t\t\t\t\t? CallbackRequirements<Complete>\n\t\t\t\t\t: never\n\nexport type EffectValue<Value> =\n\tValue extends Effect.Effect<infer Success, unknown, unknown>\n\t\t? EffectValue<Success>\n\t\t: Value extends PromiseLike<infer Awaited>\n\t\t\t? EffectValue<Awaited>\n\t\t\t: Value\n\ndeclare const checkedOperation: unique symbol\n/** Type-only evidence that the helper checked callbacks against the base context and schemas. */\nexport type CheckedEffectOperation<Context> = {\n\treadonly [checkedOperation]: {\n\t\tcontext: (context: Context) => void\n\t\terror: unknown\n\t\trequirements: unknown\n\t\tdefinition: unknown\n\t}\n}\ntype CheckedChannels<Context, Error, Requirements, Definition> = {\n\treadonly [checkedOperation]: {\n\t\tcontext: (context: Context) => void\n\t\terror: Error\n\t\trequirements: Requirements\n\t\tdefinition: Definition\n\t}\n}\n/** Named checked-definition boundary keeps the private evidence marker inside this module's declarations. */\nexport type CheckedEffectDefinition<\n\tContext,\n\tDefinition,\n\tError = never,\n\tRequirements = never,\n> = NoInfer<Omit<Definition, typeof checkedOperation>> &\n\tCheckedChannels<Context, Error, Requirements, Omit<Definition, typeof checkedOperation>>\n/** Reject stale helper evidence after callbacks or schemas are replaced. */\nexport type ValidatedEffectOperations<Operations> = {\n\t[Key in keyof Operations]: Operations[Key] extends {\n\t\treadonly [checkedOperation]: { definition: infer Definition }\n\t}\n\t\t? Operations[Key] extends Definition\n\t\t\t? Operations[Key]\n\t\t\t: never\n\t\t: never\n}\n/** Only middleware whose next contract captured a default policy can discharge its channels. */\nexport type UnwrappedDefaultError<Definition, Guard> = Definition extends { middleware: Function }\n\t? Definition extends CheckedChannels<never, infer Error, unknown, unknown>\n\t\t? Exclude<CallbackError<Guard>, Error>\n\t\t: CallbackError<Guard>\n\t: CallbackError<Guard>\nexport type UnwrappedDefaultRequirements<Definition, Guard> = Definition extends {\n\tmiddleware: Function\n}\n\t? Definition extends CheckedChannels<never, unknown, infer Requirements, unknown>\n\t\t? Exclude<CallbackRequirements<Guard>, Requirements>\n\t\t: CallbackRequirements<Guard>\n\t: CallbackRequirements<Guard>\nexport type EffectOperationArgument<Definition extends { input: ContractSchema }> = ContractInput<\n\tDefinition['input']\n>\nexport type EffectOperationInput<Definition extends { input: ContractSchema }> = ContractOutput<\n\tDefinition['input']\n>\nexport type EffectOperationHandlerResult<Definition extends { result: ContractSchema }> =\n\tContractInput<Definition['result']>\nexport type EffectOperationResult<Definition extends { result: ContractSchema }> = ContractOutput<\n\tDefinition['result']\n>\n\ntype Hook<Definition, Key extends PropertyKey> = Key extends keyof Definition\n\t? Definition[Key]\n\t: never\ntype Returned<Callback> = Callback extends (...arguments_: never[]) => infer Value ? Value : never\n/** A conditional wrapper must retain the unwrapped channels for its absent branch. */\ntype CoreValue<Definition> = [Returned<Hook<Definition, 'middleware'>>] extends [never]\n\t? Returned<Hook<Definition, 'handler'>> | Returned<Hook<Definition, 'guard'>>\n\t: undefined extends Hook<Definition, 'middleware'>\n\t\t?\n\t\t\t\t| Returned<Hook<Definition, 'handler'>>\n\t\t\t\t| Returned<Hook<Definition, 'guard'>>\n\t\t\t\t| Returned<Hook<Definition, 'middleware'>>\n\t\t: Returned<Hook<Definition, 'middleware'>>\ntype OutsideHooks = 'prepare' | 'audit' | 'checkPermission' | 'writeAudit'\nexport type EffectOperationError<Definition> =\n\t| ContractDecoderError<Hook<Definition, 'input'>>\n\t| ContractDecoderError<Hook<Definition, 'result'>>\n\t| ContractDecoderError<Hook<Definition, 'replayResult'>>\n\t| CallbackError<CoreValue<Definition>>\n\t| CallbackError<Definition[Extract<keyof Definition, OutsideHooks>]>\nexport type EffectOperationRequirements<Definition> =\n\t| ContractDecoderRequirements<Hook<Definition, 'input'>>\n\t| ContractDecoderRequirements<Hook<Definition, 'result'>>\n\t| ContractDecoderRequirements<Hook<Definition, 'replayResult'>>\n\t| CallbackRequirements<CoreValue<Definition>>\n\t| CallbackRequirements<Definition[Extract<keyof Definition, OutsideHooks>]>\n\ntype Supported<Value, Error = unknown, Requirements = unknown> =\n\t| Value\n\t| PromiseLike<Value>\n\t| Effect.Effect<Value, Error, Requirements>\nexport type EffectPreparation<Result, Error = never, Requirements = never> =\n\t| { kind: 'replay'; result: unknown }\n\t| { kind: 'execute'; complete?: (result: Result) => Supported<void, Error, Requirements> }\nexport type EffectMiddlewareInput<\n\tContext,\n\tInput,\n\tResult,\n\tExtension,\n\tError = never,\n\tRequirements = never,\n> = {\n\toperation: string\n\tcontext: Context\n\tcommand: Input\n\tinput: Input\n\tnext: keyof Extension extends never\n\t\t? (options?: { context?: Extension }) => Effect.Effect<Result, Error, Requirements>\n\t\t: (options: { context: Extension }) => Effect.Effect<Result, Error, Requirements>\n}\ntype Audit<Aggregates extends readonly string[]> = Omit<\n\tAuditEntryInput,\n\t'classification' | 'aggregate'\n> & {\n\taggregate: { type: Aggregates[number]; id: string }\n}\ntype OperationDefinition<\n\tContext,\n\tInput extends ContractSchema,\n\tOutput extends ContractSchema,\n\tExtension,\n\tAggregates extends readonly string[],\n\tHandler,\n\tGuard,\n\tPreparation,\n\tAuditResult,\n\tMiddleware,\n\tMetadata,\n\tBaseError,\n\tBaseRequirements,\n\tWire extends ContractSchema,\n\tReplay extends ContractSchema,\n> = {\n\tinput: Input\n\tresult: Output\n\thandler: (input: ContractOutput<Input>, context: Context & Extension) => Handler\n\tclassification?: string\n\tpermission?: string\n\tmetadata?: Metadata\n\taggregates?: Aggregates\n\treplayResult?: Replay & (ContractOutput<Replay> extends ContractOutput<Output> ? unknown : never)\n\twire?: { schema: Wire; project: (value: ContractOutput<Output>) => ContractInput<Wire> }\n\tguard?: (context: Context & Extension, input: ContractOutput<Input>) => Guard\n\tprepare?: (context: Context, input: ContractOutput<Input>) => Preparation\n\taudit?: (\n\t\tresolution: { command: ContractOutput<Input>; result: ContractOutput<Output> },\n\t\tcontext: Context,\n\t) => AuditResult\n} & (keyof Extension extends never\n\t? {\n\t\t\tmiddleware?: (\n\t\t\t\tinput: EffectMiddlewareInput<\n\t\t\t\t\tContext,\n\t\t\t\t\tContractOutput<Input>,\n\t\t\t\t\tContractInput<Output>,\n\t\t\t\t\tExtension,\n\t\t\t\t\tBaseError | CallbackError<Handler | Guard>,\n\t\t\t\t\tBaseRequirements | CallbackRequirements<Handler | Guard>\n\t\t\t\t>,\n\t\t\t) => Middleware\n\t\t}\n\t: {\n\t\t\tmiddleware: (\n\t\t\t\tinput: EffectMiddlewareInput<\n\t\t\t\t\tContext,\n\t\t\t\t\tContractOutput<Input>,\n\t\t\t\t\tContractInput<Output>,\n\t\t\t\t\tExtension,\n\t\t\t\t\tBaseError | CallbackError<Handler | Guard>,\n\t\t\t\t\tBaseRequirements | CallbackRequirements<Handler | Guard>\n\t\t\t\t>,\n\t\t\t) => Middleware\n\t\t})\n\n/**\n * Bind context once; middleware wraps the handler/guard channels and may discharge them.\n * Declare contextual guards/handlers before middleware, or annotate their parameters\n * and returned Effect channels when middleware comes first. TypeScript processes\n * context-sensitive object callbacks in declaration order.\n */\nexport function effectOperationFactory<\n\tContext,\n\tExtension extends Record<string, unknown> = Record<never, never>,\n\tBaseError = never,\n\tBaseRequirements = never,\n>() {\n\tfunction operation<\n\t\tconst Input extends ContractSchema,\n\t\tconst Output extends ContractSchema,\n\t\tHandler extends Supported<ContractInput<Output>>,\n\t\tGuard extends Supported<void> = never,\n\t\tPreparation extends Supported<EffectPreparation<ContractOutput<Output>, unknown, unknown>> =\n\t\t\tnever,\n\t\tconst Aggregates extends readonly string[] = readonly string[],\n\t\tAuditResult extends Supported<Audit<Aggregates> | null> = never,\n\t\tMiddleware extends Supported<ContractInput<Output>> = never,\n\t\tconst Metadata extends object = Record<never, never>,\n\t\t// Retain whether middleware is guaranteed, conditional, or omitted.\n\t\tconst Wire extends ContractSchema = ContractSchema,\n\t\tconst Replay extends ContractSchema = never,\n\t\tconst Definition extends object = object,\n\t>(\n\t\tdefinition: Definition &\n\t\t\tOperationDefinition<\n\t\t\t\tContext,\n\t\t\t\tInput,\n\t\t\t\tOutput,\n\t\t\t\tExtension,\n\t\t\t\tAggregates,\n\t\t\t\tHandler,\n\t\t\t\tGuard,\n\t\t\t\tPreparation,\n\t\t\t\tAuditResult,\n\t\t\t\tMiddleware,\n\t\t\t\tMetadata,\n\t\t\t\tBaseError,\n\t\t\t\tBaseRequirements,\n\t\t\t\tWire,\n\t\t\t\tReplay\n\t\t\t>,\n\t) {\n\t\t// SAFETY: the marker is type-only proof of the helper's checked callback contract.\n\t\treturn definition as CheckedEffectDefinition<\n\t\t\tContext,\n\t\t\ttypeof definition,\n\t\t\tBaseError,\n\t\t\tBaseRequirements\n\t\t>\n\t}\n\tfunction command<\n\t\tconst Input extends ContractSchema,\n\t\tconst Output extends ContractSchema,\n\t\tHandler extends Supported<ContractInput<Output>>,\n\t\tGuard extends Supported<void> = never,\n\t\tPreparation extends Supported<EffectPreparation<ContractOutput<Output>, unknown, unknown>> =\n\t\t\tnever,\n\t\tconst Aggregates extends readonly string[] = readonly string[],\n\t\tAuditResult extends Supported<Audit<Aggregates> | null> = never,\n\t\tMiddleware extends Supported<ContractInput<Output>> = never,\n\t\tconst Metadata extends object = Record<never, never>,\n\t\t// Retain whether middleware is guaranteed, conditional, or omitted.\n\t\tconst Wire extends ContractSchema = ContractSchema,\n\t\tconst Replay extends ContractSchema = never,\n\t\tconst Definition extends object = object,\n\t>(\n\t\tdefinition: Definition &\n\t\t\tOperationDefinition<\n\t\t\t\tContext,\n\t\t\t\tInput,\n\t\t\t\tOutput,\n\t\t\t\tExtension,\n\t\t\t\tAggregates,\n\t\t\t\tHandler,\n\t\t\t\tGuard,\n\t\t\t\tPreparation,\n\t\t\t\tAuditResult,\n\t\t\t\tMiddleware,\n\t\t\t\tMetadata,\n\t\t\t\tBaseError,\n\t\t\t\tBaseRequirements,\n\t\t\t\tWire,\n\t\t\t\tReplay\n\t\t\t> & {\n\t\t\t\tclassification: string\n\t\t\t\taudit: (\n\t\t\t\t\tresolution: { command: ContractOutput<Input>; result: ContractOutput<Output> },\n\t\t\t\t\tcontext: Context,\n\t\t\t\t) => AuditResult\n\t\t\t},\n\t) {\n\t\t// SAFETY: the marker is type-only proof of the helper's checked callback contract.\n\t\treturn definition as CheckedEffectDefinition<\n\t\t\tContext,\n\t\t\ttypeof definition,\n\t\t\tBaseError,\n\t\t\tBaseRequirements\n\t\t>\n\t}\n\tfunction query<\n\t\tconst Input extends ContractSchema,\n\t\tconst Output extends ContractSchema,\n\t\tHandler extends Supported<ContractInput<Output>>,\n\t\tGuard extends Supported<void> = never,\n\t\tMiddleware extends Supported<ContractInput<Output>> = never,\n\t\tconst Metadata extends object = Record<never, never>,\n\t\tconst Wire extends ContractSchema = ContractSchema,\n\t\tconst Replay extends ContractSchema = never,\n\t\tconst Definition extends object = object,\n\t>(\n\t\tdefinition: Definition &\n\t\t\tOperationDefinition<\n\t\t\t\tContext,\n\t\t\t\tInput,\n\t\t\t\tOutput,\n\t\t\t\tExtension,\n\t\t\t\treadonly string[],\n\t\t\t\tHandler,\n\t\t\t\tGuard,\n\t\t\t\tnever,\n\t\t\t\tnever,\n\t\t\t\tMiddleware,\n\t\t\t\tMetadata,\n\t\t\t\tBaseError,\n\t\t\t\tBaseRequirements,\n\t\t\t\tWire,\n\t\t\t\tReplay\n\t\t\t> & {\n\t\t\t\tprepare?: never\n\t\t\t\taudit?: never\n\t\t\t\taggregates?: never\n\t\t\t\treplayResult?: never\n\t\t\t},\n\t) {\n\t\t// SAFETY: the marker is type-only proof of the helper's checked callback contract.\n\t\treturn definition as CheckedEffectDefinition<\n\t\t\tContext,\n\t\t\ttypeof definition,\n\t\t\tBaseError,\n\t\t\tBaseRequirements\n\t\t>\n\t}\n\treturn { operation, command, query }\n}\n"],"mappings":"AA0NA,SAAgBA,GAKZ,CACH,SAASC,EAgBR,EAkBC,CAED,OAAOC,CAMR,CACA,SAASC,EAgBR,EAwBC,CAED,OAAOD,CAMR,CACA,SAASE,EAWR,EAuBC,CAED,OAAOF,CAMR,CACA,MAAO,CAAE,YAAW,UAAS,OAAM,CACpC"}
|
|
@@ -23,7 +23,7 @@ type QueryRegistry<Context> = Readonly<Record<string, Pick<QueryDefinition, 'inp
|
|
|
23
23
|
}>>;
|
|
24
24
|
type OperationKey<Operations> = Extract<keyof Operations, string>;
|
|
25
25
|
/** Injectable domain queries compose lazily; the API chooses native function kind. */
|
|
26
|
-
declare function createEffectQuery<Host, ContextReturned, const Operations extends QueryRegistry<EffectValue<ContextReturned>>, PermissionReturned = never, GuardReturned extends Supported<void> = never>(configuration: {
|
|
26
|
+
export declare function createEffectQuery<Host, ContextReturned, const Operations extends QueryRegistry<EffectValue<ContextReturned>>, PermissionReturned = never, GuardReturned extends Supported<void> = never>(configuration: {
|
|
27
27
|
context: (host: Host) => ContextReturned;
|
|
28
28
|
operations: (definitions: ReturnType<typeof effectOperationFactory<EffectValue<ContextReturned>, Record<never, never>, NoInfer<CallbackError<GuardReturned>>, NoInfer<CallbackRequirements<GuardReturned>>>>) => Operations & NoInfer<ValidatedEffectOperations<Operations>>;
|
|
29
29
|
checkPermission?: (host: Host, input: {
|
|
@@ -48,7 +48,7 @@ type CallbackHost<Callback> = Callback extends ((host: infer Host, input: never)
|
|
|
48
48
|
type CallbackReturned<Callback> = Callback extends ((...arguments_: never[]) => infer Returned) ? Returned : never;
|
|
49
49
|
type PolicyHost<Dependencies> = [CallbackHost<Policy<Dependencies>>] extends [never] ? unknown : CallbackHost<Policy<Dependencies>>;
|
|
50
50
|
type PolicyReturned<Dependencies> = CallbackReturned<Policy<Dependencies>>;
|
|
51
|
-
type EffectQueryDependencies = {
|
|
51
|
+
export type EffectQueryDependencies = {
|
|
52
52
|
observability: Observability;
|
|
53
53
|
checkPermission?: (host: never, input: {
|
|
54
54
|
permission: string;
|
|
@@ -56,7 +56,7 @@ type EffectQueryDependencies = {
|
|
|
56
56
|
}) => unknown;
|
|
57
57
|
};
|
|
58
58
|
/** The public Foundation binds trusted application policies once. */
|
|
59
|
-
declare function bindEffectQuery<const Dependencies extends EffectQueryDependencies>(dependencies: Dependencies): <Host extends PolicyHost<Dependencies>, ContextReturned, const Operations extends QueryRegistry<EffectValue<ContextReturned>>, GuardReturned extends Supported<void> = never>(configuration: {
|
|
59
|
+
export declare function bindEffectQuery<const Dependencies extends EffectQueryDependencies>(dependencies: Dependencies): <Host extends PolicyHost<Dependencies>, ContextReturned, const Operations extends QueryRegistry<EffectValue<ContextReturned>>, GuardReturned extends Supported<void> = never>(configuration: {
|
|
60
60
|
context: (host: Host) => ContextReturned;
|
|
61
61
|
operations: (definitions: ReturnType<typeof effectOperationFactory<EffectValue<ContextReturned>, Record<never, never>, NoInfer<CallbackError<GuardReturned>>, NoInfer<CallbackRequirements<GuardReturned>>>>) => Operations & NoInfer<ValidatedEffectOperations<Operations>>;
|
|
62
62
|
defaults?: {
|
|
@@ -65,5 +65,4 @@ declare function bindEffectQuery<const Dependencies extends EffectQueryDependenc
|
|
|
65
65
|
};
|
|
66
66
|
}) => ReturnType<typeof createEffectQuery<Host, ContextReturned, Operations, PolicyReturned<Dependencies>, GuardReturned>>;
|
|
67
67
|
//#endregion
|
|
68
|
-
export { EffectQueryDependencies, bindEffectQuery, createEffectQuery };
|
|
69
68
|
//# sourceMappingURL=query.d.mts.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{selectOperation as e}from"../contracts/exposure.mjs";import{
|
|
1
|
+
import{selectOperation as e}from"../contracts/exposure.mjs";import{normalizeEffect as t,observationFailure as n}from"./normalize.mjs";import{effectOperationFactory as r}from"./operation.mjs";import{Observability as i}from"../../components/foundation/modules/observability/observability.mjs";import{decodeEffectContract as a}from"./schema.mjs";import{Effect as o,Exit as s}from"effect";var c=class extends Error{code=`QUERY_MIDDLEWARE_NEXT_REUSED`;name=`QueryMiddlewareError`;constructor(){super(`A query middleware called next() more than once`)}},l=class extends Error{code=`QUERY_OPERATION_NOT_CONFIGURED`;name=`QueryConfigurationError`;constructor(){super(`The selected query operation is not configured`)}},u=class extends Error{code=`QUERY_PERMISSION_CHECKER_MISSING`;name=`QueryPermissionError`;constructor(){super(`Query permission requires an injected permission checker`)}};function d(d){let f=r(),p=d.operations(f),m=d.observability instanceof i?d.observability:new i(d.observability??{enabled:!1,classifyError:()=>({outcome:`failed`,errorCode:`UNEXPECTED`})});function h(e,r,i){return o.suspend(()=>{if(!Object.prototype.hasOwnProperty.call(p,e))return o.die(new l);let f=p[e];return o.flatMap(a(f.input,r),r=>{let l=m.start({operation:e,classification:f.classification??`query`});return o.gen(function*(){if(f.permission!==void 0){let n=d.checkPermission;if(!n)return yield*o.die(new u);yield*t(()=>n(i,{permission:f.permission,operation:e}))}let n=yield*t(()=>d.context(i)),s={...d.defaults?.metadata,...f.metadata},l=e=>o.gen(function*(){let n=d.defaults?.guard;return n&&(yield*t(()=>n(e))),f.guard&&(yield*t(()=>f.guard(e,r))),yield*t(()=>f.handler(r,e))}),p=!1,m=f.middleware,h=m?yield*t(()=>m({operation:e,input:r,command:r,context:n,metadata:s,next:e=>o.suspend(()=>p?o.die(new c):(p=!0,l(e?.context?Object.assign({},n,e.context):n)))})):yield*l(n);return yield*a(f.result,h)}).pipe(o.onExit(e=>o.sync(()=>{s.isSuccess(e)?l.completed():l.failed(n(e.cause))})))})})}function g(t,n){if(!Object.hasOwn(p,n))throw new l;return e(t,`query`,n,p[n])}return{exec:h,expose:g,withContext(e){return{exec:(t,n)=>h(t,n,e)}}}}function f(e){return function(t){let n=e.checkPermission;return d({...t,observability:e.observability,checkPermission:e.checkPermission?n:void 0})}}export{f as bindEffectQuery,d as createEffectQuery};
|
|
2
2
|
//# sourceMappingURL=query.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.mjs","names":[],"sources":["../../../src/modules/effect/query.ts"],"sourcesContent":["import { Effect, Exit } from 'effect'\nimport type { ContractSchema } from '../contracts/contract'\nimport {\n\tselectOperation,\n\ttype SelectedOperation,\n\ttype OperationPublicResult,\n} from '../contracts/exposure'\nimport { decodeEffectContract } from './schema'\n// oxlint-disable-next-line cvx/component-boundaries -- SAFETY: Internal optional adapter shares the Effect-free Foundation lifecycle and types without entering the Convex component deployment graph.\nimport {\n\tObservability,\n\ttype ObservabilityOptions,\n} from '../../components/foundation/modules/observability/observability'\nimport { normalizeEffect, observationFailure } from './normalize'\nimport {\n\teffectOperationFactory,\n\ttype CallbackError,\n\ttype CallbackRequirements,\n\ttype EffectOperationArgument,\n\ttype EffectOperationError,\n\ttype EffectOperationRequirements,\n\ttype EffectOperationResult,\n\ttype EffectValue,\n\ttype CheckedEffectOperation,\n\ttype UnwrappedDefaultError,\n\ttype UnwrappedDefaultRequirements,\n\ttype ValidatedEffectOperations,\n} from './operation'\n\ntype Supported<Value> = Value | PromiseLike<Value> | Effect.Effect<Value, unknown, unknown>\ntype QueryDefinition = {\n\tinput: ContractSchema\n\tresult: ContractSchema\n\t// oxlint-disable-next-line anti-slop/no-unknown-returns -- Internal heterogeneous storage; selected schemas restore the concrete result at exec.\n\thandler: (input: never, context: never) => unknown\n\tclassification?: string\n\tpermission?: string\n\tmetadata?: object\n\t// oxlint-disable-next-line anti-slop/no-unknown-returns -- Internal hook storage retains the concrete definition separately.\n\tguard?: (context: never, input: never) => unknown\n\t// oxlint-disable-next-line anti-slop/no-unknown-returns -- Internal hook storage retains the concrete definition separately.\n\tmiddleware?: (input: never) => unknown\n}\ntype QueryRegistry<Context> = Readonly<\n\tRecord<\n\t\tstring,\n\t\tPick<QueryDefinition, 'input' | 'result' | 'handler'> &\n\t\t\tCheckedEffectOperation<Context> & {\n\t\t\t\tprepare?: never\n\t\t\t\taudit?: never\n\t\t\t\taggregates?: never\n\t\t\t\treplayResult?: never\n\t\t\t}\n\t>\n>\ntype OperationKey<Operations> = Extract<keyof Operations, string>\n\nclass QueryMiddlewareError extends Error {\n\treadonly code = 'QUERY_MIDDLEWARE_NEXT_REUSED'\n\treadonly name = 'QueryMiddlewareError'\n\tconstructor() {\n\t\tsuper('A query middleware called next() more than once')\n\t}\n}\nclass QueryConfigurationError extends Error {\n\treadonly code = 'QUERY_OPERATION_NOT_CONFIGURED'\n\treadonly name = 'QueryConfigurationError'\n\tconstructor() {\n\t\tsuper('The selected query operation is not configured')\n\t}\n}\nclass QueryPermissionError extends Error {\n\treadonly code = 'QUERY_PERMISSION_CHECKER_MISSING'\n\treadonly name = 'QueryPermissionError'\n\tconstructor() {\n\t\tsuper('Query permission requires an injected permission checker')\n\t}\n}\n\n/** Injectable domain queries compose lazily; the API chooses native function kind. */\nexport function createEffectQuery<\n\tHost,\n\tContextReturned,\n\tconst Operations extends QueryRegistry<EffectValue<ContextReturned>>,\n\tPermissionReturned = never,\n\tGuardReturned extends Supported<void> = never,\n>(configuration: {\n\tcontext: (host: Host) => ContextReturned\n\toperations: (\n\t\tdefinitions: ReturnType<\n\t\t\ttypeof effectOperationFactory<\n\t\t\t\tEffectValue<ContextReturned>,\n\t\t\t\tRecord<never, never>,\n\t\t\t\tNoInfer<CallbackError<GuardReturned>>,\n\t\t\t\tNoInfer<CallbackRequirements<GuardReturned>>\n\t\t\t>\n\t\t>,\n\t) => Operations & NoInfer<ValidatedEffectOperations<Operations>>\n\tcheckPermission?: (\n\t\thost: Host,\n\t\tinput: { permission: string; operation: string },\n\t) => PermissionReturned\n\tdefaults?: { metadata?: object; guard?: (context: EffectValue<ContextReturned>) => GuardReturned }\n\tobservability?: ObservabilityOptions | Observability\n}) {\n\tconst definitions = effectOperationFactory<\n\t\tEffectValue<ContextReturned>,\n\t\tRecord<never, never>,\n\t\tCallbackError<GuardReturned>,\n\t\tCallbackRequirements<GuardReturned>\n\t>()\n\tconst operations: Operations = configuration.operations(definitions)\n\tconst observability =\n\t\tconfiguration.observability instanceof Observability\n\t\t\t? configuration.observability\n\t\t\t: new Observability(\n\t\t\t\t\tconfiguration.observability ?? {\n\t\t\t\t\t\tenabled: false,\n\t\t\t\t\t\tclassifyError: () => ({ outcome: 'failed', errorCode: 'UNEXPECTED' }),\n\t\t\t\t\t},\n\t\t\t\t)\n\n\tfunction exec<const Key extends OperationKey<Operations>>(\n\t\toperation: Key,\n\t\tinput: EffectOperationArgument<Operations[Key]>,\n\t\thost: Host,\n\t): Effect.Effect<\n\t\tEffectOperationResult<Operations[Key]>,\n\t\t| EffectOperationError<Operations[Key]>\n\t\t| CallbackError<ContextReturned | PermissionReturned>\n\t\t| UnwrappedDefaultError<Operations[Key], GuardReturned>,\n\t\t| EffectOperationRequirements<Operations[Key]>\n\t\t| CallbackRequirements<ContextReturned | PermissionReturned>\n\t\t| UnwrappedDefaultRequirements<Operations[Key], GuardReturned>\n\t> {\n\t\tconst execution = Effect.suspend(() => {\n\t\t\tif (!Object.prototype.hasOwnProperty.call(operations, operation)) {\n\t\t\t\treturn Effect.die(new QueryConfigurationError())\n\t\t\t}\n\t\t\t// SAFETY: operation helpers check hooks before this heterogeneous storage seam.\n\t\t\tconst definition: QueryDefinition = operations[operation]\n\t\t\treturn Effect.flatMap(decodeEffectContract(definition.input, input), (parsedInput) => {\n\t\t\t\tconst observation = observability.start({\n\t\t\t\t\toperation,\n\t\t\t\t\tclassification: definition.classification ?? 'query',\n\t\t\t\t})\n\t\t\t\tconst run = Effect.gen(function* () {\n\t\t\t\t\tif (definition.permission !== undefined) {\n\t\t\t\t\t\tconst check = configuration.checkPermission\n\t\t\t\t\t\tif (!check) return yield* Effect.die(new QueryPermissionError())\n\t\t\t\t\t\tyield* normalizeEffect(() =>\n\t\t\t\t\t\t\tcheck(host, { permission: definition.permission!, operation }),\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t\tconst context = yield* normalizeEffect(() => configuration.context(host))\n\t\t\t\t\tconst metadata = { ...configuration.defaults?.metadata, ...definition.metadata }\n\t\t\t\t\tconst core = (current: EffectValue<ContextReturned>) =>\n\t\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\t\tconst guard = configuration.defaults?.guard\n\t\t\t\t\t\t\tif (guard) yield* normalizeEffect(() => guard(current))\n\t\t\t\t\t\t\tif (definition.guard)\n\t\t\t\t\t\t\t\tyield* normalizeEffect(() => {\n\t\t\t\t\t\t\t\t\t// SAFETY: selected schemas and context own the stored guard parameters.\n\t\t\t\t\t\t\t\t\treturn definition.guard!(current as never, parsedInput as never)\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\treturn yield* normalizeEffect(() => {\n\t\t\t\t\t\t\t\t// SAFETY: selected schemas and context own the stored handler parameters.\n\t\t\t\t\t\t\t\treturn definition.handler(parsedInput as never, current as never)\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t})\n\t\t\t\t\tlet usedNext = false\n\t\t\t\t\tconst middleware = definition.middleware\n\t\t\t\t\tconst output = middleware\n\t\t\t\t\t\t? yield* normalizeEffect(() => {\n\t\t\t\t\t\t\t\t// SAFETY: the selected helper checked this middleware's input and next contract.\n\t\t\t\t\t\t\t\treturn middleware({\n\t\t\t\t\t\t\t\t\toperation,\n\t\t\t\t\t\t\t\t\tinput: parsedInput,\n\t\t\t\t\t\t\t\t\tcommand: parsedInput,\n\t\t\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\t\t\tmetadata,\n\t\t\t\t\t\t\t\t\tnext: (options?: { context?: object }) =>\n\t\t\t\t\t\t\t\t\t\tEffect.suspend(() => {\n\t\t\t\t\t\t\t\t\t\t\tif (usedNext) return Effect.die(new QueryMiddlewareError())\n\t\t\t\t\t\t\t\t\t\t\tusedNext = true\n\t\t\t\t\t\t\t\t\t\t\treturn core(\n\t\t\t\t\t\t\t\t\t\t\t\toptions?.context ? Object.assign({}, context, options.context) : context,\n\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t} as never)\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t: yield* core(context)\n\t\t\t\t\treturn yield* decodeEffectContract(definition.result, output)\n\t\t\t\t})\n\t\t\t\treturn run.pipe(\n\t\t\t\t\tEffect.onExit((exit) =>\n\t\t\t\t\t\tEffect.sync(() => {\n\t\t\t\t\t\t\tif (Exit.isSuccess(exit)) observation.completed()\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tobservation.failed(observationFailure(exit.cause))\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t})\n\t\t})\n\t\t// SAFETY: selected schemas own A; concrete callbacks and the wrapped middleware\n\t\t// own E/R. No interpreter or runner executes this Effect before the caller does.\n\t\treturn execution as ReturnType<typeof exec<Key>>\n\t}\n\tfunction expose<const Owner extends symbol, const Key extends OperationKey<Operations>>(\n\t\towner: Owner,\n\t\toperation: Key,\n\t): SelectedOperation<\n\t\tOwner,\n\t\tKey,\n\t\tOperations[Key]['input'],\n\t\tOperationPublicResult<Operations[Key]>\n\t> {\n\t\tif (!Object.hasOwn(operations, operation)) throw new QueryConfigurationError()\n\t\treturn selectOperation(owner, 'query', operation, operations[operation])\n\t}\n\treturn {\n\t\texec,\n\t\texpose,\n\t\t/** Bind invocation context without resolving it or running an operation. */\n\t\twithContext(context: Host) {\n\t\t\treturn {\n\t\t\t\texec: <const Key extends OperationKey<Operations>>(\n\t\t\t\t\toperation: Key,\n\t\t\t\t\tinput: EffectOperationArgument<Operations[Key]>,\n\t\t\t\t) => exec(operation, input, context),\n\t\t\t}\n\t\t},\n\t}\n}\n\ntype Policy<Dependencies> = 'checkPermission' extends keyof Dependencies\n\t? Dependencies['checkPermission']\n\t: never\n// oxlint-disable-next-line anti-slop/no-unknown-returns -- Conditional type extracts the host; no unknown result is exposed by the registry.\ntype CallbackHost<Callback> = Callback extends (host: infer Host, input: never) => unknown\n\t? Host\n\t: never\ntype CallbackReturned<Callback> = Callback extends (...arguments_: never[]) => infer Returned\n\t? Returned\n\t: never\ntype PolicyHost<Dependencies> = [CallbackHost<Policy<Dependencies>>] extends [never]\n\t? unknown\n\t: CallbackHost<Policy<Dependencies>>\ntype PolicyReturned<Dependencies> = CallbackReturned<Policy<Dependencies>>\nexport type EffectQueryDependencies = {\n\tobservability: Observability\n\t// oxlint-disable-next-line anti-slop/no-unknown-returns -- Host policy storage is erased; the bound generic dependency retains its concrete E/R.\n\tcheckPermission?: (host: never, input: { permission: string; operation: string }) => unknown\n}\n\n/** The public Foundation binds trusted application policies once. */\nexport function bindEffectQuery<const Dependencies extends EffectQueryDependencies>(\n\tdependencies: Dependencies,\n) {\n\treturn function query<\n\t\tHost extends PolicyHost<Dependencies>,\n\t\tContextReturned,\n\t\tconst Operations extends QueryRegistry<EffectValue<ContextReturned>>,\n\t\tGuardReturned extends Supported<void> = never,\n\t>(configuration: {\n\t\tcontext: (host: Host) => ContextReturned\n\t\toperations: (\n\t\t\tdefinitions: ReturnType<\n\t\t\t\ttypeof effectOperationFactory<\n\t\t\t\t\tEffectValue<ContextReturned>,\n\t\t\t\t\tRecord<never, never>,\n\t\t\t\t\tNoInfer<CallbackError<GuardReturned>>,\n\t\t\t\t\tNoInfer<CallbackRequirements<GuardReturned>>\n\t\t\t\t>\n\t\t\t>,\n\t\t) => Operations & NoInfer<ValidatedEffectOperations<Operations>>\n\t\tdefaults?: {\n\t\t\tmetadata?: object\n\t\t\tguard?: (context: EffectValue<ContextReturned>) => GuardReturned\n\t\t}\n\t}): ReturnType<\n\t\ttypeof createEffectQuery<\n\t\t\tHost,\n\t\t\tContextReturned,\n\t\t\tOperations,\n\t\t\tPolicyReturned<Dependencies>,\n\t\t\tGuardReturned\n\t\t>\n\t> {\n\t\t// SAFETY: Host is constrained to the trusted checker's host type; its concrete\n\t\t// return is retained while restoring the erased invocation argument slot.\n\t\tconst checkPermission = dependencies.checkPermission as (\n\t\t\thost: Host,\n\t\t\tinput: { permission: string; operation: string },\n\t\t) => PolicyReturned<Dependencies>\n\t\treturn createEffectQuery<\n\t\t\tHost,\n\t\t\tContextReturned,\n\t\t\tOperations,\n\t\t\tPolicyReturned<Dependencies>,\n\t\t\tGuardReturned\n\t\t>({\n\t\t\t...configuration,\n\t\t\tobservability: dependencies.observability,\n\t\t\tcheckPermission: dependencies.checkPermission ? checkPermission : undefined,\n\t\t})\n\t}\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"query.mjs","names":["QueryMiddlewareError","QueryConfigurationError","QueryPermissionError","createEffectQuery","definitions","effectOperationFactory","operations","configuration","observability","Observability","exec","Effect","operation","definition","decodeEffectContract","input","observation","check","normalizeEffect","host","context","metadata","core","guard","current","parsedInput","usedNext","middleware","output","options","Exit","exit","observationFailure","expose","selectOperation","owner","bindEffectQuery","checkPermission","dependencies"],"sources":["../../../src/modules/effect/query.ts"],"sourcesContent":["import { Effect, Exit } from 'effect'\nimport type { ContractSchema } from '../contracts/contract'\nimport {\n\tselectOperation,\n\ttype SelectedOperation,\n\ttype OperationPublicResult,\n} from '../contracts/exposure'\nimport { decodeEffectContract } from './schema'\n// oxlint-disable-next-line cvx/component-boundaries -- SAFETY: Internal optional adapter shares the Effect-free Foundation lifecycle and types without entering the Convex component deployment graph.\nimport {\n\tObservability,\n\ttype ObservabilityOptions,\n} from '../../components/foundation/modules/observability/observability'\nimport { normalizeEffect, observationFailure } from './normalize'\nimport {\n\teffectOperationFactory,\n\ttype CallbackError,\n\ttype CallbackRequirements,\n\ttype EffectOperationArgument,\n\ttype EffectOperationError,\n\ttype EffectOperationRequirements,\n\ttype EffectOperationResult,\n\ttype EffectValue,\n\ttype CheckedEffectOperation,\n\ttype UnwrappedDefaultError,\n\ttype UnwrappedDefaultRequirements,\n\ttype ValidatedEffectOperations,\n} from './operation'\n\ntype Supported<Value> = Value | PromiseLike<Value> | Effect.Effect<Value, unknown, unknown>\ntype QueryDefinition = {\n\tinput: ContractSchema\n\tresult: ContractSchema\n\t// oxlint-disable-next-line anti-slop/no-unknown-returns -- Internal heterogeneous storage; selected schemas restore the concrete result at exec.\n\thandler: (input: never, context: never) => unknown\n\tclassification?: string\n\tpermission?: string\n\tmetadata?: object\n\t// oxlint-disable-next-line anti-slop/no-unknown-returns -- Internal hook storage retains the concrete definition separately.\n\tguard?: (context: never, input: never) => unknown\n\t// oxlint-disable-next-line anti-slop/no-unknown-returns -- Internal hook storage retains the concrete definition separately.\n\tmiddleware?: (input: never) => unknown\n}\ntype QueryRegistry<Context> = Readonly<\n\tRecord<\n\t\tstring,\n\t\tPick<QueryDefinition, 'input' | 'result' | 'handler'> &\n\t\t\tCheckedEffectOperation<Context> & {\n\t\t\t\tprepare?: never\n\t\t\t\taudit?: never\n\t\t\t\taggregates?: never\n\t\t\t\treplayResult?: never\n\t\t\t}\n\t>\n>\ntype OperationKey<Operations> = Extract<keyof Operations, string>\n\nclass QueryMiddlewareError extends Error {\n\treadonly code = 'QUERY_MIDDLEWARE_NEXT_REUSED'\n\treadonly name = 'QueryMiddlewareError'\n\tconstructor() {\n\t\tsuper('A query middleware called next() more than once')\n\t}\n}\nclass QueryConfigurationError extends Error {\n\treadonly code = 'QUERY_OPERATION_NOT_CONFIGURED'\n\treadonly name = 'QueryConfigurationError'\n\tconstructor() {\n\t\tsuper('The selected query operation is not configured')\n\t}\n}\nclass QueryPermissionError extends Error {\n\treadonly code = 'QUERY_PERMISSION_CHECKER_MISSING'\n\treadonly name = 'QueryPermissionError'\n\tconstructor() {\n\t\tsuper('Query permission requires an injected permission checker')\n\t}\n}\n\n/** Injectable domain queries compose lazily; the API chooses native function kind. */\nexport function createEffectQuery<\n\tHost,\n\tContextReturned,\n\tconst Operations extends QueryRegistry<EffectValue<ContextReturned>>,\n\tPermissionReturned = never,\n\tGuardReturned extends Supported<void> = never,\n>(configuration: {\n\tcontext: (host: Host) => ContextReturned\n\toperations: (\n\t\tdefinitions: ReturnType<\n\t\t\ttypeof effectOperationFactory<\n\t\t\t\tEffectValue<ContextReturned>,\n\t\t\t\tRecord<never, never>,\n\t\t\t\tNoInfer<CallbackError<GuardReturned>>,\n\t\t\t\tNoInfer<CallbackRequirements<GuardReturned>>\n\t\t\t>\n\t\t>,\n\t) => Operations & NoInfer<ValidatedEffectOperations<Operations>>\n\tcheckPermission?: (\n\t\thost: Host,\n\t\tinput: { permission: string; operation: string },\n\t) => PermissionReturned\n\tdefaults?: { metadata?: object; guard?: (context: EffectValue<ContextReturned>) => GuardReturned }\n\tobservability?: ObservabilityOptions | Observability\n}) {\n\tconst definitions = effectOperationFactory<\n\t\tEffectValue<ContextReturned>,\n\t\tRecord<never, never>,\n\t\tCallbackError<GuardReturned>,\n\t\tCallbackRequirements<GuardReturned>\n\t>()\n\tconst operations: Operations = configuration.operations(definitions)\n\tconst observability =\n\t\tconfiguration.observability instanceof Observability\n\t\t\t? configuration.observability\n\t\t\t: new Observability(\n\t\t\t\t\tconfiguration.observability ?? {\n\t\t\t\t\t\tenabled: false,\n\t\t\t\t\t\tclassifyError: () => ({ outcome: 'failed', errorCode: 'UNEXPECTED' }),\n\t\t\t\t\t},\n\t\t\t\t)\n\n\tfunction exec<const Key extends OperationKey<Operations>>(\n\t\toperation: Key,\n\t\tinput: EffectOperationArgument<Operations[Key]>,\n\t\thost: Host,\n\t): Effect.Effect<\n\t\tEffectOperationResult<Operations[Key]>,\n\t\t| EffectOperationError<Operations[Key]>\n\t\t| CallbackError<ContextReturned | PermissionReturned>\n\t\t| UnwrappedDefaultError<Operations[Key], GuardReturned>,\n\t\t| EffectOperationRequirements<Operations[Key]>\n\t\t| CallbackRequirements<ContextReturned | PermissionReturned>\n\t\t| UnwrappedDefaultRequirements<Operations[Key], GuardReturned>\n\t> {\n\t\tconst execution = Effect.suspend(() => {\n\t\t\tif (!Object.prototype.hasOwnProperty.call(operations, operation)) {\n\t\t\t\treturn Effect.die(new QueryConfigurationError())\n\t\t\t}\n\t\t\t// SAFETY: operation helpers check hooks before this heterogeneous storage seam.\n\t\t\tconst definition: QueryDefinition = operations[operation]\n\t\t\treturn Effect.flatMap(decodeEffectContract(definition.input, input), (parsedInput) => {\n\t\t\t\tconst observation = observability.start({\n\t\t\t\t\toperation,\n\t\t\t\t\tclassification: definition.classification ?? 'query',\n\t\t\t\t})\n\t\t\t\tconst run = Effect.gen(function* () {\n\t\t\t\t\tif (definition.permission !== undefined) {\n\t\t\t\t\t\tconst check = configuration.checkPermission\n\t\t\t\t\t\tif (!check) return yield* Effect.die(new QueryPermissionError())\n\t\t\t\t\t\tyield* normalizeEffect(() =>\n\t\t\t\t\t\t\tcheck(host, { permission: definition.permission!, operation }),\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t\tconst context = yield* normalizeEffect(() => configuration.context(host))\n\t\t\t\t\tconst metadata = { ...configuration.defaults?.metadata, ...definition.metadata }\n\t\t\t\t\tconst core = (current: EffectValue<ContextReturned>) =>\n\t\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\t\tconst guard = configuration.defaults?.guard\n\t\t\t\t\t\t\tif (guard) yield* normalizeEffect(() => guard(current))\n\t\t\t\t\t\t\tif (definition.guard)\n\t\t\t\t\t\t\t\tyield* normalizeEffect(() => {\n\t\t\t\t\t\t\t\t\t// SAFETY: selected schemas and context own the stored guard parameters.\n\t\t\t\t\t\t\t\t\treturn definition.guard!(current as never, parsedInput as never)\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\treturn yield* normalizeEffect(() => {\n\t\t\t\t\t\t\t\t// SAFETY: selected schemas and context own the stored handler parameters.\n\t\t\t\t\t\t\t\treturn definition.handler(parsedInput as never, current as never)\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t})\n\t\t\t\t\tlet usedNext = false\n\t\t\t\t\tconst middleware = definition.middleware\n\t\t\t\t\tconst output = middleware\n\t\t\t\t\t\t? yield* normalizeEffect(() => {\n\t\t\t\t\t\t\t\t// SAFETY: the selected helper checked this middleware's input and next contract.\n\t\t\t\t\t\t\t\treturn middleware({\n\t\t\t\t\t\t\t\t\toperation,\n\t\t\t\t\t\t\t\t\tinput: parsedInput,\n\t\t\t\t\t\t\t\t\tcommand: parsedInput,\n\t\t\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\t\t\tmetadata,\n\t\t\t\t\t\t\t\t\tnext: (options?: { context?: object }) =>\n\t\t\t\t\t\t\t\t\t\tEffect.suspend(() => {\n\t\t\t\t\t\t\t\t\t\t\tif (usedNext) return Effect.die(new QueryMiddlewareError())\n\t\t\t\t\t\t\t\t\t\t\tusedNext = true\n\t\t\t\t\t\t\t\t\t\t\treturn core(\n\t\t\t\t\t\t\t\t\t\t\t\toptions?.context ? Object.assign({}, context, options.context) : context,\n\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t} as never)\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t: yield* core(context)\n\t\t\t\t\treturn yield* decodeEffectContract(definition.result, output)\n\t\t\t\t})\n\t\t\t\treturn run.pipe(\n\t\t\t\t\tEffect.onExit((exit) =>\n\t\t\t\t\t\tEffect.sync(() => {\n\t\t\t\t\t\t\tif (Exit.isSuccess(exit)) observation.completed()\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tobservation.failed(observationFailure(exit.cause))\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t})\n\t\t})\n\t\t// SAFETY: selected schemas own A; concrete callbacks and the wrapped middleware\n\t\t// own E/R. No interpreter or runner executes this Effect before the caller does.\n\t\treturn execution as ReturnType<typeof exec<Key>>\n\t}\n\tfunction expose<const Owner extends symbol, const Key extends OperationKey<Operations>>(\n\t\towner: Owner,\n\t\toperation: Key,\n\t): SelectedOperation<\n\t\tOwner,\n\t\tKey,\n\t\tOperations[Key]['input'],\n\t\tOperationPublicResult<Operations[Key]>\n\t> {\n\t\tif (!Object.hasOwn(operations, operation)) throw new QueryConfigurationError()\n\t\treturn selectOperation(owner, 'query', operation, operations[operation])\n\t}\n\treturn {\n\t\texec,\n\t\texpose,\n\t\t/** Bind invocation context without resolving it or running an operation. */\n\t\twithContext(context: Host) {\n\t\t\treturn {\n\t\t\t\texec: <const Key extends OperationKey<Operations>>(\n\t\t\t\t\toperation: Key,\n\t\t\t\t\tinput: EffectOperationArgument<Operations[Key]>,\n\t\t\t\t) => exec(operation, input, context),\n\t\t\t}\n\t\t},\n\t}\n}\n\ntype Policy<Dependencies> = 'checkPermission' extends keyof Dependencies\n\t? Dependencies['checkPermission']\n\t: never\n// oxlint-disable-next-line anti-slop/no-unknown-returns -- Conditional type extracts the host; no unknown result is exposed by the registry.\ntype CallbackHost<Callback> = Callback extends (host: infer Host, input: never) => unknown\n\t? Host\n\t: never\ntype CallbackReturned<Callback> = Callback extends (...arguments_: never[]) => infer Returned\n\t? Returned\n\t: never\ntype PolicyHost<Dependencies> = [CallbackHost<Policy<Dependencies>>] extends [never]\n\t? unknown\n\t: CallbackHost<Policy<Dependencies>>\ntype PolicyReturned<Dependencies> = CallbackReturned<Policy<Dependencies>>\nexport type EffectQueryDependencies = {\n\tobservability: Observability\n\t// oxlint-disable-next-line anti-slop/no-unknown-returns -- Host policy storage is erased; the bound generic dependency retains its concrete E/R.\n\tcheckPermission?: (host: never, input: { permission: string; operation: string }) => unknown\n}\n\n/** The public Foundation binds trusted application policies once. */\nexport function bindEffectQuery<const Dependencies extends EffectQueryDependencies>(\n\tdependencies: Dependencies,\n) {\n\treturn function query<\n\t\tHost extends PolicyHost<Dependencies>,\n\t\tContextReturned,\n\t\tconst Operations extends QueryRegistry<EffectValue<ContextReturned>>,\n\t\tGuardReturned extends Supported<void> = never,\n\t>(configuration: {\n\t\tcontext: (host: Host) => ContextReturned\n\t\toperations: (\n\t\t\tdefinitions: ReturnType<\n\t\t\t\ttypeof effectOperationFactory<\n\t\t\t\t\tEffectValue<ContextReturned>,\n\t\t\t\t\tRecord<never, never>,\n\t\t\t\t\tNoInfer<CallbackError<GuardReturned>>,\n\t\t\t\t\tNoInfer<CallbackRequirements<GuardReturned>>\n\t\t\t\t>\n\t\t\t>,\n\t\t) => Operations & NoInfer<ValidatedEffectOperations<Operations>>\n\t\tdefaults?: {\n\t\t\tmetadata?: object\n\t\t\tguard?: (context: EffectValue<ContextReturned>) => GuardReturned\n\t\t}\n\t}): ReturnType<\n\t\ttypeof createEffectQuery<\n\t\t\tHost,\n\t\t\tContextReturned,\n\t\t\tOperations,\n\t\t\tPolicyReturned<Dependencies>,\n\t\t\tGuardReturned\n\t\t>\n\t> {\n\t\t// SAFETY: Host is constrained to the trusted checker's host type; its concrete\n\t\t// return is retained while restoring the erased invocation argument slot.\n\t\tconst checkPermission = dependencies.checkPermission as (\n\t\t\thost: Host,\n\t\t\tinput: { permission: string; operation: string },\n\t\t) => PolicyReturned<Dependencies>\n\t\treturn createEffectQuery<\n\t\t\tHost,\n\t\t\tContextReturned,\n\t\t\tOperations,\n\t\t\tPolicyReturned<Dependencies>,\n\t\t\tGuardReturned\n\t\t>({\n\t\t\t...configuration,\n\t\t\tobservability: dependencies.observability,\n\t\t\tcheckPermission: dependencies.checkPermission ? checkPermission : undefined,\n\t\t})\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { ContractOutput, ContractSchema, Decoder, LegacyParser, ValidationIssue } from "../contracts/contract.mjs";
|
|
2
2
|
import { Effect, Schema } from "effect";
|
|
3
3
|
//#region src/modules/effect/schema.d.ts
|
|
4
|
-
declare class ContractValidationError {
|
|
4
|
+
export declare class ContractValidationError {
|
|
5
5
|
readonly issues: readonly ValidationIssue[];
|
|
6
6
|
readonly _tag = "ContractValidationError";
|
|
7
7
|
constructor(issues: readonly ValidationIssue[]);
|
|
8
8
|
}
|
|
9
|
-
interface EffectDecoder<Input, Output, Error = never, Requirements = never> extends Decoder<Input, Output, Effect.Effect<Output, Error, Requirements>> {
|
|
9
|
+
export interface EffectDecoder<Input, Output, Error = never, Requirements = never> extends Decoder<Input, Output, Effect.Effect<Output, Error, Requirements>> {
|
|
10
10
|
readonly kind: 'effect-contract';
|
|
11
11
|
}
|
|
12
12
|
/** Explicit custom decoders preserve their exact typed error and service channels. */
|
|
13
|
-
declare function effectContract<Input, Output, Error = never, Requirements = never>(decode: (value: unknown) => Effect.Effect<Output, Error, Requirements>): EffectDecoder<Input, Output, Error, Requirements>;
|
|
13
|
+
export declare function effectContract<Input, Output, Error = never, Requirements = never>(decode: (value: unknown) => Effect.Effect<Output, Error, Requirements>): EffectDecoder<Input, Output, Error, Requirements>;
|
|
14
14
|
/** Encoding requirements remain independent of the decoder's requirements. */
|
|
15
|
-
declare function effectSchema<const S extends Schema.Constraint>(schema: S): {
|
|
15
|
+
export declare function effectSchema<const S extends Schema.Constraint>(schema: S): {
|
|
16
16
|
types?: {
|
|
17
17
|
readonly input: S["Encoded"];
|
|
18
18
|
readonly output: S["Type"];
|
|
@@ -23,11 +23,10 @@ declare function effectSchema<const S extends Schema.Constraint>(schema: S): {
|
|
|
23
23
|
encode: (input: S["Type"], options?: import("effect/SchemaAST").ParseOptions) => Effect.Effect<S["Encoded"], Schema.SchemaError, S["EncodingServices"]>;
|
|
24
24
|
};
|
|
25
25
|
/** The service-free bridge cannot erase decoder requirements. */
|
|
26
|
-
declare function effectStandardSchema<const S extends Schema.ConstraintDecoder<unknown>>(schema: S): import("effect/StandardSchema").StandardSchemaV1<S["Encoded"], S["Type"]> & S;
|
|
27
|
-
type ContractDecoderError<S> = S extends EffectDecoder<unknown, unknown, infer Error, unknown> ? Error : S extends LegacyParser ? never : S extends ContractSchema ? ContractValidationError : never;
|
|
28
|
-
type ContractDecoderRequirements<S> = S extends EffectDecoder<unknown, unknown, unknown, infer Requirements> ? Requirements : never;
|
|
26
|
+
export declare function effectStandardSchema<const S extends Schema.ConstraintDecoder<unknown>>(schema: S): import("effect/StandardSchema").StandardSchemaV1<S["Encoded"], S["Type"]> & S;
|
|
27
|
+
export type ContractDecoderError<S> = S extends EffectDecoder<unknown, unknown, infer Error, unknown> ? Error : S extends LegacyParser ? never : S extends ContractSchema ? ContractValidationError : never;
|
|
28
|
+
export type ContractDecoderRequirements<S> = S extends EffectDecoder<unknown, unknown, unknown, infer Requirements> ? Requirements : never;
|
|
29
29
|
/** Decode input, fresh results, and final replay values within the current Effect scope. */
|
|
30
|
-
declare function decodeEffectContract<S extends ContractSchema>(schema: S, value: unknown): Effect.Effect<ContractOutput<S>, ContractDecoderError<S>, ContractDecoderRequirements<S>>;
|
|
30
|
+
export declare function decodeEffectContract<S extends ContractSchema>(schema: S, value: unknown): Effect.Effect<ContractOutput<S>, ContractDecoderError<S>, ContractDecoderRequirements<S>>;
|
|
31
31
|
//#endregion
|
|
32
|
-
export { ContractDecoderError, ContractDecoderRequirements, ContractValidationError, EffectDecoder, decodeEffectContract, effectContract, effectSchema, effectStandardSchema };
|
|
33
32
|
//# sourceMappingURL=schema.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.mjs","names":[],"sources":["../../../src/modules/effect/schema.ts"],"sourcesContent":["/* oxlint-disable anti-slop/no-unknown-parameters -- Explicit schema decoder boundaries validate untrusted transport input. */\nimport { Effect, Schema } from 'effect'\nimport type {\n\tContractSchema,\n\tContractOutput,\n\tDecoder,\n\tLegacyParser,\n\tNeutralSchema,\n\tValidationIssue,\n} from '../contracts/contract'\nimport { decodeContract } from '../contracts/contract'\n\nexport class ContractValidationError {\n\treadonly _tag = 'ContractValidationError'\n\tconstructor(readonly issues: readonly ValidationIssue[]) {}\n}\nexport interface EffectDecoder<Input, Output, Error = never, Requirements = never> extends Decoder<\n\tInput,\n\tOutput,\n\tEffect.Effect<Output, Error, Requirements>\n> {\n\treadonly kind: 'effect-contract'\n}\n/** Explicit custom decoders preserve their exact typed error and service channels. */\nexport function effectContract<Input, Output, Error = never, Requirements = never>(\n\tdecode: (value: unknown) => Effect.Effect<Output, Error, Requirements>,\n): EffectDecoder<Input, Output, Error, Requirements> {\n\treturn { kind: 'effect-contract', decode }\n}\n/** Encoding requirements remain independent of the decoder's requirements. */\nexport function effectSchema<const S extends Schema.Constraint>(schema: S) {\n\treturn {\n\t\t...effectContract<S['Encoded'], S['Type'], Schema.SchemaError, S['DecodingServices']>(\n\t\t\tSchema.decodeUnknownEffect(schema),\n\t\t),\n\t\tschema,\n\t\tencode: Schema.encodeEffect(schema),\n\t}\n}\n/** The service-free bridge cannot erase decoder requirements. */\nexport function effectStandardSchema<const S extends Schema.ConstraintDecoder<unknown>>(schema: S) {\n\treturn Schema.toStandardSchemaV1(schema)\n}\nexport type ContractDecoderError<S> =\n\tS extends EffectDecoder<unknown, unknown, infer Error, unknown>\n\t\t? Error\n\t\t: S extends LegacyParser\n\t\t\t? never\n\t\t\t: S extends ContractSchema\n\t\t\t\t? ContractValidationError\n\t\t\t\t: never\nexport type ContractDecoderRequirements<S> =\n\tS extends EffectDecoder<unknown, unknown, unknown, infer Requirements> ? Requirements : never\n\n/** Decode input, fresh results, and final replay values within the current Effect scope. */\nexport function decodeEffectContract<S extends ContractSchema>(\n\tschema: S,\n\tvalue: unknown,\n): Effect.Effect<ContractOutput<S>, ContractDecoderError<S>, ContractDecoderRequirements<S>> {\n\tconst decoded = Effect.suspend(() => {\n\t\tif ('kind' in schema && schema.kind === 'effect-contract') {\n\t\t\t// SAFETY: only the explicit optional adapter exposes this discriminator.\n\t\t\treturn schema.decode(value) as Effect.Effect<unknown, unknown, unknown>\n\t\t}\n\t\t// SAFETY: the Effect discriminator was excluded; ordinary adapters return validation results.\n\t\treturn Effect.promise(() => decodeContract(schema as NeutralSchema, value)).pipe(\n\t\t\tEffect.flatMap((result) => {\n\t\t\t\tif (!result.issues) return Effect.succeed(result.value)\n\t\t\t\tconst error = new ContractValidationError(result.issues)\n\t\t\t\t// Legacy parsers have always exposed validation throws as defects.\n\t\t\t\treturn 'parse' in schema ? Effect.die(error) : Effect.fail(error)\n\t\t\t}),\n\t\t)\n\t})\n\t// SAFETY: conditional channels correspond to the explicit Effect branch or neutral validation branch.\n\treturn decoded as Effect.Effect<\n\t\tContractOutput<S>,\n\t\tContractDecoderError<S>,\n\t\tContractDecoderRequirements<S>\n\t>\n}\n"],"mappings":"uGAYA,
|
|
1
|
+
{"version":3,"file":"schema.mjs","names":["ContractValidationError","issues","effectContract","effectSchema","Schema","schema","effectStandardSchema","decodeEffectContract","Effect","value","decodeContract","result","error"],"sources":["../../../src/modules/effect/schema.ts"],"sourcesContent":["/* oxlint-disable anti-slop/no-unknown-parameters -- Explicit schema decoder boundaries validate untrusted transport input. */\nimport { Effect, Schema } from 'effect'\nimport type {\n\tContractSchema,\n\tContractOutput,\n\tDecoder,\n\tLegacyParser,\n\tNeutralSchema,\n\tValidationIssue,\n} from '../contracts/contract'\nimport { decodeContract } from '../contracts/contract'\n\nexport class ContractValidationError {\n\treadonly _tag = 'ContractValidationError'\n\tconstructor(readonly issues: readonly ValidationIssue[]) {}\n}\nexport interface EffectDecoder<Input, Output, Error = never, Requirements = never> extends Decoder<\n\tInput,\n\tOutput,\n\tEffect.Effect<Output, Error, Requirements>\n> {\n\treadonly kind: 'effect-contract'\n}\n/** Explicit custom decoders preserve their exact typed error and service channels. */\nexport function effectContract<Input, Output, Error = never, Requirements = never>(\n\tdecode: (value: unknown) => Effect.Effect<Output, Error, Requirements>,\n): EffectDecoder<Input, Output, Error, Requirements> {\n\treturn { kind: 'effect-contract', decode }\n}\n/** Encoding requirements remain independent of the decoder's requirements. */\nexport function effectSchema<const S extends Schema.Constraint>(schema: S) {\n\treturn {\n\t\t...effectContract<S['Encoded'], S['Type'], Schema.SchemaError, S['DecodingServices']>(\n\t\t\tSchema.decodeUnknownEffect(schema),\n\t\t),\n\t\tschema,\n\t\tencode: Schema.encodeEffect(schema),\n\t}\n}\n/** The service-free bridge cannot erase decoder requirements. */\nexport function effectStandardSchema<const S extends Schema.ConstraintDecoder<unknown>>(schema: S) {\n\treturn Schema.toStandardSchemaV1(schema)\n}\nexport type ContractDecoderError<S> =\n\tS extends EffectDecoder<unknown, unknown, infer Error, unknown>\n\t\t? Error\n\t\t: S extends LegacyParser\n\t\t\t? never\n\t\t\t: S extends ContractSchema\n\t\t\t\t? ContractValidationError\n\t\t\t\t: never\nexport type ContractDecoderRequirements<S> =\n\tS extends EffectDecoder<unknown, unknown, unknown, infer Requirements> ? Requirements : never\n\n/** Decode input, fresh results, and final replay values within the current Effect scope. */\nexport function decodeEffectContract<S extends ContractSchema>(\n\tschema: S,\n\tvalue: unknown,\n): Effect.Effect<ContractOutput<S>, ContractDecoderError<S>, ContractDecoderRequirements<S>> {\n\tconst decoded = Effect.suspend(() => {\n\t\tif ('kind' in schema && schema.kind === 'effect-contract') {\n\t\t\t// SAFETY: only the explicit optional adapter exposes this discriminator.\n\t\t\treturn schema.decode(value) as Effect.Effect<unknown, unknown, unknown>\n\t\t}\n\t\t// SAFETY: the Effect discriminator was excluded; ordinary adapters return validation results.\n\t\treturn Effect.promise(() => decodeContract(schema as NeutralSchema, value)).pipe(\n\t\t\tEffect.flatMap((result) => {\n\t\t\t\tif (!result.issues) return Effect.succeed(result.value)\n\t\t\t\tconst error = new ContractValidationError(result.issues)\n\t\t\t\t// Legacy parsers have always exposed validation throws as defects.\n\t\t\t\treturn 'parse' in schema ? Effect.die(error) : Effect.fail(error)\n\t\t\t}),\n\t\t)\n\t})\n\t// SAFETY: conditional channels correspond to the explicit Effect branch or neutral validation branch.\n\treturn decoded as Effect.Effect<\n\t\tContractOutput<S>,\n\t\tContractDecoderError<S>,\n\t\tContractDecoderRequirements<S>\n\t>\n}\n"],"mappings":"uGAYA,IAAaA,EAAb,KAAqC,CAEf,OADrB,KAAgB,0BAChB,YAAY,EAA6C,CAApC,KAAA,OAAAC,CAAqC,CAC3D,EASA,SAAgBC,EACf,EACoD,CACpD,MAAO,CAAE,KAAM,kBAAmB,QAAO,CAC1C,CAEA,SAAgBC,EAAgD,EAAW,CAC1E,MAAO,CACN,GAAGD,EACFE,EAAO,oBAAoBC,CAAM,CAClC,EACA,SACA,OAAQD,EAAO,aAAaC,CAAM,CACnC,CACD,CAEA,SAAgBC,EAAwE,EAAW,CAClG,OAAOF,EAAO,mBAAmBC,CAAM,CACxC,CAaA,SAAgBE,EACf,EACA,EAC4F,CAiB5F,OAhBgBC,EAAO,YAClB,SAAUH,GAAUA,EAAO,OAAS,kBAEhCA,EAAO,OAAOI,CAAK,EAGpBD,EAAO,YAAcE,EAAeL,EAAyBI,CAAK,CAAC,CAAC,CAAC,KAC3ED,EAAO,QAAS,GAAW,CAC1B,GAAI,CAACG,EAAO,OAAQ,OAAOH,EAAO,QAAQG,EAAO,KAAK,EACtD,IAAMC,EAAQ,IAAIZ,EAAwBW,EAAO,MAAM,EAEvD,MAAO,UAAWN,EAASG,EAAO,IAAII,CAAK,EAAIJ,EAAO,KAAKI,CAAK,CACjE,CAAC,CACF,CAGY,CAKd"}
|
|
@@ -8,12 +8,12 @@ import { Effect } from "effect";
|
|
|
8
8
|
//#region src/modules/effect/workflow.d.ts
|
|
9
9
|
type Supported<A> = A | PromiseLike<A> | Effect.Effect<A, unknown, unknown>;
|
|
10
10
|
/** Services exist only inside a new native invocation; ordinary throws/rejections remain defects. */
|
|
11
|
-
declare function effectWorkflowAttempt<Args, Authorize, Execute>(configuration: {
|
|
11
|
+
export declare function effectWorkflowAttempt<Args, Authorize, Execute>(configuration: {
|
|
12
12
|
authorize: (execution: WorkflowExecution<Args>) => Authorize;
|
|
13
13
|
execute: (execution: WorkflowExecution<Args>, authority: EffectValue<Authorize>) => Execute;
|
|
14
14
|
}): (input: WorkflowExecution<Args>) => Effect.Effect<EffectValue<Execute>, WorkflowBindingError | CallbackError<Authorize | Execute>, CallbackRequirements<Authorize | Execute>>;
|
|
15
15
|
/** Native mutation promise rejects outside the child transaction before mapping declared terminal details. */
|
|
16
|
-
declare function effectTerminalWorkflowAttempt<Args, Authorize, const Result extends ContractSchema, const Failure extends ContractSchema, Terminal extends Supported<ContractInput<Failure> | undefined>>(configuration: ({
|
|
16
|
+
export declare function effectTerminalWorkflowAttempt<Args, Authorize, const Result extends ContractSchema, const Failure extends ContractSchema, Terminal extends Supported<ContractInput<Failure> | undefined>>(configuration: ({
|
|
17
17
|
kind: 'mutation';
|
|
18
18
|
atomicJournalProof: 'host-verified';
|
|
19
19
|
} | {
|
|
@@ -27,7 +27,7 @@ declare function effectTerminalWorkflowAttempt<Args, Authorize, const Result ext
|
|
|
27
27
|
failure: Failure;
|
|
28
28
|
}): (input: WorkflowExecution<Args>) => Effect.Effect<WorkflowOutcome<ContractInput<Result>, ContractOutput<Failure>>, WorkflowBindingError | CallbackError<Authorize | Terminal> | ContractDecoderError<Result | Failure>, CallbackRequirements<Authorize | Terminal> | ContractDecoderRequirements<Result | Failure>>;
|
|
29
29
|
declare const protectedMutation: unique symbol;
|
|
30
|
-
interface EffectReceiptProtectedWorkflowMutation<Args, Result, Error, Requirements> {
|
|
30
|
+
export interface EffectReceiptProtectedWorkflowMutation<Args, Result, Error, Requirements> {
|
|
31
31
|
readonly [protectedMutation]: {
|
|
32
32
|
args: Args;
|
|
33
33
|
result: Result;
|
|
@@ -40,7 +40,7 @@ type Completion<Prepare> = Extract<EffectValue<Prepare>, {
|
|
|
40
40
|
complete: (...arguments_: never[]) => infer Returned;
|
|
41
41
|
} ? Returned : never;
|
|
42
42
|
/** Host runs the handler in the secured inner native mutation transaction, including receipt completion. */
|
|
43
|
-
declare function effectReceiptWorkflowMutation<Args, Authorize, const Replay extends ContractSchema, Prepare extends Supported<EffectIdempotencyPreparation<ContractOutput<Replay>, unknown, unknown>>, Execute extends Supported<ContractOutput<Replay>>>(configuration: {
|
|
43
|
+
export declare function effectReceiptWorkflowMutation<Args, Authorize, const Replay extends ContractSchema, Prepare extends Supported<EffectIdempotencyPreparation<ContractOutput<Replay>, unknown, unknown>>, Execute extends Supported<ContractOutput<Replay>>>(configuration: {
|
|
44
44
|
authorize: (execution: WorkflowExecution<Args>) => Authorize;
|
|
45
45
|
receipt: (authority: EffectValue<Authorize>) => {
|
|
46
46
|
replayResult: Replay;
|
|
@@ -52,7 +52,7 @@ declare function effectReceiptWorkflowMutation<Args, Authorize, const Replay ext
|
|
|
52
52
|
type StateResult<Read> = EffectValue<Read> extends WorkflowHostState<infer Result, unknown> ? Result : never;
|
|
53
53
|
type StateFailure<Read> = EffectValue<Read> extends WorkflowHostState<unknown, infer Failure> ? Failure : never;
|
|
54
54
|
/** The host still owns native manager calls and transactional/CAS writes; each method retains only its used channels. */
|
|
55
|
-
declare function effectWorkflowStatusBindings<Authorize, Read extends Supported<WorkflowHostState>, Write, Native extends Supported<WorkflowNativeStatus>, Receipt extends Supported<WorkflowOutcome<StateResult<Read>, StateFailure<Read>> | undefined>, Cancel, Restart>(configuration: {
|
|
55
|
+
export declare function effectWorkflowStatusBindings<Authorize, Read extends Supported<WorkflowHostState>, Write, Native extends Supported<WorkflowNativeStatus>, Receipt extends Supported<WorkflowOutcome<StateResult<Read>, StateFailure<Read>> | undefined>, Cancel, Restart>(configuration: {
|
|
56
56
|
authorize: () => Authorize;
|
|
57
57
|
read: () => Read;
|
|
58
58
|
write: (expectedGeneration: number, state: WorkflowHostState<StateResult<Read>, StateFailure<Read>>) => Write;
|
|
@@ -73,5 +73,4 @@ declare function effectWorkflowStatusBindings<Authorize, Read extends Supported<
|
|
|
73
73
|
}, WorkflowBindingError | CallbackError<Authorize> | CallbackError<Read> | CallbackError<Restart> | CallbackError<Write>, CallbackRequirements<Authorize> | CallbackRequirements<Read> | CallbackRequirements<Restart> | CallbackRequirements<Write>>;
|
|
74
74
|
};
|
|
75
75
|
//#endregion
|
|
76
|
-
export { EffectReceiptProtectedWorkflowMutation, effectReceiptWorkflowMutation, effectTerminalWorkflowAttempt, effectWorkflowAttempt, effectWorkflowStatusBindings };
|
|
77
76
|
//# sourceMappingURL=workflow.d.mts.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{normalizeEffect as e}from"./normalize.mjs";import{decodeEffectContract as t}from"./schema.mjs";import{WorkflowBindingError as n,workflowCancel as r,workflowExecution as i,workflowRestart as a,workflowTransition as o}from"../contracts/workflow.mjs";import{Effect as s}from"effect";function c(t){return n=>s.gen(function*(){let r=yield*f(n),i=yield*e(()=>t.authorize(r));return yield*e(()=>t.execute(r,i))})}function l(n){return r=>s.gen(function*(){let i=yield*f(r),a=yield*e(()=>n.authorize(i)),o=yield*s.tryPromise({try:()=>n.invokeMutation(i,a),catch:e=>e}).pipe(s.map(e=>({kind:`success`,value:e})),s.catch(e=>s.succeed({kind:`rejected`,error:e})));if(o.kind===`rejected`){let r=yield*e(()=>n.terminal(o.error));if(r===void 0)return yield*s.die(o.error);let a=yield*t(n.failure,r);return yield*f({...i,args:a}),{version:1,kind:`failed`,error:a}}return yield*t(n.result,o.value),yield*f({...i,args:o.value}),{version:1,kind:`succeeded`,value:o.value}})}function u(n){return{handler:r=>s.gen(function*(){let i=yield*f(r),a=yield*e(()=>n.authorize(i)),o=n.receipt(a),s=yield*e(()=>o.prepare(n.invocation(i,a)));if(s.kind===`replay`)return yield*t(o.replayResult,s.result);let c=yield*e(()=>n.execute(i,a)),l=s.complete;return yield*e(()=>l(c)),c})}}function d(t){function n(){return e(()=>t.read()).pipe(s.map(e=>e))}function i(r,i,a){return s.gen(function*(){let s=yield*n(),c={generation:r,nativeStatus:i},l=yield*p(()=>o(s,a===void 0?c:{...c,outcome:a}));return l.kind===`applied`&&(yield*e(()=>t.write(r,l.state))),l})}return{callback(n,r,a){return e(()=>t.authorize()).pipe(s.flatMap(()=>i(n,r,a)))},reconcile(n){return s.gen(function*(){return yield*e(()=>t.authorize()),yield*i(n,yield*e(()=>t.nativeStatus()),yield*e(()=>t.receiptOutcome()))})},cancel(i){return s.gen(function*(){yield*e(()=>t.authorize());let a=yield*n(),o=yield*p(()=>r(a,i));return o.kind===`applied`&&a.status===`running`&&(yield*e(()=>t.cancelNative()),yield*e(()=>t.write(i,o.state))),o})},restart(r){return s.gen(function*(){yield*e(()=>t.authorize());let i=yield*n();if(i.generation!==r)return{kind:`ignored`,state:i};let o=yield*p(()=>a(i));return yield*e(()=>t.restartNative()),yield*e(()=>t.write(r,o)),{kind:`applied`,state:o}})}}}function f(e){return p(()=>i(e))}function p(e){return s.try({try:e,catch:e=>{if(e instanceof n)return e;throw e}})}export{u as effectReceiptWorkflowMutation,l as effectTerminalWorkflowAttempt,c as effectWorkflowAttempt,d as effectWorkflowStatusBindings};
|
|
2
2
|
//# sourceMappingURL=workflow.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow.mjs","names":[],"sources":["../../../src/modules/effect/workflow.ts"],"sourcesContent":["import { Effect } from 'effect'\nimport type { ContractInput, ContractOutput, ContractSchema } from '../contracts/contract'\nimport {\n\tWorkflowBindingError,\n\tworkflowExecution,\n\tworkflowTransition,\n\tworkflowCancel,\n\tworkflowRestart,\n\ttype WorkflowExecution,\n\ttype WorkflowOutcome,\n\ttype WorkflowHostState,\n\ttype WorkflowNativeStatus,\n} from '../contracts/workflow'\nimport type { IdempotencyInvocation } from '../contracts/idempotency'\nimport type { EffectIdempotencyPreparation } from './idempotency'\nimport type { CallbackError, CallbackRequirements, EffectValue } from './operation'\nimport { normalizeEffect } from './normalize'\nimport {\n\tdecodeEffectContract,\n\ttype ContractDecoderError,\n\ttype ContractDecoderRequirements,\n} from './schema'\n\ntype Supported<A> = A | PromiseLike<A> | Effect.Effect<A, unknown, unknown>\n/** Services exist only inside a new native invocation; ordinary throws/rejections remain defects. */\nexport function effectWorkflowAttempt<Args, Authorize, Execute>(configuration: {\n\tauthorize: (execution: WorkflowExecution<Args>) => Authorize\n\texecute: (execution: WorkflowExecution<Args>, authority: EffectValue<Authorize>) => Execute\n}) {\n\treturn (\n\t\tinput: WorkflowExecution<Args>,\n\t): Effect.Effect<\n\t\tEffectValue<Execute>,\n\t\tWorkflowBindingError | CallbackError<Authorize | Execute>,\n\t\tCallbackRequirements<Authorize | Execute>\n\t> =>\n\t\tEffect.gen(function* () {\n\t\t\tconst execution = yield* descriptor(input)\n\t\t\tconst authority = yield* normalizeEffect(() => configuration.authorize(execution))\n\t\t\treturn yield* normalizeEffect(() => configuration.execute(execution, authority))\n\t\t})\n}\n/** Native mutation promise rejects outside the child transaction before mapping declared terminal details. */\nexport function effectTerminalWorkflowAttempt<\n\tArgs,\n\tAuthorize,\n\tconst Result extends ContractSchema,\n\tconst Failure extends ContractSchema,\n\tTerminal extends Supported<ContractInput<Failure> | undefined>,\n>(\n\tconfiguration: (\n\t\t| { kind: 'mutation'; atomicJournalProof: 'host-verified' }\n\t\t| {\n\t\t\t\tkind: 'action'\n\t\t\t\tprotectedMutation: EffectReceiptProtectedWorkflowMutation<Args, unknown, unknown, unknown>\n\t\t }\n\t) & {\n\t\tauthorize: (execution: WorkflowExecution<Args>) => Authorize\n\t\tinvokeMutation: (\n\t\t\texecution: WorkflowExecution<Args>,\n\t\t\tauthority: EffectValue<Authorize>,\n\t\t) => Promise<ContractInput<Result>>\n\t\t// oxlint-disable-next-line anti-slop/no-unknown-parameters -- A rejected native mutation can throw any value; the host terminal callback classifies it before failure contract validation.\n\t\tterminal: (error: unknown) => Terminal\n\t\tresult: Result\n\t\tfailure: Failure\n\t},\n) {\n\treturn (\n\t\tinput: WorkflowExecution<Args>,\n\t): Effect.Effect<\n\t\tWorkflowOutcome<ContractInput<Result>, ContractOutput<Failure>>,\n\t\t| WorkflowBindingError\n\t\t| CallbackError<Authorize | Terminal>\n\t\t| ContractDecoderError<Result | Failure>,\n\t\tCallbackRequirements<Authorize | Terminal> | ContractDecoderRequirements<Result | Failure>\n\t> =>\n\t\tEffect.gen(function* () {\n\t\t\tconst execution = yield* descriptor(input)\n\t\t\tconst authority = yield* normalizeEffect(() => configuration.authorize(execution))\n\t\t\tconst native = yield* Effect.tryPromise({\n\t\t\t\ttry: () => configuration.invokeMutation(execution, authority),\n\t\t\t\tcatch: (error) => error,\n\t\t\t}).pipe(\n\t\t\t\tEffect.map((value) => ({ kind: 'success' as const, value })),\n\t\t\t\tEffect.catch((error) => Effect.succeed({ kind: 'rejected' as const, error })),\n\t\t\t)\n\t\t\tif (native.kind === 'rejected') {\n\t\t\t\tconst failure = yield* normalizeEffect(() => configuration.terminal(native.error))\n\t\t\t\tif (failure === undefined) return yield* Effect.die(native.error)\n\t\t\t\t// SAFETY: Terminal is constrained to this exact failure wire input or undefined.\n\t\t\t\tconst error = yield* decodeEffectContract(\n\t\t\t\t\tconfiguration.failure,\n\t\t\t\t\tfailure as ContractInput<Failure>,\n\t\t\t\t)\n\t\t\t\tyield* descriptor({ ...execution, args: error })\n\t\t\t\treturn { version: 1 as const, kind: 'failed' as const, error }\n\t\t\t}\n\t\t\tyield* decodeEffectContract(configuration.result, native.value)\n\t\t\tyield* descriptor({ ...execution, args: native.value })\n\t\t\treturn { version: 1 as const, kind: 'succeeded' as const, value: native.value }\n\t\t})\n}\ndeclare const protectedMutation: unique symbol\nexport interface EffectReceiptProtectedWorkflowMutation<Args, Result, Error, Requirements> {\n\treadonly [protectedMutation]: { args: Args; result: Result }\n\treadonly handler: (\n\t\texecution: WorkflowExecution<Args>,\n\t) => Effect.Effect<Result, Error, Requirements>\n}\ntype Completion<Prepare> =\n\tExtract<EffectValue<Prepare>, { kind: 'execute' }> extends {\n\t\tcomplete: (...arguments_: never[]) => infer Returned\n\t}\n\t\t? Returned\n\t\t: never\n/** Host runs the handler in the secured inner native mutation transaction, including receipt completion. */\nexport function effectReceiptWorkflowMutation<\n\tArgs,\n\tAuthorize,\n\tconst Replay extends ContractSchema,\n\tPrepare extends Supported<EffectIdempotencyPreparation<ContractOutput<Replay>, unknown, unknown>>,\n\tExecute extends Supported<ContractOutput<Replay>>,\n>(configuration: {\n\tauthorize: (execution: WorkflowExecution<Args>) => Authorize\n\treceipt: (authority: EffectValue<Authorize>) => {\n\t\treplayResult: Replay\n\t\tprepare: (invocation: IdempotencyInvocation) => Prepare\n\t}\n\tinvocation: (\n\t\texecution: WorkflowExecution<Args>,\n\t\tauthority: EffectValue<Authorize>,\n\t) => IdempotencyInvocation\n\texecute: (execution: WorkflowExecution<Args>, authority: EffectValue<Authorize>) => Execute\n}): EffectReceiptProtectedWorkflowMutation<\n\tArgs,\n\tContractOutput<Replay>,\n\t| WorkflowBindingError\n\t| CallbackError<Authorize | Prepare | Execute | Completion<Prepare>>\n\t| ContractDecoderError<Replay>,\n\t| CallbackRequirements<Authorize | Prepare | Execute | Completion<Prepare>>\n\t| ContractDecoderRequirements<Replay>\n> {\n\tconst handler = (input: WorkflowExecution<Args>) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst execution = yield* descriptor(input)\n\t\t\tconst authority = yield* normalizeEffect(() => configuration.authorize(execution))\n\t\t\tconst adapter = configuration.receipt(authority)\n\t\t\tconst preparation = yield* normalizeEffect(() =>\n\t\t\t\tadapter.prepare(configuration.invocation(execution, authority)),\n\t\t\t)\n\t\t\tif (preparation.kind === 'replay')\n\t\t\t\treturn yield* decodeEffectContract(adapter.replayResult, preparation.result)\n\t\t\tconst value = yield* normalizeEffect(() => configuration.execute(execution, authority))\n\t\t\t// SAFETY: the execute branch came from this exact Prepare value; recover its complete callback rather than the broad constraint.\n\t\t\tconst complete = preparation.complete as (\n\t\t\t\tresult: ContractOutput<Replay>,\n\t\t\t) => Completion<Prepare>\n\t\t\t// SAFETY: Execute's supported success is the exact final replay output contract.\n\t\t\tyield* normalizeEffect(() => complete(value as ContractOutput<Replay>))\n\t\t\t// SAFETY: Execute's supported success is the exact final replay output contract.\n\t\t\treturn value as ContractOutput<Replay>\n\t\t})\n\t// SAFETY: only private receipt evidence is asserted; handler's inferred E/R remain checked against the public return.\n\treturn { handler } as ReceiptEvidence<Args, ContractOutput<Replay>, typeof handler>\n}\ntype ReceiptEvidence<Args, Result, Handler> = {\n\thandler: Handler\n\treadonly [protectedMutation]: { args: Args; result: Result }\n}\ntype StateResult<Read> =\n\tEffectValue<Read> extends WorkflowHostState<infer Result, unknown> ? Result : never\ntype StateFailure<Read> =\n\tEffectValue<Read> extends WorkflowHostState<unknown, infer Failure> ? Failure : never\n/** The host still owns native manager calls and transactional/CAS writes; each method retains only its used channels. */\nexport function effectWorkflowStatusBindings<\n\tAuthorize,\n\tRead extends Supported<WorkflowHostState>,\n\tWrite,\n\tNative extends Supported<WorkflowNativeStatus>,\n\tReceipt extends Supported<WorkflowOutcome<StateResult<Read>, StateFailure<Read>> | undefined>,\n\tCancel,\n\tRestart,\n>(configuration: {\n\tauthorize: () => Authorize\n\tread: () => Read\n\twrite: (\n\t\texpectedGeneration: number,\n\t\tstate: WorkflowHostState<StateResult<Read>, StateFailure<Read>>,\n\t) => Write\n\tnativeStatus: () => Native\n\treceiptOutcome: () => Receipt\n\tcancelNative: () => Cancel\n\trestartNative: () => Restart\n}) {\n\ttype State = WorkflowHostState<StateResult<Read>, StateFailure<Read>>\n\tfunction read() {\n\t\t// SAFETY: Read's supported success is the host state whose outcome types are extracted above.\n\t\treturn normalizeEffect(() => configuration.read()).pipe(Effect.map((state) => state as State))\n\t}\n\tfunction apply(\n\t\texpectedGeneration: number,\n\t\tnativeStatus: WorkflowNativeStatus,\n\t\toutcome?: WorkflowOutcome<StateResult<Read>, StateFailure<Read>>,\n\t) {\n\t\treturn Effect.gen(function* () {\n\t\t\tconst current = yield* read()\n\t\t\tconst update = { generation: expectedGeneration, nativeStatus }\n\t\t\tconst transition = yield* protocol(() =>\n\t\t\t\tworkflowTransition(current, outcome === undefined ? update : { ...update, outcome }),\n\t\t\t)\n\t\t\tif (transition.kind === 'applied')\n\t\t\t\tyield* normalizeEffect(() => configuration.write(expectedGeneration, transition.state))\n\t\t\treturn transition\n\t\t})\n\t}\n\treturn {\n\t\tcallback(\n\t\t\texpectedGeneration: number,\n\t\t\tnativeStatus: WorkflowNativeStatus,\n\t\t\toutcome?: WorkflowOutcome<StateResult<Read>, StateFailure<Read>>,\n\t\t) {\n\t\t\treturn normalizeEffect(() => configuration.authorize()).pipe(\n\t\t\t\tEffect.flatMap(() => apply(expectedGeneration, nativeStatus, outcome)),\n\t\t\t)\n\t\t},\n\t\treconcile(expectedGeneration: number) {\n\t\t\treturn Effect.gen(function* () {\n\t\t\t\tyield* normalizeEffect(() => configuration.authorize())\n\t\t\t\tconst native = yield* normalizeEffect(() => configuration.nativeStatus())\n\t\t\t\tconst outcome = yield* normalizeEffect(() => configuration.receiptOutcome())\n\t\t\t\t// SAFETY: Native and Receipt are constrained to these exact host transport values.\n\t\t\t\treturn yield* apply(\n\t\t\t\t\texpectedGeneration,\n\t\t\t\t\tnative as WorkflowNativeStatus,\n\t\t\t\t\toutcome as WorkflowOutcome<StateResult<Read>, StateFailure<Read>> | undefined,\n\t\t\t\t)\n\t\t\t})\n\t\t},\n\t\tcancel(expectedGeneration: number) {\n\t\t\treturn Effect.gen(function* () {\n\t\t\t\tyield* normalizeEffect(() => configuration.authorize())\n\t\t\t\tconst current = yield* read()\n\t\t\t\tconst transition = yield* protocol(() => workflowCancel(current, expectedGeneration))\n\t\t\t\tif (transition.kind === 'applied' && current.status === 'running') {\n\t\t\t\t\tyield* normalizeEffect(() => configuration.cancelNative())\n\t\t\t\t\tyield* normalizeEffect(() => configuration.write(expectedGeneration, transition.state))\n\t\t\t\t}\n\t\t\t\treturn transition\n\t\t\t})\n\t\t},\n\t\trestart(expectedGeneration: number) {\n\t\t\treturn Effect.gen(function* () {\n\t\t\t\tyield* normalizeEffect(() => configuration.authorize())\n\t\t\t\tconst current = yield* read()\n\t\t\t\tif (current.generation !== expectedGeneration)\n\t\t\t\t\treturn { kind: 'ignored' as const, state: current }\n\t\t\t\tconst state = yield* protocol(() => workflowRestart(current))\n\t\t\t\tyield* normalizeEffect(() => configuration.restartNative())\n\t\t\t\tyield* normalizeEffect(() => configuration.write(expectedGeneration, state))\n\t\t\t\treturn { kind: 'applied' as const, state }\n\t\t\t})\n\t\t},\n\t}\n}\nfunction descriptor<Args>(\n\tvalue: WorkflowExecution<Args>,\n): Effect.Effect<WorkflowExecution<Args>, WorkflowBindingError> {\n\treturn protocol(() => workflowExecution(value))\n}\nfunction protocol<A>(evaluate: () => A): Effect.Effect<A, WorkflowBindingError> {\n\treturn Effect.try({\n\t\ttry: evaluate,\n\t\tcatch: (error) => {\n\t\t\tif (error instanceof WorkflowBindingError) return error\n\t\t\tthrow error\n\t\t},\n\t})\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"workflow.mjs","names":["effectWorkflowAttempt","Effect","execution","descriptor","input","authority","normalizeEffect","configuration","effectTerminalWorkflowAttempt","native","error","failure","decodeEffectContract","effectReceiptWorkflowMutation","adapter","preparation","value","complete","effectWorkflowStatusBindings","read","state","apply","current","update","expectedGeneration","transition","protocol","workflowTransition","outcome","nativeStatus","workflowCancel","workflowRestart","workflowExecution","evaluate","WorkflowBindingError"],"sources":["../../../src/modules/effect/workflow.ts"],"sourcesContent":["import { Effect } from 'effect'\nimport type { ContractInput, ContractOutput, ContractSchema } from '../contracts/contract'\nimport {\n\tWorkflowBindingError,\n\tworkflowExecution,\n\tworkflowTransition,\n\tworkflowCancel,\n\tworkflowRestart,\n\ttype WorkflowExecution,\n\ttype WorkflowOutcome,\n\ttype WorkflowHostState,\n\ttype WorkflowNativeStatus,\n} from '../contracts/workflow'\nimport type { IdempotencyInvocation } from '../contracts/idempotency'\nimport type { EffectIdempotencyPreparation } from './idempotency'\nimport type { CallbackError, CallbackRequirements, EffectValue } from './operation'\nimport { normalizeEffect } from './normalize'\nimport {\n\tdecodeEffectContract,\n\ttype ContractDecoderError,\n\ttype ContractDecoderRequirements,\n} from './schema'\n\ntype Supported<A> = A | PromiseLike<A> | Effect.Effect<A, unknown, unknown>\n/** Services exist only inside a new native invocation; ordinary throws/rejections remain defects. */\nexport function effectWorkflowAttempt<Args, Authorize, Execute>(configuration: {\n\tauthorize: (execution: WorkflowExecution<Args>) => Authorize\n\texecute: (execution: WorkflowExecution<Args>, authority: EffectValue<Authorize>) => Execute\n}) {\n\treturn (\n\t\tinput: WorkflowExecution<Args>,\n\t): Effect.Effect<\n\t\tEffectValue<Execute>,\n\t\tWorkflowBindingError | CallbackError<Authorize | Execute>,\n\t\tCallbackRequirements<Authorize | Execute>\n\t> =>\n\t\tEffect.gen(function* () {\n\t\t\tconst execution = yield* descriptor(input)\n\t\t\tconst authority = yield* normalizeEffect(() => configuration.authorize(execution))\n\t\t\treturn yield* normalizeEffect(() => configuration.execute(execution, authority))\n\t\t})\n}\n/** Native mutation promise rejects outside the child transaction before mapping declared terminal details. */\nexport function effectTerminalWorkflowAttempt<\n\tArgs,\n\tAuthorize,\n\tconst Result extends ContractSchema,\n\tconst Failure extends ContractSchema,\n\tTerminal extends Supported<ContractInput<Failure> | undefined>,\n>(\n\tconfiguration: (\n\t\t| { kind: 'mutation'; atomicJournalProof: 'host-verified' }\n\t\t| {\n\t\t\t\tkind: 'action'\n\t\t\t\tprotectedMutation: EffectReceiptProtectedWorkflowMutation<Args, unknown, unknown, unknown>\n\t\t }\n\t) & {\n\t\tauthorize: (execution: WorkflowExecution<Args>) => Authorize\n\t\tinvokeMutation: (\n\t\t\texecution: WorkflowExecution<Args>,\n\t\t\tauthority: EffectValue<Authorize>,\n\t\t) => Promise<ContractInput<Result>>\n\t\t// oxlint-disable-next-line anti-slop/no-unknown-parameters -- A rejected native mutation can throw any value; the host terminal callback classifies it before failure contract validation.\n\t\tterminal: (error: unknown) => Terminal\n\t\tresult: Result\n\t\tfailure: Failure\n\t},\n) {\n\treturn (\n\t\tinput: WorkflowExecution<Args>,\n\t): Effect.Effect<\n\t\tWorkflowOutcome<ContractInput<Result>, ContractOutput<Failure>>,\n\t\t| WorkflowBindingError\n\t\t| CallbackError<Authorize | Terminal>\n\t\t| ContractDecoderError<Result | Failure>,\n\t\tCallbackRequirements<Authorize | Terminal> | ContractDecoderRequirements<Result | Failure>\n\t> =>\n\t\tEffect.gen(function* () {\n\t\t\tconst execution = yield* descriptor(input)\n\t\t\tconst authority = yield* normalizeEffect(() => configuration.authorize(execution))\n\t\t\tconst native = yield* Effect.tryPromise({\n\t\t\t\ttry: () => configuration.invokeMutation(execution, authority),\n\t\t\t\tcatch: (error) => error,\n\t\t\t}).pipe(\n\t\t\t\tEffect.map((value) => ({ kind: 'success' as const, value })),\n\t\t\t\tEffect.catch((error) => Effect.succeed({ kind: 'rejected' as const, error })),\n\t\t\t)\n\t\t\tif (native.kind === 'rejected') {\n\t\t\t\tconst failure = yield* normalizeEffect(() => configuration.terminal(native.error))\n\t\t\t\tif (failure === undefined) return yield* Effect.die(native.error)\n\t\t\t\t// SAFETY: Terminal is constrained to this exact failure wire input or undefined.\n\t\t\t\tconst error = yield* decodeEffectContract(\n\t\t\t\t\tconfiguration.failure,\n\t\t\t\t\tfailure as ContractInput<Failure>,\n\t\t\t\t)\n\t\t\t\tyield* descriptor({ ...execution, args: error })\n\t\t\t\treturn { version: 1 as const, kind: 'failed' as const, error }\n\t\t\t}\n\t\t\tyield* decodeEffectContract(configuration.result, native.value)\n\t\t\tyield* descriptor({ ...execution, args: native.value })\n\t\t\treturn { version: 1 as const, kind: 'succeeded' as const, value: native.value }\n\t\t})\n}\ndeclare const protectedMutation: unique symbol\nexport interface EffectReceiptProtectedWorkflowMutation<Args, Result, Error, Requirements> {\n\treadonly [protectedMutation]: { args: Args; result: Result }\n\treadonly handler: (\n\t\texecution: WorkflowExecution<Args>,\n\t) => Effect.Effect<Result, Error, Requirements>\n}\ntype Completion<Prepare> =\n\tExtract<EffectValue<Prepare>, { kind: 'execute' }> extends {\n\t\tcomplete: (...arguments_: never[]) => infer Returned\n\t}\n\t\t? Returned\n\t\t: never\n/** Host runs the handler in the secured inner native mutation transaction, including receipt completion. */\nexport function effectReceiptWorkflowMutation<\n\tArgs,\n\tAuthorize,\n\tconst Replay extends ContractSchema,\n\tPrepare extends Supported<EffectIdempotencyPreparation<ContractOutput<Replay>, unknown, unknown>>,\n\tExecute extends Supported<ContractOutput<Replay>>,\n>(configuration: {\n\tauthorize: (execution: WorkflowExecution<Args>) => Authorize\n\treceipt: (authority: EffectValue<Authorize>) => {\n\t\treplayResult: Replay\n\t\tprepare: (invocation: IdempotencyInvocation) => Prepare\n\t}\n\tinvocation: (\n\t\texecution: WorkflowExecution<Args>,\n\t\tauthority: EffectValue<Authorize>,\n\t) => IdempotencyInvocation\n\texecute: (execution: WorkflowExecution<Args>, authority: EffectValue<Authorize>) => Execute\n}): EffectReceiptProtectedWorkflowMutation<\n\tArgs,\n\tContractOutput<Replay>,\n\t| WorkflowBindingError\n\t| CallbackError<Authorize | Prepare | Execute | Completion<Prepare>>\n\t| ContractDecoderError<Replay>,\n\t| CallbackRequirements<Authorize | Prepare | Execute | Completion<Prepare>>\n\t| ContractDecoderRequirements<Replay>\n> {\n\tconst handler = (input: WorkflowExecution<Args>) =>\n\t\tEffect.gen(function* () {\n\t\t\tconst execution = yield* descriptor(input)\n\t\t\tconst authority = yield* normalizeEffect(() => configuration.authorize(execution))\n\t\t\tconst adapter = configuration.receipt(authority)\n\t\t\tconst preparation = yield* normalizeEffect(() =>\n\t\t\t\tadapter.prepare(configuration.invocation(execution, authority)),\n\t\t\t)\n\t\t\tif (preparation.kind === 'replay')\n\t\t\t\treturn yield* decodeEffectContract(adapter.replayResult, preparation.result)\n\t\t\tconst value = yield* normalizeEffect(() => configuration.execute(execution, authority))\n\t\t\t// SAFETY: the execute branch came from this exact Prepare value; recover its complete callback rather than the broad constraint.\n\t\t\tconst complete = preparation.complete as (\n\t\t\t\tresult: ContractOutput<Replay>,\n\t\t\t) => Completion<Prepare>\n\t\t\t// SAFETY: Execute's supported success is the exact final replay output contract.\n\t\t\tyield* normalizeEffect(() => complete(value as ContractOutput<Replay>))\n\t\t\t// SAFETY: Execute's supported success is the exact final replay output contract.\n\t\t\treturn value as ContractOutput<Replay>\n\t\t})\n\t// SAFETY: only private receipt evidence is asserted; handler's inferred E/R remain checked against the public return.\n\treturn { handler } as ReceiptEvidence<Args, ContractOutput<Replay>, typeof handler>\n}\ntype ReceiptEvidence<Args, Result, Handler> = {\n\thandler: Handler\n\treadonly [protectedMutation]: { args: Args; result: Result }\n}\ntype StateResult<Read> =\n\tEffectValue<Read> extends WorkflowHostState<infer Result, unknown> ? Result : never\ntype StateFailure<Read> =\n\tEffectValue<Read> extends WorkflowHostState<unknown, infer Failure> ? Failure : never\n/** The host still owns native manager calls and transactional/CAS writes; each method retains only its used channels. */\nexport function effectWorkflowStatusBindings<\n\tAuthorize,\n\tRead extends Supported<WorkflowHostState>,\n\tWrite,\n\tNative extends Supported<WorkflowNativeStatus>,\n\tReceipt extends Supported<WorkflowOutcome<StateResult<Read>, StateFailure<Read>> | undefined>,\n\tCancel,\n\tRestart,\n>(configuration: {\n\tauthorize: () => Authorize\n\tread: () => Read\n\twrite: (\n\t\texpectedGeneration: number,\n\t\tstate: WorkflowHostState<StateResult<Read>, StateFailure<Read>>,\n\t) => Write\n\tnativeStatus: () => Native\n\treceiptOutcome: () => Receipt\n\tcancelNative: () => Cancel\n\trestartNative: () => Restart\n}) {\n\ttype State = WorkflowHostState<StateResult<Read>, StateFailure<Read>>\n\tfunction read() {\n\t\t// SAFETY: Read's supported success is the host state whose outcome types are extracted above.\n\t\treturn normalizeEffect(() => configuration.read()).pipe(Effect.map((state) => state as State))\n\t}\n\tfunction apply(\n\t\texpectedGeneration: number,\n\t\tnativeStatus: WorkflowNativeStatus,\n\t\toutcome?: WorkflowOutcome<StateResult<Read>, StateFailure<Read>>,\n\t) {\n\t\treturn Effect.gen(function* () {\n\t\t\tconst current = yield* read()\n\t\t\tconst update = { generation: expectedGeneration, nativeStatus }\n\t\t\tconst transition = yield* protocol(() =>\n\t\t\t\tworkflowTransition(current, outcome === undefined ? update : { ...update, outcome }),\n\t\t\t)\n\t\t\tif (transition.kind === 'applied')\n\t\t\t\tyield* normalizeEffect(() => configuration.write(expectedGeneration, transition.state))\n\t\t\treturn transition\n\t\t})\n\t}\n\treturn {\n\t\tcallback(\n\t\t\texpectedGeneration: number,\n\t\t\tnativeStatus: WorkflowNativeStatus,\n\t\t\toutcome?: WorkflowOutcome<StateResult<Read>, StateFailure<Read>>,\n\t\t) {\n\t\t\treturn normalizeEffect(() => configuration.authorize()).pipe(\n\t\t\t\tEffect.flatMap(() => apply(expectedGeneration, nativeStatus, outcome)),\n\t\t\t)\n\t\t},\n\t\treconcile(expectedGeneration: number) {\n\t\t\treturn Effect.gen(function* () {\n\t\t\t\tyield* normalizeEffect(() => configuration.authorize())\n\t\t\t\tconst native = yield* normalizeEffect(() => configuration.nativeStatus())\n\t\t\t\tconst outcome = yield* normalizeEffect(() => configuration.receiptOutcome())\n\t\t\t\t// SAFETY: Native and Receipt are constrained to these exact host transport values.\n\t\t\t\treturn yield* apply(\n\t\t\t\t\texpectedGeneration,\n\t\t\t\t\tnative as WorkflowNativeStatus,\n\t\t\t\t\toutcome as WorkflowOutcome<StateResult<Read>, StateFailure<Read>> | undefined,\n\t\t\t\t)\n\t\t\t})\n\t\t},\n\t\tcancel(expectedGeneration: number) {\n\t\t\treturn Effect.gen(function* () {\n\t\t\t\tyield* normalizeEffect(() => configuration.authorize())\n\t\t\t\tconst current = yield* read()\n\t\t\t\tconst transition = yield* protocol(() => workflowCancel(current, expectedGeneration))\n\t\t\t\tif (transition.kind === 'applied' && current.status === 'running') {\n\t\t\t\t\tyield* normalizeEffect(() => configuration.cancelNative())\n\t\t\t\t\tyield* normalizeEffect(() => configuration.write(expectedGeneration, transition.state))\n\t\t\t\t}\n\t\t\t\treturn transition\n\t\t\t})\n\t\t},\n\t\trestart(expectedGeneration: number) {\n\t\t\treturn Effect.gen(function* () {\n\t\t\t\tyield* normalizeEffect(() => configuration.authorize())\n\t\t\t\tconst current = yield* read()\n\t\t\t\tif (current.generation !== expectedGeneration)\n\t\t\t\t\treturn { kind: 'ignored' as const, state: current }\n\t\t\t\tconst state = yield* protocol(() => workflowRestart(current))\n\t\t\t\tyield* normalizeEffect(() => configuration.restartNative())\n\t\t\t\tyield* normalizeEffect(() => configuration.write(expectedGeneration, state))\n\t\t\t\treturn { kind: 'applied' as const, state }\n\t\t\t})\n\t\t},\n\t}\n}\nfunction descriptor<Args>(\n\tvalue: WorkflowExecution<Args>,\n): Effect.Effect<WorkflowExecution<Args>, WorkflowBindingError> {\n\treturn protocol(() => workflowExecution(value))\n}\nfunction protocol<A>(evaluate: () => A): Effect.Effect<A, WorkflowBindingError> {\n\treturn Effect.try({\n\t\ttry: evaluate,\n\t\tcatch: (error) => {\n\t\t\tif (error instanceof WorkflowBindingError) return error\n\t\t\tthrow error\n\t\t},\n\t})\n}\n"],"mappings":"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"}
|
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
import { ResolverFactory } from "oxc-resolver";
|
|
2
2
|
//#region src/oxlint/architecture.d.ts
|
|
3
|
-
interface ArchitectureOptions {
|
|
3
|
+
export interface ArchitectureOptions {
|
|
4
4
|
cwd?: string;
|
|
5
5
|
convexDir?: string;
|
|
6
6
|
}
|
|
7
|
-
interface ArchitectureDiagnostic {
|
|
7
|
+
export interface ArchitectureDiagnostic {
|
|
8
8
|
code: 'missing-root' | 'root-directory' | 'tests' | 'test-location' | 'parse' | 'cycle' | 'symlink' | 'domain-entry' | 'shared-owner';
|
|
9
9
|
file: string;
|
|
10
10
|
message: string;
|
|
11
11
|
}
|
|
12
12
|
/** Full-project checks, independent of the consumer's test runner. No persistent cache. */
|
|
13
|
-
declare function inspectArchitecture(options?: ArchitectureOptions): ArchitectureDiagnostic[];
|
|
14
|
-
declare function createResolver(): ResolverFactory;
|
|
15
|
-
declare function resolveImport(resolver: ResolverFactory, filename: string, source: string): string | null;
|
|
13
|
+
export declare function inspectArchitecture(options?: ArchitectureOptions): ArchitectureDiagnostic[];
|
|
14
|
+
export declare function createResolver(): ResolverFactory;
|
|
15
|
+
export declare function resolveImport(resolver: ResolverFactory, filename: string, source: string): string | null;
|
|
16
16
|
/** The lint rule runs the project scan on one deterministic source file. */
|
|
17
|
-
declare function architectureAnchor(root: string): string | null;
|
|
17
|
+
export declare function architectureAnchor(root: string): string | null;
|
|
18
18
|
//#endregion
|
|
19
|
-
export { ArchitectureDiagnostic, ArchitectureOptions, architectureAnchor, createResolver, inspectArchitecture, resolveImport };
|
|
20
19
|
//# sourceMappingURL=architecture.d.mts.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{dirname as e,relative as t,resolve as n,sep as r}from"node:path";import{existsSync as i,readFileSync as a,readdirSync as o,realpathSync as s}from"node:fs";import{Visitor as c,parseSync as l}from"oxc-parser";import{ResolverFactory as u}from"oxc-resolver";function d(o={}){let c=n(o.cwd??process.cwd(),o.convexDir??`convex`),u=i(c)?s(c):c,d=[];if(!i(u))return[{code:`missing-root`,file:`.`,message:`Convex directory does not exist: ${u}`}];let m=h(u,d),y
|
|
1
|
+
import{dirname as e,relative as t,resolve as n,sep as r}from"node:path";import{existsSync as i,readFileSync as a,readdirSync as o,realpathSync as s}from"node:fs";import{Visitor as c,parseSync as l}from"oxc-parser";import{ResolverFactory as u}from"oxc-resolver";function d(o={}){let c=n(o.cwd??process.cwd(),o.convexDir??`convex`),u=i(c)?s(c):c,d=[];if(!i(u))return[{code:`missing-root`,file:`.`,message:`Convex directory does not exist: ${u}`}];let m=h(u,d),y=/* @__PURE__ */ new Set,w=/* @__PURE__ */ new Set,T=/* @__PURE__ */ new Map,E=/* @__PURE__ */ new Map,D=f();for(let i of m){let o=n(u,i),s=l(o,a(o,`utf8`));if(s.errors.length){d.push({code:`parse`,file:i,message:`Cannot validate ${i}: ${s.errors[0].message}`});continue}if(g(i)){i.includes(`__tests__/`)?e(i).endsWith(`__tests__`)&&v(s.program)&&w.add(e(e(i))):d.push({code:`test-location`,file:i,message:`Place tests in a sibling __tests__/ directory.`});continue}if(i.split(`/`).includes(`__tests__`))continue;/^domain\/[^/]+$/.test(i)&&i!==`domain/table.ts`&&d.push({code:`domain-entry`,file:i,message:`Domain source belongs in domain/<module>/ or domain/shared/. Only domain/table.ts assembles module tables.`}),_(s.program)&&i!==`domain/table.ts`&&y.add(e(i));let c=x(i)??``,f=/* @__PURE__ */ new Set;E.set(i,f);for(let e of b(s.program)){let n=p(D,o,e);if(!n)continue;let i=t(u,n).split(r).join(`/`);f.add(i);let a=x(i);if(c&&a&&c!==a){let e=T.get(c)??/* @__PURE__ */ new Set;T.set(c,e),e.add(a)}}}for(let e of y)w.has(e)||d.push({code:`tests`,file:e,message:`${e}/__tests__/ must contain a .test or .spec file with a nonempty, non-skipped test. Parent or child suites do not count.`});d.push(...C(E));for(let e of S(T))d.push({code:`cycle`,file:e[0],message:`Module dependency cycle: ${e.join(` → `)}.`});return d.sort((e,t)=>e.file.localeCompare(t.file)||e.code.localeCompare(t.code))}function f(){return new u({tsconfig:`auto`,extensions:[`.ts`,`.tsx`,`.mts`,`.cts`,`.js`,`.jsx`,`.mjs`,`.cjs`,`.json`],extensionAlias:{".js":[`.ts`,`.tsx`,`.js`],".mjs":[`.mts`,`.mjs`],".cjs":[`.cts`,`.cjs`]},conditionNames:[`types`,`import`,`node`,`default`],symlinks:!0})}function p(t,r,i){return t.resolveFileSync(r,i).path||(i.startsWith(`.`)?n(e(r),i):null)}function m(e){if(!i(e))return null;if(i(n(e,`convex.config.ts`)))return s(n(e,`convex.config.ts`));e=s(e);for(let t of h(e,[]))if(!t.includes(`__tests__/`)&&!g(t))return n(e,t);return null}function*h(e,i){let a=/* @__PURE__ */ new Set([`_generated`,`__tests__`,`api`,`domain`,`application`,`migrations`,`components`]);function*s(c){for(let l of o(c,{withFileTypes:!0}).sort((e,t)=>e.name.localeCompare(t.name))){let o=n(c,l.name),u=t(e,o).split(r).join(`/`);if(l.isSymbolicLink()){i.push({code:`symlink`,file:u,message:`Keep application source inside its owning directory; symlinked files and folders are not allowed.`});continue}l.isDirectory()?(c===e&&!a.has(l.name)&&i.push({code:`root-directory`,file:u,message:`Root folder ${l.name}/ is not allowed. Use api/, domain/, application/, migrations/, components/, __tests__/, or _generated/.`}),l.name!==`_generated`&&l.name!==`node_modules`&&!l.name.startsWith(`.`)&&(yield*s(o))):/\.[cm]?[jt]sx?$/.test(l.name)&&!/\.d\.[cm]?ts$/.test(l.name)&&(yield u)}}yield*s(e)}function g(e){return/\.(?:test|spec)\.[cm]?[jt]sx?$/.test(e)}function _(e){return e.body.some(e=>{let t=e.type===`ExportNamedDeclaration`?e.declaration:e;return t&&`declare`in t&&t.declare||e.type===`ImportDeclaration`||e.type===`EmptyStatement`?!1:e.type===`ExportNamedDeclaration`?e.exportKind===`type`||!e.declaration?!1:![`TSInterfaceDeclaration`,`TSTypeAliasDeclaration`,`TSDeclareFunction`].includes(e.declaration.type):![`TSInterfaceDeclaration`,`TSTypeAliasDeclaration`,`TSDeclareFunction`,`ExportAllDeclaration`].includes(e.type)})}function v(e){let t=/* @__PURE__ */ new Map([[`test`,`test`],[`it`,`it`],[`describe`,`describe`],[`suite`,`suite`]]);for(let n of e.body){let e=n.type===`ExportNamedDeclaration`?n.declaration:n;if(e?.type===`FunctionDeclaration`&&e.id&&t.delete(e.id.name),e?.type===`VariableDeclaration`)for(let n of e.declarations)n.id.type===`Identifier`&&t.delete(n.id.name);if(n.type===`ImportDeclaration`)for(let e of n.specifiers)t.delete(e.local.name),[`vitest`,`vite-plus/test`,`bun:test`,`node:test`,`@jest/globals`].includes(n.source.value)&&(e.type===`ImportNamespaceSpecifier`?t.set(e.local.name,`*`):e.type===`ImportDefaultSpecifier`?t.set(e.local.name,`test`):e.imported.type===`Identifier`&&t.set(e.local.name,e.imported.name))}let n=[];new c({CallExpression(e){n.push(e)}}).visit(e);let r=n.filter(e=>{let n=y(e.callee,t);return[`test`,`it`,`describe`,`suite`].includes(n[0])&&(n.some(e=>[`skip`,`todo`,`skipIf`,`runIf`].includes(e))||e.arguments.some(e=>e.type===`ObjectExpression`&&e.properties.some(e=>e.type===`Property`&&[`skip`,`todo`].includes(e.key.type===`Identifier`?e.key.name:e.key.type===`Literal`?String(e.key.value):``)&&(e.value.type!==`Literal`||e.value.value!==!1))))});return n.some(e=>{let n=y(e.callee,t);return![`test`,`it`].includes(n[0])||r.some(t=>e.start>=t.start&&e.end<=t.end)?!1:e.arguments.some(e=>(e.type===`ArrowFunctionExpression`||e.type===`FunctionExpression`)&&e.body&&(e.body.type!==`BlockStatement`||e.body.body.some(e=>e.type!==`EmptyStatement`)))})}function y(e,t){if(e.type===`Identifier`){let n=t.get(e.name);return n?[n]:[]}if(e.type===`CallExpression`)return y(e.callee,t);if(e.type===`MemberExpression`){let n=y(e.object,t),r=!e.computed&&e.property.type===`Identifier`?e.property.name:e.property.type===`Literal`?String(e.property.value):``;return!n.length||!r?[]:n[0]===`*`?[r]:[...n,r]}return[]}function b(e){let t=[];return new c({ImportDeclaration(e){e.importKind!==`type`&&(e.specifiers.length===0||e.specifiers.some(e=>e.type!==`ImportSpecifier`||e.importKind!==`type`))&&t.push(e.source.value)},ExportNamedDeclaration(e){e.source&&e.exportKind!==`type`&&e.specifiers.some(e=>e.exportKind!==`type`)&&t.push(e.source.value)},ExportAllDeclaration(e){e.exportKind!==`type`&&t.push(e.source.value)},ImportExpression(e){e.source.type===`Literal`&&String(e.source.value)===e.source.value&&t.push(String(e.source.value))}}).visit(e),t}function x(e){let t=e.split(`/`);return t[0]===`domain`&&t.length>=3&&t[1]!==`__tests__`?`domain/${t[1]}`:null}function S(e){let t=/* @__PURE__ */ new Set,n=[],r=[];function i(a){let o=n.indexOf(a);if(o>=0){r.push([...n.slice(o),a]);return}if(!t.has(a)){n.push(a);for(let t of e.get(a)??[])i(t);n.pop(),t.add(a)}}for(let t of e.keys())i(t);return r}function C(e){let t=/* @__PURE__ */ new Map;for(let[n,r]of e){let i=x(n)??``;if(!i||i===`domain/shared`)continue;let a=/* @__PURE__ */ new Set;function o(n){if(!n.startsWith(`domain/shared/`)||a.has(n))return;a.add(n);let r=t.get(n)??/* @__PURE__ */ new Set;r.add(i),t.set(n,r);for(let t of e.get(n)??[])o(t)}for(let e of r)o(e)}let n=[];for(let[e,r]of t)r.size===1&&n.push({code:`shared-owner`,file:e,message:`This shared implementation is used only by ${[...r][0]}. Move it into that module until another module needs it.`});return n}export{m as architectureAnchor,f as createResolver,d as inspectArchitecture,p as resolveImport};
|
|
2
2
|
//# sourceMappingURL=architecture.mjs.map
|