@blotch/angular-lynx 22.2.1 → 22.2.2

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.
@@ -0,0 +1,472 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const schematics_1 = require("@angular-devkit/schematics");
4
+ const dependency_1 = require("@schematics/angular/utility/dependency");
5
+ const json_file_1 = require("@schematics/angular/utility/json-file");
6
+ const workspace_1 = require("@schematics/angular/utility/workspace");
7
+ const versions_1 = require("./versions");
8
+ /**
9
+ * Transforms a standard `ng new` Angular project into a Lynx-native application.
10
+ * The schematic replaces browser-specific bootstrap (main.ts, app.config.ts,
11
+ * app.component.ts) with Lynx equivalents, points `ng build`, `ng serve` and
12
+ * `ng test` at the AngularLynx builders and `ng generate` at its schematics,
13
+ * and optionally sets up Tailwind with the Lynx preset. Everything else stays
14
+ * as `ng new` left it: the app needs no build config besides angular.json.
15
+ * This is a one-shot destructive transform — the old browser-Angular files
16
+ * are deleted because they reference DOM APIs and HTML elements that don't
17
+ * exist on the Lynx runtime.
18
+ */
19
+ exports.default = (options) => async (tree) => {
20
+ const workspace = await (0, workspace_1.getWorkspace)(tree);
21
+ const projectName = options.project ??
22
+ workspace.extensions['defaultProject'] ??
23
+ [...workspace.projects.keys()][0];
24
+ if (!projectName) {
25
+ throw new schematics_1.SchematicsException('No project found. Run this schematic inside an Angular workspace.');
26
+ }
27
+ const project = workspace.projects.get(projectName);
28
+ if (!project) {
29
+ throw new schematics_1.SchematicsException(`Project "${projectName}" not found in angular.json.`);
30
+ }
31
+ const sourceRoot = (project.sourceRoot ?? `${project.root}/src`);
32
+ const projectRoot = project.root;
33
+ const prefix = project.extensions['prefix'] ?? 'app';
34
+ // The tsconfig the app is built with. `ng new` points the build target's
35
+ // `tsConfig` at tsconfig.app.json.
36
+ const buildTsConfig = project.targets.get('build')?.options?.['tsConfig'];
37
+ const appTsconfig = typeof buildTsConfig === 'string'
38
+ ? buildTsConfig
39
+ : `${projectRoot ? projectRoot + '/' : ''}tsconfig.app.json`;
40
+ const rules = [
41
+ addTemplateFiles(projectRoot, sourceRoot),
42
+ replaceMainTs(sourceRoot),
43
+ replaceAppConfig(sourceRoot),
44
+ replaceApp(sourceRoot, prefix, projectName),
45
+ deleteOldAppFiles(sourceRoot),
46
+ excludeTestFilesFromAppBuild(appTsconfig),
47
+ includeTestFilesInSpecTsconfig(`${projectRoot ? projectRoot + '/' : ''}tsconfig.spec.json`),
48
+ useLynxBuilders(projectName),
49
+ useLynxSchematics(),
50
+ updatePackageScripts(),
51
+ addCoreDependencies(),
52
+ ];
53
+ // `"false"` is how `ng add ... --tailwind=false` arrives (see schema.ts).
54
+ if (options.tailwind !== false && options.tailwind !== 'false') {
55
+ rules.push(addTailwindConfig(projectRoot), updateStylesCss(sourceRoot), addTailwindDependencies());
56
+ }
57
+ return (0, schematics_1.chain)(rules);
58
+ };
59
+ const addTemplateFiles = (projectRoot, _sourceRoot) => (0, schematics_1.mergeWith)(
60
+ // MergeStrategy.Overwrite is deliberate — `ng add` is meant to be
61
+ // idempotent so re-running it should refresh the template files
62
+ // (src/rspeedy-env.d.ts) to the package's current version. Default merge
63
+ // strategy would error on file collisions.
64
+ (0, schematics_1.apply)((0, schematics_1.url)('../files'), [(0, schematics_1.applyTemplates)({}), (0, schematics_1.move)(projectRoot || '/')]), schematics_1.MergeStrategy.Overwrite);
65
+ const replaceMainTs = (sourceRoot) => {
66
+ return (tree) => {
67
+ // `ng new` generates a main.ts that calls bootstrapApplication from
68
+ // @angular/platform-browser. That platform implementation reaches into
69
+ // browser globals (document, history, navigator) which don't exist on
70
+ // Lynx, so we replace the bootstrap entrypoint with the AngularLynx
71
+ // equivalent that wires the Lynx renderer instead.
72
+ const mainPath = `${sourceRoot}/main.ts`;
73
+ const content = `import { bootstrapApplication } from '@blotch/angular-lynx';
74
+ import { App } from './app/app';
75
+ import { appConfig } from './app/app.config';
76
+
77
+ bootstrapApplication(App, appConfig);
78
+ `;
79
+ tree.overwrite(mainPath, content);
80
+ };
81
+ };
82
+ const replaceAppConfig = (sourceRoot) => {
83
+ return (tree) => {
84
+ // Two providers are required for any AngularLynx app:
85
+ // 1. provideZonelessChangeDetection() — Lynx doesn't carry zone.js, so
86
+ // Angular must run in zoneless mode (signals + manual change detection
87
+ // triggers are the only reactivity path).
88
+ // 2. provideRenderer() — registers the Lynx RendererFactory2 over
89
+ // Angular's default DOM renderer so element creation calls go to
90
+ // __CreateElement/__SetAttribute instead of document.createElement.
91
+ // provideRouter is included by default so the generated App has a working
92
+ // <router-outlet> for the user to hang their routes off.
93
+ const configPath = `${sourceRoot}/app/app.config.ts`;
94
+ const content = `import {
95
+ type ApplicationConfig,
96
+ provideZonelessChangeDetection,
97
+ } from '@angular/core';
98
+ import { provideRenderer, provideRouter } from '@blotch/angular-lynx';
99
+
100
+ import { routes } from './app.routes';
101
+
102
+ export const appConfig: ApplicationConfig = {
103
+ providers: [
104
+ provideZonelessChangeDetection(),
105
+ provideRenderer(),
106
+ provideRouter(routes),
107
+ ],
108
+ };
109
+ `;
110
+ tree.overwrite(configPath, content);
111
+ };
112
+ };
113
+ const replaceApp = (sourceRoot, prefix, projectName) => {
114
+ return (tree) => {
115
+ // `ng new` before Angular 20 generated app.component.ts — delete it and
116
+ // create app.ts. The Angular 2025 style guide drops the `.component`
117
+ // suffix, and AngularLynx's component schematic follows the same
118
+ // convention so the bootstrap component should too.
119
+ const oldPath = `${sourceRoot}/app/app.component.ts`;
120
+ if (tree.exists(oldPath)) {
121
+ tree.delete(oldPath);
122
+ }
123
+ // LYNX_ELEMENTS is the directive bundle that registers <view>, <text>,
124
+ // <scroll-view>, etc. as Angular elements. Without it, the template would
125
+ // fail compilation because those tags aren't known HTML elements and the
126
+ // user hasn't yet added CUSTOM_ELEMENTS_SCHEMA (the build plugin injects
127
+ // it automatically but the type-checker still surfaces template errors).
128
+ const newPath = `${sourceRoot}/app/app.ts`;
129
+ const content = `import { Component, signal } from '@angular/core';
130
+ import { RouterOutlet } from '@angular/router';
131
+ import { LYNX_ELEMENTS } from '@blotch/angular-lynx';
132
+
133
+ @Component({
134
+ selector: '${prefix}-root',
135
+ imports: [RouterOutlet, LYNX_ELEMENTS],
136
+ template: \`
137
+ <scroll-view scroll-orientation="vertical">
138
+ <view style="padding: 24px; align-items: center;">
139
+ <text style="font-size: 24px; font-weight: bold;">{{ title() }}</text>
140
+ <text style="font-size: 14px; margin-top: 8px; color: #666;">
141
+ Edit src/app/app.ts to get started
142
+ </text>
143
+ <router-outlet />
144
+ </view>
145
+ </scroll-view>
146
+ \`,
147
+ })
148
+ export class App {
149
+ title = signal('${projectName}');
150
+ }
151
+ `;
152
+ if (tree.exists(newPath)) {
153
+ tree.overwrite(newPath, content);
154
+ }
155
+ else {
156
+ tree.create(newPath, content);
157
+ }
158
+ };
159
+ };
160
+ const deleteOldAppFiles = (sourceRoot) => {
161
+ return (tree) => {
162
+ // Remove files generated by `ng new` that we don't need.
163
+ // The root component's template and styles are dead once we inline the
164
+ // template above, and its spec tests the browser template we replaced, so
165
+ // it would fail if left behind. Angular 20+ names them app.html, app.css
166
+ // and app.spec.ts; earlier versions used an `app.component.` prefix. We
167
+ // don't try to migrate the user's existing template/styles because this
168
+ // schematic is intended for fresh `ng new` projects — running it on an
169
+ // established app is unsupported.
170
+ for (const file of [
171
+ `${sourceRoot}/app/app.html`,
172
+ `${sourceRoot}/app/app.spec.ts`,
173
+ `${sourceRoot}/app/app.css`,
174
+ `${sourceRoot}/app/app.scss`,
175
+ `${sourceRoot}/app/app.component.html`,
176
+ `${sourceRoot}/app/app.component.spec.ts`,
177
+ `${sourceRoot}/app/app.component.css`,
178
+ `${sourceRoot}/app/app.component.scss`,
179
+ ]) {
180
+ if (tree.exists(file)) {
181
+ tree.delete(file);
182
+ }
183
+ }
184
+ };
185
+ };
186
+ const excludeTestFilesFromAppBuild = (tsconfigPath) => {
187
+ return (tree) => {
188
+ // `ng new` excludes `*.spec.ts` from the app build, but AngularLynx's
189
+ // component and add-testing schematics name tests `*.test.ts`. Left
190
+ // in, the Rsbuild plugin compiles every test file into the app, and a
191
+ // test importing the testing library (a devDependency the app bundle
192
+ // can't resolve) produces build errors.
193
+ if (!tree.exists(tsconfigPath)) {
194
+ return;
195
+ }
196
+ const tsconfig = new json_file_1.JSONFile(tree, tsconfigPath);
197
+ const exclude = tsconfig.get(['exclude']);
198
+ const patterns = Array.isArray(exclude) ? exclude : [];
199
+ if (!patterns.includes('src/**/*.test.ts')) {
200
+ tsconfig.modify(['exclude'], [...patterns, 'src/**/*.test.ts']);
201
+ }
202
+ };
203
+ };
204
+ const includeTestFilesInSpecTsconfig = (tsconfigPath) => {
205
+ return (tree) => {
206
+ // `ng test` compiles `*.test.ts` files alongside `ng new`'s `*.spec.ts`
207
+ // ones, and AngularLynx's schematics name tests `*.test.ts`. Listed in
208
+ // tsconfig.spec.json, editors type-check them with the test types
209
+ // (vitest/globals) instead of treating them as files of no project.
210
+ if (!tree.exists(tsconfigPath)) {
211
+ return;
212
+ }
213
+ const tsconfig = new json_file_1.JSONFile(tree, tsconfigPath);
214
+ const include = tsconfig.get(['include']);
215
+ if (Array.isArray(include) && !include.includes('src/**/*.test.ts')) {
216
+ tsconfig.modify(['include'], [...include, 'src/**/*.test.ts']);
217
+ }
218
+ };
219
+ };
220
+ /**
221
+ * Angular compiler options from `ng new`'s build target that the Lynx builder
222
+ * accepts (see @blotch/angular-lynx-build's builders/application/schema.json).
223
+ * @blotch/rsbuild-plugin-angular-lynx and `ng test` read them from
224
+ * angular.json; anything else, such as options only the browser builder
225
+ * knows, would fail the builder's option validation. `optimization` also picks
226
+ * the bundle's production or development mode.
227
+ */
228
+ const ANGULAR_BUILD_OPTIONS = new Set([
229
+ 'browser',
230
+ 'tsConfig',
231
+ 'polyfills',
232
+ 'styles',
233
+ 'assets',
234
+ 'scripts',
235
+ 'inlineStyleLanguage',
236
+ 'fileReplacements',
237
+ 'aot',
238
+ 'optimization',
239
+ 'sourceMap',
240
+ 'outputHashing',
241
+ 'i18nMissingTranslation',
242
+ 'budgets',
243
+ 'extractLicenses',
244
+ 'outputPath',
245
+ 'index',
246
+ ]);
247
+ const keepAngularOptions = (options) => Object.fromEntries(Object.entries(options ?? {}).filter(([key]) => ANGULAR_BUILD_OPTIONS.has(key)));
248
+ /**
249
+ * Options of Angular's dev server that the Lynx dev server accepts too (see
250
+ * @blotch/angular-lynx-build's builders/dev-server/schema.json).
251
+ */
252
+ const DEV_SERVER_OPTIONS = new Set(['buildTarget', 'port', 'host']);
253
+ const keepDevServerOptions = (options) => Object.fromEntries(Object.entries(options ?? {}).filter(([key]) => DEV_SERVER_OPTIONS.has(key)));
254
+ /**
255
+ * `ng new`'s initial-bundle budget, sized for a web app's first download.
256
+ */
257
+ const NG_NEW_INITIAL_BUDGET = { maximumWarning: '500kB', maximumError: '1MB' };
258
+ /**
259
+ * The initial-bundle budget for a Lynx bundle. It carries more than a web
260
+ * app's first download: Angular runs on both of Lynx's threads, so the
261
+ * framework is in it twice, and a new app's bundle is already about 1 MB.
262
+ * Kept at roughly the same multiples of a new app as Angular's budget.
263
+ */
264
+ const LYNX_INITIAL_BUDGET = { maximumWarning: '2MB', maximumError: '5MB' };
265
+ /**
266
+ * A configuration's options with `ng new`'s initial-bundle budget resized for
267
+ * a Lynx bundle. Budgets the user set differently stay as they are.
268
+ */
269
+ const withLynxBudgets = (options) => {
270
+ if (!Array.isArray(options['budgets'])) {
271
+ return options;
272
+ }
273
+ return {
274
+ ...options,
275
+ budgets: options['budgets'].map((budget) => budget['type'] === 'initial' &&
276
+ budget['maximumWarning'] === NG_NEW_INITIAL_BUDGET.maximumWarning &&
277
+ budget['maximumError'] === NG_NEW_INITIAL_BUDGET.maximumError
278
+ ? { ...budget, ...LYNX_INITIAL_BUDGET }
279
+ : budget),
280
+ };
281
+ };
282
+ /**
283
+ * Points `ng build`, `ng serve` and `ng test` at the AngularLynx builders.
284
+ * The first two run rspeedy with @blotch/rsbuild-plugin-angular-lynx added,
285
+ * and `ng build --platform ios|android` also produces the native app; the
286
+ * third runs Angular's unit-test builder set up for Lynx. The build target
287
+ * keeps `ng new`'s Angular compiler options, which the build plugin and
288
+ * `ng test` read, and gains the app's identity for native builds.
289
+ */
290
+ const useLynxBuilders = (projectName) => (0, workspace_1.updateWorkspace)((workspace) => {
291
+ const project = workspace.projects.get(projectName);
292
+ const build = project.targets.get('build');
293
+ const configurations = Object.fromEntries(Object.entries(build?.configurations ?? {}).map(([name, options]) => [
294
+ name,
295
+ withLynxBudgets(keepAngularOptions(options)),
296
+ ]));
297
+ const buildDefinition = {
298
+ builder: '@blotch/angular-lynx-build:application',
299
+ options: {
300
+ ...keepAngularOptions(build?.options),
301
+ appName: projectName,
302
+ // A placeholder the user replaces before publishing: the stores
303
+ // identify the app by it, and it can't change after the first upload.
304
+ appId: `com.example.${projectName.toLowerCase().replace(/[^a-z0-9]/g, '') || 'app'}`,
305
+ },
306
+ configurations,
307
+ defaultConfiguration: build?.defaultConfiguration ?? 'production',
308
+ };
309
+ if (build) {
310
+ project.targets.delete('build');
311
+ }
312
+ project.targets.add({ name: 'build', ...buildDefinition });
313
+ // The Lynx dev server takes `buildTarget` like Angular's, so `ng new`'s
314
+ // configurations (production and development, each naming its build
315
+ // configuration) carry over, and `ng serve -c production` keeps working.
316
+ // Options only the browser dev server knows (ssl, proxyConfig, ...) are
317
+ // dropped: they would fail the builder's option validation.
318
+ // Without a serve target to keep, write the one `ng new` would have, for
319
+ // the build configurations that exist. Without a development one, serve
320
+ // the build target's default configuration rather than the dev server's
321
+ // default (`::development`), which would point at nothing.
322
+ const serve = project.targets.get('serve');
323
+ const serveConfigurations = Object.fromEntries(Object.entries(serve?.configurations ??
324
+ Object.fromEntries(['production', 'development']
325
+ .filter((name) => name in configurations)
326
+ .map((name) => [
327
+ name,
328
+ { buildTarget: `${projectName}:build:${name}` },
329
+ ]))).map(([name, options]) => [name, keepDevServerOptions(options)]));
330
+ const serveDefinition = serve
331
+ ? {
332
+ builder: '@blotch/angular-lynx-build:dev-server',
333
+ options: keepDevServerOptions(serve.options),
334
+ configurations: serveConfigurations,
335
+ defaultConfiguration: serve.defaultConfiguration,
336
+ }
337
+ : {
338
+ builder: '@blotch/angular-lynx-build:dev-server',
339
+ options: 'development' in serveConfigurations
340
+ ? {}
341
+ : { buildTarget: `${projectName}:build` },
342
+ configurations: serveConfigurations,
343
+ defaultConfiguration: 'development' in serveConfigurations ? 'development' : undefined,
344
+ };
345
+ if (serve) {
346
+ project.targets.delete('serve');
347
+ }
348
+ project.targets.add({ name: 'serve', ...serveDefinition });
349
+ // The Lynx unit-test builder is Angular's, set up for Lynx, so it takes
350
+ // the same options and `ng new`'s carry over (as do its own, when `ng add`
351
+ // runs again). Any other test builder (Karma, from older `ng new`
352
+ // versions) can't run Lynx code; its options don't apply.
353
+ const test = project.targets.get('test');
354
+ const keepTest = test?.builder === '@angular/build:unit-test' ||
355
+ test?.builder === '@blotch/angular-lynx-build:unit-test';
356
+ if (test) {
357
+ project.targets.delete('test');
358
+ }
359
+ project.targets.add({
360
+ name: 'test',
361
+ builder: '@blotch/angular-lynx-build:unit-test',
362
+ ...(keepTest && {
363
+ options: test.options,
364
+ configurations: test.configurations,
365
+ defaultConfiguration: test.defaultConfiguration,
366
+ }),
367
+ });
368
+ });
369
+ /**
370
+ * Makes `ng generate` reach AngularLynx's schematics first, so
371
+ * `ng generate component` makes a component with Lynx elements. Angular's own
372
+ * collection stays after it: AngularLynx only has the schematics that differ
373
+ * on Lynx, and `ng generate service`, `pipe`, `guard` and the rest come from
374
+ * Angular's as before.
375
+ */
376
+ const useLynxSchematics = () => (0, workspace_1.updateWorkspace)((workspace) => {
377
+ const cli = (workspace.extensions['cli'] ?? {});
378
+ const collections = Array.isArray(cli['schematicCollections'])
379
+ ? cli['schematicCollections']
380
+ : // What Angular CLI uses when the list isn't set.
381
+ ['@schematics/angular'];
382
+ workspace.extensions['cli'] = {
383
+ ...cli,
384
+ schematicCollections: [
385
+ '@blotch/angular-lynx',
386
+ ...collections.filter((collection) => collection !== '@blotch/angular-lynx'),
387
+ ],
388
+ };
389
+ });
390
+ const updatePackageScripts = () => {
391
+ return (tree) => {
392
+ // `npm start` and `npm run build` go through the Angular CLI, which runs
393
+ // the AngularLynx builders set up by useLynxBuilders. `ng new` already
394
+ // writes these (and `npm test` as `ng test`); this keeps them for
395
+ // projects whose scripts called rspeedy directly.
396
+ const pkg = new json_file_1.JSONFile(tree, '/package.json');
397
+ pkg.modify(['scripts', 'start'], 'ng serve');
398
+ pkg.modify(['scripts', 'build'], 'ng build');
399
+ };
400
+ };
401
+ const addCoreDependencies = () => {
402
+ return (0, schematics_1.chain)([
403
+ // The `ng build`, `ng serve` and `ng test` builders, the one build
404
+ // dependency an AngularLynx app needs, as `@angular/build` is for a web
405
+ // app. They bring rspeedy, the rsbuild plugin that compiles Angular, the
406
+ // QR code plugin and the iOS and Android app builder with them. Taken at
407
+ // this package's own release, which they were tested with.
408
+ (0, dependency_1.addDependency)('@blotch/angular-lynx-build', (0, versions_1.ownVersionRange)(), {
409
+ type: dependency_1.DependencyType.Dev,
410
+ install: dependency_1.InstallBehavior.Auto,
411
+ }),
412
+ (0, dependency_1.addDependency)('@lynx-js/types', versions_1.VERSIONS.lynxTypes, {
413
+ type: dependency_1.DependencyType.Dev,
414
+ install: dependency_1.InstallBehavior.Auto,
415
+ }),
416
+ ]);
417
+ };
418
+ const addTailwindConfig = (projectRoot) => {
419
+ return (tree) => {
420
+ const configPath = `${projectRoot ? projectRoot + '/' : ''}tailwind.config.ts`;
421
+ const content = `import type { Config } from 'tailwindcss';
422
+ import preset from '@lynx-js/tailwind-preset';
423
+
424
+ const config: Config = {
425
+ content: ['./src/**/*.ts'],
426
+ presets: [preset],
427
+ };
428
+
429
+ export default config;
430
+ `;
431
+ if (tree.exists(configPath)) {
432
+ tree.overwrite(configPath, content);
433
+ }
434
+ else {
435
+ tree.create(configPath, content);
436
+ }
437
+ };
438
+ };
439
+ const updateStylesCss = (sourceRoot) => {
440
+ return (tree) => {
441
+ const cssPath = `${sourceRoot}/styles.css`;
442
+ const scssPath = `${sourceRoot}/styles.scss`;
443
+ const targetPath = tree.exists(scssPath) ? scssPath : cssPath;
444
+ // Only @tailwind base + utilities — no @tailwind components. Lynx doesn't
445
+ // support all of Tailwind's component-layer reset rules (e.g. button
446
+ // resets that reference focus-visible, form input pseudo-classes), and
447
+ // bundling them in would generate CSS the runtime can't parse, producing
448
+ // diagnostic noise. The base layer ships with @lynx-js/tailwind-preset's
449
+ // own Lynx-compatible normalize rules.
450
+ const content = `@tailwind base;
451
+ @tailwind utilities;
452
+ `;
453
+ if (tree.exists(targetPath)) {
454
+ tree.overwrite(targetPath, content);
455
+ }
456
+ else {
457
+ tree.create(cssPath, content);
458
+ }
459
+ };
460
+ };
461
+ const addTailwindDependencies = () => {
462
+ return (0, schematics_1.chain)([
463
+ (0, dependency_1.addDependency)('tailwindcss', versions_1.VERSIONS.tailwindcss, {
464
+ type: dependency_1.DependencyType.Dev,
465
+ install: dependency_1.InstallBehavior.Auto,
466
+ }),
467
+ (0, dependency_1.addDependency)('@lynx-js/tailwind-preset', versions_1.VERSIONS.tailwindPreset, {
468
+ type: dependency_1.DependencyType.Dev,
469
+ install: dependency_1.InstallBehavior.Auto,
470
+ }),
471
+ ]);
472
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -14,10 +14,14 @@
14
14
  }
15
15
  },
16
16
  "tailwind": {
17
- "type": "boolean",
17
+ "type": ["boolean", "string"],
18
+ "pattern": "^(true|false)$",
18
19
  "description": "Whether to add Tailwind CSS with @lynx-js/tailwind-preset.",
19
20
  "default": true,
20
- "x-prompt": "Would you like to add Tailwind CSS with Lynx preset?"
21
+ "x-prompt": {
22
+ "message": "Would you like to add Tailwind CSS with Lynx preset?",
23
+ "type": "confirmation"
24
+ }
21
25
  }
22
26
  },
23
27
  "required": []
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ownVersionRange = exports.VERSIONS = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const node_fs_1 = require("node:fs");
6
+ const node_path_1 = tslib_1.__importDefault(require("node:path"));
7
+ /**
8
+ * Versions of the third-party packages the `ng add @blotch/angular-lynx`
9
+ * schematics install: the ones AngularLynx is tested with.
10
+ *
11
+ * Keep this map in sync when upgrading any Lynx or build-tooling dependency.
12
+ * It lists none of our own packages or Angular's: those come from
13
+ * {@link ownVersionRange} and the app's own `@angular/core`, so they can't go
14
+ * stale.
15
+ */
16
+ exports.VERSIONS = {
17
+ /**
18
+ * @lynx-js/types — TypeScript type definitions for the Lynx runtime APIs
19
+ */
20
+ lynxTypes: '^4.3.0',
21
+ /**
22
+ * tailwindcss — utility-first CSS framework (optional, controlled by the `tailwind` schema option)
23
+ */
24
+ tailwindcss: '^3.4.19',
25
+ /**
26
+ * @lynx-js/tailwind-preset — Lynx-specific Tailwind preset with native design tokens
27
+ */
28
+ tailwindPreset: '^0.6.0',
29
+ /**
30
+ * vitest — fast unit test runner powered by Vite. Only added when the
31
+ * project has none; `ng new` already adds it.
32
+ */
33
+ vitest: '^5.0.0',
34
+ /**
35
+ * jsdom — DOM environment for running component tests. Only added when the
36
+ * project has none; `ng new` already adds it.
37
+ */
38
+ jsdom: '^30.0.0',
39
+ };
40
+ /**
41
+ * The range the schematics install our other packages at
42
+ * (@blotch/angular-lynx-build, the testing library): the version of
43
+ * @blotch/angular-lynx they shipped in. Every package is released at one
44
+ * version (see packages/release), so a range written out here would go stale
45
+ * at each release unless someone remembered to move it, as `^22.2.1` nearly
46
+ * shipped in 22.2.2. The E2E tests check that a new app gets this range.
47
+ *
48
+ * `../../package.json` is the runtime's package.json both in the repository
49
+ * and in the published package, where ng-packagr copies it into dist/ beside
50
+ * the schematics. (`../package.json` is schematics/package.json, which only
51
+ * marks the schematics as CommonJS.)
52
+ */
53
+ const ownVersionRange = () => {
54
+ const { version } = JSON.parse((0, node_fs_1.readFileSync)(node_path_1.default.join(__dirname, '../../package.json'), 'utf8'));
55
+ return `^${version}`;
56
+ };
57
+ exports.ownVersionRange = ownVersionRange;
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }