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 +21 -0
- package/package.json +1 -1
- package/src/cli.js +5 -7
- package/src/scaffold.js +87 -17
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
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.
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
//
|
|
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`
|
|
74
|
-
//
|
|
75
|
-
//
|
|
76
|
-
//
|
|
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
|
|
97
|
-
//
|
|
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
|
|
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
|
-
|
|
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
|
|
175
|
-
|
|
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
|
|
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
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
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)
|