@pikku/inspector 0.11.2 → 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 +36 -1
- package/OPTIMIZATION-PLAN.md +195 -0
- package/dist/add/add-ai-agent.d.ts +2 -0
- package/dist/add/add-ai-agent.js +314 -0
- package/dist/add/add-channel.js +81 -61
- package/dist/add/add-cli.d.ts +1 -1
- package/dist/add/add-cli.js +42 -19
- 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 -0
- package/dist/add/add-functions.d.ts +1 -1
- package/dist/add/add-functions.js +256 -82
- package/dist/add/add-http-route.d.ts +20 -10
- package/dist/add/add-http-route.js +156 -66
- package/dist/add/add-http-routes.d.ts +5 -0
- package/dist/add/add-http-routes.js +160 -0
- package/dist/add/add-keyed-wiring.d.ts +12 -0
- package/dist/add/add-keyed-wiring.js +97 -0
- package/dist/add/add-mcp-prompt.d.ts +1 -1
- package/dist/add/add-mcp-prompt.js +14 -9
- package/dist/add/add-mcp-resource.d.ts +1 -1
- package/dist/add/add-mcp-resource.js +14 -9
- package/dist/add/add-middleware.d.ts +1 -4
- package/dist/add/add-middleware.js +364 -79
- package/dist/add/add-permission.d.ts +1 -1
- package/dist/add/add-permission.js +152 -40
- package/dist/add/add-queue-worker.d.ts +1 -1
- package/dist/add/add-queue-worker.js +18 -12
- package/dist/add/add-rpc-invocations.d.ts +3 -3
- package/dist/add/add-rpc-invocations.js +24 -10
- package/dist/add/add-schedule.d.ts +1 -1
- package/dist/add/add-schedule.js +11 -5
- package/dist/add/add-secret.d.ts +3 -0
- package/dist/add/add-secret.js +82 -0
- package/dist/add/add-trigger.d.ts +2 -0
- package/dist/add/add-trigger.js +87 -0
- package/dist/add/add-variable.d.ts +1 -0
- package/dist/add/add-variable.js +8 -0
- package/dist/add/add-wire-addon.d.ts +7 -0
- package/dist/add/add-wire-addon.js +70 -0
- package/dist/add/add-workflow-graph.d.ts +3 -2
- package/dist/add/add-workflow-graph.js +143 -406
- package/dist/add/add-workflow.d.ts +1 -1
- package/dist/add/add-workflow.js +6 -4
- package/dist/error-codes.d.ts +15 -1
- package/dist/error-codes.js +20 -1
- package/dist/index.d.ts +9 -8
- package/dist/index.js +5 -4
- package/dist/inspector.d.ts +2 -2
- package/dist/inspector.js +95 -15
- package/dist/schema-generator.d.ts +1 -0
- package/dist/schema-generator.js +1 -0
- package/dist/types-map.js +10 -1
- package/dist/types.d.ts +180 -50
- package/dist/utils/compute-required-schemas.d.ts +4 -0
- package/dist/utils/compute-required-schemas.js +40 -0
- package/dist/utils/contract-hashes.d.ts +52 -0
- package/dist/utils/contract-hashes.js +269 -0
- package/dist/utils/custom-types-generator.d.ts +9 -0
- package/dist/utils/custom-types-generator.js +71 -0
- package/dist/utils/detect-schema-vendor.d.ts +22 -0
- package/dist/utils/detect-schema-vendor.js +76 -0
- package/dist/utils/does-type-extend-core-type.d.ts +1 -1
- package/dist/utils/ensure-function-metadata.d.ts +6 -3
- package/dist/utils/ensure-function-metadata.js +220 -6
- package/dist/utils/extract-function-name.d.ts +5 -16
- package/dist/utils/extract-function-name.js +86 -291
- package/dist/utils/extract-services.d.ts +2 -1
- package/dist/utils/extract-services.js +25 -1
- package/dist/utils/filter-inspector-state.d.ts +1 -1
- package/dist/utils/filter-inspector-state.js +107 -23
- package/dist/utils/filter-utils.d.ts +2 -2
- package/dist/utils/get-files-and-methods.d.ts +1 -1
- package/dist/utils/get-property-value.d.ts +6 -1
- package/dist/utils/get-property-value.js +28 -3
- package/dist/utils/hash.d.ts +2 -0
- package/dist/utils/hash.js +23 -0
- package/dist/utils/middleware.d.ts +9 -32
- package/dist/utils/middleware.js +80 -66
- package/dist/utils/permissions.d.ts +4 -4
- package/dist/utils/permissions.js +10 -10
- package/dist/utils/post-process.d.ts +11 -11
- package/dist/utils/post-process.js +247 -24
- package/dist/utils/resolve-addon-package.d.ts +16 -0
- package/dist/utils/resolve-addon-package.js +34 -0
- package/dist/utils/resolve-function-types.d.ts +6 -0
- package/dist/utils/resolve-function-types.js +29 -0
- package/dist/utils/resolve-identifier.d.ts +10 -0
- package/dist/utils/resolve-identifier.js +36 -0
- package/dist/utils/resolve-versions.d.ts +2 -0
- package/dist/utils/resolve-versions.js +78 -0
- package/dist/utils/schema-generator.d.ts +9 -0
- package/dist/utils/schema-generator.js +209 -0
- package/dist/utils/serialize-inspector-state.d.ts +70 -23
- package/dist/utils/serialize-inspector-state.js +98 -22
- package/dist/utils/serialize-mcp-json.d.ts +2 -0
- package/dist/utils/serialize-mcp-json.js +99 -0
- package/dist/utils/serialize-middleware-groups-meta.d.ts +12 -0
- package/dist/utils/serialize-middleware-groups-meta.js +28 -0
- package/dist/utils/serialize-openapi-json.d.ts +85 -0
- package/dist/utils/serialize-openapi-json.js +151 -0
- package/dist/utils/serialize-permissions-groups-meta.d.ts +6 -0
- package/dist/utils/serialize-permissions-groups-meta.js +31 -0
- package/dist/utils/validate-auth-sessionless.d.ts +3 -0
- package/dist/utils/validate-auth-sessionless.js +14 -0
- package/dist/utils/workflow/dsl/deserialize-dsl-workflow.js +34 -102
- package/dist/utils/workflow/dsl/extract-dsl-workflow.d.ts +1 -1
- package/dist/utils/workflow/dsl/extract-dsl-workflow.js +23 -4
- package/dist/utils/workflow/graph/convert-dsl-to-graph.js +12 -10
- package/dist/utils/workflow/graph/finalize-workflow-wires.d.ts +3 -0
- package/dist/utils/workflow/graph/finalize-workflow-wires.js +276 -0
- package/dist/utils/workflow/graph/finalize-workflows.d.ts +2 -0
- package/dist/utils/workflow/graph/finalize-workflows.js +75 -0
- package/dist/utils/workflow/graph/index.d.ts +2 -0
- package/dist/utils/workflow/graph/index.js +2 -0
- package/dist/utils/workflow/graph/serialize-workflow-graph.d.ts +0 -8
- package/dist/utils/workflow/graph/serialize-workflow-graph.js +1 -3
- package/dist/utils/workflow/graph/workflow-graph.types.d.ts +53 -79
- package/dist/utils/workflow/graph/workflow-graph.types.js +1 -1
- package/dist/visit.d.ts +1 -1
- package/dist/visit.js +13 -6
- package/package.json +14 -4
- package/src/add/add-ai-agent.ts +468 -0
- package/src/add/add-channel.ts +103 -79
- package/src/add/add-cli.ts +68 -24
- 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 -1
- package/src/add/add-functions.ts +349 -103
- package/src/add/add-http-route.ts +263 -89
- package/src/add/add-http-routes.ts +229 -0
- package/src/add/add-keyed-wiring.ts +151 -0
- package/src/add/add-mcp-prompt.ts +27 -16
- package/src/add/add-mcp-resource.ts +28 -16
- package/src/add/add-middleware.ts +482 -80
- package/src/add/add-permission.ts +199 -40
- package/src/add/add-queue-worker.ts +25 -20
- package/src/add/add-rpc-invocations.ts +28 -11
- package/src/add/add-schedule.ts +17 -12
- package/src/add/add-secret.ts +140 -0
- package/src/add/add-trigger.ts +154 -0
- package/src/add/add-variable.ts +9 -0
- package/src/add/add-wire-addon.ts +80 -0
- package/src/add/add-workflow-graph.ts +180 -522
- package/src/add/add-workflow.ts +7 -6
- package/src/error-codes.ts +25 -1
- package/src/index.ts +23 -13
- package/src/inspector.ts +139 -19
- package/src/schema-generator.ts +1 -0
- package/src/types-map.ts +12 -1
- package/src/types.ts +199 -69
- package/src/utils/compute-required-schemas.ts +48 -0
- package/src/utils/contract-hashes.test.ts +553 -0
- package/src/utils/contract-hashes.ts +386 -0
- package/src/utils/custom-types-generator.ts +88 -0
- package/src/utils/detect-schema-vendor.ts +90 -0
- package/src/utils/does-type-extend-core-type.ts +1 -1
- package/src/utils/ensure-function-metadata.ts +325 -8
- package/src/utils/extract-function-name.ts +101 -351
- package/src/utils/extract-services.ts +35 -2
- package/src/utils/filter-inspector-state.test.ts +37 -25
- package/src/utils/filter-inspector-state.ts +146 -32
- 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/get-property-value.ts +42 -4
- package/src/utils/hash.ts +26 -0
- package/src/utils/middleware.test.ts +204 -0
- package/src/utils/middleware.ts +131 -69
- package/src/utils/permissions.test.ts +35 -12
- package/src/utils/permissions.ts +12 -12
- package/src/utils/post-process.ts +306 -44
- package/src/utils/resolve-addon-package.ts +49 -0
- package/src/utils/resolve-function-types.ts +42 -0
- package/src/utils/resolve-identifier.ts +46 -0
- package/src/utils/resolve-versions.test.ts +249 -0
- package/src/utils/resolve-versions.ts +105 -0
- package/src/utils/schema-generator.ts +329 -0
- package/src/utils/serialize-inspector-state.ts +184 -43
- package/src/utils/serialize-mcp-json.ts +145 -0
- package/src/utils/serialize-middleware-groups-meta.ts +33 -0
- package/src/utils/serialize-openapi-json.ts +277 -0
- package/src/utils/serialize-permissions-groups-meta.ts +35 -0
- package/src/utils/test-data/inspector-state.json +69 -66
- package/src/utils/validate-auth-sessionless.ts +29 -0
- package/src/utils/workflow/dsl/deserialize-dsl-workflow.ts +43 -119
- package/src/utils/workflow/dsl/extract-dsl-workflow.ts +26 -6
- package/src/utils/workflow/graph/convert-dsl-to-graph.ts +17 -10
- package/src/utils/workflow/graph/finalize-workflow-wires.ts +310 -0
- package/src/utils/workflow/graph/finalize-workflows.ts +100 -0
- package/src/utils/workflow/graph/index.ts +5 -0
- package/src/utils/workflow/graph/serialize-workflow-graph.ts +1 -8
- package/src/utils/workflow/graph/workflow-graph.types.ts +29 -78
- package/src/visit.ts +19 -7
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/add/add-forge-credential.d.ts +0 -8
- package/dist/add/add-forge-credential.js +0 -77
- package/dist/add/add-forge-node.d.ts +0 -7
- package/dist/add/add-forge-node.js +0 -77
- package/dist/add/add-mcp-tool.d.ts +0 -2
- package/dist/add/add-mcp-tool.js +0 -81
- package/dist/utils/extract-service-metadata.d.ts +0 -19
- package/dist/utils/extract-service-metadata.js +0 -244
- package/dist/utils/write-service-metadata.d.ts +0 -13
- package/dist/utils/write-service-metadata.js +0 -37
- package/src/add/add-forge-credential.ts +0 -119
- package/src/add/add-forge-node.ts +0 -132
- package/src/add/add-mcp-tool.ts +0 -141
- package/src/utils/extract-service-metadata.ts +0 -353
- package/src/utils/write-service-metadata.ts +0 -51
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
export const serializeMCPJson = (logger, state) => {
|
|
2
|
+
const { mcpEndpoints, functions, schemas } = state;
|
|
3
|
+
const { meta: functionsMeta, typesMap } = functions;
|
|
4
|
+
const { resourcesMeta, toolsMeta, promptsMeta } = mcpEndpoints;
|
|
5
|
+
const tools = [];
|
|
6
|
+
const resources = [];
|
|
7
|
+
const prompts = [];
|
|
8
|
+
const loadSchema = (typeName) => {
|
|
9
|
+
if (!typeName ||
|
|
10
|
+
[
|
|
11
|
+
'boolean',
|
|
12
|
+
'string',
|
|
13
|
+
'number',
|
|
14
|
+
'null',
|
|
15
|
+
'undefined',
|
|
16
|
+
'void',
|
|
17
|
+
'unknown',
|
|
18
|
+
'never',
|
|
19
|
+
].includes(typeName)) {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
const uniqueName = typesMap.getUniqueName(typeName);
|
|
23
|
+
if (!uniqueName) {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
const schema = schemas[uniqueName];
|
|
27
|
+
if (!schema) {
|
|
28
|
+
logger.warn(`Serialize MCP: Could not find schema for type: ${uniqueName}`);
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
return schema;
|
|
32
|
+
};
|
|
33
|
+
for (const [name, endpointMeta] of Object.entries(resourcesMeta)) {
|
|
34
|
+
const functionMeta = functionsMeta[endpointMeta.pikkuFuncId];
|
|
35
|
+
if (!functionMeta) {
|
|
36
|
+
logger.warn(`Function ${endpointMeta.pikkuFuncId} not found in functionsMeta. Skipping resource ${name}.`);
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
const inputType = functionMeta.inputs?.[0];
|
|
40
|
+
const outputType = functionMeta.outputs?.[0];
|
|
41
|
+
const parameters = loadSchema(inputType);
|
|
42
|
+
const returns = loadSchema(outputType);
|
|
43
|
+
resources.push({
|
|
44
|
+
uri: name,
|
|
45
|
+
name,
|
|
46
|
+
description: endpointMeta.description,
|
|
47
|
+
...(parameters && { parameters }),
|
|
48
|
+
...(returns && { returns }),
|
|
49
|
+
...(endpointMeta.streaming && { streaming: true }),
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
for (const [name, endpointMeta] of Object.entries(toolsMeta)) {
|
|
53
|
+
const functionMeta = functionsMeta[endpointMeta.pikkuFuncId];
|
|
54
|
+
if (!functionMeta) {
|
|
55
|
+
logger.warn(`Function ${endpointMeta.pikkuFuncId} not found in functionsMeta. Skipping tool ${name}.`);
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
const inputType = functionMeta.inputs?.[0];
|
|
59
|
+
const outputType = functionMeta.outputs?.[0];
|
|
60
|
+
const parameters = loadSchema(inputType);
|
|
61
|
+
const returns = loadSchema(outputType);
|
|
62
|
+
tools.push({
|
|
63
|
+
name,
|
|
64
|
+
description: endpointMeta.description,
|
|
65
|
+
...(parameters && { parameters }),
|
|
66
|
+
...(returns && { returns }),
|
|
67
|
+
...(endpointMeta.streaming && { streaming: true }),
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
for (const [name, endpointMeta] of Object.entries(promptsMeta)) {
|
|
71
|
+
const functionMeta = functionsMeta[endpointMeta.pikkuFuncId];
|
|
72
|
+
if (!functionMeta) {
|
|
73
|
+
logger.warn(`Function ${endpointMeta.pikkuFuncId} not found in functionsMeta. Skipping prompt ${name}.`);
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
const inputType = functionMeta.inputs?.[0];
|
|
77
|
+
const inputSchema = loadSchema(inputType);
|
|
78
|
+
const argumentsArray = [];
|
|
79
|
+
if (inputSchema &&
|
|
80
|
+
typeof inputSchema === 'object' &&
|
|
81
|
+
!(inputSchema instanceof Array)) {
|
|
82
|
+
const properties = inputSchema.properties;
|
|
83
|
+
const required = inputSchema.required || [];
|
|
84
|
+
for (const [propName, propSchema] of Object.entries(properties)) {
|
|
85
|
+
argumentsArray.push({
|
|
86
|
+
name: propName,
|
|
87
|
+
description: propSchema.description || `${propName} parameter`,
|
|
88
|
+
required: required.includes(propName),
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
prompts.push({
|
|
93
|
+
name,
|
|
94
|
+
description: endpointMeta.description,
|
|
95
|
+
arguments: argumentsArray,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
return JSON.stringify({ tools, resources, prompts }, null, 2);
|
|
99
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { InspectorState } from '../types.js';
|
|
2
|
+
export declare const serializeMiddlewareGroupsMeta: (state: InspectorState) => {
|
|
3
|
+
definitions: Record<string, import("../types.js").InspectorMiddlewareDefinition>;
|
|
4
|
+
instances: Record<string, import("../types.js").InspectorMiddlewareInstance>;
|
|
5
|
+
httpGroups: Record<string, any>;
|
|
6
|
+
tagGroups: Record<string, any>;
|
|
7
|
+
channelMiddleware: {
|
|
8
|
+
definitions: Record<string, import("../types.js").InspectorMiddlewareDefinition>;
|
|
9
|
+
instances: Record<string, import("../types.js").InspectorMiddlewareInstance>;
|
|
10
|
+
tagGroups: Record<string, any>;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const serializeGroupMap = (groupMap) => {
|
|
2
|
+
const result = {};
|
|
3
|
+
for (const [key, meta] of groupMap.entries()) {
|
|
4
|
+
result[key] = {
|
|
5
|
+
exportName: meta.exportName,
|
|
6
|
+
sourceFile: meta.sourceFile,
|
|
7
|
+
position: meta.position,
|
|
8
|
+
services: meta.services,
|
|
9
|
+
count: meta.count,
|
|
10
|
+
instanceIds: meta.instanceIds,
|
|
11
|
+
isFactory: meta.isFactory,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
return result;
|
|
15
|
+
};
|
|
16
|
+
export const serializeMiddlewareGroupsMeta = (state) => {
|
|
17
|
+
return {
|
|
18
|
+
definitions: state.middleware.definitions,
|
|
19
|
+
instances: state.middleware.instances,
|
|
20
|
+
httpGroups: serializeGroupMap(state.http.routeMiddleware),
|
|
21
|
+
tagGroups: serializeGroupMap(state.middleware.tagMiddleware),
|
|
22
|
+
channelMiddleware: {
|
|
23
|
+
definitions: state.channelMiddleware.definitions,
|
|
24
|
+
instances: state.channelMiddleware.instances,
|
|
25
|
+
tagGroups: serializeGroupMap(state.channelMiddleware.tagMiddleware),
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { FunctionsMeta } from '@pikku/core';
|
|
2
|
+
import type { HTTPWiringsMeta } from '@pikku/core/http';
|
|
3
|
+
import type { InspectorLogger } from '../types.js';
|
|
4
|
+
interface ErrorDetails {
|
|
5
|
+
status: number;
|
|
6
|
+
message: string;
|
|
7
|
+
}
|
|
8
|
+
interface OpenAPISpec {
|
|
9
|
+
openapi: string;
|
|
10
|
+
info: {
|
|
11
|
+
title: string;
|
|
12
|
+
version: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
termsOfService?: string;
|
|
15
|
+
contact?: {
|
|
16
|
+
name?: string;
|
|
17
|
+
url?: string;
|
|
18
|
+
email?: string;
|
|
19
|
+
};
|
|
20
|
+
license?: {
|
|
21
|
+
name: string;
|
|
22
|
+
url?: string;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
servers: {
|
|
26
|
+
url: string;
|
|
27
|
+
description?: string;
|
|
28
|
+
}[];
|
|
29
|
+
paths: Record<string, any>;
|
|
30
|
+
components: {
|
|
31
|
+
schemas: Record<string, any>;
|
|
32
|
+
responses?: Record<string, any>;
|
|
33
|
+
parameters?: Record<string, any>;
|
|
34
|
+
examples?: Record<string, any>;
|
|
35
|
+
requestBodies?: Record<string, any>;
|
|
36
|
+
headers?: Record<string, any>;
|
|
37
|
+
securitySchemes?: Record<string, any>;
|
|
38
|
+
};
|
|
39
|
+
security?: {
|
|
40
|
+
[key: string]: any[];
|
|
41
|
+
}[];
|
|
42
|
+
tags?: {
|
|
43
|
+
name: string;
|
|
44
|
+
description?: string;
|
|
45
|
+
}[];
|
|
46
|
+
externalDocs?: {
|
|
47
|
+
description?: string;
|
|
48
|
+
url: string;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
export interface OpenAPISpecInfo {
|
|
52
|
+
info: {
|
|
53
|
+
title: string;
|
|
54
|
+
version: string;
|
|
55
|
+
description: string;
|
|
56
|
+
termsOfService?: string;
|
|
57
|
+
contact?: {
|
|
58
|
+
name?: string;
|
|
59
|
+
url?: string;
|
|
60
|
+
email?: string;
|
|
61
|
+
};
|
|
62
|
+
license?: {
|
|
63
|
+
name: string;
|
|
64
|
+
url?: string;
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
servers: {
|
|
68
|
+
url: string;
|
|
69
|
+
description?: string;
|
|
70
|
+
}[];
|
|
71
|
+
tags?: {
|
|
72
|
+
name: string;
|
|
73
|
+
description?: string;
|
|
74
|
+
}[];
|
|
75
|
+
externalDocs?: {
|
|
76
|
+
description?: string;
|
|
77
|
+
url: string;
|
|
78
|
+
};
|
|
79
|
+
securitySchemes?: Record<string, any>;
|
|
80
|
+
security?: {
|
|
81
|
+
[key: string]: any[];
|
|
82
|
+
}[];
|
|
83
|
+
}
|
|
84
|
+
export declare function generateOpenAPISpec(logger: InspectorLogger, functionsMeta: FunctionsMeta, httpMeta: HTTPWiringsMeta, schemas: Record<string, any>, additionalInfo: OpenAPISpecInfo, errors?: Map<any, ErrorDetails>): Promise<OpenAPISpec>;
|
|
85
|
+
export {};
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import _convertSchema from '@openapi-contrib/json-schema-to-openapi-schema';
|
|
2
|
+
const convertSchema = 'default' in _convertSchema ? _convertSchema.default : _convertSchema;
|
|
3
|
+
const getErrorResponseForConstructorName = (constructorName, errors) => {
|
|
4
|
+
const entries = Array.from(errors.entries());
|
|
5
|
+
const foundError = entries.find(([e]) => e.name === constructorName);
|
|
6
|
+
if (foundError) {
|
|
7
|
+
return foundError[1];
|
|
8
|
+
}
|
|
9
|
+
return undefined;
|
|
10
|
+
};
|
|
11
|
+
const convertSchemasToBodyPayloads = async (functionsMeta, routesMeta, schemas) => {
|
|
12
|
+
const requiredSchemas = new Set();
|
|
13
|
+
for (const routeMeta of Object.values(routesMeta)) {
|
|
14
|
+
for (const { inputTypes, pikkuFuncId } of Object.values(routeMeta)) {
|
|
15
|
+
const output = functionsMeta[pikkuFuncId]?.outputs?.[0];
|
|
16
|
+
if (inputTypes?.body) {
|
|
17
|
+
requiredSchemas.add(inputTypes?.body);
|
|
18
|
+
}
|
|
19
|
+
if (output) {
|
|
20
|
+
requiredSchemas.add(output);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const convertedEntries = await Promise.all(Object.entries(schemas).map(async ([key, schema]) => {
|
|
25
|
+
if (requiredSchemas.has(key)) {
|
|
26
|
+
const convertedSchema = await convertSchema(schema, {
|
|
27
|
+
convertUnreferencedDefinitions: false,
|
|
28
|
+
dereference: { circular: 'ignore' },
|
|
29
|
+
});
|
|
30
|
+
return [key, convertedSchema];
|
|
31
|
+
}
|
|
32
|
+
return;
|
|
33
|
+
}));
|
|
34
|
+
return Object.fromEntries(convertedEntries.filter((s) => !!s));
|
|
35
|
+
};
|
|
36
|
+
export async function generateOpenAPISpec(logger, functionsMeta, httpMeta, schemas, additionalInfo, errors) {
|
|
37
|
+
const paths = {};
|
|
38
|
+
const errorsMap = errors ?? new Map();
|
|
39
|
+
for (const routeMeta of Object.values(httpMeta)) {
|
|
40
|
+
for (const meta of Object.values(routeMeta)) {
|
|
41
|
+
const { route, method, inputTypes, pikkuFuncId, params, query, errors, description, tags, } = meta;
|
|
42
|
+
const functionMeta = functionsMeta[pikkuFuncId];
|
|
43
|
+
if (!functionMeta) {
|
|
44
|
+
logger.error(`• No function metadata found for '${pikkuFuncId}' in route '${route}'.`);
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
const output = functionMeta.outputs ? functionMeta.outputs[0] : undefined;
|
|
48
|
+
const path = route.replace(/:(\w+)/g, '{$1}');
|
|
49
|
+
if (!paths[path]) {
|
|
50
|
+
paths[path] = {};
|
|
51
|
+
}
|
|
52
|
+
const responses = {};
|
|
53
|
+
errors?.forEach((error) => {
|
|
54
|
+
const errorResponse = getErrorResponseForConstructorName(error, errorsMap);
|
|
55
|
+
if (errorResponse) {
|
|
56
|
+
responses[errorResponse.status] = {
|
|
57
|
+
description: errorResponse.message,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
const operation = {
|
|
62
|
+
description: description ||
|
|
63
|
+
`This endpoint handles the ${method.toUpperCase()} request for the route ${route}.`,
|
|
64
|
+
tags: tags || [route.split('/')[1] || 'default'],
|
|
65
|
+
parameters: [],
|
|
66
|
+
responses: {
|
|
67
|
+
...responses,
|
|
68
|
+
'200': {
|
|
69
|
+
description: 'Successful response',
|
|
70
|
+
content: output
|
|
71
|
+
? {
|
|
72
|
+
'application/json': {
|
|
73
|
+
schema: typeof output === 'string' &&
|
|
74
|
+
['boolean', 'string', 'number'].includes(output)
|
|
75
|
+
? { type: output }
|
|
76
|
+
: { $ref: `#/components/schemas/${output}` },
|
|
77
|
+
},
|
|
78
|
+
}
|
|
79
|
+
: undefined,
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
const bodyType = inputTypes?.body;
|
|
84
|
+
if (bodyType) {
|
|
85
|
+
operation.requestBody = {
|
|
86
|
+
required: true,
|
|
87
|
+
content: {
|
|
88
|
+
'application/json': {
|
|
89
|
+
schema: typeof bodyType === 'string' &&
|
|
90
|
+
['boolean', 'string', 'number'].includes(bodyType)
|
|
91
|
+
? { type: bodyType }
|
|
92
|
+
: { $ref: `#/components/schemas/${bodyType}` },
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
if (params) {
|
|
98
|
+
operation.parameters = params.map((param) => ({
|
|
99
|
+
name: param,
|
|
100
|
+
in: 'path',
|
|
101
|
+
required: true,
|
|
102
|
+
schema: { type: 'string' },
|
|
103
|
+
}));
|
|
104
|
+
}
|
|
105
|
+
if (query) {
|
|
106
|
+
operation.parameters.push(...query.map((query) => ({
|
|
107
|
+
name: query,
|
|
108
|
+
in: 'query',
|
|
109
|
+
required: false,
|
|
110
|
+
schema: { type: 'string' },
|
|
111
|
+
})));
|
|
112
|
+
}
|
|
113
|
+
paths[path][method] = operation;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return {
|
|
117
|
+
openapi: '3.1.0',
|
|
118
|
+
info: additionalInfo.info,
|
|
119
|
+
servers: additionalInfo.servers,
|
|
120
|
+
paths,
|
|
121
|
+
components: {
|
|
122
|
+
schemas: await convertSchemasToBodyPayloads(functionsMeta, httpMeta, schemas),
|
|
123
|
+
responses: {},
|
|
124
|
+
parameters: {},
|
|
125
|
+
examples: {},
|
|
126
|
+
requestBodies: {},
|
|
127
|
+
headers: {},
|
|
128
|
+
securitySchemes: additionalInfo.securitySchemes || {
|
|
129
|
+
ApiKeyAuth: {
|
|
130
|
+
type: 'apiKey',
|
|
131
|
+
in: 'header',
|
|
132
|
+
name: 'x-api-key',
|
|
133
|
+
},
|
|
134
|
+
BearerAuth: {
|
|
135
|
+
type: 'http',
|
|
136
|
+
scheme: 'bearer',
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
security: additionalInfo.security || [
|
|
141
|
+
{
|
|
142
|
+
ApiKeyAuth: [],
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
BearerAuth: [],
|
|
146
|
+
},
|
|
147
|
+
],
|
|
148
|
+
tags: additionalInfo.tags,
|
|
149
|
+
externalDocs: additionalInfo.externalDocs,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { InspectorState } from '../types.js';
|
|
2
|
+
export declare const serializePermissionsGroupsMeta: (state: InspectorState) => {
|
|
3
|
+
definitions: Record<string, import("../types.js").InspectorPermissionDefinition>;
|
|
4
|
+
httpGroups: Record<string, any>;
|
|
5
|
+
tagGroups: Record<string, any>;
|
|
6
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export const serializePermissionsGroupsMeta = (state) => {
|
|
2
|
+
const httpGroups = {};
|
|
3
|
+
for (const [pattern, meta] of state.http.routePermissions.entries()) {
|
|
4
|
+
httpGroups[pattern] = {
|
|
5
|
+
exportName: meta.exportName,
|
|
6
|
+
sourceFile: meta.sourceFile,
|
|
7
|
+
position: meta.position,
|
|
8
|
+
services: meta.services,
|
|
9
|
+
count: meta.count,
|
|
10
|
+
instanceIds: meta.instanceIds,
|
|
11
|
+
isFactory: meta.isFactory,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
const tagGroups = {};
|
|
15
|
+
for (const [tag, meta] of state.permissions.tagPermissions.entries()) {
|
|
16
|
+
tagGroups[tag] = {
|
|
17
|
+
exportName: meta.exportName,
|
|
18
|
+
sourceFile: meta.sourceFile,
|
|
19
|
+
position: meta.position,
|
|
20
|
+
services: meta.services,
|
|
21
|
+
count: meta.count,
|
|
22
|
+
instanceIds: meta.instanceIds,
|
|
23
|
+
isFactory: meta.isFactory,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
definitions: state.permissions.definitions,
|
|
28
|
+
httpGroups,
|
|
29
|
+
tagGroups,
|
|
30
|
+
};
|
|
31
|
+
};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import * as ts from 'typescript';
|
|
2
|
+
import type { InspectorLogger, InspectorState } from '../types.js';
|
|
3
|
+
export declare function validateAuthSessionless(logger: InspectorLogger, obj: ts.ObjectLiteralExpression, state: InspectorState, funcName: string, wireDescription: string, inheritedAuth?: boolean): boolean;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { getPropertyValue } from './get-property-value.js';
|
|
2
|
+
import { ErrorCode } from '../error-codes.js';
|
|
3
|
+
export function validateAuthSessionless(logger, obj, state, funcName, wireDescription, inheritedAuth) {
|
|
4
|
+
const fnMeta = state.functions.meta[funcName];
|
|
5
|
+
if (!fnMeta)
|
|
6
|
+
return true;
|
|
7
|
+
const routeAuth = getPropertyValue(obj, 'auth');
|
|
8
|
+
const resolvedAuth = routeAuth === true || routeAuth === false ? routeAuth : inheritedAuth;
|
|
9
|
+
if (resolvedAuth === false && fnMeta.sessionless === false) {
|
|
10
|
+
logger.critical(ErrorCode.AUTH_DISABLED_REQUIRES_SESSIONLESS, `${wireDescription} has auth disabled but function '${funcName}' uses pikkuFunc (requires session). Use pikkuSessionlessFunc instead.`);
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
@@ -89,6 +89,15 @@ function valueToCode(value, itemVar) {
|
|
|
89
89
|
if (isTemplateRef(value)) {
|
|
90
90
|
return templateRefToCode(value, itemVar);
|
|
91
91
|
}
|
|
92
|
+
if (Array.isArray(value)) {
|
|
93
|
+
const elements = value.map((v) => valueToCode(v, itemVar));
|
|
94
|
+
return `[${elements.join(', ')}]`;
|
|
95
|
+
}
|
|
96
|
+
if (typeof value === 'object' && value !== null) {
|
|
97
|
+
const entries = Object.entries(value);
|
|
98
|
+
const props = entries.map(([k, v]) => `${k}: ${valueToCode(v, itemVar)}`);
|
|
99
|
+
return `{ ${props.join(', ')} }`;
|
|
100
|
+
}
|
|
92
101
|
return JSON.stringify(value);
|
|
93
102
|
}
|
|
94
103
|
/**
|
|
@@ -626,6 +635,26 @@ function templateRefToGraphCode(tmpl, outputVarToNodeId) {
|
|
|
626
635
|
.replace(/\r/g, '\\r');
|
|
627
636
|
return `template('${templateStr}', [${refs.join(', ')}])`;
|
|
628
637
|
}
|
|
638
|
+
function valueToGraphCode(value, outputVarToNodeId, refTracker) {
|
|
639
|
+
if (isDataRef(value)) {
|
|
640
|
+
refTracker.hasRefs = true;
|
|
641
|
+
return dataRefToGraphRef(value, outputVarToNodeId);
|
|
642
|
+
}
|
|
643
|
+
if (isTemplateRef(value)) {
|
|
644
|
+
refTracker.hasRefs = true;
|
|
645
|
+
return templateRefToGraphCode(value, outputVarToNodeId);
|
|
646
|
+
}
|
|
647
|
+
if (Array.isArray(value)) {
|
|
648
|
+
const elements = value.map((v) => valueToGraphCode(v, outputVarToNodeId, refTracker));
|
|
649
|
+
return `[${elements.join(', ')}]`;
|
|
650
|
+
}
|
|
651
|
+
if (typeof value === 'object' && value !== null) {
|
|
652
|
+
const entries = Object.entries(value);
|
|
653
|
+
const props = entries.map(([k, v]) => `${k}: ${valueToGraphCode(v, outputVarToNodeId, refTracker)}`);
|
|
654
|
+
return `{ ${props.join(', ')} }`;
|
|
655
|
+
}
|
|
656
|
+
return JSON.stringify(value);
|
|
657
|
+
}
|
|
629
658
|
/**
|
|
630
659
|
* Convert input object to graph input code using ref()
|
|
631
660
|
* @param input - The input mapping
|
|
@@ -635,73 +664,15 @@ function inputToGraphCode(input, outputVarToNodeId) {
|
|
|
635
664
|
const entries = Object.entries(input);
|
|
636
665
|
if (entries.length === 0)
|
|
637
666
|
return { hasRefs: false, code: '{}' };
|
|
638
|
-
|
|
667
|
+
const refTracker = { hasRefs: false };
|
|
639
668
|
const lines = entries.map(([key, value]) => {
|
|
640
|
-
|
|
641
|
-
hasRefs = true;
|
|
642
|
-
return ` ${key}: ${dataRefToGraphRef(value, outputVarToNodeId)},`;
|
|
643
|
-
}
|
|
644
|
-
if (isTemplateRef(value)) {
|
|
645
|
-
hasRefs = true;
|
|
646
|
-
return ` ${key}: ${templateRefToGraphCode(value, outputVarToNodeId)},`;
|
|
647
|
-
}
|
|
648
|
-
return ` ${key}: ${JSON.stringify(value)},`;
|
|
669
|
+
return ` ${key}: ${valueToGraphCode(value, outputVarToNodeId, refTracker)},`;
|
|
649
670
|
});
|
|
650
671
|
return {
|
|
651
|
-
hasRefs,
|
|
672
|
+
hasRefs: refTracker.hasRefs,
|
|
652
673
|
code: `{\n${lines.join('\n')}\n }`,
|
|
653
674
|
};
|
|
654
675
|
}
|
|
655
|
-
/**
|
|
656
|
-
* Serialize wires to code
|
|
657
|
-
*/
|
|
658
|
-
function wiresToCode(wires) {
|
|
659
|
-
if (!wires || Object.keys(wires).length === 0)
|
|
660
|
-
return '{}';
|
|
661
|
-
const parts = [];
|
|
662
|
-
if (wires.http && wires.http.length > 0) {
|
|
663
|
-
const httpItems = wires.http.map((h) => `{ route: '${h.route}', method: '${h.method}', startNode: '${h.startNode}' }`);
|
|
664
|
-
parts.push(`http: [${httpItems.join(', ')}]`);
|
|
665
|
-
}
|
|
666
|
-
if (wires.channel && wires.channel.length > 0) {
|
|
667
|
-
const channelItems = wires.channel.map((c) => {
|
|
668
|
-
const channelParts = [`name: '${c.name}'`];
|
|
669
|
-
if (c.onConnect)
|
|
670
|
-
channelParts.push(`onConnect: '${c.onConnect}'`);
|
|
671
|
-
if (c.onDisconnect)
|
|
672
|
-
channelParts.push(`onDisconnect: '${c.onDisconnect}'`);
|
|
673
|
-
if (c.onMessage)
|
|
674
|
-
channelParts.push(`onMessage: '${c.onMessage}'`);
|
|
675
|
-
return `{ ${channelParts.join(', ')} }`;
|
|
676
|
-
});
|
|
677
|
-
parts.push(`channel: [${channelItems.join(', ')}]`);
|
|
678
|
-
}
|
|
679
|
-
if (wires.queue && wires.queue.length > 0) {
|
|
680
|
-
const queueItems = wires.queue.map((q) => `{ name: '${q.name}', startNode: '${q.startNode}' }`);
|
|
681
|
-
parts.push(`queue: [${queueItems.join(', ')}]`);
|
|
682
|
-
}
|
|
683
|
-
if (wires.cli && wires.cli.length > 0) {
|
|
684
|
-
const cliItems = wires.cli.map((c) => `{ command: '${c.command}', startNode: '${c.startNode}' }`);
|
|
685
|
-
parts.push(`cli: [${cliItems.join(', ')}]`);
|
|
686
|
-
}
|
|
687
|
-
if (wires.schedule && wires.schedule.length > 0) {
|
|
688
|
-
const scheduleItems = wires.schedule.map((s) => {
|
|
689
|
-
const scheduleParts = [];
|
|
690
|
-
if (s.cron)
|
|
691
|
-
scheduleParts.push(`cron: '${s.cron}'`);
|
|
692
|
-
if (s.interval)
|
|
693
|
-
scheduleParts.push(`interval: '${s.interval}'`);
|
|
694
|
-
scheduleParts.push(`startNode: '${s.startNode}'`);
|
|
695
|
-
return `{ ${scheduleParts.join(', ')} }`;
|
|
696
|
-
});
|
|
697
|
-
parts.push(`schedule: [${scheduleItems.join(', ')}]`);
|
|
698
|
-
}
|
|
699
|
-
if (wires.trigger && wires.trigger.length > 0) {
|
|
700
|
-
const triggerItems = wires.trigger.map((t) => `{ name: '${t.name}', startNode: '${t.startNode}' }`);
|
|
701
|
-
parts.push(`trigger: [${triggerItems.join(', ')}]`);
|
|
702
|
-
}
|
|
703
|
-
return `{ ${parts.join(', ')} }`;
|
|
704
|
-
}
|
|
705
676
|
/**
|
|
706
677
|
* Check if a node is a flow node (non-RPC control flow)
|
|
707
678
|
*/
|
|
@@ -740,7 +711,7 @@ export function deserializeGraphWorkflow(workflow, options = {}) {
|
|
|
740
711
|
const { pikkuImportPath = '../.pikku/workflow/pikku-workflow-types.gen.js' } = options;
|
|
741
712
|
const lines = [];
|
|
742
713
|
// Import statement
|
|
743
|
-
lines.push(`import { pikkuWorkflowGraph
|
|
714
|
+
lines.push(`import { pikkuWorkflowGraph } from '${pikkuImportPath}'`);
|
|
744
715
|
lines.push('');
|
|
745
716
|
// Add description as comment if present
|
|
746
717
|
if (workflow.description) {
|
|
@@ -811,26 +782,7 @@ export function deserializeGraphWorkflow(workflow, options = {}) {
|
|
|
811
782
|
nodeConfigs.push(` ${nodeId}: {\n ${configParts.join(',\n ')},\n }`);
|
|
812
783
|
}
|
|
813
784
|
}
|
|
814
|
-
//
|
|
815
|
-
const rpcNodeIds = new Set(Object.keys(nodeRpcMap));
|
|
816
|
-
const nodesWithIncomingEdges = new Set();
|
|
817
|
-
for (const [nodeId, node] of Object.entries(workflow.nodes)) {
|
|
818
|
-
if (!rpcNodeIds.has(nodeId))
|
|
819
|
-
continue;
|
|
820
|
-
if ('next' in node && node.next) {
|
|
821
|
-
const nextId = node.next;
|
|
822
|
-
// Follow through flow nodes to find the actual next RPC node
|
|
823
|
-
const actualNextId = flowNodeIds.has(nextId)
|
|
824
|
-
? findNextRpcNode(nextId, workflow.nodes, flowNodeIds)
|
|
825
|
-
: nextId;
|
|
826
|
-
if (actualNextId && rpcNodeIds.has(actualNextId)) {
|
|
827
|
-
nodesWithIncomingEdges.add(actualNextId);
|
|
828
|
-
}
|
|
829
|
-
}
|
|
830
|
-
}
|
|
831
|
-
// Entry node is the first RPC node with no incoming edges
|
|
832
|
-
const entryNode = Object.keys(nodeRpcMap).find((id) => !nodesWithIncomingEdges.has(id));
|
|
833
|
-
// Generate the pikkuWorkflowGraph call
|
|
785
|
+
// Generate the pikkuWorkflowGraph call (builds graph and registers with core)
|
|
834
786
|
lines.push(`export const ${workflow.name} = pikkuWorkflowGraph({`);
|
|
835
787
|
lines.push(` name: '${workflow.name}',`);
|
|
836
788
|
if (workflow.description) {
|
|
@@ -851,12 +803,6 @@ export function deserializeGraphWorkflow(workflow, options = {}) {
|
|
|
851
803
|
else {
|
|
852
804
|
lines.push(` nodes: {},`);
|
|
853
805
|
}
|
|
854
|
-
// Generate wires with api entry point
|
|
855
|
-
if (entryNode) {
|
|
856
|
-
lines.push(` wires: {`);
|
|
857
|
-
lines.push(` api: '${entryNode}',`);
|
|
858
|
-
lines.push(` },`);
|
|
859
|
-
}
|
|
860
806
|
// Generate config (node configurations)
|
|
861
807
|
if (nodeConfigs.length > 0) {
|
|
862
808
|
lines.push(` config: {`);
|
|
@@ -865,20 +811,6 @@ export function deserializeGraphWorkflow(workflow, options = {}) {
|
|
|
865
811
|
}
|
|
866
812
|
lines.push(`})`);
|
|
867
813
|
lines.push('');
|
|
868
|
-
// Always generate wireWorkflow to register the graph workflow
|
|
869
|
-
// (needed for testing even without explicit wires)
|
|
870
|
-
if (workflow.wires && Object.keys(workflow.wires).length > 0) {
|
|
871
|
-
lines.push(`wireWorkflow({`);
|
|
872
|
-
lines.push(` wires: ${wiresToCode(workflow.wires)},`);
|
|
873
|
-
lines.push(` graph: ${workflow.name},`);
|
|
874
|
-
lines.push(`})`);
|
|
875
|
-
}
|
|
876
|
-
else {
|
|
877
|
-
lines.push(`wireWorkflow({`);
|
|
878
|
-
lines.push(` graph: ${workflow.name},`);
|
|
879
|
-
lines.push(`})`);
|
|
880
|
-
}
|
|
881
|
-
lines.push('');
|
|
882
814
|
return lines.join('\n');
|
|
883
815
|
}
|
|
884
816
|
/**
|
|
@@ -1112,6 +1112,25 @@ function extractInputSources(node, context) {
|
|
|
1112
1112
|
}
|
|
1113
1113
|
return Object.keys(inputs).length > 0 ? inputs : undefined;
|
|
1114
1114
|
}
|
|
1115
|
+
function inputSourceToInlineValue(source) {
|
|
1116
|
+
switch (source.from) {
|
|
1117
|
+
case 'literal':
|
|
1118
|
+
return source.value;
|
|
1119
|
+
case 'input':
|
|
1120
|
+
return { $ref: 'trigger', path: source.path };
|
|
1121
|
+
case 'outputVar':
|
|
1122
|
+
return { $ref: source.name, path: source.path };
|
|
1123
|
+
case 'item':
|
|
1124
|
+
return { $ref: '$item', path: source.path };
|
|
1125
|
+
case 'template':
|
|
1126
|
+
return {
|
|
1127
|
+
$template: {
|
|
1128
|
+
parts: source.parts,
|
|
1129
|
+
expressions: source.expressions.map(inputSourceToInlineValue),
|
|
1130
|
+
},
|
|
1131
|
+
};
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1115
1134
|
/**
|
|
1116
1135
|
* Extract a single input source
|
|
1117
1136
|
*/
|
|
@@ -1174,8 +1193,8 @@ function extractInputSource(node, context) {
|
|
|
1174
1193
|
if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name)) {
|
|
1175
1194
|
const propName = prop.name.text;
|
|
1176
1195
|
const propSource = extractInputSource(prop.initializer, context);
|
|
1177
|
-
if (propSource
|
|
1178
|
-
obj[propName] = propSource
|
|
1196
|
+
if (propSource) {
|
|
1197
|
+
obj[propName] = inputSourceToInlineValue(propSource);
|
|
1179
1198
|
}
|
|
1180
1199
|
}
|
|
1181
1200
|
}
|
|
@@ -1186,8 +1205,8 @@ function extractInputSource(node, context) {
|
|
|
1186
1205
|
const arr = [];
|
|
1187
1206
|
for (const elem of node.elements) {
|
|
1188
1207
|
const elemSource = extractInputSource(elem, context);
|
|
1189
|
-
if (elemSource
|
|
1190
|
-
arr.push(elemSource
|
|
1208
|
+
if (elemSource) {
|
|
1209
|
+
arr.push(inputSourceToInlineValue(elemSource));
|
|
1191
1210
|
}
|
|
1192
1211
|
}
|
|
1193
1212
|
return { from: 'literal', value: arr };
|