@pikku/inspector 0.12.74 → 0.12.81
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 +347 -0
- package/dist/add/add-analytics.d.ts +9 -0
- package/dist/add/add-analytics.js +178 -0
- package/dist/add/add-auth.js +0 -54
- package/dist/add/add-feature-flag.d.ts +2 -0
- package/dist/add/add-feature-flag.js +162 -0
- package/dist/add/add-wire-addon.js +1 -0
- package/dist/add/add-wire-remote-addon.js +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -1
- package/dist/inspector.js +4 -0
- package/dist/surface/collect-surface.d.ts +58 -0
- package/dist/surface/collect-surface.js +613 -0
- package/dist/types.d.ts +20 -11
- package/dist/utils/filter-inspector-state.js +23 -13
- package/dist/utils/post-process.js +15 -0
- package/dist/utils/read-module-specifiers.d.ts +8 -0
- package/dist/utils/read-module-specifiers.js +23 -0
- package/dist/utils/read-tsconfig-out-dir.d.ts +5 -0
- package/dist/utils/read-tsconfig-out-dir.js +12 -0
- package/dist/utils/resolve-deploy-target.d.ts +7 -0
- package/dist/utils/resolve-deploy-target.js +15 -7
- package/dist/utils/serialize-inspector-state.d.ts +5 -0
- package/dist/utils/serialize-inspector-state.js +8 -0
- package/dist/visit.js +4 -0
- package/package.json +16 -6
- package/run-tests.sh +21 -6
- package/src/add/add-addon-bans.ts +0 -85
- package/src/add/add-agent-scorer.test.ts +0 -197
- package/src/add/add-agent-scorer.ts +0 -83
- package/src/add/add-agent.test.ts +0 -87
- package/src/add/add-agent.ts +0 -638
- package/src/add/add-approval-description.ts +0 -76
- package/src/add/add-auth.test.ts +0 -791
- package/src/add/add-auth.ts +0 -424
- package/src/add/add-channel.ts +0 -778
- package/src/add/add-cli-renderers.test.ts +0 -74
- package/src/add/add-cli.ts +0 -1006
- package/src/add/add-credential.ts +0 -186
- package/src/add/add-feature.test.ts +0 -306
- package/src/add/add-feature.ts +0 -253
- package/src/add/add-file-extends-core-type.ts +0 -66
- package/src/add/add-file-with-config.ts +0 -45
- package/src/add/add-file-with-factory.test.ts +0 -134
- package/src/add/add-file-with-factory.ts +0 -288
- package/src/add/add-functions.test.ts +0 -743
- package/src/add/add-functions.ts +0 -1548
- package/src/add/add-gateway.ts +0 -143
- package/src/add/add-http-route-ref.test.ts +0 -149
- package/src/add/add-http-route.ts +0 -530
- package/src/add/add-http-routes.ts +0 -471
- package/src/add/add-keyed-wiring.ts +0 -180
- package/src/add/add-mcp-prompt.ts +0 -157
- package/src/add/add-mcp-resource.ts +0 -175
- package/src/add/add-middleware.test.ts +0 -196
- package/src/add/add-middleware.ts +0 -879
- package/src/add/add-permission-auth.test.ts +0 -59
- package/src/add/add-permission.ts +0 -311
- package/src/add/add-personas.test.ts +0 -406
- package/src/add/add-personas.ts +0 -287
- package/src/add/add-queue-worker.ts +0 -117
- package/src/add/add-rpc-invocations.test.ts +0 -287
- package/src/add/add-rpc-invocations.ts +0 -221
- package/src/add/add-scenario-step.test.ts +0 -509
- package/src/add/add-schedule.ts +0 -120
- package/src/add/add-scope.test.ts +0 -419
- package/src/add/add-scope.ts +0 -221
- package/src/add/add-secret.ts +0 -10
- package/src/add/add-subject-scenario-steps.test.ts +0 -161
- package/src/add/add-system-role.test.ts +0 -297
- package/src/add/add-system-role.ts +0 -162
- package/src/add/add-trigger.ts +0 -165
- package/src/add/add-variable.ts +0 -10
- package/src/add/add-wire-addon.test.ts +0 -185
- package/src/add/add-wire-addon.ts +0 -146
- package/src/add/add-wire-remote-addon.ts +0 -80
- package/src/add/add-workflow-edge-cases.test.ts +0 -201
- package/src/add/add-workflow-fanout.test.ts +0 -166
- package/src/add/add-workflow-graph-foreach.test.ts +0 -174
- package/src/add/add-workflow-graph-input.test.ts +0 -94
- package/src/add/add-workflow-graph-notes.test.ts +0 -74
- package/src/add/add-workflow-graph.ts +0 -644
- package/src/add/add-workflow-on-error.test.ts +0 -118
- package/src/add/add-workflow-return-switch.test.ts +0 -121
- package/src/add/add-workflow-silent-drops.test.ts +0 -261
- package/src/add/add-workflow-sleep-expression.test.ts +0 -96
- package/src/add/add-workflow.test.ts +0 -155
- package/src/add/add-workflow.ts +0 -482
- package/src/add/addon-bans.test.ts +0 -121
- package/src/add/addon-contracts.test.ts +0 -221
- package/src/add/allow-escape-hatches.test.ts +0 -144
- package/src/add/audit-meta.test.ts +0 -75
- package/src/add/classified-sink-check.test.ts +0 -347
- package/src/add/config-value-metadata.test.ts +0 -263
- package/src/add/dynamic-import-check.test.ts +0 -119
- package/src/add/expect-eventually-scenario-only.test.ts +0 -108
- package/src/add/function-body-span.test.ts +0 -96
- package/src/add/inline-wiring-function.test.ts +0 -104
- package/src/add/pii-check.test.ts +0 -258
- package/src/add/rpc-type-cast.test.ts +0 -123
- package/src/add/scenario-instrumentation.test.ts +0 -89
- package/src/add/scenario-instrumentation.ts +0 -42
- package/src/add/scenario-marker.test.ts +0 -89
- package/src/add/scenario-not-extractable.test.ts +0 -159
- package/src/add/scenario-services.test.ts +0 -103
- package/src/add/scenario-skip.test.ts +0 -83
- package/src/add/validate-workflow-graph-addons.test.ts +0 -102
- package/src/add/wire-name-literal.test.ts +0 -117
- package/src/error-codes-emitted.test.ts +0 -76
- package/src/error-codes.ts +0 -145
- package/src/index.ts +0 -66
- package/src/inspector.ts +0 -575
- package/src/schema-generator.ts +0 -1
- package/src/source-file-cache.ts +0 -73
- package/src/tsconfig-paths.test.ts +0 -90
- package/src/types-map.ts +0 -141
- package/src/types.ts +0 -775
- package/src/utils/annotate-http-route-auth.test.ts +0 -161
- package/src/utils/annotate-http-route-auth.ts +0 -53
- package/src/utils/check-classified-sinks.ts +0 -215
- package/src/utils/check-pii-output.ts +0 -120
- package/src/utils/compute-diagnostics.test.ts +0 -106
- package/src/utils/compute-required-schemas.ts +0 -48
- package/src/utils/contract-hashes.test.ts +0 -553
- package/src/utils/contract-hashes.ts +0 -387
- package/src/utils/custom-types-generator.test.ts +0 -124
- package/src/utils/custom-types-generator.ts +0 -150
- package/src/utils/detect-schema-vendor.test.ts +0 -123
- package/src/utils/detect-schema-vendor.ts +0 -120
- package/src/utils/does-type-extend-core-type.ts +0 -53
- package/src/utils/ensure-function-metadata.ts +0 -385
- package/src/utils/extract-function-name.ts +0 -612
- package/src/utils/extract-function-node.ts +0 -70
- package/src/utils/extract-node-value.test.ts +0 -117
- package/src/utils/extract-node-value.ts +0 -172
- package/src/utils/extract-secret-usage.test.ts +0 -81
- package/src/utils/extract-secret-usage.ts +0 -73
- package/src/utils/extract-services.ts +0 -70
- package/src/utils/extract-surface-usage.test.ts +0 -147
- package/src/utils/extract-surface-usage.ts +0 -121
- package/src/utils/filter-inspector-state.test.ts +0 -2207
- package/src/utils/filter-inspector-state.ts +0 -1302
- package/src/utils/filter-utils.test.ts +0 -843
- package/src/utils/filter-utils.ts +0 -161
- package/src/utils/find-root-dir.ts +0 -68
- package/src/utils/find-zod-transform.test.ts +0 -70
- package/src/utils/find-zod-transform.ts +0 -103
- package/src/utils/get-exported-variable-name.ts +0 -48
- package/src/utils/get-files-and-methods.ts +0 -157
- package/src/utils/get-property-value.test.ts +0 -141
- package/src/utils/get-property-value.ts +0 -331
- package/src/utils/hash.ts +0 -26
- package/src/utils/literal-properties.ts +0 -97
- package/src/utils/load-addon-functions-meta.test.ts +0 -157
- package/src/utils/load-addon-functions-meta.ts +0 -508
- package/src/utils/load-addon-scopes.test.ts +0 -138
- package/src/utils/middleware.test.ts +0 -204
- package/src/utils/middleware.ts +0 -303
- package/src/utils/nested-project-filter.test.ts +0 -53
- package/src/utils/nested-project-filter.ts +0 -28
- package/src/utils/permissions-shorthand.test.ts +0 -79
- package/src/utils/permissions.test.ts +0 -125
- package/src/utils/permissions.ts +0 -129
- package/src/utils/post-process.test.ts +0 -1094
- package/src/utils/post-process.ts +0 -1604
- package/src/utils/resolve-addon-package.ts +0 -106
- package/src/utils/resolve-core-type.test.ts +0 -142
- package/src/utils/resolve-core-type.ts +0 -35
- package/src/utils/resolve-deploy-target.test.ts +0 -135
- package/src/utils/resolve-deploy-target.ts +0 -65
- package/src/utils/resolve-function-meta.ts +0 -25
- package/src/utils/resolve-function-types.ts +0 -42
- package/src/utils/resolve-identifier.ts +0 -46
- package/src/utils/resolve-ref-contract.ts +0 -71
- package/src/utils/resolve-versions.test.ts +0 -499
- package/src/utils/resolve-versions.ts +0 -228
- package/src/utils/schema-cache.test.ts +0 -124
- package/src/utils/schema-generator.test.ts +0 -272
- package/src/utils/schema-generator.ts +0 -780
- package/src/utils/secret-alias-services.test.ts +0 -146
- package/src/utils/secret-alias-services.ts +0 -58
- package/src/utils/serialize-inspector-state.ts +0 -742
- package/src/utils/serialize-mcp-json.ts +0 -150
- package/src/utils/serialize-middleware-groups-meta.ts +0 -36
- package/src/utils/serialize-openapi-json.ts +0 -277
- package/src/utils/serialize-permissions-groups-meta.ts +0 -7
- package/src/utils/single-declaration.ts +0 -57
- package/src/utils/type-utils.ts +0 -145
- package/src/utils/validate-auth-sessionless.ts +0 -30
- package/src/utils/validate-exposed-functions-gated.test.ts +0 -230
- package/src/utils/validate-exposed-functions-gated.ts +0 -103
- package/src/utils/validate-tags-resolve-to-middleware.test.ts +0 -108
- package/src/utils/validate-tags-resolve-to-middleware.ts +0 -48
- package/src/utils/workflow/derive-workflow-plan.test.ts +0 -178
- package/src/utils/workflow/derive-workflow-plan.ts +0 -117
- package/src/utils/workflow/dsl/deserialize-dsl-workflow.ts +0 -1465
- package/src/utils/workflow/dsl/deserialize-fanout-body.test.ts +0 -71
- package/src/utils/workflow/dsl/deserialize-fanout-fidelity.test.ts +0 -99
- package/src/utils/workflow/dsl/deserialize-graph-next.test.ts +0 -161
- package/src/utils/workflow/dsl/deserialize-roundtrip-bindings.test.ts +0 -121
- package/src/utils/workflow/dsl/deserialize-roundtrip-values.test.ts +0 -116
- package/src/utils/workflow/dsl/deserialize-roundtrip.test.ts +0 -145
- package/src/utils/workflow/dsl/extract-approval-policy.test.ts +0 -71
- package/src/utils/workflow/dsl/extract-dsl-workflow.ts +0 -2254
- package/src/utils/workflow/dsl/index.ts +0 -11
- package/src/utils/workflow/dsl/patterns.ts +0 -440
- package/src/utils/workflow/dsl/validation.ts +0 -203
- package/src/utils/workflow/graph/convert-dsl-to-graph-skip.test.ts +0 -35
- package/src/utils/workflow/graph/convert-dsl-to-graph.ts +0 -543
- package/src/utils/workflow/graph/fanout-node-identity.test.ts +0 -105
- package/src/utils/workflow/graph/finalize-workflow-wires.ts +0 -310
- package/src/utils/workflow/graph/finalize-workflows.test.ts +0 -50
- package/src/utils/workflow/graph/finalize-workflows.ts +0 -130
- package/src/utils/workflow/graph/index.ts +0 -28
- package/src/utils/workflow/graph/serialize-workflow-graph.ts +0 -240
- package/src/utils/workflow/graph/workflow-graph.types.ts +0 -281
- package/src/visit.ts +0 -181
- package/tsconfig.json +0 -19
- package/tsconfig.tsbuildinfo +0 -1
package/src/add/add-trigger.ts
DELETED
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
import * as ts from 'typescript'
|
|
2
|
-
import {
|
|
3
|
-
getPropertyValue,
|
|
4
|
-
getCommonWireMetaData,
|
|
5
|
-
} from '../utils/get-property-value.js'
|
|
6
|
-
import type { AddWiring } from '../types.js'
|
|
7
|
-
import {
|
|
8
|
-
extractFunctionName,
|
|
9
|
-
makeContextBasedId,
|
|
10
|
-
} from '../utils/extract-function-name.js'
|
|
11
|
-
import { getPropertyAssignmentInitializer } from '../utils/type-utils.js'
|
|
12
|
-
import { ensureInlineWiringFunction } from '../utils/ensure-function-metadata.js'
|
|
13
|
-
import { resolveMiddleware } from '../utils/middleware.js'
|
|
14
|
-
import { extractWireNames } from '../utils/post-process.js'
|
|
15
|
-
import { resolveAddonName } from '../utils/resolve-addon-package.js'
|
|
16
|
-
|
|
17
|
-
import { ErrorCode } from '../error-codes.js'
|
|
18
|
-
export const addTrigger: 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 (!ts.isIdentifier(expression)) {
|
|
34
|
-
return
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
if (expression.text === 'wireTrigger') {
|
|
38
|
-
addWireTrigger(logger, node, checker, state, firstArg)
|
|
39
|
-
} else if (expression.text === 'wireTriggerSource') {
|
|
40
|
-
addWireTriggerSource(logger, node, checker, state, options, firstArg)
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const addWireTrigger: (
|
|
45
|
-
logger: Parameters<AddWiring>[0],
|
|
46
|
-
node: ts.CallExpression,
|
|
47
|
-
checker: Parameters<AddWiring>[2],
|
|
48
|
-
state: Parameters<AddWiring>[3],
|
|
49
|
-
firstArg: ts.Expression | undefined
|
|
50
|
-
) => void = (logger, node, checker, state, firstArg) => {
|
|
51
|
-
if (!firstArg || !ts.isObjectLiteralExpression(firstArg)) {
|
|
52
|
-
return
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const obj = firstArg
|
|
56
|
-
|
|
57
|
-
const nameValue = getPropertyValue(obj, 'name') as string | null
|
|
58
|
-
const { disabled, tags, summary, description, errors } =
|
|
59
|
-
getCommonWireMetaData(obj, 'Trigger', nameValue, logger, checker)
|
|
60
|
-
|
|
61
|
-
if (disabled) return
|
|
62
|
-
|
|
63
|
-
const funcInitializer = getPropertyAssignmentInitializer(
|
|
64
|
-
obj,
|
|
65
|
-
'func',
|
|
66
|
-
true,
|
|
67
|
-
checker
|
|
68
|
-
)
|
|
69
|
-
if (!funcInitializer) {
|
|
70
|
-
logger.critical(
|
|
71
|
-
ErrorCode.MISSING_FUNC,
|
|
72
|
-
`No valid 'func' property for trigger '${nameValue}'.`
|
|
73
|
-
)
|
|
74
|
-
return
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const extracted = extractFunctionName(funcInitializer, checker, state.rootDir)
|
|
78
|
-
let pikkuFuncId = extracted.pikkuFuncId
|
|
79
|
-
if (pikkuFuncId.startsWith('__temp_') && nameValue) {
|
|
80
|
-
pikkuFuncId = makeContextBasedId('trigger', nameValue)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (!nameValue) {
|
|
84
|
-
return
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Register metadata for a func inlined into the wiring (see helper).
|
|
88
|
-
ensureInlineWiringFunction(
|
|
89
|
-
state,
|
|
90
|
-
pikkuFuncId,
|
|
91
|
-
nameValue,
|
|
92
|
-
funcInitializer,
|
|
93
|
-
checker,
|
|
94
|
-
extracted.isHelper
|
|
95
|
-
)
|
|
96
|
-
|
|
97
|
-
// --- resolve middleware ---
|
|
98
|
-
const middleware = resolveMiddleware(state, obj, tags, checker)
|
|
99
|
-
|
|
100
|
-
// --- track used functions/middleware for service aggregation ---
|
|
101
|
-
state.serviceAggregation.usedFunctions.add(pikkuFuncId)
|
|
102
|
-
extractWireNames(middleware).forEach((name) =>
|
|
103
|
-
state.serviceAggregation.usedMiddleware.add(name)
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
state.triggers.files.add(node.getSourceFile().fileName)
|
|
107
|
-
state.triggers.meta[nameValue] = {
|
|
108
|
-
pikkuFuncId,
|
|
109
|
-
name: nameValue,
|
|
110
|
-
summary,
|
|
111
|
-
description,
|
|
112
|
-
errors,
|
|
113
|
-
tags,
|
|
114
|
-
middleware,
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const addWireTriggerSource: (
|
|
119
|
-
logger: Parameters<AddWiring>[0],
|
|
120
|
-
node: ts.CallExpression,
|
|
121
|
-
checker: Parameters<AddWiring>[2],
|
|
122
|
-
state: Parameters<AddWiring>[3],
|
|
123
|
-
options: Parameters<AddWiring>[4],
|
|
124
|
-
firstArg: ts.Expression | undefined
|
|
125
|
-
) => void = (logger, node, checker, state, options, firstArg) => {
|
|
126
|
-
if (!firstArg || !ts.isObjectLiteralExpression(firstArg)) {
|
|
127
|
-
return
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
const obj = firstArg
|
|
131
|
-
|
|
132
|
-
const nameValue = getPropertyValue(obj, 'name') as string | null
|
|
133
|
-
if (!nameValue) {
|
|
134
|
-
return
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const funcInitializer = getPropertyAssignmentInitializer(
|
|
138
|
-
obj,
|
|
139
|
-
'func',
|
|
140
|
-
true,
|
|
141
|
-
checker
|
|
142
|
-
)
|
|
143
|
-
if (!funcInitializer) {
|
|
144
|
-
logger.critical(
|
|
145
|
-
ErrorCode.MISSING_FUNC,
|
|
146
|
-
`No valid 'func' property for trigger source '${nameValue}'.`
|
|
147
|
-
)
|
|
148
|
-
return
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
if (ts.isIdentifier(funcInitializer)) {
|
|
152
|
-
const packageName = resolveAddonName(
|
|
153
|
-
funcInitializer,
|
|
154
|
-
checker,
|
|
155
|
-
state.rpc.wireAddonDeclarations
|
|
156
|
-
)
|
|
157
|
-
state.triggers.sourceMeta[nameValue] = {
|
|
158
|
-
name: nameValue,
|
|
159
|
-
pikkuFuncId: funcInitializer.text,
|
|
160
|
-
packageName: packageName || undefined,
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
state.triggers.files.add(node.getSourceFile().fileName)
|
|
165
|
-
}
|
package/src/add/add-variable.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { createAddKeyedWiring } from './add-keyed-wiring.js'
|
|
2
|
-
|
|
3
|
-
export const addVariable = createAddKeyedWiring({
|
|
4
|
-
functionName: 'defineVariable',
|
|
5
|
-
idField: 'variableId',
|
|
6
|
-
label: 'Variable',
|
|
7
|
-
schemaPrefix: 'VariableSchema',
|
|
8
|
-
flagField: 'optional',
|
|
9
|
-
getState: (state) => state.variables,
|
|
10
|
-
})
|
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict'
|
|
2
|
-
import { describe, test, beforeEach } from 'node:test'
|
|
3
|
-
import * as ts from 'typescript'
|
|
4
|
-
import { addWireAddon } from './add-wire-addon.js'
|
|
5
|
-
|
|
6
|
-
let state: any
|
|
7
|
-
|
|
8
|
-
const logger = {
|
|
9
|
-
debug: () => {},
|
|
10
|
-
info: () => {},
|
|
11
|
-
warn: () => {},
|
|
12
|
-
error: () => {},
|
|
13
|
-
} as any
|
|
14
|
-
|
|
15
|
-
/** Parses a source snippet and runs addWireAddon over every call expression. */
|
|
16
|
-
const inspect = (source: string) => {
|
|
17
|
-
const file = ts.createSourceFile(
|
|
18
|
-
'wiring.ts',
|
|
19
|
-
source,
|
|
20
|
-
ts.ScriptTarget.Latest,
|
|
21
|
-
true
|
|
22
|
-
)
|
|
23
|
-
const visit = (node: ts.Node) => {
|
|
24
|
-
addWireAddon(node, state, logger)
|
|
25
|
-
ts.forEachChild(node, visit)
|
|
26
|
-
}
|
|
27
|
-
visit(file)
|
|
28
|
-
return state.rpc.wireAddonDeclarations
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
beforeEach(() => {
|
|
32
|
-
state = {
|
|
33
|
-
rpc: {
|
|
34
|
-
wireAddonDeclarations: new Map(),
|
|
35
|
-
usedAddons: new Set(),
|
|
36
|
-
wireAddonFiles: new Set(),
|
|
37
|
-
},
|
|
38
|
-
}
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
describe('addWireAddon', () => {
|
|
42
|
-
test('captures the addon gates alongside its plumbing', () => {
|
|
43
|
-
const declarations = inspect(`
|
|
44
|
-
wireAddon({
|
|
45
|
-
name: 'console',
|
|
46
|
-
package: '@pikku/addon-console',
|
|
47
|
-
rpcEndpoint: '/rpc',
|
|
48
|
-
auth: true,
|
|
49
|
-
tags: ['admin', 'internal'],
|
|
50
|
-
scopes: ['admin'],
|
|
51
|
-
})
|
|
52
|
-
`)
|
|
53
|
-
|
|
54
|
-
assert.deepEqual(declarations.get('console'), {
|
|
55
|
-
package: '@pikku/addon-console',
|
|
56
|
-
rpcEndpoint: '/rpc',
|
|
57
|
-
mcp: undefined,
|
|
58
|
-
auth: true,
|
|
59
|
-
tags: ['admin', 'internal'],
|
|
60
|
-
scopes: ['admin'],
|
|
61
|
-
secretOverrides: undefined,
|
|
62
|
-
variableOverrides: undefined,
|
|
63
|
-
credentialOverrides: undefined,
|
|
64
|
-
secretGrants: undefined,
|
|
65
|
-
credentialGrants: undefined,
|
|
66
|
-
globalSecrets: undefined,
|
|
67
|
-
globalCredentials: undefined,
|
|
68
|
-
})
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
test('captures the secrets and credentials the host lends an addon', () => {
|
|
72
|
-
const declarations = inspect(`
|
|
73
|
-
wireAddon({
|
|
74
|
-
name: 'graph',
|
|
75
|
-
package: '@pikku/addon-graph',
|
|
76
|
-
secretGrants: ['STRIPE_KEY', 'GITHUB_TOKEN'],
|
|
77
|
-
credentialGrants: ['slack'],
|
|
78
|
-
})
|
|
79
|
-
`)
|
|
80
|
-
|
|
81
|
-
assert.deepEqual(declarations.get('graph').secretGrants, [
|
|
82
|
-
'STRIPE_KEY',
|
|
83
|
-
'GITHUB_TOKEN',
|
|
84
|
-
])
|
|
85
|
-
assert.deepEqual(declarations.get('graph').credentialGrants, ['slack'])
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
test('drops a grant list that is not statically knowable', () => {
|
|
89
|
-
const declarations = inspect(`
|
|
90
|
-
wireAddon({
|
|
91
|
-
name: 'graph',
|
|
92
|
-
package: '@pikku/addon-graph',
|
|
93
|
-
secretGrants: someRuntimeList,
|
|
94
|
-
})
|
|
95
|
-
`)
|
|
96
|
-
|
|
97
|
-
assert.equal(declarations.get('graph').secretGrants, undefined)
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
test('captures the reason an addon was exempted from credential scoping', () => {
|
|
101
|
-
const declarations = inspect(`
|
|
102
|
-
wireAddon({
|
|
103
|
-
name: 'console',
|
|
104
|
-
package: '@pikku/addon-console',
|
|
105
|
-
globalCredentials: 'links credentials an operator names at runtime',
|
|
106
|
-
})
|
|
107
|
-
`)
|
|
108
|
-
|
|
109
|
-
assert.equal(
|
|
110
|
-
declarations.get('console').globalCredentials,
|
|
111
|
-
'links credentials an operator names at runtime'
|
|
112
|
-
)
|
|
113
|
-
})
|
|
114
|
-
|
|
115
|
-
test('captures the reason an addon was exempted from secret scoping', () => {
|
|
116
|
-
const declarations = inspect(`
|
|
117
|
-
wireAddon({
|
|
118
|
-
name: 'console',
|
|
119
|
-
package: '@pikku/addon-console',
|
|
120
|
-
globalSecrets: 'administers secrets an operator names at runtime',
|
|
121
|
-
})
|
|
122
|
-
`)
|
|
123
|
-
|
|
124
|
-
assert.equal(
|
|
125
|
-
declarations.get('console').globalSecrets,
|
|
126
|
-
'administers secrets an operator names at runtime'
|
|
127
|
-
)
|
|
128
|
-
})
|
|
129
|
-
|
|
130
|
-
test('a globalSecrets reason that is not a literal still reports the grant', () => {
|
|
131
|
-
// Unlike `scopes`, dropping this would under-report: the grant is real at
|
|
132
|
-
// runtime whatever the reason evaluates to. The source text is recorded so
|
|
133
|
-
// the manifest names the addon and points at where the reason comes from.
|
|
134
|
-
const declarations = inspect(`
|
|
135
|
-
wireAddon({ name: 'console', package: '@x/y', globalSecrets: REASON })
|
|
136
|
-
`)
|
|
137
|
-
|
|
138
|
-
assert.equal(declarations.get('console').globalSecrets, 'REASON')
|
|
139
|
-
})
|
|
140
|
-
|
|
141
|
-
test('leaves the gates undefined when none are declared', () => {
|
|
142
|
-
const declarations = inspect(`
|
|
143
|
-
wireAddon({ name: 'console', package: '@pikku/addon-console' })
|
|
144
|
-
`)
|
|
145
|
-
|
|
146
|
-
const declaration = declarations.get('console')
|
|
147
|
-
assert.equal(declaration.auth, undefined)
|
|
148
|
-
assert.equal(declaration.tags, undefined)
|
|
149
|
-
assert.equal(declaration.scopes, undefined)
|
|
150
|
-
})
|
|
151
|
-
|
|
152
|
-
test('records auth: false rather than dropping it', () => {
|
|
153
|
-
const declarations = inspect(`
|
|
154
|
-
wireAddon({ name: 'console', package: '@x/y', auth: false })
|
|
155
|
-
`)
|
|
156
|
-
|
|
157
|
-
assert.equal(declarations.get('console').auth, false)
|
|
158
|
-
})
|
|
159
|
-
|
|
160
|
-
test('drops a scopes array that is not statically knowable', () => {
|
|
161
|
-
// A partial list would read as the complete set of gates, so an array with
|
|
162
|
-
// any non-literal entry is reported as unknown instead.
|
|
163
|
-
const declarations = inspect(`
|
|
164
|
-
wireAddon({ name: 'console', package: '@x/y', scopes: ['admin', ...EXTRA] })
|
|
165
|
-
`)
|
|
166
|
-
|
|
167
|
-
assert.equal(declarations.get('console').scopes, undefined)
|
|
168
|
-
})
|
|
169
|
-
|
|
170
|
-
test('drops a scopes value that is a reference rather than an array', () => {
|
|
171
|
-
const declarations = inspect(`
|
|
172
|
-
wireAddon({ name: 'console', package: '@x/y', scopes: ADMIN_SCOPES })
|
|
173
|
-
`)
|
|
174
|
-
|
|
175
|
-
assert.equal(declarations.get('console').scopes, undefined)
|
|
176
|
-
})
|
|
177
|
-
|
|
178
|
-
test('keeps an explicitly empty scopes array distinct from an absent one', () => {
|
|
179
|
-
const declarations = inspect(`
|
|
180
|
-
wireAddon({ name: 'console', package: '@x/y', scopes: [] })
|
|
181
|
-
`)
|
|
182
|
-
|
|
183
|
-
assert.deepEqual(declarations.get('console').scopes, [])
|
|
184
|
-
})
|
|
185
|
-
})
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import * as ts from 'typescript'
|
|
2
|
-
import type { InspectorState, InspectorLogger } from '../types.js'
|
|
3
|
-
|
|
4
|
-
function parseStringArray(node: ts.Expression): string[] | undefined {
|
|
5
|
-
if (!ts.isArrayLiteralExpression(node)) return undefined
|
|
6
|
-
const values: string[] = []
|
|
7
|
-
for (const element of node.elements) {
|
|
8
|
-
// A non-literal entry (a spread, a const reference) is not statically
|
|
9
|
-
// knowable. Dropping the whole array rather than a silent partial keeps a
|
|
10
|
-
// consumer from reading a short list as the complete set of gates.
|
|
11
|
-
if (!ts.isStringLiteral(element)) return undefined
|
|
12
|
-
values.push(element.text)
|
|
13
|
-
}
|
|
14
|
-
return values
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function parseStringRecord(
|
|
18
|
-
obj: ts.ObjectLiteralExpression
|
|
19
|
-
): Record<string, string> {
|
|
20
|
-
const result: Record<string, string> = {}
|
|
21
|
-
for (const prop of obj.properties) {
|
|
22
|
-
if (!ts.isPropertyAssignment(prop)) continue
|
|
23
|
-
const keyNode = prop.name
|
|
24
|
-
const key = ts.isIdentifier(keyNode)
|
|
25
|
-
? keyNode.text
|
|
26
|
-
: ts.isStringLiteral(keyNode)
|
|
27
|
-
? keyNode.text
|
|
28
|
-
: undefined
|
|
29
|
-
if (key && ts.isStringLiteral(prop.initializer)) {
|
|
30
|
-
result[key] = prop.initializer.text
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
return result
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Detect wireAddon({ name: '...', package: '...' }) call expressions and
|
|
38
|
-
* populate state.rpc.wireAddonDeclarations and state.rpc.usedAddons.
|
|
39
|
-
*/
|
|
40
|
-
export function addWireAddon(
|
|
41
|
-
node: ts.Node,
|
|
42
|
-
state: InspectorState,
|
|
43
|
-
logger: InspectorLogger
|
|
44
|
-
) {
|
|
45
|
-
if (!ts.isCallExpression(node)) return
|
|
46
|
-
|
|
47
|
-
const { expression, arguments: args } = node
|
|
48
|
-
if (!ts.isIdentifier(expression) || expression.text !== 'wireAddon') return
|
|
49
|
-
|
|
50
|
-
const [firstArg] = args
|
|
51
|
-
if (!firstArg || !ts.isObjectLiteralExpression(firstArg)) return
|
|
52
|
-
|
|
53
|
-
let name: string | undefined
|
|
54
|
-
let pkg: string | undefined
|
|
55
|
-
let rpcEndpoint: string | undefined
|
|
56
|
-
let mcp: boolean | undefined
|
|
57
|
-
let auth: boolean | undefined
|
|
58
|
-
let tags: string[] | undefined
|
|
59
|
-
let scopes: string[] | undefined
|
|
60
|
-
let secretOverrides: Record<string, string> | undefined
|
|
61
|
-
let variableOverrides: Record<string, string> | undefined
|
|
62
|
-
let credentialOverrides: Record<string, string> | undefined
|
|
63
|
-
let secretGrants: string[] | undefined
|
|
64
|
-
let credentialGrants: string[] | undefined
|
|
65
|
-
let globalSecrets: string | undefined
|
|
66
|
-
let globalCredentials: string | undefined
|
|
67
|
-
|
|
68
|
-
for (const prop of firstArg.properties) {
|
|
69
|
-
if (!ts.isPropertyAssignment(prop) || !ts.isIdentifier(prop.name)) continue
|
|
70
|
-
|
|
71
|
-
const key = prop.name.text
|
|
72
|
-
if (key === 'name' && ts.isStringLiteral(prop.initializer)) {
|
|
73
|
-
name = prop.initializer.text
|
|
74
|
-
} else if (key === 'package' && ts.isStringLiteral(prop.initializer)) {
|
|
75
|
-
pkg = prop.initializer.text
|
|
76
|
-
} else if (key === 'rpcEndpoint' && ts.isStringLiteral(prop.initializer)) {
|
|
77
|
-
rpcEndpoint = prop.initializer.text
|
|
78
|
-
} else if (
|
|
79
|
-
key === 'mcp' &&
|
|
80
|
-
(prop.initializer.kind === ts.SyntaxKind.TrueKeyword ||
|
|
81
|
-
prop.initializer.kind === ts.SyntaxKind.FalseKeyword)
|
|
82
|
-
) {
|
|
83
|
-
mcp = prop.initializer.kind === ts.SyntaxKind.TrueKeyword
|
|
84
|
-
} else if (
|
|
85
|
-
key === 'auth' &&
|
|
86
|
-
(prop.initializer.kind === ts.SyntaxKind.TrueKeyword ||
|
|
87
|
-
prop.initializer.kind === ts.SyntaxKind.FalseKeyword)
|
|
88
|
-
) {
|
|
89
|
-
auth = prop.initializer.kind === ts.SyntaxKind.TrueKeyword
|
|
90
|
-
} else if (key === 'tags') {
|
|
91
|
-
tags = parseStringArray(prop.initializer)
|
|
92
|
-
} else if (key === 'scopes') {
|
|
93
|
-
scopes = parseStringArray(prop.initializer)
|
|
94
|
-
} else if (
|
|
95
|
-
key === 'secretOverrides' &&
|
|
96
|
-
ts.isObjectLiteralExpression(prop.initializer)
|
|
97
|
-
) {
|
|
98
|
-
secretOverrides = parseStringRecord(prop.initializer)
|
|
99
|
-
} else if (
|
|
100
|
-
key === 'variableOverrides' &&
|
|
101
|
-
ts.isObjectLiteralExpression(prop.initializer)
|
|
102
|
-
) {
|
|
103
|
-
variableOverrides = parseStringRecord(prop.initializer)
|
|
104
|
-
} else if (
|
|
105
|
-
key === 'credentialOverrides' &&
|
|
106
|
-
ts.isObjectLiteralExpression(prop.initializer)
|
|
107
|
-
) {
|
|
108
|
-
credentialOverrides = parseStringRecord(prop.initializer)
|
|
109
|
-
} else if (key === 'secretGrants') {
|
|
110
|
-
secretGrants = parseStringArray(prop.initializer)
|
|
111
|
-
} else if (key === 'credentialGrants') {
|
|
112
|
-
credentialGrants = parseStringArray(prop.initializer)
|
|
113
|
-
} else if (key === 'globalSecrets') {
|
|
114
|
-
// The grant is real at runtime whatever the reason evaluates to, so a
|
|
115
|
-
// non-literal is recorded as its source text rather than dropped.
|
|
116
|
-
globalSecrets = ts.isStringLiteral(prop.initializer)
|
|
117
|
-
? prop.initializer.text
|
|
118
|
-
: prop.initializer.getText()
|
|
119
|
-
} else if (key === 'globalCredentials') {
|
|
120
|
-
globalCredentials = ts.isStringLiteral(prop.initializer)
|
|
121
|
-
? prop.initializer.text
|
|
122
|
-
: prop.initializer.getText()
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
if (!name || !pkg) return
|
|
127
|
-
|
|
128
|
-
logger.debug(`• Found wireAddon: ${name} → ${pkg}`)
|
|
129
|
-
state.rpc.wireAddonDeclarations.set(name, {
|
|
130
|
-
package: pkg,
|
|
131
|
-
rpcEndpoint,
|
|
132
|
-
mcp,
|
|
133
|
-
auth,
|
|
134
|
-
tags,
|
|
135
|
-
scopes,
|
|
136
|
-
secretOverrides,
|
|
137
|
-
variableOverrides,
|
|
138
|
-
credentialOverrides,
|
|
139
|
-
secretGrants,
|
|
140
|
-
credentialGrants,
|
|
141
|
-
globalSecrets,
|
|
142
|
-
globalCredentials,
|
|
143
|
-
})
|
|
144
|
-
state.rpc.usedAddons.add(name)
|
|
145
|
-
state.rpc.wireAddonFiles.add(node.getSourceFile().fileName)
|
|
146
|
-
}
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import * as ts from 'typescript'
|
|
2
|
-
import type { InspectorState, InspectorLogger } from '../types.js'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Detect wireRemoteAddon({ name: '...', package: '...' }) call expressions and
|
|
6
|
-
* record the namespace as a **remote** addon declaration. Only name + package
|
|
7
|
-
* are needed for codegen (serverUrl/auth are runtime closures resolved by the
|
|
8
|
-
* RPC runner); the `remote` marker tells the consumer's RPC-map generator to
|
|
9
|
-
* import the addon's `.remote.gen` map instead of `.internal.gen`.
|
|
10
|
-
*/
|
|
11
|
-
export function addWireRemoteAddon(
|
|
12
|
-
node: ts.Node,
|
|
13
|
-
state: InspectorState,
|
|
14
|
-
logger: InspectorLogger
|
|
15
|
-
) {
|
|
16
|
-
if (!ts.isCallExpression(node)) return
|
|
17
|
-
|
|
18
|
-
const { expression, arguments: args } = node
|
|
19
|
-
if (!ts.isIdentifier(expression) || expression.text !== 'wireRemoteAddon')
|
|
20
|
-
return
|
|
21
|
-
|
|
22
|
-
const [firstArg] = args
|
|
23
|
-
if (!firstArg || !ts.isObjectLiteralExpression(firstArg)) return
|
|
24
|
-
|
|
25
|
-
let name: string | undefined
|
|
26
|
-
let pkg: string | undefined
|
|
27
|
-
// The auth binding is a runtime closure; we only extract the statically
|
|
28
|
-
// knowable slot names so `pikku verify` can check they exist in the
|
|
29
|
-
// consumer's own wirings. `hasAuth` distinguishes "public" (omitted) from
|
|
30
|
-
// "bound via a custom resolve()" (present but no static id).
|
|
31
|
-
let hasAuth = false
|
|
32
|
-
let authCredentialId: string | undefined
|
|
33
|
-
let authSecretId: string | undefined
|
|
34
|
-
|
|
35
|
-
for (const prop of firstArg.properties) {
|
|
36
|
-
if (!ts.isPropertyAssignment(prop) || !ts.isIdentifier(prop.name)) continue
|
|
37
|
-
const key = prop.name.text
|
|
38
|
-
if (key === 'name' && ts.isStringLiteral(prop.initializer)) {
|
|
39
|
-
name = prop.initializer.text
|
|
40
|
-
} else if (key === 'package' && ts.isStringLiteral(prop.initializer)) {
|
|
41
|
-
pkg = prop.initializer.text
|
|
42
|
-
} else if (
|
|
43
|
-
key === 'auth' &&
|
|
44
|
-
ts.isObjectLiteralExpression(prop.initializer)
|
|
45
|
-
) {
|
|
46
|
-
hasAuth = true
|
|
47
|
-
for (const authProp of prop.initializer.properties) {
|
|
48
|
-
if (
|
|
49
|
-
!ts.isPropertyAssignment(authProp) ||
|
|
50
|
-
!ts.isIdentifier(authProp.name)
|
|
51
|
-
)
|
|
52
|
-
continue
|
|
53
|
-
if (
|
|
54
|
-
authProp.name.text === 'credentialId' &&
|
|
55
|
-
ts.isStringLiteral(authProp.initializer)
|
|
56
|
-
) {
|
|
57
|
-
authCredentialId = authProp.initializer.text
|
|
58
|
-
} else if (
|
|
59
|
-
authProp.name.text === 'secretId' &&
|
|
60
|
-
ts.isStringLiteral(authProp.initializer)
|
|
61
|
-
) {
|
|
62
|
-
authSecretId = authProp.initializer.text
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
if (!name || !pkg) return
|
|
69
|
-
|
|
70
|
-
logger.debug(`• Found wireRemoteAddon: ${name} → ${pkg} (remote)`)
|
|
71
|
-
state.rpc.wireAddonDeclarations.set(name, {
|
|
72
|
-
package: pkg,
|
|
73
|
-
remote: true,
|
|
74
|
-
hasAuth,
|
|
75
|
-
authCredentialId,
|
|
76
|
-
authSecretId,
|
|
77
|
-
})
|
|
78
|
-
state.rpc.usedAddons.add(name)
|
|
79
|
-
state.rpc.wireAddonFiles.add(node.getSourceFile().fileName)
|
|
80
|
-
}
|