@ng-native/schematics 0.17.0 → 0.17.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
@@ -22,8 +22,9 @@ ng serve native # expo start: Metro, with Expo Go or a simulato
22
22
  ng build native # expo export, into dist/native
23
23
  ng test native # vitest run, on the fake Fabric
24
24
  ng run native:run-ios # expo run:ios
25
+ ng run native:typecheck # ngc: the templates as well as the code
25
26
 
26
- cd projects/native && ng generate component profile-card # <view>, <text>, and a test
27
+ cd projects/native && ng generate component profile-card # src/app/profile-card: <view>, <text>, a test
27
28
  ```
28
29
 
29
30
  ## What's in the package
@@ -40,6 +40,7 @@ function targets(root, name) {
40
40
  'run-ios': expo('run:ios'),
41
41
  'run-android': expo('run:android'),
42
42
  test: { builder: '@ng-native/schematics:vitest', options: {} },
43
+ typecheck: { builder: '@ng-native/schematics:typecheck', options: {} },
43
44
  };
44
45
  }
45
46
 
@@ -83,6 +84,7 @@ function commands(name) {
83
84
  [`ng run ${name}:run-ios`, 'the iOS simulator'],
84
85
  [`ng run ${name}:run-android`, 'the Android emulator'],
85
86
  [`ng test ${name}`, 'Vitest, in Node against a fake native layer: no simulator needed'],
87
+ [`ng run ${name}:typecheck`, 'ngc, which checks the templates as well as the code'],
86
88
  [`ng build ${name}`, 'an exported bundle'],
87
89
  ];
88
90
  const width = Math.max(...rows.map(([command]) => command.length)) + 2;
@@ -161,7 +163,7 @@ function application(options) {
161
163
  if (!options.skipInstall) context.addTask(new NodePackageInstallTask());
162
164
  context.logger.info(
163
165
  `Created ${root}. Run it with: ng serve ${name} (Metro), ng run ${name}:run-ios, ` +
164
- `ng test ${name}, ng build ${name}.`,
166
+ `ng test ${name}, ng run ${name}:typecheck, ng build ${name}.`,
165
167
  );
166
168
  };
167
169
  }
@@ -21,13 +21,14 @@ function findManifest(name, from) {
21
21
  }
22
22
 
23
23
  /**
24
- * @param {string} name the package, `expo` or `vitest`
24
+ * @param {string} name the package, such as `expo`, `vitest` or `@angular/compiler-cli`
25
25
  * @param {string} from the directory to resolve it from
26
+ * @param {string} command the entry of its `bin` to run, when not named for the package: `ngc`
26
27
  */
27
- function resolveBin(name, from) {
28
+ function resolveBin(name, from, command = name) {
28
29
  const manifestPath = findManifest(name, from);
29
30
  const { bin } = JSON.parse(readFileSync(manifestPath, 'utf8'));
30
- const file = typeof bin === 'string' ? bin : bin[name];
31
+ const file = typeof bin === 'string' ? bin : bin[command];
31
32
  return path.join(path.dirname(manifestPath), file);
32
33
  }
33
34
 
@@ -56,12 +57,25 @@ const SIGNALS = ['SIGINT', 'SIGTERM', 'SIGHUP'];
56
57
  */
57
58
  async function spawnBin(name, args, context) {
58
59
  const cwd = await projectRoot(context);
59
- const bin = resolveBin(name, cwd);
60
+ return spawnFile(resolveBin(name, cwd), args, cwd, name, context);
61
+ }
62
+
63
+ /**
64
+ * Runs `file` with Node in `cwd`, logged and reported as `label`.
65
+ *
66
+ * @param {string} file
67
+ * @param {string[]} args
68
+ * @param {string} cwd
69
+ * @param {string} label
70
+ * @param {import('@angular-devkit/architect').BuilderContext} context
71
+ * @returns {Promise<{ success: boolean, error?: string }>}
72
+ */
73
+ function spawnFile(file, args, cwd, label, context) {
60
74
  context.logger.info(
61
- `${name} ${args.join(' ')} (in ${path.relative(context.workspaceRoot, cwd)})`,
75
+ `${[label, ...args].join(' ')} (in ${path.relative(context.workspaceRoot, cwd)})`,
62
76
  );
63
77
  return new Promise((resolve) => {
64
- const child = spawn(process.execPath, [bin, ...args], { cwd, stdio: 'inherit' });
78
+ const child = spawn(process.execPath, [file, ...args], { cwd, stdio: 'inherit' });
65
79
  // Ctrl-C reaches the whole process group, but a supervisor, CI or an IDE's task runner signals
66
80
  // `ng` alone, and Metro would outlive it on its port. So a stop is passed on.
67
81
  const stop = (signal) => child.kill(signal);
@@ -75,10 +89,10 @@ async function spawnBin(name, args, context) {
75
89
  settle(
76
90
  code === 0
77
91
  ? { success: true }
78
- : { success: false, error: `${name} exited with ${signal ?? `code ${code}`}` },
92
+ : { success: false, error: `${label} exited with ${signal ?? `code ${code}`}` },
79
93
  ),
80
94
  );
81
95
  });
82
96
  }
83
97
 
84
- module.exports = { resolveBin, projectRoot, spawnBin };
98
+ module.exports = { resolveBin, projectRoot, spawnBin, spawnFile };
@@ -0,0 +1,30 @@
1
+ /**
2
+ * `@ng-native/schematics:typecheck`: the project's code and templates, checked by `ngc`.
3
+ *
4
+ * `tsc` reads no template, so a binding to an input a component does not have passes it. The Metro
5
+ * config is loaded first, as the template's `typecheck` script does: once Tailwind is added, it
6
+ * writes the sheet `src/main.ts` imports, which a fresh checkout does not have.
7
+ */
8
+ const { createBuilder } = require('@angular-devkit/architect');
9
+ const { existsSync } = require('node:fs');
10
+ const path = require('node:path');
11
+ const { projectRoot, resolveBin, spawnFile } = require('./spawn-bin.cjs');
12
+
13
+ /**
14
+ * @param {import('@angular-devkit/architect').BuilderContext} context
15
+ * @returns {Promise<{ success: boolean, error?: string }>}
16
+ */
17
+ async function runTypecheck(context) {
18
+ const cwd = await projectRoot(context);
19
+ // A project without one has no Tailwind sheet to write either.
20
+ const metroConfig = path.join(cwd, 'metro.config.js');
21
+ if (existsSync(metroConfig)) {
22
+ const config = await spawnFile(metroConfig, [], cwd, 'node metro.config.js', context);
23
+ if (!config.success) return config;
24
+ }
25
+ const ngc = resolveBin('@angular/compiler-cli', cwd, 'ngc');
26
+ return spawnFile(ngc, ['-p', 'tsconfig.json', '--noEmit'], cwd, 'ngc', context);
27
+ }
28
+
29
+ module.exports = createBuilder((_options, context) => runTypecheck(context));
30
+ module.exports.runTypecheck = runTypecheck;
@@ -0,0 +1,7 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema",
3
+ "$id": "NgNativeTypecheckBuilder",
4
+ "title": "Typecheck",
5
+ "type": "object",
6
+ "properties": {}
7
+ }
package/builders.json CHANGED
@@ -10,6 +10,11 @@
10
10
  "implementation": "./builders/vitest.cjs",
11
11
  "schema": "./builders/vitest.json",
12
12
  "description": "Runs the project's tests once with Vitest, through @ng-native/testing."
13
+ },
14
+ "typecheck": {
15
+ "implementation": "./builders/typecheck.cjs",
16
+ "schema": "./builders/typecheck.json",
17
+ "description": "Checks the project's code and templates with ngc, after loading its Metro config."
13
18
  }
14
19
  }
15
20
  }
@@ -14,17 +14,18 @@ const { componentSource, testSource } = require('./sources.cjs');
14
14
 
15
15
  /**
16
16
  * The directory the component goes in: the one `ng generate` was run from if that is inside the
17
- * project, the project's root otherwise.
17
+ * project's `src`, and `src/app` otherwise, beside `app.ts`, as Angular's own schematic and
18
+ * `@ng-native/nx:component` put it. From the project's own directory that is `src/app` too.
18
19
  */
19
20
  function directoryFor(workspace, options) {
20
21
  const project = workspace.projects?.[options.project];
21
22
  if (!project) {
22
23
  throw new SchematicsException(`angular.json has no project called "${options.project}".`);
23
24
  }
24
- const root = project.sourceRoot ?? project.root;
25
+ const src = path.join(project.root, 'src');
25
26
  const cwd = path.normalize(options.path ?? '');
26
- const inside = cwd === root || cwd.startsWith(root + '/');
27
- return { directory: inside ? cwd : root, prefix: project.prefix };
27
+ const inside = cwd === src || cwd.startsWith(src + '/');
28
+ return { directory: inside ? cwd : path.join(src, 'app'), prefix: project.prefix };
28
29
  }
29
30
 
30
31
  /**
@@ -3,8 +3,8 @@ import { Pressable, SafeAreaProvider, SafeAreaView, Text, View } from '@ng-nativ
3
3
  import { StatusBar } from '@ng-native/device';
4
4
 
5
5
  /**
6
- * Element names are lowercase, and that is load-bearing rather than style: an uppercase name is
7
- * read as an unknown Angular component and commits as a plain view with nothing in it.
6
+ * Element names are lowercase, and that is load-bearing rather than style: an uppercase name such
7
+ * as <View> matches no component's selector, and the Metro transform fails the build on it.
8
8
  */
9
9
  @Component({
10
10
  imports: [Pressable, SafeAreaProvider, SafeAreaView, Text, View],
package/migrations.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "$schema": "../../node_modules/@angular-devkit/schematics/collection-schema.json",
3
3
  "schematics": {
4
4
  "sync-app-versions": {
5
- "version": "0.17.0",
5
+ "version": "0.17.1",
6
6
  "description": "Move the @ng-native packages each project's own package.json lists to the new version.",
7
7
  "factory": "./migrations/run.cjs#sync-app-versions"
8
8
  },
@@ -30,6 +30,16 @@
30
30
  "version": "0.17.0",
31
31
  "description": "Read an engine node's children, text, kind, host and sheet by their new names.",
32
32
  "factory": "./migrations/run.cjs#engine-node-fields"
33
+ },
34
+ "library-typecheck-declaration-map": {
35
+ "version": "0.17.1",
36
+ "description": "Turn off declarationMap in each Nx library's tsconfig.typecheck.json, which TypeScript refuses beside composite: false.",
37
+ "factory": "./migrations/run.cjs#library-typecheck-declaration-map"
38
+ },
39
+ "native-typecheck-target": {
40
+ "version": "0.17.1",
41
+ "description": "Give each Angular Native project in angular.json a typecheck target, run by ngc.",
42
+ "factory": "./migrations/run.cjs#native-typecheck-target"
33
43
  }
34
44
  }
35
45
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ng-native/schematics",
3
- "version": "0.17.0",
3
+ "version": "0.17.1",
4
4
  "description": "ng add and ng generate for Angular Native: an Expo app in an Angular CLI workspace, with builders that run it.",
5
5
  "keywords": [
6
6
  "angular",
@@ -47,7 +47,7 @@
47
47
  "@angular-devkit/architect": ">=0.2200.0 <0.2300.0",
48
48
  "@angular-devkit/core": "^22.0.0",
49
49
  "@angular-devkit/schematics": "^22.0.0",
50
- "@ng-native/migrate": "0.17.0"
50
+ "@ng-native/migrate": "0.17.1"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@schematics/angular": "22.1.9"