@prestack/thread 0.0.1
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 +192 -0
- package/dist/attach.d.ts +1 -0
- package/dist/attach.js +1 -0
- package/dist/core/actor.d.ts +12 -0
- package/dist/core/actor.js +8 -0
- package/dist/core/asking.d.ts +180 -0
- package/dist/core/asking.js +1109 -0
- package/dist/core/attach.d.ts +54 -0
- package/dist/core/attach.js +510 -0
- package/dist/core/chain.d.ts +16 -0
- package/dist/core/chain.js +114 -0
- package/dist/core/cli.d.ts +2 -0
- package/dist/core/cli.js +1682 -0
- package/dist/core/condition.d.ts +52 -0
- package/dist/core/condition.js +198 -0
- package/dist/core/descend.d.ts +81 -0
- package/dist/core/descend.js +879 -0
- package/dist/core/finding.d.ts +12 -0
- package/dist/core/finding.js +23 -0
- package/dist/core/generators/meta.d.ts +2 -0
- package/dist/core/generators/meta.js +823 -0
- package/dist/core/init.d.ts +15 -0
- package/dist/core/init.js +134 -0
- package/dist/core/invoked.d.ts +9 -0
- package/dist/core/invoked.js +41 -0
- package/dist/core/round.d.ts +1 -0
- package/dist/core/round.js +57 -0
- package/dist/core/rows.d.ts +26 -0
- package/dist/core/rows.js +354 -0
- package/dist/core/scope.d.ts +6 -0
- package/dist/core/scope.js +12 -0
- package/dist/core/thread.d.ts +26 -0
- package/dist/core/thread.js +5 -0
- package/dist/core/tree.d.ts +12 -0
- package/dist/core/tree.js +56 -0
- package/dist/core/types.d.ts +49 -0
- package/dist/core/types.js +311 -0
- package/dist/derivation/attach.d.ts +2 -0
- package/dist/derivation/attach.js +61 -0
- package/dist/derivation/generators/build.d.ts +16 -0
- package/dist/derivation/generators/build.js +217 -0
- package/dist/derivation/generators/check.d.ts +18 -0
- package/dist/derivation/generators/check.js +78 -0
- package/dist/derivation/generators/derivation.d.ts +3 -0
- package/dist/derivation/generators/derivation.js +273 -0
- package/dist/derivation/generators/determinism.d.ts +20 -0
- package/dist/derivation/generators/determinism.js +110 -0
- package/dist/derivation/generators/release.d.ts +3 -0
- package/dist/derivation/generators/release.js +183 -0
- package/dist/derivation/makers/release.d.ts +1 -0
- package/dist/derivation/makers/release.js +107 -0
- package/dist/derivation/release.d.ts +10 -0
- package/dist/derivation/release.js +12 -0
- package/dist/integrations/attach.d.ts +6 -0
- package/dist/integrations/attach.js +177 -0
- package/dist/integrations/generators/read.d.ts +1 -0
- package/dist/integrations/generators/read.js +92 -0
- package/dist/integrations/generators/sdk.d.ts +1 -0
- package/dist/integrations/generators/sdk.js +148 -0
- package/dist/integrations/generators/secret.d.ts +1 -0
- package/dist/integrations/generators/secret.js +233 -0
- package/dist/integrations/generators/target.d.ts +1 -0
- package/dist/integrations/generators/target.js +765 -0
- package/dist/integrations/generators/vault.d.ts +1 -0
- package/dist/integrations/generators/vault.js +164 -0
- package/dist/integrations/sdk.d.ts +6 -0
- package/dist/integrations/sdk.js +151 -0
- package/dist/integrations/secret.d.ts +16 -0
- package/dist/integrations/secret.js +30 -0
- package/dist/integrations/target.d.ts +49 -0
- package/dist/integrations/target.js +225 -0
- package/dist/integrations/vault.d.ts +12 -0
- package/dist/integrations/vault.js +104 -0
- package/dist/integrity/attach.d.ts +2 -0
- package/dist/integrity/attach.js +213 -0
- package/dist/integrity/check-threads.d.ts +10 -0
- package/dist/integrity/check-threads.js +153 -0
- package/dist/integrity/constraint.d.ts +16 -0
- package/dist/integrity/constraint.js +1105 -0
- package/dist/integrity/generators/compiler.d.ts +1 -0
- package/dist/integrity/generators/compiler.js +130 -0
- package/dist/integrity/generators/gate.d.ts +1 -0
- package/dist/integrity/generators/gate.js +172 -0
- package/dist/integrity/generators/issues.d.ts +1 -0
- package/dist/integrity/generators/issues.js +100 -0
- package/dist/integrity/generators/publish.d.ts +1 -0
- package/dist/integrity/generators/publish.js +186 -0
- package/dist/integrity/generators/rule.d.ts +2 -0
- package/dist/integrity/generators/rule.js +213 -0
- package/dist/integrity/generators/seal.d.ts +4 -0
- package/dist/integrity/generators/seal.js +101 -0
- package/dist/integrity/generators/trial.d.ts +39 -0
- package/dist/integrity/generators/trial.js +254 -0
- package/dist/integrity/lint.d.ts +50 -0
- package/dist/integrity/lint.js +161 -0
- package/dist/integrity/lsp/bin.d.ts +2 -0
- package/dist/integrity/lsp/bin.js +35 -0
- package/dist/integrity/lsp/diagnostics.d.ts +25 -0
- package/dist/integrity/lsp/diagnostics.js +57 -0
- package/dist/integrity/lsp/findings.d.ts +20 -0
- package/dist/integrity/lsp/findings.js +39 -0
- package/dist/integrity/lsp/lint.d.ts +7 -0
- package/dist/integrity/lsp/lint.js +95 -0
- package/dist/integrity/lsp/protocol.d.ts +20 -0
- package/dist/integrity/lsp/protocol.js +57 -0
- package/dist/integrity/lsp/server.d.ts +15 -0
- package/dist/integrity/lsp/server.js +171 -0
- package/dist/integrity/sealed.d.ts +1 -0
- package/dist/integrity/sealed.js +56 -0
- package/dist/integrity/slopnator.d.ts +90 -0
- package/dist/integrity/slopnator.js +267 -0
- package/dist/integrity/slopnators/sl_broken_lineage.d.ts +2 -0
- package/dist/integrity/slopnators/sl_broken_lineage.js +35 -0
- package/dist/integrity/slopnators/sl_declared_elsewhere.d.ts +2 -0
- package/dist/integrity/slopnators/sl_declared_elsewhere.js +33 -0
- package/dist/integrity/slopnators/sl_derived_drift.d.ts +8 -0
- package/dist/integrity/slopnators/sl_derived_drift.js +91 -0
- package/dist/integrity/slopnators/sl_hardcoded_style.d.ts +2 -0
- package/dist/integrity/slopnators/sl_hardcoded_style.js +46 -0
- package/dist/integrity/slopnators/sl_inert_island.d.ts +2 -0
- package/dist/integrity/slopnators/sl_inert_island.js +85 -0
- package/dist/integrity/slopnators/sl_inert_slopnator.d.ts +2 -0
- package/dist/integrity/slopnators/sl_inert_slopnator.js +76 -0
- package/dist/integrity/slopnators/sl_missing_row.d.ts +2 -0
- package/dist/integrity/slopnators/sl_missing_row.js +180 -0
- package/dist/integrity/slopnators/sl_no_barrel.d.ts +2 -0
- package/dist/integrity/slopnators/sl_no_barrel.js +41 -0
- package/dist/integrity/slopnators/sl_no_child_process.d.ts +2 -0
- package/dist/integrity/slopnators/sl_no_child_process.js +61 -0
- package/dist/integrity/slopnators/sl_no_comment.d.ts +2 -0
- package/dist/integrity/slopnators/sl_no_comment.js +41 -0
- package/dist/integrity/slopnators/sl_no_dispatch_bypass.d.ts +2 -0
- package/dist/integrity/slopnators/sl_no_dispatch_bypass.js +301 -0
- package/dist/integrity/slopnators/sl_no_import_cycle.d.ts +2 -0
- package/dist/integrity/slopnators/sl_no_import_cycle.js +42 -0
- package/dist/integrity/slopnators/sl_no_such_command.d.ts +2 -0
- package/dist/integrity/slopnators/sl_no_such_command.js +55 -0
- package/dist/integrity/slopnators/sl_only_takes_a_literal.d.ts +2 -0
- package/dist/integrity/slopnators/sl_only_takes_a_literal.js +59 -0
- package/dist/integrity/slopnators/sl_secret_literal.d.ts +2 -0
- package/dist/integrity/slopnators/sl_secret_literal.js +89 -0
- package/dist/integrity/slopnators/sl_stale_path.d.ts +2 -0
- package/dist/integrity/slopnators/sl_stale_path.js +92 -0
- package/dist/integrity/slopnators/sl_twice_meant.d.ts +2 -0
- package/dist/integrity/slopnators/sl_twice_meant.js +30 -0
- package/dist/integrity/slopnators/sl_twice_parented.d.ts +2 -0
- package/dist/integrity/slopnators/sl_twice_parented.js +34 -0
- package/dist/integrity/slopnators/sl_undeclared_crossing.d.ts +2 -0
- package/dist/integrity/slopnators/sl_undeclared_crossing.js +78 -0
- package/dist/integrity/slopnators/sl_undeclared_destination.d.ts +2 -0
- package/dist/integrity/slopnators/sl_undeclared_destination.js +56 -0
- package/dist/integrity/slopnators/sl_undeclared_element.d.ts +2 -0
- package/dist/integrity/slopnators/sl_undeclared_element.js +34 -0
- package/dist/integrity/slopnators/sl_undeclared_node.d.ts +2 -0
- package/dist/integrity/slopnators/sl_undeclared_node.js +59 -0
- package/dist/integrity/slopnators/sl_undeclared_operation.d.ts +2 -0
- package/dist/integrity/slopnators/sl_undeclared_operation.js +120 -0
- package/dist/integrity/slopnators/sl_undeclared_variant.d.ts +2 -0
- package/dist/integrity/slopnators/sl_undeclared_variant.js +117 -0
- package/dist/integrity/slopnators/sl_undescribed.d.ts +2 -0
- package/dist/integrity/slopnators/sl_undescribed.js +54 -0
- package/dist/integrity/slopnators/sl_ungoverned_island.d.ts +2 -0
- package/dist/integrity/slopnators/sl_ungoverned_island.js +58 -0
- package/dist/integrity/slopnators/sl_unkept_rows.d.ts +2 -0
- package/dist/integrity/slopnators/sl_unkept_rows.js +104 -0
- package/dist/integrity/slopnators/sl_unnamed_island.d.ts +2 -0
- package/dist/integrity/slopnators/sl_unnamed_island.js +37 -0
- package/dist/integrity/slopnators/sl_unpaired_member.d.ts +2 -0
- package/dist/integrity/slopnators/sl_unpaired_member.js +114 -0
- package/dist/integrity/slopnators/sl_unpaired_slopnator.d.ts +2 -0
- package/dist/integrity/slopnators/sl_unpaired_slopnator.js +60 -0
- package/dist/integrity/slopnators/sl_unprefixed_member.d.ts +2 -0
- package/dist/integrity/slopnators/sl_unprefixed_member.js +126 -0
- package/dist/integrity/slopnators/sl_unseamed_reach.d.ts +2 -0
- package/dist/integrity/slopnators/sl_unseamed_reach.js +73 -0
- package/dist/integrity/slopnators/sl_unthreaded.d.ts +56 -0
- package/dist/integrity/slopnators/sl_unthreaded.js +352 -0
- package/dist/integrity/slopnators/sl_untranslated_key.d.ts +2 -0
- package/dist/integrity/slopnators/sl_untranslated_key.js +157 -0
- package/dist/integrity/slopnators/sl_unversioned.d.ts +2 -0
- package/dist/integrity/slopnators/sl_unversioned.js +31 -0
- package/dist/integrity/sweep.d.ts +24 -0
- package/dist/integrity/sweep.js +264 -0
- package/dist/knowledge/attach.d.ts +2 -0
- package/dist/knowledge/attach.js +339 -0
- package/dist/knowledge/generators/docsgen.d.ts +1 -0
- package/dist/knowledge/generators/docsgen.js +145 -0
- package/dist/knowledge/generators/glossary.d.ts +1 -0
- package/dist/knowledge/generators/glossary.js +56 -0
- package/dist/knowledge/generators/skills.d.ts +1 -0
- package/dist/knowledge/generators/skills.js +222 -0
- package/dist/knowledge/glossary.d.ts +6 -0
- package/dist/knowledge/glossary.js +1 -0
- package/dist/operations/access.d.ts +27 -0
- package/dist/operations/access.js +61 -0
- package/dist/operations/attach.d.ts +6 -0
- package/dist/operations/attach.js +414 -0
- package/dist/operations/capabilities.d.ts +37 -0
- package/dist/operations/capabilities.js +35 -0
- package/dist/operations/cost.d.ts +14 -0
- package/dist/operations/cost.js +37 -0
- package/dist/operations/dispatch.d.ts +14 -0
- package/dist/operations/dispatch.js +327 -0
- package/dist/operations/error-results.d.ts +4 -0
- package/dist/operations/error-results.js +25 -0
- package/dist/operations/errors/catalog.d.ts +58 -0
- package/dist/operations/errors/catalog.js +91 -0
- package/dist/operations/errors/classes.d.ts +73 -0
- package/dist/operations/errors/classes.js +22 -0
- package/dist/operations/errors/errors.d.ts +52 -0
- package/dist/operations/errors/errors.js +257 -0
- package/dist/operations/generators/capability.d.ts +5 -0
- package/dist/operations/generators/capability.js +603 -0
- package/dist/operations/generators/compile.d.ts +2 -0
- package/dist/operations/generators/compile.js +541 -0
- package/dist/operations/generators/grant.d.ts +1 -0
- package/dist/operations/generators/grant.js +267 -0
- package/dist/operations/generators/operation.d.ts +1 -0
- package/dist/operations/generators/operation.js +811 -0
- package/dist/operations/generators/permits.d.ts +1 -0
- package/dist/operations/generators/permits.js +196 -0
- package/dist/operations/generators/seed.d.ts +20 -0
- package/dist/operations/generators/seed.js +285 -0
- package/dist/operations/generators/trial.d.ts +53 -0
- package/dist/operations/generators/trial.js +376 -0
- package/dist/operations/http.d.ts +30 -0
- package/dist/operations/http.js +121 -0
- package/dist/operations/makers/capability.d.ts +1 -0
- package/dist/operations/makers/capability.js +117 -0
- package/dist/operations/makers/trial.d.ts +1 -0
- package/dist/operations/makers/trial.js +413 -0
- package/dist/operations/memory.d.ts +104 -0
- package/dist/operations/memory.js +365 -0
- package/dist/operations/metering.d.ts +55 -0
- package/dist/operations/metering.js +247 -0
- package/dist/operations/nodes.d.ts +35 -0
- package/dist/operations/nodes.js +15 -0
- package/dist/operations/operations.d.ts +18 -0
- package/dist/operations/operations.js +5 -0
- package/dist/operations/queue-policy.d.ts +3 -0
- package/dist/operations/queue-policy.js +8 -0
- package/dist/operations/result.d.ts +19 -0
- package/dist/operations/result.js +10 -0
- package/dist/operations/seams.d.ts +239 -0
- package/dist/operations/seams.js +45 -0
- package/dist/operations/store.d.ts +14 -0
- package/dist/operations/store.js +1 -0
- package/package.json +16 -0
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
import { ANONYMOUS, ENVIRONMENT } from "../core/actor.js";
|
|
2
|
+
import { errorDefForResult } from "./error-results.js";
|
|
3
|
+
import { DbConflict } from "./errors/errors.js";
|
|
4
|
+
import { quoted, runtime } from "./generators/seed.js";
|
|
5
|
+
import { SUPPLY } from "./seams.js";
|
|
6
|
+
export const DISPATCH_AT = 'operations/_dispatch.ts';
|
|
7
|
+
const identity = (code) => {
|
|
8
|
+
const def = errorDefForResult(code);
|
|
9
|
+
return { code: def.code, class: def.class };
|
|
10
|
+
};
|
|
11
|
+
const CODES = ['denied', 'invalid', 'rate_limited', 'feature_denied', 'quota_exceeded', 'error'];
|
|
12
|
+
const REFUSAL = {
|
|
13
|
+
denied: { said: 'not allowed', outcome: 'denied' },
|
|
14
|
+
invalid: { said: 'invalid input', outcome: 'failed' },
|
|
15
|
+
rate_limited: { said: 'rate limited', outcome: 'rate_limited' },
|
|
16
|
+
feature_denied: { said: 'not in plan', outcome: 'feature_denied' },
|
|
17
|
+
quota_exceeded: { said: 'quota exceeded', outcome: 'quota_exceeded' },
|
|
18
|
+
error: { said: 'failed', outcome: 'failed' },
|
|
19
|
+
};
|
|
20
|
+
const printed = (value) => JSON.stringify(value, null, 2);
|
|
21
|
+
const DEFS = Object.fromEntries(CODES.map((code) => [code, identity(code)]));
|
|
22
|
+
export const dispatched = (reached) => [
|
|
23
|
+
`import type { Actor } from ${quoted(runtime(DISPATCH_AT, '../../core/actor.ts'))}`,
|
|
24
|
+
`import type { Operation } from ${quoted(runtime(DISPATCH_AT, '../operations.ts'))}`,
|
|
25
|
+
`import type { FailureIdentity, Result, ResultCode } from ${quoted(runtime(DISPATCH_AT, '../result.ts'))}`,
|
|
26
|
+
`import type { AuditOutcome, Handed, LogLevel, QuotaHold, Seams } from ${quoted(runtime(DISPATCH_AT, '../seams.ts'))}`,
|
|
27
|
+
'',
|
|
28
|
+
`const ANONYMOUS: Actor = ${printed(ANONYMOUS)}`,
|
|
29
|
+
'',
|
|
30
|
+
`const ENVIRONMENT: readonly string[] = ${printed(ENVIRONMENT.map(([fact]) => fact))}`,
|
|
31
|
+
'',
|
|
32
|
+
`const REFUSAL: Readonly<Record<ResultCode, { readonly said: string; readonly outcome: AuditOutcome }>> = ${printed(REFUSAL)}`,
|
|
33
|
+
'',
|
|
34
|
+
`const DEFS = ${printed(DEFS)} as Readonly<Record<ResultCode, FailureIdentity>>`,
|
|
35
|
+
'',
|
|
36
|
+
`const CONFLICT = ${printed({ code: DbConflict.def.code, class: DbConflict.def.class })} as FailureIdentity`,
|
|
37
|
+
'',
|
|
38
|
+
`const SUPPLY: Readonly<Record<string, string>> = ${printed(SUPPLY)}`,
|
|
39
|
+
'',
|
|
40
|
+
'type Reached = Readonly<Record<string, {',
|
|
41
|
+
' readonly reach: string',
|
|
42
|
+
' readonly address: string | null',
|
|
43
|
+
' readonly sends: readonly { readonly secret: string; readonly header: string; readonly prefix: string }[]',
|
|
44
|
+
' readonly calls: Readonly<Record<string, { readonly method: string; readonly path: string }>>',
|
|
45
|
+
'}>>',
|
|
46
|
+
'',
|
|
47
|
+
`const REACHED: Reached = ${printed(reached)}`,
|
|
48
|
+
'',
|
|
49
|
+
"const STOPPED = Symbol.for('thread.operation.stopped')",
|
|
50
|
+
'',
|
|
51
|
+
'const ok = <O>(value: O): Result<O> => ({ ok: true, value })',
|
|
52
|
+
'',
|
|
53
|
+
'const fail = (code: ResultCode, error: string, because?: string, identity?: FailureIdentity): Result<never> => ({',
|
|
54
|
+
' ok: false,',
|
|
55
|
+
' code,',
|
|
56
|
+
' error,',
|
|
57
|
+
' because,',
|
|
58
|
+
' ...(identity === undefined ? {} : { errorCode: identity.code, errorClass: identity.class }),',
|
|
59
|
+
'}) as Result<never>',
|
|
60
|
+
'',
|
|
61
|
+
"const strings = (value: unknown): value is string[] => Array.isArray(value) && value.every((one) => typeof one === 'string')",
|
|
62
|
+
'',
|
|
63
|
+
'const person = (value: unknown): Actor | undefined => {',
|
|
64
|
+
" if (typeof value !== 'object' || value === null) return undefined",
|
|
65
|
+
' const one = value as Record<string, unknown>',
|
|
66
|
+
" const id = one['id']",
|
|
67
|
+
" if (!(id === null || typeof id === 'string')) return undefined",
|
|
68
|
+
" const roles = one['roles']",
|
|
69
|
+
" const entitlements = one['entitlements']",
|
|
70
|
+
' if (!strings(roles) || !strings(entitlements)) return undefined',
|
|
71
|
+
' const carried: Record<string, string> = {}',
|
|
72
|
+
' for (const fact of ENVIRONMENT) {',
|
|
73
|
+
' const held = one[fact]',
|
|
74
|
+
' if (held === undefined) continue',
|
|
75
|
+
" if (typeof held !== 'string') return undefined",
|
|
76
|
+
' carried[fact] = held',
|
|
77
|
+
' }',
|
|
78
|
+
' return { ...carried, id, roles, entitlements }',
|
|
79
|
+
'}',
|
|
80
|
+
'',
|
|
81
|
+
'const named = (thrown: unknown, what: string): boolean => {',
|
|
82
|
+
" if (typeof thrown !== 'object' || thrown === null) return false",
|
|
83
|
+
' const one = thrown as { readonly name?: unknown; readonly constructor?: { readonly name?: unknown } }',
|
|
84
|
+
' return one.name === what || one.constructor?.name === what',
|
|
85
|
+
'}',
|
|
86
|
+
'',
|
|
87
|
+
'const stopped = (thrown: unknown): { readonly value: unknown } | undefined => {',
|
|
88
|
+
" if (typeof thrown !== 'object' || thrown === null) return undefined",
|
|
89
|
+
' const one = thrown as Record<PropertyKey, unknown>',
|
|
90
|
+
" return one[STOPPED] === true ? { value: one['value'] } : undefined",
|
|
91
|
+
'}',
|
|
92
|
+
'',
|
|
93
|
+
'const marked = (thrown: unknown): string | undefined => {',
|
|
94
|
+
" if (typeof thrown !== 'object' || thrown === null) return undefined",
|
|
95
|
+
' const said = (thrown as { readonly node?: unknown }).node',
|
|
96
|
+
" return typeof said === 'string' ? said : undefined",
|
|
97
|
+
'}',
|
|
98
|
+
'',
|
|
99
|
+
'const platform = (thrown: unknown): string | undefined => {',
|
|
100
|
+
" if (typeof thrown !== 'object' || thrown === null) return undefined",
|
|
101
|
+
' const said = (thrown as { readonly because?: unknown }).because',
|
|
102
|
+
" return typeof said === 'string' ? said : undefined",
|
|
103
|
+
'}',
|
|
104
|
+
'',
|
|
105
|
+
'const filled = (path: string, fills: Readonly<Record<string, string | number>> | undefined): string => {',
|
|
106
|
+
' let held = path',
|
|
107
|
+
' for (const [name, value] of Object.entries(fills ?? {})) held = held.split(`{${name}}`).join(encodeURIComponent(String(value)))',
|
|
108
|
+
' const left = /\\{([a-z][a-z0-9_]*)\\}/.exec(held)',
|
|
109
|
+
' if (left !== null) throw new Error(`the path ${path} leaves ${left[0]} to be filled and nothing filled it`)',
|
|
110
|
+
' return held',
|
|
111
|
+
'}',
|
|
112
|
+
'',
|
|
113
|
+
'const bound = (word: string, wired: Reached[string], seams: Seams): Record<string, unknown> | string => {',
|
|
114
|
+
' const names = Object.keys(wired.calls)',
|
|
115
|
+
' if (names.length === 0) {',
|
|
116
|
+
' return `\\`${word}\\` is required and takes no call, so there is nothing to hand a node. Declare one with \\`thread create target call\\``',
|
|
117
|
+
' }',
|
|
118
|
+
' if (seams.http === undefined) {',
|
|
119
|
+
' return `\\`${word}\\` is reached over ${wired.reach} and the seams this dispatch was handed hold no \\`http\\` — wire one, or take \\`${word}\\` off that operation\'s row`',
|
|
120
|
+
' }',
|
|
121
|
+
' const wanted = [...(wired.address === null ? [] : [wired.address]), ...wired.sends.map((one) => one.secret)]',
|
|
122
|
+
' if (wanted.length > 0 && seams.vault === undefined) {',
|
|
123
|
+
' return `\\`${word}\\` needs ${wanted.join(\', \')} and the seams this dispatch was handed hold no \\`vault\\` to open them. A target is reached with what opens it or not at all`',
|
|
124
|
+
' }',
|
|
125
|
+
' const out: Record<string, unknown> = {}',
|
|
126
|
+
' for (const name of names) {',
|
|
127
|
+
' const call = wired.calls[name]',
|
|
128
|
+
' if (call === undefined) continue',
|
|
129
|
+
' out[name] = async (given?: { fills?: Readonly<Record<string, string | number>>; json?: unknown; body?: Uint8Array; contentType?: string }) => {',
|
|
130
|
+
' const values = wanted.length === 0 ? {} : await seams.vault!.resolve(wanted)',
|
|
131
|
+
' const headers: Record<string, string> = {}',
|
|
132
|
+
' for (const one of wired.sends) headers[one.header] = `${one.prefix}${values[one.secret] ?? \'\'}`',
|
|
133
|
+
' const body = given?.json === undefined ? given?.body : new TextEncoder().encode(JSON.stringify(given.json))',
|
|
134
|
+
' return await seams.http!.call({',
|
|
135
|
+
' target: word,',
|
|
136
|
+
' address: wired.address === null ? \'\' : (values[wired.address] ?? \'\'),',
|
|
137
|
+
" method: call.method as 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',",
|
|
138
|
+
' path: filled(call.path, given?.fills),',
|
|
139
|
+
' headers,',
|
|
140
|
+
' ...(body === undefined ? {} : { body, contentType: given?.contentType ?? \'application/json\' }),',
|
|
141
|
+
' })',
|
|
142
|
+
' }',
|
|
143
|
+
' }',
|
|
144
|
+
' return out',
|
|
145
|
+
'}',
|
|
146
|
+
'',
|
|
147
|
+
'const given = (operation: Operation<unknown, string>, actor: Actor, seams: Seams): Record<string, unknown> | string => {',
|
|
148
|
+
' const held: Record<string, unknown> = { actor }',
|
|
149
|
+
' for (const word of operation.requires) {',
|
|
150
|
+
' const key = SUPPLY[word]',
|
|
151
|
+
' if (key === undefined) {',
|
|
152
|
+
' const wired = REACHED[word]',
|
|
153
|
+
' if (wired === undefined) {',
|
|
154
|
+
' return `\\`${operation.id}\\` requires \\`${word}\\`, and nothing here supplies it — what may be required is ${[...Object.keys(SUPPLY), ...Object.keys(REACHED)].join(\', \')}`',
|
|
155
|
+
' }',
|
|
156
|
+
' const reached = bound(word, wired, seams)',
|
|
157
|
+
" if (typeof reached === 'string') return reached",
|
|
158
|
+
' held[word] = reached',
|
|
159
|
+
' continue',
|
|
160
|
+
' }',
|
|
161
|
+
' const seam = (seams as unknown as Record<string, unknown>)[key]',
|
|
162
|
+
' if (seam === undefined) {',
|
|
163
|
+
' return `\\`${operation.id}\\` requires \\`${word}\\`, and the seams this dispatch was handed hold no \\`${key}\\` — wire one, or take \\`${word}\\` off that operation\'s row. An operation does not run short of what it declared`',
|
|
164
|
+
' }',
|
|
165
|
+
' held[key] = seam',
|
|
166
|
+
' }',
|
|
167
|
+
' return held',
|
|
168
|
+
'}',
|
|
169
|
+
'',
|
|
170
|
+
'export async function dispatch<I, R extends string = string>(',
|
|
171
|
+
' operation: Operation<I, R>,',
|
|
172
|
+
' rawInput: unknown,',
|
|
173
|
+
' asking: Actor,',
|
|
174
|
+
' handed: Seams,',
|
|
175
|
+
'): Promise<Result<unknown>> {',
|
|
176
|
+
' const seams = running(handed)',
|
|
177
|
+
' const id = operation.id',
|
|
178
|
+
' const who = person(asking)',
|
|
179
|
+
' const run = who?.run ?? seams.random.uuid()',
|
|
180
|
+
' const actor: Actor = { ...(who ?? ANONYMOUS), run }',
|
|
181
|
+
' const span = seams.telemetry?.start(id, run, { ...actor })',
|
|
182
|
+
'',
|
|
183
|
+
' const gates = { rate: seams.rateLimiter !== undefined, replay: seams.idempotency !== undefined, quota: seams.quotas !== undefined, telemetry: seams.telemetry !== undefined }',
|
|
184
|
+
'',
|
|
185
|
+
' let hold: QuotaHold | null = null',
|
|
186
|
+
' let granted: string | undefined',
|
|
187
|
+
'',
|
|
188
|
+
' const sank = (what: string) => (thrown: unknown): void => {',
|
|
189
|
+
" seams.log?.write('error', id, actor, {",
|
|
190
|
+
' [`${what}_failed`]: thrown instanceof Error ? thrown.message : String(thrown),',
|
|
191
|
+
' })',
|
|
192
|
+
' }',
|
|
193
|
+
'',
|
|
194
|
+
' const settled = async (held: Result<unknown>, because?: string): Promise<Result<unknown>> => {',
|
|
195
|
+
" const outcome: AuditOutcome = held.ok ? 'ok' : REFUSAL[held.code].outcome",
|
|
196
|
+
' const detail = because === undefined ? {} : { because }',
|
|
197
|
+
'',
|
|
198
|
+
' const reserved = hold === null ? null : operation.estimate',
|
|
199
|
+
' let consumed: number | null = null',
|
|
200
|
+
'',
|
|
201
|
+
' if (hold !== null) {',
|
|
202
|
+
' const settling = held.ok ? hold.commit(operation.estimate) : hold.release()',
|
|
203
|
+
' consumed = held.ok ? operation.estimate : 0',
|
|
204
|
+
' hold = null',
|
|
205
|
+
" await settling.catch(sank('quota'))",
|
|
206
|
+
' }',
|
|
207
|
+
'',
|
|
208
|
+
" seams.log.write(held.ok ? 'info' : 'warn', id, actor, {",
|
|
209
|
+
' outcome,',
|
|
210
|
+
' ...detail,',
|
|
211
|
+
" access: { roles: actor.roles, entitlements: actor.entitlements, granted: granted ?? 'not reached' },",
|
|
212
|
+
' quota: { meter: id, reserved, consumed },',
|
|
213
|
+
' gates,',
|
|
214
|
+
' })',
|
|
215
|
+
' if (held.ok) span?.ok()',
|
|
216
|
+
' else span?.error(outcome)',
|
|
217
|
+
'',
|
|
218
|
+
' await seams.audit',
|
|
219
|
+
" .append(actor, { action: id, outcome, subject: { type: 'operation', id }, ...detail })",
|
|
220
|
+
" .catch(sank('audit'))",
|
|
221
|
+
'',
|
|
222
|
+
' if (!held.ok) {',
|
|
223
|
+
' const identity: FailureIdentity =',
|
|
224
|
+
' held.errorCode === undefined || held.errorClass === undefined',
|
|
225
|
+
' ? DEFS[held.code]',
|
|
226
|
+
' : { code: held.errorCode, class: held.errorClass }',
|
|
227
|
+
'',
|
|
228
|
+
' await seams.errors',
|
|
229
|
+
' .record(actor, { code: identity.code, class: identity.class, action: id, ...detail })',
|
|
230
|
+
" .catch(sank('errors'))",
|
|
231
|
+
' }',
|
|
232
|
+
'',
|
|
233
|
+
' return held',
|
|
234
|
+
' }',
|
|
235
|
+
'',
|
|
236
|
+
' const refused = (code: ResultCode, because?: string): Promise<Result<unknown>> =>',
|
|
237
|
+
' settled(fail(code, REFUSAL[code].said, because), because)',
|
|
238
|
+
'',
|
|
239
|
+
' const recorded = (began: number, ok: boolean, at: string | undefined, because?: string): void => {',
|
|
240
|
+
' const took = seams.clock.now() - began',
|
|
241
|
+
' const sections = {',
|
|
242
|
+
' node: { at: at ?? null },',
|
|
243
|
+
' audit: { actor, when: began },',
|
|
244
|
+
' observability: { ms: took, ok, ...(because === undefined ? {} : { because }) },',
|
|
245
|
+
' }',
|
|
246
|
+
'',
|
|
247
|
+
" seams.log.write(ok ? 'info' : 'warn', id, actor, sections)",
|
|
248
|
+
' seams.telemetry?.record?.({',
|
|
249
|
+
' key: id,',
|
|
250
|
+
' traceId: run,',
|
|
251
|
+
' spanId: run,',
|
|
252
|
+
' durationMs: took,',
|
|
253
|
+
' ok,',
|
|
254
|
+
' attrs: sections,',
|
|
255
|
+
' actor,',
|
|
256
|
+
' ...(at === undefined ? {} : { nodeId: at }),',
|
|
257
|
+
' workflowId: id,',
|
|
258
|
+
' ...(because === undefined ? {} : { error: because }),',
|
|
259
|
+
' })',
|
|
260
|
+
' }',
|
|
261
|
+
'',
|
|
262
|
+
' try {',
|
|
263
|
+
" if (who === undefined) return await refused('denied', 'identity_invalid')",
|
|
264
|
+
'',
|
|
265
|
+
" if (seams.rateLimiter !== undefined && !(await seams.rateLimiter.check(actor, id))) return await refused('rate_limited')",
|
|
266
|
+
'',
|
|
267
|
+
' const replayed = seams.idempotency === undefined ? null : await seams.idempotency.check(actor.replay, id)',
|
|
268
|
+
" if (replayed !== null && replayed !== undefined) return await settled(ok(replayed), 'replayed')",
|
|
269
|
+
'',
|
|
270
|
+
' const parsed = operation.input.safeParse(rawInput)',
|
|
271
|
+
' if (!parsed.success) {',
|
|
272
|
+
" return await refused('invalid', parsed.error.issues.map((one) => one.message).join('; '))",
|
|
273
|
+
' }',
|
|
274
|
+
'',
|
|
275
|
+
' if (seams.quotas) {',
|
|
276
|
+
' const reserved = await seams.quotas.reserve(actor, id, operation.estimate)',
|
|
277
|
+
" if (!reserved.ok) return await refused('quota_exceeded', reserved.behavior ?? 'block')",
|
|
278
|
+
' hold = reserved',
|
|
279
|
+
' }',
|
|
280
|
+
'',
|
|
281
|
+
' if (seams.permits === undefined) {',
|
|
282
|
+
" return await refused('denied', 'no permits check is wired, so nothing can permit this operation')",
|
|
283
|
+
' }',
|
|
284
|
+
'',
|
|
285
|
+
' const ruled = await seams.permits.check(actor, id, operation.resource(parsed.data))',
|
|
286
|
+
" if (!ruled.allow) return await refused('denied', ruled.because)",
|
|
287
|
+
' granted = ruled.because',
|
|
288
|
+
'',
|
|
289
|
+
' const hands = given(operation as Operation<unknown, string>, actor, seams)',
|
|
290
|
+
" if (typeof hands === 'string') return await refused('error', hands)",
|
|
291
|
+
'',
|
|
292
|
+
' const held: { readonly input: I } & Record<string, unknown> = { input: parsed.data }',
|
|
293
|
+
' const began = seams.clock.now()',
|
|
294
|
+
' let value: unknown',
|
|
295
|
+
' try {',
|
|
296
|
+
' value = await operation.run(hands as Handed<R>, held)',
|
|
297
|
+
' } catch (thrown) {',
|
|
298
|
+
' recorded(began, stopped(thrown) !== undefined, marked(thrown), thrown instanceof Error ? thrown.message : String(thrown))',
|
|
299
|
+
' throw thrown',
|
|
300
|
+
' }',
|
|
301
|
+
' recorded(began, true, undefined)',
|
|
302
|
+
'',
|
|
303
|
+
" if (seams.idempotency !== undefined) await seams.idempotency.store(actor.replay, id, value).catch(sank('idempotency'))",
|
|
304
|
+
'',
|
|
305
|
+
' return await settled(ok(value))',
|
|
306
|
+
' } catch (thrown) {',
|
|
307
|
+
' const early = stopped(thrown)',
|
|
308
|
+
' if (early !== undefined) {',
|
|
309
|
+
" if (seams.idempotency !== undefined) await seams.idempotency.store(actor.replay, id, early.value).catch(sank('idempotency'))",
|
|
310
|
+
" return await settled(ok(early.value), 'stopped')",
|
|
311
|
+
' }',
|
|
312
|
+
'',
|
|
313
|
+
' const message = thrown instanceof Error ? thrown.message : String(thrown)',
|
|
314
|
+
'',
|
|
315
|
+
" if (named(thrown, 'VersionConflictError')) {",
|
|
316
|
+
" return await settled(fail('invalid', message, 'version_conflict', CONFLICT), 'version_conflict')",
|
|
317
|
+
' }',
|
|
318
|
+
'',
|
|
319
|
+
" const code: ResultCode = named(thrown, 'ValidationError') ? 'invalid' : 'error'",
|
|
320
|
+
' const because = platform(thrown) ?? message',
|
|
321
|
+
' return await settled(fail(code, message, because), because)',
|
|
322
|
+
' } finally {',
|
|
323
|
+
' span?.end()',
|
|
324
|
+
' }',
|
|
325
|
+
'}',
|
|
326
|
+
'',
|
|
327
|
+
].join('\n');
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { PlatformError, type ErrorDef } from './errors/catalog.ts';
|
|
2
|
+
import type { Result, ResultCode } from './result.ts';
|
|
3
|
+
export declare function errorDefForResult(code: ResultCode): ErrorDef;
|
|
4
|
+
export declare function platformErrorForResult(result: Result<unknown>, run: string): PlatformError;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { PlatformError, catalog } from "./errors/catalog.js";
|
|
2
|
+
import { AuthDenied, FeatureNotInPlan, InternalInvalidArgument, InternalUnexpected, QuotaExceeded, RateLimitExceeded } from "./errors/errors.js";
|
|
3
|
+
const RESULT_ERROR_DEFS = {
|
|
4
|
+
invalid: InternalInvalidArgument.def,
|
|
5
|
+
denied: AuthDenied.def,
|
|
6
|
+
rate_limited: RateLimitExceeded.def,
|
|
7
|
+
quota_exceeded: QuotaExceeded.def,
|
|
8
|
+
feature_denied: FeatureNotInPlan.def,
|
|
9
|
+
error: InternalUnexpected.def,
|
|
10
|
+
};
|
|
11
|
+
export function errorDefForResult(code) {
|
|
12
|
+
return RESULT_ERROR_DEFS[code];
|
|
13
|
+
}
|
|
14
|
+
export function platformErrorForResult(result, run) {
|
|
15
|
+
if (result.ok)
|
|
16
|
+
throw new TypeError('cannot render a successful Result as a problem');
|
|
17
|
+
const def = result.errorCode === undefined ? errorDefForResult(result.code) : catalog.get(result.errorCode);
|
|
18
|
+
const resolved = def ?? InternalUnexpected.def;
|
|
19
|
+
const detail = result.errorCode === undefined && resolved.code === InternalUnexpected.def.code ? undefined : result.error;
|
|
20
|
+
return new PlatformError(resolved, {
|
|
21
|
+
...(detail === undefined ? {} : { detail }),
|
|
22
|
+
...(result.because === undefined ? {} : { because: result.because }),
|
|
23
|
+
traceId: run,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { type ErrorClass } from './classes.ts';
|
|
2
|
+
export declare const NAMESPACES: readonly ["auth", "quota", "rate_limit", "feature", "db", "workflow", "queue", "ai", "search", "comms", "config", "net", "internal"];
|
|
3
|
+
export type Namespace = (typeof NAMESPACES)[number];
|
|
4
|
+
export type ErrorCode = `${Namespace}.${string}`;
|
|
5
|
+
export interface ErrorDef<C extends ErrorCode = ErrorCode> {
|
|
6
|
+
readonly code: C;
|
|
7
|
+
readonly class: ErrorClass;
|
|
8
|
+
readonly status: number;
|
|
9
|
+
readonly titleKey: string;
|
|
10
|
+
readonly retryable: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface DefineErrorInput<C extends ErrorCode = ErrorCode> {
|
|
13
|
+
readonly code: C;
|
|
14
|
+
readonly class: ErrorClass;
|
|
15
|
+
readonly status?: number;
|
|
16
|
+
readonly retryable?: boolean;
|
|
17
|
+
readonly titleKey?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface PlatformErrorInit {
|
|
20
|
+
readonly detail?: string;
|
|
21
|
+
readonly instance?: string;
|
|
22
|
+
readonly because?: string;
|
|
23
|
+
readonly traceId?: string;
|
|
24
|
+
readonly retryAfter?: number;
|
|
25
|
+
readonly cause?: unknown;
|
|
26
|
+
readonly extensions?: Readonly<Record<string, unknown>>;
|
|
27
|
+
}
|
|
28
|
+
export declare class PlatformError<C extends ErrorCode = ErrorCode> extends Error {
|
|
29
|
+
readonly def: ErrorDef<C>;
|
|
30
|
+
readonly detail?: string;
|
|
31
|
+
readonly instance?: string;
|
|
32
|
+
readonly because?: string;
|
|
33
|
+
readonly traceId?: string;
|
|
34
|
+
readonly retryAfter?: number;
|
|
35
|
+
readonly extensions: Readonly<Record<string, unknown>>;
|
|
36
|
+
constructor(def: ErrorDef<C>, init?: PlatformErrorInit);
|
|
37
|
+
get code(): C;
|
|
38
|
+
get status(): number;
|
|
39
|
+
get retryable(): boolean;
|
|
40
|
+
}
|
|
41
|
+
export declare function isPlatformError(value: unknown): value is PlatformError;
|
|
42
|
+
export type ErrorFactory<C extends ErrorCode = ErrorCode> = ((init?: PlatformErrorInit) => PlatformError<C>) & {
|
|
43
|
+
readonly def: ErrorDef<C>;
|
|
44
|
+
readonly is: (value: unknown) => value is PlatformError<C>;
|
|
45
|
+
};
|
|
46
|
+
export declare class DuplicateErrorCodeError extends Error {
|
|
47
|
+
constructor(code: string);
|
|
48
|
+
}
|
|
49
|
+
export declare class ErrorCatalog {
|
|
50
|
+
#private;
|
|
51
|
+
define<const C extends ErrorCode>(input: DefineErrorInput<C>): ErrorFactory<C>;
|
|
52
|
+
get(code: string): ErrorDef | undefined;
|
|
53
|
+
has(code: string): boolean;
|
|
54
|
+
all(): readonly ErrorDef[];
|
|
55
|
+
get size(): number;
|
|
56
|
+
}
|
|
57
|
+
export declare const catalog: ErrorCatalog;
|
|
58
|
+
export declare function defineError<const C extends ErrorCode>(input: DefineErrorInput<C>): ErrorFactory<C>;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { classDef } from "./classes.js";
|
|
2
|
+
export const NAMESPACES = [
|
|
3
|
+
'auth',
|
|
4
|
+
'quota',
|
|
5
|
+
'rate_limit',
|
|
6
|
+
'feature',
|
|
7
|
+
'db',
|
|
8
|
+
'workflow',
|
|
9
|
+
'queue',
|
|
10
|
+
'ai',
|
|
11
|
+
'search',
|
|
12
|
+
'comms',
|
|
13
|
+
'config',
|
|
14
|
+
'net',
|
|
15
|
+
'internal',
|
|
16
|
+
];
|
|
17
|
+
export class PlatformError extends Error {
|
|
18
|
+
def;
|
|
19
|
+
detail;
|
|
20
|
+
instance;
|
|
21
|
+
because;
|
|
22
|
+
traceId;
|
|
23
|
+
retryAfter;
|
|
24
|
+
extensions;
|
|
25
|
+
constructor(def, init = {}) {
|
|
26
|
+
super(def.code, init.cause === undefined ? undefined : { cause: init.cause });
|
|
27
|
+
this.name = 'PlatformError';
|
|
28
|
+
this.def = def;
|
|
29
|
+
this.detail = init.detail;
|
|
30
|
+
this.instance = init.instance;
|
|
31
|
+
this.because = init.because;
|
|
32
|
+
this.traceId = init.traceId;
|
|
33
|
+
this.retryAfter = init.retryAfter;
|
|
34
|
+
this.extensions = init.extensions ?? {};
|
|
35
|
+
}
|
|
36
|
+
get code() {
|
|
37
|
+
return this.def.code;
|
|
38
|
+
}
|
|
39
|
+
get status() {
|
|
40
|
+
return this.def.status;
|
|
41
|
+
}
|
|
42
|
+
get retryable() {
|
|
43
|
+
return this.def.retryable;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export function isPlatformError(value) {
|
|
47
|
+
return value instanceof PlatformError;
|
|
48
|
+
}
|
|
49
|
+
export class DuplicateErrorCodeError extends Error {
|
|
50
|
+
constructor(code) {
|
|
51
|
+
super(`duplicate error code: ${code}`);
|
|
52
|
+
this.name = 'DuplicateErrorCodeError';
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
export class ErrorCatalog {
|
|
56
|
+
#byCode = new Map();
|
|
57
|
+
define(input) {
|
|
58
|
+
if (this.#byCode.has(input.code)) {
|
|
59
|
+
throw new DuplicateErrorCodeError(input.code);
|
|
60
|
+
}
|
|
61
|
+
const cls = classDef(input.class);
|
|
62
|
+
const def = {
|
|
63
|
+
code: input.code,
|
|
64
|
+
class: input.class,
|
|
65
|
+
status: input.status ?? cls.status,
|
|
66
|
+
retryable: input.retryable ?? cls.retryable,
|
|
67
|
+
titleKey: input.titleKey ?? `errors.${input.code}.title`,
|
|
68
|
+
};
|
|
69
|
+
this.#byCode.set(def.code, def);
|
|
70
|
+
const factory = ((init) => new PlatformError(def, init));
|
|
71
|
+
factory.def = def;
|
|
72
|
+
factory.is = (value) => isPlatformError(value) && value.def.code === def.code;
|
|
73
|
+
return factory;
|
|
74
|
+
}
|
|
75
|
+
get(code) {
|
|
76
|
+
return this.#byCode.get(code);
|
|
77
|
+
}
|
|
78
|
+
has(code) {
|
|
79
|
+
return this.#byCode.has(code);
|
|
80
|
+
}
|
|
81
|
+
all() {
|
|
82
|
+
return [...this.#byCode.values()].sort((a, b) => a.code.localeCompare(b.code));
|
|
83
|
+
}
|
|
84
|
+
get size() {
|
|
85
|
+
return this.#byCode.size;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
export const catalog = new ErrorCatalog();
|
|
89
|
+
export function defineError(input) {
|
|
90
|
+
return catalog.define(input);
|
|
91
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
export interface ErrorClassDef {
|
|
2
|
+
readonly status: number;
|
|
3
|
+
readonly retryable: boolean;
|
|
4
|
+
}
|
|
5
|
+
export declare const ERROR_CLASSES: {
|
|
6
|
+
readonly OK: {
|
|
7
|
+
readonly status: 200;
|
|
8
|
+
readonly retryable: false;
|
|
9
|
+
};
|
|
10
|
+
readonly CANCELLED: {
|
|
11
|
+
readonly status: 499;
|
|
12
|
+
readonly retryable: false;
|
|
13
|
+
};
|
|
14
|
+
readonly UNKNOWN: {
|
|
15
|
+
readonly status: 500;
|
|
16
|
+
readonly retryable: false;
|
|
17
|
+
};
|
|
18
|
+
readonly INVALID_ARGUMENT: {
|
|
19
|
+
readonly status: 400;
|
|
20
|
+
readonly retryable: false;
|
|
21
|
+
};
|
|
22
|
+
readonly DEADLINE_EXCEEDED: {
|
|
23
|
+
readonly status: 504;
|
|
24
|
+
readonly retryable: true;
|
|
25
|
+
};
|
|
26
|
+
readonly NOT_FOUND: {
|
|
27
|
+
readonly status: 404;
|
|
28
|
+
readonly retryable: false;
|
|
29
|
+
};
|
|
30
|
+
readonly ALREADY_EXISTS: {
|
|
31
|
+
readonly status: 409;
|
|
32
|
+
readonly retryable: false;
|
|
33
|
+
};
|
|
34
|
+
readonly PERMISSION_DENIED: {
|
|
35
|
+
readonly status: 403;
|
|
36
|
+
readonly retryable: false;
|
|
37
|
+
};
|
|
38
|
+
readonly RESOURCE_EXHAUSTED: {
|
|
39
|
+
readonly status: 429;
|
|
40
|
+
readonly retryable: true;
|
|
41
|
+
};
|
|
42
|
+
readonly FAILED_PRECONDITION: {
|
|
43
|
+
readonly status: 400;
|
|
44
|
+
readonly retryable: false;
|
|
45
|
+
};
|
|
46
|
+
readonly ABORTED: {
|
|
47
|
+
readonly status: 409;
|
|
48
|
+
readonly retryable: true;
|
|
49
|
+
};
|
|
50
|
+
readonly OUT_OF_RANGE: {
|
|
51
|
+
readonly status: 400;
|
|
52
|
+
readonly retryable: false;
|
|
53
|
+
};
|
|
54
|
+
readonly UNIMPLEMENTED: {
|
|
55
|
+
readonly status: 501;
|
|
56
|
+
readonly retryable: false;
|
|
57
|
+
};
|
|
58
|
+
readonly INTERNAL: {
|
|
59
|
+
readonly status: 500;
|
|
60
|
+
readonly retryable: false;
|
|
61
|
+
};
|
|
62
|
+
readonly UNAVAILABLE: {
|
|
63
|
+
readonly status: 503;
|
|
64
|
+
readonly retryable: true;
|
|
65
|
+
};
|
|
66
|
+
readonly UNAUTHENTICATED: {
|
|
67
|
+
readonly status: 401;
|
|
68
|
+
readonly retryable: false;
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
export type ErrorClass = keyof typeof ERROR_CLASSES;
|
|
72
|
+
export declare const ERROR_CLASS_NAMES: readonly ErrorClass[];
|
|
73
|
+
export declare function classDef(cls: ErrorClass): ErrorClassDef;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export const ERROR_CLASSES = {
|
|
2
|
+
OK: { status: 200, retryable: false },
|
|
3
|
+
CANCELLED: { status: 499, retryable: false },
|
|
4
|
+
UNKNOWN: { status: 500, retryable: false },
|
|
5
|
+
INVALID_ARGUMENT: { status: 400, retryable: false },
|
|
6
|
+
DEADLINE_EXCEEDED: { status: 504, retryable: true },
|
|
7
|
+
NOT_FOUND: { status: 404, retryable: false },
|
|
8
|
+
ALREADY_EXISTS: { status: 409, retryable: false },
|
|
9
|
+
PERMISSION_DENIED: { status: 403, retryable: false },
|
|
10
|
+
RESOURCE_EXHAUSTED: { status: 429, retryable: true },
|
|
11
|
+
FAILED_PRECONDITION: { status: 400, retryable: false },
|
|
12
|
+
ABORTED: { status: 409, retryable: true },
|
|
13
|
+
OUT_OF_RANGE: { status: 400, retryable: false },
|
|
14
|
+
UNIMPLEMENTED: { status: 501, retryable: false },
|
|
15
|
+
INTERNAL: { status: 500, retryable: false },
|
|
16
|
+
UNAVAILABLE: { status: 503, retryable: true },
|
|
17
|
+
UNAUTHENTICATED: { status: 401, retryable: false },
|
|
18
|
+
};
|
|
19
|
+
export const ERROR_CLASS_NAMES = Object.keys(ERROR_CLASSES);
|
|
20
|
+
export function classDef(cls) {
|
|
21
|
+
return ERROR_CLASSES[cls];
|
|
22
|
+
}
|