@hollware/server 0.1.0 → 0.2.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/dist/index.d.mts +106 -26
- package/dist/index.mjs +1093 -81
- package/migrations/0003_events_and_schedules.sql +57 -0
- package/migrations/meta/0003_snapshot.json +1406 -0
- package/migrations/meta/_journal.json +7 -0
- package/package.json +4 -4
package/dist/index.d.mts
CHANGED
|
@@ -1,26 +1,6 @@
|
|
|
1
1
|
import { AcknowledgedWarning, EntryDocument, EntryLookup, EntryRef, HollwareConfig, OperationByName, OperationName, ResolvedSite, Scope, Verdict, describeSite, getEntry, getTranslations, listEntries } from "@hollware/core";
|
|
2
2
|
import * as z from "zod";
|
|
3
3
|
import { WorkerEntrypoint } from "cloudflare:workers";
|
|
4
|
-
//#region src/auth/types.d.ts
|
|
5
|
-
/**
|
|
6
|
-
* Who calls an operation. The gateway turns each request into a principal before any handler
|
|
7
|
-
* runs, and the handlers check their scopes against it at call time (ADR-019).
|
|
8
|
-
*/
|
|
9
|
-
type Principal = {
|
|
10
|
-
/** A personal token. */
|
|
11
|
-
readonly kind: 'token';
|
|
12
|
-
readonly userId: string;
|
|
13
|
-
readonly tokenId: string;
|
|
14
|
-
/** The site the token belongs to; it never reaches another one. */
|
|
15
|
-
readonly site: string;
|
|
16
|
-
/** The token's own scopes intersected with those of its user's role, as of now. */
|
|
17
|
-
readonly scopes: readonly Scope[];
|
|
18
|
-
} | {
|
|
19
|
-
/** A Worker of the same account, over the RPC binding: it reads published content. */
|
|
20
|
-
readonly kind: 'binding';
|
|
21
|
-
readonly scopes: readonly ['content:read'];
|
|
22
|
-
};
|
|
23
|
-
//#endregion
|
|
24
4
|
//#region src/ports.d.ts
|
|
25
5
|
/**
|
|
26
6
|
* The ports of the operation handlers: what they need from the world, as interfaces. The D1
|
|
@@ -142,6 +122,32 @@ type WriteRefusal = {
|
|
|
142
122
|
readonly bytes: number;
|
|
143
123
|
readonly limit: number;
|
|
144
124
|
};
|
|
125
|
+
/** A scheduled publication, as the cron trigger reads it. */
|
|
126
|
+
interface StoredSchedule {
|
|
127
|
+
readonly entryId: string;
|
|
128
|
+
readonly scheduledAt: string;
|
|
129
|
+
/** The version the entry had once scheduled; another one means it changed since. */
|
|
130
|
+
readonly version: number;
|
|
131
|
+
readonly acknowledged: readonly AcknowledgedWarning[];
|
|
132
|
+
readonly actor: Actor;
|
|
133
|
+
}
|
|
134
|
+
/** One entry of a publication: what `publish` and `publishGroup` write for it. */
|
|
135
|
+
interface PublishWrite {
|
|
136
|
+
readonly entryId: string;
|
|
137
|
+
readonly expectedVersion: number;
|
|
138
|
+
readonly verdict: Verdict;
|
|
139
|
+
readonly acknowledged: readonly AcknowledgedWarning[];
|
|
140
|
+
readonly actor: Actor;
|
|
141
|
+
/** What orders the entry in published listings. */
|
|
142
|
+
readonly sortKey: string;
|
|
143
|
+
/** The event of the publication, written to the outbox in the same batch (ADR-025). */
|
|
144
|
+
readonly event?: OutboxEvent | null;
|
|
145
|
+
}
|
|
146
|
+
/** An event for the outbox: its id and what subscribers get, as JSON. */
|
|
147
|
+
interface OutboxEvent {
|
|
148
|
+
readonly id: string;
|
|
149
|
+
readonly payload: string;
|
|
150
|
+
}
|
|
145
151
|
interface ContentStore {
|
|
146
152
|
/** The entry with that collection, locale and slug, in the given view, or `null`. */
|
|
147
153
|
findEntry(site: string, ref: EntryRef, view: View): Promise<EntryView | null>;
|
|
@@ -186,22 +192,44 @@ interface ContentStore {
|
|
|
186
192
|
* Publishes the head revision, if the entry is still at `expectedVersion`, and appends the
|
|
187
193
|
* publication with its verdict and acknowledged warnings.
|
|
188
194
|
*/
|
|
189
|
-
publish(site: string, write: {
|
|
195
|
+
publish(site: string, write: PublishWrite): Promise<{
|
|
196
|
+
readonly outcome: 'published';
|
|
197
|
+
readonly view: EntryView;
|
|
198
|
+
} | WriteRefusal>;
|
|
199
|
+
/**
|
|
200
|
+
* Publishes the head revisions of a group of entries in one batch, all or none (ADR-024): every
|
|
201
|
+
* entry must still be at its `expectedVersion`. A refusal names the entry that caused it.
|
|
202
|
+
*/
|
|
203
|
+
publishGroup(site: string, writes: readonly PublishWrite[]): Promise<{
|
|
204
|
+
readonly outcome: 'published';
|
|
205
|
+
readonly views: readonly EntryView[];
|
|
206
|
+
} | (WriteRefusal & {
|
|
207
|
+
readonly entryId: string;
|
|
208
|
+
})>;
|
|
209
|
+
/**
|
|
210
|
+
* Schedules the publication of an entry that is not published, if it is still at
|
|
211
|
+
* `expectedVersion`: the entry becomes `scheduled` at the next version, and its schedule keeps
|
|
212
|
+
* the acknowledged warnings and the actor for the cron trigger (ADR-025).
|
|
213
|
+
*/
|
|
214
|
+
schedule(site: string, write: {
|
|
190
215
|
readonly entryId: string;
|
|
191
216
|
readonly expectedVersion: number;
|
|
192
|
-
readonly
|
|
217
|
+
readonly scheduledAt: string;
|
|
193
218
|
readonly acknowledged: readonly AcknowledgedWarning[];
|
|
194
219
|
readonly actor: Actor;
|
|
195
|
-
/** What orders the entry in published listings. */
|
|
196
|
-
readonly sortKey: string;
|
|
197
220
|
}): Promise<{
|
|
198
|
-
readonly outcome: '
|
|
221
|
+
readonly outcome: 'scheduled';
|
|
199
222
|
readonly view: EntryView;
|
|
200
223
|
} | WriteRefusal>;
|
|
224
|
+
/** The schedules whose time has come, at most 50, oldest first. */
|
|
225
|
+
dueSchedules(site: string, now: string): Promise<readonly StoredSchedule[]>;
|
|
226
|
+
/** Takes a scheduled entry back to a draft and drops its schedule. */
|
|
227
|
+
cancelSchedule(site: string, entryId: string): Promise<void>;
|
|
201
228
|
/** Takes the entry off the public site and appends the unpublish. */
|
|
202
229
|
unpublish(site: string, write: {
|
|
203
230
|
readonly entryId: string;
|
|
204
231
|
readonly actor: Actor;
|
|
232
|
+
readonly event?: OutboxEvent | null;
|
|
205
233
|
}): Promise<{
|
|
206
234
|
readonly outcome: 'unpublished';
|
|
207
235
|
readonly view: EntryView;
|
|
@@ -212,6 +240,45 @@ interface Clock {
|
|
|
212
240
|
now(): Date;
|
|
213
241
|
}
|
|
214
242
|
//#endregion
|
|
243
|
+
//#region src/events/run.d.ts
|
|
244
|
+
/** A message of the events Queue: the site and the id of an outbox row. */
|
|
245
|
+
interface EventMessage {
|
|
246
|
+
readonly site: string;
|
|
247
|
+
readonly id: string;
|
|
248
|
+
}
|
|
249
|
+
/** The part of a Queue binding that sends. */
|
|
250
|
+
interface EventQueue {
|
|
251
|
+
sendBatch(messages: Iterable<{
|
|
252
|
+
readonly body: EventMessage;
|
|
253
|
+
}>): Promise<unknown>;
|
|
254
|
+
}
|
|
255
|
+
/** The part of a Queue message the consumer uses; its body is checked before use. */
|
|
256
|
+
interface EventDelivery {
|
|
257
|
+
readonly body: unknown;
|
|
258
|
+
ack(): void;
|
|
259
|
+
retry(): void;
|
|
260
|
+
}
|
|
261
|
+
//#endregion
|
|
262
|
+
//#region src/auth/types.d.ts
|
|
263
|
+
/**
|
|
264
|
+
* Who calls an operation. The gateway turns each request into a principal before any handler
|
|
265
|
+
* runs, and the handlers check their scopes against it at call time (ADR-019).
|
|
266
|
+
*/
|
|
267
|
+
type Principal = {
|
|
268
|
+
/** A personal token. */
|
|
269
|
+
readonly kind: 'token';
|
|
270
|
+
readonly userId: string;
|
|
271
|
+
readonly tokenId: string;
|
|
272
|
+
/** The site the token belongs to; it never reaches another one. */
|
|
273
|
+
readonly site: string;
|
|
274
|
+
/** The token's own scopes intersected with those of its user's role, as of now. */
|
|
275
|
+
readonly scopes: readonly Scope[];
|
|
276
|
+
} | {
|
|
277
|
+
/** A Worker of the same account, over the RPC binding: it reads published content. */
|
|
278
|
+
readonly kind: 'binding';
|
|
279
|
+
readonly scopes: readonly ['content:read'];
|
|
280
|
+
};
|
|
281
|
+
//#endregion
|
|
215
282
|
//#region src/ops/types.d.ts
|
|
216
283
|
/**
|
|
217
284
|
* The handlers of the operations (ADR-017): one per spec of `@hollware/core`, paired by type,
|
|
@@ -228,6 +295,11 @@ interface OperationContext {
|
|
|
228
295
|
/** What the client said about itself; writes record it as the actor's meta. */
|
|
229
296
|
readonly client: Readonly<Record<string, unknown>> | null;
|
|
230
297
|
readonly requestId: string;
|
|
298
|
+
/**
|
|
299
|
+
* Called with the ids of the events that a write committed to the outbox, so that they reach
|
|
300
|
+
* the Queue now rather than at the next sweep of the cron trigger (ADR-025). Absent in tests.
|
|
301
|
+
*/
|
|
302
|
+
readonly notify?: (eventIds: readonly string[]) => void;
|
|
231
303
|
}
|
|
232
304
|
/** The handler of one operation: its parsed input in, its output out. */
|
|
233
305
|
type OperationHandler<Name extends OperationName> = (input: z.output<OperationByName<Name>['input']>, context: OperationContext) => Promise<z.output<OperationByName<Name>['output']>>;
|
|
@@ -266,6 +338,8 @@ export interface HollwareEnv {
|
|
|
266
338
|
* Origin the Worker answers; without it, every request fails.
|
|
267
339
|
*/
|
|
268
340
|
readonly HOLLWARE_PUBLIC_URL: string;
|
|
341
|
+
/** The Queue of publication events (ADR-025); without it, the cron trigger delivers them. */
|
|
342
|
+
readonly EVENTS?: EventQueue;
|
|
269
343
|
}
|
|
270
344
|
type Output<Spec extends {
|
|
271
345
|
output: z.ZodType;
|
|
@@ -294,6 +368,12 @@ export interface HollwareRpc {
|
|
|
294
368
|
export interface HollwareWorker {
|
|
295
369
|
/** MCP at `/mcp`, and the other routes of the gateway. */
|
|
296
370
|
readonly fetch: (request: Request, env: HollwareEnv, ctx: ExecutionContext) => Promise<Response>;
|
|
371
|
+
/** The consumer of the events Queue (`queues.consumers` in wrangler.jsonc). */
|
|
372
|
+
readonly queue: (batch: {
|
|
373
|
+
readonly messages: readonly EventDelivery[];
|
|
374
|
+
}, env: HollwareEnv, ctx: ExecutionContext) => Promise<void>;
|
|
375
|
+
/** The cron trigger of the project (`triggers.crons` in wrangler.jsonc, every minute). */
|
|
376
|
+
readonly scheduled: (controller: ScheduledController, env: HollwareEnv, ctx: ExecutionContext) => Promise<void>;
|
|
297
377
|
/** The RPC entrypoint, for the user's Worker to export under the name `Hollware`. */
|
|
298
378
|
readonly Hollware: new (ctx: ExecutionContext, env: HollwareEnv) => WorkerEntrypoint<HollwareEnv> & HollwareRpc;
|
|
299
379
|
}
|
|
@@ -306,4 +386,4 @@ export type CreateHollware = (config: HollwareConfig) => HollwareWorker;
|
|
|
306
386
|
*/
|
|
307
387
|
export declare const createHollware: CreateHollware;
|
|
308
388
|
//#endregion
|
|
309
|
-
export type { Actor, Clock, ContentStore, EntrySummaryView, EntryView, Handlers, ListQuery, NewRevision, OperationContext, OperationHandler, Principal, RevisionSummary, StoredEntry, StoredPublication, StoredRevision, View, WriteRefusal };
|
|
389
|
+
export type { Actor, Clock, ContentStore, EntrySummaryView, EntryView, EventMessage, Handlers, ListQuery, NewRevision, OperationContext, OperationHandler, OutboxEvent, Principal, PublishWrite, RevisionSummary, StoredEntry, StoredPublication, StoredRevision, StoredSchedule, View, WriteRefusal };
|