@pikku/inspector 0.12.0 → 0.12.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 +25 -0
- package/dist/add/add-ai-agent.d.ts +1 -1
- package/dist/add/add-ai-agent.js +1 -1
- package/dist/add/add-channel.js +12 -0
- package/dist/add/add-cli.d.ts +1 -1
- package/dist/add/add-cli.js +6 -1
- package/dist/add/add-file-extends-core-type.d.ts +1 -1
- package/dist/add/add-file-with-config.d.ts +1 -1
- package/dist/add/add-file-with-factory.d.ts +1 -1
- package/dist/add/add-file-with-factory.js +2 -2
- package/dist/add/add-functions.d.ts +1 -1
- package/dist/add/add-functions.js +6 -7
- package/dist/add/add-http-route.d.ts +3 -2
- package/dist/add/add-http-route.js +5 -1
- package/dist/add/add-http-routes.d.ts +1 -1
- package/dist/add/add-http-routes.js +1 -0
- package/dist/add/add-keyed-wiring.d.ts +1 -1
- package/dist/add/add-mcp-prompt.d.ts +1 -1
- package/dist/add/add-mcp-resource.d.ts +1 -1
- package/dist/add/add-queue-worker.d.ts +1 -1
- package/dist/add/add-rpc-invocations.d.ts +3 -3
- package/dist/add/add-rpc-invocations.js +10 -10
- package/dist/add/add-schedule.d.ts +1 -1
- package/dist/add/add-secret.d.ts +1 -1
- package/dist/add/add-trigger.d.ts +1 -1
- package/dist/add/add-trigger.js +2 -2
- package/dist/add/add-wire-addon.d.ts +7 -0
- package/dist/add/add-wire-addon.js +70 -0
- package/dist/add/add-workflow.d.ts +1 -1
- package/dist/error-codes.d.ts +1 -0
- package/dist/error-codes.js +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/inspector.d.ts +1 -1
- package/dist/inspector.js +7 -4
- package/dist/types.d.ts +26 -20
- package/dist/utils/compute-required-schemas.js +1 -2
- package/dist/utils/contract-hashes.d.ts +20 -3
- package/dist/utils/contract-hashes.js +77 -10
- package/dist/utils/custom-types-generator.d.ts +1 -1
- package/dist/utils/detect-schema-vendor.d.ts +1 -1
- package/dist/utils/does-type-extend-core-type.d.ts +1 -1
- package/dist/utils/ensure-function-metadata.d.ts +1 -1
- package/dist/utils/extract-services.d.ts +1 -1
- package/dist/utils/filter-inspector-state.d.ts +1 -1
- package/dist/utils/filter-utils.d.ts +2 -2
- package/dist/utils/get-files-and-methods.d.ts +1 -1
- package/dist/utils/middleware.d.ts +2 -2
- package/dist/utils/permissions.d.ts +2 -2
- package/dist/utils/post-process.d.ts +4 -3
- package/dist/utils/post-process.js +24 -8
- package/dist/utils/resolve-addon-package.d.ts +16 -0
- package/dist/utils/{resolve-external-package.js → resolve-addon-package.js} +8 -8
- package/dist/utils/schema-generator.d.ts +2 -2
- package/dist/utils/serialize-inspector-state.d.ts +13 -3
- package/dist/utils/serialize-inspector-state.js +6 -2
- package/dist/utils/validate-auth-sessionless.d.ts +3 -0
- package/dist/utils/validate-auth-sessionless.js +14 -0
- package/dist/utils/workflow/dsl/extract-dsl-workflow.d.ts +1 -1
- package/dist/visit.d.ts +1 -1
- package/dist/visit.js +2 -0
- package/package.json +2 -2
- package/src/add/add-ai-agent.ts +2 -2
- package/src/add/add-channel.ts +21 -0
- package/src/add/add-cli.ts +19 -4
- package/src/add/add-file-extends-core-type.ts +1 -1
- package/src/add/add-file-with-config.ts +1 -1
- package/src/add/add-file-with-factory.ts +3 -3
- package/src/add/add-functions.ts +21 -19
- package/src/add/add-http-route.ts +19 -2
- package/src/add/add-http-routes.ts +2 -1
- package/src/add/add-keyed-wiring.ts +1 -1
- package/src/add/add-mcp-prompt.ts +1 -1
- package/src/add/add-mcp-resource.ts +1 -1
- package/src/add/add-queue-worker.ts +1 -1
- package/src/add/add-rpc-invocations.ts +11 -11
- package/src/add/add-schedule.ts +1 -1
- package/src/add/add-secret.ts +1 -1
- package/src/add/add-trigger.ts +4 -4
- package/src/add/add-wire-addon.ts +80 -0
- package/src/add/add-workflow.ts +2 -2
- package/src/error-codes.ts +1 -0
- package/src/index.ts +1 -0
- package/src/inspector.ts +13 -5
- package/src/types.ts +33 -20
- package/src/utils/compute-required-schemas.ts +1 -2
- package/src/utils/contract-hashes.test.ts +30 -5
- package/src/utils/contract-hashes.ts +110 -14
- package/src/utils/custom-types-generator.ts +1 -1
- package/src/utils/detect-schema-vendor.ts +1 -1
- package/src/utils/does-type-extend-core-type.ts +1 -1
- package/src/utils/ensure-function-metadata.ts +1 -1
- package/src/utils/extract-services.ts +1 -1
- package/src/utils/filter-inspector-state.test.ts +3 -5
- package/src/utils/filter-inspector-state.ts +7 -2
- package/src/utils/filter-utils.test.ts +1 -1
- package/src/utils/filter-utils.ts +2 -2
- package/src/utils/get-files-and-methods.ts +1 -1
- package/src/utils/middleware.ts +2 -2
- package/src/utils/permissions.ts +2 -2
- package/src/utils/post-process.ts +34 -12
- package/src/utils/{resolve-external-package.ts → resolve-addon-package.ts} +17 -10
- package/src/utils/resolve-versions.test.ts +1 -1
- package/src/utils/schema-generator.ts +4 -4
- package/src/utils/serialize-inspector-state.ts +23 -5
- package/src/utils/validate-auth-sessionless.ts +29 -0
- package/src/utils/workflow/dsl/extract-dsl-workflow.ts +2 -2
- package/src/visit.ts +7 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/utils/resolve-external-package.d.ts +0 -12
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
## 0.12.0
|
|
2
2
|
|
|
3
|
+
## 0.12.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 62a8725: Rename 'external' to 'addon' throughout the codebase. All types, functions, config keys, and CLI options previously named `external` or `External` are now named `addon` or `Addon` (e.g. `ExternalPackageConfig` → `AddonConfig`, `externalPackages` → `addons`, `function-external` → `function-addon`).
|
|
8
|
+
- 8eed717: Add `readonly` flag to function config and runtime enforcement. Functions can be marked `readonly: true` in their config. At runtime, if a session has `readonly: true`, only functions marked as readonly can be called — otherwise a `ReadonlySessionError` (403) is thrown.
|
|
9
|
+
- 62a8725: `pikku versions check` now prints rich, human-readable output for all contract version errors instead of raw error codes. Each error type (PKU861–PKU865) shows the function name, separate input/output schema hashes with a `prev → current` arrow, and clear next-step instructions.
|
|
10
|
+
|
|
11
|
+
The version manifest now stores separate `inputHash` and `outputHash` per version entry (backward-compatible — old string-hash manifests still load and validate correctly). `VersionValidateError` gains optional detail fields (`functionKey`, `version`, `previousInputHash`, `currentInputHash`, `previousOutputHash`, `currentOutputHash`, `nextVersion`, `latestVersion`, `expectedNextVersion`) for use by tooling.
|
|
12
|
+
|
|
13
|
+
- 62a8725: Replace config-based addon declarations with the new `wireAddon()` code-based API. Addons are now declared directly in wiring files using `wireAddon({ name, package, rpcEndpoint?, auth?, tags? })` instead of the `addons` field in `pikku.config.json`. The inspector reads these declarations from the TypeScript AST at build time.
|
|
14
|
+
- 62a8725: Add `secretOverrides` and `variableOverrides` support to `wireAddon()`. These optional maps allow an app to remap an addon's secret/variable keys to its own names (e.g. `secretOverrides: { SENDGRID_API_KEY: 'MY_EMAIL_API_KEY' }`). The inspector validates that all override keys exist in the app's own secrets/variables definitions.
|
|
15
|
+
- Updated dependencies [62a8725]
|
|
16
|
+
- Updated dependencies [a3bdb0d]
|
|
17
|
+
- Updated dependencies [e0349ff]
|
|
18
|
+
- Updated dependencies [62a8725]
|
|
19
|
+
- Updated dependencies [e04531f]
|
|
20
|
+
- Updated dependencies [62a8725]
|
|
21
|
+
- Updated dependencies [a83efb8]
|
|
22
|
+
- Updated dependencies [8eed717]
|
|
23
|
+
- Updated dependencies [62a8725]
|
|
24
|
+
- Updated dependencies [62a8725]
|
|
25
|
+
- Updated dependencies [62a8725]
|
|
26
|
+
- @pikku/core@0.12.1
|
|
27
|
+
|
|
3
28
|
### New Features
|
|
4
29
|
|
|
5
30
|
- AI agent metadata extraction
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { AddWiring } from '../types.js';
|
|
1
|
+
import type { AddWiring } from '../types.js';
|
|
2
2
|
export declare const addAIAgent: AddWiring;
|
package/dist/add/add-ai-agent.js
CHANGED
|
@@ -33,7 +33,7 @@ function resolveToolReferences(obj, checker, agentName, logger) {
|
|
|
33
33
|
continue;
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
|
-
if (calleeName === '
|
|
36
|
+
if (calleeName === 'addon') {
|
|
37
37
|
const [firstArg] = element.arguments;
|
|
38
38
|
if (firstArg && ts.isStringLiteral(firstArg)) {
|
|
39
39
|
resolved.push(firstArg.text);
|
package/dist/add/add-channel.js
CHANGED
|
@@ -7,6 +7,7 @@ import { getPropertyAssignmentInitializer } from '../utils/type-utils.js';
|
|
|
7
7
|
import { resolveMiddleware, resolveChannelMiddleware, } from '../utils/middleware.js';
|
|
8
8
|
import { extractWireNames } from '../utils/post-process.js';
|
|
9
9
|
import { resolveIdentifier } from '../utils/resolve-identifier.js';
|
|
10
|
+
import { validateAuthSessionless } from '../utils/validate-auth-sessionless.js';
|
|
10
11
|
/**
|
|
11
12
|
* Safely get the "initializer" expression of a property-like AST node:
|
|
12
13
|
* - for `foo: expr`, returns `expr`
|
|
@@ -416,6 +417,17 @@ export const addChannel = (logger, node, checker, state, options) => {
|
|
|
416
417
|
}
|
|
417
418
|
}
|
|
418
419
|
extractWireNames(middleware).forEach((name) => state.serviceAggregation.usedMiddleware.add(name));
|
|
420
|
+
// --- validate auth/sessionless ---
|
|
421
|
+
const handlersToValidate = [
|
|
422
|
+
connectFuncId,
|
|
423
|
+
disconnectFuncId,
|
|
424
|
+
message?.pikkuFuncId,
|
|
425
|
+
].filter(Boolean);
|
|
426
|
+
for (const funcId of handlersToValidate) {
|
|
427
|
+
if (!validateAuthSessionless(logger, obj, state, funcId, `Channel '${name}'`)) {
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
419
431
|
state.channels.files.add(node.getSourceFile().fileName);
|
|
420
432
|
state.channels.meta[name] = {
|
|
421
433
|
name,
|
package/dist/add/add-cli.d.ts
CHANGED
package/dist/add/add-cli.js
CHANGED
|
@@ -4,6 +4,7 @@ import { resolveMiddleware } from '../utils/middleware.js';
|
|
|
4
4
|
import { extractWireNames } from '../utils/post-process.js';
|
|
5
5
|
import { getPropertyValue } from '../utils/get-property-value.js';
|
|
6
6
|
import { resolveIdentifier } from '../utils/resolve-identifier.js';
|
|
7
|
+
import { validateAuthSessionless } from '../utils/validate-auth-sessionless.js';
|
|
7
8
|
// Track if we've warned about missing Config type to avoid duplicate warnings
|
|
8
9
|
const configTypeWarningShown = new Set();
|
|
9
10
|
/**
|
|
@@ -270,10 +271,14 @@ function processCommand(logger, inspectorState, options, name, node, sourceFile,
|
|
|
270
271
|
break;
|
|
271
272
|
}
|
|
272
273
|
}
|
|
274
|
+
// --- validate auth/sessionless ---
|
|
275
|
+
if (meta.pikkuFuncId &&
|
|
276
|
+
!validateAuthSessionless(logger, node, inspectorState, meta.pikkuFuncId, `CLI command '${name}'`)) {
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
273
279
|
// --- track used functions/middleware for service aggregation ---
|
|
274
280
|
inspectorState.serviceAggregation.usedFunctions.add(meta.pikkuFuncId);
|
|
275
281
|
extractWireNames(meta.middleware).forEach((name) => inspectorState.serviceAggregation.usedMiddleware.add(name));
|
|
276
|
-
// Note: subcommands are tracked recursively when they're processed
|
|
277
282
|
return meta;
|
|
278
283
|
}
|
|
279
284
|
/**
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import * as ts from 'typescript';
|
|
2
|
-
import { PathToNameAndType, InspectorState } from '../types.js';
|
|
2
|
+
import type { PathToNameAndType, InspectorState } from '../types.js';
|
|
3
3
|
export declare const addFileExtendsCoreType: (node: ts.Node, checker: ts.TypeChecker, methods: PathToNameAndType, expectedTypeName: string, state?: InspectorState) => void;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import * as ts from 'typescript';
|
|
2
|
-
import { PathToNameAndType, InspectorState } from '../types.js';
|
|
2
|
+
import type { PathToNameAndType, InspectorState } from '../types.js';
|
|
3
3
|
export declare const addFileWithFactory: (node: ts.Node, checker: ts.TypeChecker, methods: PathToNameAndType | undefined, expectedTypeName: string, state?: InspectorState) => void;
|
|
@@ -3,9 +3,9 @@ import { extractServicesFromFunction } from '../utils/extract-services.js';
|
|
|
3
3
|
// Mapping of wrapper function names to their corresponding types
|
|
4
4
|
const wrapperFunctionMap = {
|
|
5
5
|
pikkuConfig: 'CreateConfig',
|
|
6
|
-
|
|
6
|
+
pikkuAddonConfig: 'CreateConfig',
|
|
7
7
|
pikkuServices: 'CreateSingletonServices',
|
|
8
|
-
|
|
8
|
+
pikkuAddonServices: 'CreateSingletonServices',
|
|
9
9
|
pikkuWireServices: 'CreateWireServices',
|
|
10
10
|
};
|
|
11
11
|
export const addFileWithFactory = (node, checker, methods = new Map(), expectedTypeName, state) => {
|
|
@@ -154,9 +154,7 @@ const getNamesAndTypes = (checker, typesMap, direction, funcName, type) => {
|
|
|
154
154
|
const aliasType = rawNames.join(' | ');
|
|
155
155
|
const aliasName = funcIdToTypeName(funcName) + direction;
|
|
156
156
|
// record the alias in your TypesMap
|
|
157
|
-
const references = rawTypes
|
|
158
|
-
.map((t) => resolveTypeImports(t, typesMap, true, checker))
|
|
159
|
-
.flat();
|
|
157
|
+
const references = rawTypes.flatMap((t) => resolveTypeImports(t, typesMap, true, checker));
|
|
160
158
|
typesMap.addCustomType(aliasName, aliasType, references);
|
|
161
159
|
return {
|
|
162
160
|
names: [aliasName],
|
|
@@ -164,8 +162,7 @@ const getNamesAndTypes = (checker, typesMap, direction, funcName, type) => {
|
|
|
164
162
|
};
|
|
165
163
|
}
|
|
166
164
|
// 4) Single, valid name → inline it
|
|
167
|
-
const uniqueNames = rawNames
|
|
168
|
-
.map((name, i) => {
|
|
165
|
+
const uniqueNames = rawNames.flatMap((name, i) => {
|
|
169
166
|
const t = rawTypes[i];
|
|
170
167
|
if (!t) {
|
|
171
168
|
throw new Error(`Expected type for name "${name}" in ${funcName}`);
|
|
@@ -175,8 +172,7 @@ const getNamesAndTypes = (checker, typesMap, direction, funcName, type) => {
|
|
|
175
172
|
}
|
|
176
173
|
// non-primitive: import/alias it inline
|
|
177
174
|
return resolveTypeImports(t, typesMap, false, checker);
|
|
178
|
-
})
|
|
179
|
-
.flat();
|
|
175
|
+
});
|
|
180
176
|
return {
|
|
181
177
|
names: uniqueNames,
|
|
182
178
|
types: rawTypes,
|
|
@@ -248,6 +244,7 @@ export const addFunctions = (logger, node, checker, state, options) => {
|
|
|
248
244
|
let expose;
|
|
249
245
|
let remote;
|
|
250
246
|
let mcp;
|
|
247
|
+
let readonly_;
|
|
251
248
|
let requiresApproval;
|
|
252
249
|
let version;
|
|
253
250
|
let objectNode;
|
|
@@ -313,6 +310,7 @@ export const addFunctions = (logger, node, checker, state, options) => {
|
|
|
313
310
|
expose = getPropertyValue(firstArg, 'expose');
|
|
314
311
|
remote = getPropertyValue(firstArg, 'remote');
|
|
315
312
|
mcp = getPropertyValue(firstArg, 'mcp');
|
|
313
|
+
readonly_ = getPropertyValue(firstArg, 'readonly');
|
|
316
314
|
requiresApproval = getPropertyValue(firstArg, 'requiresApproval');
|
|
317
315
|
const versionRaw = getPropertyValue(firstArg, 'version');
|
|
318
316
|
if (versionRaw !== null && versionRaw !== undefined) {
|
|
@@ -566,6 +564,7 @@ export const addFunctions = (logger, node, checker, state, options) => {
|
|
|
566
564
|
expose: expose || undefined,
|
|
567
565
|
remote: remote || undefined,
|
|
568
566
|
mcp: mcpEnabled || undefined,
|
|
567
|
+
readonly: readonly_ || undefined,
|
|
569
568
|
requiresApproval: requiresApproval || undefined,
|
|
570
569
|
version,
|
|
571
570
|
title,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as ts from 'typescript';
|
|
2
|
-
import { AddWiring, InspectorState } from '../types.js';
|
|
2
|
+
import type { AddWiring, InspectorState } from '../types.js';
|
|
3
3
|
import type { InspectorLogger } from '../types.js';
|
|
4
4
|
/**
|
|
5
5
|
* Parameters for registering an HTTP route
|
|
@@ -12,12 +12,13 @@ export interface RegisterHTTPRouteParams {
|
|
|
12
12
|
sourceFile: ts.SourceFile;
|
|
13
13
|
basePath?: string;
|
|
14
14
|
inheritedTags?: string[];
|
|
15
|
+
inheritedAuth?: boolean;
|
|
15
16
|
}
|
|
16
17
|
/**
|
|
17
18
|
* Shared function to register an HTTP route in the inspector state.
|
|
18
19
|
* Used by both wireHTTP and wireHTTPRoutes.
|
|
19
20
|
*/
|
|
20
|
-
export declare function registerHTTPRoute({ obj, state, checker, logger, sourceFile, basePath, inheritedTags, }: RegisterHTTPRouteParams): void;
|
|
21
|
+
export declare function registerHTTPRoute({ obj, state, checker, logger, sourceFile, basePath, inheritedTags, inheritedAuth, }: RegisterHTTPRouteParams): void;
|
|
21
22
|
/**
|
|
22
23
|
* Process wireHTTP calls
|
|
23
24
|
*/
|
|
@@ -8,6 +8,7 @@ import { resolveHTTPPermissionsFromObject } from '../utils/permissions.js';
|
|
|
8
8
|
import { extractWireNames } from '../utils/post-process.js';
|
|
9
9
|
import { ensureFunctionMetadata } from '../utils/ensure-function-metadata.js';
|
|
10
10
|
import { ErrorCode } from '../error-codes.js';
|
|
11
|
+
import { validateAuthSessionless } from '../utils/validate-auth-sessionless.js';
|
|
11
12
|
import { detectSchemaVendorOrError } from '../utils/detect-schema-vendor.js';
|
|
12
13
|
/**
|
|
13
14
|
* Extract header schema reference from headers property
|
|
@@ -76,7 +77,7 @@ const computeInputTypes = (metaTypes, methodType, inputType, queryValues, params
|
|
|
76
77
|
* Shared function to register an HTTP route in the inspector state.
|
|
77
78
|
* Used by both wireHTTP and wireHTTPRoutes.
|
|
78
79
|
*/
|
|
79
|
-
export function registerHTTPRoute({ obj, state, checker, logger, sourceFile, basePath = '', inheritedTags = [], }) {
|
|
80
|
+
export function registerHTTPRoute({ obj, state, checker, logger, sourceFile, basePath = '', inheritedTags = [], inheritedAuth, }) {
|
|
80
81
|
// Extract route path
|
|
81
82
|
const routePath = getPropertyValue(obj, 'route');
|
|
82
83
|
if (!routePath)
|
|
@@ -118,6 +119,9 @@ export function registerHTTPRoute({ obj, state, checker, logger, sourceFile, bas
|
|
|
118
119
|
logger.critical(ErrorCode.FUNCTION_METADATA_NOT_FOUND, `No function metadata found for '${funcName}'.`);
|
|
119
120
|
return;
|
|
120
121
|
}
|
|
122
|
+
if (!validateAuthSessionless(logger, obj, state, funcName, `Route '${fullRoute}'`, inheritedAuth)) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
121
125
|
const input = fnMeta.inputs?.[0] || null;
|
|
122
126
|
// Validate that route params and query params exist in function input type
|
|
123
127
|
if (params.length > 0 || query.length > 0) {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { AddWiring } from '../types.js';
|
|
1
|
+
import type { AddWiring } from '../types.js';
|
|
2
2
|
export declare const addMCPPrompt: AddWiring;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { AddWiring } from '../types.js';
|
|
1
|
+
import type { AddWiring } from '../types.js';
|
|
2
2
|
export declare const addMCPResource: AddWiring;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { AddWiring } from '../types.js';
|
|
1
|
+
import type { AddWiring } from '../types.js';
|
|
2
2
|
export declare const addQueueWorker: AddWiring;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as ts from 'typescript';
|
|
2
|
-
import { InspectorState, InspectorLogger } from '../types.js';
|
|
2
|
+
import type { InspectorState, InspectorLogger } from '../types.js';
|
|
3
3
|
/**
|
|
4
4
|
* Scan for rpc.invoke() calls to track which functions are actually being invoked
|
|
5
|
-
* Also detects
|
|
5
|
+
* Also detects addon usage via:
|
|
6
6
|
* - Namespaced calls: rpc.invoke('namespace:function')
|
|
7
|
-
* -
|
|
7
|
+
* - Addon helper: addon('namespace:function')
|
|
8
8
|
*/
|
|
9
9
|
export declare function addRPCInvocations(node: ts.Node, state: InspectorState, logger: InspectorLogger): void;
|
|
@@ -11,25 +11,25 @@ function extractNamespace(functionRef) {
|
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
13
|
* Scan for rpc.invoke() calls to track which functions are actually being invoked
|
|
14
|
-
* Also detects
|
|
14
|
+
* Also detects addon usage via:
|
|
15
15
|
* - Namespaced calls: rpc.invoke('namespace:function')
|
|
16
|
-
* -
|
|
16
|
+
* - Addon helper: addon('namespace:function')
|
|
17
17
|
*/
|
|
18
18
|
export function addRPCInvocations(node, state, logger) {
|
|
19
|
-
// Look for call expressions:
|
|
19
|
+
// Look for call expressions: addon('ext:hello') or rpc.invoke('...')
|
|
20
20
|
if (ts.isCallExpression(node)) {
|
|
21
21
|
const { expression, arguments: args } = node;
|
|
22
|
-
// Check for
|
|
23
|
-
if (ts.isIdentifier(expression) && expression.text === '
|
|
22
|
+
// Check for addon('namespace:function') calls
|
|
23
|
+
if (ts.isIdentifier(expression) && expression.text === 'addon') {
|
|
24
24
|
const [firstArg] = args;
|
|
25
25
|
if (firstArg && ts.isStringLiteral(firstArg)) {
|
|
26
26
|
const functionRef = firstArg.text;
|
|
27
|
-
logger.debug(`• Found
|
|
27
|
+
logger.debug(`• Found addon() call: ${functionRef}`);
|
|
28
28
|
state.rpc.invokedFunctions.add(functionRef);
|
|
29
29
|
const namespace = extractNamespace(functionRef);
|
|
30
30
|
if (namespace) {
|
|
31
|
-
logger.debug(` →
|
|
32
|
-
state.rpc.
|
|
31
|
+
logger.debug(` → Addon detected: ${namespace}`);
|
|
32
|
+
state.rpc.usedAddons.add(namespace);
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
}
|
|
@@ -60,8 +60,8 @@ export function addRPCInvocations(node, state, logger) {
|
|
|
60
60
|
state.rpc.invokedFunctions.add(functionRef);
|
|
61
61
|
const namespace = extractNamespace(functionRef);
|
|
62
62
|
if (namespace) {
|
|
63
|
-
logger.debug(` →
|
|
64
|
-
state.rpc.
|
|
63
|
+
logger.debug(` → Addon detected: ${namespace}`);
|
|
64
|
+
state.rpc.usedAddons.add(namespace);
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
// Handle template literals like `function-${name}`
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { AddWiring } from '../types.js';
|
|
1
|
+
import type { AddWiring } from '../types.js';
|
|
2
2
|
export declare const addSchedule: AddWiring;
|
package/dist/add/add-secret.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { AddWiring } from '../types.js';
|
|
1
|
+
import type { AddWiring } from '../types.js';
|
|
2
2
|
export declare const addTrigger: AddWiring;
|
package/dist/add/add-trigger.js
CHANGED
|
@@ -4,7 +4,7 @@ import { extractFunctionName, makeContextBasedId, } from '../utils/extract-funct
|
|
|
4
4
|
import { getPropertyAssignmentInitializer } from '../utils/type-utils.js';
|
|
5
5
|
import { resolveMiddleware } from '../utils/middleware.js';
|
|
6
6
|
import { extractWireNames } from '../utils/post-process.js';
|
|
7
|
-
import {
|
|
7
|
+
import { resolveAddonName } from '../utils/resolve-addon-package.js';
|
|
8
8
|
import { ErrorCode } from '../error-codes.js';
|
|
9
9
|
export const addTrigger = (logger, node, checker, state, options) => {
|
|
10
10
|
if (!ts.isCallExpression(node)) {
|
|
@@ -76,7 +76,7 @@ const addWireTriggerSource = (logger, node, checker, state, options, firstArg) =
|
|
|
76
76
|
return;
|
|
77
77
|
}
|
|
78
78
|
if (ts.isIdentifier(funcInitializer)) {
|
|
79
|
-
const packageName =
|
|
79
|
+
const packageName = resolveAddonName(funcInitializer, checker, state.rpc.wireAddonDeclarations);
|
|
80
80
|
state.triggers.sourceMeta[nameValue] = {
|
|
81
81
|
name: nameValue,
|
|
82
82
|
pikkuFuncId: funcInitializer.text,
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as ts from 'typescript';
|
|
2
|
+
import type { InspectorState, InspectorLogger } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Detect wireAddon({ name: '...', package: '...' }) call expressions and
|
|
5
|
+
* populate state.rpc.wireAddonDeclarations and state.rpc.usedAddons.
|
|
6
|
+
*/
|
|
7
|
+
export declare function addWireAddon(node: ts.Node, state: InspectorState, logger: InspectorLogger): void;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import * as ts from 'typescript';
|
|
2
|
+
function parseStringRecord(obj) {
|
|
3
|
+
const result = {};
|
|
4
|
+
for (const prop of obj.properties) {
|
|
5
|
+
if (!ts.isPropertyAssignment(prop))
|
|
6
|
+
continue;
|
|
7
|
+
const keyNode = prop.name;
|
|
8
|
+
const key = ts.isIdentifier(keyNode)
|
|
9
|
+
? keyNode.text
|
|
10
|
+
: ts.isStringLiteral(keyNode)
|
|
11
|
+
? keyNode.text
|
|
12
|
+
: undefined;
|
|
13
|
+
if (key && ts.isStringLiteral(prop.initializer)) {
|
|
14
|
+
result[key] = prop.initializer.text;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return result;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Detect wireAddon({ name: '...', package: '...' }) call expressions and
|
|
21
|
+
* populate state.rpc.wireAddonDeclarations and state.rpc.usedAddons.
|
|
22
|
+
*/
|
|
23
|
+
export function addWireAddon(node, state, logger) {
|
|
24
|
+
if (!ts.isCallExpression(node))
|
|
25
|
+
return;
|
|
26
|
+
const { expression, arguments: args } = node;
|
|
27
|
+
if (!ts.isIdentifier(expression) || expression.text !== 'wireAddon')
|
|
28
|
+
return;
|
|
29
|
+
const [firstArg] = args;
|
|
30
|
+
if (!firstArg || !ts.isObjectLiteralExpression(firstArg))
|
|
31
|
+
return;
|
|
32
|
+
let name;
|
|
33
|
+
let pkg;
|
|
34
|
+
let rpcEndpoint;
|
|
35
|
+
let secretOverrides;
|
|
36
|
+
let variableOverrides;
|
|
37
|
+
for (const prop of firstArg.properties) {
|
|
38
|
+
if (!ts.isPropertyAssignment(prop) || !ts.isIdentifier(prop.name))
|
|
39
|
+
continue;
|
|
40
|
+
const key = prop.name.text;
|
|
41
|
+
if (key === 'name' && ts.isStringLiteral(prop.initializer)) {
|
|
42
|
+
name = prop.initializer.text;
|
|
43
|
+
}
|
|
44
|
+
else if (key === 'package' && ts.isStringLiteral(prop.initializer)) {
|
|
45
|
+
pkg = prop.initializer.text;
|
|
46
|
+
}
|
|
47
|
+
else if (key === 'rpcEndpoint' && ts.isStringLiteral(prop.initializer)) {
|
|
48
|
+
rpcEndpoint = prop.initializer.text;
|
|
49
|
+
}
|
|
50
|
+
else if (key === 'secretOverrides' &&
|
|
51
|
+
ts.isObjectLiteralExpression(prop.initializer)) {
|
|
52
|
+
secretOverrides = parseStringRecord(prop.initializer);
|
|
53
|
+
}
|
|
54
|
+
else if (key === 'variableOverrides' &&
|
|
55
|
+
ts.isObjectLiteralExpression(prop.initializer)) {
|
|
56
|
+
variableOverrides = parseStringRecord(prop.initializer);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (!name || !pkg)
|
|
60
|
+
return;
|
|
61
|
+
logger.debug(`• Found wireAddon: ${name} → ${pkg}`);
|
|
62
|
+
state.rpc.wireAddonDeclarations.set(name, {
|
|
63
|
+
package: pkg,
|
|
64
|
+
rpcEndpoint,
|
|
65
|
+
secretOverrides,
|
|
66
|
+
variableOverrides,
|
|
67
|
+
});
|
|
68
|
+
state.rpc.usedAddons.add(name);
|
|
69
|
+
state.rpc.wireAddonFiles.add(node.getSourceFile().fileName);
|
|
70
|
+
}
|
package/dist/error-codes.d.ts
CHANGED
|
@@ -31,6 +31,7 @@ export declare enum ErrorCode {
|
|
|
31
31
|
HANDLER_NOT_RESOLVED = "PKU568",
|
|
32
32
|
ROUTE_PARAM_MISMATCH = "PKU571",
|
|
33
33
|
ROUTE_QUERY_MISMATCH = "PKU572",
|
|
34
|
+
AUTH_DISABLED_REQUIRES_SESSIONLESS = "PKU573",
|
|
34
35
|
MIDDLEWARE_HANDLER_INVALID = "PKU685",
|
|
35
36
|
MIDDLEWARE_TAG_INVALID = "PKU715",
|
|
36
37
|
MIDDLEWARE_EMPTY_ARRAY = "PKU736",
|
package/dist/error-codes.js
CHANGED
|
@@ -36,6 +36,7 @@ export var ErrorCode;
|
|
|
36
36
|
// HTTP Route errors
|
|
37
37
|
ErrorCode["ROUTE_PARAM_MISMATCH"] = "PKU571";
|
|
38
38
|
ErrorCode["ROUTE_QUERY_MISMATCH"] = "PKU572";
|
|
39
|
+
ErrorCode["AUTH_DISABLED_REQUIRES_SESSIONLESS"] = "PKU573";
|
|
39
40
|
// Middleware/Permission errors
|
|
40
41
|
ErrorCode["MIDDLEWARE_HANDLER_INVALID"] = "PKU685";
|
|
41
42
|
ErrorCode["MIDDLEWARE_TAG_INVALID"] = "PKU715";
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export type { SerializableInspectorState } from './utils/serialize-inspector-sta
|
|
|
8
8
|
export { filterInspectorState } from './utils/filter-inspector-state.js';
|
|
9
9
|
export { generateCustomTypes, sanitizeTypeName, } from './utils/custom-types-generator.js';
|
|
10
10
|
export { createEmptyManifest, serializeManifest, } from './utils/contract-hashes.js';
|
|
11
|
-
export type { ContractEntry, VersionValidateError, VersionManifest, VersionManifestEntry, } from './utils/contract-hashes.js';
|
|
11
|
+
export type { ContractEntry, VersionHashEntry, VersionValidateError, VersionManifest, VersionManifestEntry, } from './utils/contract-hashes.js';
|
|
12
12
|
export { serializeMCPJson } from './utils/serialize-mcp-json.js';
|
|
13
13
|
export type { OpenAPISpecInfo } from './utils/serialize-openapi-json.js';
|
|
14
14
|
export { deserializeDslWorkflow, deserializeGraphWorkflow, deserializeAllDslWorkflows, } from './utils/workflow/dsl/index.js';
|
package/dist/inspector.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { InspectorState, InspectorLogger, InspectorOptions } from './types.js';
|
|
1
|
+
import type { InspectorState, InspectorLogger, InspectorOptions } from './types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Creates an initial/empty inspector state with all required properties initialized
|
|
4
4
|
* @param rootDir - The root directory for the project
|
package/dist/inspector.js
CHANGED
|
@@ -4,9 +4,9 @@ import { visitSetup, visitRoutes } from './visit.js';
|
|
|
4
4
|
import { TypesMap } from './types-map.js';
|
|
5
5
|
import { getFilesAndMethods } from './utils/get-files-and-methods.js';
|
|
6
6
|
import { findCommonAncestor } from './utils/find-root-dir.js';
|
|
7
|
-
import { aggregateRequiredServices,
|
|
7
|
+
import { aggregateRequiredServices, validateAgentModels, validateAgentOverrides, validateSecretOverrides, validateVariableOverrides, computeResolvedIOTypes, computeMiddlewareGroupsMeta, computePermissionsGroupsMeta, computeRequiredSchemas, computeDiagnostics, } from './utils/post-process.js';
|
|
8
8
|
import { generateOpenAPISpec } from './utils/serialize-openapi-json.js';
|
|
9
|
-
import { pikkuState } from '@pikku/core';
|
|
9
|
+
import { pikkuState } from '@pikku/core/internal';
|
|
10
10
|
import { resolveLatestVersions } from './utils/resolve-versions.js';
|
|
11
11
|
import { finalizeWorkflows } from './utils/workflow/graph/finalize-workflows.js';
|
|
12
12
|
import { finalizeWorkflowHelperTypes, finalizeWorkflowWires, } from './utils/workflow/graph/finalize-workflow-wires.js';
|
|
@@ -83,7 +83,9 @@ export function getInitialInspectorState(rootDir) {
|
|
|
83
83
|
exposedMeta: {},
|
|
84
84
|
exposedFiles: new Map(),
|
|
85
85
|
invokedFunctions: new Set(),
|
|
86
|
-
|
|
86
|
+
usedAddons: new Set(),
|
|
87
|
+
wireAddonDeclarations: new Map(),
|
|
88
|
+
wireAddonFiles: new Set(),
|
|
87
89
|
},
|
|
88
90
|
mcpEndpoints: {
|
|
89
91
|
resourcesMeta: {},
|
|
@@ -238,9 +240,10 @@ export const inspect = async (logger, routeFiles, options = {}) => {
|
|
|
238
240
|
if (options.openAPI) {
|
|
239
241
|
state.openAPISpec = await generateOpenAPISpec(logger, state.functions.meta, state.http.meta, state.schemas, options.openAPI.additionalInfo, pikkuState(null, 'misc', 'errors'));
|
|
240
242
|
}
|
|
241
|
-
validateSecretOverrides(logger, state, options.externalPackages);
|
|
242
243
|
validateAgentModels(logger, state, options.modelConfig);
|
|
243
244
|
validateAgentOverrides(logger, state, options.modelConfig);
|
|
245
|
+
validateSecretOverrides(logger, state);
|
|
246
|
+
validateVariableOverrides(logger, state);
|
|
244
247
|
}
|
|
245
248
|
return state;
|
|
246
249
|
};
|
package/dist/types.d.ts
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import * as ts from 'typescript';
|
|
2
|
-
import { ChannelsMeta } from '@pikku/core/channel';
|
|
3
|
-
import { HTTPWiringsMeta } from '@pikku/core/http';
|
|
4
|
-
import { ScheduledTasksMeta } from '@pikku/core/scheduler';
|
|
5
|
-
import { TriggerMeta, TriggerSourceMeta } from '@pikku/core/trigger';
|
|
6
|
-
import { QueueWorkersMeta } from '@pikku/core/queue';
|
|
7
|
-
import { WorkflowsMeta } from '@pikku/core/workflow';
|
|
8
|
-
import { MCPResourceMeta, MCPToolMeta, MCPPromptMeta } from '@pikku/core/mcp';
|
|
9
|
-
import { AIAgentMeta } from '@pikku/core/ai-agent';
|
|
10
|
-
import { CLIMeta } from '@pikku/core/cli';
|
|
11
|
-
import { NodesMeta } from '@pikku/core/node';
|
|
12
|
-
import { SecretDefinitions } from '@pikku/core/secret';
|
|
13
|
-
import { VariableDefinitions } from '@pikku/core/variable';
|
|
14
|
-
import { TypesMap } from './types-map.js';
|
|
15
|
-
import { FunctionsMeta, FunctionServicesMeta, FunctionWiresMeta, JSONValue } from '@pikku/core';
|
|
1
|
+
import type * as ts from 'typescript';
|
|
2
|
+
import type { ChannelsMeta } from '@pikku/core/channel';
|
|
3
|
+
import type { HTTPWiringsMeta } from '@pikku/core/http';
|
|
4
|
+
import type { ScheduledTasksMeta } from '@pikku/core/scheduler';
|
|
5
|
+
import type { TriggerMeta, TriggerSourceMeta } from '@pikku/core/trigger';
|
|
6
|
+
import type { QueueWorkersMeta } from '@pikku/core/queue';
|
|
7
|
+
import type { WorkflowsMeta } from '@pikku/core/workflow';
|
|
8
|
+
import type { MCPResourceMeta, MCPToolMeta, MCPPromptMeta } from '@pikku/core/mcp';
|
|
9
|
+
import type { AIAgentMeta } from '@pikku/core/ai-agent';
|
|
10
|
+
import type { CLIMeta } from '@pikku/core/cli';
|
|
11
|
+
import type { NodesMeta } from '@pikku/core/node';
|
|
12
|
+
import type { SecretDefinitions } from '@pikku/core/secret';
|
|
13
|
+
import type { VariableDefinitions } from '@pikku/core/variable';
|
|
14
|
+
import type { TypesMap } from './types-map.js';
|
|
15
|
+
import type { FunctionsMeta, FunctionServicesMeta, FunctionWiresMeta, JSONValue } from '@pikku/core';
|
|
16
16
|
import type { OpenAPISpecInfo } from './utils/serialize-openapi-json.js';
|
|
17
|
-
import { ErrorCode } from './error-codes.js';
|
|
17
|
+
import type { ErrorCode } from './error-codes.js';
|
|
18
18
|
import type { VersionManifest, VersionValidateError } from './utils/contract-hashes.js';
|
|
19
19
|
import type { SerializedWorkflowGraphs } from './utils/workflow/graph/workflow-graph.types.js';
|
|
20
20
|
export type PathToNameAndType = Map<string, {
|
|
@@ -138,7 +138,7 @@ export type InspectorFilters = {
|
|
|
138
138
|
httpRoutes?: string[];
|
|
139
139
|
httpMethods?: string[];
|
|
140
140
|
};
|
|
141
|
-
export type
|
|
141
|
+
export type AddonConfig = {
|
|
142
142
|
package: string;
|
|
143
143
|
rpcEndpoint?: string;
|
|
144
144
|
secretOverrides?: Record<string, string>;
|
|
@@ -164,14 +164,13 @@ export type InspectorModelConfig = {
|
|
|
164
164
|
export type InspectorOptions = Partial<{
|
|
165
165
|
setupOnly: boolean;
|
|
166
166
|
rootDir: string;
|
|
167
|
-
|
|
167
|
+
isAddon: boolean;
|
|
168
168
|
types: Partial<{
|
|
169
169
|
configFileType: string;
|
|
170
170
|
userSessionType: string;
|
|
171
171
|
singletonServicesFactoryType: string;
|
|
172
172
|
wireServicesFactoryType: string;
|
|
173
173
|
}>;
|
|
174
|
-
externalPackages: Record<string, ExternalPackageConfig>;
|
|
175
174
|
schemaConfig: {
|
|
176
175
|
tsconfig: string;
|
|
177
176
|
schemasFromTypes?: string[];
|
|
@@ -301,7 +300,14 @@ export interface InspectorState {
|
|
|
301
300
|
exportedName: string;
|
|
302
301
|
}>;
|
|
303
302
|
invokedFunctions: Set<string>;
|
|
304
|
-
|
|
303
|
+
usedAddons: Set<string>;
|
|
304
|
+
wireAddonDeclarations: Map<string, {
|
|
305
|
+
package: string;
|
|
306
|
+
rpcEndpoint?: string;
|
|
307
|
+
secretOverrides?: Record<string, string>;
|
|
308
|
+
variableOverrides?: Record<string, string>;
|
|
309
|
+
}>;
|
|
310
|
+
wireAddonFiles: Set<string>;
|
|
305
311
|
};
|
|
306
312
|
mcpEndpoints: {
|
|
307
313
|
resourcesMeta: MCPResourceMeta;
|
|
@@ -12,7 +12,7 @@ const PRIMITIVE_TYPES = new Set([
|
|
|
12
12
|
export function computeRequiredSchemas(functionsMeta, typesMap, additionalTypes, schemaLookup) {
|
|
13
13
|
return new Set([
|
|
14
14
|
...Object.values(functionsMeta)
|
|
15
|
-
.
|
|
15
|
+
.flatMap(({ inputs, outputs }) => {
|
|
16
16
|
const types = [];
|
|
17
17
|
if (inputs?.[0]) {
|
|
18
18
|
try {
|
|
@@ -32,7 +32,6 @@ export function computeRequiredSchemas(functionsMeta, typesMap, additionalTypes,
|
|
|
32
32
|
}
|
|
33
33
|
return types;
|
|
34
34
|
})
|
|
35
|
-
.flat()
|
|
36
35
|
.filter((s) => !!s && !PRIMITIVE_TYPES.has(s)),
|
|
37
36
|
...typesMap.customTypes.keys(),
|
|
38
37
|
...(additionalTypes || []),
|