@appxdigital/appx-core 0.1.123 → 0.1.124

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/CHANGELOG.md CHANGED
@@ -14,6 +14,16 @@ This project follows the `MAJOR.MINOR.PATCH` scheme in `package.json`.
14
14
 
15
15
  ---
16
16
 
17
+ ## [0.1.124] — 2026-07-23
18
+
19
+ ### Fixed
20
+
21
+ - **`appx-core generate` and `generate models` now run the project's own Prisma.** Both shelled out to a bare `prisma generate`, which resolves from `PATH`. With the CLI installed **globally** the project's `node_modules/.bin` is not on `PATH`, so Prisma resolved to a *global* install — a different version than the project's — or was not found at all. The executable is now resolved inside the project (walking up from the working directory, so hoisted / monorepo layouts work), and its `.bin` is prepended to `PATH` so the generator binaries Prisma spawns (`prisma-nestjs-graphql`, …) also resolve from the project. A project with no local Prisma now fails with an actionable message instead of silently generating against a global one.
22
+
23
+ Drop-in: no changes required in your project.
24
+
25
+ ---
26
+
17
27
  ## [0.1.123] — 2026-07-22
18
28
 
19
29
  Two changes: the `generate` command is split into a deploy-safe pass + a module wizard, and generated CRUD DTOs now type each scalar column to match its Prisma model type.
package/README.md CHANGED
@@ -124,12 +124,22 @@ npm install -g @appxdigital/appx-core-cli
124
124
  npm install -g @appxdigital/appx-core-cli@beta # CLI prerelease
125
125
  ```
126
126
 
127
- `appx-core create` scaffolds a project that depends on the **stable** library. To test a library prerelease in that project, install it there:
127
+ `appx-core create` pins the library to **the CLI's own channel** — a stable CLI scaffolds a project depending on the stable library, a beta CLI (`@beta`) one depending on the beta library. To move an existing project across channels, install it there directly:
128
128
 
129
129
  ```bash
130
130
  npm install @appxdigital/appx-core@beta # inside your project
131
131
  ```
132
132
 
133
+ **Staying up to date (automatic).** The CLI keeps itself current. On each run it checks the registry in the background (throttled), and when a newer version is published **on your channel** it installs it before your *next* command and re-launches into the new binary — so a beta install stays on `beta`, a stable install stays on `latest`. The check never blocks your command, and a failed/offline check is silently ignored.
134
+
135
+ ```bash
136
+ appx-core update # update now, on your current channel
137
+ appx-core update --channel beta # switch to the beta channel (or --channel production to switch back)
138
+ APPX_CORE_NO_AUTO_UPDATE=1 … # disable the background auto-update entirely
139
+ ```
140
+
141
+ Install logs (only written when an update runs) go to `~/.appx-core/last-install.log`.
142
+
133
143
  ### 2) Create a New Project
134
144
 
135
145
  ```bash
@@ -15,11 +15,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
15
  * Scaffolding CRUD modules (which mutates code) is the separate, interactive
16
16
  * `appx generate models` wizard.
17
17
  */
18
- const child_process_1 = require("child_process");
19
18
  const utils_1 = require("./utils");
20
19
  const generate_dtos_1 = require("./generate-dtos");
21
20
  console.log('Running Prisma Generate (client + GraphQL artifacts)...');
22
- (0, child_process_1.execSync)('prisma generate', { stdio: 'inherit' });
21
+ // Project-local prisma: the CLI is usually global, so PATH has no project .bin.
22
+ (0, utils_1.runProjectBin)('prisma', 'generate');
23
23
  console.log('Generating DTO base classes...');
24
24
  (0, generate_dtos_1.generateDtoBases)((0, utils_1.loadAllModels)());
25
25
  console.log('Deploy-safe generation complete — src/generated only, no code changes.');
@@ -22,7 +22,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
22
22
  * It first runs the deploy-safe pass (prisma generate + DTO bases), so the
23
23
  * scaffolded resolver/controller imports resolve.
24
24
  */
25
- const child_process_1 = require("child_process");
26
25
  const utils_1 = require("./utils");
27
26
  const generate_dtos_1 = require("./generate-dtos");
28
27
  const generate_modules_1 = require("./generate-modules");
@@ -37,7 +36,8 @@ const dynamicImport = new Function('m', 'return import(m)');
37
36
  async function main() {
38
37
  // 1) Deploy-safe pass first — refresh client + GraphQL artifacts + DTO bases.
39
38
  console.log('Running Prisma Generate (client + GraphQL artifacts)...');
40
- (0, child_process_1.execSync)('prisma generate', { stdio: 'inherit' });
39
+ // Project-local prisma: the CLI is usually global, so PATH has no project .bin.
40
+ (0, utils_1.runProjectBin)('prisma', 'generate');
41
41
  (0, generate_dtos_1.generateDtoBases)((0, utils_1.loadAllModels)());
42
42
  // 2) Candidates = non-framework models with no module yet. "Has a module"
43
43
  // means either the canonical folder exists OR some existing module already
@@ -1,3 +1,18 @@
1
+ /**
2
+ * Run a project-local CLI binary (e.g. `prisma`) from the PROJECT's node_modules.
3
+ *
4
+ * The `appx-core` CLI is normally installed **globally**, so the project's
5
+ * `node_modules/.bin` is not on PATH — a bare `prisma generate` would resolve to
6
+ * a global Prisma (a different version than the project's, or nothing at all).
7
+ * We resolve the executable inside the project and prepend its `.bin` to PATH so
8
+ * that anything the tool spawns — Prisma's generator binaries such as
9
+ * `prisma-nestjs-graphql` — also resolves from the project.
10
+ *
11
+ * Throws with an actionable message rather than silently falling back to a
12
+ * global install, since generating against the wrong Prisma version is exactly
13
+ * the failure this avoids.
14
+ */
15
+ export declare const runProjectBin: (bin: string, args: string, cwd?: string) => void;
1
16
  export declare const kebabToPascalCase: (str: string) => string;
2
17
  export declare const pascalToKebabCase: (str: string) => string;
3
18
  export declare const createFileIfNotExists: (filePath: string, content: string) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/config/utils.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,iBAAiB,QAAS,MAAM,WAK5C,CAAC;AAEF,eAAO,MAAM,iBAAiB,QAAS,MAAM,WAK5C,CAAC;AAEF,eAAO,MAAM,qBAAqB,aAAc,MAAM,WAAW,MAAM,SAStE,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,QAGoD,CAAC;AAElF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,aAAc,MAAM,WAAW,MAAM,SAInE,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,UAA0C,CAAC;AAExE;;;;;GAKG;AACH,eAAO,MAAM,WAAW,cAAe,MAAM,KAAG,MAAsC,CAAC;AAEvF;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,QAAO,GAAG,EAInC,CAAC;AAEF,eAAO,MAAM,UAAU,QAAO,GAAG,EAAuE,CAAC;AAEzG,iFAAiF;AACjF,eAAO,MAAM,YAAY,cAAe,MAAM,KAAG,OAGhD,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,aAAc,MAAM,EAAE,KAAG,IAAI,MAAM,CAQnE,CAAC;AAEF,6EAA6E;AAC7E,eAAO,MAAM,WAAW,QAAO,IAAI,MAAM,CAYxC,CAAC"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/config/utils.ts"],"names":[],"mappings":"AAuBA;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,aAAa,QAAS,MAAM,QAAQ,MAAM,QAAO,MAAM,KAAmB,IAatF,CAAC;AAEF,eAAO,MAAM,iBAAiB,QAAS,MAAM,WAK5C,CAAC;AAEF,eAAO,MAAM,iBAAiB,QAAS,MAAM,WAK5C,CAAC;AAEF,eAAO,MAAM,qBAAqB,aAAc,MAAM,WAAW,MAAM,SAStE,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,QAGoD,CAAC;AAElF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,aAAc,MAAM,WAAW,MAAM,SAInE,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,UAA0C,CAAC;AAExE;;;;;GAKG;AACH,eAAO,MAAM,WAAW,cAAe,MAAM,KAAG,MAAsC,CAAC;AAEvF;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,QAAO,GAAG,EAInC,CAAC;AAEF,eAAO,MAAM,UAAU,QAAO,GAAG,EAAuE,CAAC;AAEzG,iFAAiF;AACjF,eAAO,MAAM,YAAY,cAAe,MAAM,KAAG,OAGhD,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,aAAc,MAAM,EAAE,KAAG,IAAI,MAAM,CAQnE,CAAC;AAEF,6EAA6E;AAC7E,eAAO,MAAM,WAAW,QAAO,IAAI,MAAM,CAYxC,CAAC"}
@@ -23,9 +23,57 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.ownedModels = exports.modelsServedBySource = exports.moduleExists = exports.loadModels = exports.loadAllModels = exports.modelFolder = exports.FRAMEWORK_MODELS = exports.writeGeneratedFile = exports.GENERATED_BANNER = exports.createFileIfNotExists = exports.pascalToKebabCase = exports.kebabToPascalCase = void 0;
26
+ exports.ownedModels = exports.modelsServedBySource = exports.moduleExists = exports.loadModels = exports.loadAllModels = exports.modelFolder = exports.FRAMEWORK_MODELS = exports.writeGeneratedFile = exports.GENERATED_BANNER = exports.createFileIfNotExists = exports.pascalToKebabCase = exports.kebabToPascalCase = exports.runProjectBin = void 0;
27
27
  const fs = __importStar(require("fs"));
28
28
  const path = __importStar(require("path"));
29
+ const child_process_1 = require("child_process");
30
+ /**
31
+ * Locate a binary inside the project's own `node_modules/.bin`, walking up from
32
+ * `cwd` so hoisted / monorepo layouts resolve too. Returns null when the project
33
+ * doesn't provide it (i.e. only a global install would be found on PATH).
34
+ */
35
+ const findProjectBin = (bin, cwd) => {
36
+ const name = process.platform === 'win32' ? `${bin}.cmd` : bin;
37
+ let dir = path.resolve(cwd);
38
+ // eslint-disable-next-line no-constant-condition
39
+ while (true) {
40
+ const binDir = path.join(dir, 'node_modules', '.bin');
41
+ const exe = path.join(binDir, name);
42
+ if (fs.existsSync(exe))
43
+ return { exe, binDir };
44
+ const parent = path.dirname(dir);
45
+ if (parent === dir)
46
+ return null;
47
+ dir = parent;
48
+ }
49
+ };
50
+ /**
51
+ * Run a project-local CLI binary (e.g. `prisma`) from the PROJECT's node_modules.
52
+ *
53
+ * The `appx-core` CLI is normally installed **globally**, so the project's
54
+ * `node_modules/.bin` is not on PATH — a bare `prisma generate` would resolve to
55
+ * a global Prisma (a different version than the project's, or nothing at all).
56
+ * We resolve the executable inside the project and prepend its `.bin` to PATH so
57
+ * that anything the tool spawns — Prisma's generator binaries such as
58
+ * `prisma-nestjs-graphql` — also resolves from the project.
59
+ *
60
+ * Throws with an actionable message rather than silently falling back to a
61
+ * global install, since generating against the wrong Prisma version is exactly
62
+ * the failure this avoids.
63
+ */
64
+ const runProjectBin = (bin, args, cwd = process.cwd()) => {
65
+ const found = findProjectBin(bin, cwd);
66
+ if (!found) {
67
+ throw new Error(`Could not find "${bin}" in this project's node_modules. ` +
68
+ `Run "npm install" in the project root and try again.`);
69
+ }
70
+ (0, child_process_1.execSync)(`"${found.exe}" ${args}`.trim(), {
71
+ cwd,
72
+ stdio: 'inherit',
73
+ env: { ...process.env, PATH: `${found.binDir}${path.delimiter}${process.env.PATH ?? ''}` },
74
+ });
75
+ };
76
+ exports.runProjectBin = runProjectBin;
29
77
  const kebabToPascalCase = (str) => {
30
78
  return str
31
79
  .split("-")
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@appxdigital/appx-core",
3
- "version": "0.1.123",
3
+ "version": "0.1.124",
4
4
  "description": "Appx Core is a library that provides a set of tools to help you build your application faster.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "scripts": {
8
8
  "build": "tsc",
9
- "build:cli": "npm --prefix cli ci",
9
+ "build:cli": "node scripts/sync-cli-core-version.mjs && npm --prefix cli ci",
10
10
  "build:all": "npm run build && npm run build:cli",
11
11
  "db-pull": "npx prisma db pull && prisma-case-format --table-case pascal --field-case camel --enum-case pascal --file prisma/schema.prisma",
12
12
  "test": "jest",