@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
|
@@ -16,12 +16,22 @@ import { ErrorCode } from '../error-codes.js'
|
|
|
16
16
|
function makeContracts(
|
|
17
17
|
entries: Record<
|
|
18
18
|
string,
|
|
19
|
-
{
|
|
19
|
+
{
|
|
20
|
+
functionKey: string
|
|
21
|
+
version: number
|
|
22
|
+
contractHash: string
|
|
23
|
+
inputHash?: string
|
|
24
|
+
outputHash?: string
|
|
25
|
+
}
|
|
20
26
|
>
|
|
21
27
|
): Map<string, ContractEntry> {
|
|
22
28
|
const map = new Map<string, ContractEntry>()
|
|
23
29
|
for (const [id, entry] of Object.entries(entries)) {
|
|
24
|
-
map.set(id,
|
|
30
|
+
map.set(id, {
|
|
31
|
+
...entry,
|
|
32
|
+
inputHash: entry.inputHash ?? entry.contractHash.slice(0, 8),
|
|
33
|
+
outputHash: entry.outputHash ?? entry.contractHash.slice(0, 8),
|
|
34
|
+
})
|
|
25
35
|
}
|
|
26
36
|
return map
|
|
27
37
|
}
|
|
@@ -414,11 +424,16 @@ describe('updateManifest', () => {
|
|
|
414
424
|
functionKey: 'createUser',
|
|
415
425
|
version: 1,
|
|
416
426
|
contractHash: 'abc',
|
|
427
|
+
inputHash: 'in123456',
|
|
428
|
+
outputHash: 'out1234',
|
|
417
429
|
},
|
|
418
430
|
})
|
|
419
431
|
const result = updateManifest(manifest, contracts)
|
|
420
432
|
assert.strictEqual(result.contracts.createUser.latest, 1)
|
|
421
|
-
assert.
|
|
433
|
+
assert.deepStrictEqual(result.contracts.createUser.versions['1'], {
|
|
434
|
+
inputHash: 'in123456',
|
|
435
|
+
outputHash: 'out1234',
|
|
436
|
+
})
|
|
422
437
|
})
|
|
423
438
|
|
|
424
439
|
test('adds new version to existing function and updates latest', () => {
|
|
@@ -433,17 +448,27 @@ describe('updateManifest', () => {
|
|
|
433
448
|
functionKey: 'createUser',
|
|
434
449
|
version: 1,
|
|
435
450
|
contractHash: 'aaa',
|
|
451
|
+
inputHash: 'inaaa123',
|
|
452
|
+
outputHash: 'outaaa12',
|
|
436
453
|
},
|
|
437
454
|
'createUser@v2': {
|
|
438
455
|
functionKey: 'createUser',
|
|
439
456
|
version: 2,
|
|
440
457
|
contractHash: 'bbb',
|
|
458
|
+
inputHash: 'inbbb123',
|
|
459
|
+
outputHash: 'outbbb12',
|
|
441
460
|
},
|
|
442
461
|
})
|
|
443
462
|
const result = updateManifest(manifest, contracts)
|
|
444
463
|
assert.strictEqual(result.contracts.createUser.latest, 2)
|
|
445
|
-
assert.
|
|
446
|
-
|
|
464
|
+
assert.deepStrictEqual(result.contracts.createUser.versions['2'], {
|
|
465
|
+
inputHash: 'inbbb123',
|
|
466
|
+
outputHash: 'outbbb12',
|
|
467
|
+
})
|
|
468
|
+
assert.deepStrictEqual(result.contracts.createUser.versions['1'], {
|
|
469
|
+
inputHash: 'inaaa123',
|
|
470
|
+
outputHash: 'outaaa12',
|
|
471
|
+
})
|
|
447
472
|
})
|
|
448
473
|
|
|
449
474
|
test('preserves deleted functions', () => {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { FunctionsMeta, JSONValue
|
|
2
|
-
import {
|
|
1
|
+
import type { FunctionsMeta, JSONValue } from '@pikku/core'
|
|
2
|
+
import { parseVersionedId } from '@pikku/core'
|
|
3
|
+
import type { TypesMap } from '../types-map.js'
|
|
3
4
|
import { ErrorCode } from '../error-codes.js'
|
|
4
5
|
import { canonicalJSON, hashString } from './hash.js'
|
|
5
6
|
|
|
@@ -7,16 +8,34 @@ export type ContractEntry = {
|
|
|
7
8
|
functionKey: string
|
|
8
9
|
version: number
|
|
9
10
|
contractHash: string
|
|
11
|
+
inputHash: string
|
|
12
|
+
outputHash: string
|
|
10
13
|
}
|
|
11
14
|
|
|
12
15
|
export type VersionValidateError = {
|
|
13
16
|
code: ErrorCode
|
|
14
17
|
message: string
|
|
18
|
+
functionKey?: string
|
|
19
|
+
version?: number
|
|
20
|
+
previousHash?: string
|
|
21
|
+
currentHash?: string
|
|
22
|
+
previousInputHash?: string
|
|
23
|
+
currentInputHash?: string
|
|
24
|
+
previousOutputHash?: string
|
|
25
|
+
currentOutputHash?: string
|
|
26
|
+
nextVersion?: number
|
|
27
|
+
latestVersion?: number
|
|
28
|
+
expectedNextVersion?: number
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export type VersionHashEntry = {
|
|
32
|
+
inputHash: string
|
|
33
|
+
outputHash: string
|
|
15
34
|
}
|
|
16
35
|
|
|
17
36
|
export type VersionManifestEntry = {
|
|
18
37
|
latest: number
|
|
19
|
-
versions: Record<string, string>
|
|
38
|
+
versions: Record<string, string | VersionHashEntry>
|
|
20
39
|
}
|
|
21
40
|
|
|
22
41
|
export type VersionManifest = {
|
|
@@ -24,6 +43,10 @@ export type VersionManifest = {
|
|
|
24
43
|
contracts: Record<string, VersionManifestEntry>
|
|
25
44
|
}
|
|
26
45
|
|
|
46
|
+
function isHashEntry(v: string | VersionHashEntry): v is VersionHashEntry {
|
|
47
|
+
return typeof v === 'object'
|
|
48
|
+
}
|
|
49
|
+
|
|
27
50
|
export function createEmptyManifest(): VersionManifest {
|
|
28
51
|
return {
|
|
29
52
|
manifestVersion: 1,
|
|
@@ -36,7 +59,7 @@ export function serializeManifest(manifest: VersionManifest): string {
|
|
|
36
59
|
|
|
37
60
|
for (const key of Object.keys(manifest.contracts).sort()) {
|
|
38
61
|
const entry = manifest.contracts[key]
|
|
39
|
-
const sortedVersions: Record<string, string> = {}
|
|
62
|
+
const sortedVersions: Record<string, string | VersionHashEntry> = {}
|
|
40
63
|
const numericKeys = Object.keys(entry.versions)
|
|
41
64
|
.map(Number)
|
|
42
65
|
.sort((a, b) => a - b)
|
|
@@ -65,6 +88,14 @@ export function computeContractHash(data: {
|
|
|
65
88
|
return hashString(canonicalJSON(data), 16)
|
|
66
89
|
}
|
|
67
90
|
|
|
91
|
+
function computeInputHash(functionKey: string, inputSchema: unknown): string {
|
|
92
|
+
return hashString(canonicalJSON({ functionKey, inputSchema }), 8)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function computeOutputHash(functionKey: string, outputSchema: unknown): string {
|
|
96
|
+
return hashString(canonicalJSON({ functionKey, outputSchema }), 8)
|
|
97
|
+
}
|
|
98
|
+
|
|
68
99
|
function resolveSchema(
|
|
69
100
|
typeNames: string[] | null | undefined,
|
|
70
101
|
allSchemas: Record<string, JSONValue>,
|
|
@@ -120,7 +151,16 @@ export function buildCurrentContracts(
|
|
|
120
151
|
inputSchema,
|
|
121
152
|
outputSchema,
|
|
122
153
|
})
|
|
123
|
-
|
|
154
|
+
const inputHash = computeInputHash(functionKey, inputSchema)
|
|
155
|
+
const outputHash = computeOutputHash(functionKey, outputSchema)
|
|
156
|
+
|
|
157
|
+
result.set(funcId, {
|
|
158
|
+
functionKey,
|
|
159
|
+
version,
|
|
160
|
+
contractHash,
|
|
161
|
+
inputHash,
|
|
162
|
+
outputHash,
|
|
163
|
+
})
|
|
124
164
|
}
|
|
125
165
|
|
|
126
166
|
return result
|
|
@@ -137,6 +177,8 @@ export function computeContractHashes(
|
|
|
137
177
|
const meta = functionsMeta[funcId]
|
|
138
178
|
if (meta) {
|
|
139
179
|
meta.contractHash = entry.contractHash
|
|
180
|
+
meta.inputHash = entry.inputHash
|
|
181
|
+
meta.outputHash = entry.outputHash
|
|
140
182
|
}
|
|
141
183
|
}
|
|
142
184
|
|
|
@@ -155,6 +197,19 @@ function groupByFunctionKey(
|
|
|
155
197
|
return grouped
|
|
156
198
|
}
|
|
157
199
|
|
|
200
|
+
function entryChanged(
|
|
201
|
+
existing: string | VersionHashEntry,
|
|
202
|
+
current: ContractEntry
|
|
203
|
+
): boolean {
|
|
204
|
+
if (isHashEntry(existing)) {
|
|
205
|
+
return (
|
|
206
|
+
existing.inputHash !== current.inputHash ||
|
|
207
|
+
existing.outputHash !== current.outputHash
|
|
208
|
+
)
|
|
209
|
+
}
|
|
210
|
+
return existing !== current.contractHash
|
|
211
|
+
}
|
|
212
|
+
|
|
158
213
|
export function validateContracts(
|
|
159
214
|
manifest: VersionManifest,
|
|
160
215
|
currentContracts: Map<string, ContractEntry>
|
|
@@ -169,15 +224,32 @@ export function validateContracts(
|
|
|
169
224
|
continue
|
|
170
225
|
}
|
|
171
226
|
|
|
172
|
-
for (const
|
|
173
|
-
const
|
|
227
|
+
for (const current of entries) {
|
|
228
|
+
const { version, contractHash, inputHash, outputHash } = current
|
|
229
|
+
const existingEntry = manifestEntry.versions[String(version)]
|
|
174
230
|
|
|
175
|
-
if (
|
|
176
|
-
if (
|
|
231
|
+
if (existingEntry !== undefined) {
|
|
232
|
+
if (entryChanged(existingEntry, current)) {
|
|
177
233
|
reportedKeys.add(`${functionKey}@${version}`)
|
|
234
|
+
const prevInputHash = isHashEntry(existingEntry)
|
|
235
|
+
? existingEntry.inputHash
|
|
236
|
+
: existingEntry
|
|
237
|
+
const prevOutputHash = isHashEntry(existingEntry)
|
|
238
|
+
? existingEntry.outputHash
|
|
239
|
+
: existingEntry
|
|
178
240
|
errors.push({
|
|
179
241
|
code: ErrorCode.FUNCTION_VERSION_MODIFIED,
|
|
180
|
-
message: `Contract for ${functionKey}@v${version} has changed (recorded: ${
|
|
242
|
+
message: `Contract for ${functionKey}@v${version} has changed (recorded: ${isHashEntry(existingEntry) ? `${existingEntry.inputHash}/${existingEntry.outputHash}` : existingEntry}, current: ${contractHash}). Existing versions are immutable.`,
|
|
243
|
+
functionKey,
|
|
244
|
+
version,
|
|
245
|
+
previousHash: isHashEntry(existingEntry)
|
|
246
|
+
? existingEntry.inputHash
|
|
247
|
+
: existingEntry,
|
|
248
|
+
currentHash: contractHash,
|
|
249
|
+
previousInputHash: prevInputHash,
|
|
250
|
+
currentInputHash: inputHash,
|
|
251
|
+
previousOutputHash: prevOutputHash,
|
|
252
|
+
currentOutputHash: outputHash,
|
|
181
253
|
})
|
|
182
254
|
}
|
|
183
255
|
} else {
|
|
@@ -185,11 +257,18 @@ export function validateContracts(
|
|
|
185
257
|
errors.push({
|
|
186
258
|
code: ErrorCode.VERSION_REGRESSION_OR_CONFLICT,
|
|
187
259
|
message: `Version ${version} for ${functionKey} is <= latest (${manifestEntry.latest}) but not recorded. Possible merge conflict.`,
|
|
260
|
+
functionKey,
|
|
261
|
+
version,
|
|
262
|
+
latestVersion: manifestEntry.latest,
|
|
188
263
|
})
|
|
189
264
|
} else if (version > manifestEntry.latest + 1) {
|
|
190
265
|
errors.push({
|
|
191
266
|
code: ErrorCode.VERSION_GAP_NOT_ALLOWED,
|
|
192
267
|
message: `Version ${version} for ${functionKey} skips versions. Latest is ${manifestEntry.latest}, next must be ${manifestEntry.latest + 1}.`,
|
|
268
|
+
functionKey,
|
|
269
|
+
version,
|
|
270
|
+
latestVersion: manifestEntry.latest,
|
|
271
|
+
expectedNextVersion: manifestEntry.latest + 1,
|
|
193
272
|
})
|
|
194
273
|
}
|
|
195
274
|
}
|
|
@@ -199,7 +278,7 @@ export function validateContracts(
|
|
|
199
278
|
for (const [functionKey, manifestEntry] of Object.entries(
|
|
200
279
|
manifest.contracts
|
|
201
280
|
)) {
|
|
202
|
-
const
|
|
281
|
+
const latestEntry = manifestEntry.versions[String(manifestEntry.latest)]
|
|
203
282
|
const currentEntries = grouped.get(functionKey)
|
|
204
283
|
if (!currentEntries) {
|
|
205
284
|
continue
|
|
@@ -210,12 +289,24 @@ export function validateContracts(
|
|
|
210
289
|
)
|
|
211
290
|
if (
|
|
212
291
|
currentLatest &&
|
|
213
|
-
currentLatest
|
|
292
|
+
entryChanged(latestEntry, currentLatest) &&
|
|
214
293
|
!reportedKeys.has(`${functionKey}@${manifestEntry.latest}`)
|
|
215
294
|
) {
|
|
295
|
+
const prevInputHash = isHashEntry(latestEntry)
|
|
296
|
+
? latestEntry.inputHash
|
|
297
|
+
: undefined
|
|
298
|
+
const prevOutputHash = isHashEntry(latestEntry)
|
|
299
|
+
? latestEntry.outputHash
|
|
300
|
+
: undefined
|
|
216
301
|
errors.push({
|
|
217
302
|
code: ErrorCode.CONTRACT_CHANGED_REQUIRES_BUMP,
|
|
218
303
|
message: `Contract for ${functionKey} changed. Set \`version: ${manifestEntry.latest + 1}\` on the function or run 'pikku versions update'.`,
|
|
304
|
+
functionKey,
|
|
305
|
+
previousInputHash: prevInputHash,
|
|
306
|
+
currentInputHash: currentLatest.inputHash,
|
|
307
|
+
previousOutputHash: prevOutputHash,
|
|
308
|
+
currentOutputHash: currentLatest.outputHash,
|
|
309
|
+
nextVersion: manifestEntry.latest + 1,
|
|
219
310
|
})
|
|
220
311
|
}
|
|
221
312
|
}
|
|
@@ -232,6 +323,9 @@ export function validateContracts(
|
|
|
232
323
|
errors.push({
|
|
233
324
|
code: ErrorCode.MANIFEST_INTEGRITY_ERROR,
|
|
234
325
|
message: `Manifest integrity error for ${functionKey}: latest field (${manifestEntry.latest}) inconsistent with version keys (max: ${maxVersion}).`,
|
|
326
|
+
functionKey,
|
|
327
|
+
latestVersion: manifestEntry.latest,
|
|
328
|
+
expectedNextVersion: maxVersion,
|
|
235
329
|
})
|
|
236
330
|
}
|
|
237
331
|
}
|
|
@@ -256,8 +350,8 @@ export function updateManifest(
|
|
|
256
350
|
}
|
|
257
351
|
|
|
258
352
|
const entry = manifest.contracts[functionKey]
|
|
259
|
-
for (const { version,
|
|
260
|
-
entry.versions[String(version)] =
|
|
353
|
+
for (const { version, inputHash, outputHash } of entries) {
|
|
354
|
+
entry.versions[String(version)] = { inputHash, outputHash }
|
|
261
355
|
entry.latest = Math.max(entry.latest, version)
|
|
262
356
|
}
|
|
263
357
|
}
|
|
@@ -283,6 +377,8 @@ export function extractContractsFromMeta(
|
|
|
283
377
|
functionKey,
|
|
284
378
|
version,
|
|
285
379
|
contractHash: meta.contractHash,
|
|
380
|
+
inputHash: meta.inputHash ?? '',
|
|
381
|
+
outputHash: meta.outputHash ?? '',
|
|
286
382
|
})
|
|
287
383
|
}
|
|
288
384
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as ts from 'typescript'
|
|
2
|
-
import { InspectorState } from '../types.js'
|
|
2
|
+
import type { InspectorState } from '../types.js'
|
|
3
3
|
import { funcIdToTypeName } from './extract-function-name.js'
|
|
4
4
|
import { getCommonWireMetaData } from './get-property-value.js'
|
|
5
5
|
import { resolveMiddleware } from './middleware.js'
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { test, describe } from 'node:test'
|
|
2
2
|
import { strict as assert } from 'node:assert'
|
|
3
3
|
import { filterInspectorState } from './filter-inspector-state.js'
|
|
4
|
-
import { InspectorState, InspectorFilters } from '../types.js'
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
SerializableInspectorState,
|
|
8
|
-
} from './serialize-inspector-state.js'
|
|
4
|
+
import type { InspectorState, InspectorFilters } from '../types.js'
|
|
5
|
+
import type { SerializableInspectorState } from './serialize-inspector-state.js'
|
|
6
|
+
import { deserializeInspectorState } from './serialize-inspector-state.js'
|
|
9
7
|
import { readFileSync } from 'node:fs'
|
|
10
8
|
import { fileURLToPath } from 'node:url'
|
|
11
9
|
import { dirname, join } from 'node:path'
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import type {
|
|
2
|
+
InspectorState,
|
|
3
|
+
InspectorFilters,
|
|
4
|
+
InspectorLogger,
|
|
5
|
+
} from '../types.js'
|
|
6
|
+
import type { PikkuWiringTypes } from '@pikku/core'
|
|
7
|
+
import { parseVersionedId } from '@pikku/core'
|
|
3
8
|
import { aggregateRequiredServices } from './post-process.js'
|
|
4
9
|
|
|
5
10
|
// Module-level Set to track warned groups across multiple filter calls
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { test, describe } from 'node:test'
|
|
2
2
|
import { strict as assert } from 'node:assert'
|
|
3
|
-
import { InspectorFilters } from '../types'
|
|
3
|
+
import type { InspectorFilters } from '../types'
|
|
4
4
|
import { matchesFilters, matchesWildcard } from './filter-utils'
|
|
5
5
|
|
|
6
6
|
describe('matchesFilters', () => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { InspectorFilters, InspectorLogger } from '../types.js'
|
|
2
|
-
import { PikkuWiringTypes } from '@pikku/core'
|
|
1
|
+
import type { InspectorFilters, InspectorLogger } from '../types.js'
|
|
2
|
+
import type { PikkuWiringTypes } from '@pikku/core'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Match a value against a pattern with wildcard support
|
package/src/utils/middleware.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as ts from 'typescript'
|
|
2
|
-
import { MiddlewareMetadata } from '@pikku/core'
|
|
2
|
+
import type { MiddlewareMetadata } from '@pikku/core'
|
|
3
3
|
import { extractFunctionName } from './extract-function-name.js'
|
|
4
|
-
import { InspectorState } from '../types.js'
|
|
4
|
+
import type { InspectorState } from '../types.js'
|
|
5
5
|
|
|
6
6
|
export interface MiddlewareRef {
|
|
7
7
|
definitionId: string
|
package/src/utils/permissions.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as ts from 'typescript'
|
|
2
|
-
import { PermissionMetadata } from '@pikku/core'
|
|
2
|
+
import type { PermissionMetadata } from '@pikku/core'
|
|
3
3
|
import { extractFunctionName } from './extract-function-name.js'
|
|
4
|
-
import { InspectorState } from '../types.js'
|
|
4
|
+
import type { InspectorState } from '../types.js'
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Extract permission pikkuFuncIds from an expression (array or object literal)
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type {
|
|
2
2
|
InspectorState,
|
|
3
3
|
InspectorLogger,
|
|
4
4
|
InspectorOptions,
|
|
5
5
|
InspectorModelConfig,
|
|
6
|
-
ExternalPackageConfig,
|
|
7
6
|
MiddlewareGroupMeta,
|
|
8
7
|
InspectorDiagnostic,
|
|
9
8
|
} from '../types.js'
|
|
10
|
-
import {
|
|
9
|
+
import type {
|
|
11
10
|
FunctionServicesMeta,
|
|
12
11
|
MiddlewareMetadata,
|
|
13
12
|
PermissionMetadata,
|
|
@@ -226,22 +225,46 @@ export function aggregateRequiredServices(
|
|
|
226
225
|
|
|
227
226
|
export function validateSecretOverrides(
|
|
228
227
|
logger: InspectorLogger,
|
|
229
|
-
state: InspectorState | Omit<InspectorState, 'typesLookup'
|
|
230
|
-
externalPackages?: Record<string, ExternalPackageConfig>
|
|
228
|
+
state: InspectorState | Omit<InspectorState, 'typesLookup'>
|
|
231
229
|
): void {
|
|
232
|
-
|
|
230
|
+
const { wireAddonDeclarations } = state.rpc
|
|
231
|
+
if (!wireAddonDeclarations || wireAddonDeclarations.size === 0) return
|
|
233
232
|
|
|
234
233
|
const secretNames = new Set(state.secrets.definitions.map((d) => d.name))
|
|
235
234
|
|
|
236
|
-
for (const [namespace,
|
|
237
|
-
if (!
|
|
235
|
+
for (const [namespace, addonDecl] of wireAddonDeclarations.entries()) {
|
|
236
|
+
if (!addonDecl.secretOverrides) continue
|
|
238
237
|
|
|
239
|
-
for (const secretKey of Object.keys(
|
|
238
|
+
for (const secretKey of Object.keys(addonDecl.secretOverrides)) {
|
|
240
239
|
if (!secretNames.has(secretKey)) {
|
|
241
240
|
const availableSecrets = Array.from(secretNames)
|
|
242
241
|
logger.critical(
|
|
243
242
|
ErrorCode.INVALID_VALUE,
|
|
244
|
-
`Secret override '${secretKey}' in
|
|
243
|
+
`Secret override '${secretKey}' in addon '${namespace}' (${addonDecl.package}) does not exist. Available secrets: ${availableSecrets.join(', ') || 'none'}`
|
|
244
|
+
)
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export function validateVariableOverrides(
|
|
251
|
+
logger: InspectorLogger,
|
|
252
|
+
state: InspectorState | Omit<InspectorState, 'typesLookup'>
|
|
253
|
+
): void {
|
|
254
|
+
const { wireAddonDeclarations } = state.rpc
|
|
255
|
+
if (!wireAddonDeclarations || wireAddonDeclarations.size === 0) return
|
|
256
|
+
|
|
257
|
+
const variableNames = new Set(state.variables.definitions.map((d) => d.name))
|
|
258
|
+
|
|
259
|
+
for (const [namespace, addonDecl] of wireAddonDeclarations.entries()) {
|
|
260
|
+
if (!addonDecl.variableOverrides) continue
|
|
261
|
+
|
|
262
|
+
for (const variableKey of Object.keys(addonDecl.variableOverrides)) {
|
|
263
|
+
if (!variableNames.has(variableKey)) {
|
|
264
|
+
const availableVariables = Array.from(variableNames)
|
|
265
|
+
logger.critical(
|
|
266
|
+
ErrorCode.INVALID_VALUE,
|
|
267
|
+
`Variable override '${variableKey}' in addon '${namespace}' (${addonDecl.package}) does not exist. Available variables: ${availableVariables.join(', ') || 'none'}`
|
|
245
268
|
)
|
|
246
269
|
}
|
|
247
270
|
}
|
|
@@ -363,7 +386,7 @@ export function computeRequiredSchemas(
|
|
|
363
386
|
|
|
364
387
|
state.requiredSchemas = new Set<string>([
|
|
365
388
|
...Object.values(functions.meta)
|
|
366
|
-
.
|
|
389
|
+
.flatMap(({ inputs, outputs }) => {
|
|
367
390
|
const types: (string | undefined)[] = []
|
|
368
391
|
if (inputs?.[0]) {
|
|
369
392
|
try {
|
|
@@ -381,7 +404,6 @@ export function computeRequiredSchemas(
|
|
|
381
404
|
}
|
|
382
405
|
return types
|
|
383
406
|
})
|
|
384
|
-
.flat()
|
|
385
407
|
.filter((s): s is string => !!s && !PRIMITIVE_TYPES.has(s)),
|
|
386
408
|
...functions.typesMap.customTypes.keys(),
|
|
387
409
|
...(schemasFromTypes || []),
|
|
@@ -1,21 +1,28 @@
|
|
|
1
1
|
import * as ts from 'typescript'
|
|
2
|
-
import { ExternalPackageConfig } from '../types.js'
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
|
-
* Resolve the
|
|
4
|
+
* Resolve the addon package name from an imported identifier.
|
|
6
5
|
* Checks if the identifier's import module specifier matches any
|
|
7
|
-
* configured
|
|
6
|
+
* configured addon package.
|
|
8
7
|
*
|
|
9
8
|
* This is a general utility — any wire handler that processes a `func`
|
|
10
9
|
* property can use it to detect when the function comes from an
|
|
11
|
-
*
|
|
10
|
+
* addon package.
|
|
12
11
|
*/
|
|
13
|
-
export const
|
|
12
|
+
export const resolveAddonName = (
|
|
14
13
|
identifier: ts.Identifier,
|
|
15
14
|
checker: ts.TypeChecker,
|
|
16
|
-
|
|
15
|
+
wireAddonDeclarations?: Map<
|
|
16
|
+
string,
|
|
17
|
+
{
|
|
18
|
+
package: string
|
|
19
|
+
rpcEndpoint?: string
|
|
20
|
+
secretOverrides?: Record<string, string>
|
|
21
|
+
variableOverrides?: Record<string, string>
|
|
22
|
+
}
|
|
23
|
+
>
|
|
17
24
|
): string | null => {
|
|
18
|
-
if (!
|
|
25
|
+
if (!wireAddonDeclarations || wireAddonDeclarations.size === 0) {
|
|
19
26
|
return null
|
|
20
27
|
}
|
|
21
28
|
|
|
@@ -32,9 +39,9 @@ export const resolveExternalPackageName = (
|
|
|
32
39
|
|
|
33
40
|
const moduleSpecifier = importDecl.moduleSpecifier.text
|
|
34
41
|
|
|
35
|
-
for (const
|
|
36
|
-
if (
|
|
37
|
-
return
|
|
42
|
+
for (const addonDecl of wireAddonDeclarations.values()) {
|
|
43
|
+
if (addonDecl.package === moduleSpecifier) {
|
|
44
|
+
return addonDecl.package
|
|
38
45
|
}
|
|
39
46
|
}
|
|
40
47
|
|
|
@@ -4,11 +4,11 @@ import { createGenerator, RootlessError } from 'ts-json-schema-generator'
|
|
|
4
4
|
import { tsImport } from 'tsx/esm/api'
|
|
5
5
|
import * as z from 'zod'
|
|
6
6
|
import { zodToTs, createAuxiliaryTypeStore } from 'zod-to-ts'
|
|
7
|
-
import { FunctionsMeta, JSONValue } from '@pikku/core'
|
|
8
|
-
import { HTTPWiringsMeta } from '@pikku/core/http'
|
|
9
|
-
import { TypesMap } from '../types-map.js'
|
|
7
|
+
import type { FunctionsMeta, JSONValue } from '@pikku/core'
|
|
8
|
+
import type { HTTPWiringsMeta } from '@pikku/core/http'
|
|
9
|
+
import type { TypesMap } from '../types-map.js'
|
|
10
10
|
import { ErrorCode } from '../error-codes.js'
|
|
11
|
-
import { InspectorLogger, InspectorState, SchemaRef } from '../types.js'
|
|
11
|
+
import type { InspectorLogger, InspectorState, SchemaRef } from '../types.js'
|
|
12
12
|
import { generateCustomTypes } from './custom-types-generator.js'
|
|
13
13
|
|
|
14
14
|
const PRIMITIVE_TYPES = new Set([
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { JSONValue } from '@pikku/core'
|
|
2
|
-
import { InspectorDiagnostic, InspectorState } from '../types.js'
|
|
1
|
+
import type { JSONValue } from '@pikku/core'
|
|
2
|
+
import type { InspectorDiagnostic, InspectorState } from '../types.js'
|
|
3
3
|
import { TypesMap } from '../types-map.js'
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -142,7 +142,19 @@ export interface SerializableInspectorState {
|
|
|
142
142
|
exposedMeta: InspectorState['rpc']['exposedMeta']
|
|
143
143
|
exposedFiles: Array<[string, { path: string; exportedName: string }]>
|
|
144
144
|
invokedFunctions: string[]
|
|
145
|
-
|
|
145
|
+
usedAddons: string[]
|
|
146
|
+
wireAddonDeclarations: Array<
|
|
147
|
+
[
|
|
148
|
+
string,
|
|
149
|
+
{
|
|
150
|
+
package: string
|
|
151
|
+
rpcEndpoint?: string
|
|
152
|
+
secretOverrides?: Record<string, string>
|
|
153
|
+
variableOverrides?: Record<string, string>
|
|
154
|
+
},
|
|
155
|
+
]
|
|
156
|
+
>
|
|
157
|
+
wireAddonFiles: string[]
|
|
146
158
|
}
|
|
147
159
|
mcpEndpoints: {
|
|
148
160
|
resourcesMeta: InspectorState['mcpEndpoints']['resourcesMeta']
|
|
@@ -329,7 +341,11 @@ export function serializeInspectorState(
|
|
|
329
341
|
exposedMeta: state.rpc.exposedMeta,
|
|
330
342
|
exposedFiles: Array.from(state.rpc.exposedFiles.entries()),
|
|
331
343
|
invokedFunctions: Array.from(state.rpc.invokedFunctions),
|
|
332
|
-
|
|
344
|
+
usedAddons: Array.from(state.rpc.usedAddons),
|
|
345
|
+
wireAddonDeclarations: Array.from(
|
|
346
|
+
state.rpc.wireAddonDeclarations.entries()
|
|
347
|
+
),
|
|
348
|
+
wireAddonFiles: Array.from(state.rpc.wireAddonFiles),
|
|
333
349
|
},
|
|
334
350
|
mcpEndpoints: {
|
|
335
351
|
resourcesMeta: state.mcpEndpoints.resourcesMeta,
|
|
@@ -489,7 +505,9 @@ export function deserializeInspectorState(
|
|
|
489
505
|
exposedMeta: data.rpc.exposedMeta,
|
|
490
506
|
exposedFiles: new Map(data.rpc.exposedFiles),
|
|
491
507
|
invokedFunctions: new Set(data.rpc.invokedFunctions),
|
|
492
|
-
|
|
508
|
+
usedAddons: new Set(data.rpc.usedAddons || []),
|
|
509
|
+
wireAddonDeclarations: new Map(data.rpc.wireAddonDeclarations || []),
|
|
510
|
+
wireAddonFiles: new Set(data.rpc.wireAddonFiles || []),
|
|
493
511
|
},
|
|
494
512
|
mcpEndpoints: {
|
|
495
513
|
resourcesMeta: data.mcpEndpoints.resourcesMeta,
|