@xforge-dev/forge-kit 0.18.1 → 0.18.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -106,6 +106,22 @@ the sign-in cookie, so a third-party script on one can read every user's session
106
106
  apps add Vercel Web Analytics (`<Analytics />` from `@vercel/analytics/next` in the root layout);
107
107
  it loads from the app's own origin, so the policy needs no extra sources.
108
108
 
109
+ ## Job catalog
110
+
111
+ The kit ships a snapshot of `data/jobs.json` for sync lookups (`job()`, `allJobs()`, ...).
112
+ `refreshJobCatalog()` (from `/server`) fetches the published copy at
113
+ `https://cdn.xforge.dev/data/jobs.json`, caching it for an hour, and installs it. The root layout
114
+ awaits it and passes the result to `ForgeJobsProvider` (from `/client`), so the browser gets the same
115
+ catalog. Whenever `data/jobs.json` changes, set `updated` to a new full ISO-8601 UTC timestamp (for
116
+ example `2026-10-29T18:30:00Z`). CI fails a content change that keeps the old stamp.
117
+
118
+ - **New enum values need a kit release first.** A new `status`, branch or stat value has to ship in
119
+ a kit release, and every app has to bump to that release, before `data/jobs.json` can use the value.
120
+ An older parser rejects the whole file and keeps its snapshot, so no part of the edit reaches that app.
121
+ - **Route handlers and server actions refresh the catalog themselves.** They don't run the root layout,
122
+ so any route handler or server action that looks up jobs must call `await refreshJobCatalog()`
123
+ before its first lookup. Otherwise it only ever sees the snapshot.
124
+
109
125
  ## Exports
110
126
 
111
127
  `isForgeAuthConfigured` is exported from the root and `/client` entry points.
@@ -3,7 +3,7 @@ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
3
3
  import { getJobCatalog, setJobCatalog } from './jobs.js';
4
4
  /** Installs the server-fetched catalog before the children render, so client lookups agree with the server. */
5
5
  export function ForgeJobsProvider({ catalog, children }) {
6
- if (catalog.updated !== getJobCatalog().updated)
6
+ if (catalog !== getJobCatalog())
7
7
  setJobCatalog(catalog);
8
8
  return _jsx(_Fragment, { children: children });
9
9
  }
@@ -1,6 +1,6 @@
1
1
  export const JOBS_SNAPSHOT = {
2
2
  "version": 1,
3
- "updated": "2026-10-29",
3
+ "updated": "2026-10-29T18:30:00Z",
4
4
  "jobs": [
5
5
  {
6
6
  "name": "Hero",
package/dist/jobs.js CHANGED
@@ -115,7 +115,7 @@ export function jobName(name) { return job(name)?.name ?? null; }
115
115
  export function allJobs(opts = {}) {
116
116
  return catalog.jobs
117
117
  .filter((j) => opts.includeRetired || j.status !== 'retired')
118
- .sort((a, b) => a.name.localeCompare(b.name));
118
+ .sort((a, b) => a.name.localeCompare(b.name, 'en'));
119
119
  }
120
120
  /** Highest Legion rank a character of this level has reached; null below rank B's level. */
121
121
  export function legionRankFor(j, level) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xforge-dev/forge-kit",
3
- "version": "0.18.1",
3
+ "version": "0.18.2",
4
4
  "description": "Shared auth, app registry and UI for xForge apps",
5
5
  "license": "MIT",
6
6
  "repository": {