@podosoft/podokit 0.17.2 → 0.17.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.
package/dist/dev.js CHANGED
@@ -156,10 +156,15 @@ function writeRuntimeFiles(runtime) {
156
156
  (0, node_fs_1.writeFileSync)(runtime.runtimeComposePath, renderRuntimeCompose(runtime));
157
157
  }
158
158
  function registerRoute(runtime) {
159
- const collision = activeEntries().find((entry) => entry.hostname === runtime.config.hostname && entry.projectRoot !== runtime.projectRoot);
159
+ const entries = activeEntries();
160
+ const collision = entries.find((entry) => entry.hostname === runtime.config.hostname && entry.projectRoot !== runtime.projectRoot);
160
161
  if (collision) {
161
162
  throw new Error(`Development hostname ${runtime.config.hostname} is already registered by ${collision.projectRoot}. Change .podokit/dev.json or run podo dev down there.`);
162
163
  }
164
+ for (const stale of entries.filter((entry) => entry.projectRoot === runtime.projectRoot && entry.routeId !== runtime.routeId)) {
165
+ (0, node_fs_1.rmSync)((0, node_path_1.join)(registryDirectory(), `${stale.routeId}.json`), { force: true });
166
+ (0, node_fs_1.rmSync)((0, node_path_1.join)(routesDirectory(), `${stale.routeId}.yml`), { force: true });
167
+ }
163
168
  (0, node_fs_1.mkdirSync)(registryDirectory(), { recursive: true });
164
169
  (0, node_fs_1.mkdirSync)(routesDirectory(), { recursive: true });
165
170
  (0, node_fs_1.writeFileSync)(routePath(runtime), renderRoute(runtime));
@@ -307,6 +312,23 @@ function runDevCommand(projectRoot, action, args, runner = defaultRunner) {
307
312
  }
308
313
  return;
309
314
  }
315
+ if (action === "up") {
316
+ ensureNetwork(runner);
317
+ registerRoute(runtime);
318
+ try {
319
+ ensureGateway(runner);
320
+ process.stdout.write(`Development URL: http://${runtime.config.hostname}\n`);
321
+ if (runtime.config.publicUrl)
322
+ process.stdout.write(`Public OAuth URL: ${runtime.config.publicUrl}\n`);
323
+ runCompose(runtime, composeCommand("up", args, profiles), runner);
324
+ }
325
+ catch (error) {
326
+ unregisterRoute(runtime);
327
+ stopGatewayWhenUnused(runner);
328
+ throw error;
329
+ }
330
+ return;
331
+ }
310
332
  if (action === "down") {
311
333
  runCompose(runtime, composeCommand("down", args, profiles), runner);
312
334
  unregisterRoute(runtime);
@@ -317,5 +339,5 @@ function runDevCommand(projectRoot, action, args, runner = defaultRunner) {
317
339
  runCompose(runtime, composeCommand(action, args, profiles), runner);
318
340
  return;
319
341
  }
320
- throw new Error("Usage: podo dev <watch|exec|logs|ps|down|url> [docker compose options]");
342
+ throw new Error("Usage: podo dev <watch|up|exec|logs|ps|down|url> [docker compose options]");
321
343
  }
@@ -27,6 +27,7 @@ Run lifecycle and container commands from a second terminal:
27
27
 
28
28
  ```bash
29
29
  npx @podosoft/podokit dev url
30
+ npx @podosoft/podokit dev up -d # detached stack without source watching
30
31
  npx @podosoft/podokit dev ps
31
32
  npx @podosoft/podokit dev logs
32
33
  npx @podosoft/podokit dev exec api npm run migration:run -w {{projectName}}-api
@@ -35,6 +36,8 @@ npx @podosoft/podokit dev down
35
36
 
36
37
  `dev watch` reads `.podokit/manifest.json` and automatically activates `cache`,
37
38
  `storage`, and `queue` when installed modules require Redis, MinIO, or a worker.
39
+ `dev up` uses the same shared gateway and module profiles without keeping Compose
40
+ Watch attached.
38
41
  You can still activate an additional Compose profile explicitly:
39
42
 
40
43
  ```bash
@@ -28,6 +28,7 @@ In a second terminal, apply the included Todo migration and use the lifecycle he
28
28
  ```bash
29
29
  npx @podosoft/podokit dev exec api npm run migration:run -w {{projectName}}-api
30
30
  npx @podosoft/podokit dev url
31
+ npx @podosoft/podokit dev up -d # detached stack without source watching
31
32
  npx @podosoft/podokit dev ps
32
33
  npx @podosoft/podokit dev logs
33
34
  npx @podosoft/podokit dev down
@@ -35,6 +36,8 @@ npx @podosoft/podokit dev down
35
36
 
36
37
  `dev watch` reads `.podokit/manifest.json` and automatically activates `cache`,
37
38
  `storage`, and `queue` when installed modules require Redis, MinIO, or a worker.
39
+ `dev up` uses the same shared gateway and module profiles without keeping Compose
40
+ Watch attached.
38
41
  You can still activate an additional Compose profile explicitly:
39
42
 
40
43
  ```bash
package/dist/update.js CHANGED
@@ -151,6 +151,14 @@ function planUpdate(projectRoot, templatesDir) {
151
151
  const classified = (0, lockfile_1.classifyTier)(path, newText ?? disk ?? "", ownedGlobs, managedOverrides);
152
152
  const tier = controlledByTarget ? classified : locked?.tier ?? classified;
153
153
  if (tier === "owned") {
154
+ // A file introduced by a newer template or module has no previous lock
155
+ // entry. Seed it once when the application has not already claimed that
156
+ // path; subsequent edits or deletions stay protected by the recorded
157
+ // owned entry.
158
+ if (!locked && disk === null && newText !== null) {
159
+ changes.push({ path, tier, action: "add", note: "new owned seed in this version" });
160
+ continue;
161
+ }
154
162
  const explicitlyOwned = ownedGlobs.some((glob) => !glob.includes("*") && (0, lockfile_1.matchGlob)(path, glob));
155
163
  changes.push({
156
164
  path,
@@ -283,6 +291,18 @@ function updatedFilesLock(projectRoot, newTree, previous, ownedGlobs, managedOve
283
291
  delete next.files[path];
284
292
  }
285
293
  }
294
+ // Keep a tombstone for an owned seed that the application deleted or moved.
295
+ // Without the previous entry, the next update would mistake the missing path
296
+ // for a newly introduced seed and recreate it.
297
+ for (const [path, entry] of Object.entries(previous.files)) {
298
+ if (entry.tier !== "owned" || next.files[path])
299
+ continue;
300
+ const newText = treeText(newTree, path);
301
+ if (newText !== null &&
302
+ (0, lockfile_1.classifyTier)(path, newText, ownedGlobs, managedOverrides) === "owned") {
303
+ next.files[path] = entry;
304
+ }
305
+ }
286
306
  return next;
287
307
  }
288
308
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@podosoft/podokit",
3
- "version": "0.17.2",
3
+ "version": "0.17.3",
4
4
  "description": "An opinionated but extensible starter toolkit and CLI for full-stack TypeScript apps with NestJS, SvelteKit, TailwindCSS, shadcn-svelte, Docker, and k3s.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {