@ontemper/sdk 0.1.0-rc.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/README.md +92 -22
  2. package/dist/AxiosError.d.ts +46 -0
  3. package/dist/AxiosError.d.ts.map +1 -0
  4. package/dist/AxiosError.js +118 -0
  5. package/dist/AxiosError.js.map +1 -0
  6. package/dist/Contract/Invocation.d.ts +21 -0
  7. package/dist/Contract/Invocation.d.ts.map +1 -0
  8. package/dist/Contract/Invocation.js +2 -0
  9. package/dist/Contract/Invocation.js.map +1 -0
  10. package/dist/Contract/Manifest.d.ts +125 -0
  11. package/dist/Contract/Manifest.d.ts.map +1 -0
  12. package/dist/Contract/Manifest.js +59 -0
  13. package/dist/Contract/Manifest.js.map +1 -0
  14. package/dist/Contract/RuntimeApi.d.ts +143 -0
  15. package/dist/Contract/RuntimeApi.d.ts.map +1 -0
  16. package/dist/Contract/RuntimeApi.js +148 -0
  17. package/dist/Contract/RuntimeApi.js.map +1 -0
  18. package/dist/Contract/index.d.ts +4 -0
  19. package/dist/Contract/index.d.ts.map +1 -0
  20. package/dist/Contract/index.js +3 -0
  21. package/dist/Contract/index.js.map +1 -0
  22. package/dist/Correlation.d.ts +33 -0
  23. package/dist/Correlation.d.ts.map +1 -0
  24. package/dist/Correlation.js +57 -0
  25. package/dist/Correlation.js.map +1 -0
  26. package/dist/HttpApiResource.d.ts +32 -0
  27. package/dist/HttpApiResource.d.ts.map +1 -0
  28. package/dist/HttpApiResource.js +35 -0
  29. package/dist/HttpApiResource.js.map +1 -0
  30. package/dist/HttpClient.d.ts +10 -0
  31. package/dist/HttpClient.d.ts.map +1 -0
  32. package/dist/HttpClient.js +167 -0
  33. package/dist/HttpClient.js.map +1 -0
  34. package/dist/HttpPayload.d.ts +9 -0
  35. package/dist/HttpPayload.d.ts.map +1 -0
  36. package/dist/HttpPayload.js +32 -0
  37. package/dist/HttpPayload.js.map +1 -0
  38. package/dist/Invocation.d.ts +1 -20
  39. package/dist/Invocation.d.ts.map +1 -1
  40. package/dist/Invocation.js.map +1 -1
  41. package/dist/LogContext.d.ts +59 -0
  42. package/dist/LogContext.d.ts.map +1 -0
  43. package/dist/LogContext.js +47 -0
  44. package/dist/LogContext.js.map +1 -0
  45. package/dist/Logger.d.ts +3 -3
  46. package/dist/Logger.d.ts.map +1 -1
  47. package/dist/Logger.js +305 -37
  48. package/dist/Logger.js.map +1 -1
  49. package/dist/Manifest.d.ts +4 -16
  50. package/dist/Manifest.d.ts.map +1 -1
  51. package/dist/Manifest.js +65 -4
  52. package/dist/Manifest.js.map +1 -1
  53. package/dist/Middleware.d.ts +5 -2
  54. package/dist/Middleware.d.ts.map +1 -1
  55. package/dist/Middleware.js +278 -27
  56. package/dist/Middleware.js.map +1 -1
  57. package/dist/Redaction.d.ts +27 -0
  58. package/dist/Redaction.d.ts.map +1 -0
  59. package/dist/Redaction.js +149 -0
  60. package/dist/Redaction.js.map +1 -0
  61. package/dist/Resource.d.ts +66 -0
  62. package/dist/Resource.d.ts.map +1 -0
  63. package/dist/Resource.js +57 -0
  64. package/dist/Resource.js.map +1 -0
  65. package/dist/ResourcesErrors.d.ts +36 -0
  66. package/dist/ResourcesErrors.d.ts.map +1 -0
  67. package/dist/ResourcesErrors.js +27 -0
  68. package/dist/ResourcesErrors.js.map +1 -0
  69. package/dist/ResourcesToken.d.ts +10 -0
  70. package/dist/ResourcesToken.d.ts.map +1 -0
  71. package/dist/ResourcesToken.js +63 -0
  72. package/dist/ResourcesToken.js.map +1 -0
  73. package/dist/RuntimeResources.d.ts +26 -0
  74. package/dist/RuntimeResources.d.ts.map +1 -0
  75. package/dist/RuntimeResources.js +115 -0
  76. package/dist/RuntimeResources.js.map +1 -0
  77. package/dist/Trigger.d.ts +1 -26
  78. package/dist/Trigger.d.ts.map +1 -1
  79. package/dist/Trigger.js +1 -24
  80. package/dist/Trigger.js.map +1 -1
  81. package/dist/Workflow.d.ts +26 -9
  82. package/dist/Workflow.d.ts.map +1 -1
  83. package/dist/Workflow.js +48 -12
  84. package/dist/Workflow.js.map +1 -1
  85. package/dist/cli.d.ts.map +1 -1
  86. package/dist/cli.js +193 -41
  87. package/dist/cli.js.map +1 -1
  88. package/dist/index.d.ts +15 -4
  89. package/dist/index.d.ts.map +1 -1
  90. package/dist/index.js +12 -2
  91. package/dist/index.js.map +1 -1
  92. package/dist/testing.d.ts +34 -2
  93. package/dist/testing.d.ts.map +1 -1
  94. package/dist/testing.js +35 -0
  95. package/dist/testing.js.map +1 -1
  96. package/package.json +6 -2
@@ -0,0 +1,57 @@
1
+ import { Context, Effect, Effectable, Layer, Schema } from 'effect';
2
+ import { HttpApiMiddleware } from 'effect/unstable/httpapi';
3
+ import { JsonSchemaObject } from './Contract/Manifest.js';
4
+ import { InvalidResourceError } from './ResourcesErrors.js';
5
+ import { RuntimeResources } from './RuntimeResources.js';
6
+ // Keyed by the class `declare` builds; an author's `class X extends Resource<X>()(…)` inherits from it.
7
+ const runtimes = new WeakMap();
8
+ /** The declaration an endpoint middleware carries, if it is one. */
9
+ export const declarationOf = (middleware) => runtimes.get(middleware) ?? runtimes.get(Object.getPrototypeOf(middleware));
10
+ /** The encoded form's JSON Schema: what deploy validates the bound value against. */
11
+ const jsonSchemaOf = (schema) => {
12
+ const document = Schema.toJsonSchemaDocument(schema);
13
+ const json = Object.keys(document.definitions).length === 0
14
+ ? document.schema
15
+ : { ...document.schema, $defs: document.definitions };
16
+ return Schema.decodeUnknownSync(JsonSchemaObject)(json);
17
+ };
18
+ const decodeAs = (key, schema) => (value) => Schema.decodeUnknownEffect(schema)(value).pipe(Effect.mapError((error) => new InvalidResourceError({
19
+ target: `key ${key}`,
20
+ message: `Resource ${key} does not match the expected schema: ${error.message}`,
21
+ })));
22
+ const declare = (kind, name, manifest, read) => {
23
+ const id = `@temper/workflow/Declaration/${kind}/${name}`;
24
+ const middleware = HttpApiMiddleware.Service()(id);
25
+ // The middleware reads the value into this key on first use; yielding the declaration yields that read.
26
+ const value = Context.Service(`${id}/value`);
27
+ Object.assign(middleware, Effectable.Prototype({ label: 'Declaration', evaluate: () => Effect.flatten(value) }));
28
+ runtimes.set(middleware, { manifest, read, value });
29
+ const declared = middleware;
30
+ // SAFETY: yielding the class now evaluates to the declared value, which is the `A` this type names.
31
+ return declared;
32
+ };
33
+ /**
34
+ * A resource read by key. Declare secret fields `Redacted` (see `HttpApiResource`); name `type` to have
35
+ * deploy check the bound record's resource type too. A read the platform cannot answer is a defect.
36
+ */
37
+ export const Resource = () => (key, options) => declare('resource', key, options.type === undefined
38
+ ? { kind: 'resource', key, schema: jsonSchemaOf(options.schema) }
39
+ : { kind: 'resource', key, type: options.type, schema: jsonSchemaOf(options.schema) }, (resources) => resources.resolve(key).pipe(Effect.flatMap(decodeAs(key, options.schema)), Effect.orDie));
40
+ /** A Variable read by key; it arrives `Redacted` because the platform decides what is secret. */
41
+ export const Variable = () => (key) => declare('variable', key, { kind: 'variable', key }, (resources) => Effect.orDie(resources.variable(key)));
42
+ /**
43
+ * A resource type whose record the handler selects at run time, for example the tenant a request
44
+ * names. Deploy checks that the type exists; `select` finds the record and decodes it with `schema`.
45
+ */
46
+ export const ResourceType = () => (type, options) => declare('resourceType', type, { kind: 'resourceType', type, schema: jsonSchemaOf(options.schema) }, (resources) => Effect.succeed({
47
+ select: (match) => Effect.gen(function* () {
48
+ const key = yield* resources.select({ resourceTypeKey: type, match });
49
+ const value = yield* resources.resolve(key).pipe(Effect.flatMap(decodeAs(key, options.schema)));
50
+ return { key, value };
51
+ }),
52
+ }));
53
+ /** The middleware one declaration needs: its value, read through `RuntimeResources` on first use in a request. */
54
+ export const declarationLayer = (middleware, runtime) => Layer.effect(
55
+ // The key's declared service is the handler's value; its context slot holds this middleware function.
56
+ middleware, Effect.map(RuntimeResources, (resources) => (httpEffect) => Effect.flatMap(Effect.cached(runtime.read(resources)), (read) => Effect.provideService(httpEffect, runtime.value, read))));
57
+ //# sourceMappingURL=Resource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Resource.js","sourceRoot":"","sources":["../src/Resource.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import { Schema } from 'effect';
2
+ declare const ResourceNotFoundError_base: Schema.Class<ResourceNotFoundError, Schema.TaggedStruct<"ResourceNotFoundError", {
3
+ readonly target: Schema.String;
4
+ readonly message: Schema.String;
5
+ }>, import("effect/Cause").YieldableError>;
6
+ /** Nothing answers to the key or selector. For a selector this is the caller's answer (an unknown tenant), not a fault. */
7
+ export declare class ResourceNotFoundError extends ResourceNotFoundError_base {
8
+ }
9
+ declare const ResourceNotSelectableError_base: Schema.Class<ResourceNotSelectableError, Schema.TaggedStruct<"ResourceNotSelectableError", {
10
+ readonly target: Schema.String;
11
+ readonly message: Schema.String;
12
+ }>, import("effect/Cause").YieldableError>;
13
+ /** The selector was refused: its field is not the type's `x-selectable` one, or the match is empty or names several fields. */
14
+ export declare class ResourceNotSelectableError extends ResourceNotSelectableError_base {
15
+ }
16
+ declare const InvalidResourceError_base: Schema.Class<InvalidResourceError, Schema.TaggedStruct<"InvalidResourceError", {
17
+ readonly target: Schema.String;
18
+ readonly message: Schema.String;
19
+ }>, import("effect/Cause").YieldableError>;
20
+ /** The record exists but cannot serve this read: a reference cycle, several records matching one selector, or a value the caller's schema rejects. */
21
+ export declare class InvalidResourceError extends InvalidResourceError_base {
22
+ }
23
+ declare const ResourcesUnauthorizedError_base: Schema.Class<ResourcesUnauthorizedError, Schema.TaggedStruct<"ResourcesUnauthorizedError", {
24
+ readonly message: Schema.String;
25
+ }>, import("effect/Cause").YieldableError>;
26
+ /** The runtime identity is missing or refused: no API URL or runtime token, a provider that never published a fresh token, or a 401/403. */
27
+ export declare class ResourcesUnauthorizedError extends ResourcesUnauthorizedError_base {
28
+ }
29
+ declare const ResourcesUnavailableError_base: Schema.Class<ResourcesUnavailableError, Schema.TaggedStruct<"ResourcesUnavailableError", {
30
+ readonly message: Schema.String;
31
+ }>, import("effect/Cause").YieldableError>;
32
+ /** The runtime API gave no usable answer: a transport failure, a timeout, a 5xx, or a body the SDK cannot read. */
33
+ export declare class ResourcesUnavailableError extends ResourcesUnavailableError_base {
34
+ }
35
+ export {};
36
+ //# sourceMappingURL=ResourcesErrors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ResourcesErrors.d.ts","sourceRoot":"","sources":["../src/ResourcesErrors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;;;;;AAIhC,2HAA2H;AAC3H,qBAAa,qBAAsB,SAAQ,0BAGzC;CAAG;;;;;AAEL,+HAA+H;AAC/H,qBAAa,0BAA2B,SAAQ,+BAM/C;CAAG;;;;;AAEJ,sJAAsJ;AACtJ,qBAAa,oBAAqB,SAAQ,yBAGxC;CAAG;;;;AAEL,4IAA4I;AAC5I,qBAAa,0BAA2B,SAAQ,+BAG/C;CAAG;;;;AAEJ,mHAAmH;AACnH,qBAAa,yBAA0B,SAAQ,8BAG9C;CAAG"}
@@ -0,0 +1,27 @@
1
+ import { Schema } from 'effect';
2
+ // `target` names what was asked for — `key <key>` or `<type> matching <field>` — never a presented match value.
3
+ /** Nothing answers to the key or selector. For a selector this is the caller's answer (an unknown tenant), not a fault. */
4
+ export class ResourceNotFoundError extends Schema.TaggedError()('ResourceNotFoundError', {
5
+ target: Schema.String,
6
+ message: Schema.String,
7
+ }) {
8
+ }
9
+ /** The selector was refused: its field is not the type's `x-selectable` one, or the match is empty or names several fields. */
10
+ export class ResourceNotSelectableError extends Schema.TaggedError()('ResourceNotSelectableError', {
11
+ target: Schema.String,
12
+ message: Schema.String,
13
+ }) {
14
+ }
15
+ /** The record exists but cannot serve this read: a reference cycle, several records matching one selector, or a value the caller's schema rejects. */
16
+ export class InvalidResourceError extends Schema.TaggedError()('InvalidResourceError', {
17
+ target: Schema.String,
18
+ message: Schema.String,
19
+ }) {
20
+ }
21
+ /** The runtime identity is missing or refused: no API URL or runtime token, a provider that never published a fresh token, or a 401/403. */
22
+ export class ResourcesUnauthorizedError extends Schema.TaggedError()('ResourcesUnauthorizedError', { message: Schema.String }) {
23
+ }
24
+ /** The runtime API gave no usable answer: a transport failure, a timeout, a 5xx, or a body the SDK cannot read. */
25
+ export class ResourcesUnavailableError extends Schema.TaggedError()('ResourcesUnavailableError', { message: Schema.String }) {
26
+ }
27
+ //# sourceMappingURL=ResourcesErrors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ResourcesErrors.js","sourceRoot":"","sources":["../src/ResourcesErrors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,gHAAgH;AAEhH,2HAA2H;AAC3H,MAAM,OAAO,qBAAsB,SAAQ,MAAM,CAAC,WAAW,EAAyB,CAAC,uBAAuB,EAAE;IAC9G,MAAM,EAAE,MAAM,CAAC,MAAM;IACrB,OAAO,EAAE,MAAM,CAAC,MAAM;CACvB,CAAC;CAAG;AAEL,+HAA+H;AAC/H,MAAM,OAAO,0BAA2B,SAAQ,MAAM,CAAC,WAAW,EAA8B,CAC9F,4BAA4B,EAC5B;IACE,MAAM,EAAE,MAAM,CAAC,MAAM;IACrB,OAAO,EAAE,MAAM,CAAC,MAAM;CACvB,CACF;CAAG;AAEJ,sJAAsJ;AACtJ,MAAM,OAAO,oBAAqB,SAAQ,MAAM,CAAC,WAAW,EAAwB,CAAC,sBAAsB,EAAE;IAC3G,MAAM,EAAE,MAAM,CAAC,MAAM;IACrB,OAAO,EAAE,MAAM,CAAC,MAAM;CACvB,CAAC;CAAG;AAEL,4IAA4I;AAC5I,MAAM,OAAO,0BAA2B,SAAQ,MAAM,CAAC,WAAW,EAA8B,CAC9F,4BAA4B,EAC5B,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,CAC3B;CAAG;AAEJ,mHAAmH;AACnH,MAAM,OAAO,yBAA0B,SAAQ,MAAM,CAAC,WAAW,EAA6B,CAC5F,2BAA2B,EAC3B,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,CAC3B;CAAG"}
@@ -0,0 +1,10 @@
1
+ import { Effect } from 'effect';
2
+ import { ResourcesUnauthorizedError } from './ResourcesErrors.js';
3
+ export interface RuntimeTokens {
4
+ /** The provider's token when it outlives the refresh window, otherwise the next one it publishes. */
5
+ readonly current: Effect.Effect<string, ResourcesUnauthorizedError>;
6
+ /** The first usable token other than the one the runtime API just refused. */
7
+ readonly replacing: (refused: string) => Effect.Effect<string, ResourcesUnauthorizedError>;
8
+ }
9
+ export declare const makeRuntimeTokens: Effect.Effect<RuntimeTokens>;
10
+ //# sourceMappingURL=ResourcesToken.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ResourcesToken.d.ts","sourceRoot":"","sources":["../src/ResourcesToken.ts"],"names":[],"mappings":"AACA,OAAO,EAAkC,MAAM,EAAsC,MAAM,QAAQ,CAAC;AACpG,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAuElE,MAAM,WAAW,aAAa;IAC5B,qGAAqG;IACrG,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC;IACpE,8EAA8E;IAC9E,QAAQ,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC;CAC5F;AAED,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,CAAC,aAAa,CAWzD,CAAC"}
@@ -0,0 +1,63 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { Cache, Clock, Config, Duration, Effect, Option, Redacted, Schedule, Schema } from 'effect';
3
+ import { ResourcesUnauthorizedError } from './ResourcesErrors.js';
4
+ /** A token this close to `exp` could lapse mid-request, so it counts as spent. */
5
+ const REFRESH_WINDOW_MS = 30_000;
6
+ /** Providers republish well inside this: the k8s refresher every 30 s, the Firecracker host on every renewal. */
7
+ const PUBLISH_TIMEOUT = Duration.seconds(35);
8
+ const POLL_INTERVAL = Duration.millis(100);
9
+ const TokenExpiry = Schema.StringFromBase64Url.pipe(Schema.decodeTo(Schema.fromJsonString(Schema.Struct({ exp: Schema.Number }))));
10
+ const decodeTokenExpiry = Schema.decodeUnknownOption(TokenExpiry);
11
+ /** Only a JWT that outlives the refresh window is sent; one without `exp` never is, as in `@ontemper/resources`. */
12
+ const outlivesRefreshWindow = (token, now) => Option.match(decodeTokenExpiry(token.split('.')[1]), {
13
+ onNone: () => false,
14
+ onSome: ({ exp }) => exp * 1000 - now > REFRESH_WINDOW_MS,
15
+ });
16
+ const TokenSources = Config.all({
17
+ file: Config.option(Config.String('UNNBOUND_RUNTIME_TOKEN_FILE')),
18
+ token: Config.option(Config.Redacted('UNNBOUND_RUNTIME_TOKEN')),
19
+ }).pipe(Effect.mapError((error) => new ResourcesUnauthorizedError({ message: `Runtime token settings are unreadable: ${error.message}` })));
20
+ /**
21
+ * The provider's file wins over the env token and both are re-read on every call, so a rotation is seen at once.
22
+ * An unreadable or empty file falls back to the env token; with neither configured nothing can ever authenticate.
23
+ */
24
+ const readToken = Effect.gen(function* () {
25
+ const sources = yield* TokenSources;
26
+ const file = Option.filter(sources.file, (path) => path.length > 0);
27
+ const token = Option.filter(Option.map(sources.token, Redacted.value), (value) => value.length > 0);
28
+ if (Option.isNone(file) && Option.isNone(token)) {
29
+ return yield* new ResourcesUnauthorizedError({
30
+ message: 'No runtime token is configured: set UNNBOUND_RUNTIME_TOKEN_FILE or UNNBOUND_RUNTIME_TOKEN.',
31
+ });
32
+ }
33
+ if (Option.isSome(file)) {
34
+ const contents = yield* Effect.option(Effect.tryPromise(() => readFile(file.value, 'utf8')));
35
+ const published = Option.filter(Option.map(contents, (text) => text.trim()), (text) => text.length > 0);
36
+ if (Option.isSome(published))
37
+ return published;
38
+ }
39
+ return token;
40
+ });
41
+ /** Polls the provider until it publishes a usable token other than `refused`. */
42
+ const awaitPublished = (refused) => Effect.gen(function* () {
43
+ const token = yield* readToken;
44
+ const now = yield* Clock.currentTimeMillis;
45
+ return Option.filter(token, (candidate) => candidate !== refused && outlivesRefreshWindow(candidate, now));
46
+ }).pipe(Effect.repeat({ schedule: Schedule.spaced(POLL_INTERVAL), until: Option.isSome }), Effect.map((published) => published.value), Effect.timeoutOrElse({
47
+ duration: PUBLISH_TIMEOUT,
48
+ orElse: () => Effect.fail(new ResourcesUnauthorizedError({ message: 'Runtime resolver token provider did not publish a fresh token.' })),
49
+ }));
50
+ export const makeRuntimeTokens = Effect.gen(function* () {
51
+ // Waiters on one refused token share a single poll; a refusal of a newer token starts its own.
52
+ const published = yield* Cache.makeWith(awaitPublished, { capacity: 8, timeToLive: () => Duration.zero });
53
+ const replacing = (refused) => Cache.get(published, refused);
54
+ const current = Effect.gen(function* () {
55
+ const token = yield* readToken;
56
+ const now = yield* Clock.currentTimeMillis;
57
+ if (Option.isSome(token) && outlivesRefreshWindow(token.value, now))
58
+ return token.value;
59
+ return yield* replacing(Option.getOrElse(token, () => ''));
60
+ });
61
+ return { current, replacing };
62
+ });
63
+ //# sourceMappingURL=ResourcesToken.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ResourcesToken.js","sourceRoot":"","sources":["../src/ResourcesToken.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import { Context, Effect, Layer, Redacted, Schema } from 'effect';
2
+ import { HttpClient } from 'effect/unstable/http';
3
+ import { type SelectResourceRuntimeInputSchema } from './Contract/RuntimeApi.js';
4
+ import { InvalidResourceError, ResourceNotFoundError, ResourceNotSelectableError, ResourcesUnauthorizedError, ResourcesUnavailableError } from './ResourcesErrors.js';
5
+ /** Finds the one record of a type whose `x-selectable` field equals the value a tenant presented. */
6
+ export type ResourceSelector = typeof SelectResourceRuntimeInputSchema.Type;
7
+ export type ReadError = ResourceNotFoundError | ResourcesUnauthorizedError | ResourcesUnavailableError;
8
+ /** What declared resources read through: the Temper runtime API in production, fixed values in tests. */
9
+ export interface ResourceReader {
10
+ /** A Variable's live value; `Redacted` because the platform, not the caller, decides what is secret. */
11
+ readonly variable: (key: string) => Effect.Effect<Redacted.Redacted<string>, ReadError>;
12
+ /** The record's value with every secret filled in, still undecoded. */
13
+ readonly resolve: (key: string) => Effect.Effect<Schema.Json, ReadError | InvalidResourceError>;
14
+ /** The key of the one record whose `x-selectable` field matches. */
15
+ readonly select: (selector: ResourceSelector) => Effect.Effect<string, ReadError | ResourceNotSelectableError | InvalidResourceError>;
16
+ }
17
+ declare const RuntimeResources_base: Context.ServiceClass<RuntimeResources, "@temper/workflow/RuntimeResources", ResourceReader>;
18
+ /**
19
+ * Variables and resources read live from the Temper runtime API with the workflow's runtime identity
20
+ * (`UNNBOUND_API_URL` plus `UNNBOUND_RUNTIME_TOKEN_FILE` or `UNNBOUND_RUNTIME_TOKEN`), cached for 30 s.
21
+ */
22
+ export declare class RuntimeResources extends RuntimeResources_base {
23
+ static readonly layer: Layer.Layer<RuntimeResources, never, HttpClient.HttpClient>;
24
+ }
25
+ export {};
26
+ //# sourceMappingURL=RuntimeResources.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RuntimeResources.d.ts","sourceRoot":"","sources":["../src/RuntimeResources.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,OAAO,EAAY,MAAM,EAAQ,KAAK,EAAU,QAAQ,EAAE,MAAM,EAAc,MAAM,QAAQ,CAAC;AAErH,OAAO,EAAE,UAAU,EAA2C,MAAM,sBAAsB,CAAC;AAE3F,OAAO,EAQL,KAAK,gCAAgC,EACtC,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,0BAA0B,EAC1B,0BAA0B,EAC1B,yBAAyB,EAC1B,MAAM,sBAAsB,CAAC;AAY9B,qGAAqG;AACrG,MAAM,MAAM,gBAAgB,GAAG,OAAO,gCAAgC,CAAC,IAAI,CAAC;AAE5E,MAAM,MAAM,SAAS,GAAG,qBAAqB,GAAG,0BAA0B,GAAG,yBAAyB,CAAC;AA2KvG,yGAAyG;AACzG,MAAM,WAAW,cAAc;IAC7B,wGAAwG;IACxG,QAAQ,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC,CAAC;IACxF,uEAAuE;IACvE,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,GAAG,oBAAoB,CAAC,CAAC;IAChG,oEAAoE;IACpE,QAAQ,CAAC,MAAM,EAAE,CACf,QAAQ,EAAE,gBAAgB,KACvB,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,0BAA0B,GAAG,oBAAoB,CAAC,CAAC;CAC3F;;AAED;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,qBAErC;IAEC,MAAM,CAAC,QAAQ,CAAC,KAAK,8DAAiD;CACvE"}
@@ -0,0 +1,115 @@
1
+ import { Cache, Config, Context, Duration, Effect, Exit, Layer, Option, Redacted, Schema } from 'effect';
2
+ import { constTrue } from 'effect/Function';
3
+ import { HttpClient, HttpClientRequest } from 'effect/unstable/http';
4
+ import { HttpApiClient } from 'effect/unstable/httpapi';
5
+ import { ResourcesRuntimeApi, } from './Contract/RuntimeApi.js';
6
+ import { registerSecrets } from './Redaction.js';
7
+ import { InvalidResourceError, ResourceNotFoundError, ResourceNotSelectableError, ResourcesUnauthorizedError, ResourcesUnavailableError, } from './ResourcesErrors.js';
8
+ import { makeRuntimeTokens } from './ResourcesToken.js';
9
+ // Resolved values are live configuration: an edit, or a revoked secret, reaches a warm process within this window.
10
+ const CACHE_TTL = Duration.seconds(30);
11
+ // Bounds memory for a workflow that selects across many tenants; the least recently read entry goes first.
12
+ const CACHE_CAPACITY = 1_024;
13
+ const REQUEST_TIMEOUT = Duration.seconds(5);
14
+ const Endpoints = ResourcesRuntimeApi.groups.resourcesRuntime.endpoints;
15
+ // A 401 on the first attempt ends it before its body is read, so the retry never waits on a refused answer.
16
+ class TokenRefused extends Schema.TaggedError()('TokenRefused', {}) {
17
+ }
18
+ class ApiUrlMissing extends Schema.TaggedError()('ApiUrlMissing', {}) {
19
+ }
20
+ // The status each declared runtime error answers with (see `Contract/RuntimeApi.ts`).
21
+ const statusOfRuntimeError = {
22
+ RuntimeResourcesBadRequestError: 400,
23
+ RuntimeResourcesUnauthorizedError: 401,
24
+ RuntimeResourcesForbiddenError: 403,
25
+ RuntimeResourcesNotFoundError: 404,
26
+ RuntimeResourcesConflictError: 409,
27
+ RuntimeResourcesUnavailableError: 503,
28
+ };
29
+ const ResourcesMake = Effect.gen(function* () {
30
+ const tokens = yield* makeRuntimeTokens;
31
+ // Each attempt's scope owns its request: leaving the scope aborts it, so no response outlives its attempt.
32
+ const platform = HttpClient.withScope(yield* HttpClient.HttpClient).pipe(HttpClient.mapRequestEffect((request) => Config.NonEmptyString('UNNBOUND_API_URL').pipe(Effect.map((apiUrl) => HttpClientRequest.prependUrl(request, apiUrl)), Effect.mapError(() => new ApiUrlMissing()))));
33
+ // A 401's body is the fixed `Unauthorized`; failing before it is read lets a refused attempt end at once.
34
+ const client = yield* HttpApiClient.makeWith(ResourcesRuntimeApi, {
35
+ httpClient: platform.pipe(HttpClient.filterOrFail((response) => response.status !== 401, () => new TokenRefused())),
36
+ });
37
+ // One call to the runtime API; a 401 swaps in the provider's next token and tries once more.
38
+ const call = (operation, target, send, refuse = () => undefined) => {
39
+ const failed = (detail) => `Runtime resolver ${Endpoints[operation].path} failed for ${target}: ${detail}`;
40
+ // A status the contract does not declare, or a body the SDK cannot read, leaves the resolver unavailable.
41
+ const toReadError = (error) => {
42
+ switch (error._tag) {
43
+ case 'ApiUrlMissing':
44
+ return new ResourcesUnauthorizedError({ message: failed('UNNBOUND_API_URL is not set') });
45
+ case 'TokenRefused':
46
+ return new ResourcesUnauthorizedError({ message: failed('401 Unauthorized') });
47
+ case 'HttpClientError':
48
+ return new ResourcesUnavailableError({
49
+ message: failed(error.response === undefined ? error.message : `${error.response.status}`),
50
+ });
51
+ case 'SchemaError':
52
+ return new ResourcesUnavailableError({ message: failed('unreadable answer') });
53
+ default: {
54
+ const status = statusOfRuntimeError[error._tag];
55
+ const message = failed(`${status} ${error.error}`);
56
+ if (status === 401 || status === 403)
57
+ return new ResourcesUnauthorizedError({ message });
58
+ if (status === 404)
59
+ return new ResourceNotFoundError({ target, message });
60
+ return refuse(status, message) ?? new ResourcesUnavailableError({ message });
61
+ }
62
+ }
63
+ };
64
+ // One request under one deadline that also covers reading its body; the attempt aborts the request as it ends.
65
+ const attempt = (attemptClient, token) => send(attemptClient, `Bearer ${token}`).pipe(Effect.scoped, Effect.timeoutOrElse({
66
+ duration: REQUEST_TIMEOUT,
67
+ orElse: () => Effect.fail(new ResourcesUnavailableError({
68
+ message: failed(`no answer within ${Duration.toMillis(REQUEST_TIMEOUT)} ms`),
69
+ })),
70
+ }),
71
+ // Resolver traffic is Temper's own transport, not the customer's work: no protocol lines, no span (T-3831).
72
+ Effect.provideService(HttpClient.TracerDisabledWhen, constTrue));
73
+ return Effect.gen(function* () {
74
+ const token = yield* tokens.current;
75
+ const first = yield* attempt(client.resourcesRuntime, token).pipe(Effect.map(Option.some), Effect.catchTag('TokenRefused', () => Effect.succeedNone));
76
+ if (Option.isSome(first))
77
+ return first.value;
78
+ return yield* attempt(client.resourcesRuntime, yield* tokens.replacing(token));
79
+ }).pipe(Effect.catchIf((error) => error._tag !== 'ResourcesUnauthorizedError' && error._tag !== 'ResourcesUnavailableError', (error) => Effect.fail(toReadError(error))));
80
+ };
81
+ const cache = (lookup) => Cache.makeWith(lookup, {
82
+ capacity: CACHE_CAPACITY,
83
+ // A failure is not kept: the next read asks the resolver again.
84
+ timeToLive: (exit) => (Exit.isSuccess(exit) ? CACHE_TTL : Duration.zero),
85
+ });
86
+ const variables = yield* cache((key) => call('resolveVariable', `key ${key}`, (api, authorization) => api.resolveVariable({ headers: { authorization }, payload: { key } })));
87
+ const values = yield* cache((key) => call('resolveResource', `key ${key}`, (api, authorization) => api.resolveResource({ headers: { authorization }, payload: { key } }), (status, message) => (status === 409 ? new InvalidResourceError({ target: `key ${key}`, message }) : undefined)));
88
+ // Keyed by value: `{a,b}` and `{b,a}` share one entry, and each tenant's presented value gets its own.
89
+ const selections = yield* cache((selector) => {
90
+ const target = `${selector.resourceTypeKey} matching ${Object.keys(selector.match).join(', ')}`;
91
+ return call('selectResource', target, (api, authorization) => api.selectResource({ headers: { authorization }, payload: selector }), (status, message) => status === 400
92
+ ? new ResourceNotSelectableError({ target, message })
93
+ : status === 409
94
+ ? new InvalidResourceError({ target, message })
95
+ : undefined);
96
+ });
97
+ // Registers the answer's secrets in the caller's context, so a cached read masks them like a fresh one.
98
+ const unwrap = (read) => read.pipe(Effect.tap(({ redactionMasks }) => registerSecrets(redactionMasks ?? [])), Effect.map(({ value }) => value));
99
+ return RuntimeResources.of({
100
+ variable: (key) => Effect.map(unwrap(Cache.get(variables, key)), Redacted.make),
101
+ // Each caller gets its own copy: the cached value is shared across requests for 30 s.
102
+ resolve: (key) => Effect.map(unwrap(Cache.get(values, key)), (value) => structuredClone(value)),
103
+ // A fresh key: Effect caches an object's hash by reference, so a reused, mutated selector could hit another tenant's entry.
104
+ select: (selector) => Effect.map(unwrap(Cache.get(selections, { resourceTypeKey: selector.resourceTypeKey, match: { ...selector.match } })), (selected) => selected.key),
105
+ });
106
+ });
107
+ /**
108
+ * Variables and resources read live from the Temper runtime API with the workflow's runtime identity
109
+ * (`UNNBOUND_API_URL` plus `UNNBOUND_RUNTIME_TOKEN_FILE` or `UNNBOUND_RUNTIME_TOKEN`), cached for 30 s.
110
+ */
111
+ export class RuntimeResources extends Context.Service()('@temper/workflow/RuntimeResources') {
112
+ // Needs `HttpClient`, which `workflow()` provides.
113
+ static layer = Layer.effect(RuntimeResources, ResourcesMake);
114
+ }
115
+ //# sourceMappingURL=RuntimeResources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RuntimeResources.js","sourceRoot":"","sources":["../src/RuntimeResources.ts"],"names":[],"mappings":"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"}
package/dist/Trigger.d.ts CHANGED
@@ -1,29 +1,4 @@
1
- import { Context, Schema } from 'effect';
2
- export declare const TriggerKind: Schema.Literals<readonly ["http", "schedule", "manual", "internal"]>;
3
- export type TriggerKind = typeof TriggerKind.Type;
4
- export declare const ResponsePolicy: Schema.Literals<readonly ["wait", "ack"]>;
5
- export type ResponsePolicy = typeof ResponsePolicy.Type;
6
- /**
7
- * How the platform invokes one route. `kind` is the contract; the other fields are DEFAULTS that
8
- * deploy seeds into the stored Trigger and Schedule records when none exist. A stored record edited
9
- * through the product or the Temper agent always wins afterwards; deploy reports the drift.
10
- */
11
- export declare const TriggerMetadata: Schema.Union<readonly [Schema.Struct<{
12
- readonly kind: Schema.Literal<"http">;
13
- /** Default response policy for the stored Trigger: `wait` returns the handler response, `ack` returns 202. */
14
- readonly response: Schema.optional<Schema.Literals<readonly ["wait", "ack"]>>;
15
- }>, Schema.Struct<{
16
- readonly kind: Schema.Literal<"schedule">;
17
- /** Default cadence for the stored Schedule; five-field cron. Without it deploy warns until a Schedule exists. */
18
- readonly cron: Schema.optional<Schema.String>;
19
- /** IANA timezone for `cron`; the platform default is UTC. */
20
- readonly timezone: Schema.optional<Schema.String>;
21
- }>, Schema.Struct<{
22
- readonly kind: Schema.Literal<"manual">;
23
- }>, Schema.Struct<{
24
- readonly kind: Schema.Literal<"internal">;
25
- }>]>;
26
- export type TriggerMetadata = typeof TriggerMetadata.Type;
1
+ import { Context } from 'effect';
27
2
  declare const Trigger_base: Context.ServiceClass<Trigger, "@temper/workflow/Trigger", {
28
3
  readonly kind: "http";
29
4
  readonly response?: "ack" | "wait" | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"Trigger.d.ts","sourceRoot":"","sources":["../src/Trigger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEzC,eAAO,MAAM,WAAW,sEAA8D,CAAC;AACvF,MAAM,MAAM,WAAW,GAAG,OAAO,WAAW,CAAC,IAAI,CAAC;AAElD,eAAO,MAAM,cAAc,2CAAmC,CAAC;AAC/D,MAAM,MAAM,cAAc,GAAG,OAAO,cAAc,CAAC,IAAI,CAAC;AAExD;;;;GAIG;AACH,eAAO,MAAM,eAAe;;IAGxB,8GAA8G;;;;IAK9G,iHAAiH;;IAEjH,6DAA6D;;;;;;IAK/D,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,eAAe,CAAC,IAAI,CAAC;;;;;;;;;;;;;AAE1D,qBAAa,OAAQ,SAAQ,YAAuE;CAAG"}
1
+ {"version":3,"file":"Trigger.d.ts","sourceRoot":"","sources":["../src/Trigger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;;;;;;;;;;;;;AAGjC,qBAAa,OAAQ,SAAQ,YAAuE;CAAG"}
package/dist/Trigger.js CHANGED
@@ -1,27 +1,4 @@
1
- import { Context, Schema } from 'effect';
2
- export const TriggerKind = Schema.Literals(['http', 'schedule', 'manual', 'internal']);
3
- export const ResponsePolicy = Schema.Literals(['wait', 'ack']);
4
- /**
5
- * How the platform invokes one route. `kind` is the contract; the other fields are DEFAULTS that
6
- * deploy seeds into the stored Trigger and Schedule records when none exist. A stored record edited
7
- * through the product or the Temper agent always wins afterwards; deploy reports the drift.
8
- */
9
- export const TriggerMetadata = Schema.Union([
10
- Schema.Struct({
11
- kind: Schema.Literal('http'),
12
- /** Default response policy for the stored Trigger: `wait` returns the handler response, `ack` returns 202. */
13
- response: Schema.optional(ResponsePolicy),
14
- }),
15
- Schema.Struct({
16
- kind: Schema.Literal('schedule'),
17
- /** Default cadence for the stored Schedule; five-field cron. Without it deploy warns until a Schedule exists. */
18
- cron: Schema.optional(Schema.String),
19
- /** IANA timezone for `cron`; the platform default is UTC. */
20
- timezone: Schema.optional(Schema.String),
21
- }),
22
- Schema.Struct({ kind: Schema.Literal('manual') }),
23
- Schema.Struct({ kind: Schema.Literal('internal') }),
24
- ]);
1
+ import { Context } from 'effect';
25
2
  export class Trigger extends Context.Service()('@temper/workflow/Trigger') {
26
3
  }
27
4
  //# sourceMappingURL=Trigger.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Trigger.js","sourceRoot":"","sources":["../src/Trigger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEzC,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC;AAGvF,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;AAG/D;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,KAAK,CAAC;IAC1C,MAAM,CAAC,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;QAC5B,8GAA8G;QAC9G,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC;KAC1C,CAAC;IACF,MAAM,CAAC,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;QAChC,iHAAiH;QACjH,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;QACpC,6DAA6D;QAC7D,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;KACzC,CAAC;IACF,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;IACjD,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;CACpD,CAAC,CAAC;AAGH,MAAM,OAAO,OAAQ,SAAQ,OAAO,CAAC,OAAO,EAA4B,CAAC,0BAA0B,CAAC;CAAG"}
1
+ {"version":3,"file":"Trigger.js","sourceRoot":"","sources":["../src/Trigger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAGjC,MAAM,OAAO,OAAQ,SAAQ,OAAO,CAAC,OAAO,EAA4B,CAAC,0BAA0B,CAAC;CAAG"}
@@ -1,19 +1,36 @@
1
- import { Layer } from 'effect';
2
- import { HttpRouter } from 'effect/unstable/http';
3
- import { type HttpApi, type HttpApiGroup } from 'effect/unstable/httpapi';
4
- import { Invocation, type InvocationContext } from './Invocation.js';
5
- import { type WorkflowManifest } from './Manifest.js';
1
+ import { Clock, ConfigProvider, Layer } from 'effect';
2
+ import { type HttpClient, HttpRouter } from 'effect/unstable/http';
3
+ import { HttpApi, type HttpApiGroup } from 'effect/unstable/httpapi';
4
+ import type { InvocationContext } from './Contract/Invocation.js';
5
+ import type { WorkflowManifest } from './Contract/Manifest.js';
6
+ import { type OutboundFetch } from './HttpClient.js';
7
+ import { Invocation } from './Invocation.js';
8
+ import { type AnyDeclaration } from './Resource.js';
9
+ import { type ResourceReader } from './RuntimeResources.js';
10
+ /** Platform services a test or local tool may replace; production uses every default. */
11
+ export interface WorkflowPlatform {
12
+ /** Receives one JSON line per log. Defaults to stdout, which the platform reads. */
13
+ readonly writeLog?: ((line: string) => void) | undefined;
14
+ /** Answers `Config` reads. Defaults to the live process environment. */
15
+ readonly configProvider?: ConfigProvider.ConfigProvider | undefined;
16
+ /** Sends the requests of the workflow's `HttpClient`. Defaults to the global `fetch`. */
17
+ readonly outboundFetch?: OutboundFetch | undefined;
18
+ /** Times the invocation deadline and log spans. Defaults to the system clock. */
19
+ readonly clock?: Clock.Clock | undefined;
20
+ /** Answers declared resources and variables. Defaults to the Temper runtime API. */
21
+ readonly resources?: ResourceReader | undefined;
22
+ }
6
23
  export interface WorkflowModule<Api extends HttpApi.Constraint = HttpApi.Constraint> {
7
24
  readonly api: Api;
8
25
  readonly manifest: WorkflowManifest;
9
26
  readonly fetch: (request: Request, context: InvocationContext) => Promise<Response>;
10
27
  readonly dispose: () => Promise<void>;
28
+ /** The same workflow over replaced platform services; the caller disposes it. */
29
+ readonly withPlatform: (platform: WorkflowPlatform) => WorkflowModule<Api>;
11
30
  }
12
- export interface WorkflowOptions<Id extends string, Groups extends HttpApiGroup.Constraint> {
31
+ export interface WorkflowOptions<Id extends string, Groups extends HttpApiGroup.Constraint> extends WorkflowPlatform {
13
32
  readonly api: HttpApi.HttpApi<Id, Groups>;
14
- readonly handlers: Layer.Layer<HttpApiGroup.ToService<Id, Groups>, never, HttpRouter.Request.From<'Requires', Invocation>>;
15
- /** Receives one JSON log line per `Effect.log*` call. Defaults to stdout, which the platform reads. */
16
- readonly writeLog?: (line: string) => void;
33
+ readonly handlers: Layer.Layer<HttpApiGroup.ToService<Id, Groups>, never, HttpRouter.Request.From<'Requires', Invocation> | HttpClient.HttpClient | AnyDeclaration>;
17
34
  }
18
35
  export declare const workflow: <Id extends string, Groups extends HttpApiGroup.Constraint>(options: WorkflowOptions<Id, Groups>) => WorkflowModule<HttpApi.HttpApi<Id, Groups>>;
19
36
  //# sourceMappingURL=Workflow.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Workflow.d.ts","sourceRoot":"","sources":["../src/Workflow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,EAAoB,MAAM,QAAQ,CAAC;AACtE,OAAO,EAAsB,UAAU,EAAkC,MAAM,sBAAsB,CAAC;AACtG,OAAO,EAAkB,KAAK,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC1F,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAErE,OAAO,EAAgB,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAkBpE,MAAM,WAAW,cAAc,CAAC,GAAG,SAAS,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU;IACjF,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IACpF,QAAQ,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,MAAM,SAAS,YAAY,CAAC,UAAU;IACxF,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IAC1C,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,KAAK,CAC5B,YAAY,CAAC,SAAS,CAAC,EAAE,EAAE,MAAM,CAAC,EAClC,KAAK,EACL,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,CAChD,CAAC;IACF,uGAAuG;IACvG,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5C;AAWD,eAAO,MAAM,QAAQ,GAAI,EAAE,SAAS,MAAM,EAAE,MAAM,SAAS,YAAY,CAAC,UAAU,WACvE,eAAe,CAAC,EAAE,EAAE,MAAM,CAAC,KACnC,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,CAyB5C,CAAC"}
1
+ {"version":3,"file":"Workflow.d.ts","sourceRoot":"","sources":["../src/Workflow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,cAAc,EAAuB,KAAK,EAAQ,MAAM,QAAQ,CAAC;AACjF,OAAO,EAAQ,KAAK,UAAU,EAAgB,UAAU,EAAkC,MAAM,sBAAsB,CAAC;AACvH,OAAO,EAAE,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACrF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAK7C,OAAO,EAAE,KAAK,cAAc,EAAmC,MAAM,eAAe,CAAC;AACrF,OAAO,EAAoB,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAkB9E,yFAAyF;AACzF,MAAM,WAAW,gBAAgB;IAC/B,oFAAoF;IACpF,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACzD,wEAAwE;IACxE,QAAQ,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC,cAAc,GAAG,SAAS,CAAC;IACpE,yFAAyF;IACzF,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IACnD,iFAAiF;IACjF,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,KAAK,GAAG,SAAS,CAAC;IACzC,oFAAoF;IACpF,QAAQ,CAAC,SAAS,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;CACjD;AAED,MAAM,WAAW,cAAc,CAAC,GAAG,SAAS,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU;IACjF,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IACpF,QAAQ,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,iFAAiF;IACjF,QAAQ,CAAC,YAAY,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,cAAc,CAAC,GAAG,CAAC,CAAC;CAC5E;AAED,MAAM,WAAW,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,MAAM,SAAS,YAAY,CAAC,UAAU,CAAE,SAAQ,gBAAgB;IAClH,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IAC1C,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,KAAK,CAC5B,YAAY,CAAC,SAAS,CAAC,EAAE,EAAE,MAAM,CAAC,EAClC,KAAK,EACL,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,GAAG,UAAU,CAAC,UAAU,GAAG,cAAc,CACzF,CAAC;CACH;AAsDD,eAAO,MAAM,QAAQ,GAAI,EAAE,SAAS,MAAM,EAAE,MAAM,SAAS,YAAY,CAAC,UAAU,WACvE,eAAe,CAAC,EAAE,EAAE,MAAM,CAAC,KACnC,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,CAmC5C,CAAC"}