@m4l-jweb/build 1.3.0 → 1.3.1

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.
Files changed (2) hide show
  1. package/package.json +2 -2
  2. package/src/index.mjs +34 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@m4l-jweb/build",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "m4l-jweb: the CLI that builds and packages a device repo into installable Max for Live devices.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -35,6 +35,6 @@
35
35
  "archiver": "^7.0.1",
36
36
  "esbuild": "^0.25.0",
37
37
  "typescript": "^5.7.0",
38
- "@m4l-jweb/wrapper": "1.3.0"
38
+ "@m4l-jweb/wrapper": "1.3.1"
39
39
  }
40
40
  }
package/src/index.mjs CHANGED
@@ -123,6 +123,26 @@ async function readManifest(root) {
123
123
  return (await import(pathToFileURL(p).href)).default;
124
124
  }
125
125
 
126
+ /**
127
+ * Files that ride along with the release without being part of any device.
128
+ *
129
+ * A user manual, a licence, a chart - things a person opens, not things Max loads. They
130
+ * are declared as a named `docs` export next to the manifest:
131
+ *
132
+ * export const docs = ["USERSMANUAL.md", "dist/manual/USERSMANUAL.pdf"];
133
+ *
134
+ * MISSING IS NOT FATAL, and that is the whole reason this is a list rather than a
135
+ * `looseFiles` entry: a generated doc (a PDF rendered by a headless browser) may not
136
+ * exist on a machine that has no browser, and a manual is never worth failing a build
137
+ * that produced every device correctly. What is missing is named in the log.
138
+ */
139
+ async function readDocs(root) {
140
+ const p = path.join(root, "patcher", "devices.mjs");
141
+ if (!existsSync(p)) return [];
142
+ const mod = await import(pathToFileURL(p).href);
143
+ return Array.isArray(mod.docs) ? mod.docs : [];
144
+ }
145
+
126
146
  /** patcher/base.json in the device repo wins; otherwise the packaged template. */
127
147
  function readBase(root) {
128
148
  const local = path.join(root, "patcher", "base.json");
@@ -457,6 +477,19 @@ export async function packageDevices(root) {
457
477
  console.log(`m4l-jweb: ${f} -> dist/${name}/ (preset)`);
458
478
  }
459
479
 
480
+ // Documentation for the human, alongside the devices for Max. See readDocs.
481
+ const docs = [];
482
+ for (const f of await readDocs(root)) {
483
+ const from = path.join(root, f);
484
+ if (!existsSync(from)) {
485
+ console.warn(`m4l-jweb: doc ${f} is not there - skipped (it is not part of any device)`);
486
+ continue;
487
+ }
488
+ await copyFile(from, path.join(outDir, path.basename(f)));
489
+ docs.push(path.basename(f));
490
+ console.log(`m4l-jweb: ${path.basename(f)} -> dist/${name}/ (doc)`);
491
+ }
492
+
460
493
  // Installers go next to the devices so `dist/install-*.ps1` just works.
461
494
  const installers = ["install-windows.ps1", "install-mac.sh"];
462
495
  for (const f of installers) await copyFile(path.join(templates, f), path.join(dist, f));
@@ -473,6 +506,7 @@ export async function packageDevices(root) {
473
506
  ...devices.map((d) => `${d.name}.html`), // each device's own UI, for inspection
474
507
  ...loose.map((f) => path.basename(f)),
475
508
  ...presets,
509
+ ...docs,
476
510
  "wrapper.js",
477
511
  ];
478
512
  for (const f of files) {