@forwardimpact/pathway 0.25.1 → 0.25.3

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.
@@ -31,6 +31,7 @@
31
31
 
32
32
  import { join, resolve, dirname } from "path";
33
33
  import { fileURLToPath } from "url";
34
+ import { readFileSync } from "fs";
34
35
  import fs from "fs/promises";
35
36
  import { homedir } from "os";
36
37
  import { createDataLoader } from "@forwardimpact/map/loader";
@@ -62,6 +63,11 @@ import { runUpdateCommand } from "../src/commands/update.js";
62
63
  const __dirname = dirname(fileURLToPath(import.meta.url));
63
64
  const TEMPLATE_DIR = join(__dirname, "..", "templates");
64
65
 
66
+ /** Package version read from package.json */
67
+ const VERSION = JSON.parse(
68
+ readFileSync(join(__dirname, "..", "package.json"), "utf8"),
69
+ ).version;
70
+
65
71
  const COMMANDS = {
66
72
  discipline: runDisciplineCommand,
67
73
  level: runLevelCommand,
@@ -88,6 +94,7 @@ Global Options:
88
94
  --list Output IDs only (for piping to other commands)
89
95
  --json Output as JSON
90
96
  --data=PATH Path to data directory (default: ./data or examples/)
97
+ --version Show version number
91
98
  --help Show this help message
92
99
 
93
100
  ────────────────────────────────────────────────────────────────────────────────
@@ -240,6 +247,7 @@ function parseArgs(args) {
240
247
  list: false,
241
248
  json: false,
242
249
  help: false,
250
+ version: false,
243
251
  type: "full",
244
252
  compare: null,
245
253
  data: null,
@@ -265,7 +273,9 @@ function parseArgs(args) {
265
273
  };
266
274
 
267
275
  for (const arg of args) {
268
- if (arg === "--help" || arg === "-h") {
276
+ if (arg === "--version" || arg === "-v") {
277
+ result.version = true;
278
+ } else if (arg === "--help" || arg === "-h") {
269
279
  result.help = true;
270
280
  } else if (arg === "--list" || arg === "-l") {
271
281
  result.list = true;
@@ -345,6 +355,11 @@ async function main() {
345
355
  const args = process.argv.slice(2);
346
356
  const options = parseArgs(args);
347
357
 
358
+ if (options.version) {
359
+ console.log(VERSION);
360
+ process.exit(0);
361
+ }
362
+
348
363
  if (options.help) {
349
364
  printHelp();
350
365
  process.exit(0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forwardimpact/pathway",
3
- "version": "0.25.1",
3
+ "version": "0.25.3",
4
4
  "description": "Career progression web app and CLI for exploring roles and generating agent teams",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -44,6 +44,7 @@
44
44
  "@forwardimpact/libskill": "^4.0.0",
45
45
  "@forwardimpact/libtemplate": "^0.2.0",
46
46
  "@forwardimpact/libui": "^1.0.0",
47
+ "@forwardimpact/libutil": "^0.1.64",
47
48
  "mustache": "^4.2.0",
48
49
  "simple-icons": "^16.13.0",
49
50
  "yaml": "^2.8.3"
@@ -193,6 +193,14 @@ ${framework.emojiIcon} Generating ${framework.title} static site...
193
193
  console.log(` ✓ data/ (from ${relative(process.cwd(), dataDir)})`);
194
194
  }
195
195
 
196
+ // Write version.json for the web app footer
197
+ const version = getPathwayVersion();
198
+ await writeFile(
199
+ join(outputDir, "version.json"),
200
+ JSON.stringify({ version }) + "\n",
201
+ );
202
+ console.log(` ✓ version.json (${version})`);
203
+
196
204
  // Generate distribution bundle if siteUrl is configured
197
205
  const siteUrl = options.url || framework.distribution?.siteUrl;
198
206
  if (siteUrl) {
@@ -7,6 +7,7 @@
7
7
 
8
8
  import { createServer } from "http";
9
9
  import { readFile, stat } from "fs/promises";
10
+ import { readFileSync } from "fs";
10
11
  import { join, extname, dirname } from "path";
11
12
  import { fileURLToPath } from "url";
12
13
  import { createIndexGenerator } from "@forwardimpact/map/index-generator";
@@ -17,6 +18,11 @@ const __dirname = dirname(__filename);
17
18
  const publicDir = join(__dirname, "..");
18
19
  const rootDir = join(__dirname, "../..");
19
20
 
21
+ /** Package version for serving as /version.json */
22
+ const VERSION = JSON.parse(
23
+ readFileSync(join(rootDir, "package.json"), "utf8"),
24
+ ).version;
25
+
20
26
  /**
21
27
  * Resolve package directory using Node's module resolution.
22
28
  * Works in both monorepo (development) and installed (production) contexts.
@@ -140,7 +146,11 @@ export async function runDevCommand({ dataDir, options }) {
140
146
 
141
147
  let filePath;
142
148
 
143
- if (pathname.startsWith("/data/")) {
149
+ if (pathname === "/version.json") {
150
+ res.setHeader("Content-Type", "application/json; charset=utf-8");
151
+ res.end(JSON.stringify({ version: VERSION }));
152
+ return;
153
+ } else if (pathname.startsWith("/data/")) {
144
154
  // Serve from user's data directory
145
155
  filePath = join(dataDir, pathname.slice(6));
146
156
  } else if (pathname.startsWith("/templates/")) {
package/src/index.html CHANGED
@@ -136,7 +136,7 @@
136
136
  </main>
137
137
 
138
138
  <footer id="app-footer">
139
- <p>Engineering Pathway</p>
139
+ <p>Engineering Pathway <span id="app-version"></span></p>
140
140
  <nav class="footer-links">
141
141
  <a href="slides.html">Slides</a>
142
142
  <a href="handout.html">Handouts</a>
package/src/main.js CHANGED
@@ -55,6 +55,9 @@ async function init() {
55
55
 
56
56
  // Populate branding from framework data
57
57
  populateBranding();
58
+
59
+ // Load and display version
60
+ loadVersion();
58
61
  } catch (error) {
59
62
  console.error("Failed to load data:", error);
60
63
  setError(error);
@@ -208,10 +211,27 @@ function populateBranding() {
208
211
  // Update footer
209
212
  const footer = document.querySelector("#app-footer p");
210
213
  if (footer) {
211
- footer.textContent = branding.title;
214
+ const versionSpan = footer.querySelector("#app-version");
215
+ footer.textContent = branding.title + " ";
216
+ if (versionSpan) footer.appendChild(versionSpan);
212
217
  }
213
218
  }
214
219
 
220
+ /**
221
+ * Fetch version.json and display in the footer
222
+ */
223
+ function loadVersion() {
224
+ fetch("./version.json")
225
+ .then((r) => (r.ok ? r.json() : null))
226
+ .then((data) => {
227
+ if (data?.version) {
228
+ const el = document.getElementById("app-version");
229
+ if (el) el.textContent = `v${data.version}`;
230
+ }
231
+ })
232
+ .catch(() => {});
233
+ }
234
+
215
235
  /**
216
236
  * Set up drawer overlay for mobile backdrop and auto-close behavior
217
237
  */