create-deka-app 0.53.6 → 0.53.7-canary-4551de1

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
@@ -53,6 +53,32 @@ pin fails, create-deka-app falls back to the latest published
53
53
  `@dekaruntime/deka` version, prints a clear warning, and never leaves a
54
54
  nonexistent version pinned in the generated `package.json`.
55
55
 
56
+ ## Channels
57
+
58
+ There are two channels, [rfd#68](https://github.com/dekaruntime/rfd/issues/68):
59
+
60
+ ```sh
61
+ npx create-deka-app@latest myapp # stable (the default)
62
+ npx create-deka-app@canary myapp # canary
63
+ ```
64
+
65
+ **Stable** (`npx create-deka-app@latest`, or just `npx create-deka-app`) pins
66
+ a plain `X.Y.Z` deka runtime — the default, and what everyone not
67
+ deliberately opting in gets.
68
+
69
+ **Canary** (`npx create-deka-app@canary`) pins a prerelease version shaped
70
+ `X.Y.Z-canary-<7-char-commit-sha>` (e.g. `0.59.0-canary-d5661ed`) — every
71
+ merge to deka's `main` branch, published immediately, before a human has
72
+ promoted it to stable. Lockstep versioning holds within a channel: a canary
73
+ create-deka-app pins the *matching* canary `@dekaruntime/deka`, never a
74
+ stable one.
75
+
76
+ A canary's binaries report their **base version** on `deka --version` /
77
+ `dsc --version` — `0.59.0`, never `0.59.0-canary-d5661ed`. Promotion
78
+ republishes the exact same compiled bytes under the plain stable tag, so
79
+ the binary itself never learns it was ever a canary; only the git tag, the
80
+ R2 path and the npm version string say so.
81
+
56
82
  ## Platforms
57
83
 
58
84
  | Platform | Status |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-deka-app",
3
- "version": "0.53.6",
3
+ "version": "0.53.7-canary-4551de1",
4
4
  "description": "Scaffold a new deka app",
5
5
  "bin": {
6
6
  "create-deka-app": "./index.js"
package/src/channel.js ADDED
@@ -0,0 +1,36 @@
1
+ // rfd#68 (Release Channels): a version carries its channel in its own
2
+ // string. `X.Y.Z-canary-<sha>` is a canary -- a build published under the
3
+ // `canary` npm dist-tag, from a `vX.Y.Z-canary-<sha>` release tag. Anything
4
+ // else (plain `X.Y.Z`) is stable, published under `latest`.
5
+ //
6
+ // Shared between the CLI this package ships (src/scaffold.js: the lockstep
7
+ // pin and its registry-lookup fallback) and the release pipeline that is
8
+ // NOT shipped (scripts/lib/manifest.js: R2 URL shapes) -- kept in src/ (not
9
+ // scripts/) because scripts/ is excluded from the published npm tarball
10
+ // (see package.json "files"), so anything scaffold.js depends on has to
11
+ // live somewhere that ships.
12
+ // https://github.com/dekaruntime/rfd/issues/68
13
+ const CANARY_SUFFIX = /-canary-[0-9a-f]+$/i
14
+
15
+ export function versionChannel(version) {
16
+ return CANARY_SUFFIX.test(String(version)) ? 'canary' : 'stable'
17
+ }
18
+
19
+ export function distTagFor(channel) {
20
+ return channel === 'canary' ? 'canary' : 'latest'
21
+ }
22
+
23
+ // The base version a canary's own binaries report on `--version`.
24
+ // Promotion republishes the exact same bytes under the plain tag, so a
25
+ // canary build never learns it is a canary -- its `--version` output
26
+ // always names the base version (plus a commit sha), never the
27
+ // "-canary-<sha>" suffix. Manifests written under rfd#68 carry an explicit
28
+ // `base_version` field; a manifest that predates it (or a caller that
29
+ // hasn't fetched one) falls back to stripping the suffix from the full
30
+ // version string.
31
+ export function baseVersionOf(version, manifest) {
32
+ if (manifest && typeof manifest.base_version === 'string' && manifest.base_version) {
33
+ return manifest.base_version
34
+ }
35
+ return String(version).replace(CANARY_SUFFIX, '')
36
+ }
package/src/scaffold.js CHANGED
@@ -3,6 +3,7 @@ import { spawnSync } from 'node:child_process'
3
3
  import path from 'node:path'
4
4
  import { detectPackageManager } from './package-manager.js'
5
5
  import { isSupportedPlatform, platformKey } from './platform.js'
6
+ import { versionChannel, distTagFor } from './channel.js'
6
7
 
7
8
  // Thrown for every expected failure. `message` is written straight to
8
9
  // stderr, so it always says what happened and what to do about it.
@@ -104,21 +105,33 @@ export function buildPackageJson(dirName, runtimeVersion) {
104
105
  // create or bun create, and `npm view` is a read-only registry query with
105
106
  // no project-local side effects.
106
107
  //
107
- // Falls back to the "latest" dist-tag -- never to a version we already
108
- // know is wrong -- if the registry can't be reached (offline, registry
109
- // outage, etc), and says so via `log` so the fallback is visible.
110
- export function resolveLatestRuntimeVersion({ spawn = spawnSync, cwd = process.cwd(), log = console.log } = {}) {
111
- const result = spawn('npm', ['view', RUNTIME_PACKAGE, 'version'], { cwd, encoding: 'utf8' })
108
+ // Falls back to the running version's OWN channel's dist-tag -- never to a
109
+ // version we already know is wrong, and never silently to `latest` for a
110
+ // canary -- if the registry can't be reached (offline, registry outage,
111
+ // etc), and says so via `log` so the fallback is visible.
112
+ //
113
+ // rfd#68: `channel` is the channel of the create-deka-app version that is
114
+ // running (see resolveRuntimeVersion / createApp below) -- `canary` looks
115
+ // up `@dekaruntime/deka@canary`, so `npx create-deka-app@canary myapp`
116
+ // falls back onto another canary build, never quietly onto `latest` stable.
117
+ export function resolveLatestRuntimeVersion({
118
+ spawn = spawnSync,
119
+ cwd = process.cwd(),
120
+ log = console.log,
121
+ channel = 'stable',
122
+ } = {}) {
123
+ const distTag = distTagFor(channel)
124
+ const result = spawn('npm', ['view', `${RUNTIME_PACKAGE}@${distTag}`, 'version'], { cwd, encoding: 'utf8' })
112
125
 
113
126
  const version =
114
127
  result && !result.error && result.status === 0 ? String(result.stdout || '').trim() : ''
115
128
 
116
129
  if (!version) {
117
130
  log(
118
- `> Could not resolve the latest ${RUNTIME_PACKAGE} version from the npm registry ` +
119
- '(offline, or the registry is unreachable); pinning "latest" instead.'
131
+ `> Could not resolve the ${distTag} ${RUNTIME_PACKAGE} version from the npm registry ` +
132
+ `(offline, or the registry is unreachable); pinning "${distTag}" instead.`
120
133
  )
121
- return 'latest'
134
+ return distTag
122
135
  }
123
136
 
124
137
  return version
@@ -234,7 +247,7 @@ export function createApp({
234
247
  `This can happen when create-deka-app@${ownVersion} shipped before its matching runtime build did. ` +
235
248
  'Falling back to the latest published version instead.'
236
249
  )
237
- const fallbackVersion = resolveLatestRuntimeVersion({ spawn, cwd: targetDir, log })
250
+ const fallbackVersion = resolveLatestRuntimeVersion({ spawn, cwd: targetDir, log, channel: versionChannel(ownVersion) })
238
251
  if (fallbackVersion === runtimeVersion) {
239
252
  throw new ScaffoldError(
240
253
  `"${pm.name} install" failed in ${targetDir} (exit code ${install.status}), ` +