@rainbow-robotics/muscat-plugin-kit 0.1.2-dev.38 → 0.1.2-dev.39

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.
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env node
2
+ // Pre-build step: serialise cli/templates/** into cli/src/templates-embedded.mjs
3
+ // so that `bun build --compile` can embed them without needing the filesystem.
4
+ import { readdirSync, readFileSync, writeFileSync, statSync } from "node:fs";
5
+ import { resolve, relative } from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+
8
+ const root = resolve(fileURLToPath(import.meta.url), "..");
9
+ const templatesDir = resolve(root, "templates");
10
+ const out = resolve(root, "src/templates-embedded.mjs");
11
+
12
+ const files = {};
13
+ function walk(dir) {
14
+ for (const name of readdirSync(dir)) {
15
+ const full = resolve(dir, name);
16
+ if (statSync(full).isDirectory()) { walk(full); continue; }
17
+ const key = relative(templatesDir, full);
18
+ files[key] = readFileSync(full, "base64");
19
+ }
20
+ }
21
+ walk(templatesDir);
22
+
23
+ writeFileSync(out,
24
+ `// AUTO-GENERATED by cli/bundle-templates.mjs — do not edit.\n` +
25
+ `// ponytail: generated at publish time; not tracked in git.\n` +
26
+ `export const TEMPLATES = ${JSON.stringify(files)};\n`
27
+ );
28
+ console.log(`bundled ${Object.keys(files).length} template files → src/templates-embedded.mjs`);
@@ -53,6 +53,7 @@ function runPython(root) {
53
53
  log.step("starting Python dev container…");
54
54
  const up = docker(
55
55
  ["run", "-d", "--name", container, ...netFlags,
56
+ "-e", "PIP_ROOT_USER_ACTION=ignore",
56
57
  "-v", `${root}:/plugin`, "-w", "/plugin", PYTHON_DEV_IMAGE, "sleep", "infinity"],
57
58
  { stdio: "inherit" },
58
59
  );
@@ -112,7 +113,7 @@ function runRos2(root) {
112
113
  docker(["rm", "-f", container], { stdio: "ignore" });
113
114
  log.step("starting ROS2 dev container…");
114
115
  const up = docker(
115
- ["run", "-d", "--name", container, "-v", `${root}:/plugin`, "-w", "/plugin", ROS2_DEV_IMAGE, "sleep", "infinity"],
116
+ ["run", "-d", "--name", container, "-e", "PIP_ROOT_USER_ACTION=ignore", "-v", `${root}:/plugin`, "-w", "/plugin", ROS2_DEV_IMAGE, "sleep", "infinity"],
116
117
  { stdio: "inherit" },
117
118
  );
118
119
  if (up.status !== 0) throw new Error("failed to start dev container.");
package/cli/src/new.mjs CHANGED
@@ -7,13 +7,28 @@ import {
7
7
  readFileSync,
8
8
  readdirSync,
9
9
  renameSync,
10
+ rmSync,
10
11
  statSync,
11
12
  writeFileSync,
12
13
  } from "node:fs";
13
- import { basename, resolve } from "node:path";
14
- import { rmSync } from "node:fs";
14
+ import { basename, dirname, resolve } from "node:path";
15
15
  import { hasBin, kitVersion, parseArgs, prompt, templatesDir, log } from "./util.mjs";
16
16
 
17
+ // Like cpSync(src, dst, {recursive:true}) but reads from the embedded snapshot
18
+ // when the templates dir doesn't exist on disk (compiled binary mode).
19
+ // ponytail: import() is module-cached by the runtime — no manual cache needed.
20
+ async function copyTemplate(srcDir, dst) {
21
+ if (existsSync(templatesDir)) { cpSync(srcDir, dst, { recursive: true }); return; }
22
+ const { TEMPLATES } = await import("./templates-embedded.mjs");
23
+ const prefix = srcDir.slice(templatesDir.length + 1).replace(/\\/g, "/") + "/";
24
+ for (const [key, b64] of Object.entries(TEMPLATES)) {
25
+ if (!key.startsWith(prefix)) continue;
26
+ const dest = resolve(dst, key.slice(prefix.length));
27
+ mkdirSync(dirname(dest), { recursive: true });
28
+ writeFileSync(dest, Buffer.from(b64, "base64"));
29
+ }
30
+ }
31
+
17
32
  // `--type` values map to a runtime descriptor. ros2 has a python (rclpy) and a
18
33
  // C++ (rclcpp) flavor; we expose them as distinct type choices for clarity.
19
34
  export const TYPE_CHOICES = {
@@ -91,15 +106,15 @@ function renameSlugPaths(dir, slug) {
91
106
  // the kit (cli/docker/) so authors can't edit it. Caller runs applyTokens after.
92
107
  // rclpy → templates/ros2 (ament_python)
93
108
  // rclcpp → templates/ros2-cpp (ament_cmake)
94
- export function overlayRos2(target, slug, rosClient = "rclpy") {
109
+ export async function overlayRos2(target, slug, rosClient = "rclpy") {
95
110
  const tmpl = rosClient === "rclcpp" ? "ros2-cpp" : "ros2";
96
- cpSync(resolve(templatesDir, tmpl), target, { recursive: true });
111
+ await copyTemplate(resolve(templatesDir, tmpl), target);
97
112
  renameSlugPaths(resolve(target, "ros2_ws"), slug);
98
113
  }
99
114
 
100
115
  // Copy the cpp/ overlay (CMake project) into a plugin. Caller runs applyTokens after.
101
- export function overlayCpp(target) {
102
- cpSync(resolve(templatesDir, "cpp"), target, { recursive: true });
116
+ export async function overlayCpp(target) {
117
+ await copyTemplate(resolve(templatesDir, "cpp"), target);
103
118
  }
104
119
 
105
120
  export async function runNew(args) {
@@ -171,10 +186,10 @@ export async function runNew(args) {
171
186
  // cpp → cpp/ 오버레이, py/·requirements.txt 제거
172
187
  // ros2(*) → ros2_ws/ 오버레이 (rclpy=ament_python, rclcpp=ament_cmake)
173
188
  log.step(`scaffolding ${type} plugin → ${target}`);
174
- cpSync(resolve(templatesDir, "common"), target, { recursive: true });
175
- if (runtimeChoice.type === "ros2") overlayRos2(target, slug, runtimeChoice.rosClient);
189
+ await copyTemplate(resolve(templatesDir, "common"), target);
190
+ if (runtimeChoice.type === "ros2") await overlayRos2(target, slug, runtimeChoice.rosClient);
176
191
  if (runtimeChoice.type === "cpp") {
177
- overlayCpp(target);
192
+ await overlayCpp(target);
178
193
  rmSync(resolve(target, "py"), { recursive: true, force: true });
179
194
  rmSync(resolve(target, "requirements.txt"), { force: true });
180
195
  }
package/cli/src/ros2.mjs CHANGED
@@ -89,7 +89,7 @@ export function colconBuild(root, { image = ROS2_DEV_IMAGE, symlink = false, arc
89
89
  const platformFlags = dockerPlatform ? ["--platform", dockerPlatform] : [];
90
90
  const r = spawnSync(
91
91
  "docker",
92
- ["run", "--rm", ...platformFlags, "-v", `${root}:/plugin`, "-w", "/plugin", actualImage, "bash", "-lc", script],
92
+ ["run", "--rm", ...platformFlags, "-e", "PIP_ROOT_USER_ACTION=ignore", "-v", `${root}:/plugin`, "-w", "/plugin", actualImage, "bash", "-lc", script],
93
93
  { cwd: root, stdio: "inherit" },
94
94
  );
95
95
  if (r.status !== 0) throw new Error(`colcon build failed${arch ? ` (${arch})` : ""}.`);
package/cli/src/type.mjs CHANGED
@@ -69,7 +69,7 @@ export async function runType(args) {
69
69
  log.warn("ros2_ws/ already exists — keeping it, only flipping manifest type.");
70
70
  } else {
71
71
  log.step(`adding ros2_ws/ overlay (${runtimeChoice.rosClient})`);
72
- overlayRos2(root, slug, runtimeChoice.rosClient);
72
+ await overlayRos2(root, slug, runtimeChoice.rosClient);
73
73
  applyTokens(root, {
74
74
  __PLUGIN_ID__: pluginId,
75
75
  __PLUGIN_NAME__: pluginName,
@@ -83,7 +83,7 @@ export async function runType(args) {
83
83
  log.warn("cpp/ already exists — keeping it, only flipping manifest type.");
84
84
  } else {
85
85
  log.step("adding cpp/ overlay");
86
- overlayCpp(root);
86
+ await overlayCpp(root);
87
87
  applyTokens(root, {
88
88
  __PLUGIN_ID__: pluginId,
89
89
  __PLUGIN_NAME__: pluginName,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rainbow-robotics/muscat-plugin-kit",
3
- "version": "0.1.2-dev.38",
3
+ "version": "0.1.2-dev.39",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": ">=20"
@@ -31,7 +31,7 @@
31
31
  "@types/react-dom": "^19.0.4"
32
32
  },
33
33
  "dependencies": {
34
- "@rainbow-robotics/preview-host": "0.1.2-dev.38",
34
+ "@rainbow-robotics/preview-host": "0.1.2-dev.39",
35
35
  "socket.io": "^4.8.1"
36
36
  },
37
37
  "optionalDependencies": {