@brust/create-app 2.0.0-alpha.32 → 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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brust/create-app",
3
- "version": "2.0.0-alpha.32",
3
+ "version": "2.0.0-alpha.34",
4
4
  "description": "Scaffold a brust v2 app — bun create @brust/app <name>",
5
5
  "license": "MIT",
6
6
  "homepage": "https://brust.dev",
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 displayPath = targetDir.startsWith(`${cwd}/`) ? `./${targetDir.slice(cwd.length + 1)}` : targetDir
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 overrides: Record<string, string> = { '@brust/runtime-dom': `file:${root}/packages/runtime-dom` }
47
- overrides['@brust/core-cf'] = `file:${root}/npm/core-cf`
48
- for (const p of PLATS) overrides[`@brust/native-${p}`] = `file:${root}/npm/${p}`
49
- return { kind: 'file', spec: `file:${root}/packages/brust`, overrides }
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 && node_modules/.bin/brust shadcn init${components.map((c) => ` ${shq(c)}`).join('')}`
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(` node_modules/.bin/brust shadcn init${components.map((c) => ` ${shq(c)}`).join('')}`)
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([join(targetDir, 'node_modules/.bin/brust'), 'shadcn', 'init', ...components], targetDir)
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)} && node_modules/.bin/brust shadcn init${components.map((c) => ` ${shq(c)}`).join('')}`)
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
  }