@pikku/inspector 0.12.103 → 0.12.107
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/add/add-auth.d.ts +1 -9
- package/dist/add/add-auth.js +64 -17
- package/dist/add/add-cli.js +25 -11
- package/dist/add/add-functions.js +35 -39
- package/dist/add/add-keyed-wiring.js +22 -2
- package/dist/add/add-middleware.js +17 -16
- package/dist/add/add-permission.d.ts +0 -3
- package/dist/add/add-permission.js +213 -22
- package/dist/add/add-scope.d.ts +1 -7
- package/dist/add/add-scope.js +1 -21
- package/dist/add/add-virtual-users.d.ts +13 -0
- package/dist/add/{add-personas.js → add-virtual-users.js} +33 -33
- package/dist/add/add-workflow.js +14 -10
- package/dist/add/check-indirect-registrations.d.ts +9 -0
- package/dist/add/check-indirect-registrations.js +114 -0
- package/dist/error-codes.d.ts +5 -3
- package/dist/error-codes.js +5 -3
- package/dist/finalize.d.ts +10 -0
- package/dist/finalize.js +102 -0
- package/dist/index.d.ts +8 -6
- package/dist/index.js +6 -5
- package/dist/initial-state.d.ts +7 -0
- package/dist/initial-state.js +216 -0
- package/dist/inspector.d.ts +6 -4
- package/dist/inspector.js +28 -300
- package/dist/lite.d.ts +26 -0
- package/dist/lite.js +25 -0
- package/dist/source-file-cache.d.ts +11 -0
- package/dist/source-file-cache.js +34 -10
- package/dist/types-map.js +2 -1
- package/dist/types.d.ts +35 -3
- package/dist/utils/apply-declared-scopes.d.ts +8 -0
- package/dist/utils/apply-declared-scopes.js +21 -0
- package/dist/utils/canonical-type-string.d.ts +14 -0
- package/dist/utils/canonical-type-string.js +162 -0
- package/dist/utils/context-based-id.d.ts +7 -0
- package/dist/utils/context-based-id.js +9 -0
- package/dist/utils/custom-types-generator.d.ts +15 -1
- package/dist/utils/custom-types-generator.js +17 -5
- package/dist/utils/ensure-function-metadata.d.ts +0 -14
- package/dist/utils/ensure-function-metadata.js +4 -1
- package/dist/utils/extract-function-name.d.ts +1 -1
- package/dist/utils/extract-function-name.js +2 -4
- package/dist/utils/filter-inspector-state.js +31 -1
- package/dist/utils/get-property-value.d.ts +5 -0
- package/dist/utils/get-property-value.js +15 -1
- package/dist/utils/inspector-constants.d.ts +16 -0
- package/dist/utils/inspector-constants.js +16 -0
- package/dist/utils/load-addon-functions-meta.js +1 -0
- package/dist/utils/post-process.d.ts +35 -36
- package/dist/utils/post-process.js +218 -193
- package/dist/utils/resolve-callee-name.d.ts +27 -0
- package/dist/utils/resolve-callee-name.js +147 -0
- package/dist/utils/resolve-service-types.d.ts +8 -0
- package/dist/utils/resolve-service-types.js +21 -0
- package/dist/utils/schema-generator.js +29 -2
- package/dist/utils/serialize-inspector-state.d.ts +9 -3
- package/dist/utils/serialize-inspector-state.js +22 -7
- package/dist/utils/single-declaration.d.ts +3 -3
- package/dist/utils/single-declaration.js +3 -3
- package/dist/utils/validate-single-step-workflows.d.ts +3 -0
- package/dist/utils/validate-single-step-workflows.js +32 -0
- package/dist/utils/workflow/dsl/extract-dsl-workflow.js +3 -3
- package/dist/utils/workflow/dsl/patterns.d.ts +4 -11
- package/dist/utils/workflow/dsl/patterns.js +5 -11
- package/dist/utils/workflow/graph/convert-dsl-to-graph.js +6 -6
- package/dist/utils/workflow/graph/workflow-graph.types.d.ts +5 -5
- package/dist/visit.js +4 -2
- package/package.json +25 -9
- package/CHANGELOG.md +0 -4318
- package/OPTIMIZATION-PLAN.md +0 -201
- package/dist/add/add-personas.d.ts +0 -13
- package/run-tests.sh +0 -68
- package/src/utils/test-data/inspector-state.json +0 -1687
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A printed type with the members of every union in it sorted: by text, with
|
|
3
|
+
* `null` and `undefined` last. The checker prints a union in the order its
|
|
4
|
+
* members were created, which follows whichever file it happened to check
|
|
5
|
+
* first, and so differs between runtimes and between the TypeScript and native
|
|
6
|
+
* inspectors. Everything other than a union's order is left byte for byte.
|
|
7
|
+
*
|
|
8
|
+
* A level the scanner cannot split safely (a conditional type, a type
|
|
9
|
+
* parameter's constraint, a type predicate) keeps its order and only has the
|
|
10
|
+
* brackets inside it canonicalized. The native inspector's
|
|
11
|
+
* `typesmap.CanonicalTypeString` is the same algorithm, and both run the cases
|
|
12
|
+
* in `canonical-type-string.cases.json`.
|
|
13
|
+
*/
|
|
14
|
+
export const canonicalTypeString = (type) => {
|
|
15
|
+
const lead = type.length - type.replace(/^[ \t\n\r]+/, '').length;
|
|
16
|
+
const trail = type.length - type.replace(/[ \t\n\r]+$/, '').length;
|
|
17
|
+
if (lead === type.length)
|
|
18
|
+
return type;
|
|
19
|
+
const body = type.slice(lead, type.length - trail);
|
|
20
|
+
return (type.slice(0, lead) + canonicalBody(body) + type.slice(type.length - trail));
|
|
21
|
+
};
|
|
22
|
+
const OPENERS = '{[(<';
|
|
23
|
+
const CLOSE = { '{': '}', '[': ']', '(': ')', '<': '>' };
|
|
24
|
+
const CLOSERS = '}])>';
|
|
25
|
+
const QUOTES = `"'\``;
|
|
26
|
+
const UNSPLITTABLE = new Set(['extends', 'is', 'asserts', 'infer', 'as']);
|
|
27
|
+
const MAPPED_KEY = /^[A-Za-z_$][\w$]*[ \t\n\r]+in[ \t\n\r]/;
|
|
28
|
+
/** Where the comment starting at `i` ends (exclusive), or -1 if none starts there. */
|
|
29
|
+
const commentEnd = (s, i) => {
|
|
30
|
+
if (s[i] !== '/')
|
|
31
|
+
return -1;
|
|
32
|
+
if (s[i + 1] === '*') {
|
|
33
|
+
const end = s.indexOf('*/', i + 2);
|
|
34
|
+
return end === -1 ? s.length : end + 2;
|
|
35
|
+
}
|
|
36
|
+
if (s[i + 1] === '/') {
|
|
37
|
+
const end = s.indexOf('\n', i + 2);
|
|
38
|
+
return end === -1 ? s.length : end;
|
|
39
|
+
}
|
|
40
|
+
return -1;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* `s` with everything inside brackets, string literals and comments blanked,
|
|
44
|
+
* and the outermost bracket pairs.
|
|
45
|
+
*/
|
|
46
|
+
const topLevel = (s) => {
|
|
47
|
+
const mask = Array.from({ length: s.length }, () => ' ');
|
|
48
|
+
const groups = [];
|
|
49
|
+
let depth = 0;
|
|
50
|
+
let open = -1;
|
|
51
|
+
for (let i = 0; i < s.length; i++) {
|
|
52
|
+
const char = s[i];
|
|
53
|
+
if (QUOTES.includes(char)) {
|
|
54
|
+
let j = i + 1;
|
|
55
|
+
while (j < s.length && s[j] !== char)
|
|
56
|
+
j += s[j] === '\\' ? 2 : 1;
|
|
57
|
+
i = j;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
const end = commentEnd(s, i);
|
|
61
|
+
if (end !== -1) {
|
|
62
|
+
i = end - 1;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (OPENERS.includes(char)) {
|
|
66
|
+
if (depth === 0)
|
|
67
|
+
open = i;
|
|
68
|
+
depth++;
|
|
69
|
+
}
|
|
70
|
+
else if (CLOSERS.includes(char) && !(char === '>' && s[i - 1] === '=')) {
|
|
71
|
+
if (depth > 0)
|
|
72
|
+
depth--;
|
|
73
|
+
if (depth === 0 && open !== -1 && CLOSE[s[open]] === char) {
|
|
74
|
+
groups.push([open, i]);
|
|
75
|
+
open = -1;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
else if (depth === 0) {
|
|
79
|
+
mask[i] = char;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return { mask: mask.join(''), groups };
|
|
83
|
+
};
|
|
84
|
+
const isNullish = (member) => member === 'null' || member === 'undefined';
|
|
85
|
+
const sortMembers = (members) => members.sort((a, b) => isNullish(a) !== isNullish(b)
|
|
86
|
+
? isNullish(a)
|
|
87
|
+
? 1
|
|
88
|
+
: -1
|
|
89
|
+
: a < b
|
|
90
|
+
? -1
|
|
91
|
+
: a > b
|
|
92
|
+
? 1
|
|
93
|
+
: 0);
|
|
94
|
+
const unsplittable = (mask) => {
|
|
95
|
+
if (/[?:]/.test(mask))
|
|
96
|
+
return true;
|
|
97
|
+
for (let i = 0; i < mask.length; i++) {
|
|
98
|
+
if (mask[i] === '=' && mask[i + 1] !== '>')
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
return mask.split(/[^A-Za-z0-9_$]+/).some((word) => UNSPLITTABLE.has(word));
|
|
102
|
+
};
|
|
103
|
+
const canonicalBody = (body) => {
|
|
104
|
+
const { mask } = topLevel(body);
|
|
105
|
+
const arrow = mask.indexOf('=>');
|
|
106
|
+
if (arrow !== -1 && !mask.slice(0, arrow).includes('|')) {
|
|
107
|
+
return `${rewriteGroups(body.slice(0, arrow))}=>${canonicalTypeString(body.slice(arrow + 2))}`;
|
|
108
|
+
}
|
|
109
|
+
const mapped = MAPPED_KEY.exec(mask);
|
|
110
|
+
if (mapped) {
|
|
111
|
+
const key = mapped[0].length;
|
|
112
|
+
return body.slice(0, key) + canonicalTypeString(body.slice(key));
|
|
113
|
+
}
|
|
114
|
+
if (!mask.includes('|') || unsplittable(mask))
|
|
115
|
+
return rewriteGroups(body);
|
|
116
|
+
const members = [];
|
|
117
|
+
let start = 0;
|
|
118
|
+
for (let i = 0; i <= mask.length; i++) {
|
|
119
|
+
if (i === mask.length || mask[i] === '|') {
|
|
120
|
+
const member = canonicalTypeString(body.slice(start, i)).trim();
|
|
121
|
+
if (member)
|
|
122
|
+
members.push(member);
|
|
123
|
+
start = i + 1;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return members.length > 1
|
|
127
|
+
? sortMembers(members).join(' | ')
|
|
128
|
+
: rewriteGroups(body);
|
|
129
|
+
};
|
|
130
|
+
/** `s` with the contents of each outermost bracket pair canonicalized. */
|
|
131
|
+
const rewriteGroups = (s) => {
|
|
132
|
+
let out = '';
|
|
133
|
+
let last = 0;
|
|
134
|
+
for (const [open, close] of topLevel(s).groups) {
|
|
135
|
+
out +=
|
|
136
|
+
s.slice(last, open + 1) + rewriteList(s.slice(open + 1, close), s[open]);
|
|
137
|
+
last = close;
|
|
138
|
+
}
|
|
139
|
+
return out + s.slice(last);
|
|
140
|
+
};
|
|
141
|
+
/** A bracket's contents: members of an object, parameters, or type arguments. */
|
|
142
|
+
const rewriteList = (inner, opener) => {
|
|
143
|
+
const separators = opener === '{' ? ';,' : ',';
|
|
144
|
+
const { mask } = topLevel(inner);
|
|
145
|
+
let out = '';
|
|
146
|
+
let start = 0;
|
|
147
|
+
for (let i = 0; i <= mask.length; i++) {
|
|
148
|
+
if (i === mask.length || separators.includes(mask[i])) {
|
|
149
|
+
out += rewriteItem(inner.slice(start, i), opener) + (inner[i] ?? '');
|
|
150
|
+
start = i + 1;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return out;
|
|
154
|
+
};
|
|
155
|
+
const rewriteItem = (item, opener) => {
|
|
156
|
+
if (opener === '<')
|
|
157
|
+
return canonicalTypeString(item);
|
|
158
|
+
const colon = topLevel(item).mask.indexOf(':');
|
|
159
|
+
if (colon === -1)
|
|
160
|
+
return canonicalTypeString(item);
|
|
161
|
+
return `${rewriteGroups(item.slice(0, colon))}:${canonicalTypeString(item.slice(colon + 1))}`;
|
|
162
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The id of a function wired inline rather than declared on its own: the
|
|
3
|
+
* wiring type followed by whatever identifies the wiring (`queue:emails`,
|
|
4
|
+
* `http:get:/todos`). Kept apart from `extract-function-name.ts`, which needs
|
|
5
|
+
* the TypeScript compiler, so pure state helpers can use it without loading it.
|
|
6
|
+
*/
|
|
7
|
+
export declare function makeContextBasedId(wiringType: string, ...segments: string[]): string;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The id of a function wired inline rather than declared on its own: the
|
|
3
|
+
* wiring type followed by whatever identifies the wiring (`queue:emails`,
|
|
4
|
+
* `http:get:/todos`). Kept apart from `extract-function-name.ts`, which needs
|
|
5
|
+
* the TypeScript compiler, so pure state helpers can use it without loading it.
|
|
6
|
+
*/
|
|
7
|
+
export function makeContextBasedId(wiringType, ...segments) {
|
|
8
|
+
return [wiringType, ...segments].join(':');
|
|
9
|
+
}
|
|
@@ -6,4 +6,18 @@ import type { TypesMap } from '../types-map.js';
|
|
|
6
6
|
* ts-json-schema-generator can discover inline/custom types from typesMap.
|
|
7
7
|
*/
|
|
8
8
|
export declare function sanitizeTypeName(name: string): string;
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* The names `generateCustomTypes` declares, in the order it declares them. A
|
|
11
|
+
* file that imports from the shared custom-types file uses this to know which
|
|
12
|
+
* names exist there.
|
|
13
|
+
*/
|
|
14
|
+
export declare function customTypeNames(typesMap: TypesMap): string[];
|
|
15
|
+
export interface GenerateCustomTypesOptions {
|
|
16
|
+
/**
|
|
17
|
+
* Turns the absolute path of a type's source file into the specifier the
|
|
18
|
+
* import line uses. Left out, the absolute path is used as-is — fine for the
|
|
19
|
+
* in-memory source the schema generator compiles, wrong for a file on disk.
|
|
20
|
+
*/
|
|
21
|
+
resolveImportPath?: (absolutePath: string) => string;
|
|
22
|
+
}
|
|
23
|
+
export declare function generateCustomTypes(typesMap: TypesMap, requiredTypes: Set<string>, { resolveImportPath }?: GenerateCustomTypesOptions): string;
|
|
@@ -55,14 +55,26 @@ function stripClassificationWrappers(type) {
|
|
|
55
55
|
}
|
|
56
56
|
return output;
|
|
57
57
|
}
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
function emittableCustomTypes(typesMap) {
|
|
59
|
+
return Array.from(typesMap.customTypes.entries())
|
|
60
60
|
.sort(([a], [b]) => a.localeCompare(b))
|
|
61
61
|
.filter(([_name, { type }]) => {
|
|
62
62
|
const hasUndefinedGeneric = /\b(Name|In|Out|Key)\b/.test(type) && /\[.*\]/.test(type);
|
|
63
63
|
return !hasUndefinedGeneric;
|
|
64
|
-
})
|
|
65
|
-
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* The names `generateCustomTypes` declares, in the order it declares them. A
|
|
68
|
+
* file that imports from the shared custom-types file uses this to know which
|
|
69
|
+
* names exist there.
|
|
70
|
+
*/
|
|
71
|
+
export function customTypeNames(typesMap) {
|
|
72
|
+
return emittableCustomTypes(typesMap)
|
|
73
|
+
.filter(([originalName, { type }]) => sanitizeTypeName(originalName) !== stripClassificationWrappers(type))
|
|
74
|
+
.map(([originalName]) => sanitizeTypeName(originalName));
|
|
75
|
+
}
|
|
76
|
+
export function generateCustomTypes(typesMap, requiredTypes, { resolveImportPath = (path) => path } = {}) {
|
|
77
|
+
const typeDeclarations = emittableCustomTypes(typesMap).map(([originalName, { type, references }]) => {
|
|
66
78
|
const name = sanitizeTypeName(originalName);
|
|
67
79
|
references.forEach((refName) => {
|
|
68
80
|
if (refName !== '__object' &&
|
|
@@ -118,7 +130,7 @@ export function generateCustomTypes(typesMap, requiredTypes) {
|
|
|
118
130
|
}
|
|
119
131
|
}
|
|
120
132
|
const importLines = Array.from(importsByPath.entries())
|
|
121
|
-
.map(([path, types]) => `import type { ${Array.from(types).join(', ')} } from '${path}'`)
|
|
133
|
+
.map(([path, types]) => `import type { ${Array.from(types).join(', ')} } from '${resolveImportPath(path)}'`)
|
|
122
134
|
.join('\n');
|
|
123
135
|
return `${importLines}\n\n${typeDeclarations.filter(Boolean).join('\n')}`;
|
|
124
136
|
}
|
|
@@ -7,18 +7,4 @@ import type { InspectorState } from '../types.js';
|
|
|
7
7
|
* extracts tags/middleware/permissions from the pikkuFunc() config.
|
|
8
8
|
*/
|
|
9
9
|
export declare function ensureFunctionMetadata(state: InspectorState, pikkuFuncId: string, fallbackName?: string, funcInitializer?: ts.Node, checker?: ts.TypeChecker, isHelper?: boolean): void;
|
|
10
|
-
/**
|
|
11
|
-
* Register metadata for a `func:` inlined into a wiring (queue/scheduler/
|
|
12
|
-
* trigger/gateway/…).
|
|
13
|
-
*
|
|
14
|
-
* An inline function has no exported name, so `addFunctions` skips it (it bails
|
|
15
|
-
* on `__temp_` ids) and only the wiring's context-based id exists. Without this
|
|
16
|
-
* the wiring points at a function that was never registered and the worker
|
|
17
|
-
* resolves to nothing at runtime ("Missing generated metadata for ...").
|
|
18
|
-
*
|
|
19
|
-
* The stub also carries no session info, so the runtime would treat it as
|
|
20
|
-
* session-required and every invocation would fail with "Authentication
|
|
21
|
-
* required". Derive `sessionless` from the helper the function was built with —
|
|
22
|
-
* the same rule `addFunctions` applies to named ones (`!== 'pikkuFunc'`).
|
|
23
|
-
*/
|
|
24
10
|
export declare function ensureInlineWiringFunction(state: InspectorState, pikkuFuncId: string, fallbackName: string | undefined, funcInitializer: ts.Node, checker: ts.TypeChecker, isHelper?: boolean): void;
|
|
@@ -3,6 +3,7 @@ import { funcIdToTypeName } from './extract-function-name.js';
|
|
|
3
3
|
import { getCommonWireMetaData } from './get-property-value.js';
|
|
4
4
|
import { resolveMiddleware } from './middleware.js';
|
|
5
5
|
import { resolvePermissions } from './permissions.js';
|
|
6
|
+
import { resolveCalleeName } from './resolve-callee-name.js';
|
|
6
7
|
function isVoidLike(type) {
|
|
7
8
|
return !!(type.flags &
|
|
8
9
|
(ts.TypeFlags.Void | ts.TypeFlags.Undefined | ts.TypeFlags.VoidLike));
|
|
@@ -224,6 +225,7 @@ export function ensureFunctionMetadata(state, pikkuFuncId, fallbackName, funcIni
|
|
|
224
225
|
* required". Derive `sessionless` from the helper the function was built with —
|
|
225
226
|
* the same rule `addFunctions` applies to named ones (`!== 'pikkuFunc'`).
|
|
226
227
|
*/
|
|
228
|
+
const isPikkuFunc = (name) => name === 'pikkuFunc';
|
|
227
229
|
export function ensureInlineWiringFunction(state, pikkuFuncId, fallbackName, funcInitializer, checker, isHelper) {
|
|
228
230
|
ensureFunctionMetadata(state, pikkuFuncId, fallbackName, funcInitializer, checker, isHelper);
|
|
229
231
|
const meta = state.functions.meta[pikkuFuncId];
|
|
@@ -231,7 +233,8 @@ export function ensureInlineWiringFunction(state, pikkuFuncId, fallbackName, fun
|
|
|
231
233
|
meta.sessionless === undefined &&
|
|
232
234
|
ts.isCallExpression(funcInitializer) &&
|
|
233
235
|
ts.isIdentifier(funcInitializer.expression)) {
|
|
234
|
-
meta.sessionless =
|
|
236
|
+
meta.sessionless =
|
|
237
|
+
resolveCalleeName(funcInitializer, checker, isPikkuFunc) !== 'pikkuFunc';
|
|
235
238
|
}
|
|
236
239
|
}
|
|
237
240
|
function populateTypesLookup(state, pikkuFuncId, funcInitializer, checker) {
|
|
@@ -8,7 +8,7 @@ export type ExtractedFunctionName = {
|
|
|
8
8
|
isHelper: boolean;
|
|
9
9
|
version: number | null;
|
|
10
10
|
};
|
|
11
|
-
export
|
|
11
|
+
export { makeContextBasedId } from './context-based-id.js';
|
|
12
12
|
export declare function funcIdToTypeName(id: string): string;
|
|
13
13
|
export declare function extractFunctionName(callExpr: ts.Node, checker: ts.TypeChecker, rootDir: string): ExtractedFunctionName;
|
|
14
14
|
/**
|
|
@@ -18,9 +18,7 @@ function tempFuncId(callExpr, rootDir) {
|
|
|
18
18
|
.slice(0, 16);
|
|
19
19
|
return `__temp_${hash}`;
|
|
20
20
|
}
|
|
21
|
-
export
|
|
22
|
-
return [wiringType, ...segments].join(':');
|
|
23
|
-
}
|
|
21
|
+
export { makeContextBasedId } from './context-based-id.js';
|
|
24
22
|
export function funcIdToTypeName(id) {
|
|
25
23
|
return id
|
|
26
24
|
.split(/[^a-zA-Z0-9]/)
|
|
@@ -30,7 +28,7 @@ export function funcIdToTypeName(id) {
|
|
|
30
28
|
}
|
|
31
29
|
/**
|
|
32
30
|
* The step wrappers, whichever kind of subject acts in them. A scenario calls a
|
|
33
|
-
* platform or addon step by name exactly as it calls a
|
|
31
|
+
* platform or addon step by name exactly as it calls a virtual user one.
|
|
34
32
|
*/
|
|
35
33
|
const SCENARIO_STEP_WRAPPERS = new Set([
|
|
36
34
|
'pikkuScenarioStep',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { parseVersionedId } from '@pikku/core/utils';
|
|
2
|
-
import { makeContextBasedId } from './
|
|
2
|
+
import { makeContextBasedId } from './context-based-id.js';
|
|
3
3
|
import { aggregateRequiredServices } from './post-process.js';
|
|
4
4
|
import { IncompatibleDeployTargetError, resolveDeployTarget, } from './resolve-deploy-target.js';
|
|
5
5
|
/**
|
|
@@ -359,6 +359,11 @@ export function filterInspectorState(state, filters, logger) {
|
|
|
359
359
|
meta: JSON.parse(JSON.stringify(state.channels.meta)),
|
|
360
360
|
files: new Set(), // Will be repopulated with filtered files
|
|
361
361
|
},
|
|
362
|
+
gateways: {
|
|
363
|
+
...state.gateways,
|
|
364
|
+
meta: JSON.parse(JSON.stringify(state.gateways?.meta ?? {})),
|
|
365
|
+
files: new Set(),
|
|
366
|
+
},
|
|
362
367
|
triggers: {
|
|
363
368
|
...state.triggers,
|
|
364
369
|
meta: JSON.parse(JSON.stringify(state.triggers?.meta ?? {})),
|
|
@@ -511,6 +516,31 @@ export function filterInspectorState(state, filters, logger) {
|
|
|
511
516
|
}
|
|
512
517
|
}
|
|
513
518
|
filteredState.channels.files = repopulateFileSetFromMeta(filteredState.channels.meta, state.channels.files, Object.keys(filteredState.channels.meta).length > 0);
|
|
519
|
+
// Filter gateways. A gateway is addressed by its own name or by the function
|
|
520
|
+
// it runs, so a deploy unit naming either keeps the wiring that serves it.
|
|
521
|
+
for (const name of Object.keys(filteredState.gateways.meta)) {
|
|
522
|
+
const gatewayMeta = filteredState.gateways.meta[name];
|
|
523
|
+
const matches = matchesFilters(filters, {
|
|
524
|
+
type: 'gateway',
|
|
525
|
+
name: gatewayMeta.pikkuFuncId,
|
|
526
|
+
altNames: [name],
|
|
527
|
+
tags: gatewayMeta.tags,
|
|
528
|
+
httpRoute: gatewayMeta.route,
|
|
529
|
+
}, logger, undefined, keptByDeploy);
|
|
530
|
+
if (!matches) {
|
|
531
|
+
delete filteredState.gateways.meta[name];
|
|
532
|
+
}
|
|
533
|
+
else {
|
|
534
|
+
filteredState.serviceAggregation.usedFunctions.add(gatewayMeta.pikkuFuncId);
|
|
535
|
+
extractWireNames(gatewayMeta.middleware).forEach((name) => filteredState.serviceAggregation.usedMiddleware.add(name));
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
// The meta records no source file per gateway, so a surviving gateway keeps
|
|
539
|
+
// every gateway file and none surviving drops them all.
|
|
540
|
+
filteredState.gateways.files =
|
|
541
|
+
Object.keys(filteredState.gateways.meta).length > 0
|
|
542
|
+
? new Set(state.gateways?.files ?? [])
|
|
543
|
+
: new Set();
|
|
514
544
|
// Filter triggers
|
|
515
545
|
for (const name of Object.keys(filteredState.triggers.meta)) {
|
|
516
546
|
const triggerMeta = filteredState.triggers.meta[name];
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import * as ts from 'typescript';
|
|
2
2
|
import { ErrorCode } from '../error-codes.js';
|
|
3
3
|
export declare const getArrayPropertyValue: (obj: ts.ObjectLiteralExpression, propertyName: string) => string[] | null;
|
|
4
|
+
/**
|
|
5
|
+
* Returns the object literal assigned to a property, or null when the property
|
|
6
|
+
* is absent or is not an inline object.
|
|
7
|
+
*/
|
|
8
|
+
export declare const getObjectPropertyLiteral: (obj: ts.ObjectLiteralExpression, propertyName: string) => ts.ObjectLiteralExpression | null;
|
|
4
9
|
/**
|
|
5
10
|
* Extracts a string->string record from an object property.
|
|
6
11
|
*
|
|
@@ -27,6 +27,20 @@ export const getArrayPropertyValue = (obj, propertyName) => {
|
|
|
27
27
|
}
|
|
28
28
|
return null;
|
|
29
29
|
};
|
|
30
|
+
/**
|
|
31
|
+
* Returns the object literal assigned to a property, or null when the property
|
|
32
|
+
* is absent or is not an inline object.
|
|
33
|
+
*/
|
|
34
|
+
export const getObjectPropertyLiteral = (obj, propertyName) => {
|
|
35
|
+
const property = obj.properties.find((p) => ts.isPropertyAssignment(p) &&
|
|
36
|
+
ts.isIdentifier(p.name) &&
|
|
37
|
+
p.name.text === propertyName);
|
|
38
|
+
if (!property || !ts.isPropertyAssignment(property)) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
const initializer = unwrapAs(property.initializer);
|
|
42
|
+
return ts.isObjectLiteralExpression(initializer) ? initializer : null;
|
|
43
|
+
};
|
|
30
44
|
/**
|
|
31
45
|
* Extracts a string->string record from an object property.
|
|
32
46
|
*
|
|
@@ -102,7 +116,7 @@ export const assertStringLiteralProperty = (obj, propertyName, wiringType, logge
|
|
|
102
116
|
* that anything written as an expression comes through raw: a `description`
|
|
103
117
|
* split across lines as `'Fetch the thing ' + 'from upstream'` reaches
|
|
104
118
|
* `infra.json` with the quotes and the `+` still in it, and is rendered that
|
|
105
|
-
* way in the
|
|
119
|
+
* way in the cloud console.
|
|
106
120
|
*
|
|
107
121
|
* Deliberately checker-free, unlike `extractStringLiteral`. Every value this
|
|
108
122
|
* resolves is a literal in the same expression, so no symbol resolution is
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pikku function id of the single shared auth handler the CLI generates
|
|
3
|
+
* (`export const authHandler = pikkuSessionlessFunc(...)` in auth.gen.ts). An
|
|
4
|
+
* exported top-level const collapses the catch-all `/api/auth/**` route onto one
|
|
5
|
+
* worker, and the export name becomes the function id. Shared with the CLI
|
|
6
|
+
* codegen and the post-process service stamp so all three agree on the same id
|
|
7
|
+
* without the inspector having to import `@pikku/better-auth`.
|
|
8
|
+
*/
|
|
9
|
+
export declare const AUTH_HANDLER_FUNC_ID = "authHandler";
|
|
10
|
+
/**
|
|
11
|
+
* Placeholder recorded when a scenario step's target isn't a static string
|
|
12
|
+
* literal. The step is kept rather than dropped so post-processing can raise
|
|
13
|
+
* PKU678 against it — a dropped step is the silent-failure mode this repo has
|
|
14
|
+
* hit repeatedly on workflow graph round-trips.
|
|
15
|
+
*/
|
|
16
|
+
export declare const DYNAMIC_SCENARIO_STEP_TARGET = "<dynamic>";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pikku function id of the single shared auth handler the CLI generates
|
|
3
|
+
* (`export const authHandler = pikkuSessionlessFunc(...)` in auth.gen.ts). An
|
|
4
|
+
* exported top-level const collapses the catch-all `/api/auth/**` route onto one
|
|
5
|
+
* worker, and the export name becomes the function id. Shared with the CLI
|
|
6
|
+
* codegen and the post-process service stamp so all three agree on the same id
|
|
7
|
+
* without the inspector having to import `@pikku/better-auth`.
|
|
8
|
+
*/
|
|
9
|
+
export const AUTH_HANDLER_FUNC_ID = 'authHandler';
|
|
10
|
+
/**
|
|
11
|
+
* Placeholder recorded when a scenario step's target isn't a static string
|
|
12
|
+
* literal. The step is kept rather than dropped so post-processing can raise
|
|
13
|
+
* PKU678 against it — a dropped step is the silent-failure mode this repo has
|
|
14
|
+
* hit repeatedly on workflow graph round-trips.
|
|
15
|
+
*/
|
|
16
|
+
export const DYNAMIC_SCENARIO_STEP_TARGET = '<dynamic>';
|
|
@@ -45,6 +45,7 @@ const applyPackageToCLICommands = (commands, packageName, namespace) => {
|
|
|
45
45
|
}
|
|
46
46
|
if (namespace &&
|
|
47
47
|
typeof command.pikkuFuncId === 'string' &&
|
|
48
|
+
command.pikkuFuncId !== '' &&
|
|
48
49
|
!command.pikkuFuncId.includes(':')) {
|
|
49
50
|
command.pikkuFuncId = `${namespace}:${command.pikkuFuncId}`;
|
|
50
51
|
}
|