Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
f6c0ac2
create-app: update validateRawArgs
Razerspine Apr 9, 2026
c84c01b
create-app: add try catch for handle error on steps
Razerspine Apr 9, 2026
d69229b
create-app: fix timeout error for tests
Razerspine Apr 9, 2026
c2636e0
create-app: update template loader and resolver
Razerspine Apr 9, 2026
528aa8e
create-app: add try catch for patch-package.ts, update jsDocs
Razerspine Apr 9, 2026
1764649
create-app: fix imports, update annotations for utils
Razerspine Apr 9, 2026
d00b98e
create-app: update handle errors for run file
Razerspine Apr 9, 2026
f21b0e9
create-app: fix packageManager field (valid variant), update test
Razerspine Apr 9, 2026
d64b6d8
create-app: remove resolve template step, migrate logic to create-app…
Razerspine Apr 9, 2026
36e1eb0
create-app: update CHANGELOG.md and README.md
Razerspine Apr 9, 2026
5be7268
create-app: fix README.md
Razerspine Apr 9, 2026
5faf22b
create-app: add new step write gitignore for pipeline, update create …
Razerspine Apr 9, 2026
3cce549
create-app: update README.md and CHANGELOG.md
Razerspine Apr 9, 2026
0b4531d
templates: update all core dependency
Razerspine Apr 9, 2026
7f2d995
templates: add new logo, update styles
Razerspine Apr 9, 2026
6b95123
create-app: fix error on test
Razerspine Apr 9, 2026
f3dbddc
templates: update gradient for all templates
Razerspine Apr 10, 2026
12d677a
templates: update webpack config for all templates (new defineConfig …
Razerspine Apr 10, 2026
618cf8d
templates: remove unusable dependency, fix tsconfig.json for all temp…
Razerspine Apr 10, 2026
4059e76
create-app: update docs
Razerspine Apr 10, 2026
64dc808
create-app: 1.0.2
Razerspine Apr 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Razerspine Stack is designed for developers who want:
Scaffolds production-ready projects with flexible architecture

- ⚙️ **Build System (`@razerspine/build`)**
Modular webpack configuration with smart defaults
Modular webpack configuration with smart defaults via the `defineConfig` API

- 🎨 **UI Layer (`@razerspine/ui`)**
Pug-based UI toolkit and reusable components
Expand Down Expand Up @@ -360,6 +360,32 @@ Removes:
- `dist`
- `lock files`

### Webpack configuration

All templates use the `defineConfig` API from `@razerspine/build`:

```js
const { defineConfig } = require('@razerspine/build');
const uiKit = require('@razerspine/ui');

module.exports = defineConfig({
scripts: 'ts',
styles: 'scss',
appType: 'spa',
templates: {
type: 'pug',
entry: 'src/app/app.pug',
},
resolve: {
alias: {
'pug-mixins': uiKit.paths.mixins,
},
},
});
```

`defineConfig` returns a Webpack-compatible factory function and handles dev/prod branching internally.

---

## Release Process
Expand Down
13 changes: 9 additions & 4 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,15 +238,20 @@ No:

```ts
defineConfig({
scripts: 'ts',
styles: 'scss',
appType: 'spa',
script: 'ts',
style: 'scss',
templates: {
entry: 'src/app/app.pug'
}
type: 'pug',
entry: 'src/app/app.pug',
},
});
```

`defineConfig` accepts a static object, a synchronous factory `(env) => config`, or an async factory.
It always returns a Webpack-compatible factory function — mode is resolved from `config.mode` →
CLI `--mode` → `'development'` (default).

### Pug Dual Mode

| Mode | Purpose |
Expand Down
1 change: 1 addition & 0 deletions docs/release-checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ If releasing `@razerspine/create-app`:
- `@razerspine/runtime`
- `@razerspine/build`
- `@razerspine/ui`
- [ ] All template `webpack.config.js` files use `defineConfig` API (not `createBaseConfig` / `createDevConfig` / `createProdConfig`)
- [ ] `--pm` flag works (`npm`, `pnpm`, `yarn`, `bun`)
- [ ] `--dry-run` works correctly
- [ ] `--no-install` works correctly
Expand Down
93 changes: 90 additions & 3 deletions packages/create-app/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,99 @@
# Changelog

## [1.0.2] - 2026-04-09

### Added

- **`.gitignore` generation** (`steps/write-gitignore.step.ts`, `utils/write-gitignore.ts`): the pipeline now
automatically writes a `.gitignore` file into every generated project. The file covers `node_modules/`, `dist/`,
log files, `.env*` variants, common editor directories, and OS metadata files. The step runs after `patchPackageStep`
and before dependency installation; it is a no-op in `--dry-run` mode.

### Templates

#### Updated

- **Dependency versions** — all 8 templates updated to the latest published versions of core packages:
- `@razerspine/build` → `^1.0.2`
- `@razerspine/runtime` → `^1.0.2`
- `@razerspine/ui` → `^1.0.2`

- **Webpack config migrated to `defineConfig` API** — all 8 templates (`spa-pug-scss-ts`,
`spa-pug-scss-js`, `spa-pug-less-ts`, `spa-pug-less-js`, `mpa-pug-scss-ts`, `mpa-pug-scss-js`,
`mpa-pug-less-ts`, `mpa-pug-less-js`) have been refactored from the low-level
`createBaseConfig` / `createDevConfig` / `createProdConfig` pattern to the high-level `defineConfig`
helper exposed by `@razerspine/build`. Manual mode resolution (`argv?.mode || env?.mode || …`) and the
dev/prod branching `if` block are fully removed — `defineConfig` handles this internally and returns a
Webpack-compatible factory function. The `templates` object now explicitly declares `type: 'pug'`.

#### Fixed

- **`@icons` alias path in SPA TypeScript `tsconfig.json`** (`spa-pug-scss-ts`, `spa-pug-less-ts`): the
path mapping was `"assets/icons*"` (missing trailing slash), which caused TypeScript to fail to resolve
the alias. Corrected to `"assets/icons/*"`.

- **Missing `tsconfig.json` compiler options in SPA TypeScript templates** (`spa-pug-scss-ts`,
`spa-pug-less-ts`): `"isolatedModules": true` and `"sourceMap": true` were present in MPA templates but
absent in their SPA counterparts. Both options are now aligned across all TypeScript templates.

#### Removed

- **`dotenv`** removed from `devDependencies` in all 8 templates — the package was never imported or used
in any webpack config or source file.

- **`webpack-merge`** removed from `devDependencies` in all 8 templates — manual config merging was
previously required with the low-level API. With `defineConfig`, all merging is handled internally by
`@razerspine/build`.

### Fixed

- **Entry point error handling** (`src/index.ts`): replaced `.then()` (no-op) with `.catch()` — ensures top-level fatal
errors are never silently swallowed.

- **`packageManager` field in generated `package.json`** (`utils/patch-package.ts`): field was set to `"${pm}@latest"`,
which is invalid for corepack. It now uses `execSync("${pm} --version")` to inject the exact installed version (e.g.
`pnpm@9.1.0`). If version detection fails the field is skipped with a warning instead of writing a broken value.

- **`bun.lock` not filtered during template copy** (`utils/copier.ts`): `IGNORED_FILES` contained `bun.lockb` but not
`bun.lock` (Bun 1.2+ format). The new entry is now included so lock files are never copied into generated projects.

- **Signal-terminated install process** (`utils/installer.ts`): `close` event handler did not distinguish between a
normal exit (`code !== 0`) and signal termination (`code === null`). The error message now correctly reports
`"terminated by signal SIGTERM"` instead of the misleading `"exit code null"`.

- **`JSON.parse()` without error handling** (`templates/template-loader.ts`, `utils/patch-package.ts`): bare
`JSON.parse()` calls would throw a native `SyntaxError` with a raw stack trace on malformed files. Both are now
wrapped in `try/catch` and surface a descriptive error message with the file path.

- **`validateRawArgs` skipped multi-argument inputs** (`cli/validate-args.ts`): the early-return guard
`if (rawArgs.length !== 1) return` caused the reserved-word check to be bypassed whenever the user passed zero or
multiple positional arguments. The function now iterates over every argument regardless of count.

### Changed

- **Windows install process** (`utils/installer.ts`): replaced `shell: true` (which routes through `cmd.exe` and is a
potential injection surface) with `shell: false` + `cmd.cmd` suffix resolution. Package managers are now invoked
directly as `npm.cmd`, `pnpm.cmd`, etc., matching the standard cross-platform Node.js convention.

### Refactored

- **Eliminated redundant `loadTemplates()` calls** (`cli/resolve-template.ts`, `core/create-app.ts`, `steps/`):
templates were loaded three times per CLI session — once as a module-level side effect in `templates.ts`, and once
each in `cli/resolve-template.ts` and `resolveTemplateStep`. The CLI now creates a single `TemplateService` instance,
resolves and loads the template in one pass, and passes the ready `LoadedTemplate` object directly into the pipeline
context. `resolveTemplateStep` has been removed as a consequence.

---

## [1.0.1] - 2026-03-30

### Fixed

- **Template Dependencies**: Added `html-webpack-plugin` to `devDependencies` in all templates (`spa-pug-scss-ts`, etc.). This
resolves the `MODULE_NOT_FOUND` error when running `npm run dev` in a newly generated project, caused by the peer dependency
requirements of `@razerspine/build`.
- **Template Dependencies**: Added `html-webpack-plugin` to `devDependencies` in all templates (`spa-pug-scss-ts`,
etc.). This
resolves the `MODULE_NOT_FOUND` error when running `npm run dev` in a newly generated project, caused by the peer
dependency
requirements of `@razerspine/build`.

---

Expand Down
94 changes: 31 additions & 63 deletions packages/create-app/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# @razerspine/create-app

[![npm version](https://img.shields.io/npm/v/@razerspine/create-app.svg)](https://www.npmjs.com/package/@razerspine/create-app)
[![Vitest](https://img.shields.io/badge/Vitest-62_passed-success?logo=vitest)]()
[![CI](https://github.com/Razerspine/razerspine-stack/actions/workflows/ci.yml/badge.svg)](https://github.com/Razerspine/razerspine-stack/actions)
[![changelog](https://img.shields.io/badge/docs-changelog-blue.svg)](./CHANGELOG.md)
[![license](https://img.shields.io/npm/l/@razerspine/create-app.svg)](./LICENSE)

Expand All @@ -20,7 +20,7 @@ Create a modern webpack project using production-ready **SPA or MPA templates**
- [Template Resolution](#template-resolution)
- [Testing](#testing)
- [How It Works](#how-it-works)
- [Changelog (1.0.0)](#changelog-100)
- [Changelog](#changelog)
- [Documentation](#documentation)
- [License](#license)

Expand Down Expand Up @@ -105,7 +105,7 @@ Supported:

- Auto script adaptation:
- `npm run build` → `pnpm build` / `yarn build`
- Adds `packageManager` field to `package.json`
- Injects exact `packageManager` version into `package.json` (corepack-compatible, e.g. `pnpm@9.1.0`)
- Fallback to `npm` if not specified

---
Expand Down Expand Up @@ -202,83 +202,51 @@ Highlights:

## How It Works

Pipeline-based architecture:
The CLI resolves and loads the template before the pipeline starts, then passes the ready template object directly into
the first step:

```text
resolve template
CLI layer
resolve template (TemplateService — single load)
prepare directory
Pipeline
prepare directory
copy files
copy files
patch package.json
patch package.json
install dependencies
write .gitignore
install dependencies
```

---

## Changelog (1.0.0)
## Changelog

### [1.0.2] — Latest

### Major Release
- Added automatic `.gitignore` generation for every scaffolded project (`node_modules/`, `dist/`, `.env*`, logs, editor dirs)
- Fixed `packageManager` field: now injects exact version (e.g. `pnpm@9.1.0`) instead of invalid `@latest`
- Fixed `bun.lock` (Bun 1.2+) being copied into generated projects
- Fixed signal-terminated install process reporting misleading `"exit code null"`
- Fixed `JSON.parse()` in template loader and package patcher — now surfaces file path on error
- Fixed `validateRawArgs` skipping checks for 0 or 2+ positional arguments
- Fixed top-level `run().then()` no-op — replaced with `.catch()`
- Improved Windows install: `shell: false` + `.cmd` suffix instead of `shell: true`
- Refactored template resolution: single `TemplateService` load per session, removed redundant `resolveTemplateStep`

### [1.0.0] — Major Release

- Full CLI rewrite
- New package: `@razerspine/create-app`
- New command: `create`

---

### ⚠️ Breaking Changes

- `create-webpack-starter` → `create-app`
- New binary: `dist/index.cjs`
- Switched to `tsup`
- Removed direct `package.json` imports

---

### Features

- Interactive CLI (inquirer)
- Smart template resolution
- Dry-run mode
- Improved validation

---

### Package Manager Support

- Added `--pm` flag
- Supports: npm, pnpm, yarn, bun
- Script auto-adaptation
- Injects `packageManager` field

---

### Testing

- Vitest migration
- Full E2E coverage
- Fixed cleanup race conditions

---

### Architecture

- Pipeline-based system
- Clean separation:
- CLI
- core
- steps
- utils

---

### DX Improvements

- `tsx` instead of `ts-node`
- Better logs (ora + kleur)
- Improved CLI UX
- Dry-run mode, `--pm` flag
- Vitest migration, full E2E coverage
- Pipeline-based architecture

---

Expand Down
2 changes: 1 addition & 1 deletion packages/create-app/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@razerspine/create-app",
"version": "1.0.1",
"version": "1.0.2",
"description": "CLI to scaffold production-ready SPA & MPA applications with a modular build system, Pug templates, and a lightweight reactive runtime.",
"author": "Razerspine",
"license": "ISC",
Expand Down
10 changes: 5 additions & 5 deletions packages/create-app/src/cli/resolve-template.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {TemplateKey} from '../templates/templates';
import {createTemplateService} from '../core/template.service';
import {TemplateFeatures} from '../templates/types';
import {TemplateFeatures, LoadedTemplate} from '../templates/types';

/**
* Resolves template key using TemplateService.
* Resolves and returns the full LoadedTemplate using a single TemplateService instance.
*/
export function resolveTemplate(input: TemplateFeatures): TemplateKey {
export function resolveTemplate(input: TemplateFeatures): LoadedTemplate {
const service = createTemplateService();
return service.resolve(input);
const key = service.resolve(input);
return service.getByKey(key);
}
5 changes: 2 additions & 3 deletions packages/create-app/src/cli/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {TemplateFeatures, AppType} from '../templates/types';
import {TemplateKey} from '../templates/templates';
import {TemplateFeatures, AppType, LoadedTemplate} from '../templates/types';
import {PackageManager} from '../utils';

/**
Expand All @@ -17,7 +16,7 @@ export type CliOptions = Partial<TemplateFeatures> & {
*/
export type CliContext = {
projectName: string;
template: TemplateKey;
template: LoadedTemplate;
appType: AppType;
noInstall: boolean;
dryRun: boolean;
Expand Down
Loading
Loading