@patterkit/ops 0.8.0 → 0.9.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.
package/dist/index.d.ts CHANGED
@@ -142,10 +142,17 @@ declare function defaultGameScopesDir(root: string): string;
142
142
  * engine's, which is that engine's to declare). The project keeps its copy. When the walk-up from the
143
143
  * project would not find `dir`, the project names it (`gameScopes`), so it is found next time. Returns
144
144
  * the writes (the folder comes with the first), and the project as it should now be saved.
145
+ *
146
+ * A folder another tool already made is JOINED, never overwritten: an existing `game.scopes.json` keeps
147
+ * every scope it holds, and gains only the project's game scopes it doesn't declare yet (as the
148
+ * Storylet Engine's share adds `@world` only when the file has none). One that won't parse is an error,
149
+ * and nothing is written.
145
150
  */
146
151
  declare function planShareScopes(root: string, project: ProjectFile, dir: string): {
147
152
  writes: PlannedWrite[];
148
153
  project: ProjectFile;
154
+ } | {
155
+ error: string;
149
156
  };
150
157
 
151
158
  interface LoadedProject {
package/dist/index.js CHANGED
@@ -211,18 +211,23 @@ function defaultGameScopesDir(root) {
211
211
  }
212
212
  function planShareScopes(root, project, dir) {
213
213
  const target = resolve(dir);
214
- const game = {
215
- version: 1,
216
- owner: GAME_SCOPES_OWNER,
217
- scopes: (project.scopeRegistry?.scopes ?? []).filter((h) => isGameToken(h.token, void 0)).map((h) => ({
218
- token: h.token,
219
- ...h.writable !== void 0 ? { writable: h.writable } : {},
220
- ...h.declarations ? { declarations: h.declarations.map((d) => ({ ...d })) } : {}
221
- }))
222
- };
214
+ const gamePath = join(target, GAME_SCOPES_FILE);
215
+ let existing = { version: 1, owner: GAME_SCOPES_OWNER, scopes: [] };
216
+ if (existsSync(gamePath)) {
217
+ const parsed = parseScopesFile(readFileSync(gamePath, "utf8"), GAME_SCOPES_FILE);
218
+ if (!parsed.file) return { error: `${GAME_SCOPES_FILE} in ${target} won't parse, so it was left alone: ${parsed.issues.map((i) => i.message).join("; ")}` };
219
+ existing = parsed.file;
220
+ }
221
+ const held = new Set(existing.scopes.map((s) => s.token));
222
+ const added = (project.scopeRegistry?.scopes ?? []).filter((h) => isGameToken(h.token, void 0) && !held.has(h.token)).map((h) => ({
223
+ token: h.token,
224
+ ...h.writable !== void 0 ? { writable: h.writable } : {},
225
+ ...h.declarations ? { declarations: h.declarations.map((d) => ({ ...d })) } : {}
226
+ }));
227
+ const game = { ...existing, scopes: [...existing.scopes, ...added] };
223
228
  const writes = [
224
229
  { path: join(target, PATTER_SCOPES_FILE), content: serialiseScopesFile(patterScopesFile(project)) },
225
- { path: join(target, GAME_SCOPES_FILE), content: serialiseScopesFile(game) }
230
+ { path: gamePath, content: serialiseScopesFile(game) }
226
231
  ];
227
232
  let found = false;
228
233
  for (let at = resolve(root); ; ) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patterkit/ops",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "The shared operations layer: every project operation (load, validate, export, format, play, ...) as a pure function, consumed by the patter CLI and Patterpad alike.",
5
5
  "type": "module",
6
6
  "license": "MIT",