@ng-native/nx 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/README.md +8 -3
- package/application/index.cjs +64 -14
- package/component/index.cjs +66 -0
- package/component/schema.json +38 -0
- 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/generators.json +22 -0
- package/init/index.cjs +91 -1
- package/library/index.cjs +336 -0
- package/library/schema.json +36 -0
- package/migrations/run.cjs +5 -0
- package/migrations.json +24 -0
- package/native-app.cjs +47 -171
- package/package.json +30 -4
- package/sync/index.cjs +233 -0
- package/sync/schema.json +8 -0
- package/tailwind/index.cjs +573 -0
- package/tailwind/schema.json +37 -0
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `nx g @ng-native/nx:library packages/ui`: a library of native components, tested the way an
|
|
3
|
+
* Angular Native app is.
|
|
4
|
+
*
|
|
5
|
+
* The library itself is the workspace's own kind: `@nx/angular:library` where the workspace has
|
|
6
|
+
* `@nx/angular`, and `@nx/js:library` in the TypeScript preset, which cannot take `@nx/angular`
|
|
7
|
+
* because Angular does not support TypeScript project references. Either is run without its
|
|
8
|
+
* tests, which would be Analog on jsdom or a plain Vitest, neither of which can render a native
|
|
9
|
+
* component. In their place this writes the app's `vitest.config.mts`, a `test` target that runs
|
|
10
|
+
* it once, a `tsconfig.spec.json` for the tests, and a native component with a test for the fake
|
|
11
|
+
* Fabric in place of the one the generator wrote.
|
|
12
|
+
*/
|
|
13
|
+
const { readFileSync } = require('node:fs');
|
|
14
|
+
const nodePath = require('node:path');
|
|
15
|
+
const path = nodePath.posix;
|
|
16
|
+
const {
|
|
17
|
+
addDependenciesToPackageJson,
|
|
18
|
+
ensurePackage,
|
|
19
|
+
formatFiles,
|
|
20
|
+
getProjects,
|
|
21
|
+
installPackagesTask,
|
|
22
|
+
joinPathFragments,
|
|
23
|
+
names,
|
|
24
|
+
readNxJson,
|
|
25
|
+
readJson,
|
|
26
|
+
writeJson,
|
|
27
|
+
updateJson,
|
|
28
|
+
updateProjectConfiguration,
|
|
29
|
+
} = require('@nx/devkit');
|
|
30
|
+
const native = require('../native-app.cjs');
|
|
31
|
+
const { workspaceNxVersion } = require('../init/index.cjs');
|
|
32
|
+
const { hasPathAliases } = require('../application/index.cjs');
|
|
33
|
+
const { usesWorkspaces } = require('../application/workspaces.cjs');
|
|
34
|
+
const { asSaved } = require('../save-exact.cjs');
|
|
35
|
+
const { writeComponent } = require('../component/index.cjs');
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The defaults a generator's schema gives its options, from the copy installed at `root`.
|
|
39
|
+
*
|
|
40
|
+
* @param {string} root
|
|
41
|
+
* @param {string} pkg
|
|
42
|
+
* @param {string} generator
|
|
43
|
+
* @returns {Record<string, unknown>}
|
|
44
|
+
*/
|
|
45
|
+
function schemaDefaults(root, pkg, generator) {
|
|
46
|
+
let manifest;
|
|
47
|
+
try {
|
|
48
|
+
manifest = require.resolve(`${pkg}/package.json`, { paths: [root] });
|
|
49
|
+
} catch {
|
|
50
|
+
return {};
|
|
51
|
+
}
|
|
52
|
+
const read = (file) =>
|
|
53
|
+
JSON.parse(readFileSync(nodePath.join(nodePath.dirname(manifest), file), 'utf8'));
|
|
54
|
+
const entry = read(read('package.json').generators).generators[generator];
|
|
55
|
+
const { properties = {} } = read(entry.schema);
|
|
56
|
+
return Object.fromEntries(
|
|
57
|
+
Object.entries(properties)
|
|
58
|
+
.filter(([, property]) => 'default' in property)
|
|
59
|
+
.map(([name, property]) => [name, property.default]),
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* The options `nx g <pkg>:<generator>` starts from: its schema's defaults, then the workspace's
|
|
65
|
+
* own in `nx.json`. A generator called from another gets neither, and `@nx/angular:library` called
|
|
66
|
+
* bare writes a library with strict type checking off.
|
|
67
|
+
*
|
|
68
|
+
* @param {import('@nx/devkit').Tree} tree
|
|
69
|
+
* @param {string} pkg
|
|
70
|
+
* @param {string} generator
|
|
71
|
+
*/
|
|
72
|
+
function generatorDefaults(tree, pkg, generator, root = tree.root) {
|
|
73
|
+
const workspace = readNxJson(tree)?.generators ?? {};
|
|
74
|
+
return {
|
|
75
|
+
...schemaDefaults(root, pkg, generator),
|
|
76
|
+
...workspace[pkg]?.[generator],
|
|
77
|
+
...workspace[`${pkg}:${generator}`],
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** The library generators this one builds on, at the workspace's Nx. Replaced in tests. */
|
|
82
|
+
const bases = {
|
|
83
|
+
/** @param {import('@nx/devkit').Tree} tree @param {object} options */
|
|
84
|
+
async angular(tree, options) {
|
|
85
|
+
// Only run where the workspace lists `@nx/angular`, whose root export has no generators.
|
|
86
|
+
const { libraryGenerator } = ensurePackage('@nx/angular/generators', workspaceNxVersion(tree));
|
|
87
|
+
return libraryGenerator(tree, {
|
|
88
|
+
...generatorDefaults(tree, '@nx/angular', 'library'),
|
|
89
|
+
...options,
|
|
90
|
+
});
|
|
91
|
+
},
|
|
92
|
+
/** @param {import('@nx/devkit').Tree} tree @param {object} options */
|
|
93
|
+
async js(tree, options) {
|
|
94
|
+
const { libraryGenerator } = ensurePackage('@nx/js', workspaceNxVersion(tree));
|
|
95
|
+
return libraryGenerator(tree, { ...generatorDefaults(tree, '@nx/js', 'library'), ...options });
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
/** What the component and its test import. */
|
|
100
|
+
const imports = {
|
|
101
|
+
dependencies: {
|
|
102
|
+
'@angular/core': native.dependencies['@angular/core'],
|
|
103
|
+
'@ng-native/components': native.dependencies['@ng-native/components'],
|
|
104
|
+
},
|
|
105
|
+
devDependencies: {
|
|
106
|
+
'@ng-native/testing': native.devDependencies['@ng-native/testing'],
|
|
107
|
+
vitest: native.devDependencies.vitest,
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/** What `nx typecheck` runs for a library in the TypeScript preset: `ngc`, which reads templates. */
|
|
112
|
+
const typecheckDependencies = {
|
|
113
|
+
'@angular/compiler-cli': native.devDependencies['@angular/compiler-cli'],
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
function projectAt(tree, root) {
|
|
117
|
+
for (const [name, project] of getProjects(tree))
|
|
118
|
+
if (project.root === root) return { name, project };
|
|
119
|
+
throw new Error(`No project was generated in ${root}.`);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* The native component and its test, where the generator put its own component: in a folder of
|
|
124
|
+
* its own under `src/lib` from `@nx/angular`, with an external template and stylesheet this
|
|
125
|
+
* leaves out, or as `src/lib/<name>.ts` from `@nx/js`. `src/index.ts` already exports it.
|
|
126
|
+
*/
|
|
127
|
+
function replaceComponent(tree, project, file) {
|
|
128
|
+
const lib = joinPathFragments(project.root, 'src', 'lib');
|
|
129
|
+
const folder = tree.exists(joinPathFragments(lib, file, `${file}.ts`))
|
|
130
|
+
? joinPathFragments(lib, file)
|
|
131
|
+
: lib;
|
|
132
|
+
for (const extension of ['html', 'css', 'spec.ts']) {
|
|
133
|
+
const own = joinPathFragments(folder, `${file}.${extension}`);
|
|
134
|
+
if (tree.exists(own)) tree.delete(own);
|
|
135
|
+
}
|
|
136
|
+
writeComponent(tree, folder, file, project.prefix);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* A `tsconfig.spec.json` like the one each generator writes with its tests, including the tests
|
|
141
|
+
* and the Vitest config. The tests import their component as `./ui.ts`, as the template's do.
|
|
142
|
+
*/
|
|
143
|
+
function writeSpecConfig(tree, root, angular) {
|
|
144
|
+
const include = ['vitest.config.mts', 'src/**/*.test.ts'];
|
|
145
|
+
const spec = angular
|
|
146
|
+
? {
|
|
147
|
+
extends: './tsconfig.json',
|
|
148
|
+
compilerOptions: { noEmit: true, allowImportingTsExtensions: true },
|
|
149
|
+
include,
|
|
150
|
+
}
|
|
151
|
+
: {
|
|
152
|
+
// A project reference of the TypeScript preset's, which emits declarations only.
|
|
153
|
+
extends: readJson(tree, joinPathFragments(root, 'tsconfig.lib.json')).extends,
|
|
154
|
+
compilerOptions: { outDir: './out-tsc/vitest', allowImportingTsExtensions: true },
|
|
155
|
+
include,
|
|
156
|
+
references: [{ path: './tsconfig.lib.json' }],
|
|
157
|
+
};
|
|
158
|
+
tree.write(joinPathFragments(root, 'tsconfig.spec.json'), JSON.stringify(spec, null, 2) + '\n');
|
|
159
|
+
updateJson(tree, joinPathFragments(root, 'tsconfig.json'), (config) => {
|
|
160
|
+
const references = config.references ?? [];
|
|
161
|
+
if (!references.some((reference) => reference.path === './tsconfig.spec.json')) {
|
|
162
|
+
references.push({ path: './tsconfig.spec.json' });
|
|
163
|
+
}
|
|
164
|
+
return { ...config, references };
|
|
165
|
+
});
|
|
166
|
+
updateJson(tree, joinPathFragments(root, 'tsconfig.lib.json'), (config) => {
|
|
167
|
+
const exclude = config.exclude ?? [];
|
|
168
|
+
if (!exclude.includes('src/**/*.test.ts')) exclude.push('src/**/*.test.ts');
|
|
169
|
+
return { ...config, exclude };
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Lets the library's source import as its test, the template and the documentation do, with
|
|
175
|
+
* `.ts`: `allowImportingTsExtensions` in `tsconfig.lib.json`, and `src/index.ts` written that way
|
|
176
|
+
* in place of the `.js` `@nx/js` gives it.
|
|
177
|
+
*
|
|
178
|
+
* TypeScript takes the option only where no JavaScript is emitted, which is the TypeScript
|
|
179
|
+
* preset's own setting (`emitDeclarationOnly`, which `@nx/js` writes into `tsconfig.lib.json`). A
|
|
180
|
+
* workspace that has turned that off keeps `.js`.
|
|
181
|
+
*/
|
|
182
|
+
function importWithTsExtensions(tree, root) {
|
|
183
|
+
const config = joinPathFragments(root, 'tsconfig.lib.json');
|
|
184
|
+
if (!emitsDeclarationsOnly(tree, config)) return;
|
|
185
|
+
updateJson(tree, config, (lib) => ({
|
|
186
|
+
...lib,
|
|
187
|
+
compilerOptions: { ...lib.compilerOptions, allowImportingTsExtensions: true },
|
|
188
|
+
}));
|
|
189
|
+
const index = joinPathFragments(root, 'src', 'index.ts');
|
|
190
|
+
if (!tree.exists(index)) return;
|
|
191
|
+
const source = tree.read(index, 'utf-8');
|
|
192
|
+
tree.write(index, source.replace(/(from\s+['"]\.{1,2}\/[^'"]*)\.js(['"])/g, '$1.ts$2'));
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/** The config `nx typecheck` gives `ngc` for a library, beside the one it is built with. */
|
|
196
|
+
const TYPECHECK_CONFIG = 'tsconfig.typecheck.json';
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* A config `ngc` can check the library's templates with, as an app's `typecheck` does. `@nx/js`
|
|
200
|
+
* infers a `typecheck` that runs `tsc`, which reads no template: a misspelled input passes.
|
|
201
|
+
*
|
|
202
|
+
* `tsconfig.lib.json` itself will not do: `ngc` refuses `emitDeclarationOnly`, and a project that
|
|
203
|
+
* is `composite` has to emit. The Angular options are the generated app's: a native view has no
|
|
204
|
+
* DOM to check a host binding or an event against.
|
|
205
|
+
*/
|
|
206
|
+
function writeTypecheckConfig(tree, root) {
|
|
207
|
+
writeJson(tree, joinPathFragments(root, TYPECHECK_CONFIG), {
|
|
208
|
+
extends: './tsconfig.lib.json',
|
|
209
|
+
compilerOptions: { noEmit: true, composite: false, emitDeclarationOnly: false },
|
|
210
|
+
angularCompilerOptions: {
|
|
211
|
+
strictTemplates: true,
|
|
212
|
+
typeCheckHostBindings: false,
|
|
213
|
+
strictDomEventTypes: false,
|
|
214
|
+
},
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/** `nx typecheck <library>`: `ngc`, in place of the `tsc` `@nx/js` infers. */
|
|
219
|
+
function typecheckTarget(root) {
|
|
220
|
+
return {
|
|
221
|
+
executor: 'nx:run-commands',
|
|
222
|
+
options: { cwd: root, command: `ngc -p ${TYPECHECK_CONFIG}` },
|
|
223
|
+
cache: true,
|
|
224
|
+
inputs: ['default', '^production'],
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/** Whether a tsconfig emits declarations and no JavaScript, once what it extends is merged in. */
|
|
229
|
+
function emitsDeclarationsOnly(tree, file) {
|
|
230
|
+
const { noEmit, emitDeclarationOnly } = emitOptions(tree, file, new Set());
|
|
231
|
+
return noEmit === true || emitDeclarationOnly === true;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* `noEmit` and `emitDeclarationOnly` as the compiler reads them: each from the nearest config that
|
|
236
|
+
* sets it, and a later entry of an `extends` list over an earlier one.
|
|
237
|
+
*/
|
|
238
|
+
function emitOptions(tree, file, seen) {
|
|
239
|
+
if (seen.has(file) || !tree.exists(file)) return {};
|
|
240
|
+
// The configs on the way here, to stop at a cycle. Not every config read: two entries of a list
|
|
241
|
+
// may share an ancestor, and each is read whole.
|
|
242
|
+
const above = new Set(seen).add(file);
|
|
243
|
+
const { compilerOptions = {}, extends: base = [] } = readJson(tree, file);
|
|
244
|
+
// ponytail: a config that comes from a package is not followed, so a library under one keeps
|
|
245
|
+
// `.js`. Resolve the specifier from the config's directory if a workspace needs it.
|
|
246
|
+
const inherited = [base]
|
|
247
|
+
.flat()
|
|
248
|
+
.filter((from) => typeof from === 'string' && from.startsWith('.'))
|
|
249
|
+
.map((from) => joinPathFragments(path.dirname(file), from))
|
|
250
|
+
.map((from) => emitOptions(tree, from.endsWith('.json') ? from : `${from}.json`, above));
|
|
251
|
+
const { noEmit, emitDeclarationOnly } = compilerOptions;
|
|
252
|
+
return Object.assign(
|
|
253
|
+
{},
|
|
254
|
+
...inherited,
|
|
255
|
+
noEmit === undefined ? {} : { noEmit },
|
|
256
|
+
emitDeclarationOnly === undefined ? {} : { emitDeclarationOnly },
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* The packages the component and its test import: in the library's own `package.json` when it is
|
|
262
|
+
* a workspace package, which pnpm links from, and at the root otherwise. A version already there
|
|
263
|
+
* is left alone.
|
|
264
|
+
*/
|
|
265
|
+
async function addImports(tree, root, alsoDev = {}) {
|
|
266
|
+
const devDependencies = { ...imports.devDependencies, ...alsoDev };
|
|
267
|
+
const manifest = joinPathFragments(root, 'package.json');
|
|
268
|
+
const rootManifest = readJson(tree, 'package.json');
|
|
269
|
+
if (tree.exists(manifest)) {
|
|
270
|
+
const own = async (wanted) => asSaved(tree, native.reuseRootRanges(wanted, rootManifest));
|
|
271
|
+
return addDependenciesToPackageJson(
|
|
272
|
+
tree,
|
|
273
|
+
await own(imports.dependencies),
|
|
274
|
+
await own(devDependencies),
|
|
275
|
+
manifest,
|
|
276
|
+
true,
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
const existing = Object.keys({ ...rootManifest.dependencies, ...rootManifest.devDependencies });
|
|
280
|
+
return addDependenciesToPackageJson(
|
|
281
|
+
tree,
|
|
282
|
+
await asSaved(tree, imports.dependencies, existing),
|
|
283
|
+
await asSaved(tree, devDependencies, existing),
|
|
284
|
+
'package.json',
|
|
285
|
+
true,
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* @param {import('@nx/devkit').Tree} tree
|
|
291
|
+
* @param {{ directory: string, name?: string, tags?: string, skipInstall?: boolean, skipFormat?: boolean }} options
|
|
292
|
+
*/
|
|
293
|
+
async function library(tree, options) {
|
|
294
|
+
const directory = path.normalize(options.directory).replace(/\/$/, '');
|
|
295
|
+
const { dependencies, devDependencies } = readJson(tree, 'package.json');
|
|
296
|
+
const angular = Boolean({ ...dependencies, ...devDependencies }['@nx/angular']);
|
|
297
|
+
const shared = { directory, name: options.name, tags: options.tags, unitTestRunner: 'none' };
|
|
298
|
+
if (angular) await bases.angular(tree, { ...shared, skipFormat: true });
|
|
299
|
+
else await bases.js(tree, { ...shared, bundler: 'none', skipFormat: true });
|
|
300
|
+
|
|
301
|
+
const { name, project } = projectAt(tree, directory);
|
|
302
|
+
const file = names(options.name ?? path.basename(directory)).fileName;
|
|
303
|
+
replaceComponent(tree, project, file);
|
|
304
|
+
|
|
305
|
+
const aliases = hasPathAliases(tree, usesWorkspaces(tree));
|
|
306
|
+
tree.write(joinPathFragments(directory, 'vitest.config.mts'), native.vitestConfig(aliases));
|
|
307
|
+
writeSpecConfig(tree, directory, angular);
|
|
308
|
+
if (!angular) importWithTsExtensions(tree, directory);
|
|
309
|
+
if (!angular) writeTypecheckConfig(tree, directory);
|
|
310
|
+
updateProjectConfiguration(tree, name, {
|
|
311
|
+
...project,
|
|
312
|
+
targets: {
|
|
313
|
+
...project.targets,
|
|
314
|
+
...(angular ? {} : { typecheck: typecheckTarget(directory) }),
|
|
315
|
+
test: {
|
|
316
|
+
executor: 'nx:run-commands',
|
|
317
|
+
options: { cwd: directory, command: 'vitest run' },
|
|
318
|
+
cache: true,
|
|
319
|
+
inputs: ['default', '^production'],
|
|
320
|
+
},
|
|
321
|
+
},
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
await addImports(tree, directory, angular ? {} : typecheckDependencies);
|
|
325
|
+
// `nxViteTsPaths()`, which the Vitest config uses to reach the workspace's other libraries.
|
|
326
|
+
if (aliases) {
|
|
327
|
+
const vite = { '@nx/vite': workspaceNxVersion(tree) };
|
|
328
|
+
addDependenciesToPackageJson(tree, {}, vite, 'package.json', true);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
if (!options.skipFormat) await formatFiles(tree);
|
|
332
|
+
if (options.skipInstall) return () => {};
|
|
333
|
+
return () => installPackagesTask(tree, true);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
module.exports = { library, bases, generatorDefaults };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/schema",
|
|
3
|
+
"$id": "NgNativeNxLibrary",
|
|
4
|
+
"title": "Angular Native library",
|
|
5
|
+
"description": "A library of native components, whose tests render on the fake Fabric as an app's do.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"directory": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"description": "Where the library goes, relative to the workspace root: packages/ui.",
|
|
11
|
+
"$default": { "$source": "argv", "index": 0 },
|
|
12
|
+
"x-prompt": "Which directory should the library be created in?"
|
|
13
|
+
},
|
|
14
|
+
"name": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"description": "The project name. Defaults to the directory's last segment.",
|
|
17
|
+
"pattern": "^[a-z][a-z0-9-]*$"
|
|
18
|
+
},
|
|
19
|
+
"tags": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"description": "Comma-separated tags for the project."
|
|
22
|
+
},
|
|
23
|
+
"skipInstall": {
|
|
24
|
+
"type": "boolean",
|
|
25
|
+
"description": "Write the files without installing.",
|
|
26
|
+
"default": false
|
|
27
|
+
},
|
|
28
|
+
"skipFormat": {
|
|
29
|
+
"type": "boolean",
|
|
30
|
+
"description": "Leave the generated files unformatted.",
|
|
31
|
+
"default": false,
|
|
32
|
+
"x-priority": "internal"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"required": ["directory"]
|
|
36
|
+
}
|
package/migrations.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"generators": {
|
|
3
|
+
"sync-app-versions": {
|
|
4
|
+
"version": "0.4.0",
|
|
5
|
+
"description": "Move the @ng-native packages each project's own package.json lists to the new version.",
|
|
6
|
+
"implementation": "./migrations/run.cjs#sync-app-versions"
|
|
7
|
+
},
|
|
8
|
+
"split-store-and-player": {
|
|
9
|
+
"version": "0.3.0",
|
|
10
|
+
"description": "Import Storage, SecureStorage, audioPlayer and videoPlayer from the entry points that now hold them.",
|
|
11
|
+
"implementation": "./migrations/run.cjs#split-store-and-player"
|
|
12
|
+
},
|
|
13
|
+
"tracking-available-getter": {
|
|
14
|
+
"version": "0.3.0",
|
|
15
|
+
"description": "Read Tracking's available as a property rather than calling it.",
|
|
16
|
+
"implementation": "./migrations/run.cjs#tracking-available-getter"
|
|
17
|
+
},
|
|
18
|
+
"device-react-native-import": {
|
|
19
|
+
"version": "0.3.0",
|
|
20
|
+
"description": "Note each import of reactNative or ReactNative from @ng-native/device, which no longer exports them.",
|
|
21
|
+
"implementation": "./migrations/run.cjs#device-react-native-import"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|