@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.
Files changed (38) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/dist/add/add-credential.d.ts +2 -0
  3. package/dist/add/add-credential.js +118 -0
  4. package/dist/add/add-middleware.js +6 -10
  5. package/dist/add/add-permission.js +10 -12
  6. package/dist/add/add-secret.d.ts +1 -3
  7. package/dist/add/add-secret.js +0 -74
  8. package/dist/add/add-workflow.js +7 -1
  9. package/dist/error-codes.d.ts +1 -0
  10. package/dist/error-codes.js +2 -0
  11. package/dist/inspector.js +18 -7
  12. package/dist/types.d.ts +7 -0
  13. package/dist/utils/custom-types-generator.js +1 -0
  14. package/dist/utils/post-process.d.ts +9 -0
  15. package/dist/utils/post-process.js +46 -0
  16. package/dist/utils/schema-generator.js +26 -6
  17. package/dist/utils/serialize-inspector-state.d.ts +4 -0
  18. package/dist/utils/serialize-inspector-state.js +9 -0
  19. package/dist/utils/workflow/graph/convert-dsl-to-graph.js +1 -0
  20. package/dist/utils/workflow/graph/workflow-graph.types.d.ts +2 -0
  21. package/dist/visit.js +3 -2
  22. package/package.json +4 -3
  23. package/src/add/add-credential.ts +178 -0
  24. package/src/add/add-middleware.ts +6 -14
  25. package/src/add/add-permission.ts +10 -16
  26. package/src/add/add-secret.ts +0 -131
  27. package/src/add/add-workflow.ts +11 -1
  28. package/src/error-codes.ts +3 -0
  29. package/src/inspector.ts +25 -6
  30. package/src/types.ts +7 -0
  31. package/src/utils/custom-types-generator.ts +1 -0
  32. package/src/utils/post-process.ts +59 -0
  33. package/src/utils/schema-generator.ts +38 -10
  34. package/src/utils/serialize-inspector-state.ts +13 -0
  35. package/src/utils/workflow/graph/convert-dsl-to-graph.ts +1 -0
  36. package/src/utils/workflow/graph/workflow-graph.types.ts +2 -0
  37. package/src/visit.ts +3 -2
  38. 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
  }
@@ -301,6 +301,7 @@ export function convertDslToGraph(workflowName, meta) {
301
301
  source,
302
302
  description: meta.description,
303
303
  tags: meta.tags,
304
+ inline: meta.inline,
304
305
  context: meta.context,
305
306
  nodes: nodesRecord,
306
307
  entryNodeIds,
@@ -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, addOAuth2Credential } from './add/add-secret.js';
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
- addOAuth2Credential(logger, node, checker, state, options);
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",
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.3",
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
- renameTempDefinitions(state, definitionIds, 'tag', tag)
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
- renameTempDefinitions(state, definitionIds, 'http', pattern)
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 isInsidePermissionFactory(node: ts.Node): boolean {
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 (isInsidePermissionFactory(node)) return
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 (isInsidePermissionFactory(node)) return
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 === 0) {
377
- logger.warn(`• addPermission('${tag}', ...) has empty permissions array`)
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 === 0) {
483
- logger.warn(
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]
@@ -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
- }
@@ -11,7 +11,10 @@ import {
11
11
  extractDescription,
12
12
  extractDuration,
13
13
  } from '../utils/extract-node-value.js'
14
- import { getCommonWireMetaData } from '../utils/get-property-value.js'
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
  }
@@ -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 startProgram = performance.now()
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(2)}ms`
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(2)}ms`
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(2)}ms`
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
  }