@pithy-sh/core 0.9.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access/access.d.ts +172 -0
- package/dist/access/access.d.ts.map +1 -0
- package/dist/access/access.js +147 -0
- package/dist/access/acting.d.ts +49 -0
- package/dist/access/acting.d.ts.map +1 -0
- package/dist/access/acting.js +21 -0
- package/dist/access/policyCheck.d.ts +33 -0
- package/dist/access/policyCheck.d.ts.map +1 -0
- package/dist/access/policyCheck.js +48 -0
- package/dist/access/usage.d.ts +83 -0
- package/dist/access/usage.d.ts.map +1 -0
- package/dist/access/usage.js +104 -0
- package/dist/access/visibility.d.ts +66 -0
- package/dist/access/visibility.d.ts.map +1 -0
- package/dist/access/visibility.js +86 -0
- package/dist/asyncapi/document.d.ts +46 -0
- package/dist/asyncapi/document.d.ts.map +1 -0
- package/dist/asyncapi/document.js +115 -0
- package/dist/audit/auditEvent.d.ts +5 -0
- package/dist/audit/auditEvent.d.ts.map +1 -1
- package/dist/audit/auditEvent.js +2 -0
- package/dist/capability/bindings.d.ts +47 -2
- package/dist/capability/bindings.d.ts.map +1 -1
- package/dist/capability/bindings.js +117 -7
- package/dist/capability/capability.d.ts +105 -28
- package/dist/capability/capability.d.ts.map +1 -1
- package/dist/capability/composition.d.ts.map +1 -1
- package/dist/capability/composition.js +5 -1
- package/dist/capability/manifest.d.ts +2 -1
- package/dist/capability/manifest.d.ts.map +1 -1
- package/dist/capability/manifest.js +1 -1
- package/dist/capability/settings.d.ts +96 -4
- package/dist/capability/settings.d.ts.map +1 -1
- package/dist/capability/settings.js +85 -4
- package/dist/cli/command.d.ts +364 -0
- package/dist/cli/command.d.ts.map +1 -0
- package/dist/cli/command.js +418 -0
- package/dist/cli/commandCatalog.generated.d.ts +2437 -0
- package/dist/cli/commandCatalog.generated.d.ts.map +1 -0
- package/dist/cli/commandCatalog.generated.js +2564 -0
- package/dist/cli/commandFacts.d.ts +164 -0
- package/dist/cli/commandFacts.d.ts.map +1 -0
- package/dist/cli/commandFacts.js +216 -0
- package/dist/controlPlane/capability.d.ts.map +1 -1
- package/dist/controlPlane/capability.js +12 -2
- package/dist/controlPlane/context.d.ts +5 -0
- package/dist/controlPlane/context.d.ts.map +1 -1
- package/dist/controlPlane/context.js +3 -1
- package/dist/controlPlane/data/connection.d.ts +47 -0
- package/dist/controlPlane/data/connection.d.ts.map +1 -1
- package/dist/controlPlane/data/connection.js +55 -1
- package/dist/controlPlane/error/errors.d.ts.map +1 -1
- package/dist/controlPlane/error/errors.js +4 -3
- package/dist/controlPlane/http/cors.d.ts +4 -4
- package/dist/controlPlane/http/cors.js +4 -4
- package/dist/controlPlane/http/guard.d.ts +11 -0
- package/dist/controlPlane/http/guard.d.ts.map +1 -1
- package/dist/controlPlane/http/guard.js +28 -2
- package/dist/controlPlane/http/handlers.d.ts +60 -0
- package/dist/controlPlane/http/handlers.d.ts.map +1 -1
- package/dist/controlPlane/http/handlers.js +31 -2
- package/dist/controlPlane/http/readiness.d.ts +33 -0
- package/dist/controlPlane/http/readiness.d.ts.map +1 -0
- package/dist/controlPlane/http/readiness.js +39 -0
- package/dist/controlPlane/http/responses.d.ts +147 -0
- package/dist/controlPlane/http/responses.d.ts.map +1 -1
- package/dist/controlPlane/http/responses.js +61 -4
- package/dist/controlPlane/http/routes.d.ts +2 -1
- package/dist/controlPlane/http/routes.d.ts.map +1 -1
- package/dist/controlPlane/http/routes.js +50 -9
- package/dist/controlPlane/http/verify.d.ts.map +1 -1
- package/dist/controlPlane/http/verify.js +2 -1
- package/dist/controlPlane/migrationState/migrationState.d.ts +102 -0
- package/dist/controlPlane/migrationState/migrationState.d.ts.map +1 -0
- package/dist/controlPlane/migrationState/migrationState.js +142 -0
- package/dist/controlPlane/migrations/0003_connection_principal.d.ts +21 -0
- package/dist/controlPlane/migrations/0003_connection_principal.d.ts.map +1 -0
- package/dist/controlPlane/migrations/0003_connection_principal.js +33 -0
- package/dist/controlPlane/scope/scope.d.ts +13 -2
- package/dist/controlPlane/scope/scope.d.ts.map +1 -1
- package/dist/controlPlane/scope/scope.js +14 -3
- package/dist/createBackend.d.ts +7 -0
- package/dist/createBackend.d.ts.map +1 -1
- package/dist/createBackend.js +41 -6
- package/dist/createEntrypoint.d.ts.map +1 -1
- package/dist/createEntrypoint.js +5 -3
- package/dist/entitlement/allowance.d.ts +25 -0
- package/dist/entitlement/allowance.d.ts.map +1 -0
- package/dist/entitlement/allowance.js +80 -0
- package/dist/entitlement/entitlement.d.ts +41 -0
- package/dist/entitlement/entitlement.d.ts.map +1 -1
- package/dist/entitlement/meter.d.ts +57 -0
- package/dist/entitlement/meter.d.ts.map +1 -0
- package/dist/entitlement/meter.js +13 -0
- package/dist/entitlement/require.js +1 -1
- package/dist/error/cause.d.ts +16 -116
- package/dist/error/cause.d.ts.map +1 -1
- package/dist/error/cause.js +19 -153
- package/dist/error/http.d.ts +184 -0
- package/dist/error/http.d.ts.map +1 -1
- package/dist/error/payload.d.ts +368 -0
- package/dist/error/payload.d.ts.map +1 -1
- package/dist/error/payload.js +126 -4
- package/dist/error/pithyError.d.ts +44 -0
- package/dist/error/pithyError.d.ts.map +1 -1
- package/dist/error/pithyError.js +56 -1
- package/dist/error/unresolved.d.ts +265 -0
- package/dist/error/unresolved.d.ts.map +1 -0
- package/dist/error/unresolved.js +599 -0
- package/dist/error/wire.d.ts +20 -0
- package/dist/error/wire.d.ts.map +1 -0
- package/dist/error/wire.js +19 -0
- package/dist/http/authContext.d.ts +7 -0
- package/dist/http/authContext.d.ts.map +1 -1
- package/dist/http/authContext.js +8 -1
- package/dist/http/oidcWebhook.d.ts +3 -3
- package/dist/http/oidcWebhook.js +3 -3
- package/dist/http/routeContract.js +1 -1
- package/dist/http/routeSpec.d.ts +66 -0
- package/dist/http/routeSpec.d.ts.map +1 -0
- package/dist/http/routeSpec.js +40 -0
- package/dist/http/sameOrigin.d.ts +1 -1
- package/dist/http/sameOrigin.js +1 -1
- package/dist/http/scopeGates.d.ts +20 -0
- package/dist/http/scopeGates.d.ts.map +1 -0
- package/dist/http/scopeGates.js +36 -0
- package/dist/http/signedWebhook.d.ts +3 -3
- package/dist/http/signedWebhook.js +3 -3
- package/dist/http/socket.d.ts +52 -0
- package/dist/http/socket.d.ts.map +1 -0
- package/dist/http/socket.js +2 -0
- package/dist/http/subprotocol.d.ts +29 -0
- package/dist/http/subprotocol.d.ts.map +1 -0
- package/dist/http/subprotocol.js +37 -0
- package/dist/http/validation.d.ts +40 -8
- package/dist/http/validation.d.ts.map +1 -1
- package/dist/http/validation.js +25 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/logger/record.d.ts +107 -0
- package/dist/logger/record.d.ts.map +1 -1
- package/dist/migrations/bookkeeping.d.ts +21 -0
- package/dist/migrations/bookkeeping.d.ts.map +1 -1
- package/dist/migrations/bookkeeping.js +32 -3
- package/dist/migrations/capabilitySets.d.ts +23 -0
- package/dist/migrations/capabilitySets.d.ts.map +1 -0
- package/dist/migrations/capabilitySets.js +74 -0
- package/dist/migrations/groups.d.ts +140 -0
- package/dist/migrations/groups.d.ts.map +1 -0
- package/dist/migrations/groups.js +191 -0
- package/dist/migrations/migrateStep.d.ts +13 -0
- package/dist/migrations/migrateStep.d.ts.map +1 -0
- package/dist/migrations/migrateStep.js +20 -0
- package/dist/migrations/owner.d.ts +7 -0
- package/dist/migrations/owner.d.ts.map +1 -1
- package/dist/migrations/owner.js +11 -7
- package/dist/migrations/registry.d.ts +26 -0
- package/dist/migrations/registry.d.ts.map +1 -1
- package/dist/migrations/registry.js +38 -7
- package/dist/migrations/retained.js +2 -2
- package/dist/migrations/runner.d.ts +76 -5
- package/dist/migrations/runner.d.ts.map +1 -1
- package/dist/migrations/runner.js +130 -19
- package/dist/migrations/state.d.ts +60 -0
- package/dist/migrations/state.d.ts.map +1 -0
- package/dist/migrations/state.js +46 -0
- package/dist/naming/domains.d.ts +17 -0
- package/dist/naming/domains.d.ts.map +1 -1
- package/dist/naming/domains.js +62 -4
- package/dist/naming/environment.d.ts.map +1 -1
- package/dist/naming/environment.js +2 -1
- package/dist/naming/feature.d.ts +27 -5
- package/dist/naming/feature.d.ts.map +1 -1
- package/dist/naming/feature.js +36 -6
- package/dist/naming/limits.d.ts +47 -3
- package/dist/naming/limits.d.ts.map +1 -1
- package/dist/naming/limits.js +47 -3
- package/dist/naming/packageName.d.ts +17 -0
- package/dist/naming/packageName.d.ts.map +1 -0
- package/dist/naming/packageName.js +22 -0
- package/dist/naming/provisionScope.d.ts +6 -0
- package/dist/naming/provisionScope.d.ts.map +1 -1
- package/dist/naming/provisionScope.js +10 -4
- package/dist/naming/resourceNames.d.ts +21 -2
- package/dist/naming/resourceNames.d.ts.map +1 -1
- package/dist/naming/resourceNames.js +21 -3
- package/dist/openapi/document.d.ts +106 -0
- package/dist/openapi/document.d.ts.map +1 -0
- package/dist/openapi/document.js +314 -0
- package/dist/openapi/routeGroups.d.ts +8 -0
- package/dist/openapi/routeGroups.d.ts.map +1 -0
- package/dist/openapi/routeGroups.js +23 -0
- package/dist/seed/writeD1.d.ts +7 -1
- package/dist/seed/writeD1.d.ts.map +1 -1
- package/dist/seed/writeD1.js +9 -3
- package/dist/seed/writeKv.d.ts +2 -0
- package/dist/seed/writeKv.d.ts.map +1 -1
- package/dist/seed/writeKv.js +6 -2
- package/dist/text/comments.js +66 -4
- package/dist/text/literals.d.ts +43 -0
- package/dist/text/literals.d.ts.map +1 -0
- package/dist/text/literals.js +293 -0
- package/dist/version.generated.d.ts +1 -1
- package/dist/version.generated.d.ts.map +1 -1
- package/dist/version.generated.js +1 -1
- package/dist/worker/serviceLoopback.d.ts +36 -0
- package/dist/worker/serviceLoopback.d.ts.map +1 -0
- package/dist/worker/serviceLoopback.js +74 -0
- package/dist/workflow/dispatchRoute.d.ts.map +1 -1
- package/dist/workflow/dispatchRoute.js +12 -6
- package/dist/workflow/faults.d.ts +12 -1
- package/dist/workflow/faults.d.ts.map +1 -1
- package/dist/workflow/faults.js +24 -18
- package/dist/workflow/hostEnv.d.ts +1 -0
- package/dist/workflow/hostEnv.d.ts.map +1 -1
- package/dist/workflow/hostEnv.js +4 -2
- package/dist/workflow/loopback.d.ts.map +1 -1
- package/dist/workflow/loopback.js +2 -1
- package/package.json +4 -4
- package/src/access/access.ts +298 -0
- package/src/access/acting.ts +59 -0
- package/src/access/policyCheck.ts +77 -0
- package/src/access/usage.ts +141 -0
- package/src/access/visibility.ts +109 -0
- package/src/asyncapi/document.ts +164 -0
- package/src/audit/auditEvent.ts +4 -0
- package/src/capability/bindings.ts +159 -13
- package/src/capability/capability.ts +106 -29
- package/src/capability/composition.ts +2 -1
- package/src/capability/settings.ts +165 -4
- package/src/cli/command.ts +865 -0
- package/src/cli/commandCatalog.generated.ts +2723 -0
- package/src/cli/commandFacts.ts +220 -0
- package/src/controlPlane/capability.ts +25 -1
- package/src/controlPlane/context.ts +4 -0
- package/src/controlPlane/data/connection.ts +90 -0
- package/src/controlPlane/error/errors.ts +10 -3
- package/src/controlPlane/http/cors.ts +4 -4
- package/src/controlPlane/http/guard.ts +35 -2
- package/src/controlPlane/http/handlers.ts +41 -0
- package/src/controlPlane/http/readiness.ts +50 -0
- package/src/controlPlane/http/responses.ts +140 -2
- package/src/controlPlane/http/routes.ts +82 -10
- package/src/controlPlane/http/verify.ts +2 -0
- package/src/controlPlane/migrationState/migrationState.ts +200 -0
- package/src/controlPlane/migrations/0003_connection_principal.ts +37 -0
- package/src/controlPlane/scope/scope.ts +14 -2
- package/src/createBackend.ts +59 -8
- package/src/createEntrypoint.ts +9 -3
- package/src/entitlement/allowance.ts +85 -0
- package/src/entitlement/entitlement.ts +38 -0
- package/src/entitlement/meter.ts +69 -0
- package/src/entitlement/require.ts +1 -1
- package/src/error/cause.ts +18 -181
- package/src/error/payload.ts +270 -4
- package/src/error/pithyError.ts +76 -0
- package/src/error/unresolved.ts +853 -0
- package/src/error/wire.ts +40 -0
- package/src/http/authContext.ts +13 -1
- package/src/http/oidcWebhook.ts +3 -3
- package/src/http/routeContract.ts +1 -1
- package/src/http/routeSpec.ts +81 -0
- package/src/http/sameOrigin.ts +1 -1
- package/src/http/scopeGates.ts +34 -0
- package/src/http/signedWebhook.ts +3 -3
- package/src/http/socket.ts +55 -0
- package/src/http/subprotocol.ts +47 -0
- package/src/http/validation.ts +50 -8
- package/src/index.ts +1 -0
- package/src/migrations/bookkeeping.ts +39 -2
- package/src/migrations/capabilitySets.ts +87 -0
- package/src/migrations/groups.ts +295 -0
- package/src/migrations/migrateStep.ts +19 -0
- package/src/migrations/owner.ts +10 -6
- package/src/migrations/registry.ts +46 -2
- package/src/migrations/retained.ts +2 -2
- package/src/migrations/runner.ts +214 -22
- package/src/migrations/state.ts +94 -0
- package/src/naming/domains.ts +75 -16
- package/src/naming/environment.ts +2 -1
- package/src/naming/feature.ts +46 -7
- package/src/naming/limits.ts +35 -3
- package/src/naming/packageName.ts +20 -0
- package/src/naming/provisionScope.ts +21 -2
- package/src/naming/resourceNames.ts +52 -5
- package/src/openapi/document.ts +412 -0
- package/src/openapi/routeGroups.ts +25 -0
- package/src/seed/writeD1.ts +13 -4
- package/src/seed/writeKv.ts +6 -2
- package/src/text/comments.ts +56 -4
- package/src/text/literals.ts +294 -0
- package/src/version.generated.ts +1 -1
- package/src/worker/serviceLoopback.ts +105 -0
- package/src/workflow/dispatchRoute.ts +13 -6
- package/src/workflow/faults.ts +56 -27
- package/src/workflow/hostEnv.ts +9 -1
- package/src/workflow/loopback.ts +2 -1
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 Pithy
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
//#region src/text/literals.ts
|
|
4
|
+
/**
|
|
5
|
+
* **Every string a source file writes, as it reads at run time near enough to scan (#711)** — each quoted or
|
|
6
|
+
* template literal's text, quotes off, escapes resolved to the character they stand for, and every `${…}` blanked
|
|
7
|
+
* to `<x>`.
|
|
8
|
+
*
|
|
9
|
+
* Gates that read what the code *says* — `packages/cli/src/ci/runnableCommands.test.ts` reads every `pithy …` a
|
|
10
|
+
* line names — used one regular expression for "a string or template literal", and it has a measured false
|
|
11
|
+
* reading: a template whose interpolation holds a template of its own, `` `${path}${detail ? ` — ${detail}` :
|
|
12
|
+
* ""}` ``, closed at the inner backtick, and everything after it was read as a literal that opened there. The
|
|
13
|
+
* scan then reported text the file does not contain, and missed the text it does. So this walks the source and
|
|
14
|
+
* keeps a stack: a `${` opens an expression, whose own literals are read as literals in their turn, and its
|
|
15
|
+
* matching `}` resumes the template it interrupted.
|
|
16
|
+
*
|
|
17
|
+
* Comments must be blanked first (`./comments`), as every caller here already does. A regex literal is stepped
|
|
18
|
+
* over by the same rule `./comments` uses — a `/` where a value may begin opens one — so a quote inside a pattern
|
|
19
|
+
* does not open a string.
|
|
20
|
+
*/
|
|
21
|
+
function literalTexts(source, options = {}) {
|
|
22
|
+
return literalSpans(source, options).map((span) => span.text);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* {@link literalTexts}, with where each one sits — so a gate can read what is around a literal: a `+` beside it, or
|
|
26
|
+
* the array it is an element of being joined.
|
|
27
|
+
*/
|
|
28
|
+
function literalSpans(source, options = {}) {
|
|
29
|
+
const found = [];
|
|
30
|
+
walk(source, 0, found, false, options.jsx === true);
|
|
31
|
+
return found;
|
|
32
|
+
}
|
|
33
|
+
/** After one of these, a `/` opens a regex literal; after anything else it divides. */
|
|
34
|
+
const VALUE_POSITION = /* @__PURE__ */ new Set([
|
|
35
|
+
"",
|
|
36
|
+
"(",
|
|
37
|
+
",",
|
|
38
|
+
"=",
|
|
39
|
+
":",
|
|
40
|
+
"[",
|
|
41
|
+
"!",
|
|
42
|
+
"&",
|
|
43
|
+
"|",
|
|
44
|
+
"?",
|
|
45
|
+
"{",
|
|
46
|
+
"}",
|
|
47
|
+
";",
|
|
48
|
+
"+",
|
|
49
|
+
"-",
|
|
50
|
+
"*",
|
|
51
|
+
"%",
|
|
52
|
+
"^",
|
|
53
|
+
"~",
|
|
54
|
+
"<",
|
|
55
|
+
">"
|
|
56
|
+
]);
|
|
57
|
+
/**
|
|
58
|
+
* Walk code from `start`, pushing every literal it meets. Inside an interpolation (`nested`), an unmatched `}`
|
|
59
|
+
* closes it: the walk returns the index just past that brace.
|
|
60
|
+
*/
|
|
61
|
+
function walk(source, start, found, nested, jsx) {
|
|
62
|
+
let depth = 0;
|
|
63
|
+
let previous = "";
|
|
64
|
+
let index = start;
|
|
65
|
+
while (index < source.length) {
|
|
66
|
+
const char = source[index];
|
|
67
|
+
if (char === "\"" || char === "'") {
|
|
68
|
+
index = quoted(source, index, char, found);
|
|
69
|
+
previous = char;
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
if (char === "`") {
|
|
73
|
+
index = template(source, index, found, jsx);
|
|
74
|
+
previous = char;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (jsx && char === "<" && opensElement(source, index, previous)) {
|
|
78
|
+
const mark = found.length;
|
|
79
|
+
const end = element(source, index, found);
|
|
80
|
+
if (end !== null) {
|
|
81
|
+
index = end;
|
|
82
|
+
previous = ")";
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
found.length = mark;
|
|
86
|
+
}
|
|
87
|
+
if (char === "/" && VALUE_POSITION.has(previous)) {
|
|
88
|
+
index = endOfRegex(source, index);
|
|
89
|
+
previous = "/";
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (char === "{") depth += 1;
|
|
93
|
+
if (char === "}") {
|
|
94
|
+
if (depth === 0 && nested) return index + 1;
|
|
95
|
+
depth -= 1;
|
|
96
|
+
}
|
|
97
|
+
if (!/\s/.test(char)) previous = char;
|
|
98
|
+
index += 1;
|
|
99
|
+
}
|
|
100
|
+
return index;
|
|
101
|
+
}
|
|
102
|
+
/** One quoted string: its text pushed, the index past its closing quote returned. A newline ends it unclosed. */
|
|
103
|
+
function quoted(source, start, quote, found) {
|
|
104
|
+
let text = "";
|
|
105
|
+
for (let index = start + 1; index < source.length; index += 1) {
|
|
106
|
+
const char = source[index];
|
|
107
|
+
if (char === "\\") {
|
|
108
|
+
text += source[index + 1] ?? "";
|
|
109
|
+
index += 1;
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
if (char === quote || char === "\n") {
|
|
113
|
+
const end = char === quote ? index + 1 : index;
|
|
114
|
+
found.push({
|
|
115
|
+
text,
|
|
116
|
+
start,
|
|
117
|
+
end
|
|
118
|
+
});
|
|
119
|
+
return end;
|
|
120
|
+
}
|
|
121
|
+
text += char;
|
|
122
|
+
}
|
|
123
|
+
found.push({
|
|
124
|
+
text,
|
|
125
|
+
start,
|
|
126
|
+
end: source.length
|
|
127
|
+
});
|
|
128
|
+
return source.length;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* One template: its text pushed with each `${…}` as `<x>`, and every literal inside an interpolation pushed in
|
|
132
|
+
* its own right. Returns the index past the closing backtick.
|
|
133
|
+
*/
|
|
134
|
+
function template(source, start, found, jsx) {
|
|
135
|
+
let text = "";
|
|
136
|
+
const holes = [];
|
|
137
|
+
const slot = found.length;
|
|
138
|
+
found.push({
|
|
139
|
+
text: "",
|
|
140
|
+
start,
|
|
141
|
+
end: start
|
|
142
|
+
});
|
|
143
|
+
const close = (end) => ({
|
|
144
|
+
text,
|
|
145
|
+
start,
|
|
146
|
+
end,
|
|
147
|
+
...holes.length > 0 ? { holes } : {}
|
|
148
|
+
});
|
|
149
|
+
let index = start + 1;
|
|
150
|
+
while (index < source.length) {
|
|
151
|
+
const char = source[index];
|
|
152
|
+
if (char === "\\") {
|
|
153
|
+
text += source[index + 1] ?? "";
|
|
154
|
+
index += 2;
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
if (char === "`") {
|
|
158
|
+
found[slot] = close(index + 1);
|
|
159
|
+
return index + 1;
|
|
160
|
+
}
|
|
161
|
+
if (char === "$" && source[index + 1] === "{") {
|
|
162
|
+
text += "<x>";
|
|
163
|
+
const from = index + 2;
|
|
164
|
+
index = walk(source, from, found, true, jsx);
|
|
165
|
+
holes.push([from, source[index - 1] === "}" ? index - 1 : index]);
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
text += char;
|
|
169
|
+
index += 1;
|
|
170
|
+
}
|
|
171
|
+
found[slot] = close(source.length);
|
|
172
|
+
return source.length;
|
|
173
|
+
}
|
|
174
|
+
/** After one of these words, as after a {@link VALUE_POSITION} character, a value begins. */
|
|
175
|
+
const VALUE_WORDS = /* @__PURE__ */ new Set([
|
|
176
|
+
"return",
|
|
177
|
+
"yield",
|
|
178
|
+
"await",
|
|
179
|
+
"default",
|
|
180
|
+
"case",
|
|
181
|
+
"else",
|
|
182
|
+
"do"
|
|
183
|
+
]);
|
|
184
|
+
/**
|
|
185
|
+
* Whether the `<` at `index` opens a JSX element: where a value may begin — after an operator, a bracket, or a
|
|
186
|
+
* word such as `return` — and followed by a tag name or, for a fragment, `>`. After an identifier or a closing
|
|
187
|
+
* bracket it compares, or opens a type's arguments.
|
|
188
|
+
*/
|
|
189
|
+
function opensElement(source, index, previous) {
|
|
190
|
+
if (!/[A-Za-z_$>]/.test(source[index + 1] ?? "")) return false;
|
|
191
|
+
if (VALUE_POSITION.has(previous)) return true;
|
|
192
|
+
const before = /([A-Za-z_$][\w$]*)\s*$/.exec(source.slice(Math.max(0, index - 32), index));
|
|
193
|
+
return before !== null && VALUE_WORDS.has(before[1]);
|
|
194
|
+
}
|
|
195
|
+
/** A JSX text run as React renders it: whitespace collapsed, and nothing pushed for a run that is only space. */
|
|
196
|
+
function pushText(text, start, end, found) {
|
|
197
|
+
const collapsed = text.replace(/\s+/g, " ").trim();
|
|
198
|
+
if (collapsed.length > 0) found.push({
|
|
199
|
+
text: collapsed,
|
|
200
|
+
start,
|
|
201
|
+
end
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* One JSX element from its `<`: each attribute string and each text run pushed, every `{…}` walked as code. Returns
|
|
206
|
+
* the index past the element, or `null` when what follows the `<` is not an element — a generic arrow `<T,>(…)`,
|
|
207
|
+
* or a `<` that never closes — for the caller to read as code.
|
|
208
|
+
*/
|
|
209
|
+
function element(source, start, found) {
|
|
210
|
+
let index = start + 1;
|
|
211
|
+
const name = /^[A-Za-z_$][\w$.:-]*/.exec(source.slice(index))?.[0] ?? "";
|
|
212
|
+
index += name.length;
|
|
213
|
+
for (;;) {
|
|
214
|
+
while (/\s/.test(source[index] ?? "")) index += 1;
|
|
215
|
+
const char = source[index];
|
|
216
|
+
if (char === void 0) return null;
|
|
217
|
+
if (char === "/" && source[index + 1] === ">") return index + 2;
|
|
218
|
+
if (char === ">") {
|
|
219
|
+
index += 1;
|
|
220
|
+
break;
|
|
221
|
+
}
|
|
222
|
+
if (char === "{") {
|
|
223
|
+
index = walk(source, index + 1, found, true, true);
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
const attribute = /^[A-Za-z_$][\w$:-]*/.exec(source.slice(index))?.[0];
|
|
227
|
+
if (attribute === void 0 || name === "") return null;
|
|
228
|
+
index += attribute.length;
|
|
229
|
+
while (/\s/.test(source[index] ?? "")) index += 1;
|
|
230
|
+
if (source[index] !== "=") continue;
|
|
231
|
+
index += 1;
|
|
232
|
+
while (/\s/.test(source[index] ?? "")) index += 1;
|
|
233
|
+
const value = source[index];
|
|
234
|
+
if (value === "{") {
|
|
235
|
+
index = walk(source, index + 1, found, true, true);
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
if (value !== "\"" && value !== "'") return null;
|
|
239
|
+
const close = source.indexOf(value, index + 1);
|
|
240
|
+
if (close === -1) return null;
|
|
241
|
+
found.push({
|
|
242
|
+
text: source.slice(index + 1, close),
|
|
243
|
+
start: index,
|
|
244
|
+
end: close + 1
|
|
245
|
+
});
|
|
246
|
+
index = close + 1;
|
|
247
|
+
}
|
|
248
|
+
let text = "";
|
|
249
|
+
let from = index;
|
|
250
|
+
while (index < source.length) {
|
|
251
|
+
const char = source[index];
|
|
252
|
+
if (char === "{") {
|
|
253
|
+
text += "<x>";
|
|
254
|
+
index = walk(source, index + 1, found, true, true);
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
if (char === "<") {
|
|
258
|
+
if (/^<\s*\//.exec(source.slice(index)) !== null) {
|
|
259
|
+
pushText(text, from, index, found);
|
|
260
|
+
const end = source.indexOf(">", index);
|
|
261
|
+
return end === -1 ? null : end + 1;
|
|
262
|
+
}
|
|
263
|
+
pushText(text, from, index, found);
|
|
264
|
+
const end = element(source, index, found);
|
|
265
|
+
if (end === null) return null;
|
|
266
|
+
index = end;
|
|
267
|
+
text = "";
|
|
268
|
+
from = index;
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
text += char;
|
|
272
|
+
index += 1;
|
|
273
|
+
}
|
|
274
|
+
return null;
|
|
275
|
+
}
|
|
276
|
+
/** Where a regex literal ends. A `/` inside a character class does not close it; a newline does. */
|
|
277
|
+
function endOfRegex(source, start) {
|
|
278
|
+
let inClass = false;
|
|
279
|
+
for (let index = start + 1; index < source.length; index += 1) {
|
|
280
|
+
const char = source[index];
|
|
281
|
+
if (char === "\\") {
|
|
282
|
+
index += 1;
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
if (char === "\n") return index;
|
|
286
|
+
if (char === "[") inClass = true;
|
|
287
|
+
else if (char === "]") inClass = false;
|
|
288
|
+
else if (char === "/" && !inClass) return index + 1;
|
|
289
|
+
}
|
|
290
|
+
return source.length;
|
|
291
|
+
}
|
|
292
|
+
//#endregion
|
|
293
|
+
export { literalSpans, literalTexts };
|
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
/** This package's npm name — the join key against a release feed. */
|
|
4
4
|
export declare const PACKAGE_NAME = "@pithy-sh/core";
|
|
5
5
|
/** This package's version, stamped from its own package.json at generation time. */
|
|
6
|
-
export declare const PACKAGE_VERSION = "0.
|
|
6
|
+
export declare const PACKAGE_VERSION = "0.11.0";
|
|
7
7
|
//# sourceMappingURL=version.generated.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.generated.d.ts","sourceRoot":"","sources":["../src/version.generated.ts"],"names":[],"mappings":"AAWA,qEAAqE;AACrE,eAAO,MAAM,YAAY,mBAAmB,CAAC;AAE7C,oFAAoF;AACpF,eAAO,MAAM,eAAe,
|
|
1
|
+
{"version":3,"file":"version.generated.d.ts","sourceRoot":"","sources":["../src/version.generated.ts"],"names":[],"mappings":"AAWA,qEAAqE;AACrE,eAAO,MAAM,YAAY,mBAAmB,CAAC;AAE7C,oFAAoF;AACpF,eAAO,MAAM,eAAe,WAAW,CAAC"}
|
|
@@ -4,6 +4,6 @@
|
|
|
4
4
|
/** This package's npm name — the join key against a release feed. */
|
|
5
5
|
const PACKAGE_NAME = "@pithy-sh/core";
|
|
6
6
|
/** This package's version, stamped from its own package.json at generation time. */
|
|
7
|
-
const PACKAGE_VERSION = "0.
|
|
7
|
+
const PACKAGE_VERSION = "0.11.0";
|
|
8
8
|
//#endregion
|
|
9
9
|
export { PACKAGE_NAME, PACKAGE_VERSION };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 Pithy
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
/**
|
|
4
|
+
* **A service binding under `pithy dev`: the call reaches the local target on its pinned port (#617).**
|
|
5
|
+
*
|
|
6
|
+
* Deployed, `env.APP_B.fetch(request)` is a service binding: Cloudflare runs the call inside the runtime, into
|
|
7
|
+
* the script the binding names. Locally there is no such script. `wrangler dev` would look for one in its own
|
|
8
|
+
* cross-process registry — the one `pithy dev` never relies on — and a Worker started on its own with
|
|
9
|
+
* `pithy dev --app app-a` would find nothing there at all. What does exist is the target itself, on the port its
|
|
10
|
+
* feature pinned for it, and `pithy dev` knows that address before anything starts.
|
|
11
|
+
*
|
|
12
|
+
* So `pithy dev` publishes one var, {@link SERVICE_ORIGINS_VAR}: a JSON map from each service binding this
|
|
13
|
+
* Worker declares to its target's local origin. Under `dev`, and only there, each of those bindings is replaced
|
|
14
|
+
* with a stand-in whose `fetch` sends the same request to that origin. The call site is byte-identical either
|
|
15
|
+
* way. A target that is not running refuses the connection, so the call fails at once as
|
|
16
|
+
* `core/upstream_failed`, naming the binding and the address, rather than hanging on a registry lookup.
|
|
17
|
+
*
|
|
18
|
+
* **Only `dev`, and only what was published.** The var is written by `pithy dev` and by nothing else, and the
|
|
19
|
+
* gate reads `ENVIRONMENT` off the request env as the Workflow loopback does (`workflow/dispatch.ts`): a
|
|
20
|
+
* deployment that lost its `ENVIRONMENT` var never opens it.
|
|
21
|
+
*/
|
|
22
|
+
/** The var `pithy dev` publishes: each service binding's local target, as JSON. */
|
|
23
|
+
export declare const SERVICE_ORIGINS_VAR = "PITHY_SERVICE_ORIGINS";
|
|
24
|
+
/** The transport. The runtime's `fetch`, or a test's. */
|
|
25
|
+
export type ServiceLoopbackFetch = (request: Request) => Promise<Response>;
|
|
26
|
+
/** Options for {@link withLocalServices}. */
|
|
27
|
+
export interface LocalServicesOptions {
|
|
28
|
+
/** The transport. Defaults to the runtime's `fetch`. */
|
|
29
|
+
fetch?: ServiceLoopbackFetch;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The env a request runs with: under `pithy dev`, each published service binding replaced with its local
|
|
33
|
+
* stand-in; anywhere else, the env unchanged — the same object, so nothing outside `dev` pays for this.
|
|
34
|
+
*/
|
|
35
|
+
export declare function withLocalServices(env: Record<string, unknown>, options?: LocalServicesOptions): Record<string, unknown>;
|
|
36
|
+
//# sourceMappingURL=serviceLoopback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serviceLoopback.d.ts","sourceRoot":"","sources":["../../src/worker/serviceLoopback.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,mFAAmF;AACnF,eAAO,MAAM,mBAAmB,0BAA0B,CAAC;AAa3D,yDAAyD;AACzD,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AAgC3E,6CAA6C;AAC7C,MAAM,WAAW,oBAAoB;IACnC,wDAAwD;IACxD,KAAK,CAAC,EAAE,oBAAoB,CAAC;CAC9B;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,OAAO,GAAE,oBAAyB,GACjC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAgBzB"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 Pithy
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
import { UpstreamError } from "../error/pithyError.js";
|
|
4
|
+
import { commandName } from "../cli/command.js";
|
|
5
|
+
import "./identity.js";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
//#region src/worker/serviceLoopback.ts
|
|
8
|
+
/**
|
|
9
|
+
* **A service binding under `pithy dev`: the call reaches the local target on its pinned port (#617).**
|
|
10
|
+
*
|
|
11
|
+
* Deployed, `env.APP_B.fetch(request)` is a service binding: Cloudflare runs the call inside the runtime, into
|
|
12
|
+
* the script the binding names. Locally there is no such script. `wrangler dev` would look for one in its own
|
|
13
|
+
* cross-process registry — the one `pithy dev` never relies on — and a Worker started on its own with
|
|
14
|
+
* `pithy dev --app app-a` would find nothing there at all. What does exist is the target itself, on the port its
|
|
15
|
+
* feature pinned for it, and `pithy dev` knows that address before anything starts.
|
|
16
|
+
*
|
|
17
|
+
* So `pithy dev` publishes one var, {@link SERVICE_ORIGINS_VAR}: a JSON map from each service binding this
|
|
18
|
+
* Worker declares to its target's local origin. Under `dev`, and only there, each of those bindings is replaced
|
|
19
|
+
* with a stand-in whose `fetch` sends the same request to that origin. The call site is byte-identical either
|
|
20
|
+
* way. A target that is not running refuses the connection, so the call fails at once as
|
|
21
|
+
* `core/upstream_failed`, naming the binding and the address, rather than hanging on a registry lookup.
|
|
22
|
+
*
|
|
23
|
+
* **Only `dev`, and only what was published.** The var is written by `pithy dev` and by nothing else, and the
|
|
24
|
+
* gate reads `ENVIRONMENT` off the request env as the Workflow loopback does (`workflow/dispatch.ts`): a
|
|
25
|
+
* deployment that lost its `ENVIRONMENT` var never opens it.
|
|
26
|
+
*/
|
|
27
|
+
/** The var `pithy dev` publishes: each service binding's local target, as JSON. */
|
|
28
|
+
const SERVICE_ORIGINS_VAR = "PITHY_SERVICE_ORIGINS";
|
|
29
|
+
/** The one environment the stand-in is made in. */
|
|
30
|
+
const LOCAL = "dev";
|
|
31
|
+
/** What the var carries: binding name to an `http(s)` origin. */
|
|
32
|
+
const ServiceOrigins = z.record(z.string().describe("A service binding's name in the Worker env."), z.url({ protocol: /^https?$/ }).describe("The local origin of the Worker it calls, as `pithy dev` pinned it.")).describe("Each service binding's local target, published by `pithy dev`.");
|
|
33
|
+
/** A stand-in for one service binding: every request sent to `origin`, its path, method, headers and body kept. */
|
|
34
|
+
function localService(binding, origin, send) {
|
|
35
|
+
const target = new URL(origin);
|
|
36
|
+
return { async fetch(input, init) {
|
|
37
|
+
const request = new Request(input, init);
|
|
38
|
+
const url = new URL(request.url);
|
|
39
|
+
url.protocol = target.protocol;
|
|
40
|
+
url.host = target.host;
|
|
41
|
+
try {
|
|
42
|
+
return await send(new Request(url, request));
|
|
43
|
+
} catch (cause) {
|
|
44
|
+
throw new UpstreamError({
|
|
45
|
+
message: `The Worker ${binding} calls is not answering.`,
|
|
46
|
+
action: `Check that it is running under ${commandName("dev")} at ${target.origin}.`,
|
|
47
|
+
detail: `${request.method} ${url.href} failed: ${String(cause)}`
|
|
48
|
+
}, { cause });
|
|
49
|
+
}
|
|
50
|
+
} };
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The env a request runs with: under `pithy dev`, each published service binding replaced with its local
|
|
54
|
+
* stand-in; anywhere else, the env unchanged — the same object, so nothing outside `dev` pays for this.
|
|
55
|
+
*/
|
|
56
|
+
function withLocalServices(env, options = {}) {
|
|
57
|
+
if (env["ENVIRONMENT"] !== LOCAL) return env;
|
|
58
|
+
const published = env[SERVICE_ORIGINS_VAR];
|
|
59
|
+
if (typeof published !== "string") return env;
|
|
60
|
+
let parsed;
|
|
61
|
+
try {
|
|
62
|
+
parsed = JSON.parse(published);
|
|
63
|
+
} catch {
|
|
64
|
+
return env;
|
|
65
|
+
}
|
|
66
|
+
const origins = ServiceOrigins.safeParse(parsed);
|
|
67
|
+
if (!origins.success || Object.keys(origins.data).length === 0) return env;
|
|
68
|
+
const send = options.fetch ?? ((request) => fetch(request));
|
|
69
|
+
const local = { ...env };
|
|
70
|
+
for (const [binding, origin] of Object.entries(origins.data)) local[binding] = localService(binding, origin, send);
|
|
71
|
+
return local;
|
|
72
|
+
}
|
|
73
|
+
//#endregion
|
|
74
|
+
export { SERVICE_ORIGINS_VAR, withLocalServices };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatchRoute.d.ts","sourceRoot":"","sources":["../../src/workflow/dispatchRoute.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dispatchRoute.d.ts","sourceRoot":"","sources":["../../src/workflow/dispatchRoute.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAW,IAAI,EAAQ,MAAM,MAAM,CAAC;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,EAAE,KAAK,UAAU,EAAsC,MAAM,gBAAgB,CAAC;AAIrF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAQjE,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AAEnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,8BAA8B,EAAE,oBAA+B,CAAC;AAK7E,iGAAiG;AACjG,MAAM,WAAW,uBAAuB;IACtC,wGAAwG;IACxG,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,QAAQ,EAAE,gBAAgB,CAAC;IAC3B;;;OAGG;IACH,GAAG,CAAC,EAAE,UAAU,CAAC;CAClB;AAqBD;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,IAAI,CAAC,YAAY,CAAC,EAAE,OAAO,EAAE,uBAAuB,GAAG,IAAI,CAwE7G"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
// SPDX-FileCopyrightText: 2026 Pithy
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
3
|
import { ForbiddenError, PithyError } from "../error/pithyError.js";
|
|
4
|
-
import {
|
|
5
|
-
import { WORKFLOW_DISPATCH_ROUTE, WorkflowDispatchParams, WorkflowDispatchRequest } from "./schemas.js";
|
|
6
|
-
import { workflowBindingFor } from "./dispatch.js";
|
|
4
|
+
import { commandName } from "../cli/command.js";
|
|
7
5
|
import { ambientEnv, compositionEnvironment } from "../env/ambient.js";
|
|
8
|
-
import {
|
|
6
|
+
import { describeRoute } from "../http/routeSpec.js";
|
|
7
|
+
import { validate } from "../http/validation.js";
|
|
8
|
+
import { WORKFLOW_DISPATCH_ROUTE, WorkflowDispatchParams, WorkflowDispatchRequest, WorkflowDispatchResponse } from "./schemas.js";
|
|
9
|
+
import { workflowBindingFor } from "./dispatch.js";
|
|
9
10
|
//#region src/workflow/dispatchRoute.ts
|
|
10
11
|
/**
|
|
11
12
|
* The host's dispatch route — the loopback door `pithy dev` starts an instance through.
|
|
@@ -73,7 +74,7 @@ function specForBinding(registry, binding) {
|
|
|
73
74
|
function refuseOutsideDev(capability, environment) {
|
|
74
75
|
return new ForbiddenError({
|
|
75
76
|
message: `Workflow dispatch over HTTP is served only in the ${DISPATCH_ENVIRONMENT} environment.`,
|
|
76
|
-
action: `Dispatch through the cross-script ${capability} Workflow binding, or run this host under
|
|
77
|
+
action: `Dispatch through the cross-script ${capability} Workflow binding, or run this host under ${commandName("dev")}.`,
|
|
77
78
|
detail: `The composition's ENVIRONMENT is ${environment ?? "unstamped"}.`
|
|
78
79
|
});
|
|
79
80
|
}
|
|
@@ -91,7 +92,12 @@ function registerWorkflowDispatchRoute(app, options) {
|
|
|
91
92
|
if (environment !== DISPATCH_ENVIRONMENT) throw refuseOutsideDev(capability, environment);
|
|
92
93
|
await next();
|
|
93
94
|
};
|
|
94
|
-
app.post(WORKFLOW_DISPATCH_ROUTE,
|
|
95
|
+
app.post(WORKFLOW_DISPATCH_ROUTE, describeRoute({
|
|
96
|
+
summary: "Start a Workflow instance on this host, in dev only.",
|
|
97
|
+
description: "Refused outside a `dev` composition. Deployed Workers dispatch through a Workflow binding instead.",
|
|
98
|
+
verification: WORKFLOW_DISPATCH_VERIFICATION,
|
|
99
|
+
responses: { 202: WorkflowDispatchResponse }
|
|
100
|
+
}), guard, validate("param", WorkflowDispatchParams), validate("json", WorkflowDispatchRequest), async (c) => {
|
|
95
101
|
const { binding } = c.req.valid("param");
|
|
96
102
|
const { id, params } = c.req.valid("json");
|
|
97
103
|
const entry = specForBinding(registry, binding);
|
|
@@ -102,6 +102,17 @@ export interface DurableStepLike extends WorkflowStepLike {
|
|
|
102
102
|
/** Pause the instance for `durationMs`, then resume. */
|
|
103
103
|
sleep(name: string, durationMs: number): Promise<void>;
|
|
104
104
|
}
|
|
105
|
+
/** What {@link classifiedSteps} hands back: a pausing runner, and a step that runs exactly once. */
|
|
106
|
+
export interface ClassifiedSteps extends DurableStepLike {
|
|
107
|
+
/**
|
|
108
|
+
* Run a named step with **no retries**, still classified (pithy-sh/pithy#602).
|
|
109
|
+
*
|
|
110
|
+
* For a body that mutates somebody else's system — a provider roll — where a platform re-running the
|
|
111
|
+
* step after an eviction would do it twice. The classification still decides what the instance's
|
|
112
|
+
* failure says; it can no longer decide on a retry, because there is none to give.
|
|
113
|
+
*/
|
|
114
|
+
once<T>(name: string, fn: () => Promise<T>): Promise<T>;
|
|
115
|
+
}
|
|
105
116
|
/**
|
|
106
117
|
* The platform's terminal-error class — `NonRetryableError` from `cloudflare:workflows`, taken as a
|
|
107
118
|
* parameter.
|
|
@@ -127,5 +138,5 @@ export interface TerminalErrorConstructor {
|
|
|
127
138
|
* `runSendBatch`, `runAtRestKeyRotation`) takes this instead with no change: the classification is
|
|
128
139
|
* declared once, at the entrypoint, and every step below it inherits the decision.
|
|
129
140
|
*/
|
|
130
|
-
export declare function classifiedSteps(step: WorkflowStepLike, policy: WorkflowRetryPolicy, terminalError: TerminalErrorConstructor):
|
|
141
|
+
export declare function classifiedSteps(step: WorkflowStepLike, policy: WorkflowRetryPolicy, terminalError: TerminalErrorConstructor): ClassifiedSteps;
|
|
131
142
|
//# sourceMappingURL=faults.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"faults.d.ts","sourceRoot":"","sources":["../../src/workflow/faults.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,2FAA2F;AAC3F,MAAM,MAAM,wBAAwB,GAAG,OAAO,GAAG,UAAU,CAAC;AAE5D;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IAClC,iHAAiH;IACjH,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC7C;AAED,2FAA2F;AAC3F,MAAM,WAAW,aAAa;IAC5B,sBAAsB;IACtB,WAAW,EAAE,wBAAwB,CAAC;IACtC,mFAAmF;IACnF,IAAI,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,MAAM,EAAE,MAAM,CAAC;CAChB;AAsDD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,mBAAmB,GAAG,aAAa,CA0BhG;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,gBAAgB;IAC/B,+FAA+F;IAC/F,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACtD;;;OAGG;IACH,KAAK,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzD;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,eAAgB,SAAQ,gBAAgB;IACvD,wDAAwD;IACxD,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxD;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,wBAAwB;IACvC,KAAK,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC;CAC9B;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,mBAAmB,EAC3B,aAAa,EAAE,wBAAwB,GACtC,eAAe,
|
|
1
|
+
{"version":3,"file":"faults.d.ts","sourceRoot":"","sources":["../../src/workflow/faults.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,2FAA2F;AAC3F,MAAM,MAAM,wBAAwB,GAAG,OAAO,GAAG,UAAU,CAAC;AAE5D;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IAClC,iHAAiH;IACjH,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC7C;AAED,2FAA2F;AAC3F,MAAM,WAAW,aAAa;IAC5B,sBAAsB;IACtB,WAAW,EAAE,wBAAwB,CAAC;IACtC,mFAAmF;IACnF,IAAI,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,MAAM,EAAE,MAAM,CAAC;CAChB;AAsDD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,mBAAmB,GAAG,aAAa,CA0BhG;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,gBAAgB;IAC/B,+FAA+F;IAC/F,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACtD;;;OAGG;IACH,KAAK,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzD;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,eAAgB,SAAQ,gBAAgB;IACvD,wDAAwD;IACxD,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxD;AAWD,oGAAoG;AACpG,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD;;;;;;OAMG;IACH,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CACzD;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,wBAAwB;IACvC,KAAK,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC;CAC9B;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,mBAAmB,EAC3B,aAAa,EAAE,wBAAwB,GACtC,eAAe,CA2DjB"}
|
package/dist/workflow/faults.js
CHANGED
|
@@ -91,23 +91,30 @@ function classifyWorkflowFault(error, policy) {
|
|
|
91
91
|
* declared once, at the entrypoint, and every step below it inherits the decision.
|
|
92
92
|
*/
|
|
93
93
|
function classifiedSteps(step, policy, terminalError) {
|
|
94
|
+
const classify = (fn) => async () => {
|
|
95
|
+
try {
|
|
96
|
+
return await fn();
|
|
97
|
+
} catch (error) {
|
|
98
|
+
const fault = classifyWorkflowFault(error, policy);
|
|
99
|
+
if (fault.disposition === "retry") throw error;
|
|
100
|
+
const terminal = new terminalError(encodeWorkflowStepMessage({
|
|
101
|
+
code: fault.code,
|
|
102
|
+
message: messageOf(error),
|
|
103
|
+
action: pithyActionOf(error)
|
|
104
|
+
}));
|
|
105
|
+
terminal.cause = error;
|
|
106
|
+
throw terminal;
|
|
107
|
+
}
|
|
108
|
+
};
|
|
94
109
|
const runner = {
|
|
95
110
|
do(name, fn) {
|
|
96
|
-
return step.do(name,
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
code: fault.code,
|
|
104
|
-
message: messageOf(error),
|
|
105
|
-
action: pithyActionOf(error)
|
|
106
|
-
}));
|
|
107
|
-
terminal.cause = error;
|
|
108
|
-
throw terminal;
|
|
109
|
-
}
|
|
110
|
-
});
|
|
111
|
+
return step.do(name, classify(fn));
|
|
112
|
+
},
|
|
113
|
+
once(name, fn) {
|
|
114
|
+
return step.do(name, { retries: {
|
|
115
|
+
limit: 0,
|
|
116
|
+
delay: 0
|
|
117
|
+
} }, classify(fn));
|
|
111
118
|
},
|
|
112
119
|
/**
|
|
113
120
|
* Forwarded, and deliberately unclassified. A pause raises no fault of the capability's — the
|
|
@@ -120,15 +127,14 @@ function classifiedSteps(step, policy, terminalError) {
|
|
|
120
127
|
* answer that cannot change.
|
|
121
128
|
*/
|
|
122
129
|
sleep(name, durationMs) {
|
|
123
|
-
|
|
124
|
-
if (pause === void 0) return runner.do(`${name}/cannot-pause`, async () => {
|
|
130
|
+
if (step.sleep === void 0) return runner.do(`${name}/cannot-pause`, async () => {
|
|
125
131
|
throw new InternalError({
|
|
126
132
|
message: "This Workflow step runner cannot pause.",
|
|
127
133
|
action: "Give the step runner a `sleep`; the platform's own `WorkflowStep` always has one.",
|
|
128
134
|
detail: `step '${name}' asked to pause ${durationMs}ms through a runner that declares no sleep`
|
|
129
135
|
});
|
|
130
136
|
});
|
|
131
|
-
return
|
|
137
|
+
return step.sleep(name, durationMs);
|
|
132
138
|
}
|
|
133
139
|
};
|
|
134
140
|
return runner;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hostEnv.d.ts","sourceRoot":"","sources":["../../src/workflow/hostEnv.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAG/C;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,yGAAyG;AACzG,eAAO,MAAM,mBAAmB;;;;;EAI7B,CAAC;AACJ,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEtE;;;;GAIG;AACH,eAAO,MAAM,eAAe
|
|
1
|
+
{"version":3,"file":"hostEnv.d.ts","sourceRoot":"","sources":["../../src/workflow/hostEnv.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAG/C;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,yGAAyG;AACzG,eAAO,MAAM,mBAAmB;;;;;EAI7B,CAAC;AACJ,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEtE;;;;GAIG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;iBAoBiF,CAAC;AAC9G,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAE9D;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB,CAAC,GAAG,SAAS,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS;IACvE,yFAAyF;IACzF,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,qGAAqG;IACrG,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,6FAA6F;IAC7F,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC;CAC9D;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,SAAS,CAAC,CAAC,SAAS,EAAE,WAAW,EAAE;IAClE,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,GAAG,CAAC;IACT,QAAQ,EAAE;QAAE,QAAQ,EAAE,KAAK,IAAI,MAAM,GAAG,CAAC,OAAO,CAAC,GAAG,MAAM,GAAG,eAAe;KAAE,CAAC;CAChF,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAW1B;AAED,sFAAsF;AACtF,MAAM,WAAW,cAAc;IAC7B,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,MAAM,EAAE,MAAM,CAAC;IACf,wBAAwB;IACxB,QAAQ,EAAE,eAAe,CAAC;CAC3B;AAED,qGAAqG;AACrG,MAAM,WAAW,aAAa,CAAC,KAAK;IAClC,2CAA2C;IAC3C,EAAE,EAAE,OAAO,CAAC;IACZ,yFAAyF;IACzF,KAAK,EAAE,KAAK,GAAG,SAAS,CAAC;IACzB,kEAAkE;IAClE,QAAQ,EAAE,cAAc,EAAE,CAAC;CAC5B;AAOD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,GAAG,SAAS,CAAC,CAAC,SAAS,EAClD,WAAW,EAAE,kBAAkB,CAAC,GAAG,CAAC,EACpC,GAAG,EAAE,OAAO,GACX,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAsB9B;AAED,6GAA6G;AAC7G,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,CAWzE;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,cAAc,EAAE,GAAG,MAAM,CAMrG;AAWD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,GAAG,SAAS,CAAC,CAAC,SAAS,EACpD,WAAW,EAAE,kBAAkB,CAAC,GAAG,CAAC,EACpC,GAAG,EAAE,OAAO,EACZ,GAAG,GAAE,MAA6B,GACjC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAkBf;AAED,kGAAkG;AAClG,MAAM,WAAW,YAAY;IAC3B,6CAA6C;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,mFAAmF;IACnF,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,wBAAwB;IACxB,QAAQ,EAAE,eAAe,CAAC;IAC1B,+FAA+F;IAC/F,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,kBAAkB,GAAG,YAAY,EAAE,CAS7E"}
|
package/dist/workflow/hostEnv.js
CHANGED
|
@@ -46,7 +46,8 @@ const HostEnvProviderKind = z.enum([
|
|
|
46
46
|
const HostEnvProvider = z.object({
|
|
47
47
|
kind: HostEnvProviderKind.describe("Which kind of thing fills this field."),
|
|
48
48
|
name: z.string().min(1).describe("The binding name, var name, secret name, or config key — spelled exactly as it is authored."),
|
|
49
|
-
command: z.string().min(1).optional().describe("The `pithy` command that fills it, where one does. Rendered as the report's action line.")
|
|
49
|
+
command: z.string().min(1).optional().describe("The `pithy` command that fills it, where one does. Rendered as the report's action line."),
|
|
50
|
+
decision: z.string().min(1).optional().describe("What fills it when only a person may run the command that does — one that touches production — said as their decision. Rendered in place of `command`.")
|
|
50
51
|
}).describe("What fills one field of a host worker's env, so a failure names the thing an operator changes.");
|
|
51
52
|
/**
|
|
52
53
|
* Declare a host's env. The mapped `provided` type makes an unaccounted field a compile error; the
|
|
@@ -109,7 +110,8 @@ function checkHostEnv(declaration, env) {
|
|
|
109
110
|
/** One sentence naming the thing an operator changes, plus the command that writes it where there is one. */
|
|
110
111
|
function hostEnvProviderSentence(provider) {
|
|
111
112
|
const where = provider.kind === "binding" ? `Binding ${provider.name} in the host's wrangler.jsonc.` : provider.kind === "var" ? `Var ${provider.name} in the host's wrangler.jsonc.` : provider.kind === "secret" ? `Secret ${provider.name}, read through @pithy-sh/secrets.` : `Config key ${provider.name}.`;
|
|
112
|
-
|
|
113
|
+
if (provider.command) return `${where} Run ${provider.command}.`;
|
|
114
|
+
return provider.decision ? `${where} ${provider.decision}` : where;
|
|
113
115
|
}
|
|
114
116
|
/**
|
|
115
117
|
* The block a host logs before it refuses. One headline, then one line per field: the field, why it
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loopback.d.ts","sourceRoot":"","sources":["../../src/workflow/loopback.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"loopback.d.ts","sourceRoot":"","sources":["../../src/workflow/loopback.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AAE9C;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,iGAAiG;AACjG,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AAElF,mFAAmF;AACnF,MAAM,WAAW,uBAAuB;IACtC;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,sFAAsF;IACtF,OAAO,EAAE,MAAM,CAAC;IAChB,mGAAmG;IACnG,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8EAA8E;IAC9E,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,qGAAqG;IACrG,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAuBD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,uBAAuB,GAAG,eAAe,CAoEzF"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// SPDX-FileCopyrightText: 2026 Pithy
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
3
|
import { UpstreamError, UpstreamTimeoutError } from "../error/pithyError.js";
|
|
4
|
+
import { commandName } from "../cli/command.js";
|
|
4
5
|
import { workflowDispatchPath } from "./schemas.js";
|
|
5
6
|
//#region src/workflow/loopback.ts
|
|
6
7
|
/** 10 seconds. A loopback dispatch either lands immediately or is not going to. */
|
|
@@ -32,7 +33,7 @@ function loopbackWorkflowBinding(options) {
|
|
|
32
33
|
const owner = options.capability ?? options.binding;
|
|
33
34
|
const send = options.fetch ?? ((target, init) => fetch(target, init));
|
|
34
35
|
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
35
|
-
const running = `Check that the ${owner} host is running under
|
|
36
|
+
const running = `Check that the ${owner} host is running under ${commandName("dev")} at ${origin}.`;
|
|
36
37
|
return { async create(instance) {
|
|
37
38
|
const body = {
|
|
38
39
|
id: instance?.id,
|