@escape-game-over/atlas 0.1.117 → 0.1.119

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
@@ -130,8 +130,8 @@ export const baseRoutes = atlas.routes({...})
130
130
  export const messages = atlas.catalog(baseMessages, { locales: [...], override: {...} })
131
131
  export const { project, redirects } = atlas.project(messages, baseRoutes, {...})
132
132
 
133
- // 4. the API the pages use: the deployment's catalog, the routes, the deployment
134
- export const site = atlas.site(messages, baseRoutes, project)
133
+ // 4. the API the pages use, from the deployment and what it was checked against
134
+ export const site = atlas.site(project)
135
135
  ```
136
136
 
137
137
  A site that publishes one language under several regions writes the words once:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@escape-game-over/atlas",
3
- "version": "0.1.117",
3
+ "version": "0.1.119",
4
4
  "type": "module",
5
5
  "description": "Typed, data-driven machinery for static multi-locale, multi-deployment Astro sites.",
6
6
  "private": false,
package/src/index.ts CHANGED
@@ -9,7 +9,7 @@
9
9
  * export const defaultRoutes = atlas.routes({...}) // routes.ts
10
10
  * export const messages = atlas.catalog(defaultMessages, {...}) // projects/<name>/messages.ts
11
11
  * export const { project, redirects } = atlas.project(messages, defaultRoutes, {...}) // projects/<name>/project.ts
12
- * export const site = atlas.site(messages, defaultRoutes, project) // site.ts
12
+ * export const site = atlas.site(project) // site.ts
13
13
  * ```
14
14
  */
15
15
 
package/src/project.ts CHANGED
@@ -157,6 +157,12 @@ export type ProjectRouteId<
157
157
  P extends { readonly overrideRoutes: unknown },
158
158
  > = EnabledRouteIdFor<Routes, P["overrideRoutes"]> & StringKeys<Routes>;
159
159
 
160
+ /** What a project was built from, which the site is built from too. */
161
+ export interface ProjectSources<Cat, Routes> {
162
+ readonly catalog: Cat;
163
+ readonly routes: Routes;
164
+ }
165
+
160
166
  /**
161
167
  * What `atlas.project()` hands back: the project, and its redirects.
162
168
  *
@@ -170,11 +176,17 @@ export type ProjectRouteId<
170
176
  * resolves, and writes to `_redirects` with the rules the route table implies.
171
177
  */
172
178
  export interface DefinedProject<
179
+ Cat,
173
180
  Routes extends EnabledFlagSource,
174
181
  T extends ProjectInput<string, Routes>,
175
182
  Published extends string,
176
183
  > {
177
- readonly project: T;
184
+ /**
185
+ * The project, carrying the catalog and the routes it was checked
186
+ * against: `atlas.site(project)` reads them from here, so a site cannot
187
+ * be handed a catalog its project was not checked against.
188
+ */
189
+ readonly project: T & ProjectSources<Cat, Routes>;
178
190
  /** Rules for this project's old URLs, checked against what it builds. */
179
191
  readonly redirects: <
180
192
  const Rules extends readonly RedirectRule<
@@ -200,7 +212,7 @@ export function bindRedirects<
200
212
  _routes: Routes,
201
213
  _project: T,
202
214
  _catalog: ProjectCatalog<unknown, Published, unknown, unknown>
203
- ): DefinedProject<Routes, T, Published>["redirects"] {
215
+ ): DefinedProject<unknown, Routes, T, Published>["redirects"] {
204
216
  return (rules) => rules as never;
205
217
  }
206
218
 
@@ -303,29 +315,6 @@ type ClockCheck<T, Published extends string> = T extends {
303
315
  }
304
316
  : unknown;
305
317
 
306
- /**
307
- * The catalog each project was built with, so the site can check it is given
308
- * the same one. Weak, so a project nothing holds any more is not kept alive.
309
- */
310
- const builtWith = new WeakMap<object, object>();
311
-
312
- /**
313
- * Throws if a site is given a catalog other than the one its project was built
314
- * with: the project's locale checks were made against that one. A project
315
- * assembled by hand, which `defineProject` never saw, has nothing to compare.
316
- */
317
- export function checkProjectCatalog(
318
- project: { readonly siteName: string },
319
- catalog: object
320
- ): void {
321
- const own = builtWith.get(project);
322
- if (own !== undefined && own !== catalog) {
323
- throw new Error(
324
- `Project "${project.siteName}" was built with a different catalog than the one passed to atlas.site(): pass the catalog its project.ts uses.`
325
- );
326
- }
327
- }
328
-
329
318
  export function defineProject<
330
319
  const C extends SiteConfigShape,
331
320
  const Cat extends ProjectCatalog<
@@ -385,6 +374,5 @@ export function defineProject<
385
374
  `Project "${project.siteName}": formats.prices.locale names ${priceLocale}, which this project does not publish.`
386
375
  );
387
376
  }
388
- builtWith.set(project, catalog);
389
377
  return project;
390
378
  }
@@ -390,14 +390,22 @@ export interface RouteFamily<
390
390
  /**
391
391
  * One override for many members, for a project's `overrideRoutes`: by
392
392
  * default, `{ enabled: true }`. Keys stay literal; see {@link enableRoutes}.
393
+ *
394
+ * Takes any id, not only the family's members, so a helper generic over a
395
+ * venue's rooms can pass them through. A member the family lacks is still
396
+ * an error: on the `overrideRoutes` line, as a route the table lacks.
397
+ *
398
+ * The members' own list sits beside `Picked` for the editor: it offers
399
+ * the members from it, which it would not from a constraint that also
400
+ * admits any string, since it completes a generic from what it inferred.
393
401
  */
394
402
  enable<
395
- const Picked extends readonly (Member | { readonly id: Member })[],
403
+ const Picked extends readonly (string | { readonly id: string })[],
396
404
  const Override extends { readonly enabled?: boolean } = {
397
405
  readonly enabled: true;
398
406
  },
399
407
  >(
400
- members: Picked,
408
+ members: Picked | readonly (Member | { readonly id: Member })[],
401
409
  override?: Override
402
410
  ): {
403
411
  readonly [M in Picked[number] as `${Dashed<Prefix>}-${MemberId<M> &
@@ -464,7 +472,8 @@ export function createFamily<
464
472
  }
465
473
  return member as never;
466
474
  },
467
- enable: (picked, override) => enable(picked, override),
475
+ // The keys come from `Picked`; the members' own list is for the editor.
476
+ enable: (picked, override) => enable(picked, override) as never,
468
477
  slugs: (segment, segmentByLocale) => {
469
478
  // The join `familyMemberSlugs` makes, with the family's own prefix
470
479
  // translations rather than a copy of them.
@@ -30,11 +30,7 @@ import {
30
30
  resolveShareImage,
31
31
  } from "../meta/index.ts";
32
32
  import type { PriceDecimals } from "../price-format.ts";
33
- import {
34
- checkProjectCatalog,
35
- type ProjectInput,
36
- type ProjectRouteId,
37
- } from "../project.ts";
33
+ import type { ProjectInput, ProjectRouteId } from "../project.ts";
38
34
  import {
39
35
  buildRedirects,
40
36
  type RedirectRule,
@@ -135,7 +131,6 @@ export function createSite<
135
131
  config_.defaultRouting.prefixDefaultLocale;
136
132
 
137
133
  // Checks that types cannot express, run once at build time.
138
- checkProjectCatalog(project, catalog);
139
134
  if (locales.length === 0) {
140
135
  throw new Error("A project must publish at least one locale.");
141
136
  }
@@ -60,7 +60,7 @@ import { createSite } from "./create.ts";
60
60
  * export const defaultMessages = atlas.messages({…});
61
61
  * export const messages = atlas.catalog(defaultMessages, { locales: […], override: {…} });
62
62
  * export const { project, redirects } = atlas.project(messages, defaultRoutes, {…});
63
- * export const site = atlas.site(messages, defaultRoutes, project);
63
+ * export const site = atlas.site(project);
64
64
  * ```
65
65
  *
66
66
  * Every check each step makes is the same one it makes as a function: a typo'd
@@ -152,7 +152,7 @@ export function defineSite<
152
152
  catalog: Cat,
153
153
  routes: Routes,
154
154
  project: T & ProjectOverrideChecks<PublishedOf<Cat>, Routes, T>
155
- ): DefinedProject<Routes, T, PublishedOf<Cat>> {
155
+ ): DefinedProject<Cat, Routes, T, PublishedOf<Cat>> {
156
156
  const defined = defineProject(
157
157
  config,
158
158
  catalog,
@@ -160,12 +160,15 @@ export function defineSite<
160
160
  project as never
161
161
  ) as T;
162
162
  return {
163
- project: defined,
163
+ project: { ...defined, catalog, routes },
164
164
  redirects: bindRedirects(routes, defined, catalog),
165
165
  };
166
166
  },
167
167
 
168
- /** The API every page reads, wired for one project and its catalog. */
168
+ /**
169
+ * The API every page reads, wired for one project: built from the
170
+ * catalog and routes the project was checked against, which it carries.
171
+ */
169
172
  site<
170
173
  const Cat extends ProjectCatalog<
171
174
  BaseCatalog<L>,
@@ -177,11 +180,16 @@ export function defineSite<
177
180
  const Routes extends RouteRegistry<L>,
178
181
  const P extends ProjectInput<L, Routes>,
179
182
  >(
180
- catalog: Cat & { readonly locales: readonly Published[] },
181
- routes: Routes,
182
- project: P
183
+ project: P & {
184
+ // `Published` is inferred from the locales themselves, as
185
+ // `createSite` explains.
186
+ readonly catalog: Cat & {
187
+ readonly locales: readonly Published[];
188
+ };
189
+ readonly routes: Routes;
190
+ }
183
191
  ): ReturnType<typeof createSite<C, Cat, Published, Routes, P>> {
184
- return createSite(config, catalog, routes, project);
192
+ return createSite(config, project.catalog, project.routes, project);
185
193
  },
186
194
  };
187
195
  }