@zapier/kitcore 0.15.0 → 0.17.0
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 +131 -0
- package/README.md +9 -7
- package/dist/index.cjs +510 -183
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +465 -100
- package/dist/index.d.ts +465 -100
- package/dist/index.mjs +506 -183
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,136 @@
|
|
|
1
1
|
# @zapier/kitcore
|
|
2
2
|
|
|
3
|
+
## 0.17.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 9cde1f6: **`getRegistry(sdk)` reads an SDK's registry without the SDK surfacing
|
|
8
|
+
anything**, and `createController` accepts any built SDK, so introspection costs
|
|
9
|
+
no `getRegistryPlugin` re-export. Re-export it anyway if you want
|
|
10
|
+
`sdk.getRegistry()` for your own callers; both return the same result.
|
|
11
|
+
|
|
12
|
+
Every accessor reads one registry: the free `getRegistry(sdk)`, a re-exported
|
|
13
|
+
`getRegistry()`, and the one a legacy-bridged SDK surfaces all return the same
|
|
14
|
+
memoized object. It is memoized per SDK and per package filter, and every reader
|
|
15
|
+
shares it, so `functions`, `categories`, and each category's own `functions` are
|
|
16
|
+
frozen. Copy before sorting or splicing. The memo lives on the SDK's context, so a process holding two
|
|
17
|
+
copies of kitcore, one bundled into a head and one loaded directly, shares it
|
|
18
|
+
and invalidates it once. A `createPluginStack()` build has no kitcore context and so no
|
|
19
|
+
memo: there the call forwards to the SDK's own `getRegistry()` and hands back a
|
|
20
|
+
fresh, mutable result each time.
|
|
21
|
+
|
|
22
|
+
**A property that declares `dynamicMembers` must have an object value when the
|
|
23
|
+
SDK is built.** `createSdk` throws otherwise, naming the property. The registry
|
|
24
|
+
reports a member like `apps.{appKey}` only while its root is a live object, and
|
|
25
|
+
that answer is memoized, so a root arriving later would leave the registry
|
|
26
|
+
reporting whatever was true when something first read it. Build the root in
|
|
27
|
+
`setup` and return it from `get`.
|
|
28
|
+
|
|
29
|
+
**`defineOverride(method, { ... })` patches how a surface presents a method.**
|
|
30
|
+
Pass the method itself, or a `declareMethod` stand-in when you want to patch one
|
|
31
|
+
without importing it, so no id is respelled and a rename cannot leave a silent
|
|
32
|
+
no-op behind. `namespace` names the override rather than the target, so two
|
|
33
|
+
surfaces can patch the same method in one graph. `defineMethodOverride({ target })`
|
|
34
|
+
still works and warns.
|
|
35
|
+
|
|
36
|
+
**An override patches presentation only.** Its config takes
|
|
37
|
+
`OverridableMetaFields`: `description`, `categories`, `itemType`, `returnType`,
|
|
38
|
+
`packages`, `experimental`, `deprecation`, and `supportsJsonOutput`. Anything
|
|
39
|
+
else throws, including for JavaScript callers the type does not reach. An
|
|
40
|
+
override changes how a surface describes a method, never what it does. A
|
|
41
|
+
method's declared type is fixed at `defineMethod` and nothing re-checks it
|
|
42
|
+
afterwards, so patching output validation, a host's confirmation prompt, or
|
|
43
|
+
which input a caller can pass would let a call fail against a contract its own
|
|
44
|
+
return type says it satisfies. That rules out `outputSchema`, `confirm`, and
|
|
45
|
+
`aliases`, and `type` too, because the registry derives `confirm` from it.
|
|
46
|
+
|
|
47
|
+
**Provide a declared method or property by reference.**
|
|
48
|
+
`defineProperty(ref, { value })` and `defineMethod(ref, { run })` take a
|
|
49
|
+
`declareProperty` / `declareMethod` stand-in instead of a config that respells
|
|
50
|
+
its `name` and `namespace`, so no id string is repeated and `value` and `run`
|
|
51
|
+
are typed against the declaration. It is also how a graph supplies framework
|
|
52
|
+
options as ordinary properties rather than through `createSdk`'s `configuration`
|
|
53
|
+
channel. The method form covers raw output only.
|
|
54
|
+
|
|
55
|
+
**`requireParameters` accepts an absolute path**, which says exactly which value
|
|
56
|
+
a resolver means. A bare name is convenient and can go wrong: it resolves in the
|
|
57
|
+
resolver's own container first, then the root, so when both hold the name the
|
|
58
|
+
container wins and there is no way to say otherwise. An array
|
|
59
|
+
(`[["nested", "owner"]]`) is a path from the root, so it names one place. It also
|
|
60
|
+
reaches a field inside another parameter, which no bare name can address. A
|
|
61
|
+
dotted string is one key, not a path.
|
|
62
|
+
|
|
63
|
+
**A raw method's `outputSchema` is enforced.** Raw has no envelope, so the schema
|
|
64
|
+
is matched against the whole return, and a method that meant to be
|
|
65
|
+
`output: "item"` and returns `{ data }` fails with an error saying so. It
|
|
66
|
+
validates without reshaping: the caller gets the original object back, extras and
|
|
67
|
+
all. **A raw method carrying a schema for projection only needs
|
|
68
|
+
`skipOutputValidation: true`.**
|
|
69
|
+
|
|
70
|
+
**A caller can skip output validation for one call** by passing
|
|
71
|
+
`skipOutputDataValidation: true` alongside an item or list method's input. An
|
|
72
|
+
author's `skipOutputValidation` wins, so a caller can only ever subtract. Raw
|
|
73
|
+
methods do not take it: their call object is entirely the author's, so the key
|
|
74
|
+
there is ordinary input.
|
|
75
|
+
|
|
76
|
+
**A call runs through BOTH schemas.** The framework's own parameters (`cursor`,
|
|
77
|
+
`pageSize`, `maxItems`, `skipOutputDataValidation`) are held to a minimal floor,
|
|
78
|
+
whatever a method declares and even when it declares no `inputSchema` at all.
|
|
79
|
+
The floor rejects only what the machinery cannot act on: `pageSize` at least 1,
|
|
80
|
+
because a page loop asking for zero items does not terminate, `maxItems` at
|
|
81
|
+
least 0, and `cursor` any string.
|
|
82
|
+
|
|
83
|
+
The method's own `inputSchema` then sees the whole call, so a constraint it
|
|
84
|
+
declares on one of those parameters still applies. Write
|
|
85
|
+
`pageSize: z.number().max(100)` and callers get your cap on top of the floor.
|
|
86
|
+
Nothing reads your schema's shape to work this out, so a `.transform()` or
|
|
87
|
+
`.refine()` wrapper cannot hide a declaration.
|
|
88
|
+
|
|
89
|
+
A `strict()` schema is the exception, since it cannot ignore a key it never
|
|
90
|
+
declared. When it rejects a framework parameter by name, that parameter is
|
|
91
|
+
removed and the parse runs again, so the method sees exactly the input it
|
|
92
|
+
described and the error names only the caller's own mistakes.
|
|
93
|
+
|
|
94
|
+
On the way to `run`, the framework's validated value wins for the parameters it
|
|
95
|
+
owns, so a caller asking for `pageSize: 5` gets 5. A list `run` receives the
|
|
96
|
+
`cursor` and `pageSize` of the page it must fetch. `maxItems` and the output
|
|
97
|
+
skip stop at the framework, which is the only thing that can act on them. The
|
|
98
|
+
types say the same: `Parameters<typeof method.run>[0]["input"]` carries the page
|
|
99
|
+
controls and nothing else.
|
|
100
|
+
|
|
101
|
+
**`meta.outputDataValidation` reports what the framework did**, typed
|
|
102
|
+
`OutputDataValidationReport`:
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
| { skipped: true }
|
|
106
|
+
| { skipped: false; droppedPaths: null }
|
|
107
|
+
| { skipped: false; droppedPaths: string[]; instruction: string }
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
`skipped` says whether the framework parsed, never that the data is unchecked.
|
|
111
|
+
`droppedPaths: null` means nothing was dropped, and `instruction` rides only the
|
|
112
|
+
arm where it is actionable. Reading `droppedPaths` requires narrowing on
|
|
113
|
+
`skipped` first. A report appears only when there is something to say: a caller's
|
|
114
|
+
skip that changed something, or paths dropped with the
|
|
115
|
+
`includeOutputValidationDroppedPaths` core option on.
|
|
116
|
+
|
|
117
|
+
The shape and the instruction wording match the connectors SDK, so a consumer
|
|
118
|
+
moving between them reads one report.
|
|
119
|
+
|
|
120
|
+
`meta.outputValidation` is deprecated in favour of it. It is still written, with
|
|
121
|
+
the same `{ droppedPaths }` shape and the same emission rule, and it will be
|
|
122
|
+
removed in a later release.
|
|
123
|
+
|
|
124
|
+
`StandInId` and `SdkContextCarrier` are exported so a package building on
|
|
125
|
+
kitcore can emit declarations that name them. Nothing asks you to write either
|
|
126
|
+
one yourself.
|
|
127
|
+
|
|
128
|
+
## 0.16.0
|
|
129
|
+
|
|
130
|
+
### Minor Changes
|
|
131
|
+
|
|
132
|
+
- cd0616e: Added an optional `callContext` to the `defineProperty` `get` bag, so a property getter can read the current call's context (e.g. its correlation id) when accessed through a method's `imports`. Every method call supplies one, at any depth; it is absent only where no call is in flight — the property bound onto the SDK object itself, and reads from a `setup`-time `imports` bag. Additive — existing property getters are unaffected.
|
|
133
|
+
|
|
3
134
|
## 0.15.0
|
|
4
135
|
|
|
5
136
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -350,21 +350,23 @@ await disposeSdk(sdk, { exitCode: 0 });
|
|
|
350
350
|
|
|
351
351
|
## Introspection
|
|
352
352
|
|
|
353
|
-
|
|
353
|
+
`getRegistry(sdk)` reports the live surface as plain data (one entry per binding, with the leaf's metadata), which is what drives generated docs, CLI commands, and MCP tools. It needs nothing on the SDK itself.
|
|
354
354
|
|
|
355
355
|
```ts
|
|
356
|
-
import {
|
|
356
|
+
import { getRegistry } from "@zapier/kitcore";
|
|
357
357
|
|
|
358
|
-
const sdk = createSdk(
|
|
359
|
-
definePlugin({ name: "api", exports: [greet, getRegistryPlugin] }),
|
|
360
|
-
);
|
|
358
|
+
const sdk = createSdk(definePlugin({ name: "api", exports: [greet] }));
|
|
361
359
|
|
|
362
|
-
const registry =
|
|
360
|
+
const registry = getRegistry(sdk);
|
|
363
361
|
registry.functions; // [{ name, description, inputSchema, ... }]
|
|
364
362
|
registry.categories; // grouped for menus / docs
|
|
365
363
|
```
|
|
366
364
|
|
|
367
|
-
|
|
365
|
+
Re-export the built-in `getRegistryPlugin` if you also want a `getRegistry()` method on the SDK surface for your own callers. It is a thin shim over the same result, so the two agree. Ids are scoped to a graph, so separate SDKs in one process can each register it; what cannot work is one graph pulling in two copies of kitcore, whose built-ins would then collide on the shared `kitcore/getRegistry` id. Introspection does not depend on the re-export either way.
|
|
366
|
+
|
|
367
|
+
The result is memoized per SDK and per package filter, and `addPlugin` drops it, so a registry read still reflects anything added after the build. Because every reader shares that one object, its `functions` and `categories` arrays are frozen: copy before sorting or filtering in place.
|
|
368
|
+
|
|
369
|
+
That holds for an SDK with a kitcore context, which is anything `createSdk` built. An SDK without one, meaning a `createPluginStack()` build, has no memo to share: `getRegistry(sdk)` forwards to the SDK's own `getRegistry()` and hands back whatever it builds, fresh and mutable on every call.
|
|
368
370
|
|
|
369
371
|
## Resolving inputs: controllers
|
|
370
372
|
|