@emeryld/rrroutes-export 1.0.12 → 1.0.14

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
@@ -9,6 +9,8 @@ Export helpers and CLI for RRRoutes finalized leaves.
9
9
  - `writeFinalizedLeavesExport`
10
10
  - `exportFinalizedLeavesChangelog`
11
11
  - `writeFinalizedLeavesChangelogExport`
12
+ - `buildFinalizedLeavesViewerBundle`
13
+ - `writeFinalizedLeavesViewerBundle`
12
14
  - CLI:
13
15
  - `rrroutes-export-finalized-leaves`
14
16
  - `rrroutes-export-changelog`
@@ -134,6 +136,8 @@ Per run, it writes a timestamped directory:
134
136
  - `finalized-leaves.viewer.html`
135
137
  - `finalized-leaves.changelog.json`
136
138
  - `finalized-leaves.changelog.viewer.html`
139
+ - `finalized-leaves.bundle.json`
140
+ - `finalized-leaves.bundle.viewer.html`
137
141
  - `summary.json`
138
142
 
139
143
  This is the recommended CI/release flow because outputs are immutable per run and easy to archive.
@@ -142,8 +146,10 @@ This is the recommended CI/release flow because outputs are immutable per run an
142
146
 
143
147
  ```ts
144
148
  import {
149
+ buildFinalizedLeavesViewerBundle,
145
150
  exportFinalizedLeaves,
146
151
  exportFinalizedLeavesChangelog,
152
+ writeFinalizedLeavesViewerBundle,
147
153
  } from '@emeryld/rrroutes-export'
148
154
 
149
155
  const snapshot = await exportFinalizedLeaves(leaves, {
@@ -165,4 +171,14 @@ const changelog = await exportFinalizedLeavesChangelog({
165
171
  htmlFile: './finalized-leaves.changelog.viewer.html',
166
172
  log: (message) => console.log(message),
167
173
  })
174
+
175
+ const unified = buildFinalizedLeavesViewerBundle({
176
+ leavesPayload: snapshot,
177
+ changelogPayload: changelog,
178
+ })
179
+
180
+ await writeFinalizedLeavesViewerBundle(unified, {
181
+ outFile: './finalized-leaves.bundle.json',
182
+ htmlFile: './finalized-leaves.bundle.viewer.html',
183
+ })
168
184
  ```
@@ -0,0 +1,21 @@
1
+ import type { FinalizedLeavesExport, WriteFinalizedLeavesExportOptions } from './exportFinalizedLeaves';
2
+ import type { FinalizedLeavesChangelogExport } from './exportFinalizedLeaves.changelog';
3
+ export type FinalizedLeavesViewerBundleMeta = {
4
+ generatedAt: string;
5
+ description: string;
6
+ };
7
+ export type FinalizedLeavesViewerBundle = {
8
+ kind: 'finalized-leaves-bundle';
9
+ _meta: FinalizedLeavesViewerBundleMeta;
10
+ leavesPayload: FinalizedLeavesExport;
11
+ changelogPayload: FinalizedLeavesChangelogExport;
12
+ };
13
+ export type BuildFinalizedLeavesViewerBundleInput = {
14
+ leavesPayload: FinalizedLeavesExport;
15
+ changelogPayload: FinalizedLeavesChangelogExport;
16
+ };
17
+ export declare function buildFinalizedLeavesViewerBundle(input: BuildFinalizedLeavesViewerBundleInput): FinalizedLeavesViewerBundle;
18
+ export declare function writeFinalizedLeavesViewerBundle(payload: FinalizedLeavesViewerBundle, outFileOrOptions: string | WriteFinalizedLeavesExportOptions): Promise<{
19
+ outFile?: string;
20
+ htmlFile?: string;
21
+ }>;
@@ -58,6 +58,7 @@ export type SourceSchemaPathDelta = {
58
58
  export type ChangelogCommit = {
59
59
  sha: string;
60
60
  authorDate: string;
61
+ authorName: string;
61
62
  subject: string;
62
63
  };
63
64
  export type RouteChangeType = 'route_added' | 'route_removed' | 'schema_changed' | 'cfg_changed';
package/dist/index.cjs CHANGED
@@ -32,6 +32,7 @@ var index_exports = {};
32
32
  __export(index_exports, {
33
33
  DEFAULT_VIEWER_TEMPLATE: () => DEFAULT_VIEWER_TEMPLATE,
34
34
  __private: () => __private,
35
+ buildFinalizedLeavesViewerBundle: () => buildFinalizedLeavesViewerBundle,
35
36
  clearSchemaIntrospectionHandlers: () => clearSchemaIntrospectionHandlers,
36
37
  createSchemaIntrospector: () => createSchemaIntrospector,
37
38
  exportFinalizedLeaves: () => exportFinalizedLeaves,
@@ -50,7 +51,8 @@ __export(index_exports, {
50
51
  serializeLeafContract: () => serializeLeafContract,
51
52
  serializeLeavesContract: () => serializeLeavesContract,
52
53
  writeFinalizedLeavesChangelogExport: () => writeFinalizedLeavesChangelogExport,
53
- writeFinalizedLeavesExport: () => writeFinalizedLeavesExport
54
+ writeFinalizedLeavesExport: () => writeFinalizedLeavesExport,
55
+ writeFinalizedLeavesViewerBundle: () => writeFinalizedLeavesViewerBundle
54
56
  });
55
57
  module.exports = __toCommonJS(index_exports);
56
58
 
@@ -350,46 +352,46 @@ function normalizeType(schema) {
350
352
  return "unknown";
351
353
  }
352
354
  }
353
- function isNonEmptyPath(path6) {
354
- return typeof path6 === "string" && path6.length > 0;
355
+ function isNonEmptyPath(path7) {
356
+ return typeof path7 === "string" && path7.length > 0;
355
357
  }
356
- function setNode(out, path6, schema, inherited) {
357
- if (!isNonEmptyPath(path6)) return;
358
- out[path6] = {
358
+ function setNode(out, path7, schema, inherited) {
359
+ if (!isNonEmptyPath(path7)) return;
360
+ out[path7] = {
359
361
  type: normalizeType(schema),
360
362
  nullable: inherited.nullable || Boolean(schema.nullable),
361
363
  optional: inherited.optional || Boolean(schema.optional),
362
364
  literal: schema.kind === "literal" ? schema.literal : void 0
363
365
  };
364
366
  }
365
- function flattenInto(out, schema, path6, inherited) {
366
- if (!schema || !isNonEmptyPath(path6)) return;
367
+ function flattenInto(out, schema, path7, inherited) {
368
+ if (!schema || !isNonEmptyPath(path7)) return;
367
369
  const nextInherited = {
368
370
  optional: inherited.optional || Boolean(schema.optional),
369
371
  nullable: inherited.nullable || Boolean(schema.nullable)
370
372
  };
371
373
  if (schema.kind === "union" && Array.isArray(schema.union) && schema.union.length > 0) {
372
374
  schema.union.forEach((option, index) => {
373
- const optionPath = `${path6}-${index + 1}`;
375
+ const optionPath = `${path7}-${index + 1}`;
374
376
  flattenInto(out, option, optionPath, inherited);
375
377
  });
376
378
  return;
377
379
  }
378
- setNode(out, path6, schema, inherited);
380
+ setNode(out, path7, schema, inherited);
379
381
  if (schema.kind === "object" && schema.properties) {
380
382
  for (const [key, child] of Object.entries(schema.properties)) {
381
- const childPath = `${path6}.${key}`;
383
+ const childPath = `${path7}.${key}`;
382
384
  flattenInto(out, child, childPath, nextInherited);
383
385
  }
384
386
  return;
385
387
  }
386
388
  if (schema.kind === "array" && schema.element) {
387
- flattenInto(out, schema.element, `${path6}[]`, nextInherited);
389
+ flattenInto(out, schema.element, `${path7}[]`, nextInherited);
388
390
  }
389
391
  }
390
- function flattenSerializableSchema(schema, path6) {
392
+ function flattenSerializableSchema(schema, path7) {
391
393
  const out = {};
392
- flattenInto(out, schema, path6, { optional: false, nullable: false });
394
+ flattenInto(out, schema, path7, { optional: false, nullable: false });
393
395
  return out;
394
396
  }
395
397
  function isSerializedLeaf(value) {
@@ -1661,14 +1663,15 @@ async function filterCommits(cwd, commits, moduleCandidates, tsconfigRel) {
1661
1663
  return keep;
1662
1664
  }
1663
1665
  async function getCommitMetadata(cwd, commit) {
1664
- const out = await runGit(cwd, ["show", "-s", "--format=%H%x1f%aI%x1f%s", commit]);
1665
- const [sha, authorDate, subject] = out.split("");
1666
- if (!sha || !authorDate) {
1666
+ const out = await runGit(cwd, ["show", "-s", "--format=%H%x1f%aI%x1f%an%x1f%s", commit]);
1667
+ const [sha, authorDate, authorName, subject] = out.split("");
1668
+ if (!sha || !authorDate || !authorName) {
1667
1669
  throw new Error(`Unable to read commit metadata for ${commit}`);
1668
1670
  }
1669
1671
  return {
1670
1672
  sha,
1671
1673
  authorDate,
1674
+ authorName,
1672
1675
  subject: subject ?? ""
1673
1676
  };
1674
1677
  }
@@ -2619,10 +2622,124 @@ async function runExportFinalizedLeavesChangelogCli(argv) {
2619
2622
  htmlFile: args.htmlFile ? import_node_path5.default.resolve(args.htmlFile) : void 0
2620
2623
  };
2621
2624
  }
2625
+
2626
+ // src/exportFinalizedLeaves.bundle.ts
2627
+ var import_promises3 = __toESM(require("fs/promises"), 1);
2628
+ var import_node_path6 = __toESM(require("path"), 1);
2629
+ var import_node_child_process3 = require("child_process");
2630
+ var BAKED_PAYLOAD_MARKER3 = "<!--__FINALIZED_LEAVES_BAKED_PAYLOAD__-->";
2631
+ function escapePayloadForInlineScript3(payload) {
2632
+ return JSON.stringify(payload).replace(/<\//g, "<\\/").replace(/<!--/g, "<\\!--");
2633
+ }
2634
+ function injectPayloadIntoViewerHtml3(htmlTemplate, payload) {
2635
+ const payloadScript = `${BAKED_PAYLOAD_MARKER3}
2636
+ <script id="finalized-leaves-baked-payload">window.__FINALIZED_LEAVES_PAYLOAD = ${escapePayloadForInlineScript3(
2637
+ payload
2638
+ )};</script>`;
2639
+ if (htmlTemplate.includes(BAKED_PAYLOAD_MARKER3)) {
2640
+ return htmlTemplate.replace(BAKED_PAYLOAD_MARKER3, payloadScript);
2641
+ }
2642
+ if (htmlTemplate.includes("</body>")) {
2643
+ return htmlTemplate.replace("</body>", `${payloadScript}
2644
+ </body>`);
2645
+ }
2646
+ return `${payloadScript}
2647
+ ${htmlTemplate}`;
2648
+ }
2649
+ async function resolveViewerTemplatePath3(viewerTemplateFile) {
2650
+ if (viewerTemplateFile) {
2651
+ const resolved = import_node_path6.default.resolve(viewerTemplateFile);
2652
+ await import_promises3.default.access(resolved);
2653
+ return resolved;
2654
+ }
2655
+ const candidates = [
2656
+ import_node_path6.default.resolve(
2657
+ process.cwd(),
2658
+ "node_modules/@emeryld/rrroutes-export/tools/finalized-leaves-viewer.html"
2659
+ ),
2660
+ import_node_path6.default.resolve(process.cwd(), "tools/finalized-leaves-viewer.html"),
2661
+ import_node_path6.default.resolve(process.cwd(), "packages/export/tools/finalized-leaves-viewer.html")
2662
+ ];
2663
+ for (const candidate of candidates) {
2664
+ try {
2665
+ await import_promises3.default.access(candidate);
2666
+ return candidate;
2667
+ } catch {
2668
+ }
2669
+ }
2670
+ return void 0;
2671
+ }
2672
+ async function writeJsonExport3(payload, outFile) {
2673
+ const resolved = import_node_path6.default.resolve(outFile);
2674
+ await import_promises3.default.mkdir(import_node_path6.default.dirname(resolved), { recursive: true });
2675
+ await import_promises3.default.writeFile(resolved, `${JSON.stringify(payload, null, 2)}
2676
+ `, "utf8");
2677
+ return resolved;
2678
+ }
2679
+ async function writeBakedHtmlExport3(payload, htmlFile, viewerTemplateFile) {
2680
+ const templatePath = await resolveViewerTemplatePath3(viewerTemplateFile);
2681
+ const template = templatePath ? await import_promises3.default.readFile(templatePath, "utf8") : DEFAULT_VIEWER_TEMPLATE;
2682
+ const baked = injectPayloadIntoViewerHtml3(template, payload);
2683
+ const resolved = import_node_path6.default.resolve(htmlFile);
2684
+ await import_promises3.default.mkdir(import_node_path6.default.dirname(resolved), { recursive: true });
2685
+ await import_promises3.default.writeFile(resolved, baked, "utf8");
2686
+ return resolved;
2687
+ }
2688
+ async function openHtmlInBrowser3(filePath) {
2689
+ const resolved = import_node_path6.default.resolve(filePath);
2690
+ const platform = process.platform;
2691
+ if (platform === "darwin") {
2692
+ (0, import_node_child_process3.spawn)("open", [resolved], { detached: true, stdio: "ignore" }).unref();
2693
+ return;
2694
+ }
2695
+ if (platform === "win32") {
2696
+ (0, import_node_child_process3.spawn)("cmd", ["/c", "start", "", resolved], {
2697
+ detached: true,
2698
+ stdio: "ignore"
2699
+ }).unref();
2700
+ return;
2701
+ }
2702
+ (0, import_node_child_process3.spawn)("xdg-open", [resolved], { detached: true, stdio: "ignore" }).unref();
2703
+ }
2704
+ function buildFinalizedLeavesViewerBundle(input) {
2705
+ return {
2706
+ kind: "finalized-leaves-bundle",
2707
+ _meta: {
2708
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
2709
+ description: "Unified viewer bundle including finalized leaves snapshot and changelog timeline payloads."
2710
+ },
2711
+ leavesPayload: input.leavesPayload,
2712
+ changelogPayload: input.changelogPayload
2713
+ };
2714
+ }
2715
+ async function writeFinalizedLeavesViewerBundle(payload, outFileOrOptions) {
2716
+ const options = typeof outFileOrOptions === "string" ? { outFile: outFileOrOptions } : outFileOrOptions;
2717
+ const written = {};
2718
+ if (options.outFile) {
2719
+ written.outFile = await writeJsonExport3(payload, options.outFile);
2720
+ }
2721
+ if (options.htmlFile) {
2722
+ written.htmlFile = await writeBakedHtmlExport3(
2723
+ payload,
2724
+ options.htmlFile,
2725
+ options.viewerTemplateFile
2726
+ );
2727
+ }
2728
+ if (options.openOnFinish) {
2729
+ if (!written.htmlFile) {
2730
+ throw new Error(
2731
+ "openOnFinish requires htmlFile. Provide htmlFile to open the baked viewer."
2732
+ );
2733
+ }
2734
+ await openHtmlInBrowser3(written.htmlFile);
2735
+ }
2736
+ return written;
2737
+ }
2622
2738
  // Annotate the CommonJS export names for ESM import in node:
2623
2739
  0 && (module.exports = {
2624
2740
  DEFAULT_VIEWER_TEMPLATE,
2625
2741
  __private,
2742
+ buildFinalizedLeavesViewerBundle,
2626
2743
  clearSchemaIntrospectionHandlers,
2627
2744
  createSchemaIntrospector,
2628
2745
  exportFinalizedLeaves,
@@ -2641,6 +2758,7 @@ async function runExportFinalizedLeavesChangelogCli(argv) {
2641
2758
  serializeLeafContract,
2642
2759
  serializeLeavesContract,
2643
2760
  writeFinalizedLeavesChangelogExport,
2644
- writeFinalizedLeavesExport
2761
+ writeFinalizedLeavesExport,
2762
+ writeFinalizedLeavesViewerBundle
2645
2763
  });
2646
2764
  //# sourceMappingURL=index.cjs.map