@podosoft/podokit 0.16.0 → 0.16.2

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.
@@ -38,7 +38,7 @@ ${annotations.map((annotation) => ` ${annotation}`).join("\n")}`;
38
38
  }
39
39
  function storageClassLine(dependency) {
40
40
  return dependency.storageClassName
41
- ? ` storageClassName: ${quote(dependency.storageClassName)}\n`
41
+ ? ` storageClassName: ${quote(dependency.storageClassName)}\n`
42
42
  : "";
43
43
  }
44
44
  function resources(profile, indent = 10) {
package/dist/deploy.js CHANGED
@@ -529,9 +529,13 @@ function deploymentLockName(profile) {
529
529
  const prefix = profile.target.release.slice(0, 39).replace(/-+$/g, "");
530
530
  return `${prefix}-${suffix}-deploy-lock`;
531
531
  }
532
+ function kubernetesMicroTime(date) {
533
+ return `${date.toISOString().slice(0, -1)}000Z`;
534
+ }
532
535
  function acquireDeploymentLock(profile, runner) {
533
536
  const name = deploymentLockName(profile);
534
537
  const holderIdentity = `podokit:${(0, node_crypto_1.randomUUID)()}`;
538
+ const timestamp = kubernetesMicroTime(new Date());
535
539
  const temporaryRoot = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "podokit-deploy-lock-"));
536
540
  const manifestPath = (0, node_path_1.join)(temporaryRoot, "lease.json");
537
541
  (0, node_fs_1.writeFileSync)(manifestPath, JSON.stringify({
@@ -544,8 +548,8 @@ function acquireDeploymentLock(profile, runner) {
544
548
  spec: {
545
549
  holderIdentity,
546
550
  leaseDurationSeconds: 3600,
547
- acquireTime: new Date().toISOString(),
548
- renewTime: new Date().toISOString(),
551
+ acquireTime: timestamp,
552
+ renewTime: timestamp,
549
553
  },
550
554
  }));
551
555
  try {
package/dist/update.js CHANGED
@@ -23,6 +23,56 @@ function diskContent(projectRoot, path) {
23
23
  const abs = (0, node_path_1.join)(projectRoot, path);
24
24
  return (0, node_fs_1.existsSync)(abs) ? (0, node_fs_1.readFileSync)(abs) : null;
25
25
  }
26
+ /**
27
+ * Expand the recorded module list against the target manifests. A module may
28
+ * gain a new requirement after it was first added to a project; updates must
29
+ * apply that requirement before rebuilding the dependent module or the target
30
+ * tree can contain imports and wiring for files that were never installed.
31
+ */
32
+ function targetModules(projectRoot, templatesDir, modules) {
33
+ const modulesDir = (0, node_path_1.join)(templatesDir, "modules");
34
+ const recorded = new Map(modules.map((module) => [module.name, module]));
35
+ const ordered = [];
36
+ const visiting = new Set();
37
+ const visited = new Set();
38
+ const visit = (name, requiredBy) => {
39
+ if (visited.has(name))
40
+ return;
41
+ if (visiting.has(name)) {
42
+ throw new Error(`Module dependency cycle detected at "${name}".`);
43
+ }
44
+ const existing = recorded.get(name);
45
+ const resolved = (0, add_1.resolveModule)(existing?.packageName ?? name, modulesDir, projectRoot);
46
+ if (!resolved) {
47
+ throw new Error(requiredBy
48
+ ? `Module "${requiredBy}" requires unknown module "${name}".`
49
+ : `Cannot resolve module "${name}" while updating the project.`);
50
+ }
51
+ visiting.add(name);
52
+ const moduleManifest = (0, add_1.readModuleManifest)(resolved.dir);
53
+ for (const required of moduleManifest.requires ?? [])
54
+ visit(required, name);
55
+ visiting.delete(name);
56
+ visited.add(name);
57
+ ordered.push({
58
+ ...(existing ?? {
59
+ name: resolved.name,
60
+ addedWith: (0, lockfile_1.podokitVersion)(),
61
+ }),
62
+ order: ordered.length,
63
+ ...(resolved.packageName
64
+ ? {
65
+ packageName: resolved.packageName,
66
+ moduleVersion: resolved.moduleVersion,
67
+ }
68
+ : {}),
69
+ });
70
+ };
71
+ for (const module of [...modules].sort((a, b) => a.order - b.order)) {
72
+ visit(module.name);
73
+ }
74
+ return ordered;
75
+ }
26
76
  function targetManagedOverrides(projectRoot, templatesDir, modules, current = []) {
27
77
  const overrides = new Set(current);
28
78
  const modulesDir = (0, node_path_1.join)(templatesDir, "modules");
@@ -56,16 +106,17 @@ function planUpdate(projectRoot, templatesDir) {
56
106
  const lock = (0, lockfile_1.readFilesLock)(projectRoot);
57
107
  if (!manifest || !lock)
58
108
  throw new inspect_1.NotAProjectError();
109
+ const modules = targetModules(projectRoot, templatesDir, manifest.modules);
59
110
  const newTree = (0, assemble_1.assembleProject)({
60
111
  templatesDir,
61
112
  template: manifest.template,
62
113
  answers: manifest.answers,
63
- modules: manifest.modules,
114
+ modules,
64
115
  projectRoot,
65
116
  });
66
- const managedOverrides = targetManagedOverrides(projectRoot, templatesDir, manifest.modules, manifest.managedOverrides);
67
- const ownedGlobs = targetOwnedGlobs(projectRoot, templatesDir, manifest.modules, manifest.ownedGlobs);
68
- const pendingMigrations = (0, module_migrations_1.collectPendingMigrations)(projectRoot, templatesDir, manifest.modules);
117
+ const managedOverrides = targetManagedOverrides(projectRoot, templatesDir, modules, manifest.managedOverrides);
118
+ const ownedGlobs = targetOwnedGlobs(projectRoot, templatesDir, modules, manifest.ownedGlobs);
119
+ const pendingMigrations = (0, module_migrations_1.collectPendingMigrations)(projectRoot, templatesDir, modules);
69
120
  const migrationPlan = (0, module_migrations_1.planModuleMigrations)(projectRoot, newTree, lock, pendingMigrations);
70
121
  const changes = migrationPlan.moves.map((move) => ({
71
122
  path: move.to,
@@ -147,7 +198,7 @@ function planUpdate(projectRoot, templatesDir) {
147
198
  fromVersion: manifest.podokitVersion,
148
199
  toVersion: (0, lockfile_1.podokitVersion)(),
149
200
  template: manifest.template,
150
- modules: manifest.modules.map((m) => m.name),
201
+ modules: modules.map((module) => module.name),
151
202
  changes,
152
203
  };
153
204
  }
@@ -247,7 +298,7 @@ function applyUpdate(projectRoot, templatesDir, options = {}) {
247
298
  if (!manifest || !previousLock)
248
299
  throw new inspect_1.NotAProjectError();
249
300
  const plan = planUpdate(projectRoot, templatesDir);
250
- const modules = manifest.modules;
301
+ const modules = targetModules(projectRoot, templatesDir, manifest.modules);
251
302
  const newTree = (0, assemble_1.assembleProject)({
252
303
  templatesDir,
253
304
  template: manifest.template,
@@ -273,13 +324,13 @@ function applyUpdate(projectRoot, templatesDir, options = {}) {
273
324
  const needsMergeBase = plan.changes.some((change) => change.action === "conflict");
274
325
  let oldTree = null;
275
326
  if (options.oldTemplatesDir && needsMergeBase) {
276
- const previousModules = previousExternalModules(projectRoot, options.oldTemplatesDir, modules, options.oldExternalModulesRoot);
327
+ const previousModules = previousExternalModules(projectRoot, options.oldTemplatesDir, manifest.modules, options.oldExternalModulesRoot);
277
328
  try {
278
329
  oldTree = (0, assemble_1.assembleProject)({
279
330
  templatesDir: options.oldTemplatesDir,
280
331
  template: manifest.template,
281
332
  answers: manifest.answers,
282
- modules,
333
+ modules: manifest.modules,
283
334
  projectRoot: previousModules.root,
284
335
  });
285
336
  }
@@ -332,7 +383,7 @@ function applyUpdate(projectRoot, templatesDir, options = {}) {
332
383
  ids.push(pending.migration.id);
333
384
  appliedMigrations.set(pending.module, ids);
334
385
  }
335
- const refreshedModules = manifest.modules.map((module) => {
386
+ const refreshedModules = modules.map((module) => {
336
387
  const resolved = (0, add_1.resolveModule)(module.packageName ?? module.name, modulesDir, projectRoot);
337
388
  const applied = [
338
389
  ...new Set([
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@podosoft/podokit",
3
- "version": "0.16.0",
3
+ "version": "0.16.2",
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": {