@micacms/runtime 0.4.1 → 0.5.0-rc.2

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 (112) hide show
  1. package/README.md +2 -2
  2. package/dist/app.d.ts +8 -37
  3. package/dist/app.d.ts.map +1 -1
  4. package/dist/app.js +7 -42
  5. package/dist/app.js.map +1 -1
  6. package/dist/config.d.ts +12 -82
  7. package/dist/config.d.ts.map +1 -1
  8. package/dist/config.js +14 -82
  9. package/dist/config.js.map +1 -1
  10. package/dist/context.d.ts +37 -66
  11. package/dist/context.d.ts.map +1 -1
  12. package/dist/context.js +24 -75
  13. package/dist/context.js.map +1 -1
  14. package/dist/http.d.ts +8 -16
  15. package/dist/http.d.ts.map +1 -1
  16. package/dist/http.js +6 -13
  17. package/dist/http.js.map +1 -1
  18. package/dist/index.d.ts +13 -14
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +12 -14
  21. package/dist/index.js.map +1 -1
  22. package/dist/lib/errors.js.map +1 -1
  23. package/dist/lib/file-type.js.map +1 -1
  24. package/dist/lib/id.js.map +1 -1
  25. package/dist/lib/logger.js.map +1 -1
  26. package/dist/lib/ports.js.map +1 -1
  27. package/dist/lib/rate-limit.js.map +1 -1
  28. package/dist/lib/schema-stats.js.map +1 -1
  29. package/dist/lib/version.js.map +1 -1
  30. package/dist/middleware/index.js.map +1 -1
  31. package/dist/routes/admin-content.d.ts +4 -17
  32. package/dist/routes/admin-content.d.ts.map +1 -1
  33. package/dist/routes/admin-content.js +11 -51
  34. package/dist/routes/admin-content.js.map +1 -1
  35. package/dist/routes/admin-media.d.ts +3 -14
  36. package/dist/routes/admin-media.d.ts.map +1 -1
  37. package/dist/routes/admin-media.js +7 -29
  38. package/dist/routes/admin-media.js.map +1 -1
  39. package/dist/routes/admin-spa.js.map +1 -1
  40. package/dist/routes/admin-staging.d.ts +4 -9
  41. package/dist/routes/admin-staging.d.ts.map +1 -1
  42. package/dist/routes/admin-staging.js +31 -18
  43. package/dist/routes/admin-staging.js.map +1 -1
  44. package/dist/routes/admin-system.d.ts +2 -8
  45. package/dist/routes/admin-system.d.ts.map +1 -1
  46. package/dist/routes/admin-system.js +9 -44
  47. package/dist/routes/admin-system.js.map +1 -1
  48. package/dist/routes/health.d.ts +3 -10
  49. package/dist/routes/health.d.ts.map +1 -1
  50. package/dist/routes/health.js +9 -26
  51. package/dist/routes/health.js.map +1 -1
  52. package/dist/schema.d.ts +10 -38
  53. package/dist/schema.d.ts.map +1 -1
  54. package/dist/schema.js +14 -65
  55. package/dist/schema.js.map +1 -1
  56. package/dist/server.d.ts +2 -10
  57. package/dist/server.d.ts.map +1 -1
  58. package/dist/server.js +3 -9
  59. package/dist/server.js.map +1 -1
  60. package/dist/services/changes.d.ts +150 -0
  61. package/dist/services/changes.d.ts.map +1 -0
  62. package/dist/services/changes.js +339 -0
  63. package/dist/services/changes.js.map +1 -0
  64. package/dist/services/content-store.d.ts +61 -0
  65. package/dist/services/content-store.d.ts.map +1 -0
  66. package/dist/services/content-store.js +330 -0
  67. package/dist/services/content-store.js.map +1 -0
  68. package/dist/services/media.d.ts +9 -29
  69. package/dist/services/media.d.ts.map +1 -1
  70. package/dist/services/media.js +17 -57
  71. package/dist/services/media.js.map +1 -1
  72. package/dist/services/staging.d.ts +35 -167
  73. package/dist/services/staging.d.ts.map +1 -1
  74. package/dist/services/staging.js +195 -458
  75. package/dist/services/staging.js.map +1 -1
  76. package/dist/workspace/developer.d.ts +14 -0
  77. package/dist/workspace/developer.d.ts.map +1 -0
  78. package/dist/workspace/developer.js +31 -0
  79. package/dist/workspace/developer.js.map +1 -0
  80. package/dist/workspace/files.d.ts +70 -0
  81. package/dist/workspace/files.d.ts.map +1 -0
  82. package/dist/workspace/files.js +176 -0
  83. package/dist/workspace/files.js.map +1 -0
  84. package/dist/workspace/git.d.ts +45 -0
  85. package/dist/workspace/git.d.ts.map +1 -0
  86. package/dist/workspace/git.js +68 -0
  87. package/dist/workspace/git.js.map +1 -0
  88. package/dist/workspace/locks.d.ts +33 -0
  89. package/dist/workspace/locks.d.ts.map +1 -0
  90. package/dist/workspace/locks.js +76 -0
  91. package/dist/workspace/locks.js.map +1 -0
  92. package/dist/workspace/policy.d.ts +92 -0
  93. package/dist/workspace/policy.d.ts.map +1 -0
  94. package/dist/workspace/policy.js +7 -0
  95. package/dist/workspace/policy.js.map +1 -0
  96. package/dist/workspace/tree.d.ts +73 -0
  97. package/dist/workspace/tree.d.ts.map +1 -0
  98. package/dist/workspace/tree.js +229 -0
  99. package/dist/workspace/tree.js.map +1 -0
  100. package/package.json +2 -3
  101. package/dist/db/driver.d.ts +0 -35
  102. package/dist/db/driver.d.ts.map +0 -1
  103. package/dist/db/driver.js +0 -95
  104. package/dist/db/driver.js.map +0 -1
  105. package/dist/lib/git.d.ts +0 -29
  106. package/dist/lib/git.d.ts.map +0 -1
  107. package/dist/lib/git.js +0 -62
  108. package/dist/lib/git.js.map +0 -1
  109. package/dist/services/staging-local.d.ts +0 -58
  110. package/dist/services/staging-local.d.ts.map +0 -1
  111. package/dist/services/staging-local.js +0 -391
  112. package/dist/services/staging-local.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"id.js","sourceRoot":"","sources":["../../src/lib/id.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,QAAQ,GAAG,kCAAkC,CAAC,CAAC,mBAAmB;AACxE,MAAM,UAAU,GAAG,EAAE,CAAC;AACtB,MAAM,YAAY,GAAG,EAAE,CAAC;AAExB,IAAI,QAAQ,GAAG,CAAC,CAAC;AACjB,IAAI,UAAU,GAAa,EAAE,CAAC;AAE9B,SAAS,UAAU,CAAC,IAAY;IAC9B,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,UAAU,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,GAAG,GAAG,QAAQ,CAAC,IAAI,GAAG,EAAE,CAAC,GAAG,GAAG,CAAC;QAChC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,WAAW;IAClB,MAAM,KAAK,GAAG,WAAW,CAAC,YAAY,CAAC,CAAC;IACxC,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;AAChD,CAAC;AAED,yFAAyF;AACzF,SAAS,UAAU,CAAC,KAAe;IACjC,MAAM,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;IACxB,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,IAAI,IAAI,CAAC,CAAC,CAAE,GAAG,EAAE,EAAE,CAAC;YAClB,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAE,GAAG,CAAC,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACd,CAAC;IACD,OAAO,WAAW,EAAE,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;IACnC,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;QACrB,UAAU,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;IACtC,CAAC;SAAM,CAAC;QACN,QAAQ,GAAG,GAAG,CAAC;QACf,UAAU,GAAG,WAAW,EAAE,CAAC;IAC7B,CAAC;IACD,OAAO,UAAU,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,KAAa;IAClC,OAAO,KAAK,CAAC,MAAM,KAAK,EAAE,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;AACpF,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,WAAW,CAAC,KAAK,GAAG,EAAE;IACpC,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AAClD,CAAC"}
1
+ {"version":3,"file":"id.js","sourceRoot":"","sources":["../../src/lib/id.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,QAAQ,GAAG,kCAAkC,CAAC,CAAC,mBAAmB;AACxE,MAAM,UAAU,GAAG,EAAE,CAAC;AACtB,MAAM,YAAY,GAAG,EAAE,CAAC;AAExB,IAAI,QAAQ,GAAG,CAAC,CAAC;AACjB,IAAI,UAAU,GAAa,EAAE,CAAC;AAE9B,SAAS,UAAU,CAAC,IAAY;IAC9B,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,UAAU,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,GAAG,GAAG,QAAQ,CAAC,IAAI,GAAG,EAAE,CAAC,GAAG,GAAG,CAAC;QAChC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,WAAW;IAClB,MAAM,KAAK,GAAG,WAAW,CAAC,YAAY,CAAC,CAAC;IACxC,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;AAChD,CAAC;AAED,yFAAyF;AACzF,SAAS,UAAU,CAAC,KAAe;IACjC,MAAM,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;IACxB,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,IAAI,IAAI,CAAC,CAAC,CAAE,GAAG,EAAE,EAAE,CAAC;YAClB,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAE,GAAG,CAAC,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACd,CAAC;IACD,OAAO,WAAW,EAAE,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;IACnC,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;QACrB,UAAU,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;IACtC,CAAC;SAAM,CAAC;QACN,QAAQ,GAAG,GAAG,CAAC;QACf,UAAU,GAAG,WAAW,EAAE,CAAC;IAC7B,CAAC;IACD,OAAO,UAAU,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,KAAa;IAClC,OAAO,KAAK,CAAC,MAAM,KAAK,EAAE,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;AACpF,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,WAAW,CAAC,KAAK,GAAG,EAAE;IACpC,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AAClD,CAAC","sourcesContent":["/**\n * ULID generation.\n *\n * Lexicographically sortable, so `ORDER BY id` matches creation order and\n * pagination stays stable without a secondary sort. This is an identifier\n * encoding, not a cryptographic construction — the randomness comes from\n * `crypto.randomBytes`.\n */\n\nimport { randomBytes } from \"node:crypto\";\n\nconst ALPHABET = \"0123456789ABCDEFGHJKMNPQRSTVWXYZ\"; // Crockford base32\nconst TIME_CHARS = 10;\nconst RANDOM_CHARS = 16;\n\nlet lastTime = 0;\nlet lastRandom: number[] = [];\n\nfunction encodeTime(time: number): string {\n let out = \"\";\n for (let i = TIME_CHARS - 1; i >= 0; i--) {\n out = ALPHABET[time % 32] + out;\n time = Math.floor(time / 32);\n }\n return out;\n}\n\nfunction randomChars(): number[] {\n const bytes = randomBytes(RANDOM_CHARS);\n return Array.from(bytes, (byte) => byte % 32);\n}\n\n/** Increments the random component so ids created in the same millisecond still sort. */\nfunction bumpRandom(chars: number[]): number[] {\n const next = [...chars];\n for (let i = next.length - 1; i >= 0; i--) {\n if (next[i]! < 31) {\n next[i] = next[i]! + 1;\n return next;\n }\n next[i] = 0;\n }\n return randomChars();\n}\n\nexport function ulid(now = Date.now()): string {\n if (now === lastTime) {\n lastRandom = bumpRandom(lastRandom);\n } else {\n lastTime = now;\n lastRandom = randomChars();\n }\n return encodeTime(now) + lastRandom.map((index) => ALPHABET[index]).join(\"\");\n}\n\nexport function isUlid(value: string): boolean {\n return value.length === 26 && [...value].every((char) => ALPHABET.includes(char));\n}\n\n/** URL-safe random token for sessions and one-time links. */\nexport function randomToken(bytes = 32): string {\n return randomBytes(bytes).toString(\"base64url\");\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Structured logging.\n *\n * JSON lines in production so a log shipper can parse them; a compact\n * human-readable form in development.\n */\n\nexport type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\" | \"silent\";\n\nconst ORDER: Record<LogLevel, number> = {\n debug: 10,\n info: 20,\n warn: 30,\n error: 40,\n silent: 100,\n};\n\nexport interface Logger {\n debug(message: string, fields?: Record<string, unknown>): void;\n info(message: string, fields?: Record<string, unknown>): void;\n warn(message: string, fields?: Record<string, unknown>): void;\n error(message: string, fields?: Record<string, unknown>): void;\n child(bindings: Record<string, unknown>): Logger;\n}\n\nconst COLORS: Record<Exclude<LogLevel, \"silent\">, string> = {\n debug: \"\u001b[90m\",\n info: \"\u001b[36m\",\n warn: \"\u001b[33m\",\n error: \"\u001b[31m\",\n};\n\nexport function createLogger(options: {\n level: LogLevel;\n pretty: boolean;\n bindings?: Record<string, unknown>;\n}): Logger {\n const threshold = ORDER[options.level];\n const bindings = options.bindings ?? {};\n\n const write = (level: Exclude<LogLevel, \"silent\">, message: string, fields?: Record<string, unknown>) => {\n if (ORDER[level] < threshold) return;\n\n const payload = { ...bindings, ...fields };\n const stream = level === \"error\" || level === \"warn\" ? process.stderr : process.stdout;\n\n if (options.pretty) {\n const extra = Object.keys(payload).length > 0 ? ` ${formatFields(payload)}` : \"\";\n stream.write(`${COLORS[level]}${level.padEnd(5)}\u001b[0m ${message}${extra}\\n`);\n return;\n }\n\n stream.write(\n `${JSON.stringify({\n time: new Date().toISOString(),\n level,\n message,\n ...payload,\n })}\\n`,\n );\n };\n\n return {\n debug: (message, fields) => write(\"debug\", message, fields),\n info: (message, fields) => write(\"info\", message, fields),\n warn: (message, fields) => write(\"warn\", message, fields),\n error: (message, fields) => write(\"error\", message, fields),\n child: (extra) =>\n createLogger({ ...options, bindings: { ...bindings, ...extra } }),\n };\n}\n\nfunction formatFields(fields: Record<string, unknown>): string {\n return Object.entries(fields)\n .map(([key, value]) => `\u001b[90m${key}=\u001b[0m${format(value)}`)\n .join(\" \");\n}\n\nfunction format(value: unknown): string {\n if (typeof value === \"string\") return value;\n if (value instanceof Error) return value.stack ?? value.message;\n try {\n return JSON.stringify(value) ?? String(value);\n } catch {\n return String(value);\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ports.js","sourceRoot":"","sources":["../../src/lib/ports.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAC;AAEjC,wDAAwD;AACxD,MAAM,CAAC,MAAM,gBAAgB,GAAG,oBAAoB,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"ports.js","sourceRoot":"","sources":["../../src/lib/ports.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAC;AAEjC,wDAAwD;AACxD,MAAM,CAAC,MAAM,gBAAgB,GAAG,oBAAoB,YAAY,EAAE,CAAC","sourcesContent":["/**\n * The port Mica listens on when nobody says otherwise.\n *\n * 6422 is `MICA` on a telephone keypad, which is the only reason anybody will\n * remember it. What matters more is what it is not: 3000, 4000, 4173, 4200,\n * 4321, 5000, 5173, 8000, 8080 and 1313 all belong to something a developer is\n * likely to be running beside Mica — Astro's dev server most of all — and IANA\n * has 6420 and 6421 assigned but not 6422, so nothing on the machine is\n * expected to want it.\n *\n * A port collision is a bad first minute: the command fails, and the reason is\n * somebody else's software. Picking an unfashionable number is the whole fix.\n */\nexport const DEFAULT_PORT = 6422;\n\n/** The address the CLI prints and the browser opens. */\nexport const DEFAULT_BASE_URL = `http://localhost:${DEFAULT_PORT}`;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../../src/lib/rate-limit.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAwBH,MAAM,UAAU,iBAAiB,CAAC,OAA2B;IAC3D,MAAM,OAAO,GAAG,IAAI,GAAG,EAA8C,CAAC;IAEtE,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;QAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACpC,IAAI,MAAM,CAAC,OAAO,IAAI,GAAG;gBAAE,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjD,CAAC;IACH,CAAC,EAAE,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;IAE1D,6DAA6D;IAC7D,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;IAEhB,OAAO;QACL,KAAK,CAAC,GAAG;YACP,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAEhC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,OAAO,IAAI,GAAG,EAAE,CAAC;gBACrC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;gBAChE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,KAAK,GAAG,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC;YACxE,CAAC;YAED,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;YAE5D,IAAI,MAAM,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;gBACjC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC;YACtD,CAAC;YAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,UAAU,EAAE,CAAC;QAChF,CAAC;QAED,KAAK,CAAC,GAAG;YACP,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC;QAED,IAAI;YACF,OAAO,OAAO,CAAC,IAAI,CAAC;QACtB,CAAC;QAED,IAAI;YACF,aAAa,CAAC,KAAK,CAAC,CAAC;YACrB,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../../src/lib/rate-limit.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAwBH,MAAM,UAAU,iBAAiB,CAAC,OAA2B;IAC3D,MAAM,OAAO,GAAG,IAAI,GAAG,EAA8C,CAAC;IAEtE,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;QAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACpC,IAAI,MAAM,CAAC,OAAO,IAAI,GAAG;gBAAE,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjD,CAAC;IACH,CAAC,EAAE,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;IAE1D,6DAA6D;IAC7D,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;IAEhB,OAAO;QACL,KAAK,CAAC,GAAG;YACP,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAEhC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,OAAO,IAAI,GAAG,EAAE,CAAC;gBACrC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;gBAChE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,KAAK,GAAG,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC;YACxE,CAAC;YAED,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;YAE5D,IAAI,MAAM,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;gBACjC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC;YACtD,CAAC;YAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,UAAU,EAAE,CAAC;QAChF,CAAC;QAED,KAAK,CAAC,GAAG;YACP,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC;QAED,IAAI;YACF,OAAO,OAAO,CAAC,IAAI,CAAC;QACtB,CAAC;QAED,IAAI;YACF,aAAa,CAAC,KAAK,CAAC,CAAC;YACrB,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["/**\n * Fixed-window rate limiting, in memory.\n *\n * The CMS is a single process by design, so an in-memory counter is\n * sufficient and avoids a Redis dependency. The trade-off is deliberate:\n * counters reset on restart. Mica checks no passwords; the identity provider\n * does, with its own limits, so a restart-and-retry loop gains little.\n */\n\nexport interface RateLimitResult {\n allowed: boolean;\n remaining: number;\n /** Seconds until the window resets. */\n retryAfter: number;\n}\n\nexport interface RateLimiter {\n check(key: string): RateLimitResult;\n /** Forgets a key — called after a successful login. */\n reset(key: string): void;\n size(): number;\n stop(): void;\n}\n\nexport interface RateLimiterOptions {\n limit: number;\n windowMs: number;\n /** How often expired buckets are swept. */\n sweepMs?: number;\n}\n\nexport function createRateLimiter(options: RateLimiterOptions): RateLimiter {\n const buckets = new Map<string, { count: number; resetAt: number }>();\n\n const sweep = setInterval(() => {\n const now = Date.now();\n for (const [key, bucket] of buckets) {\n if (bucket.resetAt <= now) buckets.delete(key);\n }\n }, options.sweepMs ?? Math.max(options.windowMs, 60_000));\n\n // A sweep timer must not keep the process alive on shutdown.\n sweep.unref?.();\n\n return {\n check(key) {\n const now = Date.now();\n const bucket = buckets.get(key);\n\n if (!bucket || bucket.resetAt <= now) {\n buckets.set(key, { count: 1, resetAt: now + options.windowMs });\n return { allowed: true, remaining: options.limit - 1, retryAfter: 0 };\n }\n\n bucket.count++;\n const retryAfter = Math.ceil((bucket.resetAt - now) / 1000);\n\n if (bucket.count > options.limit) {\n return { allowed: false, remaining: 0, retryAfter };\n }\n\n return { allowed: true, remaining: options.limit - bucket.count, retryAfter };\n },\n\n reset(key) {\n buckets.delete(key);\n },\n\n size() {\n return buckets.size;\n },\n\n stop() {\n clearInterval(sweep);\n buckets.clear();\n },\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"schema-stats.js","sourceRoot":"","sources":["../../src/lib/schema-stats.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schema-stats.js","sourceRoot":"","sources":["../../src/lib/schema-stats.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Summarises a content model.\n *\n * The admin already receives the whole model and could count fields itself, but\n * the interesting numbers are the recursive ones — objects and repeaters nest —\n * and the relation graph, which is only visible after walking every branch.\n * Doing it here keeps that walk in one place, next to the schema checks that\n * use the same shapes.\n *\n * Pure: it reads a `Site` and nothing else, so it is the same answer for the\n * same model whatever the state of the database.\n */\n\nimport {\n listedFields,\n resolveSlugField,\n resolveTitleField,\n type AnyField,\n type FieldKind,\n type FieldMap,\n type Site,\n} from \"@micacms/core\";\n\nexport interface KindUsage {\n kind: FieldKind;\n count: number;\n}\n\nexport interface RelationEdge {\n /** Collection or singleton the field is declared in. */\n from: string;\n fromType: \"collection\" | \"singleton\";\n /** Dotted path to the field, with `[]` marking a repeater. */\n path: string;\n /** Collection the relation points at. */\n to: string;\n multiple: boolean;\n}\n\nexport interface FieldCounts {\n /** Fields declared directly on the collection or singleton. */\n top: number;\n /** Every field, including those nested in objects and repeaters. */\n total: number;\n required: number;\n}\n\nexport interface CollectionStats {\n name: string;\n label: string;\n fields: FieldCounts;\n titleField: string | null;\n slugField: string | null;\n listed: number;\n sortable: boolean;\n /** Deepest level of nesting; 1 means no objects or repeaters. */\n depth: number;\n}\n\nexport interface SingletonStats {\n name: string;\n label: string;\n fields: FieldCounts;\n depth: number;\n}\n\nexport interface SchemaStats {\n collections: CollectionStats[];\n singletons: SingletonStats[];\n totals: FieldCounts & { collections: number; singletons: number };\n /** Field kinds in use, most used first. */\n kinds: KindUsage[];\n relations: RelationEdge[];\n}\n\n/** The two kinds that carry a nested `fields` map. */\nfunction children(field: AnyField): FieldMap | null {\n return field.kind === \"object\" || field.kind === \"repeater\" ? field.fields : null;\n}\n\n/**\n * Depth-first walk over a field map, visiting nested fields too.\n *\n * `path` is what an editor would say out loud — `blocks[].heading` rather than\n * `blocks.fields.heading` — so it can be printed as-is.\n */\nfunction walk(\n fields: FieldMap,\n visit: (key: string, field: AnyField, path: string, depth: number) => void,\n prefix = \"\",\n depth = 1,\n): void {\n for (const [key, field] of Object.entries(fields)) {\n const path = prefix ? `${prefix}.${key}` : key;\n visit(key, field, path, depth);\n\n const nested = children(field);\n if (nested) {\n walk(nested, visit, field.kind === \"repeater\" ? `${path}[]` : path, depth + 1);\n }\n }\n}\n\nfunction countFields(fields: FieldMap): { counts: FieldCounts; depth: number } {\n const counts: FieldCounts = { top: Object.keys(fields).length, total: 0, required: 0 };\n let deepest = 1;\n\n walk(fields, (_key, field, _path, depth) => {\n counts.total++;\n if (field.required) counts.required++;\n if (depth > deepest) deepest = depth;\n });\n\n return { counts, depth: deepest };\n}\n\nexport function schemaStats(site: Site): SchemaStats {\n const kinds = new Map<FieldKind, number>();\n const relations: RelationEdge[] = [];\n\n const totals: FieldCounts & { collections: number; singletons: number } = {\n collections: 0,\n singletons: 0,\n top: 0,\n total: 0,\n required: 0,\n };\n\n const tally = (fields: FieldMap, from: string, fromType: RelationEdge[\"fromType\"]): void => {\n walk(fields, (_key, field, path) => {\n kinds.set(field.kind, (kinds.get(field.kind) ?? 0) + 1);\n\n if (field.kind === \"relation\") {\n relations.push({ from, fromType, path, to: field.collection, multiple: field.multiple ?? false });\n }\n });\n };\n\n const collections = Object.values(site.collections).map((def): CollectionStats => {\n const { counts, depth } = countFields(def.fields);\n tally(def.fields, def.name, \"collection\");\n\n totals.collections++;\n totals.top += counts.top;\n totals.total += counts.total;\n totals.required += counts.required;\n\n return {\n name: def.name,\n label: def.label,\n fields: counts,\n // The same resolution the editor sees, not the raw declaration: both keys\n // are optional in the model and fall back to a convention.\n titleField: resolveTitleField(def) ?? null,\n slugField: resolveSlugField(def) ?? null,\n listed: listedFields(def).length,\n sortable: def.sortable ?? false,\n depth,\n };\n });\n\n const singletons = Object.values(site.singletons).map((def): SingletonStats => {\n const { counts, depth } = countFields(def.fields);\n tally(def.fields, def.name, \"singleton\");\n\n totals.singletons++;\n totals.top += counts.top;\n totals.total += counts.total;\n totals.required += counts.required;\n\n return { name: def.name, label: def.label, fields: counts, depth };\n });\n\n return {\n collections,\n singletons,\n totals,\n kinds: [...kinds]\n .map(([kind, count]) => ({ kind, count }))\n .sort((a, b) => b.count - a.count || a.kind.localeCompare(b.kind)),\n relations,\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/lib/version.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,SAAS,WAAW;IAClB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,EAAE,CAAC,YAAY,CAC9B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,oBAAoB,CAAC,EACvD,MAAM,CACP,CAAC;QACF,OAAQ,IAAI,CAAC,KAAK,CAAC,QAAQ,CAA0B,CAAC,OAAO,IAAI,SAAS,CAAC;IAC7E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC"}
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/lib/version.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,SAAS,WAAW;IAClB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,EAAE,CAAC,YAAY,CAC9B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,oBAAoB,CAAC,EACvD,MAAM,CACP,CAAC;QACF,OAAQ,IAAI,CAAC,KAAK,CAAC,QAAQ,CAA0B,CAAC,OAAO,IAAI,SAAS,CAAC;IAC7E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC","sourcesContent":["/**\n * The version of this build, read from the package manifest.\n *\n * Read rather than imported: an import would need a JSON module attribute and\n * would put a second copy of the manifest in `dist/`. The file is a fixed\n * distance from this module in both layouts — `src/lib` and `dist/lib`\n * are the same depth below the package root, and the Docker image copies\n * `package.json` next to `dist/` — so one path serves both.\n *\n * A missing or unreadable manifest is not worth failing a request over; the\n * system page shows \"unknown\" instead.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nfunction readVersion(): string {\n try {\n const manifest = fs.readFileSync(\n path.resolve(import.meta.dirname, \"../../package.json\"),\n \"utf8\",\n );\n return (JSON.parse(manifest) as { version?: string }).version ?? \"unknown\";\n } catch {\n return \"unknown\";\n }\n}\n\nexport const VERSION = readVersion();\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAY,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,iFAAiF;AACjF,MAAM,UAAU,cAAc,CAAC,GAA4B;IACzD,OAAO,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;QACvB,iFAAiF;QACjF,MAAM,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;QAC7C,MAAM,SAAS,GAAG,OAAO,IAAI,uBAAuB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QAC9F,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC;QAE/C,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAClB,CAAC,CAAC,GAAG,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;QAC9B,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACxB,CAAC,CAAC,MAAM,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;QAEpC,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QACpC,MAAM,IAAI,EAAE,CAAC;QACb,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC;QAE3D,MAAM,IAAI,GAAG;YACX,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM;YACpB,IAAI,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ;YACjC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM;YACpB,QAAQ;SACT,CAAC;QAEF;;;;;;;WAOG;QACH,MAAM,WAAW,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC;QAEzE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,IAAI,GAAG;YAAE,MAAM,CAAC,KAAK,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;aACzD,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW;YAAE,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAC;;YAC/E,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACrC,CAAC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,oBAAoB;IACpB,4BAA4B;IAC5B,mBAAmB;IACnB,iBAAiB;IACjB,wBAAwB;CACzB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,UAAU,eAAe;IAC7B,OAAO,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;QACvB,MAAM,IAAI,EAAE,CAAC;QAEb,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,EAAE,CAAC;YAClD,CAAC,CAAC,MAAM,CAAC,yBAAyB,EAAE,uBAAuB,CAAC,CAAC;QAC/D,CAAC;QACD,wEAAwE;QACxE,gEAAgE;QAChE,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC/D,CAAC,CAAC,MAAM,CAAC,2BAA2B,EAAE,kBAAkB,CAAC,CAAC;QAC5D,CAAC;QAED,CAAC,CAAC,MAAM,CAAC,wBAAwB,EAAE,SAAS,CAAC,CAAC;QAC9C,CAAC,CAAC,MAAM,CAAC,iBAAiB,EAAE,aAAa,CAAC,CAAC;QAC3C,CAAC,CAAC,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;QACpC,qEAAqE;QACrE,CAAC,CAAC,MAAM,CAAC,oBAAoB,EAAE,0CAA0C,CAAC,CAAC;IAC7E,CAAC,CAAC;AACJ,CAAC;AAED,oFAAoF;AACpF,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAEvC,gFAAgF;AAChF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AAE9C;;;;GAIG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;QACvB,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAChC,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,KAAK,kBAAkB,CAAC;QAC5E,MAAM,OAAO,GAAG,MAAM;YACpB,CAAC,CAAC,MAAM,CAAC,gBAAgB,GAAG,oBAAoB,GAAG,IAAI,GAAG,IAAI;YAC9D,CAAC,CAAC,cAAc,CAAC;QAEnB,OAAO,SAAS,CAAC;YACf,OAAO;YACP,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;gBACf,MAAM,OAAO,GAAG,IAAI,QAAQ,CAC1B,mBAAmB,EACnB,MAAM;oBACJ,CAAC,CAAC,mEAAmE;oBACrE,CAAC,CAAC,2BAA2B,CAChC,CAAC;gBACF,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,GAAG,CAAC,CAAC;YACzC,CAAC;SACF,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IACd,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;QAClB,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;QAEtD,IAAI,KAAK,YAAY,QAAQ,EAAE,CAAC;YAC9B,MAAM,CAAC,KAAK,CAAC,eAAe,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAC5E,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,KAAK,CAAC,MAA8B,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QACrF,CAAC;QAED,+EAA+E;QAC/E,IAAI,KAAK,YAAY,gBAAgB,EAAE,CAAC;YACtC,MAAM,CAAC,IAAI,CAAC,sBAAsB,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAChE,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC1C,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,OAAO,CAAC,MAA8B,CAAC,CAAC;QAC1E,CAAC;QAED,MAAM,CAAC,KAAK,CAAC,iBAAiB,EAAE;YAC9B,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;YAC9E,IAAI,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ;SAClC,CAAC,CAAC;QAEH,OAAO,CAAC,CAAC,IAAI,CACX;YACE,KAAK,EAAE;gBACL,IAAI,EAAE,gBAAyB;gBAC/B,OAAO,EAAE,yCAAyC;gBAClD,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC;aAC9B;SACF,EACD,GAAG,CACJ,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,SAAS;IACvB,OAAO,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;QACvB,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAClC,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAE/C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,IAAI,QAAQ,CAAC,cAAc,EAAE,sCAAsC,EAAE;gBACzE,OAAO,EAAE,EAAE,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE;aACtD,CAAC,CAAC;QACL,CAAC;QAED,MAAM,IAAI,EAAE,CAAC;IACf,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;AAEzD,MAAM,eAAe,GAAG,CAAC,KAAa,EAAU,EAAE;IAChD,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,UAAU,cAAc,CAAC,MAG9B;IACC,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,eAAe,EAAE,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;AAC7F,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW;IACzB,OAAO,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;QACvB,IAAI,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACnC,MAAM,IAAI,EAAE,CAAC;YACb,OAAO;QACT,CAAC;QAED,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAChC,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAEtC,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;gBAC9D,MAAM,IAAI,QAAQ,CAAC,WAAW,EAAE,gCAAgC,CAAC,CAAC;YACpE,CAAC;QACH,CAAC;aAAM,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;YAC/B,yEAAyE;YACzE,0EAA0E;YAC1E,MAAM,IAAI,QAAQ,CAAC,WAAW,EAAE,wBAAwB,CAAC,CAAC;QAC5D,CAAC;QAED,MAAM,IAAI,EAAE,CAAC;IACf,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Middleware.\n *\n * Ordering matters and is asserted in `app.ts`:\n * requestContext → guards → securityHeaders → errorBoundary → rateLimit\n * → originGuard → the auth surface's gate → route\n *\n * The gate itself is not here. Whether a request is anybody — a session\n * middleware, `allowAll()` — belongs to the composing app, which is what\n * keeps this package authentication-neutral.\n */\n\nimport { ContentPathError } from \"@micacms/core\";\nimport type { ErrorHandler, MiddlewareHandler } from \"hono\";\nimport { bodyLimit } from \"hono/body-limit\";\nimport type { ContentfulStatusCode } from \"hono/utils/http-status\";\n\nimport { ApiError, badRequest } from \"../lib/errors.js\";\nimport { clientIp, type Env } from \"../http.js\";\nimport { randomToken } from \"../lib/id.js\";\n\n/** Attaches the container, a request id and a scoped logger; logs the result. */\nexport function requestContext(ctx: Env[\"Variables\"][\"ctx\"]): MiddlewareHandler<Env> {\n return async (c, next) => {\n // A client's id is logged and echoed, so only a short, plain one is kept (#150).\n const offered = c.req.header(\"x-request-id\");\n const requestId = offered && /^[A-Za-z0-9_-]{1,64}$/.test(offered) ? offered : randomToken(8);\n const logger = ctx.logger.child({ requestId });\n\n c.set(\"ctx\", ctx);\n c.set(\"requestId\", requestId);\n c.set(\"logger\", logger);\n c.header(\"x-request-id\", requestId);\n\n const startedAt = performance.now();\n await next();\n const duration = Math.round(performance.now() - startedAt);\n\n const line = {\n method: c.req.method,\n path: new URL(c.req.url).pathname,\n status: c.res.status,\n duration,\n };\n\n /**\n * \"Am I signed in?\" — \"No.\"\n *\n * `/auth/me` is the SPA's first request on every page load, and a 401 is\n * one of its two correct answers, not a rejection worth a warning. Logging\n * it as one puts a scary line in the terminal of everybody who has simply\n * opened the editor while signed out.\n */\n const expected401 = c.res.status === 401 && line.path === \"/api/auth/me\";\n\n if (c.res.status >= 500) logger.error(\"Request failed\", line);\n else if (c.res.status >= 400 && !expected401) logger.warn(\"Request rejected\", line);\n else logger.debug(\"Request\", line);\n };\n}\n\n/**\n * Same-origin only. `blob:` and `data:` images cover previews; a route that\n * needs a stricter policy, such as the sandbox on media files, sets its own.\n */\nexport const CONTENT_SECURITY_POLICY = [\n \"default-src 'self'\",\n \"img-src 'self' blob: data:\",\n \"object-src 'none'\",\n \"base-uri 'none'\",\n \"frame-ancestors 'none'\",\n].join(\"; \");\n\nexport function securityHeaders(): MiddlewareHandler<Env> {\n return async (c, next) => {\n await next();\n\n if (!c.res.headers.has(\"content-security-policy\")) {\n c.header(\"content-security-policy\", CONTENT_SECURITY_POLICY);\n }\n // Only for an https public URL: HSTS over plain HTTP is ignored, and on\n // localhost it would pin a developer's other projects to https.\n if (c.get(\"ctx\").config.MICA_PUBLIC_URL.startsWith(\"https://\")) {\n c.header(\"strict-transport-security\", \"max-age=31536000\");\n }\n\n c.header(\"x-content-type-options\", \"nosniff\");\n c.header(\"referrer-policy\", \"same-origin\");\n c.header(\"x-frame-options\", \"DENY\");\n // The admin is a first-party SPA; nothing here needs to be embedded.\n c.header(\"permissions-policy\", \"geolocation=(), microphone=(), camera=()\");\n };\n}\n\n/** Files in one upload request; the Media view sends a selection in one request. */\nexport const MAX_FILES_PER_UPLOAD = 10;\n\n/** Far more than any entry's JSON, and small enough to refuse a flood early. */\nexport const MAX_JSON_BYTES = 2 * 1024 * 1024;\n\n/**\n * Refuses an oversized body before a handler reads it into memory (#148). An\n * upload may carry `MAX_FILES_PER_UPLOAD` files of `MAX_UPLOAD_BYTES`, plus\n * room for the multipart framing; every other request gets `MAX_JSON_BYTES`.\n */\nexport function requestSizeLimit(): MiddlewareHandler<Env> {\n return async (c, next) => {\n const { config } = c.get(\"ctx\");\n const upload = c.req.method === \"POST\" && c.req.path === \"/api/admin/media\";\n const maxSize = upload\n ? config.MAX_UPLOAD_BYTES * MAX_FILES_PER_UPLOAD + 1024 * 1024\n : MAX_JSON_BYTES;\n\n return bodyLimit({\n maxSize,\n onError: (ctx) => {\n const refused = new ApiError(\n \"payload_too_large\",\n upload\n ? \"The upload is too large. Upload fewer or smaller files at a time.\"\n : \"The request is too large.\",\n );\n return ctx.json(refused.toBody(), 413);\n },\n })(c, next);\n };\n}\n\n/**\n * Converts thrown errors into the API error envelope. Deliberate failures\n * (`ApiError`) are reported as-is; anything else is a bug and becomes a bare\n * 500, with the stack kept in the log rather than sent to the client.\n *\n * Registered with `app.onError`, not as middleware: Hono's `compose` wraps each\n * handler individually and routes a throw to `onError` at that level, so a\n * try/catch in an outer middleware would never see it.\n */\nexport function errorHandler(): ErrorHandler<Env> {\n return (error, c) => {\n const logger = c.get(\"logger\") ?? c.get(\"ctx\").logger;\n\n if (error instanceof ApiError) {\n logger.debug(\"Handled error\", { code: error.code, message: error.message });\n return c.json(error.toBody(), error.status as ContentfulStatusCode, error.headers);\n }\n\n // A path that could leave the content root is the client's mistake, not a bug.\n if (error instanceof ContentPathError) {\n logger.warn(\"Refused content path\", { message: error.message });\n const refused = badRequest(error.message);\n return c.json(refused.toBody(), refused.status as ContentfulStatusCode);\n }\n\n logger.error(\"Unhandled error\", {\n error: error instanceof Error ? (error.stack ?? error.message) : String(error),\n path: new URL(c.req.url).pathname,\n });\n\n return c.json(\n {\n error: {\n code: \"internal_error\" as const,\n message: \"Something went wrong. Please try again.\",\n requestId: c.get(\"requestId\"),\n },\n },\n 500,\n );\n };\n}\n\n/** Coarse per-IP limit, applied to the whole API surface. */\nexport function rateLimit(): MiddlewareHandler<Env> {\n return async (c, next) => {\n const { limiters } = c.get(\"ctx\");\n const result = limiters.api.check(clientIp(c));\n\n if (!result.allowed) {\n throw new ApiError(\"rate_limited\", \"Too many requests. Please slow down.\", {\n headers: { \"retry-after\": String(result.retryAfter) },\n });\n }\n\n await next();\n };\n}\n\nconst SAFE_METHODS = new Set([\"GET\", \"HEAD\", \"OPTIONS\"]);\n\nconst normaliseOrigin = (value: string): string => {\n try {\n return new URL(value).origin;\n } catch {\n return value;\n }\n};\n\nexport function allowedOrigins(config: {\n MICA_PUBLIC_URL: string;\n adminOrigins: string[];\n}): string[] {\n return [...new Set([config.MICA_PUBLIC_URL, ...config.adminOrigins].map(normaliseOrigin))];\n}\n\n/**\n * First CSRF layer: the browser sets `Origin` on every state-changing request\n * and a page on another site cannot forge it.\n *\n * Applied to the whole API — including sign-in, which has no session yet and\n * so cannot use the token check below.\n */\nexport function originGuard(): MiddlewareHandler<Env> {\n return async (c, next) => {\n if (SAFE_METHODS.has(c.req.method)) {\n await next();\n return;\n }\n\n const { config } = c.get(\"ctx\");\n const origin = c.req.header(\"origin\");\n\n if (origin) {\n if (!allowedOrigins(config).includes(normaliseOrigin(origin))) {\n throw new ApiError(\"forbidden\", \"Request origin is not allowed.\");\n }\n } else if (config.isProduction) {\n // A browser always sends Origin on writes; its absence means the request\n // did not come from one. Tolerated in development for curl-based testing.\n throw new ApiError(\"forbidden\", \"Missing Origin header.\");\n }\n\n await next();\n };\n}\n"]}
@@ -1,22 +1,9 @@
1
1
  /**
2
- * Admin content routes — entries and singletons.
3
- *
4
- * Thin: parse, delegate to the content store, serialise. Every rule about
5
- * validation, slugs and layout lives in the store, which is shared with the
6
- * Astro build rather than reimplemented here.
7
- *
8
- * Three things shape this surface:
9
- *
10
- * - An entry is addressed by `collection/slug`. The path in the API is the
11
- * path in the repository, so a URL here can be read off a diff.
12
- * - There are no revision endpoints. Git is the history.
13
- * - There is no status endpoint. Committed is published, and a draft is
14
- * unsaved work in the editor that never reaches the server.
15
- *
16
- * `revision` is what makes concurrent editing safe: an opaque token naming the
17
- * version an editor opened, sent back with the save.
2
+ * Admin routes for entries and singletons. The content store holds every rule;
3
+ * these routes only parse and serialize. The API path is the repository path,
4
+ * Git is the history, and `revision` makes concurrent edits safe.
18
5
  */
19
6
  import { Hono } from "hono";
20
- import { type Env } from "../http.js";
7
+ import type { Env } from "../http.js";
21
8
  export declare function adminContentRoutes(): Hono<Env>;
22
9
  //# sourceMappingURL=admin-content.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"admin-content.d.ts","sourceRoot":"","sources":["../../src/routes/admin-content.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B,OAAO,EAAW,KAAK,GAAG,EAAE,MAAM,YAAY,CAAC;AAwC/C,wBAAgB,kBAAkB,IAAI,IAAI,CAAC,GAAG,CAAC,CA0K9C"}
1
+ {"version":3,"file":"admin-content.d.ts","sourceRoot":"","sources":["../../src/routes/admin-content.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAiCtC,wBAAgB,kBAAkB,IAAI,IAAI,CAAC,GAAG,CAAC,CAoJ9C"}
@@ -1,34 +1,20 @@
1
1
  /**
2
- * Admin content routes — entries and singletons.
3
- *
4
- * Thin: parse, delegate to the content store, serialise. Every rule about
5
- * validation, slugs and layout lives in the store, which is shared with the
6
- * Astro build rather than reimplemented here.
7
- *
8
- * Three things shape this surface:
9
- *
10
- * - An entry is addressed by `collection/slug`. The path in the API is the
11
- * path in the repository, so a URL here can be read off a diff.
12
- * - There are no revision endpoints. Git is the history.
13
- * - There is no status endpoint. Committed is published, and a draft is
14
- * unsaved work in the editor that never reaches the server.
15
- *
16
- * `revision` is what makes concurrent editing safe: an opaque token naming the
17
- * version an editor opened, sent back with the save.
2
+ * Admin routes for entries and singletons. The content store holds every rule;
3
+ * these routes only parse and serialize. The API path is the repository path,
4
+ * Git is the history, and `revision` makes concurrent edits safe.
18
5
  */
19
- import { ConflictError, ValidationError } from "@micacms/connectors";
6
+ import { ValidationError } from "../services/content-store.js";
7
+ import { ConflictError } from "../workspace/files.js";
20
8
  import { collectionEntryPath, compareEntries, entryTitle, singletonPath } from "@micacms/core";
21
9
  import { Hono } from "hono";
22
10
  import { z } from "zod";
23
11
  import { ApiError, badRequest, notFound } from "../lib/errors.js";
24
- import { actorOf } from "../http.js";
25
12
  const saveSchema = z.object({
26
13
  data: z.record(z.string(), z.unknown()),
27
14
  slug: z.string().max(120).optional(),
28
15
  /**
29
- * The revision the editor opened. `null` asserts the entry did not exist,
30
- * which is what makes two simultaneous creates fail instead of one silently
31
- * overwriting the other.
16
+ * The revision the editor opened. `null` asserts that the entry does not
17
+ * exist, so two parallel creates cannot overwrite.
32
18
  */
33
19
  revision: z.string().nullable().optional(),
34
20
  });
@@ -38,13 +24,7 @@ async function jsonBody(c) {
38
24
  throw badRequest("The request body must be valid JSON.");
39
25
  });
40
26
  }
41
- /**
42
- * Turns a store failure into the HTTP answer it deserves.
43
- *
44
- * A conflict is 409 and is recoverable in the editor — reload and reapply. A
45
- * validation failure is 422 with the offending fields. Everything else is a
46
- * genuine fault and reaches the error handler unchanged.
47
- */
27
+ /** Maps a conflict to 409 and a validation failure to 422; other errors go to the error handler. */
48
28
  async function handled(run) {
49
29
  try {
50
30
  return await run();
@@ -60,7 +40,6 @@ async function handled(run) {
60
40
  }
61
41
  export function adminContentRoutes() {
62
42
  const app = new Hono();
63
- /* ------------------------------------------------------------ entries */
64
43
  app.get("/collections/:collection/entries", async (c) => {
65
44
  const { content } = c.get("ctx").services;
66
45
  const collection = c.req.param("collection");
@@ -74,13 +53,8 @@ export function adminContentRoutes() {
74
53
  title: entryTitle(def, entry.data),
75
54
  data: entry.data,
76
55
  }))
77
- // A substring match over the payload, which is what the SQL `LIKE` did.
78
- // Content trees are small enough that filtering in memory is simpler than
79
- // an index, and it can no longer disagree with what is on disk.
56
+ // Content trees are small, so an in-memory substring match is sufficient.
80
57
  .filter((item) => !search || JSON.stringify(item.data).toLowerCase().includes(search))
81
- // The order the model asks for — newest first for news, by hand for a
82
- // menu. Ties fall back to the manual position, so the list is stable
83
- // between requests whatever the sort field says.
84
58
  .sort(compareEntries(def));
85
59
  return c.json({ items, total: items.length });
86
60
  });
@@ -91,9 +65,7 @@ export function adminContentRoutes() {
91
65
  throw badRequest("The entry payload is malformed.");
92
66
  const saved = await handled(() => content.save(c.req.param("collection"), {
93
67
  data: parsed.data.data,
94
- // A create asserts absence unless the client says otherwise.
95
68
  expectedRevision: parsed.data.revision ?? null,
96
- author: actorOf(c) ? { name: actorOf(c).email, email: actorOf(c).email } : undefined,
97
69
  }));
98
70
  return c.json(saved, 201);
99
71
  });
@@ -129,12 +101,8 @@ export function adminContentRoutes() {
129
101
  position: entry.position,
130
102
  title: entryTitle(def, entry.data),
131
103
  data: entry.data,
132
- // Where this entry is on disk. Derived from the model, because whether an
133
- // entry is one file or a directory depends on whether it has rich text or
134
- // media — a rule the editor should not have to reimplement to show it.
104
+ // From the model, so the editor need not know when an entry is a directory.
135
105
  path: collectionEntryPath(def.fields, collection, entry.slug),
136
- // Sent back with the save. Without it the editor cannot tell the server
137
- // which version of the entry it was looking at.
138
106
  revision: await content.revisionOf(collection, slug),
139
107
  });
140
108
  });
@@ -143,21 +111,16 @@ export function adminContentRoutes() {
143
111
  const parsed = saveSchema.safeParse(await jsonBody(c));
144
112
  if (!parsed.success)
145
113
  throw badRequest("The entry payload is malformed.");
146
- const actor = actorOf(c);
147
114
  const saved = await handled(() => content.save(c.req.param("collection"), {
148
115
  data: parsed.data.data,
149
116
  slug: c.req.param("slug"),
150
117
  expectedRevision: parsed.data.revision,
151
- author: actor ? { name: actor.email, email: actor.email } : undefined,
152
118
  }));
153
119
  return c.json(saved);
154
120
  });
155
121
  app.delete("/collections/:collection/entries/:slug", async (c) => {
156
122
  const { content } = c.get("ctx").services;
157
- const actor = actorOf(c);
158
- await handled(() => content.remove(c.req.param("collection"), c.req.param("slug"), {
159
- author: actor ? { name: actor.email, email: actor.email } : undefined,
160
- }));
123
+ await handled(() => content.remove(c.req.param("collection"), c.req.param("slug")));
161
124
  return c.json({ ok: true });
162
125
  });
163
126
  /** Entries elsewhere that point at this one — shown before a delete. */
@@ -166,7 +129,6 @@ export function adminContentRoutes() {
166
129
  const references = await handled(() => content.findReferences(c.req.param("collection"), c.req.param("slug")));
167
130
  return c.json({ references });
168
131
  });
169
- /* --------------------------------------------------------- singletons */
170
132
  app.get("/singletons/:name", async (c) => {
171
133
  const { content } = c.get("ctx").services;
172
134
  const name = c.req.param("name");
@@ -182,10 +144,8 @@ export function adminContentRoutes() {
182
144
  app.put("/singletons/:name", async (c) => {
183
145
  const { content } = c.get("ctx").services;
184
146
  const body = (await jsonBody(c));
185
- const actor = actorOf(c);
186
147
  const saved = await handled(() => content.saveSingleton(c.req.param("name"), body?.data ?? {}, {
187
148
  expectedRevision: body?.revision,
188
- author: actor ? { name: actor.email, email: actor.email } : undefined,
189
149
  }));
190
150
  return c.json(saved);
191
151
  });
@@ -1 +1 @@
1
- {"version":3,"file":"admin-content.js","sourceRoot":"","sources":["../../src/routes/admin-content.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"admin-content.js","sourceRoot":"","sources":["../../src/routes/admin-content.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Admin routes for entries and singletons. The content store holds every rule;\n * these routes only parse and serialize. The API path is the repository path,\n * Git is the history, and `revision` makes concurrent edits safe.\n */\n\nimport { ValidationError } from \"../services/content-store.js\";\nimport { ConflictError } from \"../workspace/files.js\";\nimport { collectionEntryPath, compareEntries, entryTitle, singletonPath } from \"@micacms/core\";\nimport { Hono } from \"hono\";\nimport { z } from \"zod\";\n\nimport { ApiError, badRequest, notFound } from \"../lib/errors.js\";\nimport type { Env } from \"../http.js\";\n\nconst saveSchema = z.object({\n data: z.record(z.string(), z.unknown()),\n slug: z.string().max(120).optional(),\n /**\n * The revision the editor opened. `null` asserts that the entry does not\n * exist, so two parallel creates cannot overwrite.\n */\n revision: z.string().nullable().optional(),\n});\n\nconst reorderSchema = z.object({ slugs: z.array(z.string().min(1)).max(2000) });\n\nasync function jsonBody(c: { req: { json(): Promise<unknown> } }): Promise<unknown> {\n return c.req.json().catch(() => {\n throw badRequest(\"The request body must be valid JSON.\");\n });\n}\n\n/** Maps a conflict to 409 and a validation failure to 422; other errors go to the error handler. */\nasync function handled<T>(run: () => Promise<T>): Promise<T> {\n try {\n return await run();\n } catch (error) {\n if (error instanceof ConflictError) throw new ApiError(\"conflict\", error.message);\n if (error instanceof ValidationError) {\n throw new ApiError(\"validation_failed\", error.message, { issues: error.issues });\n }\n throw error;\n }\n}\n\nexport function adminContentRoutes(): Hono<Env> {\n const app = new Hono<Env>();\n\n app.get(\"/collections/:collection/entries\", async (c) => {\n const { content } = c.get(\"ctx\").services;\n const collection = c.req.param(\"collection\");\n const def = content.requireCollection(collection);\n\n const entries = await handled(() => content.list(collection));\n const search = c.req.query(\"search\")?.trim().toLowerCase();\n\n const items = entries\n .map((entry) => ({\n slug: entry.slug,\n position: entry.position,\n title: entryTitle(def, entry.data),\n data: entry.data,\n }))\n // Content trees are small, so an in-memory substring match is sufficient.\n .filter((item) => !search || JSON.stringify(item.data).toLowerCase().includes(search))\n .sort(compareEntries(def));\n\n return c.json({ items, total: items.length });\n });\n\n app.post(\"/collections/:collection/entries\", async (c) => {\n const { content } = c.get(\"ctx\").services;\n const parsed = saveSchema.safeParse(await jsonBody(c));\n if (!parsed.success) throw badRequest(\"The entry payload is malformed.\");\n\n const saved = await handled(() =>\n content.save(c.req.param(\"collection\"), {\n data: parsed.data.data,\n expectedRevision: parsed.data.revision ?? null,\n }),\n );\n\n return c.json(saved, 201);\n });\n\n app.post(\"/collections/:collection/reorder\", async (c) => {\n const { content } = c.get(\"ctx\").services;\n const parsed = reorderSchema.safeParse(await jsonBody(c));\n if (!parsed.success) throw badRequest(\"Expected a list of entry slugs.\");\n\n await handled(() => content.reorder(c.req.param(\"collection\"), parsed.data.slugs));\n return c.json({ ok: true });\n });\n\n /** Server-side slug generation, so the URL preview matches what is saved. */\n app.get(\"/collections/:collection/slug\", async (c) => {\n const { content } = c.get(\"ctx\").services;\n const source = c.req.query(\"source\") ?? \"\";\n if (!source.trim()) return c.json({ slug: \"\" });\n\n return c.json({\n slug: await handled(() =>\n content.suggestSlug(c.req.param(\"collection\"), source, c.req.query(\"except\")),\n ),\n });\n });\n\n app.get(\"/collections/:collection/entries/:slug\", async (c) => {\n const { content } = c.get(\"ctx\").services;\n const collection = c.req.param(\"collection\");\n const slug = c.req.param(\"slug\");\n\n const entry = await handled(() => content.get(collection, slug));\n if (!entry) throw notFound(\"This entry no longer exists.\");\n\n const def = content.requireCollection(collection);\n\n return c.json({\n collection,\n slug: entry.slug,\n position: entry.position,\n title: entryTitle(def, entry.data),\n data: entry.data,\n // From the model, so the editor need not know when an entry is a directory.\n path: collectionEntryPath(def.fields, collection, entry.slug),\n revision: await content.revisionOf(collection, slug),\n });\n });\n\n app.put(\"/collections/:collection/entries/:slug\", async (c) => {\n const { content } = c.get(\"ctx\").services;\n const parsed = saveSchema.safeParse(await jsonBody(c));\n if (!parsed.success) throw badRequest(\"The entry payload is malformed.\");\n\n const saved = await handled(() =>\n content.save(c.req.param(\"collection\"), {\n data: parsed.data.data,\n slug: c.req.param(\"slug\"),\n expectedRevision: parsed.data.revision,\n }),\n );\n\n return c.json(saved);\n });\n\n app.delete(\"/collections/:collection/entries/:slug\", async (c) => {\n const { content } = c.get(\"ctx\").services;\n\n await handled(() =>\n content.remove(c.req.param(\"collection\"), c.req.param(\"slug\")),\n );\n\n return c.json({ ok: true });\n });\n\n /** Entries elsewhere that point at this one — shown before a delete. */\n app.get(\"/collections/:collection/entries/:slug/references\", async (c) => {\n const { content } = c.get(\"ctx\").services;\n const references = await handled(() =>\n content.findReferences(c.req.param(\"collection\"), c.req.param(\"slug\")),\n );\n\n return c.json({ references });\n });\n\n app.get(\"/singletons/:name\", async (c) => {\n const { content } = c.get(\"ctx\").services;\n const name = c.req.param(\"name\");\n const def = content.requireSingleton(name);\n\n return c.json({\n name,\n label: def.label,\n path: singletonPath(def.fields, name),\n data: await handled(() => content.getSingleton(name)),\n revision: await content.revisionOfSingleton(name),\n });\n });\n\n app.put(\"/singletons/:name\", async (c) => {\n const { content } = c.get(\"ctx\").services;\n const body = (await jsonBody(c)) as { data?: unknown; revision?: string | null };\n\n const saved = await handled(() =>\n content.saveSingleton(c.req.param(\"name\"), body?.data ?? {}, {\n expectedRevision: body?.revision,\n }),\n );\n\n return c.json(saved);\n });\n\n return app;\n}\n"]}
@@ -1,19 +1,8 @@
1
1
  /**
2
- * Admin media routes.
3
- *
4
- * Media is files in the content repository now, so these routes are much
5
- * smaller than they were. There is no upload table to keep in step, no storage
6
- * key to generate, and no delete endpoint — removing a file that an entry still
7
- * references is a content decision made in a diff, not an API call.
8
- *
9
- * Uploads are committed on their own rather than folded into the entry save.
10
- * The editor needs a path to put in the field before it can save the entry that
11
- * references it, and a two-step flow is the honest way to say so. The cost is
12
- * an occasional unreferenced file, which is visible in the repository and
13
- * cheap to remove; the alternative would be holding uploads in server memory
14
- * between requests.
2
+ * Admin media routes. Media is files in the content repository, and there is no delete endpoint.
3
+ * An upload is written on its own, before the entry save, because the editor needs its path first.
15
4
  */
16
5
  import { Hono } from "hono";
17
- import { type Env } from "../http.js";
6
+ import type { Env } from "../http.js";
18
7
  export declare function adminMediaRoutes(): Hono<Env>;
19
8
  //# sourceMappingURL=admin-media.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"admin-media.d.ts","sourceRoot":"","sources":["../../src/routes/admin-media.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAK5B,OAAO,EAAW,KAAK,GAAG,EAAE,MAAM,YAAY,CAAC;AAE/C,wBAAgB,gBAAgB,IAAI,IAAI,CAAC,GAAG,CAAC,CAyF5C"}
1
+ {"version":3,"file":"admin-media.d.ts","sourceRoot":"","sources":["../../src/routes/admin-media.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAK5B,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAEtC,wBAAgB,gBAAgB,IAAI,IAAI,CAAC,GAAG,CAAC,CA+E5C"}
@@ -1,23 +1,11 @@
1
1
  /**
2
- * Admin media routes.
3
- *
4
- * Media is files in the content repository now, so these routes are much
5
- * smaller than they were. There is no upload table to keep in step, no storage
6
- * key to generate, and no delete endpoint — removing a file that an entry still
7
- * references is a content decision made in a diff, not an API call.
8
- *
9
- * Uploads are committed on their own rather than folded into the entry save.
10
- * The editor needs a path to put in the field before it can save the entry that
11
- * references it, and a two-step flow is the honest way to say so. The cost is
12
- * an occasional unreferenced file, which is visible in the repository and
13
- * cheap to remove; the alternative would be holding uploads in server memory
14
- * between requests.
2
+ * Admin media routes. Media is files in the content repository, and there is no delete endpoint.
3
+ * An upload is written on its own, before the entry save, because the editor needs its path first.
15
4
  */
16
5
  import { Hono } from "hono";
17
6
  import { badRequest, notFound } from "../lib/errors.js";
18
7
  import { isImageType } from "../lib/file-type.js";
19
8
  import { MAX_FILES_PER_UPLOAD } from "../middleware/index.js";
20
- import { actorOf } from "../http.js";
21
9
  export function adminMediaRoutes() {
22
10
  const app = new Hono();
23
11
  app.get("/", async (c) => {
@@ -29,9 +17,7 @@ export function adminMediaRoutes() {
29
17
  const form = await c.req.formData().catch(() => {
30
18
  throw badRequest("Expected a multipart upload.");
31
19
  });
32
- // Two `File` types are in scope here — Node's and undici's — and they are
33
- // structurally different. The runtime check is the same either way; the
34
- // cast is only to pick one of them for the compiler.
20
+ // The cast picks one of the two structurally different `File` types (Node's and undici's).
35
21
  const files = form
36
22
  .getAll("file")
37
23
  .filter((value) => typeof value !== "string");
@@ -41,33 +27,25 @@ export function adminMediaRoutes() {
41
27
  throw badRequest(`Upload at most ${MAX_FILES_PER_UPLOAD} files at a time.`);
42
28
  }
43
29
  const accept = form.get("accept");
44
- // Where the editor wants the file: an entry's own `media/` directory, or
45
- // the shared one. The media service refuses anything else.
30
+ // An entry's own `media/` directory or the shared one; the media service refuses anything else.
46
31
  const directory = typeof form.get("directory") === "string" ? String(form.get("directory")) : undefined;
47
32
  const prepared = await Promise.all(files.map((file) => ctx.services.media.prepare({
48
33
  file,
49
34
  directory,
50
35
  accept: accept === "image" || accept === "document" ? accept : "any",
51
36
  })));
52
- const actor = actorOf(c);
53
- await ctx.site.contentRepository.commit({
54
- message: `Media: upload ${prepared.map((item) => item.file.filename).join(", ")}`,
37
+ await ctx.site.contentRepository.apply({
55
38
  changes: prepared.map((item) => ({
56
39
  type: "write",
57
40
  path: item.file.path,
58
41
  contents: item.contents,
59
42
  })),
60
- author: actor ? { name: actor.email, email: actor.email } : undefined,
61
43
  });
62
44
  return c.json({ items: prepared.map((item) => item.file) }, 201);
63
45
  });
64
46
  /**
65
- * Serves a file to the editor.
66
- *
67
- * Behind the admin session, unlike the old `/media/*`, which had to be public
68
- * so that the Astro build could fetch it. The build reads the repository
69
- * directly now, so nothing outside this session needs these bytes and the
70
- * whole "media is effectively public" trade-off disappears with the route.
47
+ * Serves a file to the editor, behind the admin gate. The site build reads
48
+ * the repository, not this route.
71
49
  */
72
50
  app.get("/file/*", async (c) => {
73
51
  const { media } = c.get("ctx").services;
@@ -1 +1 @@
1
- {"version":3,"file":"admin-media.js","sourceRoot":"","sources":["../../src/routes/admin-media.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"admin-media.js","sourceRoot":"","sources":["../../src/routes/admin-media.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Admin media routes. Media is files in the content repository, and there is no delete endpoint.\n * An upload is written on its own, before the entry save, because the editor needs its path first.\n */\n\nimport { Hono } from \"hono\";\n\nimport { badRequest, notFound } from \"../lib/errors.js\";\nimport { isImageType } from \"../lib/file-type.js\";\nimport { MAX_FILES_PER_UPLOAD } from \"../middleware/index.js\";\nimport type { Env } from \"../http.js\";\n\nexport function adminMediaRoutes(): Hono<Env> {\n const app = new Hono<Env>();\n\n app.get(\"/\", async (c) => {\n const { media } = c.get(\"ctx\").services;\n return c.json({ items: await media.list() });\n });\n\n app.post(\"/\", async (c) => {\n const ctx = c.get(\"ctx\");\n const form = await c.req.formData().catch(() => {\n throw badRequest(\"Expected a multipart upload.\");\n });\n\n // The cast picks one of the two structurally different `File` types (Node's and undici's).\n const files = form\n .getAll(\"file\")\n .filter((value) => typeof value !== \"string\") as unknown as File[];\n\n if (files.length === 0) throw badRequest(\"No file was uploaded.\");\n if (files.length > MAX_FILES_PER_UPLOAD) {\n throw badRequest(`Upload at most ${MAX_FILES_PER_UPLOAD} files at a time.`);\n }\n\n const accept = form.get(\"accept\");\n // An entry's own `media/` directory or the shared one; the media service refuses anything else.\n const directory = typeof form.get(\"directory\") === \"string\" ? String(form.get(\"directory\")) : undefined;\n\n const prepared = await Promise.all(\n files.map((file) =>\n ctx.services.media.prepare({\n file,\n directory,\n accept: accept === \"image\" || accept === \"document\" ? accept : \"any\",\n }),\n ),\n );\n\n await ctx.site.contentRepository.apply({\n changes: prepared.map((item) => ({\n type: \"write\" as const,\n path: item.file.path,\n contents: item.contents,\n })),\n });\n\n return c.json({ items: prepared.map((item) => item.file) }, 201);\n });\n\n /**\n * Serves a file to the editor, behind the admin gate. The site build reads\n * the repository, not this route.\n */\n app.get(\"/file/*\", async (c) => {\n const { media } = c.get(\"ctx\").services;\n const mediaPath = c.req.path.replace(/^.*\\/file\\//, \"\");\n\n let decoded: string;\n try {\n decoded = decodeURIComponent(mediaPath);\n } catch {\n throw badRequest(\"The file path is not valid.\");\n }\n\n const found = await media.read(decoded);\n if (!found) throw notFound(\"No such file.\");\n\n return c.body(found.bytes as unknown as ArrayBuffer, 200, {\n // Text without a charset is decoded by guessing; the repository's text is UTF-8.\n \"content-type\": found.mimeType.startsWith(\"text/\") ? `${found.mimeType}; charset=utf-8` : found.mimeType,\n \"cache-control\": \"private, max-age=60\",\n // A file opened directly runs nothing and reaches nothing on this origin.\n \"content-security-policy\": \"sandbox; default-src 'none'\",\n // An image is shown as a preview; anything else is downloaded, never rendered here.\n ...(isImageType(found.mimeType) ? {} : { \"content-disposition\": \"attachment\" }),\n });\n });\n\n return app;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"admin-spa.js","sourceRoot":"","sources":["../../src/routes/admin-spa.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"admin-spa.js","sourceRoot":"","sources":["../../src/routes/admin-spa.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Serves the built administration SPA.\n *\n * Small enough to do directly rather than pull in a static-file middleware,\n * and doing it here means the caching rules are explicit: hashed asset files\n * are immutable, `index.html` never is — otherwise a deploy leaves editors on\n * a stale bundle pointing at assets that no longer exist.\n */\n\nimport fs from \"node:fs\";\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { Readable } from \"node:stream\";\n\nimport { Hono, type Context } from \"hono\";\n\nimport type { Env } from \"../http.js\";\n\nconst CONTENT_TYPES: Record<string, string> = {\n \".html\": \"text/html; charset=utf-8\",\n \".js\": \"text/javascript; charset=utf-8\",\n \".css\": \"text/css; charset=utf-8\",\n \".json\": \"application/json; charset=utf-8\",\n \".svg\": \"image/svg+xml\",\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".webp\": \"image/webp\",\n \".ico\": \"image/x-icon\",\n \".woff2\": \"font/woff2\",\n \".woff\": \"font/woff\",\n \".map\": \"application/json; charset=utf-8\",\n};\n\nexport function adminAssetsExist(directory: string): boolean {\n return fs.existsSync(path.join(directory, \"index.html\"));\n}\n\nexport function adminSpaRoutes(directory: string): Hono<Env> {\n const app = new Hono<Env>();\n const root = path.resolve(directory);\n\n const send = async (c: Context<Env>, filePath: string, immutable: boolean) => {\n const stat = await fsp.stat(filePath);\n const extension = path.extname(filePath).toLowerCase();\n\n return c.body(Readable.toWeb(fs.createReadStream(filePath)) as ReadableStream<Uint8Array>, 200, {\n \"content-type\": CONTENT_TYPES[extension] ?? \"application/octet-stream\",\n \"content-length\": String(stat.size),\n \"cache-control\": immutable\n ? \"public, max-age=31536000, immutable\"\n : \"no-cache, must-revalidate\",\n });\n };\n\n app.get(\"/*\", async (c) => {\n const url = new URL(c.req.url);\n const relative = decodeURIComponent(url.pathname.replace(/^\\/admin\\/?/, \"\"));\n const target = path.join(root, relative);\n\n // Never serve outside the build directory, whatever the path contains.\n if (relative && !path.relative(root, target).startsWith(\"..\")) {\n try {\n const stat = await fsp.stat(target);\n if (stat.isFile()) {\n // Vite emits hashed filenames under /assets, so those are immutable.\n return await send(c, target, relative.startsWith(\"assets/\"));\n }\n } catch {\n // Fall through to the SPA entry point.\n }\n }\n\n // Any other path belongs to the client-side router.\n try {\n return await send(c, path.join(root, \"index.html\"), false);\n } catch {\n return c.text(\"The admin interface has not been built. Run `rush build`.\", 503);\n }\n });\n\n return app;\n}\n"]}
@@ -1,13 +1,8 @@
1
1
  /**
2
- * Admin staging routes — the pending change set, and Publish.
3
- *
4
- * Thin, like the content routes: the two staging implementations own every
5
- * rule, and what happens here is parsing and the mapping of their refusals
6
- * onto the API's error envelope.
7
- *
8
- * `committed-pending-push` is a 200, deliberately. The commit is real and the
9
- * state is recoverable by design; an error status would make the editor treat
10
- * a publication that half-happened as one that did not happen at all.
2
+ * Admin routes for the pending changes and Publish. Sync and conflict
3
+ * resolution exist only for a clone that Mica keeps. `committed-pending-push`
4
+ * is a 200: the commit is real, and an error status would tell the editor that
5
+ * nothing happened.
11
6
  */
12
7
  import { Hono } from "hono";
13
8
  import { type Env } from "../http.js";
@@ -1 +1 @@
1
- {"version":3,"file":"admin-staging.d.ts","sourceRoot":"","sources":["../../src/routes/admin-staging.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B,OAAO,EAAW,KAAK,GAAG,EAAE,MAAM,YAAY,CAAC;AAqC/C,wBAAgB,kBAAkB,IAAI,IAAI,CAAC,GAAG,CAAC,CAuD9C"}
1
+ {"version":3,"file":"admin-staging.d.ts","sourceRoot":"","sources":["../../src/routes/admin-staging.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,OAAO,EAAW,KAAK,GAAG,EAAE,MAAM,YAAY,CAAC;AA4C/C,wBAAgB,kBAAkB,IAAI,IAAI,CAAC,GAAG,CAAC,CAuE9C"}