@pikku/inspector 0.12.60 → 0.12.61
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 +301 -0
- package/OPTIMIZATION-PLAN.md +19 -19
- package/dist/add/add-auth.js +1 -1
- package/dist/add/add-channel.d.ts +1 -1
- package/dist/add/add-cli.js +5 -0
- package/dist/add/add-functions.js +10 -1
- package/dist/add/add-http-route.js +18 -18
- package/dist/add/add-keyed-wiring.d.ts +2 -0
- package/dist/add/add-keyed-wiring.js +3 -1
- package/dist/add/add-personas.js +4 -1
- package/dist/add/add-secret.js +1 -0
- package/dist/add/add-variable.js +1 -0
- package/dist/add/add-wire-remote-addon.js +2 -1
- package/dist/add/add-workflow-graph.js +63 -6
- package/dist/add/add-workflow.d.ts +1 -1
- package/dist/error-codes.d.ts +3 -1
- package/dist/error-codes.js +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1 -0
- package/dist/inspector.js +12 -2
- package/dist/types.d.ts +25 -21
- package/dist/utils/annotate-http-route-auth.js +2 -1
- package/dist/utils/check-secret-sinks.js +2 -1
- package/dist/utils/compute-required-schemas.d.ts +1 -1
- package/dist/utils/contract-hashes.d.ts +2 -2
- package/dist/utils/contract-hashes.js +1 -1
- package/dist/utils/extract-function-name.js +1 -1
- package/dist/utils/extract-services.d.ts +1 -1
- package/dist/utils/extract-surface-usage.d.ts +29 -0
- package/dist/utils/extract-surface-usage.js +97 -0
- package/dist/utils/filter-inspector-state.js +53 -16
- package/dist/utils/filter-utils.d.ts +1 -1
- package/dist/utils/get-property-value.js +42 -3
- package/dist/utils/load-addon-functions-meta.js +31 -0
- package/dist/utils/middleware.d.ts +1 -1
- package/dist/utils/permissions.d.ts +1 -1
- package/dist/utils/post-process.d.ts +27 -7
- package/dist/utils/post-process.js +79 -14
- package/dist/utils/resolve-deploy-target.d.ts +1 -1
- package/dist/utils/resolve-function-meta.d.ts +1 -1
- package/dist/utils/resolve-function-types.d.ts +1 -1
- package/dist/utils/resolve-versions.js +1 -1
- package/dist/utils/schema-generator.d.ts +1 -1
- package/dist/utils/serialize-inspector-state.d.ts +2 -1
- package/dist/utils/serialize-inspector-state.js +2 -0
- package/dist/utils/serialize-openapi-json.d.ts +2 -2
- package/dist/utils/validate-auth-sessionless.js +2 -1
- package/dist/utils/workflow/derive-workflow-plan.d.ts +1 -1
- package/dist/utils/workflow/dsl/extract-dsl-workflow.d.ts +1 -1
- package/dist/utils/workflow/graph/convert-dsl-to-graph.d.ts +1 -1
- package/dist/utils/workflow/graph/finalize-workflows.js +1 -1
- package/dist/utils/workflow/graph/serialize-workflow-graph.d.ts +6 -1
- package/dist/utils/workflow/graph/serialize-workflow-graph.js +26 -2
- package/dist/utils/workflow/graph/workflow-graph.types.d.ts +11 -2
- package/package.json +10 -10
- package/run-tests.sh +0 -0
- package/src/add/add-agent.ts +2 -4
- package/src/add/add-auth.ts +2 -2
- package/src/add/add-channel.ts +1 -4
- package/src/add/add-cli.ts +7 -1
- package/src/add/add-credential.ts +3 -6
- package/src/add/add-file-with-factory.ts +2 -6
- package/src/add/add-functions.ts +24 -31
- package/src/add/add-gateway.ts +1 -1
- package/src/add/add-http-route-ref.test.ts +149 -0
- package/src/add/add-http-route.ts +26 -29
- package/src/add/add-keyed-wiring.ts +8 -7
- package/src/add/add-permission.ts +1 -1
- package/src/add/add-personas.test.ts +26 -2
- package/src/add/add-personas.ts +4 -3
- package/src/add/add-scenario-step.test.ts +37 -2
- package/src/add/add-scope.test.ts +15 -15
- package/src/add/add-scope.ts +5 -9
- package/src/add/add-secret.ts +1 -0
- package/src/add/add-system-role.test.ts +4 -4
- package/src/add/add-system-role.ts +2 -4
- package/src/add/add-variable.ts +1 -0
- package/src/add/add-wire-remote-addon.ts +4 -1
- package/src/add/add-workflow-graph-foreach.test.ts +174 -0
- package/src/add/add-workflow-graph-input.test.ts +1 -1
- package/src/add/add-workflow-graph.ts +78 -6
- package/src/add/add-workflow-sleep-expression.test.ts +3 -4
- package/src/add/add-workflow.ts +1 -4
- package/src/add/addon-contracts.test.ts +1 -1
- package/src/add/config-value-metadata.test.ts +94 -0
- package/src/add/secret-sink-check.test.ts +4 -1
- package/src/error-codes.ts +3 -1
- package/src/index.ts +3 -4
- package/src/inspector.ts +19 -2
- package/src/types.ts +25 -28
- package/src/utils/annotate-http-route-auth.test.ts +5 -7
- package/src/utils/annotate-http-route-auth.ts +2 -1
- package/src/utils/check-secret-sinks.ts +4 -1
- package/src/utils/compute-required-schemas.ts +1 -1
- package/src/utils/contract-hashes.test.ts +1 -1
- package/src/utils/contract-hashes.ts +3 -3
- package/src/utils/extract-function-name.ts +1 -1
- package/src/utils/extract-services.ts +1 -2
- package/src/utils/extract-surface-usage.test.ts +147 -0
- package/src/utils/extract-surface-usage.ts +121 -0
- package/src/utils/filter-inspector-state.test.ts +138 -12
- package/src/utils/filter-inspector-state.ts +82 -21
- package/src/utils/filter-utils.ts +1 -1
- package/src/utils/get-property-value.ts +43 -5
- package/src/utils/load-addon-functions-meta.ts +40 -0
- package/src/utils/middleware.ts +1 -1
- package/src/utils/permissions.ts +1 -1
- package/src/utils/post-process.test.ts +59 -2
- package/src/utils/post-process.ts +88 -25
- package/src/utils/resolve-deploy-target.ts +1 -1
- package/src/utils/resolve-function-meta.ts +1 -4
- package/src/utils/resolve-function-types.ts +1 -1
- package/src/utils/resolve-versions.ts +2 -5
- package/src/utils/schema-generator.ts +3 -3
- package/src/utils/serialize-inspector-state.ts +4 -1
- package/src/utils/serialize-mcp-json.ts +1 -1
- package/src/utils/serialize-openapi-json.ts +2 -2
- package/src/utils/validate-auth-sessionless.ts +2 -1
- package/src/utils/validate-tags-resolve-to-middleware.test.ts +4 -1
- package/src/utils/workflow/derive-workflow-plan.test.ts +1 -1
- package/src/utils/workflow/derive-workflow-plan.ts +1 -1
- package/src/utils/workflow/dsl/extract-approval-policy.test.ts +1 -1
- package/src/utils/workflow/dsl/extract-dsl-workflow.ts +2 -2
- package/src/utils/workflow/graph/convert-dsl-to-graph-skip.test.ts +1 -1
- package/src/utils/workflow/graph/convert-dsl-to-graph.ts +1 -4
- package/src/utils/workflow/graph/finalize-workflow-wires.ts +1 -1
- package/src/utils/workflow/graph/finalize-workflows.ts +2 -2
- package/src/utils/workflow/graph/serialize-workflow-graph.ts +34 -3
- package/src/utils/workflow/graph/workflow-graph.types.ts +12 -2
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/add/add-ai-agent.d.ts +0 -4
- package/dist/add/add-ai-agent.js +0 -442
- package/dist/add/add-ai-scorer.d.ts +0 -2
- package/dist/add/add-ai-scorer.js +0 -61
- package/dist/utils/secret-brokers.d.ts +0 -2
- package/dist/utils/secret-brokers.js +0 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,304 @@
|
|
|
1
|
+
## 0.12.61
|
|
2
|
+
|
|
3
|
+
### Patch Changes
|
|
4
|
+
|
|
5
|
+
- ab52d8e: Raise an addon's deploy conflict only where the consuming app wires it. A
|
|
6
|
+
function an addon publishes as `deploy: 'serverless'` while naming one of its
|
|
7
|
+
own services serverless-incompatible previously failed the build of any app
|
|
8
|
+
that merely declared the addon, whether or not that function was used.
|
|
9
|
+
- a281de6: A CLI option's type now drives how it is parsed, and it comes from the command function's input schema rather than a second hand-written declaration.
|
|
10
|
+
|
|
11
|
+
`CLIOption` gains `type?: 'string' | 'number' | 'boolean' | 'string[]'` (replacing the never-honoured `array` flag). Declared, it wins over whatever the schema says; left unset, the parser reads the type off the command function's input schema — the same schema the function is validated against — falling back to `default` and then to `'string'`. A `'string[]'` option consumes one token and splits it on commas; every other non-boolean option consumes the next token verbatim, so values that begin with `-` (base64url tokens, negative numbers, dash-leading name patterns) parse correctly. A boolean option is a flag: it consumes the next token only when that token is an explicit literal (`true`/`false`/`1`/`0`/`yes`/`no`), so `--watch false` still turns a default-on flag off instead of leaving `false` behind as a positional.
|
|
12
|
+
|
|
13
|
+
Because the schema is now what types an option, `pikku serve --console --port 4077` no longer reads `--port` as the value of `--console`, and a numeric option arrives as a number instead of a string. An explicit `type` is mostly needed for options that belong to no function input — the `pikku all` filters, which the config factory reads straight off the CLI data, are declared `string[]`, and the CLI's ad-hoc `parseCommaSeparated` normalisation is gone.
|
|
14
|
+
|
|
15
|
+
An array option takes either one comma list or the flag repeated. It never consumes more than one token, because `--tags alpha beta` cannot be told apart from an option followed by a positional; the stray token is reported as an unexpected argument rather than dropped.
|
|
16
|
+
|
|
17
|
+
- 266e3bc: One door per name: `@pikku/core/ecosystem/*` and the package root are gone
|
|
18
|
+
|
|
19
|
+
`@pikku/core` published every module twice. `ecosystem/http` re-exported
|
|
20
|
+
`./http`, `ecosystem/services` re-exported `./services`, and a name was
|
|
21
|
+
reachable through either — so every addition had to be made in two places, and a
|
|
22
|
+
consumer's import said nothing about what it actually used. The package root was
|
|
23
|
+
the same problem at a larger scale: a single barrel of 206 names that no bundler
|
|
24
|
+
could take apart, and the one specifier that revealed nothing at all.
|
|
25
|
+
|
|
26
|
+
Both are deleted. Every name now lives on the subpath that owns it, and every
|
|
27
|
+
import carries that subpath — `@pikku/core/http`, `@pikku/core/services`,
|
|
28
|
+
`@pikku/core/errors`, `@pikku/core/types`.
|
|
29
|
+
|
|
30
|
+
Deleting the facades meant the raw subpaths had to become a superset of them,
|
|
31
|
+
which they were not: the facade tree had accumulated 25 names with no raw home
|
|
32
|
+
and about 26 more filed under a different area than the module they came from.
|
|
33
|
+
Those names moved to the area that owns them, and three areas were published as
|
|
34
|
+
new entry points rather than left on a root that is going away — `./types` (the
|
|
35
|
+
shared type surface, the largest single destination), `./state` and
|
|
36
|
+
`./classification`.
|
|
37
|
+
|
|
38
|
+
`./classification` is one door onto one subject: what a value is and how it must
|
|
39
|
+
be handled. Its three halves would each have been an entry point — the brands
|
|
40
|
+
and manifest types, the stored-form helpers (`hashToken`, `unsafeAsSealed` and
|
|
41
|
+
friends), and `SecretValue` — split by whether a name happens to be a type or a
|
|
42
|
+
value, which is the same defect as the facades. The duration and versioned-id
|
|
43
|
+
helpers went to `./utils`, which already published, and `PikkuRequest` went to
|
|
44
|
+
`./function`: it is the transport-agnostic request base, not an HTTP one — HTTP
|
|
45
|
+
has `PikkuHTTPAbstractRequest`, and the only thing outside core that extends
|
|
46
|
+
`PikkuRequest` is Azure's timer request.
|
|
47
|
+
|
|
48
|
+
`./types` inherited the root barrel's habit before it inherited its contents, so
|
|
49
|
+
the names with an owner elsewhere were moved off it. The middleware types and the
|
|
50
|
+
five middleware factories — `pikkuMiddleware`, `pikkuMiddlewareFactory`,
|
|
51
|
+
`pikkuChannelMiddleware`, `pikkuChannelMiddlewareFactory` and
|
|
52
|
+
`pikkuAgentMiddleware`, runtime values on a types entry point — are now
|
|
53
|
+
`@pikku/core/middleware`; the function meta types are `@pikku/core/function`;
|
|
54
|
+
`SerializedError` is `@pikku/core/errors`; and the generic TypeScript helpers
|
|
55
|
+
(`MakeRequired`, `PickRequired`, `PickOptional`, `RequireAtLeastOne`,
|
|
56
|
+
`JSONPrimitive`, `JSONValue`) are `@pikku/core/utils`. What is left on `./types`
|
|
57
|
+
is the vocabulary the wirings share, which no single module owns.
|
|
58
|
+
|
|
59
|
+
`pikku` was itself a root barrel — `export * from '@pikku/core'` — and
|
|
60
|
+
now exports only the services it bundles.
|
|
61
|
+
|
|
62
|
+
One module survives at the old specifier, and only for the bootstrap:
|
|
63
|
+
`packages/cli` is generated by the _published_ CLI pinned in its `build.sh`, and
|
|
64
|
+
that CLI still writes a bare `@pikku/core` into the files it generates for the
|
|
65
|
+
CLI itself. `bootstrap-compat/root.ts` carries the eight types it names, a test
|
|
66
|
+
in core fails if that list grows, and it goes when the pin moves to a CLI
|
|
67
|
+
released from this branch. The adapter names the pinned CLI reaches for —
|
|
68
|
+
`pikkuState` and `CreateWireServices` — are rewritten to `@pikku/core/state` and
|
|
69
|
+
`@pikku/core/types` by the same `build.sh` patch pass, so no second shim is
|
|
70
|
+
needed for them.
|
|
71
|
+
|
|
72
|
+
A guard test keeps the root shut: it parses imports and rejects a bare
|
|
73
|
+
`@pikku/core` rather than grepping for it, because several tests hold a user's
|
|
74
|
+
file as a template literal, where `import … from '@pikku/core'` is fixture text
|
|
75
|
+
rather than an import this repo makes.
|
|
76
|
+
|
|
77
|
+
An agent scaffold a project generated under an older CLI is refreshed rather
|
|
78
|
+
than left to fail: `pikku all` already deleted one importing an entry point
|
|
79
|
+
`@pikku/core` no longer publishes, and the `#pikku` hub joins that list.
|
|
80
|
+
Without it a project that scaffolds the agent endpoint but
|
|
81
|
+
declares no agents keeps the old file forever — the generator that would rewrite
|
|
82
|
+
it only runs when agents exist, and the file being present is what stops it
|
|
83
|
+
being regenerated as missing.
|
|
84
|
+
|
|
85
|
+
`pikku new addon` also wrote a tsconfig `paths` map naming only the deleted hub.
|
|
86
|
+
An addon's `imports` map points into `dist`, so `paths` is what resolves
|
|
87
|
+
`#pikku/<leaf>` for the addon's own source build — it now names the two leaf
|
|
88
|
+
patterns, in both the addon and its test harness.
|
|
89
|
+
|
|
90
|
+
- 6eef0a0: Bump every dependency to its latest compatible minor/patch across the monorepo.
|
|
91
|
+
- 20d8a39: Drop better-auth's `admin()` plugin.
|
|
92
|
+
|
|
93
|
+
`admin()` bundles three unrelated things: a `role` column, fifteen HTTP
|
|
94
|
+
endpoints authorized against that column, and the enforcement that stops a
|
|
95
|
+
banned user from getting a session. Pikku only ever wanted the third. The
|
|
96
|
+
endpoints were never reachable directly — each sat behind a pikku function with
|
|
97
|
+
its own `admin:users:*` scope — so all the plugin added was a second gate on a
|
|
98
|
+
column that had to be kept in step with the scopes it duplicated. That sync
|
|
99
|
+
(`syncProjectedAdminRole`, run on every authenticated request) is now gone
|
|
100
|
+
along with the column.
|
|
101
|
+
|
|
102
|
+
User administration is implemented against better-auth's internal adapter
|
|
103
|
+
instead, exported from `@pikku/better-auth` so `@pikku/addon-admin` and the
|
|
104
|
+
`scaffold.userAdmin` generator share one implementation:
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
import {
|
|
108
|
+
createAuthUser,
|
|
109
|
+
deleteAuthUser,
|
|
110
|
+
revokeAuthUserSessions,
|
|
111
|
+
setAuthUserBanned,
|
|
112
|
+
setAuthUserPassword,
|
|
113
|
+
} from '@pikku/better-auth'
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Ban keeps its schema and its enforcement, in a plugin that does nothing else:
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
import { ban } from '@pikku/better-auth'
|
|
120
|
+
|
|
121
|
+
betterAuth({ plugins: [ban()] })
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
`ban()` adds `banned`, `banReason` and `banExpires` to `user`, refuses to create
|
|
125
|
+
a session for a banned user, and lapses an expired ban at the sign-in that would
|
|
126
|
+
otherwise be refused. It makes no authorization decision of its own, so it never
|
|
127
|
+
needs to know about scopes.
|
|
128
|
+
|
|
129
|
+
Breaking:
|
|
130
|
+
|
|
131
|
+
- Remove `admin()` from your better-auth `plugins`, and add `ban()` if you ban
|
|
132
|
+
users. `pikku db generate` writes the migration; `user.role` and
|
|
133
|
+
`session.impersonatedBy` are no longer declared by anything.
|
|
134
|
+
- `callAdminApi`, `AdminApiHttpWire`, `syncProjectedAdminRole`,
|
|
135
|
+
`projectedAdminRole` and `ADMIN_ROLE_SCOPES` are removed. `ADMIN_SCOPES`,
|
|
136
|
+
`ADMIN_SCOPE_ROOT` and `ADMIN_SCOPE_TREE` are unchanged.
|
|
137
|
+
- The `scaffold.userAdmin` codegen no longer fails without `admin()`. It now
|
|
138
|
+
fails only when there is no better-auth at all, and warns when `ban()` is
|
|
139
|
+
missing — banning is one capability of six, so the other five still generate.
|
|
140
|
+
- The scope on each function is now the whole authorization decision. Anywhere
|
|
141
|
+
that relied on `user.role` as a backstop no longer has one.
|
|
142
|
+
|
|
143
|
+
- 727671b: Make the public surface an artifact the CLI produces.
|
|
144
|
+
|
|
145
|
+
`@pikku/cli` now ships `surface.json`, computed when the CLI is built by
|
|
146
|
+
generating one application and one addon and reading what each `#pikku/*` leaf
|
|
147
|
+
exports, plus a curated `@pikku/core` entry point for people building on the
|
|
148
|
+
ecosystem. Consumers resolve it as `@pikku/cli/surface.json`.
|
|
149
|
+
|
|
150
|
+
`pikku all` writes the matching per-project overlay to
|
|
151
|
+
`<outDir>/surface-usage.gen.json`: how often each export is imported and which
|
|
152
|
+
source areas it was seen in. The counting happens inside the sweep the inspector
|
|
153
|
+
already makes over every source file, so a prebuild pays no extra pass.
|
|
154
|
+
|
|
155
|
+
- f25f4a2: Fix seven defects found taking one project through `pikku fabric` to deploy
|
|
156
|
+
|
|
157
|
+
**`deploy plan` rewrote the project's own scaffold.** Per-unit codegen re-runs
|
|
158
|
+
`pikku all` with `--outDir` pointed at a unit's `.pikku`, and scaffold imports
|
|
159
|
+
are computed against `config.outDir` — so `console.gen.ts` came back importing
|
|
160
|
+
`../../../../../.deploy/cloudflare/units/<unit>/.pikku/pikku-types.gen.js` and
|
|
161
|
+
the source stopped typechecking until the next ordinary `pikku all`.
|
|
162
|
+
|
|
163
|
+
A guard for this already existed in four generators and had never once fired:
|
|
164
|
+
`LocalVariablesService.get` runs values through `JSON.parse`, so
|
|
165
|
+
`PIKKU_DEPLOY_CODEGEN=1` arrived as the number `1` and every `=== '1'` test
|
|
166
|
+
was false. The comparison is fixed behind a shared `isDeployCodegen`, and the
|
|
167
|
+
real guard now sits in the file writer, which refuses writes _and removals_
|
|
168
|
+
under the scaffold directory for the duration of a per-unit run. Guarding the
|
|
169
|
+
writer rather than each generator matters here: seven further generators had no
|
|
170
|
+
guard at all, several write scaffold source and `.pikku` artifacts in the same
|
|
171
|
+
pass (so an early return would skip too much), and the legacy-scaffold pruners
|
|
172
|
+
delete from the source tree without going through a generator.
|
|
173
|
+
|
|
174
|
+
**`fabric validate` passed on a project that could not deploy.** Deploy clones
|
|
175
|
+
the repository, so a `pikkufabric.config.json` that exists only in the working
|
|
176
|
+
tree is absent exactly when it is needed, and the build container aborts with
|
|
177
|
+
`pikkufabric.config.json not found in repository root`. Validate now reports
|
|
178
|
+
that as an error, and its success line distinguishes "can be linked" from
|
|
179
|
+
"will deploy" instead of reporting unqualified success at a project that is not
|
|
180
|
+
linked yet.
|
|
181
|
+
|
|
182
|
+
**`description` reached `infra.json` as raw source.** `getPropertyValue` fell
|
|
183
|
+
back to `node.getText()`, which is indistinguishable from the value for a lone
|
|
184
|
+
literal — so nobody noticed that a description written as `'a ' + 'b'` arrived
|
|
185
|
+
with the quotes and the `+` still in it, and rendered that way in the console.
|
|
186
|
+
Compile-time constant strings are now folded, checker-free, so a node that
|
|
187
|
+
cannot be resolved statically still takes the old path.
|
|
188
|
+
|
|
189
|
+
**A wired addon that was not installed failed silently.** A missing package
|
|
190
|
+
makes `resolveAddonMeta` return null, which was caught and downgraded to a
|
|
191
|
+
warning; every `ref('<namespace>:…')` then resolved to nothing and the surface
|
|
192
|
+
was dead at runtime with nothing in the build output saying why. The generated
|
|
193
|
+
console is the common case. `wireAddon` now requires its package to be
|
|
194
|
+
installed (`PKU340`), the mirror of the existing `wireRemoteAddon` check whose
|
|
195
|
+
own docs already described this half as if it existed.
|
|
196
|
+
|
|
197
|
+
**The audit-table check demanded an unquoted identifier.** Kysely's schema
|
|
198
|
+
builder always quotes, so `create table "audit"` read as missing on the
|
|
199
|
+
projects most likely to have it. Both this and the better-auth table checks now
|
|
200
|
+
share one matcher that accepts each dialect's quoting — matched pairs only, so
|
|
201
|
+
`"audit'` is not a hit — plus an optional schema qualifier.
|
|
202
|
+
|
|
203
|
+
**Cloudflare bundles kept `pg`.** `getStubModules()` named `postgres` and
|
|
204
|
+
`kysely-postgres-js` but not `pg`, which is the more common driver in
|
|
205
|
+
application code, equally unreachable on a Worker, and additionally pulls at
|
|
206
|
+
`net`/`tls` and `pg-native`, which a Worker build cannot resolve at all.
|
|
207
|
+
|
|
208
|
+
**The deploy plan listed one secret twice.** Two `defineSecret` calls may
|
|
209
|
+
legally share a `secretId` under different local names — the auth scaffold's
|
|
210
|
+
`betterAuthSecret` alongside a hand-written one is the everyday case — and the
|
|
211
|
+
manifest mapped them straight through, so the plan printed two identical
|
|
212
|
+
`create` lines for one resource and `countUnchanged` counted it twice. Secrets
|
|
213
|
+
and variables are now deduplicated in the manifest itself, where variables were
|
|
214
|
+
already being collapsed by accident downstream.
|
|
215
|
+
|
|
216
|
+
- 20d8a39: Generate the schemas a first build used to leave out.
|
|
217
|
+
|
|
218
|
+
A contract type reaches the schema generator only through a file that imports
|
|
219
|
+
it, and for a type exported by nothing but its own function file that file is
|
|
220
|
+
the RPC internal map — which `pikku all` writes _after_ schemas. On a first
|
|
221
|
+
build there is no map to read yet, so those schemas came out missing from a run
|
|
222
|
+
that otherwise succeeded, and the RPC failed with `MissingSchemaError` on its
|
|
223
|
+
first call in a deployment. A second `pikku all` fixed it, which is why this
|
|
224
|
+
only ever bit fresh checkouts and CI.
|
|
225
|
+
|
|
226
|
+
`pikku all` now re-inspects and re-generates schemas when the build that just
|
|
227
|
+
wrote the RPC internal map for the first time left contract references
|
|
228
|
+
unresolved — the condition PKU463 already reports. Confined to that build: a
|
|
229
|
+
project whose references are unresolved for some other reason would otherwise
|
|
230
|
+
pay a second inspection on every run for a re-generation that cannot help it.
|
|
231
|
+
|
|
232
|
+
`@pikku/inspector` exports `unresolvedSchemaReferences(state)`, the check behind
|
|
233
|
+
PKU463, so the decision can be made without re-deriving it.
|
|
234
|
+
|
|
235
|
+
- 3561d67: feat(graph): per-item `forEach` fanout for declarative workflow graphs
|
|
236
|
+
|
|
237
|
+
A graph node can now run once per element of an upstream array:
|
|
238
|
+
|
|
239
|
+
```ts
|
|
240
|
+
postVideo: {
|
|
241
|
+
forEach: 'getMyVideo', // or (ref) => ref('getMyVideo', 'rows')
|
|
242
|
+
mode: 'sequential', // optional, defaults to 'parallel'
|
|
243
|
+
input: (ref, template, $item) => ({ url: $item('URL VIDEO') }),
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
Each element runs as its own step instance (`postVideo[0]`, `postVideo[1]`, …)
|
|
248
|
+
and the node's result is the ordered array of per-item results, so a fanned node
|
|
249
|
+
chains straight into another `forEach`. Downstream nodes wait for every item. A
|
|
250
|
+
non-array source fails the run loudly instead of coercing.
|
|
251
|
+
|
|
252
|
+
The change is additive: `forEach` and `mode` are new optional node fields, and
|
|
253
|
+
`$item` is appended after `template` so existing `input: (ref) => …` and
|
|
254
|
+
`input: (ref, template) => …` nodes are unchanged.
|
|
255
|
+
|
|
256
|
+
- a91c433: HTTP routes wired with `ref('ns:fn')` now record the addon function id as their own `pikkuFuncId`, the same way the CLI and channel wirings already do, instead of minting a per-route wrapper function and linking it back through `refTarget`. The `refTarget` field is gone from `HTTPWiringMeta`, and the runtime resolves a namespaced route function against the addon package's own metadata.
|
|
257
|
+
- 2b57ca8: A persona can name the `app` they sign into, and a browser run takes a url per app (`--app-url <app>=<url>`, or `appUrls` on the environment). Each actor's browser context navigates against its own app's base, so a product that is more than one frontend can be proved in one run — including a scenario that crosses from one app to the other. A run whose personas name an app nobody gave a url for is refused rather than browsing the wrong app's pages.
|
|
258
|
+
- 456c88b: Keep an addon function's contract on a route that reaches it through `ref()`, whether or not `.pikku` already exists.
|
|
259
|
+
|
|
260
|
+
The input and output types were read off the type checker, which can only see them once the consumer's own RPC map already lists the addon's functions — that is, on the second run. A first, cold generation widened the route's input to the whole `FlattenedRPCMap`, so the same sources produced a different http-map on CI than on a developer's machine, and a client compiled against the good one failed to build against the other. The addon's own metadata says what the contract is either way, and its published declaration file is where those names live.
|
|
261
|
+
|
|
262
|
+
- 727671b: `wireAddon` and `wireRemoteAddon` move from `#pikku/function` to `#pikku/addon`.
|
|
263
|
+
|
|
264
|
+
Installing an addon and authoring one are the same concept from opposite ends,
|
|
265
|
+
so they are one import: an application's `#pikku/addon` carries the two install
|
|
266
|
+
functions, an addon package's carries `pikkuAddonConfig`, `pikkuAddonServices`,
|
|
267
|
+
`pikkuAddonWireServices` and `AddonBaseServices`.
|
|
268
|
+
|
|
269
|
+
Two generation fixes came with it:
|
|
270
|
+
|
|
271
|
+
- `CredentialsMap` is generated as a type alias rather than an interface. An
|
|
272
|
+
interface has no implicit index signature, so it was never assignable to the
|
|
273
|
+
`Record<string, unknown>` that `GetCredential` is constrained by, and every
|
|
274
|
+
generated project reported two errors on its own function types.
|
|
275
|
+
- An unresolved `SingletonServices` type is now `PKU724` instead of a services
|
|
276
|
+
map with no entries in it. Written out, the empty map made every service
|
|
277
|
+
optional and the real failure resurfaced as unrelated "possibly undefined"
|
|
278
|
+
errors in files nobody had touched.
|
|
279
|
+
|
|
280
|
+
- Updated dependencies [7722ceb]
|
|
281
|
+
- Updated dependencies [375c1ff]
|
|
282
|
+
- Updated dependencies [02a70cd]
|
|
283
|
+
- Updated dependencies [aeef159]
|
|
284
|
+
- Updated dependencies [a281de6]
|
|
285
|
+
- Updated dependencies [266e3bc]
|
|
286
|
+
- Updated dependencies [02a70cd]
|
|
287
|
+
- Updated dependencies [786dae5]
|
|
288
|
+
- Updated dependencies [6eef0a0]
|
|
289
|
+
- Updated dependencies [3561d67]
|
|
290
|
+
- Updated dependencies [a91c433]
|
|
291
|
+
- Updated dependencies [02a70cd]
|
|
292
|
+
- Updated dependencies [9537f74]
|
|
293
|
+
- Updated dependencies [2b57ca8]
|
|
294
|
+
- Updated dependencies [266e3bc]
|
|
295
|
+
- Updated dependencies [9fce0f1]
|
|
296
|
+
- Updated dependencies [83683a0]
|
|
297
|
+
- Updated dependencies [456c88b]
|
|
298
|
+
- Updated dependencies [456c88b]
|
|
299
|
+
- Updated dependencies [c127273]
|
|
300
|
+
- @pikku/core@0.12.85
|
|
301
|
+
|
|
1
302
|
## 0.12.60
|
|
2
303
|
|
|
3
304
|
### Patch Changes
|
package/OPTIMIZATION-PLAN.md
CHANGED
|
@@ -44,25 +44,25 @@ node --import tsx src/benchmark.ts <target-dir> <iterations>
|
|
|
44
44
|
|
|
45
45
|
**Dispatch map for `visitRoutes`** (all handlers expect CallExpression + Identifier):
|
|
46
46
|
|
|
47
|
-
| Identifier
|
|
48
|
-
|
|
|
49
|
-
| `wireHTTP`
|
|
50
|
-
| `wireHTTPRoutes`
|
|
51
|
-
| `wireScheduler`
|
|
52
|
-
| `wireTrigger`
|
|
53
|
-
| `wireTriggerSource`
|
|
54
|
-
| `wireQueueWorker`
|
|
55
|
-
| `wireChannel`
|
|
56
|
-
| `wireCLI`
|
|
57
|
-
| `pikkuCLIRender`
|
|
58
|
-
| `wireMCPResource`
|
|
59
|
-
| `wireMCPTool`
|
|
60
|
-
| `wireMCPPrompt`
|
|
61
|
-
| `wireWorkflowGraph`
|
|
62
|
-
| `defineSecret`
|
|
63
|
-
| `defineCredential`
|
|
64
|
-
| `defineScope`
|
|
65
|
-
| `defineVariable`
|
|
47
|
+
| Identifier | Handler |
|
|
48
|
+
| ------------------- | ------------------ |
|
|
49
|
+
| `wireHTTP` | `addHTTPRoute` |
|
|
50
|
+
| `wireHTTPRoutes` | `addHTTPRoutes` |
|
|
51
|
+
| `wireScheduler` | `addSchedule` |
|
|
52
|
+
| `wireTrigger` | `addTrigger` |
|
|
53
|
+
| `wireTriggerSource` | `addTrigger` |
|
|
54
|
+
| `wireQueueWorker` | `addQueueWorker` |
|
|
55
|
+
| `wireChannel` | `addChannel` |
|
|
56
|
+
| `wireCLI` | `addCLI` |
|
|
57
|
+
| `pikkuCLIRender` | `addCLIRenderers` |
|
|
58
|
+
| `wireMCPResource` | `addMCPResource` |
|
|
59
|
+
| `wireMCPTool` | `addMCPTool` |
|
|
60
|
+
| `wireMCPPrompt` | `addMCPPrompt` |
|
|
61
|
+
| `wireWorkflowGraph` | `addWorkflowGraph` |
|
|
62
|
+
| `defineSecret` | `addSecret` |
|
|
63
|
+
| `defineCredential` | `addCredential` |
|
|
64
|
+
| `defineScope` | `addScope` |
|
|
65
|
+
| `defineVariable` | `addVariable` |
|
|
66
66
|
|
|
67
67
|
`addAuth` stays outside the map: it matches several identifiers
|
|
68
68
|
(`betterAuthStatelessSession`, `betterAuthSession`) and gates them on
|
package/dist/add/add-auth.js
CHANGED
|
@@ -62,7 +62,7 @@ const readArrayProp = (obj, name) => {
|
|
|
62
62
|
};
|
|
63
63
|
/**
|
|
64
64
|
* Read the callee name of a `plugins: [...]` entry. better-auth plugins are
|
|
65
|
-
* factory calls (`bearer()`, `twoFactor({ ... })`, `
|
|
65
|
+
* factory calls (`bearer()`, `twoFactor({ ... })`, `ban()`); the entry's id
|
|
66
66
|
* is the called function's name. Member-expression callees (`foo.bar()`) and
|
|
67
67
|
* non-call entries are ignored.
|
|
68
68
|
*/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as ts from 'typescript';
|
|
2
2
|
import { ErrorCode } from '../error-codes.js';
|
|
3
|
-
import type { ChannelMeta } from '@pikku/core/
|
|
3
|
+
import type { ChannelMeta } from '@pikku/core/channel';
|
|
4
4
|
import type { InspectorState, AddWiring } from '../types.js';
|
|
5
5
|
/**
|
|
6
6
|
* Build out the nested message-routes by looking up each handler
|
package/dist/add/add-cli.js
CHANGED
|
@@ -392,6 +392,11 @@ function processOptions(logger, node, typeChecker, inspectorState, inspectorOpti
|
|
|
392
392
|
option.short = optProp.initializer.text;
|
|
393
393
|
}
|
|
394
394
|
break;
|
|
395
|
+
case 'type':
|
|
396
|
+
if (ts.isStringLiteral(optProp.initializer)) {
|
|
397
|
+
option.type = optProp.initializer.text;
|
|
398
|
+
}
|
|
399
|
+
break;
|
|
395
400
|
case 'default':
|
|
396
401
|
// Extract default value from expression
|
|
397
402
|
if (ts.isStringLiteral(optProp.initializer)) {
|
|
@@ -3,7 +3,7 @@ import { detectSchemaVendorOrError } from '../utils/detect-schema-vendor.js';
|
|
|
3
3
|
import { extractFunctionName, funcIdToTypeName, } from '../utils/extract-function-name.js';
|
|
4
4
|
import { extractFunctionNode } from '../utils/extract-function-node.js';
|
|
5
5
|
import { extractUsedWires } from '../utils/extract-services.js';
|
|
6
|
-
import { formatVersionedId, parseVersionedId
|
|
6
|
+
import { formatVersionedId, parseVersionedId } from '@pikku/core/utils';
|
|
7
7
|
/** Binding keys a `pikkuScenarioStep` may declare, in report order. */
|
|
8
8
|
const SCENARIO_SURFACE_KEYS = [
|
|
9
9
|
'browser',
|
|
@@ -415,6 +415,7 @@ export const addFunctions = (logger, node, checker, state, options) => {
|
|
|
415
415
|
let workflowRetries;
|
|
416
416
|
let workflowTimeout;
|
|
417
417
|
let scenarioStepSurfaces;
|
|
418
|
+
let scenarioStepRequiresActor;
|
|
418
419
|
let scenarioStepAddon;
|
|
419
420
|
let scenarioStepTemplate;
|
|
420
421
|
let scopes;
|
|
@@ -549,6 +550,13 @@ export const addFunctions = (logger, node, checker, state, options) => {
|
|
|
549
550
|
scenarioStepSurfaces = declaredSurfaces.length
|
|
550
551
|
? declaredSurfaces
|
|
551
552
|
: undefined;
|
|
553
|
+
// A browser binding cannot be provisioned without a window to open, so it
|
|
554
|
+
// requires an actor whether or not the step said so.
|
|
555
|
+
scenarioStepRequiresActor =
|
|
556
|
+
getPropertyValue(firstArg, 'actor') === true ||
|
|
557
|
+
declaredSurfaces.includes('browser')
|
|
558
|
+
? true
|
|
559
|
+
: undefined;
|
|
552
560
|
}
|
|
553
561
|
scenarioStepTemplate = getPropertyValue(firstArg, 'template');
|
|
554
562
|
scopes = getArrayPropertyValue(firstArg, 'scopes') ?? undefined;
|
|
@@ -992,6 +1000,7 @@ export const addFunctions = (logger, node, checker, state, options) => {
|
|
|
992
1000
|
workflowRetries: workflowRetries ?? undefined,
|
|
993
1001
|
workflowTimeout: workflowTimeout ?? undefined,
|
|
994
1002
|
scenarioStepSurfaces,
|
|
1003
|
+
scenarioStepRequiresActor,
|
|
995
1004
|
// `persona` is the default reading of an unmarked step, so it is left off
|
|
996
1005
|
// rather than written into every step meta a project already has.
|
|
997
1006
|
scenarioStepKind: scenarioStepKind && scenarioStepKind !== 'persona'
|
|
@@ -128,22 +128,27 @@ export function registerHTTPRoute({ obj, state, checker, logger, sourceFile, bas
|
|
|
128
128
|
const packageName = ts.isIdentifier(funcInitializer)
|
|
129
129
|
? resolveAddonName(funcInitializer, checker, state.rpc.wireAddonDeclarations)
|
|
130
130
|
: null;
|
|
131
|
+
// A ref()-wired route points straight at the addon function, the same way the
|
|
132
|
+
// CLI and channel adders record one. The addon's own metadata is the contract
|
|
133
|
+
// — and it is authoritative where the checker is not: `ref('ns:fn')` only
|
|
134
|
+
// types precisely once the consumer's own rpc map already lists the addon's
|
|
135
|
+
// functions, so a cold run inferred the whole `FlattenedRPCMap` and a warm one
|
|
136
|
+
// inferred the real input. The addon's metadata says which it is either way.
|
|
137
|
+
//
|
|
138
|
+
// The route stays the consuming app's all the same, so it records no
|
|
139
|
+
// packageName: that names the package a wire *runs in*, and running this one
|
|
140
|
+
// inside the addon would hand it the addon's middleware and services instead
|
|
141
|
+
// of the app's. `ref` reaches the addon over RPC, which enters it properly.
|
|
131
142
|
if (refAddonTarget) {
|
|
132
143
|
const targetMeta = resolveFunctionMeta(state, refAddonTarget);
|
|
133
144
|
if (!targetMeta) {
|
|
134
145
|
logger.warn(`Skipping route '${fullRoute}': addon function metadata for '${refAddonTarget}' is not available yet.`);
|
|
135
146
|
return;
|
|
136
147
|
}
|
|
148
|
+
funcName = refAddonTarget;
|
|
137
149
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
// determine whether a session is required for ref()-based routes.
|
|
141
|
-
if (refAddonTarget) {
|
|
142
|
-
const targetMeta = resolveFunctionMeta(state, refAddonTarget);
|
|
143
|
-
const inlineMeta = state.functions.meta[funcName];
|
|
144
|
-
if (targetMeta && inlineMeta && targetMeta.sessionless !== undefined) {
|
|
145
|
-
inlineMeta.sessionless = targetMeta.sessionless;
|
|
146
|
-
}
|
|
150
|
+
else {
|
|
151
|
+
ensureFunctionMetadata(state, funcName, fullRoute, funcInitializer, checker, extracted.isHelper);
|
|
147
152
|
}
|
|
148
153
|
// The route's own `auth`, falling back to the group's. Recorded on the meta
|
|
149
154
|
// below so an audit can answer "is this route open?" without re-reading the
|
|
@@ -175,12 +180,11 @@ export function registerHTTPRoute({ obj, state, checker, logger, sourceFile, bas
|
|
|
175
180
|
}
|
|
176
181
|
const input = fnMeta.inputs?.[0] || null;
|
|
177
182
|
const getRouteInputKeys = () => {
|
|
178
|
-
const
|
|
179
|
-
const inputTypes = state.typesLookup.get(targetFuncName);
|
|
183
|
+
const inputTypes = state.typesLookup.get(funcName);
|
|
180
184
|
if (inputTypes && inputTypes.length > 0) {
|
|
181
185
|
return extractTypeKeys(inputTypes[0]);
|
|
182
186
|
}
|
|
183
|
-
const targetMeta = resolveFunctionMeta(state,
|
|
187
|
+
const targetMeta = resolveFunctionMeta(state, funcName);
|
|
184
188
|
if (targetMeta?.inputSchemaName) {
|
|
185
189
|
const schema = state.schemas[targetMeta.inputSchemaName];
|
|
186
190
|
const properties = schema?.properties;
|
|
@@ -203,7 +207,7 @@ export function registerHTTPRoute({ obj, state, checker, logger, sourceFile, bas
|
|
|
203
207
|
const missingParams = params.filter((p) => !inputKeys.includes(p));
|
|
204
208
|
if (missingParams.length > 0) {
|
|
205
209
|
logger.critical(ErrorCode.ROUTE_PARAM_MISMATCH, `Route '${fullRoute}' has path parameter(s) [${missingParams.join(', ')}] ` +
|
|
206
|
-
`not found in function '${
|
|
210
|
+
`not found in function '${funcName}' input type. ` +
|
|
207
211
|
`Input type has: [${inputKeys.join(', ')}]`);
|
|
208
212
|
return;
|
|
209
213
|
}
|
|
@@ -213,7 +217,7 @@ export function registerHTTPRoute({ obj, state, checker, logger, sourceFile, bas
|
|
|
213
217
|
const missingQuery = query.filter((q) => !inputKeys.includes(q));
|
|
214
218
|
if (missingQuery.length > 0) {
|
|
215
219
|
logger.critical(ErrorCode.ROUTE_QUERY_MISMATCH, `Route '${fullRoute}' has query parameter(s) [${missingQuery.join(', ')}] ` +
|
|
216
|
-
`not found in function '${
|
|
220
|
+
`not found in function '${funcName}' input type. ` +
|
|
217
221
|
`Input type has: [${inputKeys.join(', ')}]`);
|
|
218
222
|
return;
|
|
219
223
|
}
|
|
@@ -227,9 +231,6 @@ export function registerHTTPRoute({ obj, state, checker, logger, sourceFile, bas
|
|
|
227
231
|
// Resolve permissions
|
|
228
232
|
const permissions = resolvePermissions(state, obj, tags, checker);
|
|
229
233
|
state.serviceAggregation.usedFunctions.add(funcName);
|
|
230
|
-
if (refAddonTarget) {
|
|
231
|
-
state.serviceAggregation.usedFunctions.add(refAddonTarget);
|
|
232
|
-
}
|
|
233
234
|
extractWireNames(middleware).forEach((name) => state.serviceAggregation.usedMiddleware.add(name));
|
|
234
235
|
extractWireNames(permissions).forEach((name) => state.serviceAggregation.usedPermissions.add(name));
|
|
235
236
|
// Check for SSE
|
|
@@ -240,7 +241,6 @@ export function registerHTTPRoute({ obj, state, checker, logger, sourceFile, bas
|
|
|
240
241
|
state.http.files.add(sourceFile.fileName);
|
|
241
242
|
state.http.meta[method][fullRoute] = {
|
|
242
243
|
pikkuFuncId: funcName,
|
|
243
|
-
...(refAddonTarget && { refTarget: refAddonTarget }),
|
|
244
244
|
...(packageName && { packageName }),
|
|
245
245
|
route: fullRoute,
|
|
246
246
|
sourceFile: sourceFile.fileName,
|
|
@@ -4,6 +4,8 @@ export interface KeyedWiringConfig {
|
|
|
4
4
|
idField: string;
|
|
5
5
|
label: string;
|
|
6
6
|
schemaPrefix: string;
|
|
7
|
+
/** Boolean property carrying this wiring kind's deploy-gate opt-in/opt-out. */
|
|
8
|
+
flagField: string;
|
|
7
9
|
getState: (state: InspectorState) => {
|
|
8
10
|
definitions: any[];
|
|
9
11
|
files: Set<string>;
|
|
@@ -2,7 +2,7 @@ import * as ts from 'typescript';
|
|
|
2
2
|
import { getPropertyValue, getArrayPropertyValue, assertStringLiteralProperty, } from '../utils/get-property-value.js';
|
|
3
3
|
import { ErrorCode } from '../error-codes.js';
|
|
4
4
|
import { detectSchemaVendorOrError } from '../utils/detect-schema-vendor.js';
|
|
5
|
-
import { parseDurationString } from '@pikku/core/
|
|
5
|
+
import { parseDurationString } from '@pikku/core/utils';
|
|
6
6
|
export const createAddKeyedWiring = (config) => {
|
|
7
7
|
return (logger, node, checker, state, _options) => {
|
|
8
8
|
if (!ts.isCallExpression(node)) {
|
|
@@ -29,6 +29,7 @@ export const createAddKeyedWiring = (config) => {
|
|
|
29
29
|
const docsUrlValue = getPropertyValue(obj, 'docsUrl');
|
|
30
30
|
const allowedHostsValue = getArrayPropertyValue(obj, 'allowedHosts');
|
|
31
31
|
const idValue = getPropertyValue(obj, config.idField);
|
|
32
|
+
const flagValue = getPropertyValue(obj, config.flagField) === true;
|
|
32
33
|
let schemaVariableName = null;
|
|
33
34
|
let schemaSourceFile = null;
|
|
34
35
|
let schemaIdentifier = null;
|
|
@@ -107,6 +108,7 @@ export const createAddKeyedWiring = (config) => {
|
|
|
107
108
|
docsUrl: docsUrlValue || undefined,
|
|
108
109
|
allowedHosts: allowedHostsValue || undefined,
|
|
109
110
|
[config.idField]: idValue,
|
|
111
|
+
[config.flagField]: flagValue || undefined,
|
|
110
112
|
schema: schemaLookupName,
|
|
111
113
|
sourceFile,
|
|
112
114
|
});
|
package/dist/add/add-personas.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as ts from 'typescript';
|
|
2
|
-
import { DISPOSITIONS } from '@pikku/core/
|
|
2
|
+
import { DISPOSITIONS } from '@pikku/core/virtual-user';
|
|
3
3
|
import { isRunnablePersona } from '@pikku/core/persona';
|
|
4
4
|
import { ErrorCode } from '../error-codes.js';
|
|
5
5
|
import { claimSingleDeclaration } from '../utils/single-declaration.js';
|
|
@@ -192,6 +192,9 @@ export const addPersonas = (logger, node, _checker, state) => {
|
|
|
192
192
|
const personality = stringProperty(config, 'personality');
|
|
193
193
|
if (personality !== undefined)
|
|
194
194
|
persona.personality = personality;
|
|
195
|
+
const app = stringProperty(config, 'app');
|
|
196
|
+
if (app !== undefined)
|
|
197
|
+
persona.app = app;
|
|
195
198
|
if (disposition !== undefined) {
|
|
196
199
|
persona.disposition = disposition;
|
|
197
200
|
}
|
package/dist/add/add-secret.js
CHANGED
package/dist/add/add-variable.js
CHANGED
|
@@ -38,7 +38,8 @@ export function addWireRemoteAddon(node, state, logger) {
|
|
|
38
38
|
ts.isObjectLiteralExpression(prop.initializer)) {
|
|
39
39
|
hasAuth = true;
|
|
40
40
|
for (const authProp of prop.initializer.properties) {
|
|
41
|
-
if (!ts.isPropertyAssignment(authProp) ||
|
|
41
|
+
if (!ts.isPropertyAssignment(authProp) ||
|
|
42
|
+
!ts.isIdentifier(authProp.name))
|
|
42
43
|
continue;
|
|
43
44
|
if (authProp.name.text === 'credentialId' &&
|
|
44
45
|
ts.isStringLiteral(authProp.initializer)) {
|