@prestack/thread 0.1.21 → 0.1.23

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 (138) hide show
  1. package/CHANGELOG.md +227 -0
  2. package/dist/core/attach.js +21 -0
  3. package/dist/core/descend.js +6 -3
  4. package/dist/core/generators/commit.js +55 -3
  5. package/dist/core/generators/dev.d.ts +1 -0
  6. package/dist/core/generators/dev.js +69 -0
  7. package/dist/derivation/generators/build.d.ts +3 -1
  8. package/dist/derivation/generators/build.js +104 -22
  9. package/dist/derivation/generators/release.js +74 -25
  10. package/dist/derivation/release.js +3 -3
  11. package/dist/integrations/cli.d.ts +0 -1
  12. package/dist/integrations/cli.js +69 -11
  13. package/dist/integrations/declared.d.ts +2 -0
  14. package/dist/integrations/declared.js +6 -1
  15. package/dist/integrations/pglite.js +13 -3
  16. package/dist/integrations/target.d.ts +3 -0
  17. package/dist/integrity/attach.js +1 -5
  18. package/dist/integrity/slopnators/sl_stale_path.js +10 -0
  19. package/dist/operations/access.js +3 -2
  20. package/dist/operations/capabilities.d.ts +2 -0
  21. package/dist/operations/capabilities.js +2 -0
  22. package/dist/operations/generators/capability.js +237 -24
  23. package/dist/operations/generators/compile.js +150 -50
  24. package/dist/operations/generators/seed.d.ts +3 -0
  25. package/dist/operations/generators/seed.js +25 -3
  26. package/dist/operations/nodes.d.ts +2 -2
  27. package/package.json +1 -1
  28. package/dist/core/actor.ts +0 -21
  29. package/dist/core/attach.ts +0 -613
  30. package/dist/core/chain.ts +0 -145
  31. package/dist/core/condition.ts +0 -227
  32. package/dist/core/descend.ts +0 -1185
  33. package/dist/core/errors/catalogue.ts +0 -314
  34. package/dist/core/errors/classes.ts +0 -51
  35. package/dist/core/errors/error.ts +0 -152
  36. package/dist/core/errors/namespaces.ts +0 -19
  37. package/dist/core/finding.ts +0 -37
  38. package/dist/core/generators/commit.ts +0 -157
  39. package/dist/core/init.ts +0 -222
  40. package/dist/core/invoked.ts +0 -52
  41. package/dist/core/round.ts +0 -74
  42. package/dist/core/rows.ts +0 -506
  43. package/dist/core/scope.ts +0 -20
  44. package/dist/core/thread.ts +0 -29
  45. package/dist/core/tree.ts +0 -90
  46. package/dist/core/types.ts +0 -351
  47. package/dist/derivation/attach.ts +0 -57
  48. package/dist/derivation/generators/build.ts +0 -371
  49. package/dist/derivation/generators/check.ts +0 -118
  50. package/dist/derivation/generators/determinism.ts +0 -145
  51. package/dist/derivation/generators/release.ts +0 -236
  52. package/dist/derivation/release.ts +0 -43
  53. package/dist/integrations/attach.ts +0 -187
  54. package/dist/integrations/cli.ts +0 -606
  55. package/dist/integrations/declared.ts +0 -34
  56. package/dist/integrations/disk.ts +0 -466
  57. package/dist/integrations/generators/read.ts +0 -127
  58. package/dist/integrations/generators/vault.ts +0 -210
  59. package/dist/integrations/https.ts +0 -216
  60. package/dist/integrations/pglite.ts +0 -206
  61. package/dist/integrations/secret.ts +0 -54
  62. package/dist/integrations/target.ts +0 -672
  63. package/dist/integrations/vault.ts +0 -148
  64. package/dist/integrity/attach.ts +0 -150
  65. package/dist/integrity/check-threads.ts +0 -166
  66. package/dist/integrity/constraint.ts +0 -1246
  67. package/dist/integrity/generators/compiler.ts +0 -138
  68. package/dist/integrity/generators/gate.ts +0 -227
  69. package/dist/integrity/generators/issues.ts +0 -160
  70. package/dist/integrity/generators/publish.ts +0 -233
  71. package/dist/integrity/generators/trial.ts +0 -359
  72. package/dist/integrity/lint.ts +0 -214
  73. package/dist/integrity/lsp/bin.ts +0 -44
  74. package/dist/integrity/lsp/diagnostics.ts +0 -92
  75. package/dist/integrity/lsp/findings.ts +0 -63
  76. package/dist/integrity/lsp/lint.ts +0 -124
  77. package/dist/integrity/lsp/protocol.ts +0 -78
  78. package/dist/integrity/lsp/server.ts +0 -224
  79. package/dist/integrity/slopnator.ts +0 -324
  80. package/dist/integrity/slopnators/sl_broken_lineage.ts +0 -38
  81. package/dist/integrity/slopnators/sl_declared_elsewhere.ts +0 -60
  82. package/dist/integrity/slopnators/sl_derived_drift.ts +0 -101
  83. package/dist/integrity/slopnators/sl_door_in_a_node.ts +0 -250
  84. package/dist/integrity/slopnators/sl_hardcoded_style.ts +0 -55
  85. package/dist/integrity/slopnators/sl_inert_island.ts +0 -84
  86. package/dist/integrity/slopnators/sl_inert_slopnator.ts +0 -93
  87. package/dist/integrity/slopnators/sl_missing_row.ts +0 -140
  88. package/dist/integrity/slopnators/sl_no_barrel.ts +0 -48
  89. package/dist/integrity/slopnators/sl_no_child_process.ts +0 -100
  90. package/dist/integrity/slopnators/sl_no_comment.ts +0 -43
  91. package/dist/integrity/slopnators/sl_no_dispatch_bypass.ts +0 -276
  92. package/dist/integrity/slopnators/sl_no_import_cycle.ts +0 -66
  93. package/dist/integrity/slopnators/sl_no_such_command.ts +0 -81
  94. package/dist/integrity/slopnators/sl_only_takes_a_literal.ts +0 -63
  95. package/dist/integrity/slopnators/sl_outside_an_operation.ts +0 -25
  96. package/dist/integrity/slopnators/sl_screen_holds_only_declared.ts +0 -70
  97. package/dist/integrity/slopnators/sl_secret_literal.ts +0 -68
  98. package/dist/integrity/slopnators/sl_stale_path.ts +0 -178
  99. package/dist/integrity/slopnators/sl_twice_meant.ts +0 -57
  100. package/dist/integrity/slopnators/sl_twice_parented.ts +0 -82
  101. package/dist/integrity/slopnators/sl_undeclared_crossing.ts +0 -481
  102. package/dist/integrity/slopnators/sl_undeclared_destination.ts +0 -113
  103. package/dist/integrity/slopnators/sl_undeclared_element.ts +0 -44
  104. package/dist/integrity/slopnators/sl_undeclared_list.ts +0 -358
  105. package/dist/integrity/slopnators/sl_undeclared_node.ts +0 -75
  106. package/dist/integrity/slopnators/sl_undeclared_operation.ts +0 -257
  107. package/dist/integrity/slopnators/sl_undeclared_variant.ts +0 -152
  108. package/dist/integrity/slopnators/sl_undeclared_webhook.ts +0 -108
  109. package/dist/integrity/slopnators/sl_underived_route.ts +0 -72
  110. package/dist/integrity/slopnators/sl_undescribed.ts +0 -65
  111. package/dist/integrity/slopnators/sl_ungoverned_island.ts +0 -60
  112. package/dist/integrity/slopnators/sl_unlisted_program.ts +0 -46
  113. package/dist/integrity/slopnators/sl_unnamed_island.ts +0 -41
  114. package/dist/integrity/slopnators/sl_unpaired_member.ts +0 -139
  115. package/dist/integrity/slopnators/sl_unpaired_slopnator.ts +0 -71
  116. package/dist/integrity/slopnators/sl_unprefixed_member.ts +0 -110
  117. package/dist/integrity/slopnators/sl_unthreaded.ts +0 -421
  118. package/dist/integrity/slopnators/sl_untranslated_key.ts +0 -140
  119. package/dist/integrity/slopnators/sl_unvaulted_secret.ts +0 -132
  120. package/dist/integrity/slopnators/sl_unversioned.ts +0 -52
  121. package/dist/integrity/sweep.ts +0 -395
  122. package/dist/knowledge/attach.ts +0 -327
  123. package/dist/knowledge/generators/docsgen.ts +0 -186
  124. package/dist/knowledge/generators/glossary.ts +0 -73
  125. package/dist/knowledge/glossary.ts +0 -6
  126. package/dist/operations/access.ts +0 -131
  127. package/dist/operations/attach.ts +0 -408
  128. package/dist/operations/capabilities.ts +0 -88
  129. package/dist/operations/dispatch.ts +0 -294
  130. package/dist/operations/error-results.ts +0 -31
  131. package/dist/operations/generators/capability.ts +0 -1054
  132. package/dist/operations/generators/compile.ts +0 -701
  133. package/dist/operations/generators/permits.ts +0 -229
  134. package/dist/operations/generators/seed.ts +0 -359
  135. package/dist/operations/generators/trial.ts +0 -666
  136. package/dist/operations/nodes.ts +0 -53
  137. package/dist/operations/operations.ts +0 -91
  138. package/dist/operations/result.ts +0 -28
@@ -1,294 +0,0 @@
1
- import { ANONYMOUS, ENVIRONMENT } from '../core/actor.ts'
2
- import { HOLDS, type Holds, type Reach } from '../integrations/target.ts'
3
- import { PERMITS_AT } from './access.ts'
4
- import { DbConflict } from '../core/errors/catalogue.ts'
5
- import { beside, quoted, runtime } from './generators/seed.ts'
6
- import type { ResultCode } from './result.ts'
7
-
8
- const reaching = (holds: (one: Holds) => boolean): readonly Reach[] =>
9
- (Object.keys(HOLDS) as Reach[]).filter((one) => holds(HOLDS[one]))
10
-
11
- const KEEPS = reaching((one) => one.takes === 'entities')
12
-
13
- const ANSWERS = reaching((one) => one.takes === null)
14
-
15
- const RUNS = reaching((one) => one.takes === 'calls' && one.addressed === 'nothing')
16
-
17
- const asked = (reaches: readonly Reach[]): string => reaches.map((one) => "reach === '" + one + "'").join(' || ')
18
-
19
- export const DISPATCH_AT = 'operations/_dispatch.ts'
20
-
21
- const REFUSAL: Readonly<Record<ResultCode, string>> = {
22
- denied: 'not allowed',
23
- invalid: 'invalid input',
24
- rate_limited: 'rate limited',
25
- feature_denied: 'not in plan',
26
- quota_exceeded: 'quota exceeded',
27
- error: 'failed',
28
- }
29
-
30
- const printed = (value: unknown): string => JSON.stringify(value, null, 2)
31
-
32
- export const dispatched = (
33
- reached: Readonly<
34
- Record<
35
- string,
36
- {
37
- readonly reach: string
38
- readonly address?: string
39
- readonly headers: Readonly<Record<string, string>>
40
- readonly sends: readonly { readonly secret: string; readonly header: string; readonly prefix: string }[]
41
- readonly signs: readonly { readonly secret: string; readonly header: string; readonly prefix: string }[]
42
- readonly calls: Readonly<Record<string, { readonly method: string | null; readonly path: string }>>
43
- }
44
- >
45
- >,
46
- ): string => [
47
- "import { createHmac } from 'node:crypto'",
48
- '',
49
- `import type { Actor } from ${quoted(runtime(DISPATCH_AT, '../../core/actor.ts'))}`,
50
- `import type { Allowance, Counting, Operation } from ${quoted(runtime(DISPATCH_AT, '../operations.ts'))}`,
51
- `import type { FailureIdentity, Result, ResultCode } from ${quoted(runtime(DISPATCH_AT, '../result.ts'))}`,
52
- 'import type { Opened } from ' + quoted(runtime(DISPATCH_AT, '../operations.ts')),
53
- 'import type { Vault } from ' + quoted(runtime(DISPATCH_AT, '../../integrations/secret.ts')),
54
- `import { permits } from ${quoted(beside(DISPATCH_AT, PERMITS_AT))}`,
55
- '',
56
- `const ANONYMOUS: Actor = ${printed(ANONYMOUS)}`,
57
- '',
58
- `const ENVIRONMENT: readonly string[] = ${printed(ENVIRONMENT.map(([fact]) => fact))}`,
59
- '',
60
- `const REFUSAL: Readonly<Record<ResultCode, string>> = ${printed(REFUSAL)}`,
61
- '',
62
- `const CONFLICT = ${printed({ code: DbConflict.def.code, class: DbConflict.def.class })} as FailureIdentity`,
63
- '',
64
- 'type Reached = Readonly<Record<string, {',
65
- ' readonly reach: string',
66
- ' readonly address?: string',
67
- ' readonly headers: Readonly<Record<string, string>>',
68
- ' readonly sends: readonly { readonly secret: string; readonly header: string; readonly prefix: string }[]',
69
- ' readonly signs: readonly { readonly secret: string; readonly header: string; readonly prefix: string }[]',
70
- ' readonly calls: Readonly<Record<string, { readonly method: string | null; readonly path: string }>>',
71
- '}>>',
72
- '',
73
- 'type Reaches = Readonly<Record<string, unknown>>',
74
- '',
75
- `const REACHED: Reached = ${printed(reached)}`,
76
- '',
77
- "const STOPPED = Symbol.for('thread.operation.stopped')",
78
- '',
79
- 'const ok = <O>(value: O): Result<O> => ({ ok: true, value })',
80
- '',
81
- 'const fail = (code: ResultCode, error: string, because?: string, identity?: FailureIdentity): Result<never> => ({',
82
- ' ok: false,',
83
- ' code,',
84
- ' error,',
85
- ' because,',
86
- ' ...(identity === undefined ? {} : { errorCode: identity.code, errorClass: identity.class }),',
87
- '}) as Result<never>',
88
- '',
89
- 'const allowance = async (',
90
- ' id: string,',
91
- ' actor: Actor,',
92
- ' counting: Counting | undefined,',
93
- ' held: Allowance | undefined,',
94
- ' code: ResultCode,',
95
- '): Promise<Result<never> | undefined> => {',
96
- ' if (held === undefined) return undefined',
97
- ' if (counting === undefined) {',
98
- " return fail('error', REFUSAL['error'], id + ' allows ' + String(held.runs) + ' run(s) per ' + held.per + ' and this dispatch was handed nothing to count with. An operation that states an allowance is handed a counter or it does not run')",
99
- ' }',
100
- " const seen = await counting['seen'](id + '/' + String(actor.id ?? 'anonymous') + '/' + code, held.per)",
101
- ' if (seen <= held.runs) return undefined',
102
- " return fail(code, REFUSAL[code], String(seen) + ' of ' + String(held.runs) + ' allowed per ' + held.per)",
103
- '}',
104
- '',
105
- "const strings = (value: unknown): value is string[] => Array.isArray(value) && value.every((one) => typeof one === 'string')",
106
- '',
107
- 'const person = (value: unknown): Actor | undefined => {',
108
- " if (typeof value !== 'object' || value === null) return undefined",
109
- ' const one = value as Record<string, unknown>',
110
- " const id = one['id']",
111
- " if (!(id === null || typeof id === 'string')) return undefined",
112
- " const roles = one['roles']",
113
- " const entitlements = one['entitlements']",
114
- ' if (!strings(roles) || !strings(entitlements)) return undefined',
115
- ' const carried: Record<string, string> = {}',
116
- ' for (const fact of ENVIRONMENT) {',
117
- ' const held = one[fact]',
118
- ' if (held === undefined) continue',
119
- " if (typeof held !== 'string') return undefined",
120
- ' carried[fact] = held',
121
- ' }',
122
- ' return { ...carried, id, roles, entitlements }',
123
- '}',
124
- '',
125
- 'const named = (thrown: unknown, what: string): boolean => {',
126
- " if (typeof thrown !== 'object' || thrown === null) return false",
127
- ' const one = thrown as { readonly name?: unknown; readonly constructor?: { readonly name?: unknown } }',
128
- ' return one.name === what || one.constructor?.name === what',
129
- '}',
130
- '',
131
- 'const stopped = (thrown: unknown): { readonly value: unknown } | undefined => {',
132
- " if (typeof thrown !== 'object' || thrown === null) return undefined",
133
- ' const one = thrown as Record<PropertyKey, unknown>',
134
- " return one[STOPPED] === true ? { value: one['value'] } : undefined",
135
- '}',
136
- '',
137
- 'const platform = (thrown: unknown): string | undefined => {',
138
- " if (typeof thrown !== 'object' || thrown === null) return undefined",
139
- ' const said = (thrown as { readonly because?: unknown }).because',
140
- " return typeof said === 'string' ? said : undefined",
141
- '}',
142
- '',
143
- 'const filled = (path: string, fills: Readonly<Record<string, string | number>> | undefined): string => {',
144
- ' let held = path',
145
- ' for (const [name, value] of Object.entries(fills ?? {})) held = held.split(`{${name}}`).join(encodeURIComponent(String(value)))',
146
- ' const left = /\\{([a-z][a-z0-9_]*)\\}/.exec(held)',
147
- ' if (left !== null) throw new Error(`the path ${path} leaves ${left[0]} to be filled and nothing filled it`)',
148
- ' return held',
149
- '}',
150
- '',
151
- 'const bound = (word: string, wired: Reached[string], opened: Reaches, opening: Vault | undefined, within: number): Record<string, unknown> | string => {',
152
- ' const reached = opened[word]',
153
- ' const { reach } = wired',
154
- ' if (' + asked(ANSWERS) + ') {',
155
- ' const held = reached',
156
- ' if (held === undefined) {',
157
- " return word + ' is a disk this operation requires, and this dispatch was handed none under that name. The disk under this process is written in by thread capabilities; one at the other end of a connection is handed in by whoever opened it'",
158
- ' }',
159
- ' return held as unknown as Record<string, unknown>',
160
- ' }',
161
- ' if (' + asked(KEEPS) + ') {',
162
- ' if (reached === undefined) {',
163
- " return word + ' keeps rows for this app, and this dispatch was handed no store. A store is written in by thread capabilities, out of the target that keeps the entity'",
164
- ' }',
165
- ' return reached as unknown as Record<string, unknown>',
166
- ' }',
167
- '',
168
- ' const names = Object.keys(wired.calls)',
169
- ' if (names.length === 0) {',
170
- ' return `\\`${word}\\` is required and takes no call, so there is nothing to hand a node. Declare one with \\`thread create target call\\``',
171
- ' }',
172
- ' if (' + asked(RUNS) + ') {',
173
- ' const held = reached',
174
- ' if (held === undefined) {',
175
- " return word + ' is a program this operation requires, and this dispatch was handed none under that name. A program is written in by thread capabilities, out of the calls declared beside the target'",
176
- ' }',
177
- ' const out: Record<string, unknown> = {}',
178
- ' for (const name of names) {',
179
- ' const doing = (held as unknown as Record<string, unknown>)[name]',
180
- " if (typeof doing !== 'function') {",
181
- " return word + ' takes ' + name + ' and the program handed in under that name does not answer to it, so a node would be handed a word that does nothing'",
182
- ' }',
183
- ' out[name] = (args: readonly string[], shows?: boolean, sooner?: number, how?: unknown) => (doing as (a: readonly string[], s?: boolean, w?: number, h?: unknown) => unknown)(args, shows, sooner === undefined ? within : Math.min(sooner, within), how)',
184
- ' }',
185
- ' return out',
186
- ' }',
187
- ' if (reached === undefined) {',
188
- " return word + ' is reached over ' + wired.reach + ', and this dispatch was handed nothing to send an outward call through. thread capabilities writes that in; or take that word off the row that requires it'",
189
- ' }',
190
- ' const wanted = [...wired.sends.map((one) => one.secret), ...wired.signs.map((one) => one.secret)]',
191
- ' if (wanted.length > 0 && opening === undefined) {',
192
- " return word + ' needs ' + wanted.join(', ') + ' and this dispatch was handed no vault to open them. A target is reached with what opens it or not at all'",
193
- ' }',
194
- ' const out: Record<string, unknown> = {}',
195
- ' for (const name of names) {',
196
- ' const call = wired.calls[name]',
197
- ' if (call === undefined) continue',
198
- ' out[name] = async (given?: { fills?: Readonly<Record<string, string | number>>; json?: unknown; body?: Uint8Array; contentType?: string; told?: (said: unknown) => void }) => {',
199
- " const values = wanted.length === 0 ? {} : await opening!['resolve'](wanted)",
200
- ' const headers: Record<string, string> = {}',
201
- ' for (const [name, value] of Object.entries(wired.headers)) headers[name] = value',
202
- ' for (const one of wired.sends) headers[one.header] = `${one.prefix}${values[one.secret] ?? \'\'}`',
203
- ' const body = given?.json === undefined ? given?.body : new TextEncoder().encode(JSON.stringify(given.json))',
204
- ' for (const one of wired.signs) {',
205
- " const mac = createHmac('sha256', values[one.secret] ?? '').update(body ?? new Uint8Array()).digest('hex')",
206
- ' headers[one.header] = one.prefix + mac',
207
- ' }',
208
- " const send = reached as { call: (request: unknown, within?: number) => Promise<unknown> }",
209
- " return await send['call']({",
210
- ' target: word,',
211
- ' address: wired.address ?? \'\',',
212
- " method: call.method as 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',",
213
- ' path: filled(call.path, given?.fills),',
214
- ' headers,',
215
- ' ...(body === undefined ? {} : { body, contentType: given?.contentType ?? \'application/json\' }),',
216
- ' ...(given?.told === undefined ? {} : { told: given.told }),',
217
- ' }, within)',
218
- ' }',
219
- ' }',
220
- ' return out',
221
- '}',
222
- '',
223
- 'const given = (operation: Operation<unknown, string>, actor: Actor, opened: Reaches, opening: Vault | undefined, telling: (said: unknown) => void): Record<string, unknown> | string => {',
224
- ' const held: Record<string, unknown> = { actor, tell: telling }',
225
- ' for (const word of operation.requires) {',
226
- ' const wired = REACHED[word]',
227
- ' if (wired === undefined) {',
228
- ' return `\\`${operation[\'id\']}\\` requires \\`${word}\\`, and this app declares no target by that name. An operation requires targets: declare one with \\`thread create target\\`, or take that word off its row`',
229
- ' }',
230
- ' const reached = bound(word, wired, opened, opening, operation.timeout)',
231
- " if (typeof reached === 'string') return reached",
232
- ' held[word] = reached',
233
- ' }',
234
- ' return held',
235
- '}',
236
- '',
237
- 'export async function dispatch<I, R extends string = string>(',
238
- ' operation: Operation<I, R>,',
239
- ' rawInput: unknown,',
240
- ' asking: Actor,',
241
- ' opened: Reaches,',
242
- ' opening: Vault | undefined,',
243
- ' counting?: Counting,',
244
- ' telling?: (said: unknown) => void,',
245
- '): Promise<Result<unknown>> {',
246
- ' const id = operation.id',
247
- ' const who = person(asking)',
248
- ' const actor: Actor = who ?? ANONYMOUS',
249
- ' try {',
250
- " if (who === undefined) return fail('denied', REFUSAL['denied'], 'identity_invalid')",
251
- ' const parsed = operation.input.safeParse(rawInput)',
252
- ' if (!parsed.success) {',
253
- " return fail('invalid', REFUSAL['invalid'], String(parsed['error']))",
254
- ' }',
255
- ' const { resource } = operation',
256
- ' const ruled = permits(actor, id, resource(parsed[\'data\']))',
257
- ' const { allow, because: why } = ruled',
258
- " if (!allow) return fail('denied', REFUSAL['denied'], why)",
259
- '',
260
- ' const { entitled } = operation',
261
- ' if (entitled !== undefined && !actor.entitlements.includes(entitled)) {',
262
- " return fail('feature_denied', REFUSAL['feature_denied'], id + ' is offered on ' + entitled + ', which this caller does not hold')",
263
- ' }',
264
- '',
265
- " const limited = await allowance(id, actor, counting, operation.rate, 'rate_limited')",
266
- ' if (limited !== undefined) return limited',
267
- " const over = await allowance(id, actor, counting, operation.quota, 'quota_exceeded')",
268
- ' if (over !== undefined) return over',
269
- '',
270
- ' const handed = given(operation as Operation<unknown, string>, actor, opened, opening, telling ?? (() => undefined))',
271
- " if (typeof handed === 'string') return fail('error', REFUSAL['error'], handed)",
272
- '',
273
- ' const held: { readonly input: I } & Record<string, unknown> = { input: parsed.data }',
274
- ' const value = await operation.run(handed as Opened<R>, held)',
275
- ' return ok(value)',
276
- ' } catch (thrown) {',
277
- ' const early = stopped(thrown)',
278
- ' if (early !== undefined) {',
279
- ' return ok(early[\'value\'])',
280
- ' }',
281
- '',
282
- ' const message = thrown instanceof Error ? thrown.message : String(thrown)',
283
- '',
284
- " if (named(thrown, 'VersionConflictError')) {",
285
- " return fail('invalid', message, 'version_conflict', CONFLICT)",
286
- ' }',
287
- '',
288
- " const code: ResultCode = named(thrown, 'ValidationError') ? 'invalid' : 'error'",
289
- ' const because = platform(thrown) ?? message',
290
- ' return fail(code, message, because)',
291
- ' }',
292
- '}',
293
- '',
294
- ].join('\n')
@@ -1,31 +0,0 @@
1
- import { PlatformError, catalog, type ErrorDef } from '../core/errors/error.ts'
2
- import { AuthDenied, FeatureNotInPlan, InternalInvalidArgument, InternalUnexpected, QuotaExceeded, RateLimitExceeded } from '../core/errors/catalogue.ts'
3
-
4
- import type { Result, ResultCode } from './result.ts'
5
-
6
- const RESULT_ERROR_DEFS: Readonly<Record<ResultCode, ErrorDef>> = {
7
- invalid: InternalInvalidArgument.def,
8
- denied: AuthDenied.def,
9
- rate_limited: RateLimitExceeded.def,
10
- quota_exceeded: QuotaExceeded.def,
11
- feature_denied: FeatureNotInPlan.def,
12
- error: InternalUnexpected.def,
13
- }
14
-
15
- export function errorDefForResult(code: ResultCode): ErrorDef {
16
- return RESULT_ERROR_DEFS[code]
17
- }
18
-
19
- export function platformErrorForResult(result: Result<unknown>, run: string): PlatformError {
20
- if (result.ok) throw new TypeError('cannot render a successful Result as a problem')
21
-
22
- const def = result.errorCode === undefined ? errorDefForResult(result.code) : catalog.get(result.errorCode)
23
- const resolved = def ?? InternalUnexpected.def
24
- const detail = result.errorCode === undefined && resolved.code === InternalUnexpected.def.code ? undefined : result.error
25
-
26
- return new PlatformError(resolved, {
27
- ...(detail === undefined ? {} : { detail }),
28
- ...(result.because === undefined ? {} : { because: result.because }),
29
- traceId: run,
30
- })
31
- }