Files
Tyler Cloutier a4d29daec8 Fix spacetime dev template issues and clean up CLI (#4396)
## Summary

Multiple fixes and improvements to `spacetime dev`, `spacetime publish`,
`spacetime init`, and templates:

### CLI fixes
- **Fix `spacetime dev` watch path and .env.local handling** for
templates with a `spacetimedb/` subdirectory
- **Validate package manager availability** before installing
dependencies — re-prompts if the selected PM isn't on PATH
- **Remove JS/TS beta warning** from `spacetime publish`
- **Remove unstable warning** from `spacetime init`
- **Remove unused `spacetime energy` command** (can be re-added later
when properly implemented)
- **Fix `tsc` detection on Windows** — `set_extension(".cmd")` produced
`tsc..cmd` (double dot); fixed to `set_extension("cmd")`
- **Add `typescript` as devDependency** to all server template
`spacetimedb/package.json` files so `tsc` is available during build
- **Strip `\?\` extended-length path prefix** from user-facing output in
both `dev` and `publish` commands (produced by `fs::canonicalize()` on
Windows)
- **Fix publish reporting success when user declines** non-local server
prompt — changed `return Ok(())` to `bail!()` consistent with other
abort cases
- **Forward stdin to client process** in `spacetime dev` so interactive
CLI templates work

### Template fixes
- **Fix Angular template environment variables** — Angular's esbuild
builder doesn't support `import.meta.env`, so we use a dev script to
generate `environment.local.ts` with Angular's native `fileReplacements`
pattern
- **Fix TanStack Start template** — rename `createRouter` to `getRouter`
(v1.121+ breaking change), upgrade to React 19, and add
`@vitejs/plugin-react` for automatic JSX runtime support
- **Fix `moduleResolution` in remix-ts and nextjs-ts** server tsconfigs
— change from `"node"` to `"bundler"` to support subpath exports like
`spacetimedb/server`
- **Fix browser-ts template** — convert from static HTML + IIFE bundle
to standard Vite dev server app so it works with `spacetime dev` and
reads env vars from `.env.local`
- **Add `deno` as devDependency** to deno-ts template (matches how
bun-ts includes bun)
- **Convert basic-ts from empty web app to CLI app** matching basic-rs —
connect, subscribe to person table, print on insert

## Test plan

- [x] `cargo test -p spacetimedb-cli` — all 133 tests pass
- [ ] `spacetime dev --template angular-ts` — verify Angular app
connects with correct database name
- [ ] `spacetime dev --template react-ts` — verify React template still
works
- [ ] `spacetime dev --template tanstack-ts` — verify TanStack Start
template loads without errors
- [ ] `spacetime dev --template remix-ts` — verify Remix template builds
and runs
- [ ] `spacetime dev --template nextjs-ts` — verify Next.js template
still works
- [ ] `spacetime dev --template browser-ts` — verify Vite dev server
starts and app connects
- [ ] `spacetime dev --template bun-ts` — verify Bun CLI template runs
interactively
- [ ] `spacetime dev --template basic-ts` — verify CLI connects and
prints on insert
- [ ] Verify no `\?\` prefix in any displayed paths on Windows
- [ ] Verify no `tsc not found` warning when building server modules
- [ ] Select unavailable package manager at init prompt — verify
re-prompt
- [ ] Decline non-local server prompt — verify clean error instead of
"Published successfully!"

---------

Co-authored-by: Piotr Sarnacki <drogus@gmail.com>
Co-authored-by: John Detter <4099508+jdetter@users.noreply.github.com>
Co-authored-by: clockwork-labs-bot <bot@clockworklabs.com>
2026-02-24 02:39:42 -05:00

59 lines
1.8 KiB
JavaScript

/**
* Dev script that generates src/environments/environment.local.ts from
* .env.local (or process.env) before starting `ng serve`.
*
* Angular's esbuild-based builder doesn't read .env files like Vite does,
* so we generate a TypeScript environment file and use Angular's
* fileReplacements to swap it in during the development build.
*/
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
import { spawn } from 'child_process';
/** Parse a .env file into a key-value object. */
function parseEnvFile(filePath) {
const vars = {};
if (!existsSync(filePath)) return vars;
for (const line of readFileSync(filePath, 'utf-8').split('\n')) {
const trimmed = line.trim();
if (!trimmed || trimmed.startsWith('#')) continue;
const eqIdx = trimmed.indexOf('=');
if (eqIdx === -1) continue;
vars[trimmed.slice(0, eqIdx)] = trimmed.slice(eqIdx + 1);
}
return vars;
}
const envFile = parseEnvFile('.env.local');
// Resolve each variable: prefer process.env (set by `spacetime dev`),
// then .env.local, then fall back to the defaults in environment.ts.
const dbName =
process.env.SPACETIMEDB_DB_NAME ||
envFile.VITE_SPACETIMEDB_DB_NAME ||
'angular-ts';
const host =
process.env.SPACETIMEDB_HOST ||
envFile.VITE_SPACETIMEDB_HOST ||
'https://maincloud.spacetimedb.com';
mkdirSync('src/environments', { recursive: true });
writeFileSync(
'src/environments/environment.local.ts',
[
'// Auto-generated by scripts/dev.mjs — do not edit manually.',
'export const environment = {',
` SPACETIMEDB_HOST: '${host}',`,
` SPACETIMEDB_DB_NAME: '${dbName}',`,
'};',
'',
].join('\n')
);
const child = spawn('npx', ['ng', 'serve'], {
stdio: 'inherit',
shell: true,
});
child.on('exit', (code) => process.exit(code ?? 0));