@thebes/cadmus 0.2.1

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 (103) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +150 -0
  3. package/dist/astro/index.cjs +149 -0
  4. package/dist/astro/index.cjs.map +1 -0
  5. package/dist/astro/index.d.cts +101 -0
  6. package/dist/astro/index.d.cts.map +1 -0
  7. package/dist/astro/index.d.ts +101 -0
  8. package/dist/astro/index.d.ts.map +1 -0
  9. package/dist/astro/index.js +146 -0
  10. package/dist/astro/index.js.map +1 -0
  11. package/dist/auth/index.cjs +59 -0
  12. package/dist/auth/index.cjs.map +1 -0
  13. package/dist/auth/index.d.cts +14 -0
  14. package/dist/auth/index.d.cts.map +1 -0
  15. package/dist/auth/index.d.ts +14 -0
  16. package/dist/auth/index.d.ts.map +1 -0
  17. package/dist/auth/index.js +54 -0
  18. package/dist/auth/index.js.map +1 -0
  19. package/dist/cache/index.cjs +18 -0
  20. package/dist/cache/index.cjs.map +1 -0
  21. package/dist/cache/index.d.cts +10 -0
  22. package/dist/cache/index.d.cts.map +1 -0
  23. package/dist/cache/index.d.ts +10 -0
  24. package/dist/cache/index.d.ts.map +1 -0
  25. package/dist/cache/index.js +17 -0
  26. package/dist/cache/index.js.map +1 -0
  27. package/dist/cms/index.cjs +763 -0
  28. package/dist/cms/index.cjs.map +1 -0
  29. package/dist/cms/index.d.cts +2 -0
  30. package/dist/cms/index.d.ts +2 -0
  31. package/dist/cms/index.js +743 -0
  32. package/dist/cms/index.js.map +1 -0
  33. package/dist/db/index.cjs +10 -0
  34. package/dist/db/index.cjs.map +1 -0
  35. package/dist/db/index.d.cts +7 -0
  36. package/dist/db/index.d.cts.map +1 -0
  37. package/dist/db/index.d.ts +7 -0
  38. package/dist/db/index.d.ts.map +1 -0
  39. package/dist/db/index.js +9 -0
  40. package/dist/db/index.js.map +1 -0
  41. package/dist/email/index.cjs +25 -0
  42. package/dist/email/index.cjs.map +1 -0
  43. package/dist/email/index.d.cts +12 -0
  44. package/dist/email/index.d.cts.map +1 -0
  45. package/dist/email/index.d.ts +12 -0
  46. package/dist/email/index.d.ts.map +1 -0
  47. package/dist/email/index.js +24 -0
  48. package/dist/email/index.js.map +1 -0
  49. package/dist/errors-CW6Lz0AQ.cjs +196 -0
  50. package/dist/errors-CW6Lz0AQ.cjs.map +1 -0
  51. package/dist/errors-mZIqZJO4.js +125 -0
  52. package/dist/errors-mZIqZJO4.js.map +1 -0
  53. package/dist/hono/index.cjs +132 -0
  54. package/dist/hono/index.cjs.map +1 -0
  55. package/dist/hono/index.d.cts +59 -0
  56. package/dist/hono/index.d.cts.map +1 -0
  57. package/dist/hono/index.d.ts +59 -0
  58. package/dist/hono/index.d.ts.map +1 -0
  59. package/dist/hono/index.js +130 -0
  60. package/dist/hono/index.js.map +1 -0
  61. package/dist/index-BUrCSGVb.d.cts +616 -0
  62. package/dist/index-BUrCSGVb.d.cts.map +1 -0
  63. package/dist/index-BUrCSGVb.d.ts +616 -0
  64. package/dist/index-BUrCSGVb.d.ts.map +1 -0
  65. package/dist/index.cjs +60 -0
  66. package/dist/index.d.cts +107 -0
  67. package/dist/index.d.cts.map +1 -0
  68. package/dist/index.d.ts +107 -0
  69. package/dist/index.d.ts.map +1 -0
  70. package/dist/index.js +11 -0
  71. package/dist/queues/index.cjs +31 -0
  72. package/dist/queues/index.cjs.map +1 -0
  73. package/dist/queues/index.d.cts +22 -0
  74. package/dist/queues/index.d.cts.map +1 -0
  75. package/dist/queues/index.d.ts +22 -0
  76. package/dist/queues/index.d.ts.map +1 -0
  77. package/dist/queues/index.js +29 -0
  78. package/dist/queues/index.js.map +1 -0
  79. package/dist/rate-limit/index.cjs +38 -0
  80. package/dist/rate-limit/index.cjs.map +1 -0
  81. package/dist/rate-limit/index.d.cts +14 -0
  82. package/dist/rate-limit/index.d.cts.map +1 -0
  83. package/dist/rate-limit/index.d.ts +14 -0
  84. package/dist/rate-limit/index.d.ts.map +1 -0
  85. package/dist/rate-limit/index.js +37 -0
  86. package/dist/rate-limit/index.js.map +1 -0
  87. package/dist/session/index.cjs +48 -0
  88. package/dist/session/index.cjs.map +1 -0
  89. package/dist/session/index.d.cts +14 -0
  90. package/dist/session/index.d.cts.map +1 -0
  91. package/dist/session/index.d.ts +14 -0
  92. package/dist/session/index.d.ts.map +1 -0
  93. package/dist/session/index.js +45 -0
  94. package/dist/session/index.js.map +1 -0
  95. package/dist/storage/index.cjs +29 -0
  96. package/dist/storage/index.cjs.map +1 -0
  97. package/dist/storage/index.d.cts +38 -0
  98. package/dist/storage/index.d.cts.map +1 -0
  99. package/dist/storage/index.d.ts +38 -0
  100. package/dist/storage/index.d.ts.map +1 -0
  101. package/dist/storage/index.js +26 -0
  102. package/dist/storage/index.js.map +1 -0
  103. package/package.json +115 -0
package/dist/index.cjs ADDED
@@ -0,0 +1,60 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_auth_index = require("./auth/index.cjs");
3
+ const require_cache_index = require("./cache/index.cjs");
4
+ const require_errors = require("./errors-CW6Lz0AQ.cjs");
5
+ const require_queues_index = require("./queues/index.cjs");
6
+ const require_cms_index = require("./cms/index.cjs");
7
+ const require_db_index = require("./db/index.cjs");
8
+ const require_email_index = require("./email/index.cjs");
9
+ const require_rate_limit_index = require("./rate-limit/index.cjs");
10
+ const require_session_index = require("./session/index.cjs");
11
+ const require_storage_index = require("./storage/index.cjs");
12
+ exports.CadmusAccessDeniedError = require_errors.CadmusAccessDeniedError;
13
+ exports.CadmusApiError = require_errors.CadmusApiError;
14
+ exports.CadmusAuthError = require_errors.CadmusAuthError;
15
+ exports.CadmusCacheError = require_errors.CadmusCacheError;
16
+ exports.CadmusCmsError = require_errors.CadmusCmsError;
17
+ exports.CadmusDbError = require_errors.CadmusDbError;
18
+ exports.CadmusEmailError = require_errors.CadmusEmailError;
19
+ exports.CadmusError = require_errors.CadmusError;
20
+ exports.CadmusQueueError = require_errors.CadmusQueueError;
21
+ exports.CadmusRateLimitError = require_errors.CadmusRateLimitError;
22
+ exports.CadmusSessionError = require_errors.CadmusSessionError;
23
+ exports.CadmusStorageError = require_errors.CadmusStorageError;
24
+ exports.IMAGE_MIME_WHITELIST = require_storage_index.IMAGE_MIME_WHITELIST;
25
+ exports.MAX_IMAGE_UPLOAD_BYTES = require_storage_index.MAX_IMAGE_UPLOAD_BYTES;
26
+ exports.can = require_cms_index.can;
27
+ exports.checkRateLimit = require_rate_limit_index.checkRateLimit;
28
+ exports.cmsConfigToSchema = require_cms_index.cmsConfigToSchema;
29
+ exports.collectionSearchTableName = require_cms_index.collectionSearchTableName;
30
+ exports.collectionSearchTableSQL = require_cms_index.collectionSearchTableSQL;
31
+ exports.collectionToTable = require_cms_index.collectionToTable;
32
+ exports.collectionVersionsTable = require_cms_index.collectionVersionsTable;
33
+ exports.createLocalApi = require_cms_index.createLocalApi;
34
+ exports.createSession = require_session_index.createSession;
35
+ exports.createVersionedLocalApi = require_cms_index.createVersionedLocalApi;
36
+ exports.createWebhookHook = require_cms_index.createWebhookHook;
37
+ exports.db = require_db_index.db;
38
+ exports.defineCmsConfig = require_cms_index.defineCmsConfig;
39
+ exports.defineCollection = require_cms_index.defineCollection;
40
+ exports.deleteSession = require_session_index.deleteSession;
41
+ exports.deliverWebhookMessage = require_cms_index.deliverWebhookMessage;
42
+ exports.enqueue = require_queues_index.enqueue;
43
+ exports.extractSearchText = require_cms_index.extractSearchText;
44
+ exports.flattenDoc = require_cms_index.flattenDoc;
45
+ exports.flattenFields = require_cms_index.flattenFields;
46
+ exports.generateSchemaSource = require_cms_index.generateSchemaSource;
47
+ exports.generateSessionId = require_auth_index.generateSessionId;
48
+ exports.generateToken = require_auth_index.generateToken;
49
+ exports.getCollectionsMeta = require_cms_index.getCollectionsMeta;
50
+ exports.getRegisteredApi = require_cms_index.getRegisteredApi;
51
+ exports.getSession = require_session_index.getSession;
52
+ exports.hashToken = require_auth_index.hashToken;
53
+ exports.nestDoc = require_cms_index.nestDoc;
54
+ exports.processBatch = require_queues_index.processBatch;
55
+ exports.purgeCache = require_cache_index.purgeCache;
56
+ exports.relationshipJoinTables = require_cms_index.relationshipJoinTables;
57
+ exports.sendEmail = require_email_index.sendEmail;
58
+ exports.signSession = require_auth_index.signSession;
59
+ exports.validateImageFile = require_storage_index.validateImageFile;
60
+ exports.verifySession = require_auth_index.verifySession;
@@ -0,0 +1,107 @@
1
+ import { generateSessionId, generateToken, hashToken, signSession, verifySession } from "./auth/index.cjs";
2
+ import { purgeCache } from "./cache/index.cjs";
3
+ import { A as CollectionAccess, B as RelationshipFieldConfig, C as relationshipJoinTables, D as CadmeaPlugin, E as BaseFieldConfig, F as GroupFieldConfig, G as flattenDoc, H as SelectFieldConfig, I as JsonFieldConfig, K as flattenFields, L as JsonValue, M as CollectionHooks, N as DateFieldConfig, O as CheckboxFieldConfig, P as FieldConfig, R as NumberFieldConfig, S as extractSearchText, T as ArrayFieldConfig, U as TextFieldConfig, V as RichTextFieldConfig, W as UploadFieldConfig, _ as cmsConfigToSchema, a as generateSchemaSource, b as collectionToTable, c as CmsRegistry, d as can, f as createLocalApi, g as defineCollection, h as defineCmsConfig, i as deliverWebhookMessage, j as CollectionConfig, k as CmsConfig, l as LocalApi, m as getRegisteredApi, n as WebhookMessage, o as CollectionMeta, p as createVersionedLocalApi, q as nestDoc, r as createWebhookHook, s as getCollectionsMeta, t as WebhookConfig, u as VersionedLocalApi, v as collectionSearchTableName, w as AccessFn, x as collectionVersionsTable, y as collectionSearchTableSQL, z as RelationshipDepth } from "./index-BUrCSGVb.cjs";
4
+ import { db } from "./db/index.cjs";
5
+ import { SendEmailInput, sendEmail } from "./email/index.cjs";
6
+ import { QueueMessageHandler, enqueue, processBatch } from "./queues/index.cjs";
7
+ import { RateLimitResult, checkRateLimit } from "./rate-limit/index.cjs";
8
+ import { createSession, deleteSession, getSession } from "./session/index.cjs";
9
+ import { IMAGE_MIME_WHITELIST, ImageService, MAX_IMAGE_UPLOAD_BYTES, RenderedImage, validateImageFile } from "./storage/index.cjs";
10
+
11
+ //#region src/errors.d.ts
12
+ declare global {
13
+ interface ErrorConstructor {
14
+ captureStackTrace?(targetObject: object, constructorOpt?: Function): void;
15
+ }
16
+ }
17
+ /**
18
+ * Base class for all Cadmus errors.
19
+ * All primitives throw CadmusError or a typed subclass — never a raw Error.
20
+ *
21
+ * @example
22
+ * try {
23
+ * await createMagicLink({ kv, email, to })
24
+ * } catch (e) {
25
+ * if (e instanceof CadmusAuthError) {
26
+ * // auth-specific handling
27
+ * } else if (e instanceof CadmusError) {
28
+ * // any cadmus error — e.code tells you which primitive threw
29
+ * } else {
30
+ * throw e // re-throw unknown errors
31
+ * }
32
+ * }
33
+ */
34
+ declare class CadmusError extends Error {
35
+ readonly code: string;
36
+ readonly cause?: unknown | undefined;
37
+ constructor(message: string, code: string, cause?: unknown | undefined);
38
+ }
39
+ /** Thrown by @thebes/cadmus/auth primitives */
40
+ declare class CadmusAuthError extends CadmusError {
41
+ constructor(message: string, cause?: unknown);
42
+ }
43
+ /** Thrown by @thebes/cadmus/db primitives */
44
+ declare class CadmusDbError extends CadmusError {
45
+ constructor(message: string, cause?: unknown);
46
+ }
47
+ /** Thrown by @thebes/cadmus/storage primitives */
48
+ declare class CadmusStorageError extends CadmusError {
49
+ constructor(message: string, cause?: unknown);
50
+ }
51
+ /** Thrown by @thebes/cadmus/cache primitives */
52
+ declare class CadmusCacheError extends CadmusError {
53
+ constructor(message: string, cause?: unknown);
54
+ }
55
+ /** Thrown by @thebes/cadmus/email primitives */
56
+ declare class CadmusEmailError extends CadmusError {
57
+ constructor(message: string, cause?: unknown);
58
+ }
59
+ /** Thrown by @thebes/cadmus/session primitives */
60
+ declare class CadmusSessionError extends CadmusError {
61
+ constructor(message: string, cause?: unknown);
62
+ }
63
+ /** Thrown by @thebes/cadmus/rate-limit primitives */
64
+ declare class CadmusRateLimitError extends CadmusError {
65
+ constructor(message: string, cause?: unknown);
66
+ }
67
+ /** Thrown by @thebes/cadmus/queues primitives */
68
+ declare class CadmusQueueError extends CadmusError {
69
+ constructor(message: string, cause?: unknown);
70
+ }
71
+ /** Thrown by @thebes/cadmus/cms primitives */
72
+ declare class CadmusCmsError extends CadmusError {
73
+ constructor(message: string, cause?: unknown);
74
+ }
75
+ /**
76
+ * Thrown by @thebes/cadmus/cms's createLocalApi when a collection's
77
+ * `access` function rejects an operation. A distinct subclass (rather than
78
+ * a plain CadmusCmsError) so consumers like mountCmsRoutes can map it to
79
+ * 403 by `instanceof`, not by matching on message text.
80
+ */
81
+ declare class CadmusAccessDeniedError extends CadmusCmsError {
82
+ constructor(message: string, cause?: unknown);
83
+ }
84
+ /**
85
+ * Thrown by @thebes/cadmus/hono's `createCmsApiClient` when a request
86
+ * against a `mountCmsRoutes` surface returns a non-2xx response. Carries
87
+ * the HTTP status and parsed body so callers can branch on `status`
88
+ * (e.g. 403 → access denied, 404 → not found) instead of re-parsing
89
+ * `{ error: string }` response bodies by hand.
90
+ */
91
+ declare class CadmusApiError extends CadmusError {
92
+ readonly status: number;
93
+ readonly body: unknown;
94
+ constructor(message: string, status: number, body: unknown);
95
+ }
96
+ //#endregion
97
+ //#region src/index.d.ts
98
+ interface CadmusEnv {
99
+ DB: D1Database;
100
+ KV: KVNamespace;
101
+ R2: R2Bucket;
102
+ EMAIL: SendEmail;
103
+ SESSION_SECRET: string;
104
+ }
105
+ //#endregion
106
+ export { AccessFn, ArrayFieldConfig, BaseFieldConfig, CadmeaPlugin, CadmusAccessDeniedError, CadmusApiError, CadmusAuthError, CadmusCacheError, CadmusCmsError, CadmusDbError, CadmusEmailError, CadmusEnv, CadmusError, CadmusQueueError, CadmusRateLimitError, CadmusSessionError, CadmusStorageError, CheckboxFieldConfig, CmsConfig, CmsRegistry, CollectionAccess, CollectionConfig, CollectionHooks, CollectionMeta, DateFieldConfig, FieldConfig, GroupFieldConfig, IMAGE_MIME_WHITELIST, ImageService, JsonFieldConfig, JsonValue, LocalApi, MAX_IMAGE_UPLOAD_BYTES, NumberFieldConfig, QueueMessageHandler, RateLimitResult, RelationshipDepth, RelationshipFieldConfig, RenderedImage, RichTextFieldConfig, SelectFieldConfig, SendEmailInput, TextFieldConfig, UploadFieldConfig, VersionedLocalApi, WebhookConfig, WebhookMessage, can, checkRateLimit, cmsConfigToSchema, collectionSearchTableName, collectionSearchTableSQL, collectionToTable, collectionVersionsTable, createLocalApi, createSession, createVersionedLocalApi, createWebhookHook, db, defineCmsConfig, defineCollection, deleteSession, deliverWebhookMessage, enqueue, extractSearchText, flattenDoc, flattenFields, generateSchemaSource, generateSessionId, generateToken, getCollectionsMeta, getRegisteredApi, getSession, hashToken, nestDoc, processBatch, purgeCache, relationshipJoinTables, sendEmail, signSession, validateImageFile, verifySession };
107
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/errors.ts","../src/index.ts"],"mappings":";;;;;;;;;;;QAOQ,MAAA;EAAA,UACI,gBAAA;IAER,iBAAA,EAAmB,YAAA,UAAsB,cAAA,GAAiB,QAAQ;EAAA;AAAA;;;;;;;;;;;;;;;;;;cAqBzD,WAAA,SAAoB,KAAK;EAAA,SAGlB,IAAA;EAAA,SACA,KAAA;cAFhB,OAAA,UACgB,IAAA,UACA,KAAA;AAAA;;cAYP,eAAA,SAAwB,WAAW;cAClC,OAAA,UAAiB,KAAA;AAAA;;cAOlB,aAAA,SAAsB,WAAW;cAChC,OAAA,UAAiB,KAAA;AAAA;;cAOlB,kBAAA,SAA2B,WAAW;cACrC,OAAA,UAAiB,KAAA;AAAA;;cAOlB,gBAAA,SAAyB,WAAW;cACnC,OAAA,UAAiB,KAAA;AAAA;;cAOlB,gBAAA,SAAyB,WAAW;cACnC,OAAA,UAAiB,KAAA;AAAA;AAzB/B;AAAA,cAgCa,kBAAA,SAA2B,WAAW;cACrC,OAAA,UAAiB,KAAA;AAAA;;cAOlB,oBAAA,SAA6B,WAAW;cACvC,OAAA,UAAiB,KAAA;AAAA;;cAOlB,gBAAA,SAAyB,WAAW;cACnC,OAAA,UAAiB,KAAA;AAAA;;cAOlB,cAAA,SAAuB,WAAW;cACjC,OAAA,UAAiB,KAAA;AAAA;;;;AAhDe;AAO9C;;cAqDa,uBAAA,SAAgC,cAAc;cAC7C,OAAA,UAAiB,KAAA;AAAA;;;;;AArDe;AAO9C;;cA2Da,cAAA,SAAuB,WAAW;EAAA,SAG3B,MAAA;EAAA,SACA,IAAA;cAFhB,OAAA,UACgB,MAAA,UACA,IAAA;AAAA;;;UC3HH,SAAA;EACf,EAAA,EAAI,UAAA;EACJ,EAAA,EAAI,WAAA;EACJ,EAAA,EAAI,QAAA;EACJ,KAAA,EAAO,SAAA;EACP,cAAA;AAAA"}
@@ -0,0 +1,107 @@
1
+ import { generateSessionId, generateToken, hashToken, signSession, verifySession } from "./auth/index.js";
2
+ import { purgeCache } from "./cache/index.js";
3
+ import { A as CollectionAccess, B as RelationshipFieldConfig, C as relationshipJoinTables, D as CadmeaPlugin, E as BaseFieldConfig, F as GroupFieldConfig, G as flattenDoc, H as SelectFieldConfig, I as JsonFieldConfig, K as flattenFields, L as JsonValue, M as CollectionHooks, N as DateFieldConfig, O as CheckboxFieldConfig, P as FieldConfig, R as NumberFieldConfig, S as extractSearchText, T as ArrayFieldConfig, U as TextFieldConfig, V as RichTextFieldConfig, W as UploadFieldConfig, _ as cmsConfigToSchema, a as generateSchemaSource, b as collectionToTable, c as CmsRegistry, d as can, f as createLocalApi, g as defineCollection, h as defineCmsConfig, i as deliverWebhookMessage, j as CollectionConfig, k as CmsConfig, l as LocalApi, m as getRegisteredApi, n as WebhookMessage, o as CollectionMeta, p as createVersionedLocalApi, q as nestDoc, r as createWebhookHook, s as getCollectionsMeta, t as WebhookConfig, u as VersionedLocalApi, v as collectionSearchTableName, w as AccessFn, x as collectionVersionsTable, y as collectionSearchTableSQL, z as RelationshipDepth } from "./index-BUrCSGVb.js";
4
+ import { db } from "./db/index.js";
5
+ import { SendEmailInput, sendEmail } from "./email/index.js";
6
+ import { QueueMessageHandler, enqueue, processBatch } from "./queues/index.js";
7
+ import { RateLimitResult, checkRateLimit } from "./rate-limit/index.js";
8
+ import { createSession, deleteSession, getSession } from "./session/index.js";
9
+ import { IMAGE_MIME_WHITELIST, ImageService, MAX_IMAGE_UPLOAD_BYTES, RenderedImage, validateImageFile } from "./storage/index.js";
10
+
11
+ //#region src/errors.d.ts
12
+ declare global {
13
+ interface ErrorConstructor {
14
+ captureStackTrace?(targetObject: object, constructorOpt?: Function): void;
15
+ }
16
+ }
17
+ /**
18
+ * Base class for all Cadmus errors.
19
+ * All primitives throw CadmusError or a typed subclass — never a raw Error.
20
+ *
21
+ * @example
22
+ * try {
23
+ * await createMagicLink({ kv, email, to })
24
+ * } catch (e) {
25
+ * if (e instanceof CadmusAuthError) {
26
+ * // auth-specific handling
27
+ * } else if (e instanceof CadmusError) {
28
+ * // any cadmus error — e.code tells you which primitive threw
29
+ * } else {
30
+ * throw e // re-throw unknown errors
31
+ * }
32
+ * }
33
+ */
34
+ declare class CadmusError extends Error {
35
+ readonly code: string;
36
+ readonly cause?: unknown | undefined;
37
+ constructor(message: string, code: string, cause?: unknown | undefined);
38
+ }
39
+ /** Thrown by @thebes/cadmus/auth primitives */
40
+ declare class CadmusAuthError extends CadmusError {
41
+ constructor(message: string, cause?: unknown);
42
+ }
43
+ /** Thrown by @thebes/cadmus/db primitives */
44
+ declare class CadmusDbError extends CadmusError {
45
+ constructor(message: string, cause?: unknown);
46
+ }
47
+ /** Thrown by @thebes/cadmus/storage primitives */
48
+ declare class CadmusStorageError extends CadmusError {
49
+ constructor(message: string, cause?: unknown);
50
+ }
51
+ /** Thrown by @thebes/cadmus/cache primitives */
52
+ declare class CadmusCacheError extends CadmusError {
53
+ constructor(message: string, cause?: unknown);
54
+ }
55
+ /** Thrown by @thebes/cadmus/email primitives */
56
+ declare class CadmusEmailError extends CadmusError {
57
+ constructor(message: string, cause?: unknown);
58
+ }
59
+ /** Thrown by @thebes/cadmus/session primitives */
60
+ declare class CadmusSessionError extends CadmusError {
61
+ constructor(message: string, cause?: unknown);
62
+ }
63
+ /** Thrown by @thebes/cadmus/rate-limit primitives */
64
+ declare class CadmusRateLimitError extends CadmusError {
65
+ constructor(message: string, cause?: unknown);
66
+ }
67
+ /** Thrown by @thebes/cadmus/queues primitives */
68
+ declare class CadmusQueueError extends CadmusError {
69
+ constructor(message: string, cause?: unknown);
70
+ }
71
+ /** Thrown by @thebes/cadmus/cms primitives */
72
+ declare class CadmusCmsError extends CadmusError {
73
+ constructor(message: string, cause?: unknown);
74
+ }
75
+ /**
76
+ * Thrown by @thebes/cadmus/cms's createLocalApi when a collection's
77
+ * `access` function rejects an operation. A distinct subclass (rather than
78
+ * a plain CadmusCmsError) so consumers like mountCmsRoutes can map it to
79
+ * 403 by `instanceof`, not by matching on message text.
80
+ */
81
+ declare class CadmusAccessDeniedError extends CadmusCmsError {
82
+ constructor(message: string, cause?: unknown);
83
+ }
84
+ /**
85
+ * Thrown by @thebes/cadmus/hono's `createCmsApiClient` when a request
86
+ * against a `mountCmsRoutes` surface returns a non-2xx response. Carries
87
+ * the HTTP status and parsed body so callers can branch on `status`
88
+ * (e.g. 403 → access denied, 404 → not found) instead of re-parsing
89
+ * `{ error: string }` response bodies by hand.
90
+ */
91
+ declare class CadmusApiError extends CadmusError {
92
+ readonly status: number;
93
+ readonly body: unknown;
94
+ constructor(message: string, status: number, body: unknown);
95
+ }
96
+ //#endregion
97
+ //#region src/index.d.ts
98
+ interface CadmusEnv {
99
+ DB: D1Database;
100
+ KV: KVNamespace;
101
+ R2: R2Bucket;
102
+ EMAIL: SendEmail;
103
+ SESSION_SECRET: string;
104
+ }
105
+ //#endregion
106
+ export { AccessFn, ArrayFieldConfig, BaseFieldConfig, CadmeaPlugin, CadmusAccessDeniedError, CadmusApiError, CadmusAuthError, CadmusCacheError, CadmusCmsError, CadmusDbError, CadmusEmailError, CadmusEnv, CadmusError, CadmusQueueError, CadmusRateLimitError, CadmusSessionError, CadmusStorageError, CheckboxFieldConfig, CmsConfig, CmsRegistry, CollectionAccess, CollectionConfig, CollectionHooks, CollectionMeta, DateFieldConfig, FieldConfig, GroupFieldConfig, IMAGE_MIME_WHITELIST, ImageService, JsonFieldConfig, JsonValue, LocalApi, MAX_IMAGE_UPLOAD_BYTES, NumberFieldConfig, QueueMessageHandler, RateLimitResult, RelationshipDepth, RelationshipFieldConfig, RenderedImage, RichTextFieldConfig, SelectFieldConfig, SendEmailInput, TextFieldConfig, UploadFieldConfig, VersionedLocalApi, WebhookConfig, WebhookMessage, can, checkRateLimit, cmsConfigToSchema, collectionSearchTableName, collectionSearchTableSQL, collectionToTable, collectionVersionsTable, createLocalApi, createSession, createVersionedLocalApi, createWebhookHook, db, defineCmsConfig, defineCollection, deleteSession, deliverWebhookMessage, enqueue, extractSearchText, flattenDoc, flattenFields, generateSchemaSource, generateSessionId, generateToken, getCollectionsMeta, getRegisteredApi, getSession, hashToken, nestDoc, processBatch, purgeCache, relationshipJoinTables, sendEmail, signSession, validateImageFile, verifySession };
107
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/errors.ts","../src/index.ts"],"mappings":";;;;;;;;;;;QAOQ,MAAA;EAAA,UACI,gBAAA;IAER,iBAAA,EAAmB,YAAA,UAAsB,cAAA,GAAiB,QAAQ;EAAA;AAAA;;;;;;;;;;;;;;;;;;cAqBzD,WAAA,SAAoB,KAAK;EAAA,SAGlB,IAAA;EAAA,SACA,KAAA;cAFhB,OAAA,UACgB,IAAA,UACA,KAAA;AAAA;;cAYP,eAAA,SAAwB,WAAW;cAClC,OAAA,UAAiB,KAAA;AAAA;;cAOlB,aAAA,SAAsB,WAAW;cAChC,OAAA,UAAiB,KAAA;AAAA;;cAOlB,kBAAA,SAA2B,WAAW;cACrC,OAAA,UAAiB,KAAA;AAAA;;cAOlB,gBAAA,SAAyB,WAAW;cACnC,OAAA,UAAiB,KAAA;AAAA;;cAOlB,gBAAA,SAAyB,WAAW;cACnC,OAAA,UAAiB,KAAA;AAAA;AAzB/B;AAAA,cAgCa,kBAAA,SAA2B,WAAW;cACrC,OAAA,UAAiB,KAAA;AAAA;;cAOlB,oBAAA,SAA6B,WAAW;cACvC,OAAA,UAAiB,KAAA;AAAA;;cAOlB,gBAAA,SAAyB,WAAW;cACnC,OAAA,UAAiB,KAAA;AAAA;;cAOlB,cAAA,SAAuB,WAAW;cACjC,OAAA,UAAiB,KAAA;AAAA;;;;AAhDe;AAO9C;;cAqDa,uBAAA,SAAgC,cAAc;cAC7C,OAAA,UAAiB,KAAA;AAAA;;;;;AArDe;AAO9C;;cA2Da,cAAA,SAAuB,WAAW;EAAA,SAG3B,MAAA;EAAA,SACA,IAAA;cAFhB,OAAA,UACgB,MAAA,UACA,IAAA;AAAA;;;UC3HH,SAAA;EACf,EAAA,EAAI,UAAA;EACJ,EAAA,EAAI,WAAA;EACJ,EAAA,EAAI,QAAA;EACJ,KAAA,EAAO,SAAA;EACP,cAAA;AAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,11 @@
1
+ import { generateSessionId, generateToken, hashToken, signSession, verifySession } from "./auth/index.js";
2
+ import { purgeCache } from "./cache/index.js";
3
+ import { a as CadmusCmsError, c as CadmusError, d as CadmusSessionError, f as CadmusStorageError, i as CadmusCacheError, l as CadmusQueueError, n as CadmusApiError, o as CadmusDbError, r as CadmusAuthError, s as CadmusEmailError, t as CadmusAccessDeniedError, u as CadmusRateLimitError } from "./errors-mZIqZJO4.js";
4
+ import { enqueue, processBatch } from "./queues/index.js";
5
+ import { can, cmsConfigToSchema, collectionSearchTableName, collectionSearchTableSQL, collectionToTable, collectionVersionsTable, createLocalApi, createVersionedLocalApi, createWebhookHook, defineCmsConfig, defineCollection, deliverWebhookMessage, extractSearchText, flattenDoc, flattenFields, generateSchemaSource, getCollectionsMeta, getRegisteredApi, nestDoc, relationshipJoinTables } from "./cms/index.js";
6
+ import { db } from "./db/index.js";
7
+ import { sendEmail } from "./email/index.js";
8
+ import { checkRateLimit } from "./rate-limit/index.js";
9
+ import { createSession, deleteSession, getSession } from "./session/index.js";
10
+ import { IMAGE_MIME_WHITELIST, MAX_IMAGE_UPLOAD_BYTES, validateImageFile } from "./storage/index.js";
11
+ export { CadmusAccessDeniedError, CadmusApiError, CadmusAuthError, CadmusCacheError, CadmusCmsError, CadmusDbError, CadmusEmailError, CadmusError, CadmusQueueError, CadmusRateLimitError, CadmusSessionError, CadmusStorageError, IMAGE_MIME_WHITELIST, MAX_IMAGE_UPLOAD_BYTES, can, checkRateLimit, cmsConfigToSchema, collectionSearchTableName, collectionSearchTableSQL, collectionToTable, collectionVersionsTable, createLocalApi, createSession, createVersionedLocalApi, createWebhookHook, db, defineCmsConfig, defineCollection, deleteSession, deliverWebhookMessage, enqueue, extractSearchText, flattenDoc, flattenFields, generateSchemaSource, generateSessionId, generateToken, getCollectionsMeta, getRegisteredApi, getSession, hashToken, nestDoc, processBatch, purgeCache, relationshipJoinTables, sendEmail, signSession, validateImageFile, verifySession };
@@ -0,0 +1,31 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_errors = require("../errors-CW6Lz0AQ.cjs");
3
+ //#region src/queues/index.ts
4
+ /** Enqueues `message` onto `queue`. Throws CadmusQueueError on failure. */
5
+ async function enqueue(queue, message) {
6
+ try {
7
+ await queue.send(message);
8
+ } catch (cause) {
9
+ throw new require_errors.CadmusQueueError("Failed to enqueue message", cause);
10
+ }
11
+ }
12
+ /**
13
+ * Drains a `MessageBatch`, running `handler` once per message. Each
14
+ * message is acked or retried independently — one failing message
15
+ * doesn't block the rest of the batch from acking. Never throws itself;
16
+ * a handler's own errors are caught and turned into a `retry()` so a
17
+ * Worker's `queue()` export can call this directly as its entire body.
18
+ */
19
+ async function processBatch(batch, handler) {
20
+ for (const message of batch.messages) try {
21
+ await handler(message.body, { attempts: message.attempts });
22
+ message.ack();
23
+ } catch {
24
+ message.retry();
25
+ }
26
+ }
27
+ //#endregion
28
+ exports.enqueue = enqueue;
29
+ exports.processBatch = processBatch;
30
+
31
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["CadmusQueueError"],"sources":["../../src/queues/index.ts"],"sourcesContent":["// Copyright (c) 2026 BowenLabs. All rights reserved.\n// Cadmus is MIT licensed. See LICENSE in the repo root.\n//\n// @thebes/cadmus/queues\n//\n// Thin wrapper over Cloudflare Queues' `Queue`/`MessageBatch` bindings.\n// Producer side is a single `enqueue()` call; consumer side is a batch\n// runner that acks each message on success and calls `retry()` on\n// failure. Cloudflare Queues — not this module — owns the actual\n// redelivery/backoff schedule and DLQ routing: once a message exceeds the\n// queue's configured `max_retries`, CF routes it to that queue's\n// `dead_letter_queue` automatically (set in wrangler.jsonc, not here).\n\nimport { CadmusQueueError } from \"../errors.js\";\n\n/** Enqueues `message` onto `queue`. Throws CadmusQueueError on failure. */\nexport async function enqueue<T>(queue: Queue<T>, message: T): Promise<void> {\n try {\n await queue.send(message);\n } catch (cause) {\n throw new CadmusQueueError(\"Failed to enqueue message\", cause);\n }\n}\n\n/**\n * Called once per message in a batch. Throwing marks that message for\n * retry; returning normally acks it. `attempts` is the 1-indexed delivery\n * count CF Queues reports on the message itself.\n */\nexport type QueueMessageHandler<T> = (\n message: T,\n context: { attempts: number },\n) => void | Promise<void>;\n\n/**\n * Drains a `MessageBatch`, running `handler` once per message. Each\n * message is acked or retried independently — one failing message\n * doesn't block the rest of the batch from acking. Never throws itself;\n * a handler's own errors are caught and turned into a `retry()` so a\n * Worker's `queue()` export can call this directly as its entire body.\n */\nexport async function processBatch<T>(\n batch: MessageBatch<T>,\n handler: QueueMessageHandler<T>,\n): Promise<void> {\n for (const message of batch.messages) {\n try {\n await handler(message.body, { attempts: message.attempts });\n message.ack();\n } catch {\n message.retry();\n }\n }\n}\n"],"mappings":";;;;AAgBA,eAAsB,QAAW,OAAiB,SAA2B;CAC3E,IAAI;EACF,MAAM,MAAM,KAAK,OAAO;CAC1B,SAAS,OAAO;EACd,MAAM,IAAIA,eAAAA,iBAAiB,6BAA6B,KAAK;CAC/D;AACF;;;;;;;;AAmBA,eAAsB,aACpB,OACA,SACe;CACf,KAAK,MAAM,WAAW,MAAM,UAC1B,IAAI;EACF,MAAM,QAAQ,QAAQ,MAAM,EAAE,UAAU,QAAQ,SAAS,CAAC;EAC1D,QAAQ,IAAI;CACd,QAAQ;EACN,QAAQ,MAAM;CAChB;AAEJ"}
@@ -0,0 +1,22 @@
1
+ //#region src/queues/index.d.ts
2
+ /** Enqueues `message` onto `queue`. Throws CadmusQueueError on failure. */
3
+ declare function enqueue<T>(queue: Queue<T>, message: T): Promise<void>;
4
+ /**
5
+ * Called once per message in a batch. Throwing marks that message for
6
+ * retry; returning normally acks it. `attempts` is the 1-indexed delivery
7
+ * count CF Queues reports on the message itself.
8
+ */
9
+ type QueueMessageHandler<T> = (message: T, context: {
10
+ attempts: number;
11
+ }) => void | Promise<void>;
12
+ /**
13
+ * Drains a `MessageBatch`, running `handler` once per message. Each
14
+ * message is acked or retried independently — one failing message
15
+ * doesn't block the rest of the batch from acking. Never throws itself;
16
+ * a handler's own errors are caught and turned into a `retry()` so a
17
+ * Worker's `queue()` export can call this directly as its entire body.
18
+ */
19
+ declare function processBatch<T>(batch: MessageBatch<T>, handler: QueueMessageHandler<T>): Promise<void>;
20
+ //#endregion
21
+ export { QueueMessageHandler, enqueue, processBatch };
22
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../../src/queues/index.ts"],"mappings":";;iBAgBsB,OAAA,IAAW,KAAA,EAAO,KAAA,CAAM,CAAA,GAAI,OAAA,EAAS,CAAA,GAAI,OAAA;;;;;;KAanD,mBAAA,OACV,OAAA,EAAS,CAAA,EACT,OAAA;EAAW,QAAA;AAAA,aACD,OAAO;;;;;;;;iBASG,YAAA,IACpB,KAAA,EAAO,YAAA,CAAa,CAAA,GACpB,OAAA,EAAS,mBAAA,CAAoB,CAAA,IAC5B,OAAA"}
@@ -0,0 +1,22 @@
1
+ //#region src/queues/index.d.ts
2
+ /** Enqueues `message` onto `queue`. Throws CadmusQueueError on failure. */
3
+ declare function enqueue<T>(queue: Queue<T>, message: T): Promise<void>;
4
+ /**
5
+ * Called once per message in a batch. Throwing marks that message for
6
+ * retry; returning normally acks it. `attempts` is the 1-indexed delivery
7
+ * count CF Queues reports on the message itself.
8
+ */
9
+ type QueueMessageHandler<T> = (message: T, context: {
10
+ attempts: number;
11
+ }) => void | Promise<void>;
12
+ /**
13
+ * Drains a `MessageBatch`, running `handler` once per message. Each
14
+ * message is acked or retried independently — one failing message
15
+ * doesn't block the rest of the batch from acking. Never throws itself;
16
+ * a handler's own errors are caught and turned into a `retry()` so a
17
+ * Worker's `queue()` export can call this directly as its entire body.
18
+ */
19
+ declare function processBatch<T>(batch: MessageBatch<T>, handler: QueueMessageHandler<T>): Promise<void>;
20
+ //#endregion
21
+ export { QueueMessageHandler, enqueue, processBatch };
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/queues/index.ts"],"mappings":";;iBAgBsB,OAAA,IAAW,KAAA,EAAO,KAAA,CAAM,CAAA,GAAI,OAAA,EAAS,CAAA,GAAI,OAAA;;;;;;KAanD,mBAAA,OACV,OAAA,EAAS,CAAA,EACT,OAAA;EAAW,QAAA;AAAA,aACD,OAAO;;;;;;;;iBASG,YAAA,IACpB,KAAA,EAAO,YAAA,CAAa,CAAA,GACpB,OAAA,EAAS,mBAAA,CAAoB,CAAA,IAC5B,OAAA"}
@@ -0,0 +1,29 @@
1
+ import { l as CadmusQueueError } from "../errors-mZIqZJO4.js";
2
+ //#region src/queues/index.ts
3
+ /** Enqueues `message` onto `queue`. Throws CadmusQueueError on failure. */
4
+ async function enqueue(queue, message) {
5
+ try {
6
+ await queue.send(message);
7
+ } catch (cause) {
8
+ throw new CadmusQueueError("Failed to enqueue message", cause);
9
+ }
10
+ }
11
+ /**
12
+ * Drains a `MessageBatch`, running `handler` once per message. Each
13
+ * message is acked or retried independently — one failing message
14
+ * doesn't block the rest of the batch from acking. Never throws itself;
15
+ * a handler's own errors are caught and turned into a `retry()` so a
16
+ * Worker's `queue()` export can call this directly as its entire body.
17
+ */
18
+ async function processBatch(batch, handler) {
19
+ for (const message of batch.messages) try {
20
+ await handler(message.body, { attempts: message.attempts });
21
+ message.ack();
22
+ } catch {
23
+ message.retry();
24
+ }
25
+ }
26
+ //#endregion
27
+ export { enqueue, processBatch };
28
+
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/queues/index.ts"],"sourcesContent":["// Copyright (c) 2026 BowenLabs. All rights reserved.\n// Cadmus is MIT licensed. See LICENSE in the repo root.\n//\n// @thebes/cadmus/queues\n//\n// Thin wrapper over Cloudflare Queues' `Queue`/`MessageBatch` bindings.\n// Producer side is a single `enqueue()` call; consumer side is a batch\n// runner that acks each message on success and calls `retry()` on\n// failure. Cloudflare Queues — not this module — owns the actual\n// redelivery/backoff schedule and DLQ routing: once a message exceeds the\n// queue's configured `max_retries`, CF routes it to that queue's\n// `dead_letter_queue` automatically (set in wrangler.jsonc, not here).\n\nimport { CadmusQueueError } from \"../errors.js\";\n\n/** Enqueues `message` onto `queue`. Throws CadmusQueueError on failure. */\nexport async function enqueue<T>(queue: Queue<T>, message: T): Promise<void> {\n try {\n await queue.send(message);\n } catch (cause) {\n throw new CadmusQueueError(\"Failed to enqueue message\", cause);\n }\n}\n\n/**\n * Called once per message in a batch. Throwing marks that message for\n * retry; returning normally acks it. `attempts` is the 1-indexed delivery\n * count CF Queues reports on the message itself.\n */\nexport type QueueMessageHandler<T> = (\n message: T,\n context: { attempts: number },\n) => void | Promise<void>;\n\n/**\n * Drains a `MessageBatch`, running `handler` once per message. Each\n * message is acked or retried independently — one failing message\n * doesn't block the rest of the batch from acking. Never throws itself;\n * a handler's own errors are caught and turned into a `retry()` so a\n * Worker's `queue()` export can call this directly as its entire body.\n */\nexport async function processBatch<T>(\n batch: MessageBatch<T>,\n handler: QueueMessageHandler<T>,\n): Promise<void> {\n for (const message of batch.messages) {\n try {\n await handler(message.body, { attempts: message.attempts });\n message.ack();\n } catch {\n message.retry();\n }\n }\n}\n"],"mappings":";;;AAgBA,eAAsB,QAAW,OAAiB,SAA2B;CAC3E,IAAI;EACF,MAAM,MAAM,KAAK,OAAO;CAC1B,SAAS,OAAO;EACd,MAAM,IAAI,iBAAiB,6BAA6B,KAAK;CAC/D;AACF;;;;;;;;AAmBA,eAAsB,aACpB,OACA,SACe;CACf,KAAK,MAAM,WAAW,MAAM,UAC1B,IAAI;EACF,MAAM,QAAQ,QAAQ,MAAM,EAAE,UAAU,QAAQ,SAAS,CAAC;EAC1D,QAAQ,IAAI;CACd,QAAQ;EACN,QAAQ,MAAM;CAChB;AAEJ"}
@@ -0,0 +1,38 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_errors = require("../errors-CW6Lz0AQ.cjs");
3
+ //#region src/rate-limit/index.ts
4
+ /**
5
+ * Increments the counter for `key` within a fixed `windowSeconds` window,
6
+ * resetting once the window elapses. Returns whether this request is
7
+ * still within `limit`, and how many requests remain in the window.
8
+ */
9
+ async function checkRateLimit(kv, key, limit, windowSeconds) {
10
+ let record;
11
+ try {
12
+ record = await kv.get(key, "json");
13
+ } catch (cause) {
14
+ throw new require_errors.CadmusRateLimitError(`Failed to read rate limit counter "${key}"`, cause);
15
+ }
16
+ const now = Date.now();
17
+ const windowMs = windowSeconds * 1e3;
18
+ const next = !record || now >= record.resetAt ? {
19
+ count: 1,
20
+ resetAt: now + windowMs
21
+ } : {
22
+ count: record.count + 1,
23
+ resetAt: record.resetAt
24
+ };
25
+ try {
26
+ await kv.put(key, JSON.stringify(next), { expirationTtl: Math.max(1, Math.ceil((next.resetAt - now) / 1e3)) });
27
+ } catch (cause) {
28
+ throw new require_errors.CadmusRateLimitError(`Failed to write rate limit counter "${key}"`, cause);
29
+ }
30
+ return {
31
+ allowed: next.count <= limit,
32
+ remaining: Math.max(0, limit - next.count)
33
+ };
34
+ }
35
+ //#endregion
36
+ exports.checkRateLimit = checkRateLimit;
37
+
38
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["CadmusRateLimitError"],"sources":["../../src/rate-limit/index.ts"],"sourcesContent":["// Copyright (c) 2026 BowenLabs. All rights reserved.\n// Cadmus is MIT licensed. See LICENSE in the repo root.\n//\n// @thebes/cadmus/rate-limit\n//\n// Fixed-window rate limiter over KV. Best-effort, not atomic — KV has no\n// transactions, so a tight race on the same key can let one or two extra\n// requests through. That's an acceptable tradeoff for the scale this is\n// built for (per-IP/per-email request throttling, not billing-grade\n// metering); a Durable Object would be the answer if exact counts ever\n// mattered.\n\nimport { CadmusRateLimitError } from \"../errors.js\";\n\ninterface RateLimitRecord {\n count: number;\n resetAt: number;\n}\n\nexport interface RateLimitResult {\n allowed: boolean;\n remaining: number;\n}\n\n/**\n * Increments the counter for `key` within a fixed `windowSeconds` window,\n * resetting once the window elapses. Returns whether this request is\n * still within `limit`, and how many requests remain in the window.\n */\nexport async function checkRateLimit(\n kv: KVNamespace,\n key: string,\n limit: number,\n windowSeconds: number,\n): Promise<RateLimitResult> {\n let record: RateLimitRecord | null;\n try {\n record = await kv.get<RateLimitRecord>(key, \"json\");\n } catch (cause) {\n throw new CadmusRateLimitError(\n `Failed to read rate limit counter \"${key}\"`,\n cause,\n );\n }\n\n const now = Date.now();\n const windowMs = windowSeconds * 1000;\n\n const next: RateLimitRecord =\n !record || now >= record.resetAt\n ? { count: 1, resetAt: now + windowMs }\n : { count: record.count + 1, resetAt: record.resetAt };\n\n try {\n await kv.put(key, JSON.stringify(next), {\n expirationTtl: Math.max(1, Math.ceil((next.resetAt - now) / 1000)),\n });\n } catch (cause) {\n throw new CadmusRateLimitError(\n `Failed to write rate limit counter \"${key}\"`,\n cause,\n );\n }\n\n return {\n allowed: next.count <= limit,\n remaining: Math.max(0, limit - next.count),\n };\n}\n"],"mappings":";;;;;;;;AA6BA,eAAsB,eACpB,IACA,KACA,OACA,eAC0B;CAC1B,IAAI;CACJ,IAAI;EACF,SAAS,MAAM,GAAG,IAAqB,KAAK,MAAM;CACpD,SAAS,OAAO;EACd,MAAM,IAAIA,eAAAA,qBACR,sCAAsC,IAAI,IAC1C,KACF;CACF;CAEA,MAAM,MAAM,KAAK,IAAI;CACrB,MAAM,WAAW,gBAAgB;CAEjC,MAAM,OACJ,CAAC,UAAU,OAAO,OAAO,UACrB;EAAE,OAAO;EAAG,SAAS,MAAM;CAAS,IACpC;EAAE,OAAO,OAAO,QAAQ;EAAG,SAAS,OAAO;CAAQ;CAEzD,IAAI;EACF,MAAM,GAAG,IAAI,KAAK,KAAK,UAAU,IAAI,GAAG,EACtC,eAAe,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,UAAU,OAAO,GAAI,CAAC,EACnE,CAAC;CACH,SAAS,OAAO;EACd,MAAM,IAAIA,eAAAA,qBACR,uCAAuC,IAAI,IAC3C,KACF;CACF;CAEA,OAAO;EACL,SAAS,KAAK,SAAS;EACvB,WAAW,KAAK,IAAI,GAAG,QAAQ,KAAK,KAAK;CAC3C;AACF"}
@@ -0,0 +1,14 @@
1
+ //#region src/rate-limit/index.d.ts
2
+ interface RateLimitResult {
3
+ allowed: boolean;
4
+ remaining: number;
5
+ }
6
+ /**
7
+ * Increments the counter for `key` within a fixed `windowSeconds` window,
8
+ * resetting once the window elapses. Returns whether this request is
9
+ * still within `limit`, and how many requests remain in the window.
10
+ */
11
+ declare function checkRateLimit(kv: KVNamespace, key: string, limit: number, windowSeconds: number): Promise<RateLimitResult>;
12
+ //#endregion
13
+ export { RateLimitResult, checkRateLimit };
14
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../../src/rate-limit/index.ts"],"mappings":";UAmBiB,eAAA;EACf,OAAA;EACA,SAAS;AAAA;;AAAA;AAQX;;;iBAAsB,cAAA,CACpB,EAAA,EAAI,WAAA,EACJ,GAAA,UACA,KAAA,UACA,aAAA,WACC,OAAA,CAAQ,eAAA"}
@@ -0,0 +1,14 @@
1
+ //#region src/rate-limit/index.d.ts
2
+ interface RateLimitResult {
3
+ allowed: boolean;
4
+ remaining: number;
5
+ }
6
+ /**
7
+ * Increments the counter for `key` within a fixed `windowSeconds` window,
8
+ * resetting once the window elapses. Returns whether this request is
9
+ * still within `limit`, and how many requests remain in the window.
10
+ */
11
+ declare function checkRateLimit(kv: KVNamespace, key: string, limit: number, windowSeconds: number): Promise<RateLimitResult>;
12
+ //#endregion
13
+ export { RateLimitResult, checkRateLimit };
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/rate-limit/index.ts"],"mappings":";UAmBiB,eAAA;EACf,OAAA;EACA,SAAS;AAAA;;AAAA;AAQX;;;iBAAsB,cAAA,CACpB,EAAA,EAAI,WAAA,EACJ,GAAA,UACA,KAAA,UACA,aAAA,WACC,OAAA,CAAQ,eAAA"}
@@ -0,0 +1,37 @@
1
+ import { u as CadmusRateLimitError } from "../errors-mZIqZJO4.js";
2
+ //#region src/rate-limit/index.ts
3
+ /**
4
+ * Increments the counter for `key` within a fixed `windowSeconds` window,
5
+ * resetting once the window elapses. Returns whether this request is
6
+ * still within `limit`, and how many requests remain in the window.
7
+ */
8
+ async function checkRateLimit(kv, key, limit, windowSeconds) {
9
+ let record;
10
+ try {
11
+ record = await kv.get(key, "json");
12
+ } catch (cause) {
13
+ throw new CadmusRateLimitError(`Failed to read rate limit counter "${key}"`, cause);
14
+ }
15
+ const now = Date.now();
16
+ const windowMs = windowSeconds * 1e3;
17
+ const next = !record || now >= record.resetAt ? {
18
+ count: 1,
19
+ resetAt: now + windowMs
20
+ } : {
21
+ count: record.count + 1,
22
+ resetAt: record.resetAt
23
+ };
24
+ try {
25
+ await kv.put(key, JSON.stringify(next), { expirationTtl: Math.max(1, Math.ceil((next.resetAt - now) / 1e3)) });
26
+ } catch (cause) {
27
+ throw new CadmusRateLimitError(`Failed to write rate limit counter "${key}"`, cause);
28
+ }
29
+ return {
30
+ allowed: next.count <= limit,
31
+ remaining: Math.max(0, limit - next.count)
32
+ };
33
+ }
34
+ //#endregion
35
+ export { checkRateLimit };
36
+
37
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/rate-limit/index.ts"],"sourcesContent":["// Copyright (c) 2026 BowenLabs. All rights reserved.\n// Cadmus is MIT licensed. See LICENSE in the repo root.\n//\n// @thebes/cadmus/rate-limit\n//\n// Fixed-window rate limiter over KV. Best-effort, not atomic — KV has no\n// transactions, so a tight race on the same key can let one or two extra\n// requests through. That's an acceptable tradeoff for the scale this is\n// built for (per-IP/per-email request throttling, not billing-grade\n// metering); a Durable Object would be the answer if exact counts ever\n// mattered.\n\nimport { CadmusRateLimitError } from \"../errors.js\";\n\ninterface RateLimitRecord {\n count: number;\n resetAt: number;\n}\n\nexport interface RateLimitResult {\n allowed: boolean;\n remaining: number;\n}\n\n/**\n * Increments the counter for `key` within a fixed `windowSeconds` window,\n * resetting once the window elapses. Returns whether this request is\n * still within `limit`, and how many requests remain in the window.\n */\nexport async function checkRateLimit(\n kv: KVNamespace,\n key: string,\n limit: number,\n windowSeconds: number,\n): Promise<RateLimitResult> {\n let record: RateLimitRecord | null;\n try {\n record = await kv.get<RateLimitRecord>(key, \"json\");\n } catch (cause) {\n throw new CadmusRateLimitError(\n `Failed to read rate limit counter \"${key}\"`,\n cause,\n );\n }\n\n const now = Date.now();\n const windowMs = windowSeconds * 1000;\n\n const next: RateLimitRecord =\n !record || now >= record.resetAt\n ? { count: 1, resetAt: now + windowMs }\n : { count: record.count + 1, resetAt: record.resetAt };\n\n try {\n await kv.put(key, JSON.stringify(next), {\n expirationTtl: Math.max(1, Math.ceil((next.resetAt - now) / 1000)),\n });\n } catch (cause) {\n throw new CadmusRateLimitError(\n `Failed to write rate limit counter \"${key}\"`,\n cause,\n );\n }\n\n return {\n allowed: next.count <= limit,\n remaining: Math.max(0, limit - next.count),\n };\n}\n"],"mappings":";;;;;;;AA6BA,eAAsB,eACpB,IACA,KACA,OACA,eAC0B;CAC1B,IAAI;CACJ,IAAI;EACF,SAAS,MAAM,GAAG,IAAqB,KAAK,MAAM;CACpD,SAAS,OAAO;EACd,MAAM,IAAI,qBACR,sCAAsC,IAAI,IAC1C,KACF;CACF;CAEA,MAAM,MAAM,KAAK,IAAI;CACrB,MAAM,WAAW,gBAAgB;CAEjC,MAAM,OACJ,CAAC,UAAU,OAAO,OAAO,UACrB;EAAE,OAAO;EAAG,SAAS,MAAM;CAAS,IACpC;EAAE,OAAO,OAAO,QAAQ;EAAG,SAAS,OAAO;CAAQ;CAEzD,IAAI;EACF,MAAM,GAAG,IAAI,KAAK,KAAK,UAAU,IAAI,GAAG,EACtC,eAAe,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,UAAU,OAAO,GAAI,CAAC,EACnE,CAAC;CACH,SAAS,OAAO;EACd,MAAM,IAAI,qBACR,uCAAuC,IAAI,IAC3C,KACF;CACF;CAEA,OAAO;EACL,SAAS,KAAK,SAAS;EACvB,WAAW,KAAK,IAAI,GAAG,QAAQ,KAAK,KAAK;CAC3C;AACF"}
@@ -0,0 +1,48 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_errors = require("../errors-CW6Lz0AQ.cjs");
3
+ //#region src/session/index.ts
4
+ const RETRY_ATTEMPTS = 2;
5
+ const RETRY_DELAY_MS = 100;
6
+ function sleep(ms) {
7
+ return new Promise((resolve) => setTimeout(resolve, ms));
8
+ }
9
+ /** Stores `value` under `key` in KV, JSON-serialized, with a TTL in seconds. */
10
+ async function createSession(kv, key, value, ttlSeconds) {
11
+ try {
12
+ await kv.put(key, JSON.stringify(value), { expirationTtl: ttlSeconds });
13
+ } catch (cause) {
14
+ throw new require_errors.CadmusSessionError(`Failed to create session "${key}"`, cause);
15
+ }
16
+ }
17
+ /**
18
+ * Reads and JSON-parses the session at `key`. Retries on a miss (KV's
19
+ * eventual consistency can otherwise produce a false negative right after
20
+ * a write) before returning null.
21
+ */
22
+ async function getSession(kv, key) {
23
+ for (let attempt = 0; attempt <= RETRY_ATTEMPTS; attempt++) {
24
+ let raw;
25
+ try {
26
+ raw = await kv.get(key);
27
+ } catch (cause) {
28
+ throw new require_errors.CadmusSessionError(`Failed to read session "${key}"`, cause);
29
+ }
30
+ if (raw !== null) return JSON.parse(raw);
31
+ if (attempt < RETRY_ATTEMPTS) await sleep(RETRY_DELAY_MS);
32
+ }
33
+ return null;
34
+ }
35
+ /** Deletes the session at `key`. */
36
+ async function deleteSession(kv, key) {
37
+ try {
38
+ await kv.delete(key);
39
+ } catch (cause) {
40
+ throw new require_errors.CadmusSessionError(`Failed to delete session "${key}"`, cause);
41
+ }
42
+ }
43
+ //#endregion
44
+ exports.createSession = createSession;
45
+ exports.deleteSession = deleteSession;
46
+ exports.getSession = getSession;
47
+
48
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["CadmusSessionError"],"sources":["../../src/session/index.ts"],"sourcesContent":["// Copyright (c) 2026 BowenLabs. All rights reserved.\n// Cadmus is MIT licensed. See LICENSE in the repo root.\n//\n// @thebes/cadmus/session\n//\n// Thin JSON-over-KV session store. Takes a raw KVNamespace and a caller-\n// chosen key — no \"session:\" prefix or namespace convention baked in,\n// since that's an app-level choice, not a framework one. KV is eventually\n// consistent, so getSession() retries on a miss (a write immediately\n// followed by a read on a different edge location can otherwise see a\n// false negative) before concluding the session genuinely doesn't exist.\n\nimport { CadmusSessionError } from \"../errors.js\";\n\nconst RETRY_ATTEMPTS = 2;\nconst RETRY_DELAY_MS = 100;\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/** Stores `value` under `key` in KV, JSON-serialized, with a TTL in seconds. */\nexport async function createSession<T>(\n kv: KVNamespace,\n key: string,\n value: T,\n ttlSeconds: number,\n): Promise<void> {\n try {\n await kv.put(key, JSON.stringify(value), { expirationTtl: ttlSeconds });\n } catch (cause) {\n throw new CadmusSessionError(`Failed to create session \"${key}\"`, cause);\n }\n}\n\n/**\n * Reads and JSON-parses the session at `key`. Retries on a miss (KV's\n * eventual consistency can otherwise produce a false negative right after\n * a write) before returning null.\n */\nexport async function getSession<T>(\n kv: KVNamespace,\n key: string,\n): Promise<T | null> {\n for (let attempt = 0; attempt <= RETRY_ATTEMPTS; attempt++) {\n let raw: string | null;\n try {\n raw = await kv.get(key);\n } catch (cause) {\n throw new CadmusSessionError(`Failed to read session \"${key}\"`, cause);\n }\n if (raw !== null) return JSON.parse(raw) as T;\n if (attempt < RETRY_ATTEMPTS) await sleep(RETRY_DELAY_MS);\n }\n return null;\n}\n\n/** Deletes the session at `key`. */\nexport async function deleteSession(\n kv: KVNamespace,\n key: string,\n): Promise<void> {\n try {\n await kv.delete(key);\n } catch (cause) {\n throw new CadmusSessionError(`Failed to delete session \"${key}\"`, cause);\n }\n}\n"],"mappings":";;;AAcA,MAAM,iBAAiB;AACvB,MAAM,iBAAiB;AAEvB,SAAS,MAAM,IAA2B;CACxC,OAAO,IAAI,SAAS,YAAY,WAAW,SAAS,EAAE,CAAC;AACzD;;AAGA,eAAsB,cACpB,IACA,KACA,OACA,YACe;CACf,IAAI;EACF,MAAM,GAAG,IAAI,KAAK,KAAK,UAAU,KAAK,GAAG,EAAE,eAAe,WAAW,CAAC;CACxE,SAAS,OAAO;EACd,MAAM,IAAIA,eAAAA,mBAAmB,6BAA6B,IAAI,IAAI,KAAK;CACzE;AACF;;;;;;AAOA,eAAsB,WACpB,IACA,KACmB;CACnB,KAAK,IAAI,UAAU,GAAG,WAAW,gBAAgB,WAAW;EAC1D,IAAI;EACJ,IAAI;GACF,MAAM,MAAM,GAAG,IAAI,GAAG;EACxB,SAAS,OAAO;GACd,MAAM,IAAIA,eAAAA,mBAAmB,2BAA2B,IAAI,IAAI,KAAK;EACvE;EACA,IAAI,QAAQ,MAAM,OAAO,KAAK,MAAM,GAAG;EACvC,IAAI,UAAU,gBAAgB,MAAM,MAAM,cAAc;CAC1D;CACA,OAAO;AACT;;AAGA,eAAsB,cACpB,IACA,KACe;CACf,IAAI;EACF,MAAM,GAAG,OAAO,GAAG;CACrB,SAAS,OAAO;EACd,MAAM,IAAIA,eAAAA,mBAAmB,6BAA6B,IAAI,IAAI,KAAK;CACzE;AACF"}