@beechcms/core 0.6.3 → 0.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/.tsbuildinfo +1 -0
  2. package/dist/content/demo-data.repository.d.ts +4 -2
  3. package/dist/content/demo-data.repository.d.ts.map +1 -1
  4. package/dist/content/demo-data.repository.js +0 -2
  5. package/dist/engine/ddl.d.ts +5 -0
  6. package/dist/engine/ddl.d.ts.map +1 -1
  7. package/dist/engine/ddl.js +38 -9
  8. package/dist/engine/policies.d.ts +52 -4
  9. package/dist/engine/policies.d.ts.map +1 -1
  10. package/dist/engine/policies.js +144 -14
  11. package/dist/engine/privacy.service.d.ts +65 -0
  12. package/dist/engine/privacy.service.d.ts.map +1 -0
  13. package/dist/engine/privacy.service.js +114 -0
  14. package/dist/engine/query.d.ts.map +1 -1
  15. package/dist/engine/query.js +22 -3
  16. package/dist/engine/seed-registry.d.ts.map +1 -1
  17. package/dist/engine/seed-registry.js +5 -0
  18. package/dist/engine/seed-validation.d.ts.map +1 -1
  19. package/dist/engine/seed-validation.js +25 -1
  20. package/dist/engine/sql-reserved-words.d.ts +2 -0
  21. package/dist/engine/sql-reserved-words.d.ts.map +1 -0
  22. package/dist/engine/sql-reserved-words.js +21 -0
  23. package/dist/engine/types.d.ts +11 -1
  24. package/dist/engine/types.d.ts.map +1 -1
  25. package/dist/engine/validation/index.d.ts.map +1 -1
  26. package/dist/engine/validation/index.js +10 -3
  27. package/dist/engine/validation/richtext-sanitizer.d.ts.map +1 -1
  28. package/dist/engine/validation/richtext-sanitizer.js +26 -2
  29. package/dist/engine/validation/schema-builders.js +6 -6
  30. package/dist/index.d.ts +1 -0
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +1 -0
  33. package/dist/media/file-types.d.ts.map +1 -1
  34. package/dist/media/file-types.js +13 -5
  35. package/dist/notifications/notification-service.d.ts +12 -6
  36. package/dist/notifications/notification-service.d.ts.map +1 -1
  37. package/dist/notifications/notification-service.js +16 -1
  38. package/dist/queue/queue.interface.d.ts +6 -2
  39. package/dist/queue/queue.interface.d.ts.map +1 -1
  40. package/dist/queue/queue.stub.d.ts +1 -1
  41. package/dist/queue/queue.stub.d.ts.map +1 -1
  42. package/dist/queue/queue.stub.js +2 -1
  43. package/package.json +1 -1
  44. package/dist/queue.interface.d.ts +0 -39
  45. package/dist/queue.interface.d.ts.map +0 -1
  46. package/dist/queue.interface.js +0 -3
  47. package/dist/queue.stub.d.ts +0 -6
  48. package/dist/queue.stub.d.ts.map +0 -1
  49. package/dist/queue.stub.js +0 -8
@@ -21,9 +21,33 @@ const URL_LIKE_RICHTEXT_KEYS = new Set(['href', 'src']);
21
21
  const ALLOWED_URL_PROTOCOLS = new Set(['http', 'https', 'mailto', 'tel']);
22
22
  /** DoS guards, evaluated before the sanitizing walk. */
23
23
  const RICHTEXT_MAX_DEPTH = 50;
24
- /** RichText string input is no longer accepted (JSON-only). Reject as invalid. */
24
+ /** Coerces string input (JSON string or plain text) into a valid TipTap doc structure. */
25
25
  function sanitizeRichtextString(raw) {
26
- return { value: raw, dangerous: false, valid: false, size: byteLength(raw) };
26
+ const trimmed = raw.trim();
27
+ if (trimmed.startsWith('{') || trimmed.startsWith('[')) {
28
+ try {
29
+ const parsed = JSON.parse(trimmed);
30
+ if (isPlainObject(parsed)) {
31
+ return sanitizeRichtextJson(parsed);
32
+ }
33
+ }
34
+ catch {
35
+ // Fall through to plain text conversion
36
+ }
37
+ }
38
+ const isDangerous = /<script\b|javascript:|onerror=/i.test(raw);
39
+ const doc = {
40
+ type: 'doc',
41
+ content: raw.length > 0 ? [{
42
+ type: 'paragraph',
43
+ content: [{ type: 'text', text: raw }]
44
+ }] : []
45
+ };
46
+ const result = sanitizeRichtextJson(doc);
47
+ if (isDangerous) {
48
+ result.dangerous = true;
49
+ }
50
+ return result;
27
51
  }
28
52
  /** Normalizes a URL value and confirms its protocol is allowlisted.
29
53
  * Strips ALL whitespace + control chars first, defeating java\tscript: obfuscation. */
@@ -278,13 +278,13 @@ function relationSchema(branch, options) {
278
278
  throw new Error('IIdGenerator must be provided in ValidateSeedPayloadOptions when validating seeds with relation branches. ' +
279
279
  'Pass `idGenerator` (e.g. SystemIdGenerator) in the options object.');
280
280
  }
281
- const idSchema = z.string().refine((value) => gen.isValid(value), { message: 'Invalid relation id format' });
281
+ const idSchema = z.string().refine((value) => gen.isValid(value), { message: 'Expected valid-relation-id' });
282
282
  // Many-to-many: expect string[] with no duplicates
283
283
  if (branch.multiple === true) {
284
- const arraySchema = z.array(idSchema).refine((arr) => new Set(arr).size === arr.length, { message: 'Duplicate ids in multi-relation array' });
285
- return options.allowNull ? z.union([arraySchema, z.null()]) : arraySchema;
284
+ const arraySchema = z.array(idSchema).refine((arr) => new Set(arr).size === arr.length, { message: 'Expected unique-relation-ids' });
285
+ return withEmptyPreprocessing(arraySchema, options.allowNull);
286
286
  }
287
- return withNullable(idSchema, options.allowNull);
287
+ return withEmptyPreprocessing(idSchema, options.allowNull);
288
288
  }
289
289
  /**
290
290
  * Compiles a Zod validation schema for file or asset list branches.
@@ -327,7 +327,7 @@ function fileSchema(branch, allowNull) {
327
327
  }
328
328
  return items.map((item) => item.url);
329
329
  })
330
- .pipe(z.array(z.string().url()));
330
+ .pipe(z.array(z.url()));
331
331
  return withEmptyPreprocessing(inner, allowNull);
332
332
  }
333
333
  const inner = z
@@ -344,7 +344,7 @@ function fileSchema(branch, allowNull) {
344
344
  return z.NEVER;
345
345
  return candidate.url;
346
346
  })
347
- .pipe(z.string().url());
347
+ .pipe(z.url());
348
348
  return withEmptyPreprocessing(inner, allowNull);
349
349
  }
350
350
  /**
package/dist/index.d.ts CHANGED
@@ -22,6 +22,7 @@ export * from './content/idempotency.repository.js';
22
22
  export * from './media/media.repository.js';
23
23
  export * from './common/storage.js';
24
24
  export * from './engine/policies.js';
25
+ export * from './engine/privacy.service.js';
25
26
  export * from './auth/hash-provider.js';
26
27
  export * from './auth/token-service.js';
27
28
  export * from './auth/user.repository.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AAEH,cAAc,mBAAmB,CAAA;AACjC,cAAc,uBAAuB,CAAA;AACrC,cAAc,yBAAyB,CAAA;AACvC,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA;AAClC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,uCAAuC,CAAA;AACrD,cAAc,yBAAyB,CAAA;AACvC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,mBAAmB,CAAA;AACjC,cAAc,qCAAqC,CAAA;AACnD,cAAc,6BAA6B,CAAA;AAC3C,cAAc,qBAAqB,CAAA;AACnC,cAAc,sBAAsB,CAAA;AACpC,cAAc,yBAAyB,CAAA;AACvC,cAAc,yBAAyB,CAAA;AACvC,cAAc,2BAA2B,CAAA;AACzC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,2CAA2C,CAAA;AACzD,cAAc,8BAA8B,CAAA;AAC5C,cAAc,oCAAoC,CAAA;AAClD,cAAc,4CAA4C,CAAA;AAC1D,cAAc,yCAAyC,CAAA;AACvD,cAAc,4CAA4C,CAAA;AAC1D,cAAc,yCAAyC,CAAA;AACvD,cAAc,+BAA+B,CAAA;AAC7C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,sCAAsC,CAAA;AACpD,cAAc,mBAAmB,CAAA;AACjC,cAAc,0BAA0B,CAAA;AACxC,cAAc,2BAA2B,CAAA;AACzC,cAAc,oCAAoC,CAAA;AAClD,cAAc,4CAA4C,CAAA;AAC1D,cAAc,+CAA+C,CAAA;AAC7D,cAAc,mDAAmD,CAAA;AACjE,cAAc,gCAAgC,CAAA;AAC9C,cAAc,2BAA2B,CAAA;AACzC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,uBAAuB,CAAA;AACrC,cAAc,kCAAkC,CAAA;AAChD,cAAc,uBAAuB,CAAA;AACrC,cAAc,wCAAwC,CAAA;AACtD,cAAc,mCAAmC,CAAA;AACjD,cAAc,mCAAmC,CAAA;AACjD,cAAc,8CAA8C,CAAA;AAC5D,cAAc,0CAA0C,CAAA;AACxD,cAAc,wCAAwC,CAAA;AACtD,cAAc,wCAAwC,CAAA;AACtD,cAAc,6CAA6C,CAAA;AAC3D,cAAc,mDAAmD,CAAA;AACjE,cAAc,8BAA8B,CAAA;AAC5C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,sBAAsB,CAAA;AACpC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,kCAAkC,CAAA;AAChD,cAAc,8BAA8B,CAAA;AAC5C,cAAc,qCAAqC,CAAA;AACnD,cAAc,0CAA0C,CAAA;AACxD,cAAc,yDAAyD,CAAA;AACvE,cAAc,4BAA4B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AAEH,cAAc,mBAAmB,CAAA;AACjC,cAAc,uBAAuB,CAAA;AACrC,cAAc,yBAAyB,CAAA;AACvC,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA;AAClC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,uCAAuC,CAAA;AACrD,cAAc,yBAAyB,CAAA;AACvC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,mBAAmB,CAAA;AACjC,cAAc,qCAAqC,CAAA;AACnD,cAAc,6BAA6B,CAAA;AAC3C,cAAc,qBAAqB,CAAA;AACnC,cAAc,sBAAsB,CAAA;AACpC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,yBAAyB,CAAA;AACvC,cAAc,yBAAyB,CAAA;AACvC,cAAc,2BAA2B,CAAA;AACzC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,2CAA2C,CAAA;AACzD,cAAc,8BAA8B,CAAA;AAC5C,cAAc,oCAAoC,CAAA;AAClD,cAAc,4CAA4C,CAAA;AAC1D,cAAc,yCAAyC,CAAA;AACvD,cAAc,4CAA4C,CAAA;AAC1D,cAAc,yCAAyC,CAAA;AACvD,cAAc,+BAA+B,CAAA;AAC7C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,sCAAsC,CAAA;AACpD,cAAc,mBAAmB,CAAA;AACjC,cAAc,0BAA0B,CAAA;AACxC,cAAc,2BAA2B,CAAA;AACzC,cAAc,oCAAoC,CAAA;AAClD,cAAc,4CAA4C,CAAA;AAC1D,cAAc,+CAA+C,CAAA;AAC7D,cAAc,mDAAmD,CAAA;AACjE,cAAc,gCAAgC,CAAA;AAC9C,cAAc,2BAA2B,CAAA;AACzC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,uBAAuB,CAAA;AACrC,cAAc,kCAAkC,CAAA;AAChD,cAAc,uBAAuB,CAAA;AACrC,cAAc,wCAAwC,CAAA;AACtD,cAAc,mCAAmC,CAAA;AACjD,cAAc,mCAAmC,CAAA;AACjD,cAAc,8CAA8C,CAAA;AAC5D,cAAc,0CAA0C,CAAA;AACxD,cAAc,wCAAwC,CAAA;AACtD,cAAc,wCAAwC,CAAA;AACtD,cAAc,6CAA6C,CAAA;AAC3D,cAAc,mDAAmD,CAAA;AACjE,cAAc,8BAA8B,CAAA;AAC5C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,sBAAsB,CAAA;AACpC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,kCAAkC,CAAA;AAChD,cAAc,8BAA8B,CAAA;AAC5C,cAAc,qCAAqC,CAAA;AACnD,cAAc,0CAA0C,CAAA;AACxD,cAAc,yDAAyD,CAAA;AACvE,cAAc,4BAA4B,CAAA"}
package/dist/index.js CHANGED
@@ -24,6 +24,7 @@ export * from './content/idempotency.repository.js';
24
24
  export * from './media/media.repository.js';
25
25
  export * from './common/storage.js';
26
26
  export * from './engine/policies.js';
27
+ export * from './engine/privacy.service.js';
27
28
  export * from './auth/hash-provider.js';
28
29
  export * from './auth/token-service.js';
29
30
  export * from './auth/user.repository.js';
@@ -1 +1 @@
1
- {"version":3,"file":"file-types.d.ts","sourceRoot":"","sources":["../../src/media/file-types.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,UAAU,GAAG,KAAK,CAAA;AAKrD,eAAO,MAAM,gBAAgB,aAAuE,CAAA;AACpG,eAAO,MAAM,wBAAwB,aAA2B,CAAA;AAChE,eAAO,MAAM,mBAAmB,aAAoF,CAAA;AACpH,eAAO,MAAM,kBAAkB,aAA8C,CAAA;AAI7E,eAAO,MAAM,gBAAgB,YAC3B,YAAY,EACZ,WAAW,EACX,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,cAAc,EACd,0BAA0B,CAClB,CAAA;AAGV,eAAO,MAAM,wBAAwB,YAAI,eAAe,EAAE,WAAW,CAAU,CAAA;AAC/E,eAAO,MAAM,mBAAmB,YAC9B,iBAAiB,EACjB,oBAAoB,EACpB,yEAAyE,EACzE,0BAA0B,EAC1B,mEAAmE,EACnE,+BAA+B,EAC/B,2EAA2E,EAC3E,YAAY,EACZ,UAAU,EACV,eAAe,CACP,CAAA;AACV,eAAO,MAAM,kBAAkB,YAC7B,iBAAiB,EACjB,8BAA8B,EAC9B,6BAA6B,EAC7B,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,CACV,CAAA;AAEV,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAS3D;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAMnF;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAcxE"}
1
+ {"version":3,"file":"file-types.d.ts","sourceRoot":"","sources":["../../src/media/file-types.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,UAAU,GAAG,KAAK,CAAA;AAKrD,eAAO,MAAM,gBAAgB,aAAuE,CAAA;AACpG,eAAO,MAAM,wBAAwB,aAA2B,CAAA;AAChE,eAAO,MAAM,mBAAmB,aAAoF,CAAA;AACpH,eAAO,MAAM,kBAAkB,aAA8C,CAAA;AAI7E,eAAO,MAAM,gBAAgB,YAC3B,YAAY,EACZ,WAAW,EACX,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,cAAc,EACd,0BAA0B,CAClB,CAAA;AAGV,eAAO,MAAM,wBAAwB,YAAI,eAAe,EAAE,WAAW,CAAU,CAAA;AAC/E,eAAO,MAAM,mBAAmB,YAC9B,iBAAiB,EACjB,oBAAoB,EACpB,yEAAyE,EACzE,0BAA0B,EAC1B,mEAAmE,EACnE,+BAA+B,EAC/B,2EAA2E,EAC3E,YAAY,EACZ,UAAU,EACV,eAAe,CACP,CAAA;AACV,eAAO,MAAM,kBAAkB,YAC7B,iBAAiB,EACjB,8BAA8B,EAC9B,6BAA6B,EAC7B,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,CACV,CAAA;AAEV,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAgB3D;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAOnF;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAcxE"}
@@ -44,11 +44,17 @@ export const ARCHIVE_MIME_TYPES = [
44
44
  ];
45
45
  export function extensionFromUrl(url) {
46
46
  try {
47
- const path = new URL(url).pathname;
47
+ const parsed = new URL(url);
48
+ const path = parsed.pathname;
48
49
  const dot = path.lastIndexOf('.');
49
- if (dot < 0 || dot === path.length - 1)
50
- return null;
51
- return path.slice(dot + 1).toLowerCase();
50
+ if (dot >= 0 && dot < path.length - 1) {
51
+ return path.slice(dot + 1).toLowerCase();
52
+ }
53
+ const fm = parsed.searchParams.get('fm') || parsed.searchParams.get('format') || parsed.searchParams.get('ext');
54
+ if (fm && /^[a-z0-9]+$/i.test(fm)) {
55
+ return fm.toLowerCase();
56
+ }
57
+ return null;
52
58
  }
53
59
  catch {
54
60
  return null;
@@ -57,8 +63,10 @@ export function extensionFromUrl(url) {
57
63
  export function isExtensionAccepted(ext, accept) {
58
64
  if (accept === 'any')
59
65
  return true;
60
- if (ext == null)
66
+ if (ext != null && BLOCKED_IMAGE_EXTENSIONS.has(ext))
61
67
  return false;
68
+ if (ext == null)
69
+ return true;
62
70
  if (accept === 'image')
63
71
  return IMAGE_EXTENSIONS.has(ext);
64
72
  if (accept === 'document')
@@ -8,12 +8,18 @@
8
8
  *
9
9
  * @module @beechcms/core/notifications/notification-service
10
10
  */
11
- import type { NotificationType } from './notification.repository.js';
12
- export interface CreateNotificationInput {
13
- title: string;
14
- message: string;
15
- type?: NotificationType;
16
- }
11
+ import { z } from 'zod';
12
+ export declare const createNotificationSchema: z.ZodObject<{
13
+ title: z.ZodString;
14
+ message: z.ZodString;
15
+ type: z.ZodOptional<z.ZodEnum<{
16
+ error: "error";
17
+ info: "info";
18
+ success: "success";
19
+ warning: "warning";
20
+ }>>;
21
+ }, z.core.$strip>;
22
+ export type CreateNotificationInput = z.infer<typeof createNotificationSchema>;
17
23
  export interface INotificationService {
18
24
  /**
19
25
  * Emit a notification.
@@ -1 +1 @@
1
- {"version":3,"file":"notification-service.d.ts","sourceRoot":"","sources":["../../src/notifications/notification-service.ts"],"names":[],"mappings":"AAGA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AAEpE,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,gBAAgB,CAAA;CACxB;AAED,MAAM,WAAW,oBAAoB;IACnC;;;;;;;;OAQG;IACH,MAAM,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;CAC7D"}
1
+ {"version":3,"file":"notification-service.d.ts","sourceRoot":"","sources":["../../src/notifications/notification-service.ts"],"names":[],"mappings":"AAGA;;;;;;;;;GASG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,eAAO,MAAM,wBAAwB;;;;;;;;;iBAInC,CAAA;AAEF,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAA;AAE9E,MAAM,WAAW,oBAAoB;IACnC;;;;;;;;OAQG;IACH,MAAM,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;CAC7D"}
@@ -1,3 +1,18 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  // Copyright (c) 2024–2026 Flavio De Musso
3
- export {};
3
+ /**
4
+ * Notification service contract.
5
+ *
6
+ * High-level port that callers use to emit a notification without knowing
7
+ * about the underlying repository, the database, or background scheduling.
8
+ * Mirrors the email module pattern: handlers depend on the service, the
9
+ * service depends on the repository, the repository depends on D1.
10
+ *
11
+ * @module @beechcms/core/notifications/notification-service
12
+ */
13
+ import { z } from 'zod';
14
+ export const createNotificationSchema = z.object({
15
+ title: z.string().min(1),
16
+ message: z.string().min(1),
17
+ type: z.enum(['info', 'success', 'warning', 'error']).optional(),
18
+ });
@@ -31,9 +31,13 @@ export type JobRegistry = Record<string, JobHandler<any>>;
31
31
  * Producer port. `enqueue` schedules deferred work and returns once the message
32
32
  * is accepted by the transport. Like INotificationService, implementations MUST
33
33
  * decide their own fire-and-forget vs inline semantics and MUST NOT let a
34
- * transport failure crash the request that called enqueue.
34
+ * transport failure crash the request that called enqueue. Resolves `true`
35
+ * when the message was handed off successfully, `false` when it was dropped
36
+ * (e.g. transport rejection, oversized payload, no handler) — callers that
37
+ * need at-least-once delivery guarantees MUST check this instead of assuming
38
+ * a resolved promise means success.
35
39
  */
36
40
  export interface IQueueService {
37
- enqueue<T>(name: string, payload: T): Promise<void>;
41
+ enqueue<T>(name: string, payload: T): Promise<boolean>;
38
42
  }
39
43
  //# sourceMappingURL=queue.interface.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"queue.interface.d.ts","sourceRoot":"","sources":["../../src/queue/queue.interface.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAA;AACzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAE7D;;;GAGG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,OAAO;IACvC,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,CAAC,CAAA;CACX;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,iBAAiB,CAAA;IAC7B,MAAM,EAAE,WAAW,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,YAAY,CAAA;IACzB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;CACxC;AAED,0EAA0E;AAC1E,MAAM,MAAM,UAAU,CAAC,CAAC,GAAG,OAAO,IAAI,CACpC,OAAO,EAAE,CAAC,EACV,OAAO,EAAE,UAAU,KAChB,OAAO,CAAC,IAAI,CAAC,CAAA;AAElB,0DAA0D;AAC1D,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,CAAA;AAEzD;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACpD"}
1
+ {"version":3,"file":"queue.interface.d.ts","sourceRoot":"","sources":["../../src/queue/queue.interface.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAA;AACzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAE7D;;;GAGG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,OAAO;IACvC,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,CAAC,CAAA;CACX;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,iBAAiB,CAAA;IAC7B,MAAM,EAAE,WAAW,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,YAAY,CAAA;IACzB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;CACxC;AAED,0EAA0E;AAC1E,MAAM,MAAM,UAAU,CAAC,CAAC,GAAG,OAAO,IAAI,CACpC,OAAO,EAAE,CAAC,EACV,OAAO,EAAE,UAAU,KAChB,OAAO,CAAC,IAAI,CAAC,CAAA;AAElB,0DAA0D;AAC1D,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,CAAA;AAEzD;;;;;;;;;GASG;AACH,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CACvD"}
@@ -1,6 +1,6 @@
1
1
  import type { IQueueService } from './queue.interface.js';
2
2
  /** Safe no-op producer (e.g. unit tests that don't assert on enqueue). */
3
3
  export declare class NoOpQueueService implements IQueueService {
4
- enqueue<T>(_name: string, _payload: T): Promise<void>;
4
+ enqueue<T>(_name: string, _payload: T): Promise<boolean>;
5
5
  }
6
6
  //# sourceMappingURL=queue.stub.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"queue.stub.d.ts","sourceRoot":"","sources":["../../src/queue/queue.stub.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAEzD,0EAA0E;AAC1E,qBAAa,gBAAiB,YAAW,aAAa;IAC9C,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAE1D;CACF"}
1
+ {"version":3,"file":"queue.stub.d.ts","sourceRoot":"","sources":["../../src/queue/queue.stub.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAEzD,0EAA0E;AAC1E,qBAAa,gBAAiB,YAAW,aAAa;IAC9C,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAG7D;CACF"}
@@ -3,6 +3,7 @@
3
3
  /** Safe no-op producer (e.g. unit tests that don't assert on enqueue). */
4
4
  export class NoOpQueueService {
5
5
  async enqueue(_name, _payload) {
6
- // intentionally empty
6
+ // intentionally empty; reports success since there is nothing to fail
7
+ return true;
7
8
  }
8
9
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@beechcms/core",
3
- "version": "0.6.3",
3
+ "version": "0.6.5",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -1,39 +0,0 @@
1
- import type { ContentRepository } from './content/content.repository.js';
2
- import type { BeechBucket } from './common/storage.js';
3
- import type { IClock } from './common/clock.js';
4
- import type { IIdGenerator } from './common/id-generator.js';
5
- /**
6
- * The envelope put on the wire / queue. `name` selects the handler from the
7
- * JobRegistry; `payload` is the developer-supplied, JSON-serializable body.
8
- */
9
- export interface QueueMessage<T = unknown> {
10
- name: string;
11
- payload: T;
12
- }
13
- /**
14
- * Execution context handed to every job. Botanical Invariant: jobs receive the
15
- * engine-mediated repository, NEVER a raw D1Database. `env` is a read-only,
16
- * stringly-typed view of bindings/secrets for things like fetch targets — it
17
- * deliberately does not expose `DB`.
18
- */
19
- export interface JobContext {
20
- repository: ContentRepository;
21
- bucket: BeechBucket;
22
- clock: IClock;
23
- idGenerator: IIdGenerator;
24
- env: Record<string, string | undefined>;
25
- }
26
- /** A single background worker. Receives the decoded payload + context. */
27
- export type JobHandler<T = unknown> = (payload: T, context: JobContext) => Promise<void>;
28
- /** Name -> handler map, supplied via BeechConfig.jobs. */
29
- export type JobRegistry = Record<string, JobHandler<any>>;
30
- /**
31
- * Producer port. `enqueue` schedules deferred work and returns once the message
32
- * is accepted by the transport. Like INotificationService, implementations MUST
33
- * decide their own fire-and-forget vs inline semantics and MUST NOT let a
34
- * transport failure crash the request that called enqueue.
35
- */
36
- export interface IQueueService {
37
- enqueue<T>(name: string, payload: T): Promise<void>;
38
- }
39
- //# sourceMappingURL=queue.interface.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"queue.interface.d.ts","sourceRoot":"","sources":["../src/queue.interface.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AACxE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAE5D;;;GAGG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,OAAO;IACvC,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,CAAC,CAAA;CACX;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,iBAAiB,CAAA;IAC7B,MAAM,EAAE,WAAW,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,YAAY,CAAA;IACzB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;CACxC;AAED,0EAA0E;AAC1E,MAAM,MAAM,UAAU,CAAC,CAAC,GAAG,OAAO,IAAI,CACpC,OAAO,EAAE,CAAC,EACV,OAAO,EAAE,UAAU,KAChB,OAAO,CAAC,IAAI,CAAC,CAAA;AAElB,0DAA0D;AAC1D,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,CAAA;AAEzD;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACpD"}
@@ -1,3 +0,0 @@
1
- // SPDX-License-Identifier: MIT
2
- // Copyright (c) 2024–2026 Flavio De Musso
3
- export {};
@@ -1,6 +0,0 @@
1
- import type { IQueueService } from './queue.interface.js';
2
- /** Safe no-op producer (e.g. unit tests that don't assert on enqueue). */
3
- export declare class NoOpQueueService implements IQueueService {
4
- enqueue<T>(_name: string, _payload: T): Promise<void>;
5
- }
6
- //# sourceMappingURL=queue.stub.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"queue.stub.d.ts","sourceRoot":"","sources":["../src/queue.stub.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAEzD,0EAA0E;AAC1E,qBAAa,gBAAiB,YAAW,aAAa;IAC9C,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAE1D;CACF"}
@@ -1,8 +0,0 @@
1
- // SPDX-License-Identifier: MIT
2
- // Copyright (c) 2024–2026 Flavio De Musso
3
- /** Safe no-op producer (e.g. unit tests that don't assert on enqueue). */
4
- export class NoOpQueueService {
5
- async enqueue(_name, _payload) {
6
- // intentionally empty
7
- }
8
- }