@brust/create-app 2.0.0-alpha.33 → 2.0.0-alpha.34
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/package.json +1 -1
- package/src/cli.ts +3 -1
- package/src/dep.ts +13 -7
- package/src/shadcn.ts +17 -4
package/package.json
CHANGED
package/src/cli.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// `create-app` main — a port of 0.1.x runNew (runtime/cli/new.ts:221-294) with the v2 dependency resolution.
|
|
2
2
|
import { existsSync, readFileSync } from 'node:fs'
|
|
3
3
|
import { readdir, rm } from 'node:fs/promises'
|
|
4
|
+
import { isAbsolute, relative, sep } from 'node:path'
|
|
4
5
|
import { copyTemplate } from './copy.ts'
|
|
5
6
|
import { parseArgs, USAGE } from './args.ts'
|
|
6
7
|
import { applyOverrides, monorepoRoot, resolveBrustDep } from './dep.ts'
|
|
@@ -67,7 +68,8 @@ export async function main(argv: string[]): Promise<void> {
|
|
|
67
68
|
|
|
68
69
|
function printNextSteps(name: string, targetDir: string, template: string, spec: string, workspace: boolean, installed = false): void {
|
|
69
70
|
const cwd = process.cwd()
|
|
70
|
-
const
|
|
71
|
+
const rel = relative(cwd, targetDir)
|
|
72
|
+
const displayPath = rel !== '' && !isAbsolute(rel) && rel !== '..' && !rel.startsWith(`..${sep}`) ? `./${rel.split(sep).join('/')}` : targetDir
|
|
71
73
|
console.log(`Created ${name} at ${targetDir} (template: ${template}, @brust/core ${spec})\n`)
|
|
72
74
|
console.log('Next:')
|
|
73
75
|
console.log(` cd ${shq(displayPath)}`)
|
package/src/dep.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// Resolves the `@brust/core` spec written into a scaffolded package.json (`__BRUST_DEP__`, M3-F rulings R2/R3).
|
|
2
2
|
import { existsSync, readFileSync, writeFileSync } from 'node:fs'
|
|
3
|
-
import { dirname, join, relative, resolve } from 'node:path'
|
|
3
|
+
import { dirname, join, relative, resolve, sep } from 'node:path'
|
|
4
4
|
|
|
5
5
|
/** = scripts/release-files.ts PLATS. */
|
|
6
|
-
export const PLATS = ['darwin-x64', 'darwin-arm64', 'linux-x64-gnu', 'linux-arm64-gnu', 'linux-x64-musl', 'linux-arm64-musl'] as const
|
|
6
|
+
export const PLATS = ['darwin-x64', 'darwin-arm64', 'linux-x64-gnu', 'linux-arm64-gnu', 'linux-x64-musl', 'linux-arm64-musl', 'win32-x64-msvc'] as const
|
|
7
7
|
|
|
8
8
|
export interface BrustDep {
|
|
9
9
|
kind: 'explicit' | 'version' | 'workspace' | 'file'
|
|
@@ -31,11 +31,16 @@ export function monorepoRoot(pkgRoot = packageRoot()): string | null {
|
|
|
31
31
|
function inWorkspace(root: string, target: string): boolean {
|
|
32
32
|
const rootPkg = readJson(join(root, 'package.json'))
|
|
33
33
|
const globs = (rootPkg?.workspaces as string[] | undefined) ?? []
|
|
34
|
-
const rel = relative(root, resolve(target))
|
|
34
|
+
const rel = fileSpecPath(relative(root, resolve(target)))
|
|
35
35
|
if (rel.startsWith('..') || rel === '') return false
|
|
36
36
|
return globs.some((g) => (g.endsWith('/*') ? dirname(rel) === g.slice(0, -2) : rel === g))
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
/** F484: a `file:` spec path is `/`-spelled on every platform (`C:\\repo` -> `C:/repo`); a no-op on POSIX. */
|
|
40
|
+
export function fileSpecPath(p: string, s: string = sep): string {
|
|
41
|
+
return s === '/' ? p : p.split(s).join('/')
|
|
42
|
+
}
|
|
43
|
+
|
|
39
44
|
export function resolveBrustDep(o: { explicit?: string; targetDir: string; pkgRoot?: string }): BrustDep {
|
|
40
45
|
if (o.explicit) return { kind: 'explicit', spec: o.explicit }
|
|
41
46
|
const pkgRoot = o.pkgRoot ?? packageRoot()
|
|
@@ -43,10 +48,11 @@ export function resolveBrustDep(o: { explicit?: string; targetDir: string; pkgRo
|
|
|
43
48
|
if (root) {
|
|
44
49
|
if (inWorkspace(root, o.targetDir)) return { kind: 'workspace', spec: 'workspace:*' }
|
|
45
50
|
// `file:` alone fails: core's own workspace:* deps do not resolve outside the workspace globs, so override them.
|
|
46
|
-
const
|
|
47
|
-
overrides
|
|
48
|
-
|
|
49
|
-
|
|
51
|
+
const r = fileSpecPath(root)
|
|
52
|
+
const overrides: Record<string, string> = { '@brust/runtime-dom': `file:${r}/packages/runtime-dom` }
|
|
53
|
+
overrides['@brust/core-cf'] = `file:${r}/npm/core-cf`
|
|
54
|
+
for (const p of PLATS) overrides[`@brust/native-${p}`] = `file:${r}/npm/${p}`
|
|
55
|
+
return { kind: 'file', spec: `file:${r}/packages/brust`, overrides }
|
|
50
56
|
}
|
|
51
57
|
const version = (readJson(join(pkgRoot, 'package.json'))?.version as string | undefined) ?? '0.0.0'
|
|
52
58
|
return { kind: 'version', spec: `^${version}` }
|
package/src/shadcn.ts
CHANGED
|
@@ -15,16 +15,29 @@ export const spawnRunner: Runner = async (argv, cwd) => {
|
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
/** F485 P6: how to start the project's own brust CLI. POSIX runs the `.bin` shim by path (unchanged); Windows has no
|
|
19
|
+
* executable `brust` there (a `.exe`/`.cmd` shim), so the package's bin script runs through the running Bun. */
|
|
20
|
+
export function brustArgv(targetDir: string, platform: string = process.platform, execPath: string = process.execPath): string[] {
|
|
21
|
+
if (platform === 'win32') return [execPath, join(targetDir, 'node_modules', '@brust', 'core', 'bin', 'brust')]
|
|
22
|
+
return [join(targetDir, 'node_modules/.bin/brust')]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** The command text printed for the user to paste: the POSIX shim path, or on Windows the Bun-run bin script (F485 P6). */
|
|
26
|
+
export function brustHint(targetDir: string, platform: string = process.platform, execPath: string = process.execPath): string {
|
|
27
|
+
if (platform !== 'win32') return 'node_modules/.bin/brust'
|
|
28
|
+
return brustArgv(targetDir, platform, execPath).map((a) => (a.includes(' ') ? `"${a}"` : a)).join(' ')
|
|
29
|
+
}
|
|
30
|
+
|
|
18
31
|
/** POSIX single-quoting: nothing inside expands when the printed command is pasted into a shell. */
|
|
19
32
|
export const shq = (s: string): string => (/^[A-Za-z0-9_@%+=:,./-]+$/.test(s) ? s : `'${s.replace(/'/g, `'\\''`)}'`)
|
|
20
33
|
|
|
21
34
|
/** Returns 0 when done, else the failing step's exit code (the project is left in place; `lines` says what to run). */
|
|
22
35
|
export async function runShadcn(o: { targetDir: string; components: string[]; workspace: boolean; run: Runner; out: (line: string) => void }): Promise<number> {
|
|
23
36
|
const { targetDir, components, out } = o
|
|
24
|
-
const by = `cd ${shq(targetDir)} && bun install &&
|
|
37
|
+
const by = `cd ${shq(targetDir)} && bun install && ${brustHint(targetDir)} shadcn init${components.map((c) => ` ${shq(c)}`).join('')}`
|
|
25
38
|
if (o.workspace) {
|
|
26
39
|
out('--shadcn: this app is a workspace member of a brust checkout; run `bun install` at the repo root, then in the app:')
|
|
27
|
-
out(`
|
|
40
|
+
out(` ${brustHint(targetDir)} shadcn init${components.map((c) => ` ${shq(c)}`).join('')}`)
|
|
28
41
|
return 0
|
|
29
42
|
}
|
|
30
43
|
out('\n--shadcn: installing, then running `brust shadcn init` (needs @brust/core 2.0.0-alpha.11 or later)')
|
|
@@ -33,9 +46,9 @@ export async function runShadcn(o: { targetDir: string; components: string[]; wo
|
|
|
33
46
|
out(`create-app: bun install failed (exit ${install}); the project is created. Finish with: ${by}`)
|
|
34
47
|
return install
|
|
35
48
|
}
|
|
36
|
-
const init = await o.run([
|
|
49
|
+
const init = await o.run([...brustArgv(targetDir), 'shadcn', 'init', ...components], targetDir)
|
|
37
50
|
if (init !== 0) {
|
|
38
|
-
out(`create-app: brust shadcn init failed (exit ${init}); the project is created. Run again: cd ${shq(targetDir)} &&
|
|
51
|
+
out(`create-app: brust shadcn init failed (exit ${init}); the project is created. Run again: cd ${shq(targetDir)} && ${brustHint(targetDir)} shadcn init${components.map((c) => ` ${shq(c)}`).join('')}`)
|
|
39
52
|
}
|
|
40
53
|
return init
|
|
41
54
|
}
|