@sprigr/apps-app-sdk 0.11.0 → 0.12.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 +1 -0
- package/dist/index.d.ts +169 -1
- package/dist/index.js +91 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,6 +15,7 @@ The runtime injects the `env.SPRIGR` host object **only on `/__sprigr/*` dispatc
|
|
|
15
15
|
- `canEmit(env)` — whether an emit could reach the platform by either transport. Gate work that only exists to feed an emit on this, not on `env.SPRIGR?.emit`.
|
|
16
16
|
- `withSprigrEmitFallback(env)` — repair `env.SPRIGR.emit` once and leave existing call sites untouched. Matches the host object's contract (resolves `{ ok, eventId, queued }`, throws on non-2xx).
|
|
17
17
|
- `logToPlatform(env, entry | entry[], opts?)`: durable app logging from either context (`env.SPRIGR.log` on dispatch, `POST ${SPRIGR_PLATFORM_BASE}/internal/wfp/log` from an inline route). Rows land in the platform's `system_logs` Analytics Engine dataset (90-day retention, scoped to the install's company, category prefixed with the app slug), so use it instead of a per-webhook or per-tick audit row in your D1: D1 bills every row written, AE does not. Validation throws synchronously on a cap violation (summary 256, detail 4096, metadata JSON 3840, category 64 matching `[A-Za-z0-9._:-]`, 50 entries per call; nothing is ever truncated); after that the promise never rejects and resolves `{ ok: true, written }` or `{ ok: false, error, status?, detail? }`. Pass `{ waitUntil: ctx.waitUntil.bind(ctx) }` on an inline route so the send outlives the response. `withSprigrLogFallback(env, opts?)` installs `env.SPRIGR.log` once for many call sites; `canLog(env)` gates work whose only purpose is a log row; the `SprigrLogEntry` / `SprigrLogFn` types let your env interface declare the host member.
|
|
18
|
+
- `partialUpdateData(env, objects, opts?)`: merge fields into objects already in the app's data index without reading them first (`env.SPRIGR.data.partialUpdate` on dispatch, `POST ${SPRIGR_PLATFORM_BASE}/internal/wfp/data/partial-update` from an inline route). Deep merge: nested objects recurse, arrays and scalars replace wholesale, absent keys survive, `null` overwrites. `createIfNotExists` defaults to `false`; on a sharded logical index every patch must carry the `shard_field` value or the batch fails with `shard_field_invalid`; 1000 objects per call like `import`. Throws on a bad batch before sending (`SprigrDataValidationError`) and on a platform rejection (`.status`, `.error`, `.detail` on the `Error`), the same contract as `import`. `canPartialUpdate(env)` gates a patch step on either transport; the `SprigrDataPartialUpdateOpts` / `SprigrDataPartialUpdateResult` types let your env interface declare the host member.
|
|
18
19
|
- `resolveInstallBridge(env)` / `installTokenPost(bridge, path, body, opts?)`: build your own `/internal/wfp/*` fallback (collections, files, inbox) with the auth and error extraction handled. A non-2xx throws an `Error` whose `.status`, `.error` (the platform's code) and `.detail` are set alongside the message.
|
|
19
20
|
- `overlaySprigr(env, sprigr)` — overlay a patched `SPRIGR` via `Object.create`. Never rebuild a dispatch-path env by spread: the real bindings live on the prototype and `SPRIGR` is non-enumerable, so `{ ...env }` yields an env whose `DB` is `undefined`.
|
|
20
21
|
|
package/dist/index.d.ts
CHANGED
|
@@ -649,6 +649,120 @@ declare function logToPlatform(env: WfpBridgeEnv, input: SprigrLogEntry | Sprigr
|
|
|
649
649
|
*/
|
|
650
650
|
declare function withSprigrLogFallback<E extends WfpBridgeEnv & object>(env: E, opts?: LogToPlatformOptions): E;
|
|
651
651
|
|
|
652
|
+
/**
|
|
653
|
+
* `env.SPRIGR.data.partialUpdate` from BOTH execution contexts.
|
|
654
|
+
*
|
|
655
|
+
* The platform exposes `env.SPRIGR.data.partialUpdate(objects, opts)` on
|
|
656
|
+
* every `/__sprigr/*` dispatch path, backed by
|
|
657
|
+
* `POST /internal/wfp/data/partial-update` on the provisioning worker. It
|
|
658
|
+
* merges fields into objects the app already imported without the app
|
|
659
|
+
* reading them first, which is what turns a read-then-`import` round trip
|
|
660
|
+
* (two platform calls, a race window, and a whole-object rewrite) into one
|
|
661
|
+
* call that touches only the fields named.
|
|
662
|
+
*
|
|
663
|
+
* Merge semantics, identical on both transports because the platform does
|
|
664
|
+
* the merge: nested objects recurse, arrays and scalars replace wholesale,
|
|
665
|
+
* keys the patch does not carry survive, and `null` is a value that
|
|
666
|
+
* overwrites. `createIfNotExists` defaults to `false` so a patch never
|
|
667
|
+
* creates half an object unless asked. On a hash- or date-sharded logical
|
|
668
|
+
* index every patch MUST carry the `shard_field` value or the whole batch
|
|
669
|
+
* fails with `shard_field_invalid`: a patch cannot be routed to its shard
|
|
670
|
+
* otherwise. The per-call cap is the same 1000 objects as `import`.
|
|
671
|
+
*
|
|
672
|
+
* This module carries two things:
|
|
673
|
+
*
|
|
674
|
+
* 1. `buildPartialUpdateBody`, the wire body both transports send, with
|
|
675
|
+
* the client-side checks that reject a batch BEFORE anything is sent
|
|
676
|
+
* (too many objects, a patch without a string `objectID`).
|
|
677
|
+
* 2. The inline-route fallback (`partialUpdateData`, `canPartialUpdate`).
|
|
678
|
+
* Inline Next.js route handlers never receive `env.SPRIGR`, so an app
|
|
679
|
+
* whose provider webhook lands on one has no `data` namespace there.
|
|
680
|
+
* Same escape hatch as `emitMarketplaceEvent` and `logToPlatform`:
|
|
681
|
+
* `POST ${SPRIGR_PLATFORM_BASE}/internal/wfp/data/partial-update`
|
|
682
|
+
* with the `SPRIGR_INSTALL_TOKEN` bearer.
|
|
683
|
+
*
|
|
684
|
+
* Unlike `emit` and `log`, this THROWS on failure, matching the host
|
|
685
|
+
* member and `data.import`: a data write the caller wants the result of
|
|
686
|
+
* must not be reported as a soft `{ ok: false }` a webhook ack path could
|
|
687
|
+
* swallow.
|
|
688
|
+
*
|
|
689
|
+
* Wire contract (workers/provisioning/src/wfp-data.ts in sprigr-team):
|
|
690
|
+
* POST { index?, objects, createIfNotExists? }
|
|
691
|
+
* 200 { ok: true, updated, skippedMissing, index, physical_indexes? }
|
|
692
|
+
* 400 { error, detail, index? } with error one of too_many_objects,
|
|
693
|
+
* invalid_object, unknown_data_index, shard_field_invalid, ...
|
|
694
|
+
* 401 / 404 bad token / inactive install
|
|
695
|
+
*/
|
|
696
|
+
|
|
697
|
+
/** Route the host member and the fallback both call. */
|
|
698
|
+
declare const DATA_PARTIAL_UPDATE_PATH = "/internal/wfp/data/partial-update";
|
|
699
|
+
/** Same per-call cap as `data.import` (`MAX_OBJECTS_PER_CALL` in wfp-data.ts). */
|
|
700
|
+
declare const SPRIGR_DATA_MAX_OBJECTS_PER_CALL = 1000;
|
|
701
|
+
/** One patch: the target `objectID` plus only the fields to merge. */
|
|
702
|
+
type SprigrDataPatch = {
|
|
703
|
+
objectID: string;
|
|
704
|
+
[key: string]: unknown;
|
|
705
|
+
};
|
|
706
|
+
/** The body `POST /internal/wfp/data/partial-update` receives. */
|
|
707
|
+
interface SprigrDataPartialUpdateBody {
|
|
708
|
+
index?: string;
|
|
709
|
+
objects: SprigrDataPatch[];
|
|
710
|
+
createIfNotExists: boolean;
|
|
711
|
+
}
|
|
712
|
+
interface PartialUpdateDataOptions extends SprigrDataPartialUpdateOpts {
|
|
713
|
+
/** Ceiling on the HTTP fallback. No default: a data write is awaited for its result. */
|
|
714
|
+
timeoutMs?: number;
|
|
715
|
+
}
|
|
716
|
+
/**
|
|
717
|
+
* Thrown by `buildPartialUpdateBody` (and therefore by `partialUpdateData`)
|
|
718
|
+
* before anything is sent. `error` is the same code the platform would
|
|
719
|
+
* answer with, so a caller can branch on one vocabulary.
|
|
720
|
+
*/
|
|
721
|
+
declare class SprigrDataValidationError extends Error {
|
|
722
|
+
readonly error: string;
|
|
723
|
+
readonly index?: number;
|
|
724
|
+
constructor(message: string, fields: {
|
|
725
|
+
error: string;
|
|
726
|
+
index?: number;
|
|
727
|
+
});
|
|
728
|
+
}
|
|
729
|
+
/**
|
|
730
|
+
* Build the wire body, rejecting what the platform would reject anyway so
|
|
731
|
+
* the failure is at the call site rather than a 400 in a tail log. Pure.
|
|
732
|
+
* `createIfNotExists` is always explicit in the output so the default is
|
|
733
|
+
* visible on the wire and in tests, never inferred server-side.
|
|
734
|
+
*/
|
|
735
|
+
declare function buildPartialUpdateBody(objects: unknown, opts?: SprigrDataPartialUpdateOpts): SprigrDataPartialUpdateBody;
|
|
736
|
+
/**
|
|
737
|
+
* Whether a partial update could reach the platform at all, by either
|
|
738
|
+
* transport. Gate a "patch the mirror" step on this rather than on
|
|
739
|
+
* `env.SPRIGR?.data?.partialUpdate`, which is absent on every inline route
|
|
740
|
+
* and on wrapper builds older than the platform route.
|
|
741
|
+
*/
|
|
742
|
+
declare function canPartialUpdate(env: WfpBridgeEnv): boolean;
|
|
743
|
+
/**
|
|
744
|
+
* Merge fields into stored objects from any execution context.
|
|
745
|
+
*
|
|
746
|
+
* Prefers the injected `env.SPRIGR.data.partialUpdate`; falls back to the
|
|
747
|
+
* install-token bridge when it is absent (an inline Next route, or a
|
|
748
|
+
* wrapper build that predates the member). Validation runs first and
|
|
749
|
+
* THROWS `SprigrDataValidationError` on a bad batch, before anything is
|
|
750
|
+
* sent. A platform rejection also throws: the `Error` from
|
|
751
|
+
* `installTokenPost` carries `.status`, `.error` (the platform's code, e.g.
|
|
752
|
+
* `shard_field_invalid`) and `.detail`. Nothing here is swallowed.
|
|
753
|
+
*
|
|
754
|
+
* // before: two calls and a whole-object rewrite
|
|
755
|
+
* const { object } = await env.SPRIGR.data.get(orderId, { index: 'orders' });
|
|
756
|
+
* await env.SPRIGR.data.import([{ ...object, status: 'shipped' }], { index: 'orders' });
|
|
757
|
+
*
|
|
758
|
+
* // after: one call, only the named field changes
|
|
759
|
+
* await partialUpdateData(env, [{ objectID: orderId, created_at, status: 'shipped' }], { index: 'orders' });
|
|
760
|
+
*
|
|
761
|
+
* (`created_at` rides along because `orders` is date-sharded on it; an
|
|
762
|
+
* unsharded index needs only `objectID` and the fields to change.)
|
|
763
|
+
*/
|
|
764
|
+
declare function partialUpdateData(env: WfpBridgeEnv, objects: SprigrDataPatch[], opts?: PartialUpdateDataOptions): Promise<SprigrDataPartialUpdateResult>;
|
|
765
|
+
|
|
652
766
|
/**
|
|
653
767
|
* Caller identity stamped by the platform on agent-initiated WFP dispatches.
|
|
654
768
|
*
|
|
@@ -2122,6 +2236,34 @@ interface SprigrDataIndexOpts {
|
|
|
2122
2236
|
/** LOGICAL index name (a `data_indexes` key). See {@link SprigrDataSearchOpts.index}. */
|
|
2123
2237
|
index?: string;
|
|
2124
2238
|
}
|
|
2239
|
+
/** Options for `env.SPRIGR.data.partialUpdate`. */
|
|
2240
|
+
interface SprigrDataPartialUpdateOpts extends SprigrDataIndexOpts {
|
|
2241
|
+
/**
|
|
2242
|
+
* Create an object that does not exist yet from the patch alone. Default
|
|
2243
|
+
* `false`: a patch never creates half an object unless asked, and a
|
|
2244
|
+
* missing target is counted in `skippedMissing` instead of being written.
|
|
2245
|
+
*/
|
|
2246
|
+
createIfNotExists?: boolean;
|
|
2247
|
+
}
|
|
2248
|
+
/** Reply of `env.SPRIGR.data.partialUpdate` (`POST /internal/wfp/data/partial-update`). */
|
|
2249
|
+
interface SprigrDataPartialUpdateResult {
|
|
2250
|
+
ok: true;
|
|
2251
|
+
/** Objects whose stored copy changed. */
|
|
2252
|
+
updated: number;
|
|
2253
|
+
/** Objects that did not exist. Only non-zero when `createIfNotExists` is false. */
|
|
2254
|
+
skippedMissing: number;
|
|
2255
|
+
/**
|
|
2256
|
+
* The logical index name for multi-index apps, else the physical index
|
|
2257
|
+
* that was patched (informational).
|
|
2258
|
+
*/
|
|
2259
|
+
index: string;
|
|
2260
|
+
/** Multi-index apps: what was patched per physical index/shard. */
|
|
2261
|
+
physical_indexes?: Array<{
|
|
2262
|
+
index: string;
|
|
2263
|
+
shard?: string;
|
|
2264
|
+
updated: number;
|
|
2265
|
+
}>;
|
|
2266
|
+
}
|
|
2125
2267
|
/**
|
|
2126
2268
|
* The marketplace install's per-company datastore on Sprigr search,
|
|
2127
2269
|
* injected on `env.SPRIGR` by the platform wrapper for /__sprigr/*
|
|
@@ -2183,6 +2325,32 @@ interface SprigrDataApi {
|
|
|
2183
2325
|
object: Record<string, unknown> | null;
|
|
2184
2326
|
index: string;
|
|
2185
2327
|
}>;
|
|
2328
|
+
/**
|
|
2329
|
+
* Merge fields into existing objects without reading them first. Each
|
|
2330
|
+
* patch MUST carry a string `objectID`. Max 1000 objects per call, the
|
|
2331
|
+
* same cap as `import`. The platform deep-merges each patch onto the
|
|
2332
|
+
* stored object: nested objects recurse, arrays and scalars replace
|
|
2333
|
+
* wholesale, keys you do not send survive. `null` is a value and
|
|
2334
|
+
* overwrites, so strip keys you do not mean to change rather than
|
|
2335
|
+
* sending them as `null` or `undefined`-then-serialised.
|
|
2336
|
+
*
|
|
2337
|
+
* `createIfNotExists` defaults to `false`: a patch never creates half an
|
|
2338
|
+
* object unless asked, and a missing target is counted in
|
|
2339
|
+
* `skippedMissing`. On a hash- or date-sharded logical index every patch
|
|
2340
|
+
* MUST carry the `shard_field` value, or the WHOLE batch fails with
|
|
2341
|
+
* `shard_field_invalid`: a patch cannot be routed to its shard otherwise,
|
|
2342
|
+
* and the platform will not probe every shard to find it. The response's
|
|
2343
|
+
* `physical_indexes` lists what was patched per shard.
|
|
2344
|
+
*
|
|
2345
|
+
* `?`-optional because wrapper builds older than the platform route
|
|
2346
|
+
* predate it. Feature-detect, or call this package's
|
|
2347
|
+
* `partialUpdateData(env, objects, opts)`, which uses this member when
|
|
2348
|
+
* present and the install-token bridge otherwise.
|
|
2349
|
+
*/
|
|
2350
|
+
partialUpdate?(objects: Array<{
|
|
2351
|
+
objectID: string;
|
|
2352
|
+
[key: string]: unknown;
|
|
2353
|
+
}>, opts?: SprigrDataPartialUpdateOpts): Promise<SprigrDataPartialUpdateResult>;
|
|
2186
2354
|
/**
|
|
2187
2355
|
* Delete objects by objectID (mirror maintenance for source-side
|
|
2188
2356
|
* deletions). Idempotent: unknown ids and never-imported indexes are a
|
|
@@ -2371,4 +2539,4 @@ interface ExecutionContextLike {
|
|
|
2371
2539
|
}
|
|
2372
2540
|
type HandlerFn<TArgs, TResult> = (args: TArgs, env: Record<string, unknown>, ctx?: ExecutionContextLike) => Promise<TResult>;
|
|
2373
2541
|
|
|
2374
|
-
export { APPROVAL_GRANTED_KEY, type Actor, type AppApprovalEnvelope, type AppFileListItem, type AppFileUrlArgs, type AppFileUrlResult, type AppFilesEnv, type AppToolEffectsDeclaration, type AppUndoEnvelope, type ApplyPoliciesOptions, type ApprovalGateOptions, type ApprovalSpec, type ArchiveOfferOptions, type ArchiveOfferRefusal, type CaptureJournal, type ConfirmCondition, type ConfirmRule, type ConfirmationPolicy, type D1Like, type D1PreparedStatementLike, DEFAULT_EMIT_TIMEOUT_MS, DEFAULT_LOG_TIMEOUT_MS, DEFAULT_MAX_FILE_BYTES, DEFAULT_MONEY_FIELDS, DEFAULT_WRITE_PREFIXES, type DerivePolicyOptions, type DerivedPolicy, type DispatcherApprovalGate, type DispatcherApprovalOptions, type EmitMarketplaceEventOptions, type EmitResult, type EmitTransport, type EventArgs, type ExecutionContextLike, type FetchFileResult, type FetchWithRetryOptions, type GetAppFileResult, type HandlerFn, type InboxOwner, type InstallBridge, InvalidUndoEnvelopeError, type JournalRowLike, type LogToPlatformOptions, type ManifestDispatchBlock, type ManifestLike, type ManifestToolLike, type MarketplaceEventEmitOpts, type MarketplaceEventSourceIntegration, NotConnectedError, type OAuthBouncerSignals, type OAuthState, type OfferUndoArgs, type PlatformHostEnv, type PolicyCheckInput, type PolicySource, type PutAppFileArgs, type PutAppFileResult, type PutAppFileStreamArgs, type RequireApprovalOptions, type ResolveViewerOptions, type RestoreResult, type RestoreSpec, SPRIGR_LOG_LEVELS, SPRIGR_LOG_LIMITS, type ScheduleArgs, type SprigrDataAggregationCell, type SprigrDataAggregationResult, type SprigrDataAggregationSpec, type SprigrDataApi, type SprigrDataIndexOpts, type SprigrDataSearchOpts, type SprigrDataSearchResult, type SprigrFilesApi, type SprigrFilesApiWithEdit, type SprigrFilesCreateInput, type SprigrFilesCreateResult, type SprigrFilesEditInput, type SprigrFilesEditResult, type SprigrFilesJobResult, type SprigrLogEntry, type SprigrLogFn, type SprigrLogLevel, type SprigrLogResult, SprigrLogValidationError, type ToolArgs, type ToolHandler, type ToolResult, type ToolWrapperOptions, UNIT_SEP, type UndoApplyOptions, type UndoApplyResult, type UndoCaptureSpec, type UndoFidelity, VIEWER_ANONYMOUS, VIEWER_CONTEXT_HEADER, VIEWER_PLATFORM_USER_ID_HEADER, VIEWER_ROLE_HEADER, VIEWER_USER_ID_HEADER, type VerbRule, type ViewerContext, type ViewerContextFailure, type ViewerContextVerification, type ViewerEnv, type WebhookArgs, type WfpBridgeEnv, type WfpEmitReply, actorKey, actorTool, appFileUrl, applyConfirmationPolicies, approvalHash, archiveOfferRefusal, base64ToBytes, buildConfirmationPolicy, buildMarketplaceWebhookUrl, bytesToBase64, canEmit, canLog, checkConfirmationPolicy, commonDestructiveVerbs, constantTimeEqual, createMarketplaceEmitter, createToolWrappers, decodeState, deleteAppFile, deriveConfirmationPolicy, describeMissingBridge, dispatcherApproval, emitMarketplaceEvent, encodeState, fetchFileAsBase64, fetchFileBytes, fetchWithRetry, fullWarning, getAppFile, hmacSha256Hex, installTokenPost, isNotConnectedError, isStagingHost, listAppFiles, logToPlatform, manifestIsFresh, offerUndo, overlaySprigr, ownerFromActorKey, parseActor, putAppFile, putAppFileStream, randomHex, recreatedWarning, refuseWithoutForce, requireApproval, resolveInstallBridge, resolveOAuthBouncerBase, resolveOAuthBouncerCallbackUrl, resolvePlatformWebhookBase, resolveViewerContext, resolveViewerUserId, runUndoApply, safeCapture, seq, serializeManifest, set, tool, undoEnvelope, validateLogEntries, validateLogEntry, verifyViewerToken, withSprigrEmitFallback, withSprigrLogFallback };
|
|
2542
|
+
export { APPROVAL_GRANTED_KEY, type Actor, type AppApprovalEnvelope, type AppFileListItem, type AppFileUrlArgs, type AppFileUrlResult, type AppFilesEnv, type AppToolEffectsDeclaration, type AppUndoEnvelope, type ApplyPoliciesOptions, type ApprovalGateOptions, type ApprovalSpec, type ArchiveOfferOptions, type ArchiveOfferRefusal, type CaptureJournal, type ConfirmCondition, type ConfirmRule, type ConfirmationPolicy, type D1Like, type D1PreparedStatementLike, DATA_PARTIAL_UPDATE_PATH, DEFAULT_EMIT_TIMEOUT_MS, DEFAULT_LOG_TIMEOUT_MS, DEFAULT_MAX_FILE_BYTES, DEFAULT_MONEY_FIELDS, DEFAULT_WRITE_PREFIXES, type DerivePolicyOptions, type DerivedPolicy, type DispatcherApprovalGate, type DispatcherApprovalOptions, type EmitMarketplaceEventOptions, type EmitResult, type EmitTransport, type EventArgs, type ExecutionContextLike, type FetchFileResult, type FetchWithRetryOptions, type GetAppFileResult, type HandlerFn, type InboxOwner, type InstallBridge, InvalidUndoEnvelopeError, type JournalRowLike, type LogToPlatformOptions, type ManifestDispatchBlock, type ManifestLike, type ManifestToolLike, type MarketplaceEventEmitOpts, type MarketplaceEventSourceIntegration, NotConnectedError, type OAuthBouncerSignals, type OAuthState, type OfferUndoArgs, type PartialUpdateDataOptions, type PlatformHostEnv, type PolicyCheckInput, type PolicySource, type PutAppFileArgs, type PutAppFileResult, type PutAppFileStreamArgs, type RequireApprovalOptions, type ResolveViewerOptions, type RestoreResult, type RestoreSpec, SPRIGR_DATA_MAX_OBJECTS_PER_CALL, SPRIGR_LOG_LEVELS, SPRIGR_LOG_LIMITS, type ScheduleArgs, type SprigrDataAggregationCell, type SprigrDataAggregationResult, type SprigrDataAggregationSpec, type SprigrDataApi, type SprigrDataIndexOpts, type SprigrDataPartialUpdateBody, type SprigrDataPartialUpdateOpts, type SprigrDataPartialUpdateResult, type SprigrDataPatch, type SprigrDataSearchOpts, type SprigrDataSearchResult, SprigrDataValidationError, type SprigrFilesApi, type SprigrFilesApiWithEdit, type SprigrFilesCreateInput, type SprigrFilesCreateResult, type SprigrFilesEditInput, type SprigrFilesEditResult, type SprigrFilesJobResult, type SprigrLogEntry, type SprigrLogFn, type SprigrLogLevel, type SprigrLogResult, SprigrLogValidationError, type ToolArgs, type ToolHandler, type ToolResult, type ToolWrapperOptions, UNIT_SEP, type UndoApplyOptions, type UndoApplyResult, type UndoCaptureSpec, type UndoFidelity, VIEWER_ANONYMOUS, VIEWER_CONTEXT_HEADER, VIEWER_PLATFORM_USER_ID_HEADER, VIEWER_ROLE_HEADER, VIEWER_USER_ID_HEADER, type VerbRule, type ViewerContext, type ViewerContextFailure, type ViewerContextVerification, type ViewerEnv, type WebhookArgs, type WfpBridgeEnv, type WfpEmitReply, actorKey, actorTool, appFileUrl, applyConfirmationPolicies, approvalHash, archiveOfferRefusal, base64ToBytes, buildConfirmationPolicy, buildMarketplaceWebhookUrl, buildPartialUpdateBody, bytesToBase64, canEmit, canLog, canPartialUpdate, checkConfirmationPolicy, commonDestructiveVerbs, constantTimeEqual, createMarketplaceEmitter, createToolWrappers, decodeState, deleteAppFile, deriveConfirmationPolicy, describeMissingBridge, dispatcherApproval, emitMarketplaceEvent, encodeState, fetchFileAsBase64, fetchFileBytes, fetchWithRetry, fullWarning, getAppFile, hmacSha256Hex, installTokenPost, isNotConnectedError, isStagingHost, listAppFiles, logToPlatform, manifestIsFresh, offerUndo, overlaySprigr, ownerFromActorKey, parseActor, partialUpdateData, putAppFile, putAppFileStream, randomHex, recreatedWarning, refuseWithoutForce, requireApproval, resolveInstallBridge, resolveOAuthBouncerBase, resolveOAuthBouncerCallbackUrl, resolvePlatformWebhookBase, resolveViewerContext, resolveViewerUserId, runUndoApply, safeCapture, seq, serializeManifest, set, tool, undoEnvelope, validateLogEntries, validateLogEntry, verifyViewerToken, withSprigrEmitFallback, withSprigrLogFallback };
|
package/dist/index.js
CHANGED
|
@@ -509,6 +509,91 @@ function withSprigrLogFallback(env, opts) {
|
|
|
509
509
|
return overlaySprigr(env, { ...existing, log });
|
|
510
510
|
}
|
|
511
511
|
|
|
512
|
+
// src/platform-data.ts
|
|
513
|
+
var DATA_PARTIAL_UPDATE_PATH = "/internal/wfp/data/partial-update";
|
|
514
|
+
var SPRIGR_DATA_MAX_OBJECTS_PER_CALL = 1e3;
|
|
515
|
+
var SprigrDataValidationError = class extends Error {
|
|
516
|
+
error;
|
|
517
|
+
index;
|
|
518
|
+
constructor(message, fields) {
|
|
519
|
+
super(message);
|
|
520
|
+
this.name = "SprigrDataValidationError";
|
|
521
|
+
this.error = fields.error;
|
|
522
|
+
if (fields.index !== void 0) this.index = fields.index;
|
|
523
|
+
}
|
|
524
|
+
};
|
|
525
|
+
function buildPartialUpdateBody(objects, opts) {
|
|
526
|
+
const at = "env.SPRIGR.data.partialUpdate";
|
|
527
|
+
if (!Array.isArray(objects) || objects.length === 0) {
|
|
528
|
+
throw new SprigrDataValidationError(`${at}: objects must be a non-empty array`, {
|
|
529
|
+
error: "invalid_object"
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
if (objects.length > SPRIGR_DATA_MAX_OBJECTS_PER_CALL) {
|
|
533
|
+
throw new SprigrDataValidationError(
|
|
534
|
+
`${at}: at most ${SPRIGR_DATA_MAX_OBJECTS_PER_CALL} objects per call (got ${objects.length}); nothing was sent. Split the batch.`,
|
|
535
|
+
{ error: "too_many_objects" }
|
|
536
|
+
);
|
|
537
|
+
}
|
|
538
|
+
for (let i = 0; i < objects.length; i++) {
|
|
539
|
+
const o = objects[i];
|
|
540
|
+
if (!o || typeof o !== "object" || Array.isArray(o)) {
|
|
541
|
+
throw new SprigrDataValidationError(`${at}: objects[${i}] must be an object`, {
|
|
542
|
+
error: "invalid_object",
|
|
543
|
+
index: i
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
const id = o.objectID;
|
|
547
|
+
if (typeof id !== "string" || id.length === 0) {
|
|
548
|
+
throw new SprigrDataValidationError(
|
|
549
|
+
`${at}: objects[${i}].objectID must be a non-empty string (a patch has to name its target)`,
|
|
550
|
+
{ error: "invalid_object", index: i }
|
|
551
|
+
);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
if (opts?.index !== void 0 && (typeof opts.index !== "string" || opts.index.length === 0)) {
|
|
555
|
+
throw new SprigrDataValidationError(`${at}: index must be a non-empty string when given`, {
|
|
556
|
+
error: "unknown_data_index"
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
return {
|
|
560
|
+
...opts?.index !== void 0 ? { index: opts.index } : {},
|
|
561
|
+
objects,
|
|
562
|
+
createIfNotExists: opts?.createIfNotExists === true
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
function bindingPartialUpdate(env) {
|
|
566
|
+
const data = env.SPRIGR?.data;
|
|
567
|
+
return typeof data?.partialUpdate === "function" ? data.partialUpdate.bind(data) : null;
|
|
568
|
+
}
|
|
569
|
+
function canPartialUpdate(env) {
|
|
570
|
+
return bindingPartialUpdate(env) !== null || resolveInstallBridge(env) !== null;
|
|
571
|
+
}
|
|
572
|
+
function describeMissingDataPath(env) {
|
|
573
|
+
const base = typeof env.SPRIGR_PLATFORM_BASE === "string" && env.SPRIGR_PLATFORM_BASE ? "set" : "unset";
|
|
574
|
+
const token = typeof env.SPRIGR_INSTALL_TOKEN === "string" && env.SPRIGR_INSTALL_TOKEN ? "set" : "unset";
|
|
575
|
+
return `no_data_path (SPRIGR.data.partialUpdate absent, SPRIGR_PLATFORM_BASE=${base}, SPRIGR_INSTALL_TOKEN=${token})`;
|
|
576
|
+
}
|
|
577
|
+
async function partialUpdateData(env, objects, opts) {
|
|
578
|
+
const { timeoutMs, ...dataOpts } = opts ?? {};
|
|
579
|
+
const body = buildPartialUpdateBody(objects, dataOpts);
|
|
580
|
+
const injected = bindingPartialUpdate(env);
|
|
581
|
+
if (injected) {
|
|
582
|
+
return injected(body.objects, {
|
|
583
|
+
...body.index !== void 0 ? { index: body.index } : {},
|
|
584
|
+
createIfNotExists: body.createIfNotExists
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
const bridge = resolveInstallBridge(env);
|
|
588
|
+
if (!bridge) {
|
|
589
|
+
throw new Error(`env.SPRIGR.data.partialUpdate unavailable: ${describeMissingDataPath(env)}`);
|
|
590
|
+
}
|
|
591
|
+
return await installTokenPost(bridge, DATA_PARTIAL_UPDATE_PATH, body, {
|
|
592
|
+
label: "data.partialUpdate",
|
|
593
|
+
...timeoutMs !== void 0 ? { timeoutMs } : {}
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
|
|
512
597
|
// src/actor.ts
|
|
513
598
|
function parseActor(args) {
|
|
514
599
|
if (!args || typeof args !== "object") return void 0;
|
|
@@ -1363,6 +1448,7 @@ function commonDestructiveVerbs(subject) {
|
|
|
1363
1448
|
}
|
|
1364
1449
|
export {
|
|
1365
1450
|
APPROVAL_GRANTED_KEY,
|
|
1451
|
+
DATA_PARTIAL_UPDATE_PATH,
|
|
1366
1452
|
DEFAULT_EMIT_TIMEOUT_MS,
|
|
1367
1453
|
DEFAULT_LOG_TIMEOUT_MS,
|
|
1368
1454
|
DEFAULT_MAX_FILE_BYTES,
|
|
@@ -1370,8 +1456,10 @@ export {
|
|
|
1370
1456
|
DEFAULT_WRITE_PREFIXES,
|
|
1371
1457
|
InvalidUndoEnvelopeError,
|
|
1372
1458
|
NotConnectedError,
|
|
1459
|
+
SPRIGR_DATA_MAX_OBJECTS_PER_CALL,
|
|
1373
1460
|
SPRIGR_LOG_LEVELS,
|
|
1374
1461
|
SPRIGR_LOG_LIMITS,
|
|
1462
|
+
SprigrDataValidationError,
|
|
1375
1463
|
SprigrLogValidationError,
|
|
1376
1464
|
UNIT_SEP,
|
|
1377
1465
|
VIEWER_ANONYMOUS,
|
|
@@ -1388,9 +1476,11 @@ export {
|
|
|
1388
1476
|
base64ToBytes,
|
|
1389
1477
|
buildConfirmationPolicy,
|
|
1390
1478
|
buildMarketplaceWebhookUrl,
|
|
1479
|
+
buildPartialUpdateBody,
|
|
1391
1480
|
bytesToBase64,
|
|
1392
1481
|
canEmit,
|
|
1393
1482
|
canLog,
|
|
1483
|
+
canPartialUpdate,
|
|
1394
1484
|
checkConfirmationPolicy,
|
|
1395
1485
|
commonDestructiveVerbs,
|
|
1396
1486
|
constantTimeEqual,
|
|
@@ -1419,6 +1509,7 @@ export {
|
|
|
1419
1509
|
overlaySprigr,
|
|
1420
1510
|
ownerFromActorKey,
|
|
1421
1511
|
parseActor,
|
|
1512
|
+
partialUpdateData,
|
|
1422
1513
|
putAppFile,
|
|
1423
1514
|
putAppFileStream,
|
|
1424
1515
|
randomHex,
|