@pikku/inspector 0.12.0 → 0.12.2
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 +34 -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 +14 -0
- package/dist/add/add-cli.d.ts +1 -1
- package/dist/add/add-cli.js +29 -8
- 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-gateway.d.ts +2 -0
- package/dist/add/add-gateway.js +57 -0
- 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 +11 -4
- package/dist/types.d.ts +31 -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 +17 -3
- package/dist/utils/serialize-inspector-state.js +14 -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 +4 -0
- package/package.json +3 -3
- package/src/add/add-ai-agent.ts +2 -2
- package/src/add/add-channel.ts +17 -0
- package/src/add/add-cli.ts +53 -15
- 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-gateway.ts +95 -0
- 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 +17 -5
- package/src/types.ts +38 -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 +35 -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 +9 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/utils/resolve-external-package.d.ts +0 -12
|
@@ -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
|
/**
|
|
@@ -116,6 +116,10 @@ export interface SerializableInspectorState {
|
|
|
116
116
|
files: string[]
|
|
117
117
|
meta: InspectorState['channels']['meta']
|
|
118
118
|
}
|
|
119
|
+
gateways: {
|
|
120
|
+
meta: InspectorState['gateways']['meta']
|
|
121
|
+
files: string[]
|
|
122
|
+
}
|
|
119
123
|
triggers: {
|
|
120
124
|
meta: InspectorState['triggers']['meta']
|
|
121
125
|
sourceMeta: InspectorState['triggers']['sourceMeta']
|
|
@@ -142,7 +146,19 @@ export interface SerializableInspectorState {
|
|
|
142
146
|
exposedMeta: InspectorState['rpc']['exposedMeta']
|
|
143
147
|
exposedFiles: Array<[string, { path: string; exportedName: string }]>
|
|
144
148
|
invokedFunctions: string[]
|
|
145
|
-
|
|
149
|
+
usedAddons: string[]
|
|
150
|
+
wireAddonDeclarations: Array<
|
|
151
|
+
[
|
|
152
|
+
string,
|
|
153
|
+
{
|
|
154
|
+
package: string
|
|
155
|
+
rpcEndpoint?: string
|
|
156
|
+
secretOverrides?: Record<string, string>
|
|
157
|
+
variableOverrides?: Record<string, string>
|
|
158
|
+
},
|
|
159
|
+
]
|
|
160
|
+
>
|
|
161
|
+
wireAddonFiles: string[]
|
|
146
162
|
}
|
|
147
163
|
mcpEndpoints: {
|
|
148
164
|
resourcesMeta: InspectorState['mcpEndpoints']['resourcesMeta']
|
|
@@ -303,6 +319,10 @@ export function serializeInspectorState(
|
|
|
303
319
|
files: Array.from(state.channels.files),
|
|
304
320
|
meta: state.channels.meta,
|
|
305
321
|
},
|
|
322
|
+
gateways: {
|
|
323
|
+
meta: state.gateways.meta,
|
|
324
|
+
files: Array.from(state.gateways.files),
|
|
325
|
+
},
|
|
306
326
|
triggers: {
|
|
307
327
|
meta: state.triggers.meta,
|
|
308
328
|
sourceMeta: state.triggers.sourceMeta,
|
|
@@ -329,7 +349,11 @@ export function serializeInspectorState(
|
|
|
329
349
|
exposedMeta: state.rpc.exposedMeta,
|
|
330
350
|
exposedFiles: Array.from(state.rpc.exposedFiles.entries()),
|
|
331
351
|
invokedFunctions: Array.from(state.rpc.invokedFunctions),
|
|
332
|
-
|
|
352
|
+
usedAddons: Array.from(state.rpc.usedAddons),
|
|
353
|
+
wireAddonDeclarations: Array.from(
|
|
354
|
+
state.rpc.wireAddonDeclarations.entries()
|
|
355
|
+
),
|
|
356
|
+
wireAddonFiles: Array.from(state.rpc.wireAddonFiles),
|
|
333
357
|
},
|
|
334
358
|
mcpEndpoints: {
|
|
335
359
|
resourcesMeta: state.mcpEndpoints.resourcesMeta,
|
|
@@ -463,6 +487,10 @@ export function deserializeInspectorState(
|
|
|
463
487
|
files: new Set(data.channels.files),
|
|
464
488
|
meta: data.channels.meta,
|
|
465
489
|
},
|
|
490
|
+
gateways: {
|
|
491
|
+
meta: data.gateways?.meta ?? {},
|
|
492
|
+
files: new Set(data.gateways?.files ?? []),
|
|
493
|
+
},
|
|
466
494
|
triggers: {
|
|
467
495
|
meta: data.triggers?.meta ?? {},
|
|
468
496
|
sourceMeta: data.triggers?.sourceMeta ?? {},
|
|
@@ -489,7 +517,9 @@ export function deserializeInspectorState(
|
|
|
489
517
|
exposedMeta: data.rpc.exposedMeta,
|
|
490
518
|
exposedFiles: new Map(data.rpc.exposedFiles),
|
|
491
519
|
invokedFunctions: new Set(data.rpc.invokedFunctions),
|
|
492
|
-
|
|
520
|
+
usedAddons: new Set(data.rpc.usedAddons || []),
|
|
521
|
+
wireAddonDeclarations: new Map(data.rpc.wireAddonDeclarations || []),
|
|
522
|
+
wireAddonFiles: new Set(data.rpc.wireAddonFiles || []),
|
|
493
523
|
},
|
|
494
524
|
mcpEndpoints: {
|
|
495
525
|
resourcesMeta: data.mcpEndpoints.resourcesMeta,
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as ts from 'typescript'
|
|
2
|
+
import { getPropertyValue } from './get-property-value.js'
|
|
3
|
+
import { ErrorCode } from '../error-codes.js'
|
|
4
|
+
import type { InspectorLogger, InspectorState } from '../types.js'
|
|
5
|
+
|
|
6
|
+
export function validateAuthSessionless(
|
|
7
|
+
logger: InspectorLogger,
|
|
8
|
+
obj: ts.ObjectLiteralExpression,
|
|
9
|
+
state: InspectorState,
|
|
10
|
+
funcName: string,
|
|
11
|
+
wireDescription: string,
|
|
12
|
+
inheritedAuth?: boolean
|
|
13
|
+
): boolean {
|
|
14
|
+
const fnMeta = state.functions.meta[funcName]
|
|
15
|
+
if (!fnMeta) return true
|
|
16
|
+
|
|
17
|
+
const routeAuth = getPropertyValue(obj, 'auth')
|
|
18
|
+
const resolvedAuth =
|
|
19
|
+
routeAuth === true || routeAuth === false ? routeAuth : inheritedAuth
|
|
20
|
+
if (resolvedAuth === false && fnMeta.sessionless === false) {
|
|
21
|
+
logger.critical(
|
|
22
|
+
ErrorCode.AUTH_DISABLED_REQUIRES_SESSIONLESS,
|
|
23
|
+
`${wireDescription} has auth disabled but function '${funcName}' uses pikkuFunc (requires session). Use pikkuSessionlessFunc instead.`
|
|
24
|
+
)
|
|
25
|
+
return false
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return true
|
|
29
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as ts from 'typescript'
|
|
2
|
-
import {
|
|
2
|
+
import type {
|
|
3
3
|
WorkflowStepMeta,
|
|
4
4
|
RpcStepMeta,
|
|
5
5
|
BranchStepMeta,
|
|
@@ -33,11 +33,11 @@ import {
|
|
|
33
33
|
isArrayType,
|
|
34
34
|
getSourceText,
|
|
35
35
|
} from './patterns.js'
|
|
36
|
+
import type { ValidationError } from './validation.js'
|
|
36
37
|
import {
|
|
37
38
|
validateNoDisallowedPatterns,
|
|
38
39
|
validateAwaitedCalls,
|
|
39
40
|
formatValidationErrors,
|
|
40
|
-
ValidationError,
|
|
41
41
|
} from './validation.js'
|
|
42
42
|
import {
|
|
43
43
|
extractStringLiteral,
|