@easy-cms/core 1.10.0 → 1.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.
@@ -201,6 +201,17 @@ interface CreateMigrationResult {
201
201
  readonly file: string;
202
202
  readonly statements: readonly string[];
203
203
  }
204
+ /**
205
+ * A row written with a document, in the same transaction (`outbox: true` in the config): a write
206
+ * that commits leaves it, one that doesn't leaves nothing. Not written when an `update` with
207
+ * `where` doesn't match.
208
+ */
209
+ interface OutboxRow {
210
+ /** The collection the row goes to. */
211
+ readonly collection: string;
212
+ /** The row's fields, given the written document's id (`null` for a global). */
213
+ data(id: ID | null): Record<string, unknown>;
214
+ }
204
215
  /** A connected database bound to one config. Returned by `DatabaseAdapter.init`. */
205
216
  interface Database {
206
217
  find(args: FindArgs): Promise<PaginatedDocs<RawDocument>>;
@@ -231,6 +242,7 @@ interface Database {
231
242
  create(args: {
232
243
  collection: string;
233
244
  data: Record<string, unknown>;
245
+ outbox?: OutboxRow | undefined;
234
246
  }): Promise<RawDocument>;
235
247
  /**
236
248
  * `data` holds the whole document after merging. Runs in one transaction. With `where`, only
@@ -241,12 +253,14 @@ interface Database {
241
253
  collection: string;
242
254
  id: ID;
243
255
  data: Record<string, unknown>;
256
+ outbox?: OutboxRow | undefined;
244
257
  }): Promise<RawDocument>;
245
258
  update(args: {
246
259
  collection: string;
247
260
  id: ID;
248
261
  data: Record<string, unknown>;
249
262
  where: Where;
263
+ outbox?: OutboxRow | undefined;
250
264
  }): Promise<RawDocument | null>;
251
265
  /**
252
266
  * Adds `by` to a top-level number field in one statement, safe against concurrent calls; an
@@ -264,6 +278,7 @@ interface Database {
264
278
  delete(args: {
265
279
  collection: string;
266
280
  id: ID;
281
+ outbox?: OutboxRow | undefined;
267
282
  }): Promise<void>;
268
283
  findGlobal(args: {
269
284
  slug: string;
@@ -271,7 +286,13 @@ interface Database {
271
286
  updateGlobal(args: {
272
287
  slug: string;
273
288
  data: Record<string, unknown>;
289
+ outbox?: OutboxRow | undefined;
274
290
  }): Promise<Record<string, unknown>>;
291
+ /**
292
+ * True when `create`, `update`, `delete` and `updateGlobal` take `outbox`, a row written in
293
+ * the same transaction. Required by `outbox: true` in the config.
294
+ */
295
+ readonly outbox?: boolean | undefined;
275
296
  /** Writes a migration file for the difference between the config and the latest migration. `null` when nothing changed. */
276
297
  createMigration(args: {
277
298
  name: string;
@@ -1778,6 +1799,8 @@ declare class EasyCMS<C extends Config = Config> {
1778
1799
  private readonly versions;
1779
1800
  private readonly webhooks;
1780
1801
  private readonly mailer;
1802
+ /** With `outbox: true`: runs after hooks and events from rows saves write. */
1803
+ private readonly outbox;
1781
1804
  /**
1782
1805
  * The user and context of a request, as the REST API works them out: its session cookie or
1783
1806
  * Bearer token, then `onRequest`. For framework routes and server code that act for a visitor;
@@ -2038,6 +2061,11 @@ declare class EasyCMS<C extends Config = Config> {
2038
2061
  flushEmails(): Promise<void>;
2039
2062
  /** Emails queued until sent, stored in `email-deliveries`. */
2040
2063
  private emailQueue;
2064
+ /**
2065
+ * Waits until the outbox (`outbox: true`) ran what saves left so far, e.g. before a serverless
2066
+ * function returns. What fails stays queued for its retry.
2067
+ */
2068
+ flushOutbox(): Promise<void>;
2041
2069
  destroy(): Promise<void>;
2042
2070
  private schedulerTimer;
2043
2071
  private running;
@@ -2065,6 +2093,11 @@ declare class EasyCMS<C extends Config = Config> {
2065
2093
  ran: number;
2066
2094
  failed: number;
2067
2095
  };
2096
+ /** Outbox entries (`outbox: true`) run, and those that failed (to be retried). */
2097
+ outbox: {
2098
+ ran: number;
2099
+ failed: number;
2100
+ };
2068
2101
  }>;
2069
2102
  private runJobsNow;
2070
2103
  /**
@@ -2183,8 +2216,26 @@ declare class EasyCMS<C extends Config = Config> {
2183
2216
  private separateDrafts;
2184
2217
  /** Replaces published documents that have a newer draft with that draft. */
2185
2218
  private withDrafts;
2186
- /** Sends webhook events for a change; `before` is the stored status before it, if any. */
2219
+ /**
2220
+ * The tags `httpCache.purge` gets for a change: what readers see changed (anything, without
2221
+ * drafts; with drafts, a published document saved, published, unpublished or deleted).
2222
+ */
2223
+ private purgeTags;
2224
+ private isGlobal;
2225
+ /** The webhook events of a change; `before` is the stored status before it, if any. */
2226
+ private changeEvents;
2227
+ /**
2228
+ * Sends webhook events for a change and purges the HTTP cache. Not awaited; purge failures
2229
+ * are logged.
2230
+ */
2187
2231
  private emitChange;
2232
+ /**
2233
+ * The outbox row of a save (`outbox: true`): written in its transaction, then run by the outbox
2234
+ * in place of its after hooks and events. `undefined` without the outbox, or with nothing to run.
2235
+ */
2236
+ private outboxRow;
2237
+ /** Runs an outbox entry: what its save would have run right after it, without the outbox. */
2238
+ private runOutbox;
2188
2239
  /**
2189
2240
  * Writes the audit log entry for a change (`audit`): publishing, unpublishing and restoring
2190
2241
  * are told apart from other saves.
@@ -2786,6 +2837,11 @@ interface CollectionConfig {
2786
2837
  readonly versions?: boolean | VersionsConfig;
2787
2838
  /** Allow scheduling publish/unpublish for a later time (needs `drafts`). */
2788
2839
  readonly schedule?: boolean;
2840
+ /**
2841
+ * HTTP caching of public reads of this content (no login, published only), for a CDN in front.
2842
+ * Overrides the config's `httpCache` for this one; `false` keeps every read `no-store`.
2843
+ */
2844
+ readonly httpCache?: false | HttpCacheTimes;
2789
2845
  /** Live preview: the page that shows a document, e.g. `({ doc }) => \`/posts/${doc.slug}\``. */
2790
2846
  readonly preview?: PreviewURL;
2791
2847
  readonly access?: CollectionAccess;
@@ -2793,6 +2849,20 @@ interface CollectionConfig {
2793
2849
  /** How the collection looks in the admin: its menu item, list, edit page and components. */
2794
2850
  readonly admin?: CollectionAdmin;
2795
2851
  }
2852
+ /** How long a CDN may keep a public read. */
2853
+ interface HttpCacheTimes {
2854
+ /** Seconds a CDN serves it without asking again (`s-maxage`). Default 60. */
2855
+ readonly sMaxAge?: number;
2856
+ /** Seconds after that it may still serve it while it fetches a fresh one. Default 300. */
2857
+ readonly staleWhileRevalidate?: number;
2858
+ }
2859
+ interface HttpCacheConfig extends HttpCacheTimes {
2860
+ /**
2861
+ * Called after public content changes, with the cache tags of what changed: purge them from
2862
+ * your CDN, or call Next's `revalidateTag` for each. Not awaited; a failure is logged.
2863
+ */
2864
+ readonly purge?: (tags: string[]) => void | Promise<void>;
2865
+ }
2796
2866
  interface GlobalConfig {
2797
2867
  readonly slug: string;
2798
2868
  readonly label?: Label;
@@ -2802,6 +2872,11 @@ interface GlobalConfig {
2802
2872
  readonly versions?: boolean | VersionsConfig;
2803
2873
  /** Allow scheduling publish/unpublish for a later time (needs `drafts`). */
2804
2874
  readonly schedule?: boolean;
2875
+ /**
2876
+ * HTTP caching of public reads of this content (no login, published only), for a CDN in front.
2877
+ * Overrides the config's `httpCache` for this one; `false` keeps every read `no-store`.
2878
+ */
2879
+ readonly httpCache?: false | HttpCacheTimes;
2805
2880
  /** Live preview: the page that shows the global. See `CollectionConfig.preview`. */
2806
2881
  readonly preview?: PreviewURL;
2807
2882
  readonly access?: GlobalAccess;
@@ -3379,11 +3454,26 @@ interface Config {
3379
3454
  * Default 5.
3380
3455
  */
3381
3456
  readonly countCacheSeconds?: number;
3457
+ /**
3458
+ * HTTP caching of public reads (no login, no API key, published content) by a CDN or proxy in
3459
+ * front: `Cache-Control` with `s-maxage`, an `ETag`, and cache tags to purge by. Off by default:
3460
+ * every response is `no-store`. Collections and globals can override it.
3461
+ */
3462
+ readonly httpCache?: HttpCacheConfig;
3382
3463
  /**
3383
3464
  * The deepest `page` the REST API serves to API clients (not to the signed-in admin); deeper
3384
3465
  * requests get `400`, pointing to `cursor`. Deep pages are read row by row. Default: no limit.
3385
3466
  */
3386
3467
  readonly maxPage?: number;
3468
+ /**
3469
+ * Runs `afterChange` and `afterDelete` hooks, webhooks and `httpCache.purge` from an outbox:
3470
+ * saving a document also queues them, in the same database transaction, and a worker runs them
3471
+ * after it commits, retrying what fails. A save that succeeds always gets its side effects (at
3472
+ * least once; hooks must be safe to run again), and the response doesn't wait for them. Hooks
3473
+ * then get the user who saved but no `context`. Needs a migration for the `outbox` table.
3474
+ * Default `false`: hooks run in the request, after the save.
3475
+ */
3476
+ readonly outbox?: boolean;
3387
3477
  readonly plugins?: readonly Plugin[];
3388
3478
  }
3389
3479
  /** The config after plugins ran, validation passed and defaults were applied. */
@@ -3415,5 +3505,5 @@ interface ResolvedConfig extends Omit<Config, 'cors' | 'localization' | 'routes'
3415
3505
  */
3416
3506
  declare function defineConfig<const TConfig extends Config>(config: TConfig): TConfig;
3417
3507
 
3418
- export { ADAPTER_API_VERSION as A, AuditLog as J, Auth as M, ADMIN_ICONS as a, FIELD_TYPES as aD, ForbiddenError as a_, ConfigError as ac, EasyCMS as av, EasyCMSError as aw, PayloadTooLargeError as bC, QueryError as bI, ROLE_OPERATIONS as bJ, Roles as bU, SchemaError as bX, NotFoundError as bs, PLUGIN_API_VERSION as bx, logFormat as c$, SingleSignOn as c3, defineConfig as cA, defineFieldType as cB, definePlugin as cC, diskStorage as cD, hasRows as cE, isAdmin as cF, isHasMany as cG, isSignedIn as cH, isStaff as cI, isSystemAdmin as cJ, jsonLogger as cK, mimeAllowedBy as cL, rowFields as cM, silentLogger as cN, uniqueWithinOf as cO, API_KEYS as cP, API_KEY_GLOBAL_OPERATIONS as cQ, API_KEY_OPERATIONS as cR, DEFAULT_MAX_VERSIONS as cS, DEFAULT_PASSWORD_EMAILS as cT, FIELD_TYPE_BASES as cU, FOLDER_LEVELS as cV, MediaFolders as cW, SSO_COOKIE as cX, codeOfStatus as cY, isJsonLogger as cZ, keyAllows as c_, TooManyRequestsError as cc, UnauthorizedError as ce, ValidationError as cm, WEBHOOK_EVENTS as cq, anyone as cw, consoleEmail as cx, consoleLogger as cy, createEasyCMS as cz };
3419
- export type { BuiltinMediaCollection as $, ApiKeyOperation as B, ApiKeyPermissions as C, ArrayField as D, EmailSetting as E, AuditChange as F, AuditConfig as G, AuditEntry as H, ID as I, AuditPage as K, AuditVerification as L, AuthConfig as N, AuthProvider as O, PaginatedDocs as P, AuthProviderProfile as Q, AuthProviderRequest as R, AuthUser as S, BackupsConfig as T, BeforeChangeHook as U, BeforeDeleteHook as V, BeforeValidateHook as W, Block as X, BlocksField as Y, BooleanField as Z, BuiltinApiKeysCollection as _, GlobalAccess as a$, BuiltinMediaFoldersCollection as a0, BuiltinUsersCollection as a1, BundleHints as a2, CliCommand as a3, CollectionAccess as a4, CollectionAdmin as a5, CollectionConfig as a6, CollectionDocument as a7, CollectionHooks as a8, CollectionListAdmin as a9, Endpoint as aA, EndpointRequest as aB, ErrorCode as aC, Field as aE, FieldAccess as aF, FieldAccessFn as aG, FieldAdmin as aH, FieldError as aI, FieldRule as aJ, FieldType as aK, FieldTypeBase as aL, FieldTypeDefinition as aM, FieldTypeValidateContext as aN, FieldValidate as aO, FieldValidateContext as aP, FieldValue as aQ, FieldsInput as aR, FieldsValue as aS, FilterOptions as aT, FilterOptionsArgs as aU, FindAfterArgs as aV, FindArgs as aW, FindOptions as aX, FolderLevel as aY, FolderPermissions as aZ, CollectionSlug as aa, Config as ab, ConfigIssue as ad, ContainerAdmin as ae, CreateEasyCMSOptions as af, CreateInput as ag, CreateMigrationResult as ah, CursorDocs as ai, CustomField as aj, CustomFieldTypes as ak, DashboardWidget as al, Database as am, DatabaseAdapter as an, DatabaseInitArgs as ao, DatabaseTransfer as ap, DateField as aq, DepthOptions as ar, DirectUpload as as, DiskStorageOptions as at, DocumentOf as au, EmailAdapter as ax, EmailField as ay, EmailMessage as az, Access as b, Session as b$, GlobalConfig as b0, GlobalDocument as b1, GlobalHooks as b2, GlobalInput as b3, GlobalSlug as b4, GroupField as b5, ImageSize as b6, IncrementOptions as b7, InferCollection as b8, InferGlobal as b9, PasswordEmailFn as bA, PasswordLinkOptions as bB, Plugin as bD, PluginInfo as bE, PluginTypes as bF, PreviewTarget as bG, PreviewURL as bH, RawDocument as bK, ReadOptions as bL, RelationshipField as bM, RequestContext as bN, ResolvedConfig as bO, RichTextDocument as bP, RichTextField as bQ, Role as bR, RoleOperation as bS, RolePermissions as bT, RoutesConfig as bV, ScheduledPublish as bW, SchemaMode as bY, SelectField as bZ, SelectOption as b_, JobConfig as ba, JsonField as bb, KeysetPage as bc, Label as bd, LayoutNode as be, LivePreview as bf, LocaleOf as bg, LocalizationConfig as bh, LogDetails as bi, Logger as bj, LoginArgs as bk, LogsConfig as bl, MediaDocument as bm, MediaSize as bn, MembersConfig as bo, MembersSignup as bp, MigrationInfo as bq, NavGroup as br, NumberField as bt, OnRequest as bu, OnRequestArgs as bv, Operation as bw, PasswordEmail as by, PasswordEmailArgs as bz, AccessArgs as c, SidebarPanel as c0, SignupArgs as c1, SignupResult as c2, SlugField as c4, SlugOf as c5, SsoOutcome as c6, SsoProviderRef as c7, StorageAdapter as c8, StoredFile as c9, TextField as ca, TextareaField as cb, TypedPlugin as cd, UncountedDocs as cf, UpdateInput as cg, UpdateOptions as ch, UploadConfig as ci, UploadField as cj, UploadFromURLConfig as ck, UserIdentity as cl, Version as cn, VersionSummary as co, VersionsConfig as cp, WebhookConfig as cr, WebhookEvent as cs, WebhookPayload as ct, Where as cu, WhereOperators as cv, AccessOptions as d, AdminBrand as e, AdminCommand as f, AdminComponent as g, AdminConfig as h, AdminFieldArgs as i, AdminIcon as j, AdminLocale as k, AdminPage as l, AdminRole as m, AdminRoleChange as n, AdminRoleField as o, AdminRoleTarget as p, AdminRoleView as q, AdminRoles as r, AdminSso as s, AdminSwitcher as t, AdminViewAccess as u, AfterChangeHook as v, AfterDeleteHook as w, AfterReadHook as x, ApiKeyContext as y, ApiKeyGlobalOperation as z };
3508
+ export { ADAPTER_API_VERSION as A, AuditLog as J, Auth as M, ADMIN_ICONS as a, FIELD_TYPES as aD, ForbiddenError as a_, ConfigError as ac, EasyCMS as av, EasyCMSError as aw, PayloadTooLargeError as bD, QueryError as bJ, ROLE_OPERATIONS as bK, Roles as bV, SchemaError as bY, NotFoundError as bs, PLUGIN_API_VERSION as by, keyAllows as c$, SingleSignOn as c4, createEasyCMS as cA, defineConfig as cB, defineFieldType as cC, definePlugin as cD, diskStorage as cE, hasRows as cF, isAdmin as cG, isHasMany as cH, isSignedIn as cI, isStaff as cJ, isSystemAdmin as cK, jsonLogger as cL, mimeAllowedBy as cM, rowFields as cN, silentLogger as cO, uniqueWithinOf as cP, API_KEYS as cQ, API_KEY_GLOBAL_OPERATIONS as cR, API_KEY_OPERATIONS as cS, DEFAULT_MAX_VERSIONS as cT, DEFAULT_PASSWORD_EMAILS as cU, FIELD_TYPE_BASES as cV, FOLDER_LEVELS as cW, MediaFolders as cX, SSO_COOKIE as cY, codeOfStatus as cZ, isJsonLogger as c_, TooManyRequestsError as cd, UnauthorizedError as cf, ValidationError as cn, WEBHOOK_EVENTS as cr, anyone as cx, consoleEmail as cy, consoleLogger as cz, logFormat as d0 };
3509
+ export type { BuiltinMediaCollection as $, ApiKeyOperation as B, ApiKeyPermissions as C, ArrayField as D, EmailSetting as E, AuditChange as F, AuditConfig as G, AuditEntry as H, ID as I, AuditPage as K, AuditVerification as L, AuthConfig as N, AuthProvider as O, PaginatedDocs as P, AuthProviderProfile as Q, AuthProviderRequest as R, AuthUser as S, BackupsConfig as T, BeforeChangeHook as U, BeforeDeleteHook as V, BeforeValidateHook as W, Block as X, BlocksField as Y, BooleanField as Z, BuiltinApiKeysCollection as _, GlobalAccess as a$, BuiltinMediaFoldersCollection as a0, BuiltinUsersCollection as a1, BundleHints as a2, CliCommand as a3, CollectionAccess as a4, CollectionAdmin as a5, CollectionConfig as a6, CollectionDocument as a7, CollectionHooks as a8, CollectionListAdmin as a9, Endpoint as aA, EndpointRequest as aB, ErrorCode as aC, Field as aE, FieldAccess as aF, FieldAccessFn as aG, FieldAdmin as aH, FieldError as aI, FieldRule as aJ, FieldType as aK, FieldTypeBase as aL, FieldTypeDefinition as aM, FieldTypeValidateContext as aN, FieldValidate as aO, FieldValidateContext as aP, FieldValue as aQ, FieldsInput as aR, FieldsValue as aS, FilterOptions as aT, FilterOptionsArgs as aU, FindAfterArgs as aV, FindArgs as aW, FindOptions as aX, FolderLevel as aY, FolderPermissions as aZ, CollectionSlug as aa, Config as ab, ConfigIssue as ad, ContainerAdmin as ae, CreateEasyCMSOptions as af, CreateInput as ag, CreateMigrationResult as ah, CursorDocs as ai, CustomField as aj, CustomFieldTypes as ak, DashboardWidget as al, Database as am, DatabaseAdapter as an, DatabaseInitArgs as ao, DatabaseTransfer as ap, DateField as aq, DepthOptions as ar, DirectUpload as as, DiskStorageOptions as at, DocumentOf as au, EmailAdapter as ax, EmailField as ay, EmailMessage as az, Access as b, SelectOption as b$, GlobalConfig as b0, GlobalDocument as b1, GlobalHooks as b2, GlobalInput as b3, GlobalSlug as b4, GroupField as b5, ImageSize as b6, IncrementOptions as b7, InferCollection as b8, InferGlobal as b9, PasswordEmailArgs as bA, PasswordEmailFn as bB, PasswordLinkOptions as bC, Plugin as bE, PluginInfo as bF, PluginTypes as bG, PreviewTarget as bH, PreviewURL as bI, RawDocument as bL, ReadOptions as bM, RelationshipField as bN, RequestContext as bO, ResolvedConfig as bP, RichTextDocument as bQ, RichTextField as bR, Role as bS, RoleOperation as bT, RolePermissions as bU, RoutesConfig as bW, ScheduledPublish as bX, SchemaMode as bZ, SelectField as b_, JobConfig as ba, JsonField as bb, KeysetPage as bc, Label as bd, LayoutNode as be, LivePreview as bf, LocaleOf as bg, LocalizationConfig as bh, LogDetails as bi, Logger as bj, LoginArgs as bk, LogsConfig as bl, MediaDocument as bm, MediaSize as bn, MembersConfig as bo, MembersSignup as bp, MigrationInfo as bq, NavGroup as br, NumberField as bt, OnRequest as bu, OnRequestArgs as bv, Operation as bw, OutboxRow as bx, PasswordEmail as bz, AccessArgs as c, Session as c0, SidebarPanel as c1, SignupArgs as c2, SignupResult as c3, SlugField as c5, SlugOf as c6, SsoOutcome as c7, SsoProviderRef as c8, StorageAdapter as c9, StoredFile as ca, TextField as cb, TextareaField as cc, TypedPlugin as ce, UncountedDocs as cg, UpdateInput as ch, UpdateOptions as ci, UploadConfig as cj, UploadField as ck, UploadFromURLConfig as cl, UserIdentity as cm, Version as co, VersionSummary as cp, VersionsConfig as cq, WebhookConfig as cs, WebhookEvent as ct, WebhookPayload as cu, Where as cv, WhereOperators as cw, AccessOptions as d, AdminBrand as e, AdminCommand as f, AdminComponent as g, AdminConfig as h, AdminFieldArgs as i, AdminIcon as j, AdminLocale as k, AdminPage as l, AdminRole as m, AdminRoleChange as n, AdminRoleField as o, AdminRoleTarget as p, AdminRoleView as q, AdminRoles as r, AdminSso as s, AdminSwitcher as t, AdminViewAccess as u, AfterChangeHook as v, AfterDeleteHook as w, AfterReadHook as x, ApiKeyContext as y, ApiKeyGlobalOperation as z };
@@ -1,4 +1,4 @@
1
- import { I as ID, ab as Config, av as EasyCMS, bh as LocalizationConfig, aE as Field, aI as FieldError, aT as FilterOptions, af as CreateEasyCMSOptions, bO as ResolvedConfig } from './config-DL4beesW.js';
1
+ import { I as ID, ab as Config, av as EasyCMS, bh as LocalizationConfig, aE as Field, aI as FieldError, aT as FilterOptions, af as CreateEasyCMSOptions, bP as ResolvedConfig } from './config-CHEEPk1d.js';
2
2
 
3
3
  /** Decrypts a file from `encryptBackup`; throws for another key or a changed file. */
4
4
  declare function decryptBackup(data: Uint8Array, encryptionKey: string): Uint8Array;
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { P as PaginatedDocs, I as ID, E as EmailSetting } from './config-DL4beesW.js';
2
- export { A as ADAPTER_API_VERSION, a as ADMIN_ICONS, b as Access, c as AccessArgs, d as AccessOptions, e as AdminBrand, f as AdminCommand, g as AdminComponent, h as AdminConfig, i as AdminFieldArgs, j as AdminIcon, k as AdminLocale, l as AdminPage, m as AdminRole, n as AdminRoleChange, o as AdminRoleField, p as AdminRoleTarget, q as AdminRoleView, r as AdminRoles, s as AdminSso, t as AdminSwitcher, u as AdminViewAccess, v as AfterChangeHook, w as AfterDeleteHook, x as AfterReadHook, y as ApiKeyContext, z as ApiKeyGlobalOperation, B as ApiKeyOperation, C as ApiKeyPermissions, D as ArrayField, F as AuditChange, G as AuditConfig, H as AuditEntry, J as AuditLog, K as AuditPage, L as AuditVerification, M as Auth, N as AuthConfig, O as AuthProvider, Q as AuthProviderProfile, R as AuthProviderRequest, S as AuthUser, T as BackupsConfig, U as BeforeChangeHook, V as BeforeDeleteHook, W as BeforeValidateHook, X as Block, Y as BlocksField, Z as BooleanField, _ as BuiltinApiKeysCollection, $ as BuiltinMediaCollection, a0 as BuiltinMediaFoldersCollection, a1 as BuiltinUsersCollection, a2 as BundleHints, a3 as CliCommand, a4 as CollectionAccess, a5 as CollectionAdmin, a6 as CollectionConfig, a7 as CollectionDocument, a8 as CollectionHooks, a9 as CollectionListAdmin, aa as CollectionSlug, ab as Config, ac as ConfigError, ad as ConfigIssue, ae as ContainerAdmin, af as CreateEasyCMSOptions, ag as CreateInput, ah as CreateMigrationResult, ai as CursorDocs, aj as CustomField, ak as CustomFieldTypes, al as DashboardWidget, am as Database, an as DatabaseAdapter, ao as DatabaseInitArgs, ap as DatabaseTransfer, aq as DateField, ar as DepthOptions, as as DirectUpload, at as DiskStorageOptions, au as DocumentOf, av as EasyCMS, aw as EasyCMSError, ax as EmailAdapter, ay as EmailField, az as EmailMessage, aA as Endpoint, aB as EndpointRequest, aC as ErrorCode, aD as FIELD_TYPES, aE as Field, aF as FieldAccess, aG as FieldAccessFn, aH as FieldAdmin, aI as FieldError, aJ as FieldRule, aK as FieldType, aL as FieldTypeBase, aM as FieldTypeDefinition, aN as FieldTypeValidateContext, aO as FieldValidate, aP as FieldValidateContext, aQ as FieldValue, aR as FieldsInput, aS as FieldsValue, aT as FilterOptions, aU as FilterOptionsArgs, aV as FindAfterArgs, aW as FindArgs, aX as FindOptions, aY as FolderLevel, aZ as FolderPermissions, a_ as ForbiddenError, a$ as GlobalAccess, b0 as GlobalConfig, b1 as GlobalDocument, b2 as GlobalHooks, b3 as GlobalInput, b4 as GlobalSlug, b5 as GroupField, b6 as ImageSize, b7 as IncrementOptions, b8 as InferCollection, b9 as InferGlobal, ba as JobConfig, bb as JsonField, bc as KeysetPage, bd as Label, be as LayoutNode, bf as LivePreview, bg as LocaleOf, bh as LocalizationConfig, bi as LogDetails, bj as Logger, bk as LoginArgs, bl as LogsConfig, bm as MediaDocument, bn as MediaSize, bo as MembersConfig, bp as MembersSignup, bq as MigrationInfo, br as NavGroup, bs as NotFoundError, bt as NumberField, bu as OnRequest, bv as OnRequestArgs, bw as Operation, bx as PLUGIN_API_VERSION, by as PasswordEmail, bz as PasswordEmailArgs, bA as PasswordEmailFn, bB as PasswordLinkOptions, bC as PayloadTooLargeError, bD as Plugin, bE as PluginInfo, bF as PluginTypes, bG as PreviewTarget, bH as PreviewURL, bI as QueryError, bJ as ROLE_OPERATIONS, bK as RawDocument, bL as ReadOptions, bM as RelationshipField, bN as RequestContext, bO as ResolvedConfig, bP as RichTextDocument, bQ as RichTextField, bR as Role, bS as RoleOperation, bT as RolePermissions, bU as Roles, bV as RoutesConfig, bW as ScheduledPublish, bX as SchemaError, bY as SchemaMode, bZ as SelectField, b_ as SelectOption, b$ as Session, c0 as SidebarPanel, c1 as SignupArgs, c2 as SignupResult, c3 as SingleSignOn, c4 as SlugField, c5 as SlugOf, c6 as SsoOutcome, c7 as SsoProviderRef, c8 as StorageAdapter, c9 as StoredFile, ca as TextField, cb as TextareaField, cc as TooManyRequestsError, cd as TypedPlugin, ce as UnauthorizedError, cf as UncountedDocs, cg as UpdateInput, ch as UpdateOptions, ci as UploadConfig, cj as UploadField, ck as UploadFromURLConfig, cl as UserIdentity, cm as ValidationError, cn as Version, co as VersionSummary, cp as VersionsConfig, cq as WEBHOOK_EVENTS, cr as WebhookConfig, cs as WebhookEvent, ct as WebhookPayload, cu as Where, cv as WhereOperators, cw as anyone, cx as consoleEmail, cy as consoleLogger, cz as createEasyCMS, cA as defineConfig, cB as defineFieldType, cC as definePlugin, cD as diskStorage, cE as hasRows, cF as isAdmin, cG as isHasMany, cH as isSignedIn, cI as isStaff, cJ as isSystemAdmin, cK as jsonLogger, cL as mimeAllowedBy, cM as rowFields, cN as silentLogger, cO as uniqueWithinOf } from './config-DL4beesW.js';
3
- export { A as ADMIN_API_VERSION, a as AdminCollection, b as AdminComponentRef, c as AdminElementProps, d as AdminField, e as AdminGlobal, f as AdminLayoutNode, g as AdminNavGroup, h as AdminNavItem, i as AdminNavNode, j as AdminPageRef, k as AdminPageRoute, l as AdminSchema, m as AdminWidgetRef, S as SetFieldDetail, w as warnDeprecated } from './plugin-BXHlV5IZ.js';
4
- export { A as AdminBackup, a as AdminBackups, b as ApiHandlerOptions, B as BackupState, L as LoadConfigOptions, R as RestHandler, c as RestHandlerOptions, d as createApiHandler, e as createRestHandler, l as loadConfig, r as resolveConfig, s as sharedEasyCMS, f as slugify } from './handler--JrVIdYW.js';
1
+ import { P as PaginatedDocs, I as ID, E as EmailSetting } from './config-CHEEPk1d.js';
2
+ export { A as ADAPTER_API_VERSION, a as ADMIN_ICONS, b as Access, c as AccessArgs, d as AccessOptions, e as AdminBrand, f as AdminCommand, g as AdminComponent, h as AdminConfig, i as AdminFieldArgs, j as AdminIcon, k as AdminLocale, l as AdminPage, m as AdminRole, n as AdminRoleChange, o as AdminRoleField, p as AdminRoleTarget, q as AdminRoleView, r as AdminRoles, s as AdminSso, t as AdminSwitcher, u as AdminViewAccess, v as AfterChangeHook, w as AfterDeleteHook, x as AfterReadHook, y as ApiKeyContext, z as ApiKeyGlobalOperation, B as ApiKeyOperation, C as ApiKeyPermissions, D as ArrayField, F as AuditChange, G as AuditConfig, H as AuditEntry, J as AuditLog, K as AuditPage, L as AuditVerification, M as Auth, N as AuthConfig, O as AuthProvider, Q as AuthProviderProfile, R as AuthProviderRequest, S as AuthUser, T as BackupsConfig, U as BeforeChangeHook, V as BeforeDeleteHook, W as BeforeValidateHook, X as Block, Y as BlocksField, Z as BooleanField, _ as BuiltinApiKeysCollection, $ as BuiltinMediaCollection, a0 as BuiltinMediaFoldersCollection, a1 as BuiltinUsersCollection, a2 as BundleHints, a3 as CliCommand, a4 as CollectionAccess, a5 as CollectionAdmin, a6 as CollectionConfig, a7 as CollectionDocument, a8 as CollectionHooks, a9 as CollectionListAdmin, aa as CollectionSlug, ab as Config, ac as ConfigError, ad as ConfigIssue, ae as ContainerAdmin, af as CreateEasyCMSOptions, ag as CreateInput, ah as CreateMigrationResult, ai as CursorDocs, aj as CustomField, ak as CustomFieldTypes, al as DashboardWidget, am as Database, an as DatabaseAdapter, ao as DatabaseInitArgs, ap as DatabaseTransfer, aq as DateField, ar as DepthOptions, as as DirectUpload, at as DiskStorageOptions, au as DocumentOf, av as EasyCMS, aw as EasyCMSError, ax as EmailAdapter, ay as EmailField, az as EmailMessage, aA as Endpoint, aB as EndpointRequest, aC as ErrorCode, aD as FIELD_TYPES, aE as Field, aF as FieldAccess, aG as FieldAccessFn, aH as FieldAdmin, aI as FieldError, aJ as FieldRule, aK as FieldType, aL as FieldTypeBase, aM as FieldTypeDefinition, aN as FieldTypeValidateContext, aO as FieldValidate, aP as FieldValidateContext, aQ as FieldValue, aR as FieldsInput, aS as FieldsValue, aT as FilterOptions, aU as FilterOptionsArgs, aV as FindAfterArgs, aW as FindArgs, aX as FindOptions, aY as FolderLevel, aZ as FolderPermissions, a_ as ForbiddenError, a$ as GlobalAccess, b0 as GlobalConfig, b1 as GlobalDocument, b2 as GlobalHooks, b3 as GlobalInput, b4 as GlobalSlug, b5 as GroupField, b6 as ImageSize, b7 as IncrementOptions, b8 as InferCollection, b9 as InferGlobal, ba as JobConfig, bb as JsonField, bc as KeysetPage, bd as Label, be as LayoutNode, bf as LivePreview, bg as LocaleOf, bh as LocalizationConfig, bi as LogDetails, bj as Logger, bk as LoginArgs, bl as LogsConfig, bm as MediaDocument, bn as MediaSize, bo as MembersConfig, bp as MembersSignup, bq as MigrationInfo, br as NavGroup, bs as NotFoundError, bt as NumberField, bu as OnRequest, bv as OnRequestArgs, bw as Operation, bx as OutboxRow, by as PLUGIN_API_VERSION, bz as PasswordEmail, bA as PasswordEmailArgs, bB as PasswordEmailFn, bC as PasswordLinkOptions, bD as PayloadTooLargeError, bE as Plugin, bF as PluginInfo, bG as PluginTypes, bH as PreviewTarget, bI as PreviewURL, bJ as QueryError, bK as ROLE_OPERATIONS, bL as RawDocument, bM as ReadOptions, bN as RelationshipField, bO as RequestContext, bP as ResolvedConfig, bQ as RichTextDocument, bR as RichTextField, bS as Role, bT as RoleOperation, bU as RolePermissions, bV as Roles, bW as RoutesConfig, bX as ScheduledPublish, bY as SchemaError, bZ as SchemaMode, b_ as SelectField, b$ as SelectOption, c0 as Session, c1 as SidebarPanel, c2 as SignupArgs, c3 as SignupResult, c4 as SingleSignOn, c5 as SlugField, c6 as SlugOf, c7 as SsoOutcome, c8 as SsoProviderRef, c9 as StorageAdapter, ca as StoredFile, cb as TextField, cc as TextareaField, cd as TooManyRequestsError, ce as TypedPlugin, cf as UnauthorizedError, cg as UncountedDocs, ch as UpdateInput, ci as UpdateOptions, cj as UploadConfig, ck as UploadField, cl as UploadFromURLConfig, cm as UserIdentity, cn as ValidationError, co as Version, cp as VersionSummary, cq as VersionsConfig, cr as WEBHOOK_EVENTS, cs as WebhookConfig, ct as WebhookEvent, cu as WebhookPayload, cv as Where, cw as WhereOperators, cx as anyone, cy as consoleEmail, cz as consoleLogger, cA as createEasyCMS, cB as defineConfig, cC as defineFieldType, cD as definePlugin, cE as diskStorage, cF as hasRows, cG as isAdmin, cH as isHasMany, cI as isSignedIn, cJ as isStaff, cK as isSystemAdmin, cL as jsonLogger, cM as mimeAllowedBy, cN as rowFields, cO as silentLogger, cP as uniqueWithinOf } from './config-CHEEPk1d.js';
3
+ export { A as ADMIN_API_VERSION, a as AdminCollection, b as AdminComponentRef, c as AdminElementProps, d as AdminField, e as AdminGlobal, f as AdminLayoutNode, g as AdminNavGroup, h as AdminNavItem, i as AdminNavNode, j as AdminPageRef, k as AdminPageRoute, l as AdminSchema, m as AdminWidgetRef, S as SetFieldDetail, w as warnDeprecated } from './plugin-B8xypoWd.js';
4
+ export { A as AdminBackup, a as AdminBackups, b as ApiHandlerOptions, B as BackupState, L as LoadConfigOptions, R as RestHandler, c as RestHandlerOptions, d as createApiHandler, e as createRestHandler, l as loadConfig, r as resolveConfig, s as sharedEasyCMS, f as slugify } from './handler-adKUq8-U.js';
5
5
  export { FieldCondition, matchesCondition } from './conditions.js';
6
6
 
7
7
  type DeliveryKind = 'webhook' | 'email';
@@ -112,9 +112,30 @@ interface AdminScheduledJob {
112
112
  global?: string;
113
113
  doc: ID;
114
114
  }
115
+ /** An outbox entry (`outbox: true`) that failed: being retried, or given up on. */
116
+ interface AdminOutboxEntry {
117
+ id: ID;
118
+ event: 'create' | 'update' | 'draft' | 'delete';
119
+ /** The document's collection, or the global (`global`), and the document's id. */
120
+ collection?: string;
121
+ global?: string;
122
+ doc: string | null;
123
+ attempts: number;
124
+ /** `pending`: retried at `nextAttemptAt`; `failed`: given up, until someone retries it. */
125
+ state: 'pending' | 'running' | 'failed';
126
+ error: string | null;
127
+ nextAttemptAt: string;
128
+ }
129
+ interface AdminOutbox {
130
+ /** Entries waiting to run (new, or to be retried). */
131
+ waiting: number;
132
+ failed: number;
133
+ /** Entries that failed at least once, latest first (at most 100). */
134
+ entries: AdminOutboxEntry[];
135
+ }
115
136
  /** What Settings → Jobs shows (`GET <api>/admin/jobs`). */
116
137
  /** Work Easy CMS itself does with every run of the jobs, when it is set up. */
117
- type BuiltInJob = 'scheduled' | 'webhooks' | 'emails' | 'backups' | 'audit';
138
+ type BuiltInJob = 'scheduled' | 'webhooks' | 'emails' | 'outbox' | 'backups' | 'audit';
118
139
  interface AdminJobs {
119
140
  jobs: AdminJob[];
120
141
  /** When jobs last ran (the scheduler, the cron endpoint), `null` if never. */
@@ -127,6 +148,8 @@ interface AdminJobs {
127
148
  canChange: boolean;
128
149
  /** `null` when nothing uses `schedule`. */
129
150
  scheduled: AdminScheduledJob[] | null;
151
+ /** `null` without `outbox: true`. */
152
+ outbox: AdminOutbox | null;
130
153
  }
131
154
 
132
155
  interface SearchHit {
@@ -218,8 +241,19 @@ interface AdminStatus {
218
241
  attention: AdminAttention[];
219
242
  }
220
243
 
244
+ /**
245
+ * The cache tags public reads carry and `httpCache.purge` receives: `ecms` for all content,
246
+ * `ecms:posts` for a collection's lists, `ecms:posts:42` for a document, `ecms:global:site` for
247
+ * a global. Use them to tag your own fetches, e.g. Next's `fetch(url, { next: { tags } })`.
248
+ */
249
+ declare const cacheTags: {
250
+ collection: (slug: string) => string[];
251
+ document: (slug: string, id: unknown) => string[];
252
+ global: (slug: string) => string[];
253
+ };
254
+
221
255
  /** The version of `@easy-cms/core`, set when the package is built. */
222
256
  declare const VERSION: string;
223
257
 
224
- export { EmailSetting, ID, PaginatedDocs, VERSION };
225
- export type { AdminAttention, AdminDeliveries, AdminDelivery, AdminEmail, AdminEmailDelivery, AdminJob, AdminJobs, AdminScheduledJob, AdminStatus, AdminWebhookDelivery, BuiltInJob, DeliveryKind, DeliveryState, EmailCheck, SearchHit };
258
+ export { EmailSetting, ID, PaginatedDocs, VERSION, cacheTags };
259
+ export type { AdminAttention, AdminDeliveries, AdminDelivery, AdminEmail, AdminEmailDelivery, AdminJob, AdminJobs, AdminOutbox, AdminOutboxEntry, AdminScheduledJob, AdminStatus, AdminWebhookDelivery, BuiltInJob, DeliveryKind, DeliveryState, EmailCheck, SearchHit };
package/dist/index.js CHANGED
@@ -8,6 +8,7 @@ import {
8
8
  VERSION,
9
9
  WEBHOOK_EVENTS,
10
10
  anyone,
11
+ cacheTags,
11
12
  consoleEmail,
12
13
  consoleLogger,
13
14
  createApiHandler,
@@ -24,7 +25,7 @@ import {
24
25
  sharedEasyCMS,
25
26
  silentLogger,
26
27
  slugify
27
- } from "./chunk-54UFTH6S.js";
28
+ } from "./chunk-244WCY6S.js";
28
29
  import {
29
30
  matchesCondition
30
31
  } from "./chunk-U266LV4M.js";
@@ -74,6 +75,7 @@ export {
74
75
  ValidationError,
75
76
  WEBHOOK_EVENTS,
76
77
  anyone,
78
+ cacheTags,
77
79
  consoleEmail,
78
80
  consoleLogger,
79
81
  createApiHandler,
@@ -1,6 +1,6 @@
1
1
  import { Config, Database, EasyCMS, NavGroup, CollectionConfig, ID, RawDocument, Field, ResolvedConfig, ConfigIssue } from './index.js';
2
- export { cP as API_KEYS, cQ as API_KEY_GLOBAL_OPERATIONS, cR as API_KEY_OPERATIONS, cS as DEFAULT_MAX_VERSIONS, cT as DEFAULT_PASSWORD_EMAILS, cU as FIELD_TYPE_BASES, cV as FOLDER_LEVELS, cW as MediaFolders, cX as SSO_COOKIE, cY as codeOfStatus, cE as hasRows, cG as isHasMany, cZ as isJsonLogger, c_ as keyAllows, c$ as logFormat, cL as mimeAllowedBy, cM as rowFields, cO as uniqueWithinOf } from './config-DL4beesW.js';
3
- export { C as CONFIG_FILE_NAMES, g as CSRF_COOKIE, h as CSRF_HEADER, D as DEFAULT_ADMIN_PATH, i as DEFAULT_API_PATH, j as DEFAULT_MAX_FILE_SIZE, k as DEFAULT_TOKEN_EXPIRATION, m as applyDefaults, n as applyPlugins, o as createRootEndpointHandler, p as decryptBackup, q as fillMissing, t as findConfigFile, u as forwardedClientIp, v as generateSlugs, w as importConfig, x as mergeForUpdate, y as parseId, z as platformClientIp, E as readCookie, F as validateFields, G as writeBackupFile } from './handler--JrVIdYW.js';
2
+ export { cQ as API_KEYS, cR as API_KEY_GLOBAL_OPERATIONS, cS as API_KEY_OPERATIONS, cT as DEFAULT_MAX_VERSIONS, cU as DEFAULT_PASSWORD_EMAILS, cV as FIELD_TYPE_BASES, cW as FOLDER_LEVELS, cX as MediaFolders, cY as SSO_COOKIE, cZ as codeOfStatus, cF as hasRows, cH as isHasMany, c_ as isJsonLogger, c$ as keyAllows, d0 as logFormat, cM as mimeAllowedBy, cN as rowFields, cP as uniqueWithinOf } from './config-CHEEPk1d.js';
3
+ export { C as CONFIG_FILE_NAMES, g as CSRF_COOKIE, h as CSRF_HEADER, D as DEFAULT_ADMIN_PATH, i as DEFAULT_API_PATH, j as DEFAULT_MAX_FILE_SIZE, k as DEFAULT_TOKEN_EXPIRATION, m as applyDefaults, n as applyPlugins, o as createRootEndpointHandler, p as decryptBackup, q as fillMissing, t as findConfigFile, u as forwardedClientIp, v as generateSlugs, w as importConfig, x as mergeForUpdate, y as parseId, z as platformClientIp, E as readCookie, F as validateFields, G as writeBackupFile } from './handler-adKUq8-U.js';
4
4
  export { conditionIssues } from './conditions.js';
5
5
 
6
6
  /** The session cookie the REST API sets at login. */
package/dist/internal.js CHANGED
@@ -56,7 +56,7 @@ import {
56
56
  verifyPassword,
57
57
  verifyTurnstile,
58
58
  writeBackupFile
59
- } from "./chunk-54UFTH6S.js";
59
+ } from "./chunk-244WCY6S.js";
60
60
  import {
61
61
  conditionIssues
62
62
  } from "./chunk-U266LV4M.js";
@@ -1,4 +1,4 @@
1
- import { bd as Label, aE as Field, I as ID, k as AdminLocale, t as AdminSwitcher, c7 as SsoProviderRef } from './config-DL4beesW.js';
1
+ import { bd as Label, aE as Field, I as ID, k as AdminLocale, t as AdminSwitcher, c8 as SsoProviderRef } from './config-CHEEPk1d.js';
2
2
  import { FieldCondition } from './conditions.js';
3
3
 
4
4
  /** A Web Component from an admin module, with its `props` (plain JSON). */
package/dist/plugin.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export { a as ADMIN_ICONS, g as AdminComponent, j as AdminIcon, S as AuthUser, a3 as CliCommand, a4 as CollectionAccess, a6 as CollectionConfig, ab as Config, ac as ConfigError, al as DashboardWidget, aw as EasyCMSError, aA as Endpoint, aB as EndpointRequest, aC as ErrorCode, aE as Field, aF as FieldAccess, aI as FieldError, aL as FieldTypeBase, aM as FieldTypeDefinition, aN as FieldTypeValidateContext, a_ as ForbiddenError, b0 as GlobalConfig, I as ID, ba as JobConfig, bd as Label, br as NavGroup, bs as NotFoundError, bu as OnRequest, bv as OnRequestArgs, bx as PLUGIN_API_VERSION, bC as PayloadTooLargeError, bD as Plugin, bE as PluginInfo, bF as PluginTypes, bI as QueryError, bN as RequestContext, cc as TooManyRequestsError, cd as TypedPlugin, ce as UnauthorizedError, cm as ValidationError, cu as Where, cB as defineFieldType, cC as definePlugin } from './config-DL4beesW.js';
2
- export { A as ADMIN_API_VERSION, c as AdminElementProps, k as AdminPageRoute, S as SetFieldDetail, w as warnDeprecated } from './plugin-BXHlV5IZ.js';
1
+ export { a as ADMIN_ICONS, g as AdminComponent, j as AdminIcon, S as AuthUser, a3 as CliCommand, a4 as CollectionAccess, a6 as CollectionConfig, ab as Config, ac as ConfigError, al as DashboardWidget, aw as EasyCMSError, aA as Endpoint, aB as EndpointRequest, aC as ErrorCode, aE as Field, aF as FieldAccess, aI as FieldError, aL as FieldTypeBase, aM as FieldTypeDefinition, aN as FieldTypeValidateContext, a_ as ForbiddenError, b0 as GlobalConfig, I as ID, ba as JobConfig, bd as Label, br as NavGroup, bs as NotFoundError, bu as OnRequest, bv as OnRequestArgs, by as PLUGIN_API_VERSION, bD as PayloadTooLargeError, bE as Plugin, bF as PluginInfo, bG as PluginTypes, bJ as QueryError, bO as RequestContext, cd as TooManyRequestsError, ce as TypedPlugin, cf as UnauthorizedError, cn as ValidationError, cv as Where, cC as defineFieldType, cD as definePlugin } from './config-CHEEPk1d.js';
2
+ export { A as ADMIN_API_VERSION, c as AdminElementProps, k as AdminPageRoute, S as SetFieldDetail, w as warnDeprecated } from './plugin-B8xypoWd.js';
3
3
  import './conditions.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@easy-cms/core",
3
- "version": "1.10.0",
3
+ "version": "1.12.0",
4
4
  "description": "Embedded, code-first headless CMS for Nuxt and Next.js",
5
5
  "license": "MIT",
6
6
  "type": "module",