@capacms/sdk 1.0.0-next.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 +678 -0
- package/bin/capa-codegen.js +57 -0
- package/dist/client.d.ts +413 -0
- package/dist/client.js +288 -0
- package/dist/codegen.d.ts +69 -0
- package/dist/codegen.js +188 -0
- package/dist/config.d.ts +60 -0
- package/dist/config.js +15 -0
- package/dist/http.d.ts +67 -0
- package/dist/http.js +144 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +21 -0
- package/dist/next/client.d.ts +294 -0
- package/dist/next/client.js +408 -0
- package/dist/next/index.d.ts +3 -0
- package/dist/next/index.js +9 -0
- package/dist/next/select-types.d.ts +39 -0
- package/dist/next/select-types.js +2 -0
- package/dist/nextjs/index.d.ts +53 -0
- package/dist/nextjs/index.js +165 -0
- package/dist/webhook-signature.d.ts +88 -0
- package/dist/webhook-signature.js +161 -0
- package/dist/webhooks.d.ts +244 -0
- package/dist/webhooks.js +130 -0
- package/package.json +69 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* capa-codegen — write a tenant's generated types to disk.
|
|
4
|
+
*
|
|
5
|
+
* CAPA_BASE_URL=... CAPA_API_KEY=... CAPA_TENANT_ID=... \
|
|
6
|
+
* capa-codegen --out src/capa-types.ts
|
|
7
|
+
*
|
|
8
|
+
* Exit codes: 0 wrote or already current, 1 failed, 2 --check found a diff.
|
|
9
|
+
* `--check` is the CI mode: it fails when the committed file is out of date
|
|
10
|
+
* with the tenant's schema, which is the whole point of committing it.
|
|
11
|
+
*/
|
|
12
|
+
const fs = require("node:fs");
|
|
13
|
+
const path = require("node:path");
|
|
14
|
+
const { generate } = require("../dist/codegen.js");
|
|
15
|
+
|
|
16
|
+
function arg(name, fallback) {
|
|
17
|
+
const i = process.argv.indexOf(name);
|
|
18
|
+
return i === -1 ? fallback : process.argv[i + 1];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function main() {
|
|
22
|
+
const out = arg("--out", "capa-types.ts");
|
|
23
|
+
const check = process.argv.includes("--check");
|
|
24
|
+
const config = {
|
|
25
|
+
baseUrl: process.env.CAPA_BASE_URL || "",
|
|
26
|
+
apiKey: process.env.CAPA_API_KEY || "",
|
|
27
|
+
tenantId: process.env.CAPA_TENANT_ID || "",
|
|
28
|
+
};
|
|
29
|
+
const target = path.resolve(process.cwd(), out);
|
|
30
|
+
const existing = fs.existsSync(target) ? fs.readFileSync(target, "utf8") : null;
|
|
31
|
+
|
|
32
|
+
const result = await generate(config, existing);
|
|
33
|
+
|
|
34
|
+
if (!result.changed) {
|
|
35
|
+
console.log(`capa-codegen: ${out} is up to date (schema ${result.checksum ?? "unknown"}).`);
|
|
36
|
+
return 0;
|
|
37
|
+
}
|
|
38
|
+
if (check) {
|
|
39
|
+
console.error(
|
|
40
|
+
`capa-codegen: ${out} is OUT OF DATE with the tenant schema (${result.checksum}).\n` +
|
|
41
|
+
` Run: capa-codegen --out ${out}\n` +
|
|
42
|
+
` Types now present: ${result.types.join(", ")}`
|
|
43
|
+
);
|
|
44
|
+
return 2;
|
|
45
|
+
}
|
|
46
|
+
fs.writeFileSync(target, result.source, "utf8");
|
|
47
|
+
console.log(`capa-codegen: wrote ${out} — ${result.types.length} types (schema ${result.checksum}).`);
|
|
48
|
+
return 0;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
main().then(
|
|
52
|
+
(code) => process.exit(code),
|
|
53
|
+
(err) => {
|
|
54
|
+
console.error(`capa-codegen: ${err.message}`);
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
);
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* client.ts — the read client, plus the one thing it can write.
|
|
3
|
+
*
|
|
4
|
+
* This file used to say the SDK was read-only "because the surface it talks to
|
|
5
|
+
* is". That was true when it was written and is not any more: the agent surface
|
|
6
|
+
* (#383) put `/v2/agent/*` behind `verifyApiKey`, ADMIN_UI_OVERHAUL 0h.4b added
|
|
7
|
+
* `/v2/agent/workspaces`, and `tenant_api_keys.permission` became a real
|
|
8
|
+
* control (#4646).
|
|
9
|
+
*
|
|
10
|
+
* So `workspaces` writes, and nothing else does. A workspace is NAVIGATION —
|
|
11
|
+
* which models, entries and media folders the admin's left rail keeps in reach,
|
|
12
|
+
* in which folders — so applying one touches no record and deletes nothing. The
|
|
13
|
+
* content writes an SDK could now technically reach need a surface designed for
|
|
14
|
+
* them, not a fourth method quietly added to this object.
|
|
15
|
+
*/
|
|
16
|
+
import { type CapaConfig } from "./config";
|
|
17
|
+
import { type WebhooksResource } from "./webhooks";
|
|
18
|
+
export interface ListOptions {
|
|
19
|
+
limit?: number;
|
|
20
|
+
page?: number;
|
|
21
|
+
/** Relation hops to follow. Higher is much larger. */
|
|
22
|
+
depth?: number;
|
|
23
|
+
sort?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Field filters, applied server-side: `{ handle: "about-us" }` becomes
|
|
26
|
+
* `?handle=about-us`. Verified against a live tenant — a matching value
|
|
27
|
+
* returns the row, a non-matching one returns an empty set.
|
|
28
|
+
*/
|
|
29
|
+
where?: Record<string, string | number | boolean>;
|
|
30
|
+
}
|
|
31
|
+
export interface Page<T> {
|
|
32
|
+
data: T[];
|
|
33
|
+
/**
|
|
34
|
+
* Instance ids positionally matching `data`, `null` only when the API sent
|
|
35
|
+
* no usable id at all. See `instanceIdOf`. Read these rather than `row.id`,
|
|
36
|
+
* which is the model's own field whenever one is named `id`.
|
|
37
|
+
*/
|
|
38
|
+
ids: (string | null)[];
|
|
39
|
+
meta: {
|
|
40
|
+
total?: number;
|
|
41
|
+
totalPages?: number;
|
|
42
|
+
currentPage?: number;
|
|
43
|
+
limit?: number;
|
|
44
|
+
hasNextPage?: boolean | null;
|
|
45
|
+
hasPrevPage?: boolean | null;
|
|
46
|
+
};
|
|
47
|
+
/** Fastly surrogate keys for this response, for the host's CDN purging. */
|
|
48
|
+
cacheTags: string[];
|
|
49
|
+
}
|
|
50
|
+
export interface CapaClient {
|
|
51
|
+
listContent<T = Record<string, unknown>>(namespace: string, options?: ListOptions): Promise<Page<T>>;
|
|
52
|
+
getContentById<T = Record<string, unknown>>(namespace: string, id: string, options?: Pick<ListOptions, "depth">): Promise<T | null>;
|
|
53
|
+
findOne<T = Record<string, unknown>>(namespace: string, where: Record<string, string | number | boolean>, options?: Pick<ListOptions, "depth">): Promise<T | null>;
|
|
54
|
+
search(q: string, options?: {
|
|
55
|
+
namespace?: string;
|
|
56
|
+
limit?: number;
|
|
57
|
+
page?: number;
|
|
58
|
+
}): Promise<SearchHit[]>;
|
|
59
|
+
/** Saved arrangements of the Capa admin's left rail. ADMIN_UI_OVERHAUL 0h. */
|
|
60
|
+
workspaces: WorkspacesResource;
|
|
61
|
+
/** Model schema reads, and the entry-editor layout. ADMIN_UI_OVERHAUL 0m. */
|
|
62
|
+
models: ModelsResource;
|
|
63
|
+
/** Scheduled publishes and unpublishes. docs/PUBLISHING.md. */
|
|
64
|
+
scheduledActions: ScheduledActionsResource;
|
|
65
|
+
/**
|
|
66
|
+
* Webhook endpoints and their deliveries. docs/WEBHOOKS.md.
|
|
67
|
+
*
|
|
68
|
+
* The one resource that needs `accessToken` rather than `apiKey`: the routes
|
|
69
|
+
* behind it have no API key mount at all (publishing spec D8), and every
|
|
70
|
+
* method throws with that message when the token is missing.
|
|
71
|
+
*/
|
|
72
|
+
webhooks: WebhooksResource;
|
|
73
|
+
}
|
|
74
|
+
export type LayoutWidth = "full" | "two_thirds" | "half" | "third";
|
|
75
|
+
/**
|
|
76
|
+
* How a relation field renders. `picker` is a link to the related entry,
|
|
77
|
+
* `inline` a list of expandable rows, and `embedded` (0m.8) the related
|
|
78
|
+
* entry's own fields drawn directly in the parent card.
|
|
79
|
+
*/
|
|
80
|
+
export type LayoutDisplay = "picker" | "inline" | "embedded";
|
|
81
|
+
export interface LayoutInline {
|
|
82
|
+
allowCreate: boolean;
|
|
83
|
+
allowRemove: boolean;
|
|
84
|
+
allowReorder: boolean;
|
|
85
|
+
/** Up to 3 field ids of the RELATED model, shown on a collapsed row. */
|
|
86
|
+
summary: string[];
|
|
87
|
+
}
|
|
88
|
+
export interface LayoutField {
|
|
89
|
+
t: "field";
|
|
90
|
+
/** Layout node id — stable across edits, unique in the document. */
|
|
91
|
+
id: string;
|
|
92
|
+
/** A field id of THIS model. Every field appears at most once. */
|
|
93
|
+
fieldId: string;
|
|
94
|
+
width: LayoutWidth;
|
|
95
|
+
/** Relation fields only. Left out, the related model's `embedByDefault` decides. */
|
|
96
|
+
display?: LayoutDisplay;
|
|
97
|
+
/** Relation fields only. */
|
|
98
|
+
inline?: LayoutInline;
|
|
99
|
+
}
|
|
100
|
+
export interface LayoutCard {
|
|
101
|
+
t: "card";
|
|
102
|
+
id: string;
|
|
103
|
+
title: string;
|
|
104
|
+
description?: string;
|
|
105
|
+
collapsible: boolean;
|
|
106
|
+
collapsed: boolean;
|
|
107
|
+
items: LayoutField[];
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* How one model's entry editor is arranged: cards in a main column and a side
|
|
111
|
+
* column. `null` on a model means the linear editor, which is what every model
|
|
112
|
+
* had before 0m and what a model without a layout still gets.
|
|
113
|
+
*/
|
|
114
|
+
export interface ModelLayout {
|
|
115
|
+
v: 1;
|
|
116
|
+
main: LayoutCard[];
|
|
117
|
+
aside: LayoutCard[];
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* The two model-level facts 0m adds, as `GET /v2/models/:id` carries them.
|
|
121
|
+
*
|
|
122
|
+
* They are read together because a form renderer needs both: the layout says
|
|
123
|
+
* where the fields go, and `embedByDefault` decides what a relation field with
|
|
124
|
+
* no `display` does — including in linear mode, where there is no layout to
|
|
125
|
+
* carry a node at all.
|
|
126
|
+
*/
|
|
127
|
+
export interface ModelLayoutInfo {
|
|
128
|
+
/** The layout document, or null when the model is in linear mode. */
|
|
129
|
+
layout: ModelLayout | null;
|
|
130
|
+
/**
|
|
131
|
+
* Whether a relation field pointing AT this model renders this model's
|
|
132
|
+
* fields inside the parent form by default (0m.8). A layout node's own
|
|
133
|
+
* `display` always wins over it.
|
|
134
|
+
*/
|
|
135
|
+
embedByDefault: boolean;
|
|
136
|
+
}
|
|
137
|
+
export interface ModelsResource {
|
|
138
|
+
/** The layout document, or null when the model is in linear mode. */
|
|
139
|
+
getLayout(id: string): Promise<ModelLayout | null>;
|
|
140
|
+
/** `getLayout` plus the model's pass-through default, in one read. */
|
|
141
|
+
getLayoutInfo(id: string): Promise<ModelLayoutInfo>;
|
|
142
|
+
/**
|
|
143
|
+
* Save a layout, or pass `null` to reset the model to the linear editor.
|
|
144
|
+
*
|
|
145
|
+
* The API validates the document against the model (§0m.1) and answers 400
|
|
146
|
+
* with `{ error, path }` naming the offending node — `CapaError.message`
|
|
147
|
+
* carries both. It stores the NORMALISED document, which is what comes back,
|
|
148
|
+
* so the return value is what the next `getLayout` will return.
|
|
149
|
+
*/
|
|
150
|
+
setLayout(id: string, layout: ModelLayout | null): Promise<ModelLayout | null>;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* One node of a workspace document. Models take a namespace OR an id.
|
|
154
|
+
*
|
|
155
|
+
* §0t made a folder hold ANY of these. 0h had three separate trees keyed by
|
|
156
|
+
* section, so a folder had a kind; the customer names folders now, and a folder
|
|
157
|
+
* called "Config" cannot also mean a kind.
|
|
158
|
+
*/
|
|
159
|
+
export type WorkspaceDocNode = {
|
|
160
|
+
folder: string;
|
|
161
|
+
children?: WorkspaceDocNode[];
|
|
162
|
+
} | {
|
|
163
|
+
model: string;
|
|
164
|
+
} | {
|
|
165
|
+
instance: string;
|
|
166
|
+
} | {
|
|
167
|
+
media_folder: string;
|
|
168
|
+
};
|
|
169
|
+
/**
|
|
170
|
+
* 0h's three-key tree, accepted for ONE more release.
|
|
171
|
+
*
|
|
172
|
+
* Sending it lands the three lists in folders called Models, Content and Media,
|
|
173
|
+
* and a key you omit is left alone even in replace mode — that was 0h's rule
|
|
174
|
+
* for a section it had no key for, and breaking it would turn a grace period
|
|
175
|
+
* into a data-loss bug. Send `WorkspaceDocNode[]` instead.
|
|
176
|
+
*
|
|
177
|
+
* @deprecated Send a `WorkspaceDocNode[]` as `tree`.
|
|
178
|
+
*/
|
|
179
|
+
export interface WorkspaceTreeDocument {
|
|
180
|
+
model?: WorkspaceDocNode[];
|
|
181
|
+
content?: WorkspaceDocNode[];
|
|
182
|
+
/** Media folder ids. Media stays folder-backed; a workspace pins a subset. */
|
|
183
|
+
media?: string[];
|
|
184
|
+
}
|
|
185
|
+
/** What a workspace starts with (§0t). A template is only a folder list. */
|
|
186
|
+
export type WorkspaceTemplate = "blank" | "website" | "catalog";
|
|
187
|
+
/**
|
|
188
|
+
* What `get` returns and `apply` accepts — the SAME shape, so a caller can read
|
|
189
|
+
* one, edit it and write it back without a translation step.
|
|
190
|
+
*/
|
|
191
|
+
export interface WorkspaceDocument {
|
|
192
|
+
id: string;
|
|
193
|
+
name: string;
|
|
194
|
+
icon: string | null;
|
|
195
|
+
visibility: "team" | "private";
|
|
196
|
+
isDefault: boolean;
|
|
197
|
+
/** The top level. There is no root node, so this IS the workspace. */
|
|
198
|
+
tree: WorkspaceDocNode[];
|
|
199
|
+
}
|
|
200
|
+
export interface WorkspaceSummary {
|
|
201
|
+
id: string;
|
|
202
|
+
name: string;
|
|
203
|
+
icon: string | null;
|
|
204
|
+
visibility: "team" | "private";
|
|
205
|
+
isDefault: boolean;
|
|
206
|
+
sortOrder: number;
|
|
207
|
+
assignedRoles: string[];
|
|
208
|
+
createdById: string | null;
|
|
209
|
+
isMine: boolean;
|
|
210
|
+
nodeCount: number;
|
|
211
|
+
createdAt: string;
|
|
212
|
+
updatedAt: string;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* What changed. Read it rather than the final state to find out whether a call
|
|
216
|
+
* did anything: applying the same document twice reports all zeros.
|
|
217
|
+
*/
|
|
218
|
+
export interface WorkspaceChanges {
|
|
219
|
+
created: number;
|
|
220
|
+
moved: number;
|
|
221
|
+
renamed: number;
|
|
222
|
+
removed: number;
|
|
223
|
+
unchanged: number;
|
|
224
|
+
}
|
|
225
|
+
export interface WorkspaceApplyResult {
|
|
226
|
+
workspace: WorkspaceSummary;
|
|
227
|
+
changes: WorkspaceChanges;
|
|
228
|
+
/** Ids and namespaces the document named that this tenant does not have. */
|
|
229
|
+
unresolved?: string[];
|
|
230
|
+
}
|
|
231
|
+
export interface WorkspacesResource {
|
|
232
|
+
list(options?: {
|
|
233
|
+
includePrivate?: boolean;
|
|
234
|
+
}): Promise<{
|
|
235
|
+
workspaces: WorkspaceSummary[];
|
|
236
|
+
currentId: string | null;
|
|
237
|
+
defaultId: string | null;
|
|
238
|
+
}>;
|
|
239
|
+
/** One workspace's summary row, or null. */
|
|
240
|
+
get(id: string): Promise<WorkspaceSummary | null>;
|
|
241
|
+
/** The declarative document — the shape `apply` takes back. */
|
|
242
|
+
getDocument(id: string): Promise<WorkspaceDocument>;
|
|
243
|
+
apply(id: string, document: {
|
|
244
|
+
tree?: WorkspaceDocNode[] | WorkspaceTreeDocument;
|
|
245
|
+
}, options?: {
|
|
246
|
+
mode?: "replace" | "merge";
|
|
247
|
+
}): Promise<WorkspaceApplyResult>;
|
|
248
|
+
create(input: {
|
|
249
|
+
name: string;
|
|
250
|
+
icon?: string | null;
|
|
251
|
+
/** Folders to start with. Ignored when `tree` is given. */
|
|
252
|
+
template?: WorkspaceTemplate;
|
|
253
|
+
tree?: WorkspaceDocNode[] | WorkspaceTreeDocument;
|
|
254
|
+
}): Promise<WorkspaceApplyResult>;
|
|
255
|
+
}
|
|
256
|
+
export type ScheduledActionStatus = "pending" | "running" | "done" | "failed" | "dead" | "cancelled";
|
|
257
|
+
/**
|
|
258
|
+
* One row of the publishing ledger: one thing to do, to one target, at one
|
|
259
|
+
* instant. `versionId: null` means the latest draft AT FIRE TIME, which is the
|
|
260
|
+
* default and the point of the feature (decision D1) — a typo fixed on Tuesday
|
|
261
|
+
* is live when Wednesday's schedule runs.
|
|
262
|
+
*
|
|
263
|
+
* `runAt` is the only column the worker reads. `wallTime` and `timezone` are
|
|
264
|
+
* what the person chose, kept so a screen can show it back and a reschedule can
|
|
265
|
+
* re-resolve it; they are never used to decide when to fire.
|
|
266
|
+
*/
|
|
267
|
+
export interface ScheduledAction {
|
|
268
|
+
id: string;
|
|
269
|
+
tenantId: string;
|
|
270
|
+
batchId: string;
|
|
271
|
+
action: "publish" | "unpublish";
|
|
272
|
+
targetType: "instance" | "model";
|
|
273
|
+
targetId: string;
|
|
274
|
+
versionId: string | null;
|
|
275
|
+
runAt: string;
|
|
276
|
+
/** `runAt` rendered in this row's own zone, ISO with offset. */
|
|
277
|
+
runAtInTimezone: string;
|
|
278
|
+
timezone: string;
|
|
279
|
+
wallTime: string;
|
|
280
|
+
status: ScheduledActionStatus;
|
|
281
|
+
attempts: number;
|
|
282
|
+
lastError: string | null;
|
|
283
|
+
errorCode: string | null;
|
|
284
|
+
/** The version row the publish created. "Why did this go live at 3am". */
|
|
285
|
+
resultVersionId: string | null;
|
|
286
|
+
requestedBy: string | null;
|
|
287
|
+
cancelledBy: string | null;
|
|
288
|
+
cancelledAt: string | null;
|
|
289
|
+
completedAt: string | null;
|
|
290
|
+
retryOfId: string | null;
|
|
291
|
+
createdAt: string;
|
|
292
|
+
updatedAt: string;
|
|
293
|
+
/** `null` when the target row is gone. */
|
|
294
|
+
target: {
|
|
295
|
+
title: string | null;
|
|
296
|
+
modelId: string;
|
|
297
|
+
modelNamespace: string;
|
|
298
|
+
modelName: string;
|
|
299
|
+
} | null;
|
|
300
|
+
[column: string]: unknown;
|
|
301
|
+
}
|
|
302
|
+
/** What the server made of a `wallTime` + `timezone` pair. */
|
|
303
|
+
export interface ResolvedScheduleTime {
|
|
304
|
+
runAt: string;
|
|
305
|
+
wallTime: string;
|
|
306
|
+
timezone: string;
|
|
307
|
+
runAtInTimezone: string;
|
|
308
|
+
/**
|
|
309
|
+
* Non-null when daylight saving moved the time: a wall time that does not
|
|
310
|
+
* exist resolves forward, one that happens twice takes the earlier offset.
|
|
311
|
+
* Written as a sentence to show a person, so show it.
|
|
312
|
+
*/
|
|
313
|
+
note: string | null;
|
|
314
|
+
}
|
|
315
|
+
export interface ScheduledActionTarget {
|
|
316
|
+
/**
|
|
317
|
+
* `"model"` is a session-only target in phase 1. It needs `model:publish`,
|
|
318
|
+
* and no API key bundle grants that, so a model target sent with a key is a
|
|
319
|
+
* 403 every time. Schedule models from the admin until a bundle carries it.
|
|
320
|
+
*/
|
|
321
|
+
type: "instance" | "model";
|
|
322
|
+
id: string;
|
|
323
|
+
/** Omit for the latest draft at fire time, which is what you usually want. */
|
|
324
|
+
versionId?: string;
|
|
325
|
+
}
|
|
326
|
+
export interface CreateScheduledActionsInput {
|
|
327
|
+
action: "publish" | "unpublish";
|
|
328
|
+
targets: ScheduledActionTarget[];
|
|
329
|
+
/** Local wall clock, NO offset: "2026-10-01T09:00". */
|
|
330
|
+
wallTime: string;
|
|
331
|
+
/** IANA name, e.g. "America/New_York". */
|
|
332
|
+
timezone: string;
|
|
333
|
+
}
|
|
334
|
+
export interface CreateScheduledActionsResult {
|
|
335
|
+
batchId: string;
|
|
336
|
+
runAt: string;
|
|
337
|
+
resolved: ResolvedScheduleTime;
|
|
338
|
+
actions: ScheduledAction[];
|
|
339
|
+
/** Ids of actions cancelled to make room. One active action per target per verb. */
|
|
340
|
+
replaced: string[];
|
|
341
|
+
}
|
|
342
|
+
export interface ScheduledActionsPage {
|
|
343
|
+
actions: ScheduledAction[];
|
|
344
|
+
pagination: {
|
|
345
|
+
total: number;
|
|
346
|
+
page: number;
|
|
347
|
+
limit: number;
|
|
348
|
+
totalPages: number;
|
|
349
|
+
hasMore: boolean;
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
export interface ListScheduledActionsOptions {
|
|
353
|
+
status?: ScheduledActionStatus[];
|
|
354
|
+
targetId?: string;
|
|
355
|
+
batchId?: string;
|
|
356
|
+
from?: string;
|
|
357
|
+
to?: string;
|
|
358
|
+
page?: number;
|
|
359
|
+
limit?: number;
|
|
360
|
+
}
|
|
361
|
+
export interface ScheduledActionsResource {
|
|
362
|
+
create(input: CreateScheduledActionsInput): Promise<CreateScheduledActionsResult>;
|
|
363
|
+
list(options?: ListScheduledActionsOptions): Promise<ScheduledActionsPage>;
|
|
364
|
+
get(id: string): Promise<ScheduledAction | null>;
|
|
365
|
+
/**
|
|
366
|
+
* Returns the moved action with the server's `resolved` block attached, the
|
|
367
|
+
* same one `create` returns. Read `resolved.note` before showing a time.
|
|
368
|
+
*/
|
|
369
|
+
reschedule(id: string, when: {
|
|
370
|
+
wallTime: string;
|
|
371
|
+
timezone: string;
|
|
372
|
+
}): Promise<ScheduledAction & {
|
|
373
|
+
resolved: ResolvedScheduleTime;
|
|
374
|
+
}>;
|
|
375
|
+
cancel(id: string): Promise<ScheduledAction>;
|
|
376
|
+
/** Creates a NEW pending row; the failed one keeps its history. */
|
|
377
|
+
retry(id: string): Promise<ScheduledAction>;
|
|
378
|
+
}
|
|
379
|
+
export interface SearchHit {
|
|
380
|
+
/**
|
|
381
|
+
* The instance UUID, via `instanceIdOf`. `null` means the server sent no
|
|
382
|
+
* usable id: an extended search row hoists the model's own fields the same
|
|
383
|
+
* way a content row does, so a model with a field named `id` shadows it, and
|
|
384
|
+
* a server older than #4628 sends no `instanceId` beside it.
|
|
385
|
+
*/
|
|
386
|
+
id: string | null;
|
|
387
|
+
namespace: string | null;
|
|
388
|
+
model?: string;
|
|
389
|
+
title: unknown;
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* The Capa instance id for a row.
|
|
393
|
+
*
|
|
394
|
+
* `instanceId` FIRST, and it is the answer on any current server: #4628 added
|
|
395
|
+
* it to every public read row as the last key, precisely so that one key always
|
|
396
|
+
* means the instance id.
|
|
397
|
+
*
|
|
398
|
+
* `id` is the fallback, and it is a fallback because it is not trustworthy.
|
|
399
|
+
* `GET /v2/api/:ns` builds each row as `{...instance, ...formatInstanceData(instance)}`
|
|
400
|
+
* — the model's own fields are hoisted to the top level and spread SECOND, so a
|
|
401
|
+
* field named `id` overwrites the instance's id and the real UUID is then absent
|
|
402
|
+
* from the row, not merely moved. The same happens to `title` and `tags`. In one
|
|
403
|
+
* ordinary tenant 20 of 20 models have a field named `title` and 7 of 20 have
|
|
404
|
+
* one named `id` (every shopify_* model, plus judge_me_review), so this is the
|
|
405
|
+
* common case. The UUID test is therefore kept for servers older than the fix,
|
|
406
|
+
* where it is the only thing separating an instance id from a Shopify numeric
|
|
407
|
+
* id that happens to live in a field called `id`.
|
|
408
|
+
*
|
|
409
|
+
* `null` means the server sent no usable id at all: an old server AND a
|
|
410
|
+
* shadowing model. `getContentById` cannot be reached for such a row.
|
|
411
|
+
*/
|
|
412
|
+
export declare function instanceIdOf(row: unknown): string | null;
|
|
413
|
+
export declare function createClient(config: CapaConfig): CapaClient;
|