@sprigr/apps-app-sdk 0.8.4 → 0.8.5
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 +1 -1
- package/dist/index.d.ts +11 -2
- package/dist/index.js +9 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -73,7 +73,7 @@ Three platform tiers, and they are not substitutes for each other. Full guide: [
|
|
|
73
73
|
- `undoEnvelope({...})` throws on a blank field. The platform drops the whole envelope on a blank and mints nothing, silently.
|
|
74
74
|
- `refuseWithoutForce(name, handler, opts)` / `archiveOfferRefusal(...)`: a delete refuses once and offers the vendor's native archive unless `force: true`.
|
|
75
75
|
- `buildConfirmationPolicy({ irreversible, always, rules })` declares a dispatcher's policy beside its action registry; `checkConfirmationPolicy({ policy, registry, ungated, requiredInput })` returns every silent failure (dead rule, `(unset)` placeholder, money threshold, unclassified write) for a one-line test.
|
|
76
|
-
- `runUndoApply(args, { env, journal, specs, pin })` is the body of your `internal: true` reverse tool: load, re-pin to the journalled connection, restore, drop. `pin` may hand `restore` a different type from the env (a per-actor token state), may throw (`connection_unavailable`) or return null to refuse (`connection_mismatch`); a restore that throws is `restore_failed` and the copy is kept.
|
|
76
|
+
- `runUndoApply(args, { env, journal, specs, pin })` is the body of your `internal: true` reverse tool: load, re-pin to the journalled connection, restore, drop. `pin` may hand `restore` a different type from the env (a per-actor token state), may throw (`connection_unavailable`) or return null to refuse (`connection_mismatch`); a restore that throws is `restore_failed` and the copy is kept; a successful restore may return `newId`, `notRestored`, `extra` (spread into the payload) and `note` (appended after the fidelity sentence).
|
|
77
77
|
- `safeCapture(scope, name, id, read)` and `offerUndo({ journal, entity, id, before, connection, fidelity, resource, describe, warning })`: the capture-then-offer halves for a write that is not behind an approval card (a dispatcher `update_*` action). `requireApproval` uses the same two on its granted pass.
|
|
78
78
|
- `sprigr-check-write-protection` (bin): every destructive-by-name tool or enumerated dispatcher action must carry a policy, or a reason in `apps/<app>/write-protection.json`; ratchets on `tools/write-protection-baseline.json`.
|
|
79
79
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1153,9 +1153,11 @@ interface ApprovalGateOptions<E, P = E> {
|
|
|
1153
1153
|
/**
|
|
1154
1154
|
* Human label for a raw id, looked up THROUGH the pinned connection. Fall
|
|
1155
1155
|
* back to the id on any miss; never guess, a confidently wrong card is worse
|
|
1156
|
-
* than a terse one. Omit to always show the raw id.
|
|
1156
|
+
* than a terse one. Omit to always show the raw id. `name` is the tool, or
|
|
1157
|
+
* for a dispatcher the action, so a lookup can route by resource type when
|
|
1158
|
+
* the id alone does not say what it is (an Asana gid).
|
|
1157
1159
|
*/
|
|
1158
|
-
describeTarget?: (pinned: P, id: string) => Promise<string>;
|
|
1160
|
+
describeTarget?: (pinned: P, id: string, name: string) => Promise<string>;
|
|
1159
1161
|
/**
|
|
1160
1162
|
* Where before-images go. Required when any spec declares `undo`. The
|
|
1161
1163
|
* journal's own capture returns null rather than throwing, and this wrapper
|
|
@@ -1269,6 +1271,13 @@ interface RestoreResult {
|
|
|
1269
1271
|
error?: string;
|
|
1270
1272
|
notRestored?: string;
|
|
1271
1273
|
extra?: Record<string, unknown>;
|
|
1274
|
+
/**
|
|
1275
|
+
* Free-form detail appended to the runner's note (the new gid, rows it
|
|
1276
|
+
* could not refile, a sticker the vendor will not remove). The runner's own
|
|
1277
|
+
* sentence on fidelity stays first so the model reads "replacement, not an
|
|
1278
|
+
* undo" before the detail.
|
|
1279
|
+
*/
|
|
1280
|
+
note?: string;
|
|
1272
1281
|
}
|
|
1273
1282
|
interface JournalRowLike<T = unknown> {
|
|
1274
1283
|
entity: string;
|
package/dist/index.js
CHANGED
|
@@ -617,9 +617,9 @@ function rawIdOf(args, keys) {
|
|
|
617
617
|
function isOk(result) {
|
|
618
618
|
return !!result && typeof result === "object" && result.ok !== false;
|
|
619
619
|
}
|
|
620
|
-
async function safeLabel(fn, pinned, id) {
|
|
620
|
+
async function safeLabel(fn, pinned, id, name) {
|
|
621
621
|
try {
|
|
622
|
-
const label = await fn(pinned, id);
|
|
622
|
+
const label = await fn(pinned, id, name);
|
|
623
623
|
return label && label.trim() ? label : id;
|
|
624
624
|
} catch {
|
|
625
625
|
return id;
|
|
@@ -629,11 +629,11 @@ async function pin(opts, env, connection) {
|
|
|
629
629
|
if (!connection || !opts.pinEnv) return env;
|
|
630
630
|
return opts.pinEnv(env, connection);
|
|
631
631
|
}
|
|
632
|
-
async function askPass(spec, params, env, opts, hashPrefix) {
|
|
632
|
+
async function askPass(name, spec, params, env, opts, hashPrefix) {
|
|
633
633
|
const connection = await opts.resolveConnection(env, params);
|
|
634
634
|
const rawId = rawIdOf(params, spec.keys);
|
|
635
635
|
const pinned = await pin(opts, env, connection);
|
|
636
|
-
const target = rawId && opts.describeTarget ? await safeLabel(opts.describeTarget, pinned, rawId) : rawId || "(unknown id)";
|
|
636
|
+
const target = rawId && opts.describeTarget ? await safeLabel(opts.describeTarget, pinned, rawId, name) : rawId || "(unknown id)";
|
|
637
637
|
const extra = spec.hash ? spec.hash(params) : [];
|
|
638
638
|
return {
|
|
639
639
|
ok: false,
|
|
@@ -688,7 +688,7 @@ function requireApproval(handlers, specs, opts) {
|
|
|
688
688
|
const { [APPROVAL_GRANTED_KEY]: _granted, ...rest } = a;
|
|
689
689
|
return grantedPass(name, spec, rest, env, opts, () => inner(rest, env, ctx));
|
|
690
690
|
}
|
|
691
|
-
return askPass(spec, a, env, opts, []);
|
|
691
|
+
return askPass(name, spec, a, env, opts, []);
|
|
692
692
|
};
|
|
693
693
|
}
|
|
694
694
|
return gated;
|
|
@@ -707,7 +707,7 @@ function dispatcherApproval(specs, opts) {
|
|
|
707
707
|
if (a[APPROVAL_GRANTED_KEY] === true) {
|
|
708
708
|
return grantedPass(action, spec, params, env, opts, write);
|
|
709
709
|
}
|
|
710
|
-
return askPass(spec, params, env, opts, [action]);
|
|
710
|
+
return askPass(action, spec, params, env, opts, [action]);
|
|
711
711
|
}
|
|
712
712
|
};
|
|
713
713
|
}
|
|
@@ -733,7 +733,7 @@ async function runUndoApply(args, opts) {
|
|
|
733
733
|
};
|
|
734
734
|
}
|
|
735
735
|
const before = row.before;
|
|
736
|
-
if (!before || typeof before !== "object") {
|
|
736
|
+
if (!before || typeof before !== "object" || Array.isArray(before)) {
|
|
737
737
|
return { ok: false, error: "before_image_unreadable", note: "The saved copy could not be read back. Nothing was changed." };
|
|
738
738
|
}
|
|
739
739
|
let pinned;
|
|
@@ -769,6 +769,7 @@ async function runUndoApply(args, opts) {
|
|
|
769
769
|
await opts.journal.dropBefore(ref);
|
|
770
770
|
const recreated = spec.fidelity === "recreated";
|
|
771
771
|
const notRestored = result.notRestored ?? spec.notRestored;
|
|
772
|
+
const suffix = result.note && result.note.trim() ? ` ${result.note.trim()}` : "";
|
|
772
773
|
return {
|
|
773
774
|
ok: true,
|
|
774
775
|
...result.extra ?? {},
|
|
@@ -778,7 +779,7 @@ async function runUndoApply(args, opts) {
|
|
|
778
779
|
new_id: result.newId ?? null,
|
|
779
780
|
fidelity: spec.fidelity,
|
|
780
781
|
...notRestored ? { not_restored: notRestored } : {},
|
|
781
|
-
note: recreated ? `Created a NEW ${spec.resource}${result.newId ? ` (${result.newId})` : ""} from the saved copy. The original ${row.original_id} is still gone and its id will never be reissued.${notRestored ? ` Not restored: ${notRestored}.` : ""} Report this as a replacement, not as an undo
|
|
782
|
+
note: recreated ? `Created a NEW ${spec.resource}${result.newId ? ` (${result.newId})` : ""} from the saved copy. The original ${row.original_id} is still gone and its id will never be reissued.${notRestored ? ` Not restored: ${notRestored}.` : ""} Report this as a replacement, not as an undo.${suffix}` : `Restored ${spec.resource} ${row.original_id} to its saved values.${notRestored ? ` Not restored: ${notRestored}.` : ""} Anything changed since the capture was overwritten.${suffix}`
|
|
782
783
|
};
|
|
783
784
|
}
|
|
784
785
|
|