create-projx 1.6.0 → 1.6.1

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
@@ -175,27 +175,35 @@ Your custom files (controllers, pages, middleware) are never deleted. Files you
175
175
 
176
176
  ### Skip Files
177
177
 
178
- To skip component source files, add `skip` to `.projx-component`:
178
+ Common user-owned files are **default-skipped** automatically template updates won't touch them:
179
+
180
+ | Scope | Default skips |
181
+ |-------|---------------|
182
+ | Root (`.projx`) | `docker-compose.yml`, `docker-compose.dev.yml`, `README.md`, `.githooks/pre-commit`, `.github/workflows/ci.yml`, `setup.sh` |
183
+ | fastapi | `pyproject.toml` |
184
+ | fastify / frontend / e2e | `package.json` |
185
+ | mobile | `pubspec.yaml` |
186
+
187
+ Defaults are applied once on first `update` and saved to the `skip` array. To skip additional files, add them to `skip` in `.projx` (root-level) or `.projx-component` (per-component):
179
188
 
180
189
  ```json
190
+ // .projx — root skip
181
191
  {
182
- "components": ["fastapi"],
183
- "origin": "init",
184
- "skip": ["src/**", "tests/**"]
192
+ "version": "x.y.z",
193
+ "skip": ["docker-compose.yml", "README.md", "my-custom-config.yml"]
185
194
  }
186
195
  ```
187
196
 
188
- To skip root-level files (docker-compose, README), add `skip` to `.projx`:
189
-
190
197
  ```json
198
+ // fastapi/.projx-component — component skip
191
199
  {
192
- "version": "1.5.2",
193
- "components": ["fastapi", "frontend"],
194
- "skip": ["docker-compose.yml", "README.md"]
200
+ "component": "fastapi",
201
+ "origin": "init",
202
+ "skip": ["pyproject.toml", "src/custom_middleware.py"]
195
203
  }
196
204
  ```
197
205
 
198
- Skipped files are excluded from template updates.
206
+ To opt back in to updates for a skipped file, use `npx create-projx unpin <file>`.
199
207
 
200
208
  ## Options
201
209
 
@@ -274,12 +282,12 @@ When both `fastapi` and `fastify` exist, the entity generates in the **primary b
274
282
 
275
283
  Override with `--ai` (fastapi) or `--backend` (fastify).
276
284
 
277
- | Component | Generated |
278
- | ------------------------- | --------------------------------------------------------------------------------------------- |
279
- | Primary backend (fastapi) | `src/entities/<name>/_model.py` + `tests/test_<name>_entity.py` — model + 11 CRUD/auth tests |
280
- | Primary backend (fastify) | `src/modules/<name>/schemas.ts` + `index.ts` + Prisma model + `tests/modules/<name>.test.ts` |
281
- | `frontend` | `src/types/<name>.ts` — TypeScript interface + Create/Update variants |
282
- | `mobile` | `lib/entities/<name>/model.dart` — Dart class with fromJson/toJson/copyWith |
285
+ | Component | Generated |
286
+ | ------------------------- | -------------------------------------------------------------------------------------------- |
287
+ | Primary backend (fastapi) | `src/entities/<name>/_model.py` + `tests/test_<name>_entity.py` — model + 11 CRUD/auth tests |
288
+ | Primary backend (fastify) | `src/modules/<name>/schemas.ts` + `index.ts` + Prisma model + `tests/modules/<name>.test.ts` |
289
+ | `frontend` | `src/types/<name>.ts` — TypeScript interface + Create/Update variants |
290
+ | `mobile` | `lib/entities/<name>/model.dart` — Dart class with fromJson/toJson/copyWith |
283
291
 
284
292
  **Tests included**: every `gen entity` writes a working integration test file alongside the model — 11 tests for FastAPI (extending `BaseEntityApiTest`), 11 tests for Fastify (via `describeCrudEntity`). Both run against a real database (Postgres for Fastify, SQLite-in-memory for FastAPI today). New entities ship green from day one — no scrambling to bolt on tests at go-live.
285
293
 
@@ -343,6 +351,8 @@ The core idea: define a data model, get everything else for free.
343
351
 
344
352
  **Backend** — Drop a model file. The registry auto-discovers it and generates CRUD routes, schemas, pagination, filtering, sorting, search, FK expansion, and OpenAPI docs.
345
353
 
354
+ **Field privacy** — Sensitive columns (`password_hash`, `secret`, `api_key`, `mfa_secret`, etc.) are automatically stripped from API responses and `/_meta` via a built-in baseline. Add project-specific hidden fields per entity (`__hidden_fields__` in FastAPI, `hiddenFields` in Fastify). Mark entire entities as `__private__` / `private: true` to hide them from the API entirely — no routes registered, not listed in `/_meta`. The `/_meta` endpoint requires authentication on both backends.
355
+
346
356
  **Frontend** — Fetches metadata from `GET /api/v1/_meta`, renders table + form UI automatically. Customize with overrides.
347
357
 
348
358
  **Mobile** — Same metadata endpoint, generates list/detail/form screens. Offline-first with local DB and sync queue.
@@ -10,7 +10,7 @@ import {
10
10
  matchesSkip,
11
11
  saveBaselineRef,
12
12
  writeTemplateToDir
13
- } from "./chunk-G74HYIE4.js";
13
+ } from "./chunk-TNI4XBVS.js";
14
14
  import "./chunk-FTHX7ILT.js";
15
15
  export {
16
16
  BASELINE_REF,
@@ -16,9 +16,9 @@ import {
16
16
 
17
17
  // src/baseline.ts
18
18
  import { existsSync, writeFileSync, unlinkSync } from "fs";
19
- import { chmod, mkdir, writeFile, rm, readFile as readFile2 } from "fs/promises";
19
+ import { chmod, mkdir, writeFile, rm, readFile as readFile2, copyFile } from "fs/promises";
20
20
  import { execSync } from "child_process";
21
- import { join as join2 } from "path";
21
+ import { join as join2, dirname } from "path";
22
22
  import { tmpdir } from "os";
23
23
 
24
24
  // src/generators/index.ts
@@ -259,7 +259,12 @@ async function tryThreeWayMerge(cwd, templateDir, baselineRef, componentPaths) {
259
259
  if (file === ".projx") continue;
260
260
  if (file.endsWith("/.projx-component") || file === ".projx-component") continue;
261
261
  const oursPath = join2(cwd, file);
262
- if (!existsSync(oursPath)) continue;
262
+ if (!existsSync(oursPath)) {
263
+ await mkdir(dirname(oursPath), { recursive: true });
264
+ await copyFile(join2(templateDir, file), oursPath);
265
+ merged.push(file);
266
+ continue;
267
+ }
263
268
  const baseContent = lookupBaseContent(cwd, baselineRef, file, pathFallbacks);
264
269
  if (baseContent === null) continue;
265
270
  let theirsContent;
package/dist/index.js CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  matchesSkip,
10
10
  saveBaselineRef,
11
11
  writeTemplateToDir
12
- } from "./chunk-G74HYIE4.js";
12
+ } from "./chunk-TNI4XBVS.js";
13
13
  import {
14
14
  COMPONENTS,
15
15
  COMPONENT_MARKER,
@@ -371,7 +371,7 @@ function hasUncommittedChanges(cwd) {
371
371
  async function findPinnedFilesWithUpdates(cwd, repoDir, components, componentPaths, vars, version, componentSkips, rootSkip) {
372
372
  const { mkdir: mkdir5, rm: rm2, readFile: readFile7 } = await import("fs/promises");
373
373
  const { tmpdir: tmpdir2 } = await import("os");
374
- const { writeTemplateToDir: writeTemplateToDir2 } = await import("./baseline-72Z7TC2E.js");
374
+ const { writeTemplateToDir: writeTemplateToDir2 } = await import("./baseline-5XAJJ457.js");
375
375
  const config = await readProjxConfig(cwd);
376
376
  const rootPinned = Array.isArray(config.skip) ? config.skip : [];
377
377
  const componentPinned = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-projx",
3
- "version": "1.6.0",
3
+ "version": "1.6.1",
4
4
  "description": "Scaffold production-grade fullstack projects in seconds. FastAPI, Fastify, React, Flutter, Terraform — with auth, database, CI/CD, E2E tests, and Docker. One command, ready to deploy.",
5
5
  "type": "module",
6
6
  "bin": {