create-deka-app 0.0.6 → 0.53.6

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/README.md CHANGED
@@ -32,6 +32,27 @@ everything non-interactively — no prompts:
32
32
  See [deka#1091](https://github.com/dekaruntime/deka/issues/1091) for the
33
33
  design history.
34
34
 
35
+ ## Versioning
36
+
37
+ **create-deka-app's version always equals the deka runtime version it
38
+ scaffolds.** `create-deka-app@0.53.4` pins `@dekaruntime/deka@0.53.4` — not
39
+ some other version, and never its own separate `0.0.x` release line. The
40
+ two publish together, from the same CI run (`.github/workflows/publish-runtime.yml`,
41
+ the `deka` family), so a given create-deka-app version always produces the
42
+ same project: no registry lookup needed to decide the pin.
43
+
44
+ There is one publish path for this whole repo: create-deka-app has no
45
+ standalone release of its own. The version in this repo's own
46
+ `package.json` is a `0.0.0` placeholder — it is never bumped by hand or
47
+ committed as part of a release; the workflow stamps the real version into
48
+ it at publish time, in the working tree only.
49
+
50
+ The one exception to the lockstep pin is a create-deka-app release whose
51
+ exact-matching runtime build isn't published yet. If installing the exact
52
+ pin fails, create-deka-app falls back to the latest published
53
+ `@dekaruntime/deka` version, prints a clear warning, and never leaves a
54
+ nonexistent version pinned in the generated `package.json`.
55
+
35
56
  ## Platforms
36
57
 
37
58
  | Platform | Status |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-deka-app",
3
- "version": "0.0.6",
3
+ "version": "0.53.6",
4
4
  "description": "Scaffold a new deka app",
5
5
  "bin": {
6
6
  "create-deka-app": "./index.js"
package/src/cli.js CHANGED
@@ -17,17 +17,15 @@ export function run({
17
17
  cwd = process.cwd(),
18
18
  log = console.log,
19
19
  error = console.error,
20
- // create-deka-app's own version. Not currently used by createApp -- the
21
- // runtime version it pins in the generated package.json is resolved
22
- // separately, from the npm registry, since create-deka-app's own 0.0.x
23
- // line and @dekaruntime/deka's release line are not in lockstep. Kept
24
- // here as the CLI's own version for whatever legitimately needs it
25
- // (e.g. a future `--version` flag).
20
+ // create-deka-app's own version. Under lockstep versioning this IS the
21
+ // @dekaruntime/deka version createApp pins in the generated
22
+ // package.json (see src/scaffold.js) -- create-deka-app@X.Y.Z always
23
+ // scaffolds @dekaruntime/deka@X.Y.Z.
26
24
  ownVersion = ownPackageJson.version,
27
25
  } = {}) {
28
26
  const targetArg = argv[0]
29
27
  try {
30
- return createApp({ targetArg, cwd, env, log })
28
+ return createApp({ targetArg, cwd, env, log, ownVersion })
31
29
  } catch (err) {
32
30
  if (err instanceof ScaffoldError) {
33
31
  error(err.message)
package/src/scaffold.js CHANGED
@@ -70,12 +70,10 @@ export const RUNTIME_PACKAGE = '@dekaruntime/deka'
70
70
  // project. Exported so the test suite can assert on it directly without
71
71
  // re-deriving the shape.
72
72
  //
73
- // `runtimeVersion` must be the @dekaruntime/deka version resolved at
74
- // scaffold time (see resolveRuntimeVersion below) -- never this package's
75
- // own version. create-deka-app has its own 0.0.x release line and
76
- // @dekaruntime/deka tracks deka's releases; the two are not in lockstep
77
- // and never will be, so passing this package's own version here pins a
78
- // version of the runtime that may not exist (see deka#1076-era bug).
73
+ // `runtimeVersion` is whatever create-deka-app decided to pin -- under
74
+ // lockstep versioning (see createApp below) that is this scaffolder's own
75
+ // version in the common case, or the registry-resolved fallback version
76
+ // when the exact match hasn't been published.
79
77
  export function buildPackageJson(dirName, runtimeVersion) {
80
78
  return {
81
79
  name: sanitizePackageName(dirName),
@@ -93,8 +91,12 @@ export function buildPackageJson(dirName, runtimeVersion) {
93
91
  }
94
92
 
95
93
  // Looks up the latest published @dekaruntime/deka version from the npm
96
- // registry so the generated package.json pins something that actually
97
- // exists, rather than assuming it matches create-deka-app's own version.
94
+ // registry. This is the FALLBACK path only -- under lockstep versioning,
95
+ // create-deka-app@X.Y.Z always scaffolds @dekaruntime/deka@X.Y.Z directly
96
+ // (see resolveRuntimeVersion below), with no registry call. This function
97
+ // is reached only when that exact pin failed to install, e.g. a
98
+ // create-deka-app release that published before its matching runtime
99
+ // build finished.
98
100
  //
99
101
  // Always shells out to `npm` for this lookup (not the detected package
100
102
  // manager) -- npm ships with every Node.js install, so it is available
@@ -105,7 +107,7 @@ export function buildPackageJson(dirName, runtimeVersion) {
105
107
  // Falls back to the "latest" dist-tag -- never to a version we already
106
108
  // know is wrong -- if the registry can't be reached (offline, registry
107
109
  // outage, etc), and says so via `log` so the fallback is visible.
108
- export function resolveRuntimeVersion({ spawn = spawnSync, cwd = process.cwd(), log = console.log } = {}) {
110
+ export function resolveLatestRuntimeVersion({ spawn = spawnSync, cwd = process.cwd(), log = console.log } = {}) {
109
111
  const result = spawn('npm', ['view', RUNTIME_PACKAGE, 'version'], { cwd, encoding: 'utf8' })
110
112
 
111
113
  const version =
@@ -122,6 +124,23 @@ export function resolveRuntimeVersion({ spawn = spawnSync, cwd = process.cwd(),
122
124
  return version
123
125
  }
124
126
 
127
+ // Decides which @dekaruntime/deka version to pin in the scaffolded
128
+ // project. `ownVersion` is create-deka-app's own version -- under
129
+ // lockstep versioning (README: "create-deka-app's version always equals
130
+ // the deka runtime version it scaffolds") that IS the runtime version, so
131
+ // this returns it directly with no network call: a given create-deka-app
132
+ // version always produces the same pin, reproducibly.
133
+ //
134
+ // This is exported only so the test suite can call it directly; createApp
135
+ // below is what actually decides whether the pin needs the fallback (that
136
+ // requires attempting the install, which this function does not do).
137
+ export function resolveRuntimeVersion({ ownVersion }) {
138
+ if (!ownVersion) {
139
+ throw new Error('resolveRuntimeVersion requires ownVersion')
140
+ }
141
+ return ownVersion
142
+ }
143
+
125
144
  /**
126
145
  * Orchestrates the scaffold. Everything the real `deka init` binary is
127
146
  * responsible for (writing app/, public/, deka.json, deka.lock, printing
@@ -139,11 +158,16 @@ export function createApp({
139
158
  arch = process.arch,
140
159
  spawn = spawnSync,
141
160
  log = console.log,
161
+ ownVersion,
142
162
  } = {}) {
143
163
  if (!targetArg) {
144
164
  throw new ScaffoldError(USAGE, 1)
145
165
  }
146
166
 
167
+ if (!ownVersion) {
168
+ throw new Error('createApp requires ownVersion (create-deka-app pins it as the runtime version)')
169
+ }
170
+
147
171
  if (!isSupportedPlatform(platform, arch)) {
148
172
  throw new ScaffoldError(
149
173
  `create-deka-app does not support ${platformKey(platform, arch)} yet.\n` +
@@ -169,16 +193,33 @@ export function createApp({
169
193
  mkdirSync(targetDir, { recursive: true })
170
194
  }
171
195
 
172
- const runtimeVersion = resolveRuntimeVersion({ spawn, cwd: targetDir, log })
196
+ // Lockstep versioning: create-deka-app@X.Y.Z always pins
197
+ // @dekaruntime/deka@X.Y.Z -- this is create-deka-app's own version, so
198
+ // deciding the pin needs no network call and is fully reproducible (a
199
+ // given create-deka-app version always produces the same project).
200
+ //
201
+ // The one case this doesn't cover is a create-deka-app release whose
202
+ // exact-matching runtime build isn't published yet (there is no
203
+ // standalone scaffolder-only release path -- one publish path,
204
+ // .github/workflows/publish-runtime.yml). That surfaces as the install
205
+ // below failing, and is handled as a fallback: re-resolve against the
206
+ // registry and retry once, never silently leaving a nonexistent version
207
+ // pinned in the final package.json (the ETARGET bug fixed in 0.0.3).
208
+ let runtimeVersion = resolveRuntimeVersion({ ownVersion })
173
209
 
174
- const pkg = buildPackageJson(path.basename(targetDir), runtimeVersion)
175
- writeFileSync(path.join(targetDir, 'package.json'), `${JSON.stringify(pkg, null, 2)}\n`)
210
+ const writePackageJson = (version) => {
211
+ const pkg = buildPackageJson(path.basename(targetDir), version)
212
+ writeFileSync(path.join(targetDir, 'package.json'), `${JSON.stringify(pkg, null, 2)}\n`)
213
+ }
214
+ writePackageJson(runtimeVersion)
176
215
 
177
216
  const pm = detectPackageManager(env)
178
217
  log(`> Using ${pm.name} to install @dekaruntime/deka...`)
179
218
 
180
219
  const [installCmd, installArgs] = pm.install
181
- const install = spawn(installCmd, installArgs, { cwd: targetDir, stdio: 'inherit' })
220
+ const runInstall = () => spawn(installCmd, installArgs, { cwd: targetDir, stdio: 'inherit' })
221
+
222
+ let install = runInstall()
182
223
 
183
224
  if (install.error) {
184
225
  throw new ScaffoldError(
@@ -186,12 +227,41 @@ export function createApp({
186
227
  `Make sure ${pm.name} is installed and on your PATH, then run it there yourself.`
187
228
  )
188
229
  }
230
+
189
231
  if (install.status !== 0) {
190
- throw new ScaffoldError(
191
- `"${pm.name} install" failed in ${targetDir} (exit code ${install.status}).\n` +
192
- 'Run it there yourself to see the full error.',
193
- install.status ?? 1
232
+ log(
233
+ `> "${pm.name} install" could not install ${RUNTIME_PACKAGE}@${runtimeVersion} (exit code ${install.status}). ` +
234
+ `This can happen when create-deka-app@${ownVersion} shipped before its matching runtime build did. ` +
235
+ 'Falling back to the latest published version instead.'
194
236
  )
237
+ const fallbackVersion = resolveLatestRuntimeVersion({ spawn, cwd: targetDir, log })
238
+ if (fallbackVersion === runtimeVersion) {
239
+ throw new ScaffoldError(
240
+ `"${pm.name} install" failed in ${targetDir} (exit code ${install.status}), ` +
241
+ `and the npm registry also reports ${RUNTIME_PACKAGE}@${fallbackVersion} as the latest version.\n` +
242
+ 'Run it there yourself to see the full error.',
243
+ install.status ?? 1
244
+ )
245
+ }
246
+
247
+ runtimeVersion = fallbackVersion
248
+ writePackageJson(runtimeVersion)
249
+ install = runInstall()
250
+
251
+ if (install.error) {
252
+ throw new ScaffoldError(
253
+ `Could not run "${pm.name} install" in ${targetDir}: ${install.error.message}\n` +
254
+ `Make sure ${pm.name} is installed and on your PATH, then run it there yourself.`
255
+ )
256
+ }
257
+ if (install.status !== 0) {
258
+ throw new ScaffoldError(
259
+ `"${pm.name} install" failed in ${targetDir} (exit code ${install.status}), ` +
260
+ `even after falling back to ${RUNTIME_PACKAGE}@${runtimeVersion}.\n` +
261
+ 'Run it there yourself to see the full error.',
262
+ install.status ?? 1
263
+ )
264
+ }
195
265
  }
196
266
 
197
267
  const dekaBin = dekaBinPath(targetDir, platform)