@pikku/inspector 0.12.3 → 0.12.5
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 +42 -0
- package/dist/add/add-credential.d.ts +2 -0
- package/dist/add/add-credential.js +118 -0
- package/dist/add/add-middleware.js +6 -10
- package/dist/add/add-permission.js +10 -12
- package/dist/add/add-secret.d.ts +1 -3
- package/dist/add/add-secret.js +0 -74
- package/dist/add/add-workflow.js +7 -1
- package/dist/error-codes.d.ts +1 -0
- package/dist/error-codes.js +2 -0
- package/dist/inspector.js +18 -7
- package/dist/types.d.ts +7 -0
- package/dist/utils/custom-types-generator.js +1 -0
- package/dist/utils/post-process.d.ts +9 -0
- package/dist/utils/post-process.js +46 -0
- package/dist/utils/schema-generator.js +26 -6
- package/dist/utils/serialize-inspector-state.d.ts +4 -0
- package/dist/utils/serialize-inspector-state.js +9 -0
- package/dist/utils/workflow/graph/convert-dsl-to-graph.js +1 -0
- package/dist/utils/workflow/graph/workflow-graph.types.d.ts +2 -0
- package/dist/visit.js +3 -2
- package/package.json +4 -3
- package/src/add/add-credential.ts +178 -0
- package/src/add/add-middleware.ts +6 -14
- package/src/add/add-permission.ts +10 -16
- package/src/add/add-secret.ts +0 -131
- package/src/add/add-workflow.ts +11 -1
- package/src/error-codes.ts +3 -0
- package/src/inspector.ts +25 -6
- package/src/types.ts +7 -0
- package/src/utils/custom-types-generator.ts +1 -0
- package/src/utils/post-process.ts +59 -0
- package/src/utils/schema-generator.ts +38 -10
- package/src/utils/serialize-inspector-state.ts +13 -0
- package/src/utils/workflow/graph/convert-dsl-to-graph.ts +1 -0
- package/src/utils/workflow/graph/workflow-graph.types.ts +2 -0
- package/src/visit.ts +3 -2
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -205,6 +205,10 @@ export interface SerializableInspectorState {
|
|
|
205
205
|
definitions: InspectorState['secrets']['definitions'];
|
|
206
206
|
files: string[];
|
|
207
207
|
};
|
|
208
|
+
credentials: {
|
|
209
|
+
definitions: InspectorState['credentials']['definitions'];
|
|
210
|
+
files: string[];
|
|
211
|
+
};
|
|
208
212
|
variables: {
|
|
209
213
|
definitions: InspectorState['variables']['definitions'];
|
|
210
214
|
files: string[];
|
|
@@ -101,6 +101,10 @@ export function serializeInspectorState(state) {
|
|
|
101
101
|
definitions: state.secrets.definitions,
|
|
102
102
|
files: Array.from(state.secrets.files),
|
|
103
103
|
},
|
|
104
|
+
credentials: {
|
|
105
|
+
definitions: state.credentials.definitions,
|
|
106
|
+
files: Array.from(state.credentials.files),
|
|
107
|
+
},
|
|
104
108
|
variables: {
|
|
105
109
|
definitions: state.variables.definitions,
|
|
106
110
|
files: Array.from(state.variables.files),
|
|
@@ -244,6 +248,10 @@ export function deserializeInspectorState(data) {
|
|
|
244
248
|
definitions: data.secrets?.definitions || [],
|
|
245
249
|
files: new Set(data.secrets?.files || []),
|
|
246
250
|
},
|
|
251
|
+
credentials: {
|
|
252
|
+
definitions: data.credentials?.definitions || [],
|
|
253
|
+
files: new Set(data.credentials?.files || []),
|
|
254
|
+
},
|
|
247
255
|
variables: {
|
|
248
256
|
definitions: data.variables?.definitions || [],
|
|
249
257
|
files: new Set(data.variables?.files || []),
|
|
@@ -292,5 +300,6 @@ export function deserializeInspectorState(data) {
|
|
|
292
300
|
openAPISpec: data.openAPISpec || null,
|
|
293
301
|
diagnostics: data.diagnostics || [],
|
|
294
302
|
addonFunctions: data.addonFunctions || {},
|
|
303
|
+
program: null,
|
|
295
304
|
};
|
|
296
305
|
}
|
|
@@ -141,6 +141,8 @@ export interface SerializedWorkflowGraph {
|
|
|
141
141
|
description?: string;
|
|
142
142
|
/** Tags for organization */
|
|
143
143
|
tags?: string[];
|
|
144
|
+
/** If true, workflow always executes inline without queues */
|
|
145
|
+
inline?: boolean;
|
|
144
146
|
/** Workflow context/state variables (from Zod schema) */
|
|
145
147
|
context?: WorkflowContext;
|
|
146
148
|
/** Serialized nodes */
|
package/dist/visit.js
CHANGED
|
@@ -17,7 +17,8 @@ import { addWireAddon } from './add/add-wire-addon.js';
|
|
|
17
17
|
import { addMiddleware } from './add/add-middleware.js';
|
|
18
18
|
import { addPermission } from './add/add-permission.js';
|
|
19
19
|
import { addCLI, addCLIRenderers } from './add/add-cli.js';
|
|
20
|
-
import { addSecret
|
|
20
|
+
import { addSecret } from './add/add-secret.js';
|
|
21
|
+
import { addCredential } from './add/add-credential.js';
|
|
21
22
|
import { addVariable } from './add/add-variable.js';
|
|
22
23
|
import { addWorkflowGraph } from './add/add-workflow-graph.js';
|
|
23
24
|
import { addAIAgent } from './add/add-ai-agent.js';
|
|
@@ -41,7 +42,7 @@ export const visitSetup = (logger, checker, node, state, options) => {
|
|
|
41
42
|
export const visitRoutes = (logger, checker, node, state, options) => {
|
|
42
43
|
addFunctions(logger, node, checker, state, options);
|
|
43
44
|
addSecret(logger, node, checker, state, options);
|
|
44
|
-
|
|
45
|
+
addCredential(logger, node, checker, state, options);
|
|
45
46
|
addVariable(logger, node, checker, state, options);
|
|
46
47
|
addHTTPRoute(logger, node, checker, state, options);
|
|
47
48
|
addHTTPRoutes(logger, node, checker, state, options);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pikku/inspector",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.5",
|
|
4
4
|
"author": "yasser.fadl@gmail.com",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"type": "module",
|
|
@@ -30,11 +30,12 @@
|
|
|
30
30
|
"release": "yarn build && npm test",
|
|
31
31
|
"test": "bash run-tests.sh",
|
|
32
32
|
"test:watch": "bash run-tests.sh --watch",
|
|
33
|
-
"test:coverage": "bash run-tests.sh --coverage"
|
|
33
|
+
"test:coverage": "bash run-tests.sh --coverage",
|
|
34
|
+
"prepublishOnly": "yarn build"
|
|
34
35
|
},
|
|
35
36
|
"dependencies": {
|
|
36
37
|
"@openapi-contrib/json-schema-to-openapi-schema": "^4.3.1",
|
|
37
|
-
"@pikku/core": "^0.12.
|
|
38
|
+
"@pikku/core": "^0.12.10",
|
|
38
39
|
"path-to-regexp": "^8.3.0",
|
|
39
40
|
"ts-json-schema-generator": "^2.5.0",
|
|
40
41
|
"tsx": "^4.21.0",
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import * as ts from 'typescript'
|
|
2
|
+
import {
|
|
3
|
+
getPropertyValue,
|
|
4
|
+
getArrayPropertyValue,
|
|
5
|
+
} from '../utils/get-property-value.js'
|
|
6
|
+
import type { AddWiring } from '../types.js'
|
|
7
|
+
import { ErrorCode } from '../error-codes.js'
|
|
8
|
+
import { detectSchemaVendorOrError } from '../utils/detect-schema-vendor.js'
|
|
9
|
+
|
|
10
|
+
export const addCredential: AddWiring = (
|
|
11
|
+
logger,
|
|
12
|
+
node,
|
|
13
|
+
checker,
|
|
14
|
+
state,
|
|
15
|
+
_options
|
|
16
|
+
) => {
|
|
17
|
+
if (!ts.isCallExpression(node)) {
|
|
18
|
+
return
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const args = node.arguments
|
|
22
|
+
const firstArg = args[0]
|
|
23
|
+
const expression = node.expression
|
|
24
|
+
|
|
25
|
+
if (!ts.isIdentifier(expression) || expression.text !== 'wireCredential') {
|
|
26
|
+
return
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (!firstArg) {
|
|
30
|
+
return
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (ts.isObjectLiteralExpression(firstArg)) {
|
|
34
|
+
const obj = firstArg
|
|
35
|
+
|
|
36
|
+
const nameValue = getPropertyValue(obj, 'name') as string | null
|
|
37
|
+
const displayNameValue = getPropertyValue(obj, 'displayName') as
|
|
38
|
+
| string
|
|
39
|
+
| null
|
|
40
|
+
const descriptionValue = getPropertyValue(obj, 'description') as
|
|
41
|
+
| string
|
|
42
|
+
| null
|
|
43
|
+
const typeValue = getPropertyValue(obj, 'type') as string | null
|
|
44
|
+
|
|
45
|
+
if (!nameValue) {
|
|
46
|
+
logger.critical(
|
|
47
|
+
ErrorCode.MISSING_NAME,
|
|
48
|
+
"Credential is missing the required 'name' property."
|
|
49
|
+
)
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!displayNameValue) {
|
|
54
|
+
logger.critical(
|
|
55
|
+
ErrorCode.MISSING_NAME,
|
|
56
|
+
`Credential '${nameValue}' is missing the required 'displayName' property.`
|
|
57
|
+
)
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (!typeValue || (typeValue !== 'singleton' && typeValue !== 'wire')) {
|
|
62
|
+
logger.critical(
|
|
63
|
+
ErrorCode.MISSING_NAME,
|
|
64
|
+
`Credential '${nameValue}' is missing or has invalid 'type' property. Must be 'singleton' or 'wire'.`
|
|
65
|
+
)
|
|
66
|
+
return
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
let schemaVariableName: string | null = null
|
|
70
|
+
let schemaSourceFile: string | null = null
|
|
71
|
+
let schemaIdentifier: ts.Identifier | null = null
|
|
72
|
+
for (const prop of obj.properties) {
|
|
73
|
+
if (
|
|
74
|
+
ts.isPropertyAssignment(prop) &&
|
|
75
|
+
ts.isIdentifier(prop.name) &&
|
|
76
|
+
prop.name.text === 'schema'
|
|
77
|
+
) {
|
|
78
|
+
if (ts.isIdentifier(prop.initializer)) {
|
|
79
|
+
schemaVariableName = prop.initializer.text
|
|
80
|
+
schemaIdentifier = prop.initializer
|
|
81
|
+
|
|
82
|
+
const symbol = checker.getSymbolAtLocation(prop.initializer)
|
|
83
|
+
if (symbol) {
|
|
84
|
+
const decl = symbol.valueDeclaration || symbol.declarations?.[0]
|
|
85
|
+
if (decl) {
|
|
86
|
+
if (ts.isImportSpecifier(decl)) {
|
|
87
|
+
const aliasedSymbol = checker.getAliasedSymbol(symbol)
|
|
88
|
+
if (aliasedSymbol) {
|
|
89
|
+
const aliasedDecl =
|
|
90
|
+
aliasedSymbol.valueDeclaration ||
|
|
91
|
+
aliasedSymbol.declarations?.[0]
|
|
92
|
+
if (aliasedDecl) {
|
|
93
|
+
schemaSourceFile = aliasedDecl.getSourceFile().fileName
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
} else {
|
|
97
|
+
schemaSourceFile = decl.getSourceFile().fileName
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
break
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
let oauth2: any = undefined
|
|
107
|
+
const oauth2Prop = obj.properties.find(
|
|
108
|
+
(p) =>
|
|
109
|
+
ts.isPropertyAssignment(p) &&
|
|
110
|
+
ts.isIdentifier(p.name) &&
|
|
111
|
+
p.name.text === 'oauth2'
|
|
112
|
+
)
|
|
113
|
+
if (
|
|
114
|
+
oauth2Prop &&
|
|
115
|
+
ts.isPropertyAssignment(oauth2Prop) &&
|
|
116
|
+
ts.isObjectLiteralExpression(oauth2Prop.initializer)
|
|
117
|
+
) {
|
|
118
|
+
const oauth2Obj = oauth2Prop.initializer
|
|
119
|
+
const appCredentialSecretId = getPropertyValue(
|
|
120
|
+
oauth2Obj,
|
|
121
|
+
'appCredentialSecretId'
|
|
122
|
+
) as string | null
|
|
123
|
+
const tokenSecretId = getPropertyValue(oauth2Obj, 'tokenSecretId') as
|
|
124
|
+
| string
|
|
125
|
+
| null
|
|
126
|
+
const authorizationUrl = getPropertyValue(
|
|
127
|
+
oauth2Obj,
|
|
128
|
+
'authorizationUrl'
|
|
129
|
+
) as string | null
|
|
130
|
+
const tokenUrl = getPropertyValue(oauth2Obj, 'tokenUrl') as string | null
|
|
131
|
+
const scopes = getArrayPropertyValue(oauth2Obj, 'scopes')
|
|
132
|
+
const pkce = getPropertyValue(oauth2Obj, 'pkce') as boolean | null
|
|
133
|
+
|
|
134
|
+
if (appCredentialSecretId && authorizationUrl && tokenUrl && scopes) {
|
|
135
|
+
oauth2 = {
|
|
136
|
+
appCredentialSecretId,
|
|
137
|
+
tokenSecretId: tokenSecretId || undefined,
|
|
138
|
+
authorizationUrl,
|
|
139
|
+
tokenUrl,
|
|
140
|
+
scopes,
|
|
141
|
+
pkce: pkce || undefined,
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const sourceFile = node.getSourceFile().fileName
|
|
147
|
+
state.credentials.files.add(sourceFile)
|
|
148
|
+
|
|
149
|
+
let schemaLookupName: string | undefined
|
|
150
|
+
if (schemaVariableName && schemaSourceFile && schemaIdentifier) {
|
|
151
|
+
const vendor = detectSchemaVendorOrError(
|
|
152
|
+
schemaIdentifier,
|
|
153
|
+
checker,
|
|
154
|
+
logger,
|
|
155
|
+
`Credential '${nameValue}'`,
|
|
156
|
+
schemaSourceFile
|
|
157
|
+
)
|
|
158
|
+
if (vendor) {
|
|
159
|
+
schemaLookupName = `CredentialSchema_${nameValue}`
|
|
160
|
+
state.schemaLookup.set(schemaLookupName, {
|
|
161
|
+
variableName: schemaVariableName,
|
|
162
|
+
sourceFile: schemaSourceFile,
|
|
163
|
+
vendor,
|
|
164
|
+
})
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
state.credentials.definitions.push({
|
|
169
|
+
name: nameValue,
|
|
170
|
+
displayName: displayNameValue,
|
|
171
|
+
description: descriptionValue || undefined,
|
|
172
|
+
type: typeValue as 'singleton' | 'wire',
|
|
173
|
+
schema: schemaLookupName,
|
|
174
|
+
oauth2,
|
|
175
|
+
sourceFile,
|
|
176
|
+
})
|
|
177
|
+
}
|
|
178
|
+
}
|
|
@@ -274,13 +274,10 @@ export const addMiddleware: AddWiring = (logger, node, checker, state) => {
|
|
|
274
274
|
state.rootDir
|
|
275
275
|
)
|
|
276
276
|
|
|
277
|
-
if (refs.length === 0) {
|
|
278
|
-
logger.warn(`• addMiddleware('${tag}', ...) has empty middleware array`)
|
|
279
|
-
return
|
|
280
|
-
}
|
|
281
|
-
|
|
282
277
|
const definitionIds = refs.map((r) => r.definitionId)
|
|
283
|
-
|
|
278
|
+
if (definitionIds.length > 0) {
|
|
279
|
+
renameTempDefinitions(state, definitionIds, 'tag', tag)
|
|
280
|
+
}
|
|
284
281
|
|
|
285
282
|
const sourceFile = node.getSourceFile().fileName
|
|
286
283
|
const instanceIds: string[] = []
|
|
@@ -384,15 +381,10 @@ export const addMiddleware: AddWiring = (logger, node, checker, state) => {
|
|
|
384
381
|
state.rootDir
|
|
385
382
|
)
|
|
386
383
|
|
|
387
|
-
if (refs.length === 0) {
|
|
388
|
-
logger.warn(
|
|
389
|
-
`• addHTTPMiddleware('${pattern}', ...) has empty middleware array`
|
|
390
|
-
)
|
|
391
|
-
return
|
|
392
|
-
}
|
|
393
|
-
|
|
394
384
|
const definitionIds = refs.map((r) => r.definitionId)
|
|
395
|
-
|
|
385
|
+
if (definitionIds.length > 0) {
|
|
386
|
+
renameTempDefinitions(state, definitionIds, 'http', pattern)
|
|
387
|
+
}
|
|
396
388
|
|
|
397
389
|
const sourceFile = node.getSourceFile().fileName
|
|
398
390
|
const instanceIds: string[] = []
|
|
@@ -38,13 +38,15 @@ function renameTempDefinitions(
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
function
|
|
41
|
+
function isInsidePermissionContainer(node: ts.Node): boolean {
|
|
42
42
|
let current = node.parent
|
|
43
43
|
while (current) {
|
|
44
44
|
if (
|
|
45
45
|
ts.isCallExpression(current) &&
|
|
46
46
|
ts.isIdentifier(current.expression) &&
|
|
47
|
-
current.expression.text === 'pikkuPermissionFactory'
|
|
47
|
+
(current.expression.text === 'pikkuPermissionFactory' ||
|
|
48
|
+
current.expression.text === 'addPermission' ||
|
|
49
|
+
current.expression.text === 'addHTTPPermission')
|
|
48
50
|
) {
|
|
49
51
|
return true
|
|
50
52
|
}
|
|
@@ -69,7 +71,7 @@ export const addPermission: AddWiring = (logger, node, checker, state) => {
|
|
|
69
71
|
// Handle pikkuPermission(...) - individual permission function definition
|
|
70
72
|
if (expression.text === 'pikkuPermission') {
|
|
71
73
|
// Skip if nested inside pikkuPermissionFactory — the factory handler extracts services itself
|
|
72
|
-
if (
|
|
74
|
+
if (isInsidePermissionContainer(node)) return
|
|
73
75
|
|
|
74
76
|
const arg = args[0]
|
|
75
77
|
if (!arg) return
|
|
@@ -156,7 +158,7 @@ export const addPermission: AddWiring = (logger, node, checker, state) => {
|
|
|
156
158
|
}
|
|
157
159
|
|
|
158
160
|
if (expression.text === 'pikkuAuth') {
|
|
159
|
-
if (
|
|
161
|
+
if (isInsidePermissionContainer(node)) return
|
|
160
162
|
|
|
161
163
|
const arg = args[0]
|
|
162
164
|
if (!arg) return
|
|
@@ -373,13 +375,10 @@ export const addPermission: AddWiring = (logger, node, checker, state) => {
|
|
|
373
375
|
state.rootDir
|
|
374
376
|
)
|
|
375
377
|
|
|
376
|
-
if (permissionNames.length
|
|
377
|
-
|
|
378
|
-
return
|
|
378
|
+
if (permissionNames.length > 0) {
|
|
379
|
+
renameTempDefinitions(state, permissionNames, 'tag', tag)
|
|
379
380
|
}
|
|
380
381
|
|
|
381
|
-
renameTempDefinitions(state, permissionNames, 'tag', tag)
|
|
382
|
-
|
|
383
382
|
const allServices = new Set<string>()
|
|
384
383
|
for (const permissionName of permissionNames) {
|
|
385
384
|
const permissionMeta = state.permissions.definitions[permissionName]
|
|
@@ -479,15 +478,10 @@ export const addPermission: AddWiring = (logger, node, checker, state) => {
|
|
|
479
478
|
state.rootDir
|
|
480
479
|
)
|
|
481
480
|
|
|
482
|
-
if (permissionNames.length
|
|
483
|
-
|
|
484
|
-
`• addHTTPPermission('${pattern}', ...) has empty permissions array`
|
|
485
|
-
)
|
|
486
|
-
return
|
|
481
|
+
if (permissionNames.length > 0) {
|
|
482
|
+
renameTempDefinitions(state, permissionNames, 'http', pattern)
|
|
487
483
|
}
|
|
488
484
|
|
|
489
|
-
renameTempDefinitions(state, permissionNames, 'http', pattern)
|
|
490
|
-
|
|
491
485
|
const allServices = new Set<string>()
|
|
492
486
|
for (const permissionName of permissionNames) {
|
|
493
487
|
const permissionMeta = state.permissions.definitions[permissionName]
|
package/src/add/add-secret.ts
CHANGED
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
import * as ts from 'typescript'
|
|
2
|
-
import {
|
|
3
|
-
getPropertyValue,
|
|
4
|
-
getArrayPropertyValue,
|
|
5
|
-
} from '../utils/get-property-value.js'
|
|
6
|
-
import type { AddWiring } from '../types.js'
|
|
7
|
-
import { ErrorCode } from '../error-codes.js'
|
|
8
1
|
import { createAddKeyedWiring } from './add-keyed-wiring.js'
|
|
9
2
|
|
|
10
3
|
export const addSecret = createAddKeyedWiring({
|
|
@@ -14,127 +7,3 @@ export const addSecret = createAddKeyedWiring({
|
|
|
14
7
|
schemaPrefix: 'SecretSchema',
|
|
15
8
|
getState: (state) => state.secrets,
|
|
16
9
|
})
|
|
17
|
-
|
|
18
|
-
export const addOAuth2Credential: AddWiring = (
|
|
19
|
-
logger,
|
|
20
|
-
node,
|
|
21
|
-
_checker,
|
|
22
|
-
state,
|
|
23
|
-
_options
|
|
24
|
-
) => {
|
|
25
|
-
if (!ts.isCallExpression(node)) {
|
|
26
|
-
return
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const args = node.arguments
|
|
30
|
-
const firstArg = args[0]
|
|
31
|
-
const expression = node.expression
|
|
32
|
-
|
|
33
|
-
if (
|
|
34
|
-
!ts.isIdentifier(expression) ||
|
|
35
|
-
expression.text !== 'wireOAuth2Credential'
|
|
36
|
-
) {
|
|
37
|
-
return
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if (!firstArg) {
|
|
41
|
-
return
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (ts.isObjectLiteralExpression(firstArg)) {
|
|
45
|
-
const obj = firstArg
|
|
46
|
-
|
|
47
|
-
const nameValue = getPropertyValue(obj, 'name') as string | null
|
|
48
|
-
const displayNameValue = getPropertyValue(obj, 'displayName') as
|
|
49
|
-
| string
|
|
50
|
-
| null
|
|
51
|
-
const descriptionValue = getPropertyValue(obj, 'description') as
|
|
52
|
-
| string
|
|
53
|
-
| null
|
|
54
|
-
const secretIdValue = getPropertyValue(obj, 'secretId') as string | null
|
|
55
|
-
const tokenSecretIdValue = getPropertyValue(obj, 'tokenSecretId') as
|
|
56
|
-
| string
|
|
57
|
-
| null
|
|
58
|
-
const authorizationUrlValue = getPropertyValue(obj, 'authorizationUrl') as
|
|
59
|
-
| string
|
|
60
|
-
| null
|
|
61
|
-
const tokenUrlValue = getPropertyValue(obj, 'tokenUrl') as string | null
|
|
62
|
-
const scopesValue = getArrayPropertyValue(obj, 'scopes')
|
|
63
|
-
const pkceValue = getPropertyValue(obj, 'pkce') as boolean | null
|
|
64
|
-
|
|
65
|
-
if (!nameValue) {
|
|
66
|
-
logger.critical(
|
|
67
|
-
ErrorCode.MISSING_NAME,
|
|
68
|
-
"OAuth2 Credential is missing the required 'name' property."
|
|
69
|
-
)
|
|
70
|
-
return
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
if (!displayNameValue) {
|
|
74
|
-
logger.critical(
|
|
75
|
-
ErrorCode.MISSING_NAME,
|
|
76
|
-
`OAuth2 Credential '${nameValue}' is missing the required 'displayName' property.`
|
|
77
|
-
)
|
|
78
|
-
return
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (!secretIdValue) {
|
|
82
|
-
logger.critical(
|
|
83
|
-
ErrorCode.MISSING_NAME,
|
|
84
|
-
`OAuth2 Credential '${nameValue}' is missing the required 'secretId' property.`
|
|
85
|
-
)
|
|
86
|
-
return
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
if (!tokenSecretIdValue) {
|
|
90
|
-
logger.critical(
|
|
91
|
-
ErrorCode.MISSING_NAME,
|
|
92
|
-
`OAuth2 Credential '${nameValue}' is missing the required 'tokenSecretId' property.`
|
|
93
|
-
)
|
|
94
|
-
return
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
if (!authorizationUrlValue) {
|
|
98
|
-
logger.critical(
|
|
99
|
-
ErrorCode.MISSING_NAME,
|
|
100
|
-
`OAuth2 Credential '${nameValue}' is missing the required 'authorizationUrl' property.`
|
|
101
|
-
)
|
|
102
|
-
return
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (!tokenUrlValue) {
|
|
106
|
-
logger.critical(
|
|
107
|
-
ErrorCode.MISSING_NAME,
|
|
108
|
-
`OAuth2 Credential '${nameValue}' is missing the required 'tokenUrl' property.`
|
|
109
|
-
)
|
|
110
|
-
return
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (!scopesValue || scopesValue.length === 0) {
|
|
114
|
-
logger.critical(
|
|
115
|
-
ErrorCode.MISSING_NAME,
|
|
116
|
-
`OAuth2 Credential '${nameValue}' is missing the required 'scopes' property.`
|
|
117
|
-
)
|
|
118
|
-
return
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
const sourceFile = node.getSourceFile().fileName
|
|
122
|
-
|
|
123
|
-
state.secrets.files.add(sourceFile)
|
|
124
|
-
|
|
125
|
-
state.secrets.definitions.push({
|
|
126
|
-
name: nameValue,
|
|
127
|
-
displayName: displayNameValue,
|
|
128
|
-
description: descriptionValue || undefined,
|
|
129
|
-
secretId: secretIdValue,
|
|
130
|
-
oauth2: {
|
|
131
|
-
tokenSecretId: tokenSecretIdValue,
|
|
132
|
-
authorizationUrl: authorizationUrlValue,
|
|
133
|
-
tokenUrl: tokenUrlValue,
|
|
134
|
-
scopes: scopesValue,
|
|
135
|
-
pkce: pkceValue || undefined,
|
|
136
|
-
},
|
|
137
|
-
sourceFile,
|
|
138
|
-
})
|
|
139
|
-
}
|
|
140
|
-
}
|
package/src/add/add-workflow.ts
CHANGED
|
@@ -11,7 +11,10 @@ import {
|
|
|
11
11
|
extractDescription,
|
|
12
12
|
extractDuration,
|
|
13
13
|
} from '../utils/extract-node-value.js'
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
getCommonWireMetaData,
|
|
16
|
+
getPropertyValue,
|
|
17
|
+
} from '../utils/get-property-value.js'
|
|
15
18
|
import { extractDSLWorkflow } from '../utils/workflow/dsl/extract-dsl-workflow.js'
|
|
16
19
|
|
|
17
20
|
/**
|
|
@@ -206,6 +209,7 @@ export const addWorkflow: AddWiring = (logger, node, checker, state) => {
|
|
|
206
209
|
let summary: string | undefined
|
|
207
210
|
let description: string | undefined
|
|
208
211
|
let errors: string[] | undefined
|
|
212
|
+
let inline: boolean | undefined
|
|
209
213
|
|
|
210
214
|
if (ts.isObjectLiteralExpression(firstArg)) {
|
|
211
215
|
const metadata = getCommonWireMetaData(
|
|
@@ -219,6 +223,11 @@ export const addWorkflow: AddWiring = (logger, node, checker, state) => {
|
|
|
219
223
|
summary = metadata.summary
|
|
220
224
|
description = metadata.description
|
|
221
225
|
errors = metadata.errors
|
|
226
|
+
|
|
227
|
+
const inlineProp = getPropertyValue(firstArg, 'inline')
|
|
228
|
+
if (inlineProp === true) {
|
|
229
|
+
inline = true
|
|
230
|
+
}
|
|
222
231
|
}
|
|
223
232
|
|
|
224
233
|
// Validate that we got a valid function
|
|
@@ -324,5 +333,6 @@ export const addWorkflow: AddWiring = (logger, node, checker, state) => {
|
|
|
324
333
|
description,
|
|
325
334
|
errors,
|
|
326
335
|
tags,
|
|
336
|
+
inline,
|
|
327
337
|
}
|
|
328
338
|
}
|
package/src/error-codes.ts
CHANGED
|
@@ -66,6 +66,9 @@ export enum ErrorCode {
|
|
|
66
66
|
MISSING_MODEL = 'PKU145',
|
|
67
67
|
INVALID_MODEL = 'PKU146',
|
|
68
68
|
|
|
69
|
+
// File structure errors
|
|
70
|
+
SCHEMA_AND_WIRING_COLOCATED = 'PKU490',
|
|
71
|
+
|
|
69
72
|
// Optimization diagnostics
|
|
70
73
|
SERVICES_NOT_DESTRUCTURED = 'PKU410',
|
|
71
74
|
WIRES_NOT_DESTRUCTURED = 'PKU411',
|
package/src/inspector.ts
CHANGED
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
computePermissionsGroupsMeta,
|
|
21
21
|
computeRequiredSchemas,
|
|
22
22
|
computeDiagnostics,
|
|
23
|
+
validateSchemaWiringSeparation,
|
|
23
24
|
} from './utils/post-process.js'
|
|
24
25
|
import { generateOpenAPISpec } from './utils/serialize-openapi-json.js'
|
|
25
26
|
import { pikkuState } from '@pikku/core/internal'
|
|
@@ -147,6 +148,10 @@ export function getInitialInspectorState(rootDir: string): InspectorState {
|
|
|
147
148
|
definitions: [],
|
|
148
149
|
files: new Set(),
|
|
149
150
|
},
|
|
151
|
+
credentials: {
|
|
152
|
+
definitions: [],
|
|
153
|
+
files: new Set(),
|
|
154
|
+
},
|
|
150
155
|
variables: {
|
|
151
156
|
definitions: [],
|
|
152
157
|
files: new Set(),
|
|
@@ -203,6 +208,7 @@ export function getInitialInspectorState(rootDir: string): InspectorState {
|
|
|
203
208
|
openAPISpec: null,
|
|
204
209
|
diagnostics: [],
|
|
205
210
|
addonFunctions: {},
|
|
211
|
+
program: null,
|
|
206
212
|
}
|
|
207
213
|
}
|
|
208
214
|
|
|
@@ -211,8 +217,7 @@ export const inspect = async (
|
|
|
211
217
|
routeFiles: string[],
|
|
212
218
|
options: InspectorOptions = {}
|
|
213
219
|
): Promise<InspectorState> => {
|
|
214
|
-
const
|
|
215
|
-
const program = ts.createProgram(routeFiles, {
|
|
220
|
+
const compilerOptions: ts.CompilerOptions = {
|
|
216
221
|
target: ts.ScriptTarget.ESNext,
|
|
217
222
|
module: ts.ModuleKind.Node16,
|
|
218
223
|
skipLibCheck: true,
|
|
@@ -221,9 +226,16 @@ export const inspect = async (
|
|
|
221
226
|
types: [],
|
|
222
227
|
allowJs: false,
|
|
223
228
|
checkJs: false,
|
|
224
|
-
}
|
|
229
|
+
}
|
|
230
|
+
const startProgram = performance.now()
|
|
231
|
+
const program = ts.createProgram(
|
|
232
|
+
routeFiles,
|
|
233
|
+
compilerOptions,
|
|
234
|
+
undefined, // host
|
|
235
|
+
options.oldProgram
|
|
236
|
+
)
|
|
225
237
|
logger.debug(
|
|
226
|
-
`Created program in ${(performance.now() - startProgram).toFixed(
|
|
238
|
+
`Created program in ${(performance.now() - startProgram).toFixed(0)}ms (${routeFiles.length} files${options.oldProgram ? ', incremental' : ''})`
|
|
227
239
|
)
|
|
228
240
|
|
|
229
241
|
const startChecker = performance.now()
|
|
@@ -255,7 +267,7 @@ export const inspect = async (
|
|
|
255
267
|
)
|
|
256
268
|
}
|
|
257
269
|
logger.debug(
|
|
258
|
-
`Visit setup phase completed in ${(performance.now() - startSetup).toFixed(
|
|
270
|
+
`Visit setup phase completed in ${(performance.now() - startSetup).toFixed(0)}ms`
|
|
259
271
|
)
|
|
260
272
|
|
|
261
273
|
// Load addon function metadata so wirings can reference addon functions
|
|
@@ -270,17 +282,21 @@ export const inspect = async (
|
|
|
270
282
|
)
|
|
271
283
|
}
|
|
272
284
|
logger.debug(
|
|
273
|
-
`Visit routes phase completed in ${(performance.now() - startRoutes).toFixed(
|
|
285
|
+
`Visit routes phase completed in ${(performance.now() - startRoutes).toFixed(0)}ms`
|
|
274
286
|
)
|
|
275
287
|
|
|
276
288
|
resolveLatestVersions(state, logger)
|
|
277
289
|
|
|
278
290
|
if (options.schemaConfig) {
|
|
291
|
+
const startSchemas = performance.now()
|
|
279
292
|
state.schemas = await generateAllSchemas(
|
|
280
293
|
logger,
|
|
281
294
|
options.schemaConfig,
|
|
282
295
|
state
|
|
283
296
|
)
|
|
297
|
+
logger.debug(
|
|
298
|
+
`generateAllSchemas took ${(performance.now() - startSchemas).toFixed(0)}ms`
|
|
299
|
+
)
|
|
284
300
|
computeContractHashes(
|
|
285
301
|
state.schemas,
|
|
286
302
|
state.functions.typesMap,
|
|
@@ -323,6 +339,7 @@ export const inspect = async (
|
|
|
323
339
|
computeMiddlewareGroupsMeta(state)
|
|
324
340
|
computePermissionsGroupsMeta(state)
|
|
325
341
|
computeDiagnostics(state)
|
|
342
|
+
validateSchemaWiringSeparation(logger, state)
|
|
326
343
|
|
|
327
344
|
if (options.openAPI) {
|
|
328
345
|
state.openAPISpec = await generateOpenAPISpec(
|
|
@@ -341,5 +358,7 @@ export const inspect = async (
|
|
|
341
358
|
validateVariableOverrides(logger, state)
|
|
342
359
|
}
|
|
343
360
|
|
|
361
|
+
state.program = program
|
|
362
|
+
|
|
344
363
|
return state
|
|
345
364
|
}
|