@ng-native/schematics 0.2.0 → 0.4.0
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/application/index.cjs +9 -4
- package/application/schema.json +4 -0
- package/component/index.cjs +1 -30
- package/component/sources.cjs +47 -0
- package/files/AGENTS.md +11 -3
- package/files/src/app/app.ts +22 -4
- package/files/src/main.ts +4 -0
- package/migrations/run.cjs +5 -0
- package/migrations.json +25 -0
- package/native-app.cjs +10 -119
- package/ng-add/index.cjs +1 -1
- package/ng-add/schema.json +4 -0
- package/package.json +28 -2
package/application/index.cjs
CHANGED
|
@@ -96,13 +96,14 @@ function commands(name) {
|
|
|
96
96
|
].join('\n');
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
function writeFiles(tree, root, name) {
|
|
99
|
+
function writeFiles(tree, root, name, bundleIdentifier) {
|
|
100
100
|
for (const file of native.SOURCE_FILES) {
|
|
101
101
|
tree.create(path.join(root, file), native.sourceFile(file));
|
|
102
102
|
}
|
|
103
|
-
tree.create(path.join(root, 'app.json'), native.appJson(name));
|
|
103
|
+
tree.create(path.join(root, 'app.json'), native.appJson(name, bundleIdentifier));
|
|
104
104
|
tree.create(path.join(root, 'AGENTS.md'), native.agentsFile(commands(name)));
|
|
105
105
|
tree.create(path.join(root, 'CLAUDE.md'), '@AGENTS.md\n');
|
|
106
|
+
tree.create(path.join(root, '.gitignore'), native.GITIGNORE);
|
|
106
107
|
const manifest = native.projectManifest(name, readJson(tree, 'package.json'));
|
|
107
108
|
tree.create(path.join(root, 'package.json'), JSON.stringify(manifest, null, 2) + '\n');
|
|
108
109
|
}
|
|
@@ -130,7 +131,7 @@ function ignoreExpo(tree) {
|
|
|
130
131
|
}
|
|
131
132
|
|
|
132
133
|
/**
|
|
133
|
-
* @param {{ name: string, directory?: string, prefix?: string, skipInstall?: boolean }} options
|
|
134
|
+
* @param {{ name: string, directory?: string, prefix?: string, bundleIdentifier?: string, skipInstall?: boolean }} options
|
|
134
135
|
*/
|
|
135
136
|
function application(options) {
|
|
136
137
|
return (tree, context) => {
|
|
@@ -146,9 +147,13 @@ function application(options) {
|
|
|
146
147
|
throw new SchematicsException(`angular.json already has a project called "${name}".`);
|
|
147
148
|
}
|
|
148
149
|
const root = options.directory ?? path.join(workspace.newProjectRoot ?? 'projects', name);
|
|
150
|
+
const scope = readJson(tree, 'package.json').name?.match(/^@[^/]+/)?.[0];
|
|
151
|
+
const bundleIdentifier = options.bundleIdentifier ?? native.bundleIdentifier(name, scope);
|
|
152
|
+
const problem = native.bundleIdentifierProblem(bundleIdentifier);
|
|
153
|
+
if (problem) throw new SchematicsException(problem);
|
|
149
154
|
|
|
150
155
|
addDependencies(tree, context);
|
|
151
|
-
writeFiles(tree, root, name);
|
|
156
|
+
writeFiles(tree, root, name, bundleIdentifier);
|
|
152
157
|
workspace.projects = { ...workspace.projects, [name]: project(root, name, options.prefix) };
|
|
153
158
|
writeJson(tree, 'angular.json', workspace);
|
|
154
159
|
ignoreExpo(tree);
|
package/application/schema.json
CHANGED
|
@@ -21,6 +21,10 @@
|
|
|
21
21
|
"default": "app",
|
|
22
22
|
"pattern": "^[a-z][a-z0-9-]*$"
|
|
23
23
|
},
|
|
24
|
+
"bundleIdentifier": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"description": "The iOS bundle identifier and Android package: com.acme.mobile. Defaults to com.<workspace scope>.<name>."
|
|
27
|
+
},
|
|
24
28
|
"skipInstall": {
|
|
25
29
|
"type": "boolean",
|
|
26
30
|
"description": "Write the files and package.json without installing.",
|
package/component/index.cjs
CHANGED
|
@@ -10,36 +10,7 @@
|
|
|
10
10
|
const path = require('node:path').posix;
|
|
11
11
|
const { SchematicsException } = require('@angular-devkit/schematics');
|
|
12
12
|
const { strings } = require('@angular-devkit/core');
|
|
13
|
-
|
|
14
|
-
function componentSource(className, selector, label) {
|
|
15
|
-
return `import { Component } from '@angular/core';
|
|
16
|
-
import { Text, View } from '@ng-native/components';
|
|
17
|
-
|
|
18
|
-
@Component({
|
|
19
|
-
selector: '${selector}',
|
|
20
|
-
imports: [Text, View],
|
|
21
|
-
template: \`
|
|
22
|
-
<view>
|
|
23
|
-
<text>${label}</text>
|
|
24
|
-
</view>
|
|
25
|
-
\`,
|
|
26
|
-
})
|
|
27
|
-
export class ${className} {}
|
|
28
|
-
`;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function testSource(className, file, label) {
|
|
32
|
-
return `import { render, screen } from '@ng-native/testing';
|
|
33
|
-
import { expect, test } from 'vitest';
|
|
34
|
-
import { ${className} } from './${file}.ts';
|
|
35
|
-
|
|
36
|
-
test('renders', async () => {
|
|
37
|
-
await render(${className});
|
|
38
|
-
|
|
39
|
-
expect(screen.getByText('${label}')).toBeTruthy();
|
|
40
|
-
});
|
|
41
|
-
`;
|
|
42
|
-
}
|
|
13
|
+
const { componentSource, testSource } = require('./sources.cjs');
|
|
43
14
|
|
|
44
15
|
/**
|
|
45
16
|
* The directory the component goes in: the one `ng generate` was run from if that is inside the
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The files a generated component is made of: a component built from `<view>` and `<text>`, and a
|
|
3
|
+
* test that renders it on the fake Fabric. `@ng-native/schematics` and `@ng-native/nx` each ship
|
|
4
|
+
* this file, and a test in `@ng-native/nx` keeps the two identical.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @param {string} className
|
|
9
|
+
* @param {string} selector
|
|
10
|
+
* @param {string} label the text it shows, which its test finds
|
|
11
|
+
*/
|
|
12
|
+
function componentSource(className, selector, label) {
|
|
13
|
+
return `import { Component } from '@angular/core';
|
|
14
|
+
import { Text, View } from '@ng-native/components';
|
|
15
|
+
|
|
16
|
+
@Component({
|
|
17
|
+
selector: '${selector}',
|
|
18
|
+
imports: [Text, View],
|
|
19
|
+
template: \`
|
|
20
|
+
<view>
|
|
21
|
+
<text>${label}</text>
|
|
22
|
+
</view>
|
|
23
|
+
\`,
|
|
24
|
+
})
|
|
25
|
+
export class ${className} {}
|
|
26
|
+
`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @param {string} className
|
|
31
|
+
* @param {string} file the component's file name, without `.ts`
|
|
32
|
+
* @param {string} label
|
|
33
|
+
*/
|
|
34
|
+
function testSource(className, file, label) {
|
|
35
|
+
return `import { render, screen } from '@ng-native/testing';
|
|
36
|
+
import { expect, test } from 'vitest';
|
|
37
|
+
import { ${className} } from './${file}.ts';
|
|
38
|
+
|
|
39
|
+
test('renders', async () => {
|
|
40
|
+
await render(${className});
|
|
41
|
+
|
|
42
|
+
expect(screen.getByText('${label}')).toBeTruthy();
|
|
43
|
+
});
|
|
44
|
+
`;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
module.exports = { componentSource, testSource };
|
package/files/AGENTS.md
CHANGED
|
@@ -31,9 +31,17 @@ change; both are fast.
|
|
|
31
31
|
imported from `@ng-native/components` into the component's `imports`, like any Angular
|
|
32
32
|
component: `imports: [View, Text]`. `<View>` compiles to an empty template, and an element used
|
|
33
33
|
without its import renders as a plain view.
|
|
34
|
-
- **There is no DOM.** No `document`, no `window`, no `<
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
- **There is no DOM.** No `document`, no `window`, no `<button>`, `<a>`, `<input>` or `<img>`, no
|
|
35
|
+
`@angular/platform-browser`, and no `@angular/animations`. Use the native elements above. HTML's
|
|
36
|
+
text elements (`p`, `span`, `h1`, `strong`) draw as text and its layout elements (`div`,
|
|
37
|
+
`section`, `ul`) as plain views, with none of a browser's default styles.
|
|
38
|
+
- **A component's host is a flex item.** `<app-case-list />` commits as a view of its own, with no
|
|
39
|
+
`flex`, so a `flex: 1` scroll view inside it gets a height of zero and shows nothing. A component
|
|
40
|
+
that fills the space it is given sets `host: { style: 'flex: 1' }` (or `:host { flex: 1; }`).
|
|
41
|
+
- **Text is drawn in a text element.** `<text>` is the one with inputs and outputs (`numberOfLines`,
|
|
42
|
+
`(press)`). `p`, `span` and the other HTML text elements are text while they hold only text and
|
|
43
|
+
other text elements; one that holds a view is a view. Text written straight into a view is given
|
|
44
|
+
a paragraph of its own, one per run, and never flows inline with the elements beside it.
|
|
37
45
|
- **Events are native:** `(press)` on `<pressable>`, not `(click)`; `[(value)]` or `(changeText)` on
|
|
38
46
|
`<text-input>`; `(scroll)`, `(layout)`. A pressable text is `<text pressable (press)="...">`.
|
|
39
47
|
- **Signals, zoneless, AOT.** State is signals and `computed()`; there is no zone.js, so nothing
|
package/files/src/app/app.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { Component, signal } from '@angular/core';
|
|
1
|
+
import { Component, inject, signal } from '@angular/core';
|
|
2
2
|
import { Pressable, SafeAreaProvider, SafeAreaView, Text, View } from '@ng-native/components';
|
|
3
|
+
import { StatusBar } from '@ng-native/device';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Element names are lowercase, and that is load-bearing rather than style: an uppercase name is
|
|
@@ -28,7 +29,7 @@ import { Pressable, SafeAreaProvider, SafeAreaView, Text, View } from '@ng-nativ
|
|
|
28
29
|
}
|
|
29
30
|
.screen {
|
|
30
31
|
flex: 1;
|
|
31
|
-
background-color: #
|
|
32
|
+
background-color: #f5f5f7;
|
|
32
33
|
}
|
|
33
34
|
.body {
|
|
34
35
|
flex: 1;
|
|
@@ -37,12 +38,12 @@ import { Pressable, SafeAreaProvider, SafeAreaView, Text, View } from '@ng-nativ
|
|
|
37
38
|
padding: 24px;
|
|
38
39
|
}
|
|
39
40
|
.title {
|
|
40
|
-
color: #
|
|
41
|
+
color: #101014;
|
|
41
42
|
font-size: 28px;
|
|
42
43
|
font-weight: 700;
|
|
43
44
|
}
|
|
44
45
|
.hint {
|
|
45
|
-
color: #
|
|
46
|
+
color: #5f5f6b;
|
|
46
47
|
font-size: 15px;
|
|
47
48
|
}
|
|
48
49
|
.button {
|
|
@@ -57,8 +58,25 @@ import { Pressable, SafeAreaProvider, SafeAreaView, Text, View } from '@ng-nativ
|
|
|
57
58
|
font-size: 16px;
|
|
58
59
|
font-weight: 600;
|
|
59
60
|
}
|
|
61
|
+
@media (prefers-color-scheme: dark) {
|
|
62
|
+
.screen {
|
|
63
|
+
background-color: #101014;
|
|
64
|
+
}
|
|
65
|
+
.title {
|
|
66
|
+
color: #ffffff;
|
|
67
|
+
}
|
|
68
|
+
.hint {
|
|
69
|
+
color: #8b8b96;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
60
72
|
`,
|
|
61
73
|
})
|
|
62
74
|
export class App {
|
|
63
75
|
protected readonly count = signal(0);
|
|
76
|
+
|
|
77
|
+
constructor() {
|
|
78
|
+
// Dark status bar icons in light mode and light ones in dark mode. Unclaimed, Android keeps
|
|
79
|
+
// light icons whatever the scheme.
|
|
80
|
+
inject(StatusBar).set({ style: 'auto' });
|
|
81
|
+
}
|
|
64
82
|
}
|
package/files/src/main.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
// Expo's runtime: its fetch, whose response streams a body, and URL, TextDecoderStream and
|
|
2
|
+
// structuredClone. Metro runs it before this file only when something imports it, and nothing
|
|
3
|
+
// else does in a release build, which would then get React Native's fetch, with no body.
|
|
4
|
+
import 'expo';
|
|
1
5
|
import { AppRegistry, Image, Platform, processColor } from 'react-native';
|
|
2
6
|
import { mount } from '@ng-native/platform';
|
|
3
7
|
import { currentConditions, deviceTokens, watchConditions } from '@ng-native/device';
|
package/migrations.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "../../node_modules/@angular-devkit/schematics/collection-schema.json",
|
|
3
|
+
"schematics": {
|
|
4
|
+
"sync-app-versions": {
|
|
5
|
+
"version": "0.4.0",
|
|
6
|
+
"description": "Move the @ng-native packages each project's own package.json lists to the new version.",
|
|
7
|
+
"factory": "./migrations/run.cjs#sync-app-versions"
|
|
8
|
+
},
|
|
9
|
+
"split-store-and-player": {
|
|
10
|
+
"version": "0.3.0",
|
|
11
|
+
"description": "Import Storage, SecureStorage, audioPlayer and videoPlayer from the entry points that now hold them.",
|
|
12
|
+
"factory": "./migrations/run.cjs#split-store-and-player"
|
|
13
|
+
},
|
|
14
|
+
"tracking-available-getter": {
|
|
15
|
+
"version": "0.3.0",
|
|
16
|
+
"description": "Read Tracking's available as a property rather than calling it.",
|
|
17
|
+
"factory": "./migrations/run.cjs#tracking-available-getter"
|
|
18
|
+
},
|
|
19
|
+
"device-react-native-import": {
|
|
20
|
+
"version": "0.3.0",
|
|
21
|
+
"description": "Note each import of reactNative or ReactNative from @ng-native/device, which no longer exports them.",
|
|
22
|
+
"factory": "./migrations/run.cjs#device-react-native-import"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
package/native-app.cjs
CHANGED
|
@@ -2,52 +2,16 @@
|
|
|
2
2
|
* What an Angular Native app is made of, whichever workspace it is generated into.
|
|
3
3
|
*
|
|
4
4
|
* The source of truth is `template/`, the starter `create-expo-app` uses and the setup this project
|
|
5
|
-
* verifies before every release. `files/` holds verbatim copies of the template's source files
|
|
6
|
-
* the versions
|
|
7
|
-
*
|
|
5
|
+
* verifies before every release. `files/` holds verbatim copies of the template's source files,
|
|
6
|
+
* the versions are the template's own, and `native-app.test.ts` fails the moment either drifts
|
|
7
|
+
* from it. A generated app and a templated app are the same app.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
* is
|
|
9
|
+
* What does not depend on the Angular CLI, the dependencies, `app.json` and bundle identifier
|
|
10
|
+
* among them, is `@ng-native/migrate/native-app.cjs`, which `@ng-native/nx` builds its apps from too.
|
|
11
11
|
*/
|
|
12
12
|
const { readFileSync } = require('node:fs');
|
|
13
13
|
const path = require('node:path');
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
const { version } = require('./package.json');
|
|
17
|
-
|
|
18
|
-
const FRAMEWORK = [
|
|
19
|
-
'@ng-native/components',
|
|
20
|
-
'@ng-native/device',
|
|
21
|
-
'@ng-native/fabric',
|
|
22
|
-
'@ng-native/metro',
|
|
23
|
-
'@ng-native/platform',
|
|
24
|
-
];
|
|
25
|
-
|
|
26
|
-
/** @type {Record<string, string>} */
|
|
27
|
-
const dependencies = {
|
|
28
|
-
...Object.fromEntries(FRAMEWORK.map((name) => [name, version])),
|
|
29
|
-
'@angular/common': '^22.0.0',
|
|
30
|
-
'@angular/core': '^22.0.0',
|
|
31
|
-
expo: '~57.0.26',
|
|
32
|
-
'expo-status-bar': '~57.0.1',
|
|
33
|
-
'expo-system-ui': '~57.0.4',
|
|
34
|
-
react: '19.2.3',
|
|
35
|
-
'react-native': '0.86.3',
|
|
36
|
-
'react-native-safe-area-context': '~5.7.0',
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
/** @type {Record<string, string>} */
|
|
40
|
-
const devDependencies = {
|
|
41
|
-
// An Angular workspace already has Babel 8 through @angular/compiler-cli, and React Native's
|
|
42
|
-
// Babel peer would otherwise take the newest copy there is.
|
|
43
|
-
// The typecheck script compiles the templates too, which only the Angular compiler can.
|
|
44
|
-
'@angular/compiler-cli': '^22.0.0',
|
|
45
|
-
'@babel/core': '^7.29.7',
|
|
46
|
-
'@ng-native/testing': version,
|
|
47
|
-
'@types/react': '~19.2.2',
|
|
48
|
-
typescript: '~6.0.3',
|
|
49
|
-
vitest: '^5.0.0',
|
|
50
|
-
};
|
|
14
|
+
const shared = require('@ng-native/migrate/native-app.cjs');
|
|
51
15
|
|
|
52
16
|
/**
|
|
53
17
|
* The template's files, copied verbatim into the new app. Its `metro.config.js` and `tsconfig.json`
|
|
@@ -82,94 +46,21 @@ function agentsFile(commands) {
|
|
|
82
46
|
}
|
|
83
47
|
|
|
84
48
|
/**
|
|
85
|
-
* The
|
|
86
|
-
*
|
|
87
|
-
* Without the template's icons: they are the template's branding, not this app's, and Expo draws
|
|
88
|
-
* its own default until `icon` is set.
|
|
89
|
-
*
|
|
90
|
-
* @param {string} name the project name, which is also the Expo slug
|
|
91
|
-
*/
|
|
92
|
-
function appJson(name) {
|
|
93
|
-
const expo = {
|
|
94
|
-
name,
|
|
95
|
-
slug: name,
|
|
96
|
-
version: '1.0.0',
|
|
97
|
-
platforms: ['ios', 'android'],
|
|
98
|
-
orientation: 'portrait',
|
|
99
|
-
userInterfaceStyle: 'dark',
|
|
100
|
-
ios: { supportsTablet: true },
|
|
101
|
-
android: { predictiveBackGestureEnabled: false },
|
|
102
|
-
scheme: name.replace(/[^a-z0-9]/gi, '').toLowerCase(),
|
|
103
|
-
// The template's: Expo otherwise guesses a router root from src/app and says so on every start.
|
|
104
|
-
extra: { router: { root: 'src/app' } },
|
|
105
|
-
plugins: ['@ng-native/metro'],
|
|
106
|
-
};
|
|
107
|
-
return JSON.stringify({ expo }, null, 2) + '\n';
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* The project's own `package.json`, which only Expo reads: `main` is how it finds the entry file.
|
|
112
|
-
*
|
|
113
|
-
* It lists every dependency the app has too, at the ranges the workspace root installs, though
|
|
114
|
-
* nothing installs from it. Expo's autolinking links the native modules named here and no others,
|
|
115
|
-
* so one left out, such as `react-native-safe-area-context`, is missing from the native build. And
|
|
116
|
-
* `expo prebuild`, which `expo run:ios` starts with, adds `expo`, `react` or `react-native` if it
|
|
117
|
-
* does not find them and then offers to install them into the project's directory, which would put
|
|
118
|
-
* a second copy of React Native beside the root's.
|
|
49
|
+
* The project's own `package.json`, which only Expo reads: `main` is how it finds the entry file,
|
|
50
|
+
* and `prebuildPins` says why it lists every dependency the app has.
|
|
119
51
|
*
|
|
120
52
|
* @param {string} name
|
|
121
53
|
* @param {{ dependencies?: Record<string, string>, devDependencies?: Record<string, string> }} root
|
|
122
54
|
* the workspace's root `package.json`, once this app's dependencies are in it
|
|
123
55
|
*/
|
|
124
56
|
function projectManifest(name, root) {
|
|
125
|
-
|
|
126
|
-
const pinned = Object.keys(dependencies).map((pkg) => [pkg, installed[pkg] ?? dependencies[pkg]]);
|
|
127
|
-
return { name, private: true, main: 'src/main.ts', dependencies: Object.fromEntries(pinned) };
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Where what a workspace already has can be older than what a new app is given: `@ng-native/testing`
|
|
132
|
-
* installs Vitest 5 but its plugin runs on 4, which `ng new` 22.1 and the Nx preset still start on.
|
|
133
|
-
* The range here is that package's `vitest` peer, and a test holds the two together.
|
|
134
|
-
*/
|
|
135
|
-
const accepted = { vitest: '^4.0.8 || ^5.0.0' };
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Why an existing dependency would stop this app installing or running, as a sentence each.
|
|
139
|
-
*
|
|
140
|
-
* Only ranges already in the manifest are judged, and only a range that cannot overlap the one
|
|
141
|
-
* wanted is a conflict: `~6.0.2` and `~6.0.3` resolve to the same TypeScript. A missing package is
|
|
142
|
-
* added at the version above. Nothing is rewritten, because moving a workspace's Angular or Vitest is an upgrade of every
|
|
143
|
-
* project in it, and that belongs to `ng update` or `nx migrate`, not to a generator.
|
|
144
|
-
*
|
|
145
|
-
* @param {{ dependencies?: Record<string, string>, devDependencies?: Record<string, string> }} manifest
|
|
146
|
-
* @returns {string[]}
|
|
147
|
-
*/
|
|
148
|
-
function conflicts(manifest) {
|
|
149
|
-
const existing = { ...manifest.dependencies, ...manifest.devDependencies };
|
|
150
|
-
const problems = [];
|
|
151
|
-
for (const [name, installed] of Object.entries({ ...dependencies, ...devDependencies })) {
|
|
152
|
-
const range = existing[name];
|
|
153
|
-
const wanted = accepted[name] ?? installed;
|
|
154
|
-
if (!range || name.startsWith('@ng-native/')) continue;
|
|
155
|
-
if (semver.validRange(range) && !semver.intersects(range, wanted)) {
|
|
156
|
-
problems.push(
|
|
157
|
-
`${name} is ${range} here, and Angular Native needs ${wanted}. ` +
|
|
158
|
-
`npm will refuse the install until it is moved.`,
|
|
159
|
-
);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
return problems;
|
|
57
|
+
return { name, private: true, main: 'src/main.ts', dependencies: shared.prebuildPins(root) };
|
|
163
58
|
}
|
|
164
59
|
|
|
165
60
|
module.exports = {
|
|
166
|
-
|
|
167
|
-
devDependencies,
|
|
61
|
+
...shared,
|
|
168
62
|
SOURCE_FILES,
|
|
169
63
|
sourceFile,
|
|
170
64
|
agentsFile,
|
|
171
|
-
appJson,
|
|
172
65
|
projectManifest,
|
|
173
|
-
conflicts,
|
|
174
|
-
accepted,
|
|
175
66
|
};
|
package/ng-add/index.cjs
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
const { application } = require('../application/index.cjs');
|
|
10
10
|
|
|
11
|
-
/** @param {{ name?: string, directory?: string, skipInstall?: boolean }} options */
|
|
11
|
+
/** @param {{ name?: string, directory?: string, bundleIdentifier?: string, skipInstall?: boolean }} options */
|
|
12
12
|
function ngAdd(options) {
|
|
13
13
|
return application({ ...options, name: options.name ?? 'native', prefix: 'app' });
|
|
14
14
|
}
|
package/ng-add/schema.json
CHANGED
|
@@ -14,6 +14,10 @@
|
|
|
14
14
|
"type": "string",
|
|
15
15
|
"description": "Where the project goes. Defaults to newProjectRoot/name, usually projects/native."
|
|
16
16
|
},
|
|
17
|
+
"bundleIdentifier": {
|
|
18
|
+
"type": "string",
|
|
19
|
+
"description": "The iOS bundle identifier and Android package: com.acme.mobile. Defaults to com.<workspace scope>.<name>."
|
|
20
|
+
},
|
|
17
21
|
"skipInstall": {
|
|
18
22
|
"type": "boolean",
|
|
19
23
|
"description": "Write the files and package.json without installing.",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ng-native/schematics",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
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",
|
|
@@ -21,10 +21,31 @@
|
|
|
21
21
|
"ng-add": {
|
|
22
22
|
"save": "devDependencies"
|
|
23
23
|
},
|
|
24
|
+
"ng-update": {
|
|
25
|
+
"migrations": "./migrations.json",
|
|
26
|
+
"packageGroupName": "@ng-native/schematics",
|
|
27
|
+
"packageGroup": [
|
|
28
|
+
"@ng-native/components",
|
|
29
|
+
"@ng-native/device",
|
|
30
|
+
"@ng-native/expo",
|
|
31
|
+
"@ng-native/fabric",
|
|
32
|
+
"@ng-native/icons",
|
|
33
|
+
"@ng-native/metro",
|
|
34
|
+
"@ng-native/migrate",
|
|
35
|
+
"@ng-native/nx",
|
|
36
|
+
"@ng-native/platform",
|
|
37
|
+
"@ng-native/router",
|
|
38
|
+
"@ng-native/schematics",
|
|
39
|
+
"@ng-native/tailwind",
|
|
40
|
+
"@ng-native/testing",
|
|
41
|
+
"@ng-native/web"
|
|
42
|
+
]
|
|
43
|
+
},
|
|
24
44
|
"dependencies": {
|
|
25
45
|
"@angular-devkit/architect": ">=0.2200.0 <0.2300.0",
|
|
26
46
|
"@angular-devkit/core": "^22.0.0",
|
|
27
47
|
"@angular-devkit/schematics": "^22.0.0",
|
|
48
|
+
"@ng-native/migrate": "0.4.0",
|
|
28
49
|
"semver": "^7.7.0"
|
|
29
50
|
},
|
|
30
51
|
"devDependencies": {
|
|
@@ -32,9 +53,13 @@
|
|
|
32
53
|
"@types/semver": "^7.7.0"
|
|
33
54
|
},
|
|
34
55
|
"nx": {
|
|
56
|
+
"projectType": "library",
|
|
35
57
|
"tags": [
|
|
36
58
|
"scope:schematics",
|
|
37
59
|
"layer:build"
|
|
60
|
+
],
|
|
61
|
+
"implicitDependencies": [
|
|
62
|
+
"@ng-native/template"
|
|
38
63
|
]
|
|
39
64
|
},
|
|
40
65
|
"license": "MIT",
|
|
@@ -51,6 +76,7 @@
|
|
|
51
76
|
"*.cjs",
|
|
52
77
|
"collection.json",
|
|
53
78
|
"builders.json",
|
|
79
|
+
"migrations.json",
|
|
54
80
|
"*/*.cjs",
|
|
55
81
|
"*/*.json",
|
|
56
82
|
"files"
|
|
@@ -60,6 +86,6 @@
|
|
|
60
86
|
},
|
|
61
87
|
"scripts": {
|
|
62
88
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
63
|
-
"test": "node --test \"*.test.ts\" \"{application,component,builders}/*.test.ts\""
|
|
89
|
+
"test": "node --test \"*.test.ts\" \"{application,component,builders,migrations}/*.test.ts\""
|
|
64
90
|
}
|
|
65
91
|
}
|