@micacms/runtime 0.5.0-rc.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/app.js.map +1 -1
  2. package/dist/config.js.map +1 -1
  3. package/dist/context.d.ts +2 -0
  4. package/dist/context.d.ts.map +1 -1
  5. package/dist/context.js +7 -1
  6. package/dist/context.js.map +1 -1
  7. package/dist/http.js.map +1 -1
  8. package/dist/index.d.ts +1 -1
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +1 -1
  11. package/dist/index.js.map +1 -1
  12. package/dist/lib/errors.js.map +1 -1
  13. package/dist/lib/file-type.js.map +1 -1
  14. package/dist/lib/id.js.map +1 -1
  15. package/dist/lib/logger.js.map +1 -1
  16. package/dist/lib/ports.js.map +1 -1
  17. package/dist/lib/rate-limit.js.map +1 -1
  18. package/dist/lib/schema-stats.js.map +1 -1
  19. package/dist/lib/version.js.map +1 -1
  20. package/dist/middleware/index.js.map +1 -1
  21. package/dist/routes/admin-content.js +2 -2
  22. package/dist/routes/admin-content.js.map +1 -1
  23. package/dist/routes/admin-media.d.ts.map +1 -1
  24. package/dist/routes/admin-media.js +6 -1
  25. package/dist/routes/admin-media.js.map +1 -1
  26. package/dist/routes/admin-spa.js.map +1 -1
  27. package/dist/routes/admin-staging.js.map +1 -1
  28. package/dist/routes/admin-system.d.ts.map +1 -1
  29. package/dist/routes/admin-system.js +2 -0
  30. package/dist/routes/admin-system.js.map +1 -1
  31. package/dist/routes/health.js.map +1 -1
  32. package/dist/schema.d.ts +9 -3
  33. package/dist/schema.d.ts.map +1 -1
  34. package/dist/schema.js +45 -10
  35. package/dist/schema.js.map +1 -1
  36. package/dist/server.js.map +1 -1
  37. package/dist/services/changes.js.map +1 -1
  38. package/dist/services/content-store.d.ts +6 -1
  39. package/dist/services/content-store.d.ts.map +1 -1
  40. package/dist/services/content-store.js +16 -5
  41. package/dist/services/content-store.js.map +1 -1
  42. package/dist/services/media.js.map +1 -1
  43. package/dist/services/staging.d.ts +2 -0
  44. package/dist/services/staging.d.ts.map +1 -1
  45. package/dist/services/staging.js +8 -0
  46. package/dist/services/staging.js.map +1 -1
  47. package/dist/workspace/developer.js.map +1 -1
  48. package/dist/workspace/files.js.map +1 -1
  49. package/dist/workspace/git.js.map +1 -1
  50. package/dist/workspace/locks.js.map +1 -1
  51. package/dist/workspace/policy.js.map +1 -1
  52. package/dist/workspace/tree.js.map +1 -1
  53. package/package.json +2 -2
package/dist/app.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Assembles the app: health, the admin API and the admin SPA. There is no\n * public content API and no `/media/*`; a website builds from the repository,\n * not from this server. Authentication comes from the composing app.\n */\n\nimport { Hono } from \"hono\";\nimport { cors } from \"hono/cors\";\nimport type { MiddlewareHandler } from \"hono\";\n\nimport type { RuntimeContext } from \"./context.js\";\nimport type { Env } from \"./http.js\";\nimport {\n allowedOrigins,\n errorHandler,\n originGuard,\n requestSizeLimit,\n rateLimit,\n requestContext,\n securityHeaders,\n} from \"./middleware/index.js\";\nimport { adminContentRoutes } from \"./routes/admin-content.js\";\nimport { adminMediaRoutes } from \"./routes/admin-media.js\";\nimport { adminSpaRoutes, adminAssetsExist } from \"./routes/admin-spa.js\";\nimport { adminStagingRoutes } from \"./routes/admin-staging.js\";\nimport { adminSystemRoutes } from \"./routes/admin-system.js\";\nimport { healthRoutes } from \"./routes/health.js\";\n\n/** What a composing app contributes around the auth-neutral runtime. */\nexport interface AuthSurface {\n /** Mounted at `/api/auth`: sign-in, callback, logout, whatever auth needs. */\n routes: Hono<Env>;\n /** Applied before every `/api/admin` route. Must set `access` or refuse the request. */\n gate: MiddlewareHandler<Env>[];\n}\n\n/**\n * Allows every request with no identity. Safe only because the local editor is\n * loopback-bound and Host-guarded.\n */\nexport function allowAll(): MiddlewareHandler<Env> {\n return async (c, next) => {\n c.set(\"access\", { identity: null });\n await next();\n };\n}\n\n/** `/api/auth/config` with nothing behind it: the SPA's cue to skip sign-in. */\nfunction unauthenticatedSurface(): AuthSurface {\n const routes = new Hono<Env>();\n routes.get(\"/config\", (c) => c.json({ authRequired: false, provider: null }));\n return { routes, gate: [allowAll()] };\n}\n\nexport interface CreateAppOptions {\n /** Absent means the unauthenticated local surface. */\n auth?: AuthSurface;\n /**\n * Middleware in front of everything, so the local editor's Host allowlist\n * also guards the health endpoints.\n */\n guards?: MiddlewareHandler<Env>[];\n adminDir?: string;\n}\n\nexport function createApp(ctx: RuntimeContext, options: CreateAppOptions = {}): Hono<Env> {\n const app = new Hono<Env>();\n const auth = options.auth ?? unauthenticatedSurface();\n\n app.use(\"*\", requestContext(ctx));\n for (const guard of options.guards ?? []) app.use(\"*\", guard);\n app.use(\"*\", securityHeaders());\n app.onError(errorHandler());\n\n app.route(\"/\", healthRoutes());\n\n // Only for the Vite dev server on another origin; in production the SPA is same-origin.\n if (ctx.config.adminOrigins.length > 0) {\n app.use(\n \"/api/*\",\n cors({\n origin: allowedOrigins(ctx.config),\n credentials: true,\n allowHeaders: [\"content-type\", \"x-csrf-token\"],\n allowMethods: [\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", \"OPTIONS\"],\n }),\n );\n }\n\n app.use(\"/api/*\", rateLimit());\n app.use(\"/api/*\", originGuard());\n app.use(\"/api/*\", requestSizeLimit());\n\n app.route(\"/api/auth\", auth.routes);\n\n // One gate and no roles: whoever the surface admits is an editor of this site.\n for (const middleware of auth.gate) app.use(\"/api/admin/*\", middleware);\n\n app.route(\"/api/admin\", adminSystemRoutes());\n app.route(\"/api/admin\", adminContentRoutes());\n app.route(\"/api/admin\", adminStagingRoutes());\n app.route(\"/api/admin/media\", adminMediaRoutes());\n\n app.all(\"/api/*\", (c) =>\n c.json({ error: { code: \"not_found\" as const, message: \"No such endpoint.\" } }, 404),\n );\n\n const adminDir = options.adminDir ?? ctx.config.ADMIN_DIR;\n\n if (adminDir && adminAssetsExist(adminDir)) {\n app.route(\"/admin\", adminSpaRoutes(adminDir));\n } else {\n app.get(\"/admin/*\", (c) =>\n c.text(\n \"The admin interface has not been built.\\n\" +\n \"Run `rush build`, or use `rush dev` and open the Vite dev server.\",\n 503,\n ),\n );\n }\n\n app.get(\"/\", (c) => c.redirect(\"/admin/\"));\n\n app.notFound((c) => c.text(\"Not found\", 404));\n\n return app;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The environment variables the runtime reads. There is no `loadConfig`: each\n * app builds its own schema from `runtimeEnv`, because the variables and\n * defaults are what make one app different from another.\n */\n\nimport path from \"node:path\";\nimport { z } from \"zod\";\n\nimport { DEFAULT_BASE_URL, DEFAULT_PORT } from \"./lib/ports.js\";\n\n/** In Zod 4, `.default` takes the output value and skips the transform. */\nexport const bool = (fallback: boolean) =>\n z\n .enum([\"true\", \"false\", \"1\", \"0\"])\n .transform((value) => value === \"true\" || value === \"1\")\n .default(fallback);\n\n/** Splits a comma-separated list, trims entries and drops empty ones. */\nexport const list = (value: string | undefined): string[] =>\n (value ?? \"\")\n .split(\",\")\n .map((entry) => entry.trim())\n .filter(Boolean);\n\nexport class ConfigError extends Error {\n override name = \"ConfigError\";\n}\n\n/** Hostnames that are this machine, and nowhere else. */\nexport const LOOPBACK = new Set([\"localhost\", \"127.0.0.1\", \"[::1]\", \"::1\", \"0:0:0:0:0:0:0:1\"]);\n\n/** The variables the runtime itself reads. Apps spread this into their schema. */\nexport const runtimeEnv = {\n NODE_ENV: z.enum([\"development\", \"test\", \"production\"]).default(\"development\"),\n LOG_LEVEL: z.enum([\"debug\", \"info\", \"warn\", \"error\", \"silent\"]).default(\"info\"),\n\n /** The listen address. The app sets the default. */\n HOST: z.string().optional(),\n PORT: z.coerce.number().int().min(1).max(65535).default(DEFAULT_PORT),\n\n /** Public origin of the CMS itself. Used for cookies, CORS and media URLs. */\n MICA_PUBLIC_URL: z.string().url().default(DEFAULT_BASE_URL),\n\n /** The content root this Mica serves: a directory in a Git working tree. */\n CONTENT_ROOT: z.string().default(\"../../examples/muster-consulting/content\"),\n\n /** `false` disables commit and push: Publish shows the pending changes read-only. */\n MICA_LOCAL_PUBLISH: bool(true),\n\n MAX_UPLOAD_BYTES: z.coerce\n .number()\n .int()\n .positive()\n .default(25 * 1024 * 1024),\n\n /** Read the client IP from X-Forwarded-For. Only enable behind a proxy. */\n TRUST_PROXY: bool(false),\n /** Extra browser origins allowed to call the admin API (dev Vite server). */\n ADMIN_ORIGINS: z.string().optional(),\n /** Overrides where the built admin SPA is served from. */\n ADMIN_DIR: z.string().optional(),\n};\n\nconst runtimeSchema = z.object(runtimeEnv);\nexport type RuntimeEnv = z.infer<typeof runtimeSchema>;\n\n/**\n * Adds the derived values to the parsed environment. Each app calls it from its\n * own `transform`.\n */\nexport function deriveRuntime<T extends RuntimeEnv>(env: T) {\n return {\n ...env,\n isProduction: env.NODE_ENV === \"production\",\n contentRoot: path.resolve(env.CONTENT_ROOT),\n adminOrigins: list(env.ADMIN_ORIGINS),\n };\n}\n\n/** What the runtime requires of a finished configuration. */\nexport type RuntimeConfig = ReturnType<typeof deriveRuntime<RuntimeEnv>> & {\n /** Resolved by the app: the runtime never guesses an address. */\n HOST: string;\n};\n\n/** Loads `./.env` into `process.env`. Variables that are already set win. */\nexport function loadEnvFile(): void {\n try {\n process.loadEnvFile();\n } catch (error) {\n // A missing `.env` is normal; an unreadable or malformed one must not start\n // the server with defaults.\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw new ConfigError(`Could not read .env: ${(error as Error).message}`);\n }\n }\n}\n\n/** Treats a blank variable as unset, so a verbatim copy of `.env.example` with blanks is valid. */\nexport function withoutBlanks(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n return Object.fromEntries(\n Object.entries(env).filter(([, value]) => value !== undefined && value.trim() !== \"\"),\n );\n}\n\n/** Formats a Zod refusal the way a person at a terminal reads it. */\nexport function describeConfigIssues(error: z.ZodError): string {\n const details = error.issues\n .map((issue) => ` ${issue.path.join(\".\") || \"(root)\"}: ${issue.message}`)\n .join(\"\\n\");\n return `Invalid environment configuration:\\n${details}`;\n}\n"]}
package/dist/context.d.ts CHANGED
@@ -27,6 +27,8 @@ export interface SiteContext {
27
27
  * drift gate compares against it.
28
28
  */
29
29
  schemaRevision: string | null;
30
+ /** Collections and singletons this build cannot write, from `readOnlyParts`, with the reason. */
31
+ readOnly: ReadonlyMap<string, string>;
30
32
  }
31
33
  export declare const DEFAULT_SITE_ID = "default";
32
34
  /** Facts about the composition that the System page shows and the runtime cannot know. */
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
package/dist/context.js CHANGED
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import { createLogger } from "./lib/logger.js";
7
7
  import { createRateLimiter } from "./lib/rate-limit.js";
8
+ import { readOnlyParts } from "./schema.js";
8
9
  import { createMediaService } from "./services/media.js";
9
10
  import { createContentStore } from "./services/content-store.js";
10
11
  import { createWorkingTreeStagingService } from "./services/staging.js";
@@ -20,14 +21,18 @@ export function createRuntimeContext(options) {
20
21
  const schemaRevision = options.schemaRevision ?? null;
21
22
  // Services write through the lock wrapper; staging takes the locks itself.
22
23
  const locks = options.locks ?? createWorkspaceLocks();
24
+ const readOnly = readOnlyParts(model);
25
+ for (const reason of readOnly.values())
26
+ logger.warn("Read-only in this version of Mica", { reason });
23
27
  const site = {
24
28
  id: options.siteId ?? DEFAULT_SITE_ID,
25
29
  model,
26
30
  contentRepository: lockedFiles(options.files, locks.tree),
27
31
  schemaRevision,
32
+ readOnly,
28
33
  };
29
34
  const services = {
30
- content: createContentStore(model, site.contentRepository),
35
+ content: createContentStore(model, site.contentRepository, readOnly),
31
36
  media: createMediaService({
32
37
  files: site.contentRepository,
33
38
  maxBytes: config.MAX_UPLOAD_BYTES,
@@ -37,6 +42,7 @@ export function createRuntimeContext(options) {
37
42
  files: options.files,
38
43
  contentRoot: config.contentRoot,
39
44
  schemaRevision,
45
+ readOnly,
40
46
  publishEnabled: config.MICA_LOCAL_PUBLISH,
41
47
  logger,
42
48
  locks,
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAAE,YAAY,EAAe,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAoB,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAqB,MAAM,qBAAqB,CAAC;AAE5E,OAAO,EAAE,kBAAkB,EAAqB,MAAM,6BAA6B,CAAC;AACpF,OAAO,EAAE,+BAA+B,EAAE,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAuB,MAAM,sBAAsB,CAAC;AAoB9F,MAAM,CAAC,MAAM,eAAe,GAAG,SAAS,CAAC;AA6DzC,MAAM,UAAU,oBAAoB,CAAC,OAAoC;IACvE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;IAElC,MAAM,MAAM,GACV,OAAO,CAAC,MAAM;QACd,YAAY,CAAC;YACX,KAAK,EAAE,MAAM,CAAC,SAAS;YACvB,MAAM,EAAE,CAAC,MAAM,CAAC,YAAY;SAC7B,CAAC,CAAC;IAEL,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,IAAI,CAAC;IAEtD,2EAA2E;IAC3E,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,oBAAoB,EAAE,CAAC;IAEtD,MAAM,IAAI,GAAgB;QACxB,EAAE,EAAE,OAAO,CAAC,MAAM,IAAI,eAAe;QACrC,KAAK;QACL,iBAAiB,EAAE,WAAW,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC;QACzD,cAAc;KACf,CAAC;IAEF,MAAM,QAAQ,GAAG;QACf,OAAO,EAAE,kBAAkB,CAAC,KAAK,EAAE,IAAI,CAAC,iBAAiB,CAAC;QAC1D,KAAK,EAAE,kBAAkB,CAAC;YACxB,KAAK,EAAE,IAAI,CAAC,iBAAiB;YAC7B,QAAQ,EAAE,MAAM,CAAC,gBAAgB;SAClC,CAAC;QACF,OAAO,EAAE,+BAA+B,CAAC;YACvC,KAAK;YACL,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,cAAc;YACd,cAAc,EAAE,MAAM,CAAC,kBAAkB;YACzC,MAAM;YACN,KAAK;YACL,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrD,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAChD,CAAC;KACH,CAAC;IAEF,MAAM,QAAQ,GAAG;QACf,iEAAiE;QACjE,GAAG,EAAE,iBAAiB,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;KACzD,CAAC;IAEF,OAAO;QACL,MAAM;QACN,IAAI;QACJ,MAAM;QACN,QAAQ;QACR,QAAQ;QACR,WAAW,EACT,OAAO,CAAC,WAAW;YACnB,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC;QACnC,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE;QAE5B,KAAK,CAAC,QAAQ;YACZ,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YACpB,MAAM,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;QAC/B,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Builds the runtime's services for one site, with no module-level singletons.\n * The app supplies the working tree's files and the owner policy, so the\n * runtime stays authentication-neutral.\n */\n\nimport type { Site } from \"@micacms/core\";\n\nimport type { RuntimeConfig } from \"./config.js\";\nimport { createLogger, type Logger } from \"./lib/logger.js\";\nimport { createRateLimiter, type RateLimiter } from \"./lib/rate-limit.js\";\nimport { readOnlyParts } from \"./schema.js\";\nimport { createMediaService, type MediaService } from \"./services/media.js\";\nimport type { ContentStagingService } from \"./services/changes.js\";\nimport { createContentStore, type ContentStore } from \"./services/content-store.js\";\nimport { createWorkingTreeStagingService } from \"./services/staging.js\";\nimport { createWorkspaceLocks, lockedFiles, type WorkspaceLocks } from \"./workspace/locks.js\";\nimport type { OwnerPolicy } from \"./workspace/policy.js\";\nimport type { ContentFiles } from \"./workspace/files.js\";\nimport type { GitTree } from \"./workspace/tree.js\";\n\n/** The one site this process serves. Several sites means several processes. */\nexport interface SiteContext {\n /** Identifies this site in logs. */\n id: string;\n /** The content model, read from the repository at startup. */\n model: Site;\n /** The working tree's files behind the workspace locks. Only Publish makes a commit. */\n contentRepository: ContentFiles;\n /**\n * Revision of `.mica/schema.json` when the model was loaded. The publish\n * drift gate compares against it.\n */\n schemaRevision: string | null;\n /** Collections and singletons this build cannot write, from `readOnlyParts`, with the reason. */\n readOnly: ReadonlyMap<string, string>;\n}\n\nexport const DEFAULT_SITE_ID = \"default\";\n\n/** Facts about the composition that the System page shows and the runtime cannot know. */\nexport interface OperationalInfo {\n /** How this deployment authenticates, in words. */\n auth: string;\n /** What decides who may edit, in the operator's own words. */\n admission?: string;\n dataDir?: string;\n sessionTtlHours?: number;\n sessionIdleHours?: number;\n /** Names of the secrets this process generated for itself. */\n generatedSecrets?: string[];\n}\n\n/** What /ready asks the composition. */\nexport interface RuntimeHealth {\n /**\n * Whether the site can be edited, with short reason codes. Never names the\n * repository: the endpoint is public.\n */\n ready?: () => { ok: boolean; reasons: string[] };\n}\n\nexport interface RuntimeContext {\n config: RuntimeConfig;\n site: SiteContext;\n logger: Logger;\n services: {\n content: ContentStore;\n media: MediaService;\n staging: ContentStagingService;\n };\n limiters: {\n api: RateLimiter;\n };\n operational(): OperationalInfo;\n health: RuntimeHealth;\n shutdown(): Promise<void>;\n}\n\nexport interface CreateRuntimeContextOptions {\n config: RuntimeConfig;\n model: Site;\n /** The working tree's files, without locks. The app builds it. */\n files: ContentFiles;\n /** Revision of the manifest the model was read from. Null when unknown. */\n schemaRevision?: string | null;\n siteId?: string;\n logger?: Logger;\n operational?: () => OperationalInfo;\n health?: RuntimeHealth;\n /** Who owns the working tree. Defaults to the developer. */\n policy?: OwnerPolicy;\n /** Shared with the owner's own work on the tree, such as a sync. */\n locks?: WorkspaceLocks;\n /** See `WorkingTreeStagingDeps.tree`. */\n tree?: GitTree;\n onShutdown?: () => void | Promise<void>;\n}\n\nexport function createRuntimeContext(options: CreateRuntimeContextOptions): RuntimeContext {\n const { config, model } = options;\n\n const logger =\n options.logger ??\n createLogger({\n level: config.LOG_LEVEL,\n pretty: !config.isProduction,\n });\n\n const schemaRevision = options.schemaRevision ?? null;\n\n // Services write through the lock wrapper; staging takes the locks itself.\n const locks = options.locks ?? createWorkspaceLocks();\n\n const readOnly = readOnlyParts(model);\n for (const reason of readOnly.values()) logger.warn(\"Read-only in this version of Mica\", { reason });\n\n const site: SiteContext = {\n id: options.siteId ?? DEFAULT_SITE_ID,\n model,\n contentRepository: lockedFiles(options.files, locks.tree),\n schemaRevision,\n readOnly,\n };\n\n const services = {\n content: createContentStore(model, site.contentRepository, readOnly),\n media: createMediaService({\n files: site.contentRepository,\n maxBytes: config.MAX_UPLOAD_BYTES,\n }),\n staging: createWorkingTreeStagingService({\n model,\n files: options.files,\n contentRoot: config.contentRoot,\n schemaRevision,\n readOnly,\n publishEnabled: config.MICA_LOCAL_PUBLISH,\n logger,\n locks,\n ...(options.policy ? { policy: options.policy } : {}),\n ...(options.tree ? { tree: options.tree } : {}),\n }),\n };\n\n const limiters = {\n // Generous: it stops runaway scripts, it does not shape traffic.\n api: createRateLimiter({ limit: 600, windowMs: 60_000 }),\n };\n\n return {\n config,\n site,\n logger,\n services,\n limiters,\n operational:\n options.operational ??\n (() => ({ auth: \"unspecified\" })),\n health: options.health ?? {},\n\n async shutdown() {\n limiters.api.stop();\n await options.onShutdown?.();\n },\n };\n}\n"]}
package/dist/http.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAoBA;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,CAAe;IACtC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAEhC,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;QAClD,MAAM,IAAI,GAAG,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;QAClD,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC;IACxB,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,CAAC,GAAyE,CAAC;IACzF,OAAO,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,IAAI,SAAS,CAAC;AAC5D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,OAAO,CAAC,CAAe;IACrC,MAAM,QAAQ,GAAG,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAC3C,OAAO,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,CAAC,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAChG,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,QAAQ,CAAC,KAAyB,EAAE,QAAgB,EAAE,GAAW;IAC/E,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC5D,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;AAC3C,CAAC"}
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAoBA;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,CAAe;IACtC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAEhC,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;QAClD,MAAM,IAAI,GAAG,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;QAClD,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC;IACxB,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,CAAC,GAAyE,CAAC;IACzF,OAAO,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,IAAI,SAAS,CAAC;AAC5D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,OAAO,CAAC,CAAe;IACrC,MAAM,QAAQ,GAAG,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAC3C,OAAO,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,CAAC,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAChG,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,QAAQ,CAAC,KAAyB,EAAE,QAAgB,EAAE,GAAW;IAC/E,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC5D,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;AAC3C,CAAC","sourcesContent":["import type { Context } from \"hono\";\n\nimport type { AccessContext } from \"@micacms/core\";\n\nimport type { RuntimeContext } from \"./context.js\";\nimport type { Logger } from \"./lib/logger.js\";\n\nexport interface Env {\n Variables: {\n ctx: RuntimeContext;\n logger: Logger;\n requestId: string;\n /**\n * Who this request acts as. The auth surface's gate sets it on every admin\n * route; the runtime never sets it.\n */\n access: AccessContext;\n };\n}\n\n/**\n * Client IP. Reads `X-Forwarded-For` only with TRUST_PROXY, or a client could\n * spoof its address past the rate limit. The right-most entry is the address\n * the proxy saw; the entries to its left come from the client.\n */\nexport function clientIp(c: Context<Env>): string {\n const { config } = c.get(\"ctx\");\n\n if (config.TRUST_PROXY) {\n const forwarded = c.req.header(\"x-forwarded-for\");\n const last = forwarded?.split(\",\").at(-1)?.trim();\n if (last) return last;\n }\n\n const info = c.env as { incoming?: { socket?: { remoteAddress?: string } } } | undefined;\n return info?.incoming?.socket?.remoteAddress ?? \"unknown\";\n}\n\n/**\n * The commit author. Null in the local editor, where the commit keeps the\n * developer's own Git identity.\n */\nexport function actorOf(c: Context<Env>): { id: string; email: string; name: string } | null {\n const identity = c.get(\"access\")?.identity;\n return identity ? { id: identity.subject, email: identity.email, name: identity.name } : null;\n}\n\n/** Parses a positive integer query parameter, falling back when absent. */\nexport function intParam(value: string | undefined, fallback: number, max: number): number {\n const parsed = Number(value);\n if (!Number.isFinite(parsed) || parsed < 0) return fallback;\n return Math.min(Math.floor(parsed), max);\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -7,7 +7,7 @@ export { createRuntimeContext, DEFAULT_SITE_ID, type CreateRuntimeContextOptions
7
7
  export { bool, ConfigError, deriveRuntime, describeConfigIssues, list, loadEnvFile, LOOPBACK, runtimeEnv, withoutBlanks, type RuntimeConfig, type RuntimeEnv, } from "./config.js";
8
8
  export { startServer, type StartServerOptions } from "./server.js";
9
9
  export { actorOf, clientIp, intParam, type Env } from "./http.js";
10
- export { checkSchema, loadSchema, SchemaError, schemaFingerprint, schemaOrigin } from "./schema.js";
10
+ export { checkSchema, loadSchema, readOnlyParts, SchemaError, schemaFingerprint, schemaOrigin } from "./schema.js";
11
11
  export { allowedOrigins, errorHandler, originGuard, rateLimit, requestContext, securityHeaders, } from "./middleware/index.js";
12
12
  export { adminAssetsExist } from "./routes/admin-spa.js";
13
13
  export { ApiError, badRequest, conflict, forbidden, notFound, unauthenticated, validationFailed, type ApiErrorBody, type ErrorCode, } from "./lib/errors.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACxF,OAAO,EACL,oBAAoB,EACpB,eAAe,EACf,KAAK,2BAA2B,EAChC,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,WAAW,GACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,IAAI,EACJ,WAAW,EACX,aAAa,EACb,oBAAoB,EACpB,IAAI,EACJ,WAAW,EACX,QAAQ,EACR,UAAU,EACV,aAAa,EACb,KAAK,aAAa,EAClB,KAAK,UAAU,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,GAAG,EAAE,MAAM,WAAW,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,WAAW,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACnH,OAAO,EACL,cAAc,EACd,YAAY,EACZ,WAAW,EACX,SAAS,EACT,cAAc,EACd,eAAe,GAChB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EACL,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,eAAe,EACf,gBAAgB,EAChB,KAAK,YAAY,EACjB,KAAK,SAAS,GACf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,YAAY,EAAE,KAAK,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EACL,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,qBAAqB,EAC1B,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,iBAAiB,GACvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,+BAA+B,EAC/B,KAAK,sBAAsB,GAC5B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,KAAK,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACzG,OAAO,EACL,kBAAkB,EAClB,YAAY,EACZ,eAAe,EACf,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,cAAc,GACpB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,UAAU,EACV,KAAK,MAAM,EACX,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,KAAK,UAAU,EACf,KAAK,WAAW,GACjB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,oBAAoB,EACpB,SAAS,EACT,QAAQ,EACR,SAAS,EACT,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,gBAAgB,GACtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,oBAAoB,EACpB,WAAW,EACX,KAAK,KAAK,EACV,KAAK,aAAa,EAClB,KAAK,cAAc,GACpB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EACV,WAAW,EACX,mBAAmB,EACnB,qBAAqB,EACrB,YAAY,EACZ,UAAU,GACX,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AACxF,OAAO,EACL,WAAW,EACX,YAAY,EACZ,UAAU,EACV,MAAM,EACN,eAAe,EACf,OAAO,EACP,UAAU,EACV,WAAW,EACX,aAAa,EACb,KAAK,OAAO,EACZ,KAAK,UAAU,GAChB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC"}
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ export { createRuntimeContext, DEFAULT_SITE_ID, } from "./context.js";
7
7
  export { bool, ConfigError, deriveRuntime, describeConfigIssues, list, loadEnvFile, LOOPBACK, runtimeEnv, withoutBlanks, } from "./config.js";
8
8
  export { startServer } from "./server.js";
9
9
  export { actorOf, clientIp, intParam } from "./http.js";
10
- export { checkSchema, loadSchema, SchemaError, schemaFingerprint, schemaOrigin } from "./schema.js";
10
+ export { checkSchema, loadSchema, readOnlyParts, SchemaError, schemaFingerprint, schemaOrigin } from "./schema.js";
11
11
  export { allowedOrigins, errorHandler, originGuard, rateLimit, requestContext, securityHeaders, } from "./middleware/index.js";
12
12
  export { adminAssetsExist } from "./routes/admin-spa.js";
13
13
  export { ApiError, badRequest, conflict, forbidden, notFound, unauthenticated, validationFailed, } from "./lib/errors.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,QAAQ,EAA2C,MAAM,UAAU,CAAC;AACxF,OAAO,EACL,oBAAoB,EACpB,eAAe,GAMhB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,IAAI,EACJ,WAAW,EACX,aAAa,EACb,oBAAoB,EACpB,IAAI,EACJ,WAAW,EACX,QAAQ,EACR,UAAU,EACV,aAAa,GAGd,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,WAAW,EAA2B,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAY,MAAM,WAAW,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACpG,OAAO,EACL,cAAc,EACd,YAAY,EACZ,WAAW,EACX,SAAS,EACT,cAAc,EACd,eAAe,GAChB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EACL,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,eAAe,EACf,gBAAgB,GAGjB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,YAAY,EAAe,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAoB,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EACL,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,eAAe,GAShB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,+BAA+B,GAEhC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAqC,MAAM,qBAAqB,CAAC;AACzG,OAAO,EACL,kBAAkB,EAClB,YAAY,EACZ,eAAe,GAIhB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,UAAU,GAMX,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,oBAAoB,EACpB,SAAS,EACT,QAAQ,EACR,SAAS,GAIV,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,oBAAoB,EACpB,WAAW,GAIZ,MAAM,sBAAsB,CAAC;AAQ9B,OAAO,EAAE,eAAe,EAA+B,MAAM,0BAA0B,CAAC;AACxF,OAAO,EACL,WAAW,EACX,YAAY,EACZ,UAAU,EACV,MAAM,EACN,eAAe,EACf,OAAO,EACP,UAAU,EACV,WAAW,EACX,aAAa,GAGd,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,QAAQ,EAA2C,MAAM,UAAU,CAAC;AACxF,OAAO,EACL,oBAAoB,EACpB,eAAe,GAMhB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,IAAI,EACJ,WAAW,EACX,aAAa,EACb,oBAAoB,EACpB,IAAI,EACJ,WAAW,EACX,QAAQ,EACR,UAAU,EACV,aAAa,GAGd,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,WAAW,EAA2B,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAY,MAAM,WAAW,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,WAAW,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACnH,OAAO,EACL,cAAc,EACd,YAAY,EACZ,WAAW,EACX,SAAS,EACT,cAAc,EACd,eAAe,GAChB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EACL,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,eAAe,EACf,gBAAgB,GAGjB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,YAAY,EAAe,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAoB,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EACL,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,eAAe,GAShB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,+BAA+B,GAEhC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAqC,MAAM,qBAAqB,CAAC;AACzG,OAAO,EACL,kBAAkB,EAClB,YAAY,EACZ,eAAe,GAIhB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,UAAU,GAMX,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,oBAAoB,EACpB,SAAS,EACT,QAAQ,EACR,SAAS,GAIV,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,oBAAoB,EACpB,WAAW,GAIZ,MAAM,sBAAsB,CAAC;AAQ9B,OAAO,EAAE,eAAe,EAA+B,MAAM,0BAA0B,CAAC;AACxF,OAAO,EACL,WAAW,EACX,YAAY,EACZ,UAAU,EACV,MAAM,EACN,eAAe,EACf,OAAO,EACP,UAAU,EACV,WAAW,EACX,aAAa,GAGd,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC","sourcesContent":["/**\n * @micacms/runtime: the single-site, authentication-neutral Mica runtime.\n * It must never import an auth implementation; the composing app supplies the `AuthSurface`.\n */\n\nexport { createApp, allowAll, type AuthSurface, type CreateAppOptions } from \"./app.js\";\nexport {\n createRuntimeContext,\n DEFAULT_SITE_ID,\n type CreateRuntimeContextOptions,\n type OperationalInfo,\n type RuntimeContext,\n type RuntimeHealth,\n type SiteContext,\n} from \"./context.js\";\nexport {\n bool,\n ConfigError,\n deriveRuntime,\n describeConfigIssues,\n list,\n loadEnvFile,\n LOOPBACK,\n runtimeEnv,\n withoutBlanks,\n type RuntimeConfig,\n type RuntimeEnv,\n} from \"./config.js\";\nexport { startServer, type StartServerOptions } from \"./server.js\";\nexport { actorOf, clientIp, intParam, type Env } from \"./http.js\";\nexport { checkSchema, loadSchema, readOnlyParts, SchemaError, schemaFingerprint, schemaOrigin } from \"./schema.js\";\nexport {\n allowedOrigins,\n errorHandler,\n originGuard,\n rateLimit,\n requestContext,\n securityHeaders,\n} from \"./middleware/index.js\";\nexport { adminAssetsExist } from \"./routes/admin-spa.js\";\nexport {\n ApiError,\n badRequest,\n conflict,\n forbidden,\n notFound,\n unauthenticated,\n validationFailed,\n type ApiErrorBody,\n type ErrorCode,\n} from \"./lib/errors.js\";\nexport { createLogger, type Logger } from \"./lib/logger.js\";\nexport { createRateLimiter, type RateLimiter } from \"./lib/rate-limit.js\";\nexport { randomToken } from \"./lib/id.js\";\nexport { DEFAULT_BASE_URL, DEFAULT_PORT } from \"./lib/ports.js\";\nexport { VERSION } from \"./lib/version.js\";\nexport {\n analyseChanges,\n classifyPath,\n describeProblems,\n flattenProblems,\n type AnnotatedChange,\n type ChangeOwner,\n type ContentStagingService,\n type RepositoryInfo,\n type PublishInput,\n type StagingProblem,\n type StagingStatus,\n type StagingValidation,\n} from \"./services/changes.js\";\nexport {\n createWorkingTreeStagingService,\n type WorkingTreeStagingDeps,\n} from \"./services/staging.js\";\nexport { createMediaService, formatBytes, type MediaFile, type MediaService } from \"./services/media.js\";\nexport {\n createContentStore,\n ContentError,\n ValidationError,\n type ContentStore,\n type SavedEntry,\n type SaveEntryInput,\n} from \"./services/content-store.js\";\nexport {\n checkChangePaths,\n ConflictError,\n contentFiles,\n FilesError,\n type Author,\n type ContentFiles,\n type ContentFilesOptions,\n type FileChange,\n type FileChanges,\n} from \"./workspace/files.js\";\nexport {\n developerEnvironment,\n firstLine,\n GitError,\n gitRunner,\n type GitCallOptions,\n type GitRunner,\n type GitRunnerOptions,\n} from \"./workspace/git.js\";\nexport {\n createMutex,\n createReadWriteLock,\n createWorkspaceLocks,\n lockedFiles,\n type Mutex,\n type ReadWriteLock,\n type WorkspaceLocks,\n} from \"./workspace/locks.js\";\nexport type {\n OwnerPolicy,\n PublishAvailability,\n RepositoryDescription,\n SyncConflict,\n SyncStatus,\n} from \"./workspace/policy.js\";\nexport { developerPolicy, type DeveloperPolicyOptions } from \"./workspace/developer.js\";\nexport {\n commitPaths,\n headRevision,\n headSource,\n inRepo,\n listTreeChanges,\n LITERAL,\n locateTree,\n parseStatus,\n recommitPaths,\n type GitTree,\n type TreeChange,\n} from \"./workspace/tree.js\";\nexport { schemaStats } from \"./lib/schema-stats.js\";\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/lib/errors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAmBH,MAAM,MAAM,GAA8B;IACxC,WAAW,EAAE,GAAG;IAChB,iBAAiB,EAAE,GAAG;IACtB,eAAe,EAAE,GAAG;IACpB,mBAAmB,EAAE,GAAG;IACxB,SAAS,EAAE,GAAG;IACd,SAAS,EAAE,GAAG;IACd,QAAQ,EAAE,GAAG;IACb,iBAAiB,EAAE,GAAG;IACtB,sBAAsB,EAAE,GAAG;IAC3B,YAAY,EAAE,GAAG;IACjB,cAAc,EAAE,GAAG;IACnB,mBAAmB,EAAE,GAAG;CACzB,CAAC;AAUF,MAAM,OAAO,QAAS,SAAQ,KAAK;IACxB,IAAI,GAAG,UAAU,CAAC;IAClB,IAAI,CAAY;IAChB,MAAM,CAAS;IACf,MAAM,CAAgB;IAC/B,kEAAkE;IACzD,OAAO,CAA0B;IAE1C,YACE,IAAe,EACf,OAAe,EACf,UAAwF,EAAE;QAE1F,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QAC3B,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IACjC,CAAC;IAED,MAAM;QACJ,OAAO;YACL,KAAK,EAAE;gBACL,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAChD;SACF,CAAC;IACJ,CAAC;CACF;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC,IAAI,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;AACpF,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,OAAO,GAAG,0BAA0B,EAAE,EAAE,CACtE,IAAI,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC;AAC3C,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,OAAO,GAAG,0CAA0C,EAAE,EAAE,CAChF,IAAI,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;AACrC,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,OAAO,GAAG,YAAY,EAAE,EAAE,CAAC,IAAI,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;AACvF,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC,IAAI,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;AAC/E,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,MAAoB,EAAE,OAAO,GAAG,2BAA2B,EAAE,EAAE,CAC9F,IAAI,QAAQ,CAAC,mBAAmB,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/lib/errors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAmBH,MAAM,MAAM,GAA8B;IACxC,WAAW,EAAE,GAAG;IAChB,iBAAiB,EAAE,GAAG;IACtB,eAAe,EAAE,GAAG;IACpB,mBAAmB,EAAE,GAAG;IACxB,SAAS,EAAE,GAAG;IACd,SAAS,EAAE,GAAG;IACd,QAAQ,EAAE,GAAG;IACb,iBAAiB,EAAE,GAAG;IACtB,sBAAsB,EAAE,GAAG;IAC3B,YAAY,EAAE,GAAG;IACjB,cAAc,EAAE,GAAG;IACnB,mBAAmB,EAAE,GAAG;CACzB,CAAC;AAUF,MAAM,OAAO,QAAS,SAAQ,KAAK;IACxB,IAAI,GAAG,UAAU,CAAC;IAClB,IAAI,CAAY;IAChB,MAAM,CAAS;IACf,MAAM,CAAgB;IAC/B,kEAAkE;IACzD,OAAO,CAA0B;IAE1C,YACE,IAAe,EACf,OAAe,EACf,UAAwF,EAAE;QAE1F,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QAC3B,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IACjC,CAAC;IAED,MAAM;QACJ,OAAO;YACL,KAAK,EAAE;gBACL,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAChD;SACF,CAAC;IACJ,CAAC;CACF;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC,IAAI,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;AACpF,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,OAAO,GAAG,0BAA0B,EAAE,EAAE,CACtE,IAAI,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC;AAC3C,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,OAAO,GAAG,0CAA0C,EAAE,EAAE,CAChF,IAAI,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;AACrC,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,OAAO,GAAG,YAAY,EAAE,EAAE,CAAC,IAAI,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;AACvF,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC,IAAI,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;AAC/E,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,MAAoB,EAAE,OAAO,GAAG,2BAA2B,EAAE,EAAE,CAC9F,IAAI,QAAQ,CAAC,mBAAmB,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC","sourcesContent":["/**\n * Error taxonomy.\n *\n * Every failure the API reports on purpose is an `ApiError` carrying a stable\n * machine-readable `code`. Anything else that reaches the error middleware is\n * treated as a bug: logged with its stack, reported as a bare 500.\n */\n\nimport type { FieldIssue } from \"@micacms/core\";\n\nexport type ErrorCode =\n | \"bad_request\"\n | \"validation_failed\"\n | \"unauthenticated\"\n | \"invalid_credentials\"\n | \"forbidden\"\n | \"not_found\"\n | \"conflict\"\n | \"payload_too_large\"\n | \"unsupported_media_type\"\n | \"rate_limited\"\n | \"internal_error\"\n /** An identity provider Mica depends on could not be reached. */\n | \"service_unavailable\";\n\nconst STATUS: Record<ErrorCode, number> = {\n bad_request: 400,\n validation_failed: 422,\n unauthenticated: 401,\n invalid_credentials: 401,\n forbidden: 403,\n not_found: 404,\n conflict: 409,\n payload_too_large: 413,\n unsupported_media_type: 415,\n rate_limited: 429,\n internal_error: 500,\n service_unavailable: 503,\n};\n\nexport interface ApiErrorBody {\n error: {\n code: ErrorCode;\n message: string;\n issues?: FieldIssue[];\n };\n}\n\nexport class ApiError extends Error {\n override name = \"ApiError\";\n readonly code: ErrorCode;\n readonly status: number;\n readonly issues?: FieldIssue[];\n /** Extra response headers, e.g. `Retry-After` on a rate limit. */\n readonly headers?: Record<string, string>;\n\n constructor(\n code: ErrorCode,\n message: string,\n options: { issues?: FieldIssue[]; headers?: Record<string, string>; cause?: unknown } = {},\n ) {\n super(message, { cause: options.cause });\n this.code = code;\n this.status = STATUS[code];\n this.issues = options.issues;\n this.headers = options.headers;\n }\n\n toBody(): ApiErrorBody {\n return {\n error: {\n code: this.code,\n message: this.message,\n ...(this.issues ? { issues: this.issues } : {}),\n },\n };\n }\n}\n\nexport const badRequest = (message: string) => new ApiError(\"bad_request\", message);\nexport const unauthenticated = (message = \"Authentication required.\") =>\n new ApiError(\"unauthenticated\", message);\nexport const forbidden = (message = \"You do not have access to this resource.\") =>\n new ApiError(\"forbidden\", message);\nexport const notFound = (message = \"Not found.\") => new ApiError(\"not_found\", message);\nexport const conflict = (message: string) => new ApiError(\"conflict\", message);\nexport const validationFailed = (issues: FieldIssue[], message = \"The content is not valid.\") =>\n new ApiError(\"validation_failed\", message, { issues });\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"file-type.js","sourceRoot":"","sources":["../../src/lib/file-type.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"file-type.js","sourceRoot":"","sources":["../../src/lib/file-type.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Content sniffing for uploads.\n *\n * The browser-supplied MIME type is attacker-controlled and must not be\n * trusted: an executable renamed to `.jpg` arrives as `image/jpeg`. The stored\n * type is derived from the bytes instead, and the extension is regenerated\n * from it rather than taken from the filename.\n */\n\nexport interface DetectedType {\n mimeType: string;\n extension: string;\n}\n\nconst startsWith = (bytes: Uint8Array, signature: number[], offset = 0): boolean =>\n signature.every((byte, index) => bytes[offset + index] === byte);\n\nconst ascii = (bytes: Uint8Array, offset: number, length: number): string =>\n Array.from(bytes.slice(offset, offset + length), (byte) => String.fromCharCode(byte)).join(\"\");\n\nexport function detectFileType(bytes: Uint8Array): DetectedType | null {\n if (bytes.length < 12) return null;\n\n if (startsWith(bytes, [0xff, 0xd8, 0xff])) {\n return { mimeType: \"image/jpeg\", extension: \"jpg\" };\n }\n\n if (startsWith(bytes, [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])) {\n return { mimeType: \"image/png\", extension: \"png\" };\n }\n\n const header = ascii(bytes, 0, 6);\n if (header === \"GIF87a\" || header === \"GIF89a\") {\n return { mimeType: \"image/gif\", extension: \"gif\" };\n }\n\n if (ascii(bytes, 0, 4) === \"RIFF\" && ascii(bytes, 8, 4) === \"WEBP\") {\n return { mimeType: \"image/webp\", extension: \"webp\" };\n }\n\n // ISO base media formats declare their brand at offset 8, after the box size.\n if (ascii(bytes, 4, 4) === \"ftyp\") {\n const brand = ascii(bytes, 8, 4);\n if (brand === \"avif\" || brand === \"avis\") {\n return { mimeType: \"image/avif\", extension: \"avif\" };\n }\n if (brand === \"heic\" || brand === \"heix\" || brand === \"mif1\") {\n return { mimeType: \"image/heic\", extension: \"heic\" };\n }\n if (brand === \"isom\" || brand === \"mp42\" || brand === \"M4V \") {\n return { mimeType: \"video/mp4\", extension: \"mp4\" };\n }\n }\n\n if (ascii(bytes, 0, 5) === \"%PDF-\") {\n return { mimeType: \"application/pdf\", extension: \"pdf\" };\n }\n\n if (isSvg(bytes)) {\n return { mimeType: \"image/svg+xml\", extension: \"svg\" };\n }\n\n return null;\n}\n\n/** SVG has no magic number, so look for a root `<svg>` in the leading text. */\nfunction isSvg(bytes: Uint8Array): boolean {\n const head = new TextDecoder(\"utf-8\", { fatal: false })\n .decode(bytes.slice(0, 1024))\n .trimStart()\n .toLowerCase();\n\n if (head.startsWith(\"<svg\")) return true;\n if (head.startsWith(\"<?xml\") || head.startsWith(\"<!doctype svg\")) {\n return head.includes(\"<svg\");\n }\n return false;\n}\n\nconst IMAGE_TYPES = new Set([\n \"image/jpeg\",\n \"image/png\",\n \"image/gif\",\n \"image/webp\",\n \"image/avif\",\n \"image/heic\",\n]);\n\nconst DOCUMENT_TYPES = new Set([\"application/pdf\"]);\n\nexport const isImageType = (mimeType: string): boolean => IMAGE_TYPES.has(mimeType);\n\n/**\n * Whether a detected type is acceptable for a field's `accept` setting.\n * `any` deliberately does not mean \"anything\": only the types listed here can\n * be stored at all.\n */\nexport function isAccepted(mimeType: string, accept: \"image\" | \"document\" | \"any\"): boolean {\n if (accept === \"image\") return IMAGE_TYPES.has(mimeType);\n if (accept === \"document\") return DOCUMENT_TYPES.has(mimeType);\n return IMAGE_TYPES.has(mimeType) || DOCUMENT_TYPES.has(mimeType) || mimeType === \"video/mp4\";\n}\n\n/**\n * SVG can carry scripts, so Mica neither stores nor shows it (#86). It is still\n * detected, so that the refusal can say why.\n */\nexport const SVG_TYPE = \"image/svg+xml\";\n"]}
@@ -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":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,GAKlB,MAAM,eAAe,CAAC;AAsDvB,sDAAsD;AACtD,SAAS,QAAQ,CAAC,KAAe;IAC/B,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AACpF,CAAC;AAED;;;;;GAKG;AACH,SAAS,IAAI,CACX,MAAgB,EAChB,KAA0E,EAC1E,MAAM,GAAG,EAAE,EACX,KAAK,GAAG,CAAC;IAET,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;QAC/C,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;QAE/B,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC/B,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;QACjF,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,MAAgB;IACnC,MAAM,MAAM,GAAgB,EAAE,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IACvF,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QACzC,MAAM,CAAC,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,CAAC,QAAQ;YAAE,MAAM,CAAC,QAAQ,EAAE,CAAC;QACtC,IAAI,KAAK,GAAG,OAAO;YAAE,OAAO,GAAG,KAAK,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAU;IACpC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAqB,CAAC;IAC3C,MAAM,SAAS,GAAmB,EAAE,CAAC;IAErC,MAAM,MAAM,GAA8D;QACxE,WAAW,EAAE,CAAC;QACd,UAAU,EAAE,CAAC;QACb,GAAG,EAAE,CAAC;QACN,KAAK,EAAE,CAAC;QACR,QAAQ,EAAE,CAAC;KACZ,CAAC;IAEF,MAAM,KAAK,GAAG,CAAC,MAAgB,EAAE,IAAY,EAAE,QAAkC,EAAQ,EAAE;QACzF,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YACjC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAExD,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBAC9B,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,CAAC,UAAU,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,KAAK,EAAE,CAAC,CAAC;YACpG,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAmB,EAAE;QAC/E,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAClD,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;QAE1C,MAAM,CAAC,WAAW,EAAE,CAAC;QACrB,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,GAAG,CAAC;QACzB,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC;QAC7B,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC;QAEnC,OAAO;YACL,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,MAAM,EAAE,MAAM;YACd,0EAA0E;YAC1E,2DAA2D;YAC3D,UAAU,EAAE,iBAAiB,CAAC,GAAG,CAAC,IAAI,IAAI;YAC1C,SAAS,EAAE,gBAAgB,CAAC,GAAG,CAAC,IAAI,IAAI;YACxC,MAAM,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,MAAM;YAChC,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,KAAK;YAC/B,KAAK;SACN,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAkB,EAAE;QAC5E,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAClD,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QAEzC,MAAM,CAAC,UAAU,EAAE,CAAC;QACpB,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,GAAG,CAAC;QACzB,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC;QAC7B,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC;QAEnC,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,WAAW;QACX,UAAU;QACV,MAAM;QACN,KAAK,EAAE,CAAC,GAAG,KAAK,CAAC;aACd,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;aACzC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACpE,SAAS;KACV,CAAC;AACJ,CAAC"}
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":"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"}
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"]}
@@ -3,7 +3,7 @@
3
3
  * these routes only parse and serialize. The API path is the repository path,
4
4
  * Git is the history, and `revision` makes concurrent edits safe.
5
5
  */
6
- import { ValidationError } from "../services/content-store.js";
6
+ import { ReadOnlyError, ValidationError } from "../services/content-store.js";
7
7
  import { ConflictError } from "../workspace/files.js";
8
8
  import { collectionEntryPath, compareEntries, entryTitle, singletonPath } from "@micacms/core";
9
9
  import { Hono } from "hono";
@@ -30,7 +30,7 @@ async function handled(run) {
30
30
  return await run();
31
31
  }
32
32
  catch (error) {
33
- if (error instanceof ConflictError)
33
+ if (error instanceof ConflictError || error instanceof ReadOnlyError)
34
34
  throw new ApiError("conflict", error.message);
35
35
  if (error instanceof ValidationError) {
36
36
  throw new ApiError("validation_failed", error.message, { issues: error.issues });
@@ -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 { ReadOnlyError, 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 || error instanceof ReadOnlyError) 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 +1 @@
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
+ {"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,CAmF5C"}
@@ -3,7 +3,7 @@
3
3
  * An upload is written on its own, before the entry save, because the editor needs its path first.
4
4
  */
5
5
  import { Hono } from "hono";
6
- import { badRequest, notFound } from "../lib/errors.js";
6
+ import { ApiError, badRequest, notFound } from "../lib/errors.js";
7
7
  import { isImageType } from "../lib/file-type.js";
8
8
  import { MAX_FILES_PER_UPLOAD } from "../middleware/index.js";
9
9
  export function adminMediaRoutes() {
@@ -29,6 +29,11 @@ export function adminMediaRoutes() {
29
29
  const accept = form.get("accept");
30
30
  // An entry's own `media/` directory or the shared one; the media service refuses anything else.
31
31
  const directory = typeof form.get("directory") === "string" ? String(form.get("directory")) : undefined;
32
+ // The media service accepts `/gallery/x/media` too; take the owner from the path it will write to.
33
+ const owner = (directory ?? "").replace(/^[/\\]+/, "").split(/[/\\]/)[0] ?? "";
34
+ const readOnly = ctx.site.readOnly.get(`collections.${owner}`) ?? ctx.site.readOnly.get(`singletons.${owner}`);
35
+ if (readOnly)
36
+ throw new ApiError("conflict", readOnly);
32
37
  const prepared = await Promise.all(files.map((file) => ctx.services.media.prepare({
33
38
  file,
34
39
  directory,
@@ -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 { ApiError, 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 // The media service accepts `/gallery/x/media` too; take the owner from the path it will write to.\n const owner = (directory ?? \"\").replace(/^[/\\\\]+/, \"\").split(/[/\\\\]/)[0] ?? \"\";\n const readOnly = ctx.site.readOnly.get(`collections.${owner}`) ?? ctx.site.readOnly.get(`singletons.${owner}`);\n if (readOnly) throw new ApiError(\"conflict\", readOnly);\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"]}