@lessly/sdk-app 63.3.0 → 63.4.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/README.md CHANGED
@@ -45,6 +45,38 @@ function, so they survive destructuring (`const { list } = sdk.organization.conn
45
45
  `src/gen/manifest.gen.ts` additionally exports `operations`, the whole tool-name -> level table,
46
46
  for callers that need a level without holding a client.
47
47
 
48
+ ### Composer steps: `compositions`
49
+
50
+ A catalog tool may declare a **composition** — the contract a workflow builder needs to offer that
51
+ operation as a **step**. `src/gen/manifest.gen.ts` exports the whole table, re-exported from the
52
+ package root:
53
+
54
+ ```ts
55
+ import { compositions } from '@lessly/sdk-app';
56
+
57
+ if ('mail_domain_create' in compositions) {
58
+ const step = compositions['mail_domain_create'];
59
+ step.label; // 'Add a domain' — how a builder names the step
60
+ step.completion_event; // 'mail.domain.added' — the event that settles an async step
61
+ step.options; // Record<string, string> — builder-level knobs
62
+ step.pii; // input fields carrying personal data
63
+ step.secrets; // input fields carrying secrets
64
+ }
65
+ ```
66
+
67
+ **Presence is the whole signal.** A key is in the map exactly when the catalog gave that tool a
68
+ composition, and the value may legitimately be `{}` ("composable, nothing further to say"). Ask
69
+ `name in compositions`; a truthiness test on `label` would drop a perfectly composable step.
70
+
71
+ Every member is optional and the SDK reads none of them — the object is carried **verbatim** from
72
+ the catalog into the generated map, so a key the platform adds reaches your App even before this
73
+ SDK's `ToolComposition` type names it. Unlike `operations`, the map is **not** restricted to REST
74
+ tools: composability is a property of the operation, not of its transport, so a ws-bound step is
75
+ listed too.
76
+
77
+ A tool gaining, losing or re-declaring a composition ships as a **minor** — the map only ever gains
78
+ or loses a key, and no exported symbol appears or disappears with it.
79
+
48
80
  Streaming (`<tool>Connect`) factories carry neither field: a socket is neither a read nor a write,
49
81
  and the catalog declares no level for a ws-only tool.
50
82
 
@@ -1,3 +1,4 @@
1
- import type { ToolLevel } from '../runtime/types.js';
1
+ import type { ToolLevel, ToolComposition } from '../runtime/types.js';
2
2
  export declare const namespaces: readonly ["analytics", "brain", "consent", "content", "deployment", "mail", "observe", "organization", "playground", "realtime", "support", "tracking", "users", "waitlist", "workflow"];
3
3
  export declare const operations: Record<string, ToolLevel>;
4
+ export declare const compositions: Record<string, ToolComposition>;
@@ -4,7 +4,8 @@ export { connectStream } from './runtime/connectStream.js';
4
4
  export { LesslyApiError, isAccessDenied } from './runtime/errors.js';
5
5
  export { accessReason } from './runtime/access-reason.js';
6
6
  export { operations } from './runtime/operations.js';
7
- export type { LesslyAppOptions, HttpMethod, Binding, BindingsMap, ParamSpec, ParamIn, ToolLevel, Operation, } from './runtime/types.js';
7
+ export { compositions } from './runtime/compositions.js';
8
+ export type { LesslyAppOptions, HttpMethod, Binding, BindingsMap, ParamSpec, ParamIn, ToolLevel, ToolComposition, Operation, } from './runtime/types.js';
8
9
  export type { WsBinding, WsBindingsMap, LesslyStream, LesslyStreamOpener, StreamCloseInfo, StreamData, WebSocketCtor, WebSocketLike, } from './runtime/types.js';
9
10
  export type { Access, AccessState, AccessApi } from './runtime/access.js';
10
11
  export type { GeneratedClient } from './gen/client.gen.js';
@@ -0,0 +1,16 @@
1
+ import type { ToolComposition } from './types.js';
2
+ /**
3
+ * Every catalog operation usable as a COMPOSER STEP, with the composition contract it declared.
4
+ *
5
+ * Presence is the signal: a key is here exactly when the catalog gave the tool a `composition`,
6
+ * and the value may legitimately be `{}`. So ask `'mail_domain_create' in compositions` — a
7
+ * truthiness test on `label` (or any other member) would drop a perfectly composable step.
8
+ *
9
+ * The generated file is regenerated at publish time from the live catalog, so the map tracks the
10
+ * platform rather than anyone's memory, and the values are carried verbatim — a key the platform
11
+ * adds reaches the App even before this SDK's type names it.
12
+ *
13
+ * Only a re-export: the generated file stays the single source, this narrows it to `Readonly` so
14
+ * a consumer cannot write into the shared object.
15
+ */
16
+ export declare const compositions: Readonly<Record<string, ToolComposition>>;
@@ -10,6 +10,26 @@ export interface ParamSpec {
10
10
  * is the access check's business; this SDK only transports the value it was given.
11
11
  */
12
12
  export type ToolLevel = 'read' | 'write' | 'admin';
13
+ /**
14
+ * The composer contract of a catalog operation: what a workflow builder needs to offer it as a
15
+ * STEP. Presence of an entry in `compositions` is the whole signal — `{}` is a valid, complete
16
+ * declaration ("composable, nothing further to say") and is deliberately distinct from absent
17
+ * ("not a composer step"). Ask `name in compositions`, never `compositions[name].label != null`.
18
+ *
19
+ * Every member is optional and this SDK reads none of them — it transports the object the catalog
20
+ * declared, verbatim: `label` names the step in a builder, `completion_event` is the event that
21
+ * settles an async step, `options` are builder-level knobs, and `pii`/`secrets` name input fields
22
+ * a composer must handle carefully. The platform owns this schema; an index signature is
23
+ * deliberately absent so a consumer reads the named keys type-safely, while the GENERATED map
24
+ * still carries any key the platform adds (the emitter serializes the catalog object as-is).
25
+ */
26
+ export interface ToolComposition {
27
+ label?: string;
28
+ completion_event?: string;
29
+ options?: Record<string, string>;
30
+ pii?: string[];
31
+ secrets?: string[];
32
+ }
13
33
  /**
14
34
  * The identity of a catalog operation, carried by both a `Binding` and every generated method.
15
35
  * `operationKey` is the catalog tool name verbatim (`mail_domains_create`), which is what an
package/dist/index.cjs CHANGED
@@ -11208,6 +11208,7 @@ var operations = {
11208
11208
  "waitlist_signups_list": "read",
11209
11209
  "workflow_health_ping": "read"
11210
11210
  };
11211
+ var compositions = {};
11211
11212
 
11212
11213
  // src/runtime/permission-match.ts
11213
11214
  var LEVELS = ["read", "write", "admin"];
@@ -11444,8 +11445,12 @@ function accessReason(op) {
11444
11445
  // src/runtime/operations.ts
11445
11446
  var operations2 = operations;
11446
11447
 
11448
+ // src/runtime/compositions.ts
11449
+ var compositions2 = compositions;
11450
+
11447
11451
  exports.LesslyApiError = LesslyApiError;
11448
11452
  exports.accessReason = accessReason;
11453
+ exports.compositions = compositions2;
11449
11454
  exports.connectStream = connectStream;
11450
11455
  exports.createLesslyApp = createLesslyApp;
11451
11456
  exports.isAccessDenied = isAccessDenied;