@particle-academy/fancy-connector-core 0.14.0 → 0.15.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 CHANGED
@@ -6,6 +6,33 @@ All notable changes to `fancy-connector-core` are documented here, in
6
6
  **This package is pre-1.0, so breaking changes land in MINOR releases.** The
7
7
  version number is not a promise it can keep yet; the entries below are.
8
8
 
9
+ ## [0.15.0] - 2026-11-08
10
+
11
+ ### Added
12
+
13
+ - **`SetupStep` says who does each step and what it yields.** New optional
14
+ fields, in both runtimes:
15
+ - `actor`: `person` (the default when absent) or `agent`; `SETUP_ACTORS` /
16
+ `Setup::ACTORS` ship it as data.
17
+ - `prompt`: what an agent is asked to do. Required for an agent step.
18
+ - `copy`: `[{label, value}]` values the person pastes somewhere, such as a
19
+ callback URL.
20
+ - `fields`: the credential keys the step yields.
21
+ - `done`: how the person knows the step is done.
22
+
23
+ PHP's `SetupStep` gains `fromArray()` / `toArray()`. Absent stays absent:
24
+ a field nobody wrote is omitted, never null.
25
+ - **`renderSetup` / `Setup::render`: a connector's steps rendered for one
26
+ app.** `{{appUrl}}`, `{{appName}}` and `{{connector}}` are filled in every
27
+ text a person or an agent reads.
28
+ - Any other `{{...}}` is refused as `unknown-token`, so a person never
29
+ pastes a literal brace into a provider console.
30
+ - A token with no value, or an empty one, is refused as `missing-context`,
31
+ so a callback never becomes `/hooks/twilio`.
32
+ - `appUrl` loses one trailing slash first, and a value is never expanded
33
+ again.
34
+ - Held to `fixtures/setup-render/cases.json` in both runtimes.
35
+
9
36
  ## [0.14.0] - 2026-11-07
10
37
 
11
38
  ### Added
package/dist/index.cjs CHANGED
@@ -55,8 +55,12 @@ __export(src_exports, {
55
55
  RENDERER_VERSION: () => RENDERER_VERSION,
56
56
  REVIEW_STALE_DAYS: () => REVIEW_STALE_DAYS,
57
57
  SANDBOX_KINDS: () => SANDBOX_KINDS,
58
+ SETUP_ACTORS: () => SETUP_ACTORS,
59
+ SETUP_RENDER_REASONS: () => SETUP_RENDER_REASONS,
60
+ SETUP_TOKENS: () => SETUP_TOKENS,
58
61
  SIGNED_URI_RULES: () => SIGNED_URI_RULES,
59
62
  SUPPORTED_CONNECTOR_API: () => SUPPORTED_CONNECTOR_API,
63
+ SetupRenderError: () => SetupRenderError,
60
64
  assertConnectorApi: () => assertConnectorApi,
61
65
  byteRangeOf: () => byteRangeOf,
62
66
  callConnector: () => callConnector,
@@ -110,6 +114,7 @@ __export(src_exports, {
110
114
  registerConnectionHost: () => registerConnectionHost,
111
115
  registerTransport: () => registerTransport,
112
116
  render: () => render,
117
+ renderSetup: () => renderSetup,
113
118
  reported: () => reported,
114
119
  resetRateState: () => resetRateState,
115
120
  resolveConnection: () => resolveConnection,
@@ -2496,6 +2501,53 @@ function withResolvedLimit(rules, limit) {
2496
2501
  var CREDENTIAL_SCOPES = ["provider", "account"];
2497
2502
  var PROBLEM_SEVERITIES = ["block", "warn"];
2498
2503
  var CANONICAL_METRICS = ["like", "share", "reply", "quote", "view"];
2504
+ var SETUP_ACTORS = ["person", "agent"];
2505
+
2506
+ // src/setup.ts
2507
+ var SETUP_TOKENS = ["appUrl", "appName", "connector"];
2508
+ var SETUP_RENDER_REASONS = ["unknown-token", "missing-context"];
2509
+ var SetupRenderError = class extends Error {
2510
+ constructor(reason, message) {
2511
+ super(message);
2512
+ this.reason = reason;
2513
+ this.name = "SetupRenderError";
2514
+ }
2515
+ reason;
2516
+ };
2517
+ var TOKEN = /\{\{([^{}]*)\}\}/g;
2518
+ function fill(text, context) {
2519
+ return text.replace(TOKEN, (whole, name) => {
2520
+ if (!SETUP_TOKENS.includes(name)) {
2521
+ throw new SetupRenderError(
2522
+ "unknown-token",
2523
+ `setup step text uses ${whole}, which is not one of ${SETUP_TOKENS.map((t) => `{{${t}}}`).join(", ")}`
2524
+ );
2525
+ }
2526
+ let value = context[name];
2527
+ if (value === void 0 || value === null || value === "") {
2528
+ throw new SetupRenderError("missing-context", `setup step text uses ${whole} and the host gave no value for ${name}`);
2529
+ }
2530
+ if (name === "appUrl" && value.endsWith("/")) value = value.slice(0, -1);
2531
+ return value;
2532
+ });
2533
+ }
2534
+ function renderSetup(steps, context) {
2535
+ return steps.map((step) => {
2536
+ const out = {
2537
+ title: fill(step.title, context),
2538
+ detail: fill(step.detail, context),
2539
+ actor: step.actor ?? "person",
2540
+ fields: [...step.fields ?? []]
2541
+ };
2542
+ if (step.url !== void 0) out.url = fill(step.url, context);
2543
+ if (step.prompt !== void 0) out.prompt = fill(step.prompt, context);
2544
+ if (step.done !== void 0) out.done = fill(step.done, context);
2545
+ if (step.copy !== void 0) {
2546
+ out.copy = step.copy.map((c) => ({ label: fill(c.label, context), value: fill(c.value, context) }));
2547
+ }
2548
+ return out;
2549
+ });
2550
+ }
2499
2551
 
2500
2552
  // src/trigger.ts
2501
2553
  function isOidcJwtSpec(spec) {
@@ -2601,8 +2653,12 @@ function hasDelivery(value) {
2601
2653
  RENDERER_VERSION,
2602
2654
  REVIEW_STALE_DAYS,
2603
2655
  SANDBOX_KINDS,
2656
+ SETUP_ACTORS,
2657
+ SETUP_RENDER_REASONS,
2658
+ SETUP_TOKENS,
2604
2659
  SIGNED_URI_RULES,
2605
2660
  SUPPORTED_CONNECTOR_API,
2661
+ SetupRenderError,
2606
2662
  assertConnectorApi,
2607
2663
  byteRangeOf,
2608
2664
  callConnector,
@@ -2656,6 +2712,7 @@ function hasDelivery(value) {
2656
2712
  registerConnectionHost,
2657
2713
  registerTransport,
2658
2714
  render,
2715
+ renderSetup,
2659
2716
  reported,
2660
2717
  resetRateState,
2661
2718
  resolveConnection,