@tramvai/cli 2.98.2 → 2.101.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.
Files changed (74) hide show
  1. package/lib/api/start-prod/providers/application.js +2 -3
  2. package/lib/api/start-prod/providers/application.js.map +1 -1
  3. package/lib/builder/webpack/tokens.d.ts +3 -0
  4. package/lib/commands/analyze/command.js +7 -1
  5. package/lib/commands/analyze/command.js.map +1 -1
  6. package/lib/commands/build/command.js +2 -0
  7. package/lib/commands/build/command.js.map +1 -1
  8. package/lib/commands/start/command.js +2 -0
  9. package/lib/commands/start/command.js.map +1 -1
  10. package/lib/commands/start-prod/command.js +7 -1
  11. package/lib/commands/start-prod/command.js.map +1 -1
  12. package/lib/commands/static/application.js +1 -1
  13. package/lib/commands/static/application.js.map +1 -1
  14. package/lib/config/configManager.d.ts +1 -0
  15. package/lib/config/configManager.js +23 -1
  16. package/lib/config/configManager.js.map +1 -1
  17. package/lib/di/tokens/config.d.ts +1 -0
  18. package/lib/library/webpack/application/client/common.js +2 -0
  19. package/lib/library/webpack/application/client/common.js.map +1 -1
  20. package/lib/library/webpack/application/server/common.js +2 -0
  21. package/lib/library/webpack/application/server/common.js.map +1 -1
  22. package/lib/library/webpack/blocks/pwa/client.d.ts +4 -0
  23. package/lib/library/webpack/blocks/pwa/client.js +62 -0
  24. package/lib/library/webpack/blocks/pwa/client.js.map +1 -0
  25. package/lib/library/webpack/blocks/pwa/server.d.ts +4 -0
  26. package/lib/library/webpack/blocks/pwa/server.js +9 -0
  27. package/lib/library/webpack/blocks/pwa/server.js.map +1 -0
  28. package/lib/library/webpack/blocks/pwa/shared.d.ts +4 -0
  29. package/lib/library/webpack/blocks/pwa/shared.js +18 -0
  30. package/lib/library/webpack/blocks/pwa/shared.js.map +1 -0
  31. package/lib/library/webpack/plugins/PwaIconsPlugin.d.ts +9 -0
  32. package/lib/library/webpack/plugins/PwaIconsPlugin.js +78 -0
  33. package/lib/library/webpack/plugins/PwaIconsPlugin.js.map +1 -0
  34. package/lib/library/webpack/plugins/WebManifestPlugin.d.ts +8 -0
  35. package/lib/library/webpack/plugins/WebManifestPlugin.js +28 -0
  36. package/lib/library/webpack/plugins/WebManifestPlugin.js.map +1 -0
  37. package/lib/schema/autogeneratedSchema.json +183 -0
  38. package/lib/typings/configEntry/application.d.ts +54 -0
  39. package/lib/typings/public.d.ts +1 -0
  40. package/lib/typings/public.js +2 -0
  41. package/lib/typings/public.js.map +1 -1
  42. package/lib/typings/pwa/index.d.ts +59 -0
  43. package/lib/typings/pwa/index.js +3 -0
  44. package/lib/typings/pwa/index.js.map +1 -0
  45. package/lib/validators/commands/checkPwaDependencies.d.ts +2 -0
  46. package/lib/validators/commands/checkPwaDependencies.js +18 -0
  47. package/lib/validators/commands/checkPwaDependencies.js.map +1 -0
  48. package/package.json +15 -11
  49. package/schema.json +183 -0
  50. package/src/api/start-prod/providers/application.ts +3 -4
  51. package/src/commands/analyze/command.ts +7 -1
  52. package/src/commands/build/command.ts +2 -0
  53. package/src/commands/start/command.ts +2 -0
  54. package/src/commands/start-prod/command.ts +7 -1
  55. package/src/commands/static/application.ts +1 -4
  56. package/src/config/configManager.ts +37 -0
  57. package/src/library/webpack/application/client/common.ts +2 -0
  58. package/src/library/webpack/application/server/common.ts +2 -0
  59. package/src/library/webpack/blocks/pwa/client.ts +83 -0
  60. package/src/library/webpack/blocks/pwa/server.ts +9 -0
  61. package/src/library/webpack/blocks/pwa/shared.ts +26 -0
  62. package/src/library/webpack/plugins/PwaIconsPlugin.ts +87 -0
  63. package/src/library/webpack/plugins/WebManifestPlugin.ts +32 -0
  64. package/src/models/config.spec.ts +54 -0
  65. package/src/schema/autogeneratedSchema.json +183 -0
  66. package/src/schema/tramvai.spec.ts +27 -0
  67. package/src/typings/configEntry/application.ts +55 -0
  68. package/src/typings/public.ts +2 -0
  69. package/src/typings/pwa/index.ts +64 -0
  70. package/src/validators/commands/checkPwaDependencies.ts +17 -0
  71. package/lib/utils/webpackBuild.d.ts +0 -5
  72. package/lib/utils/webpackBuild.js +0 -32
  73. package/lib/utils/webpackBuild.js.map +0 -1
  74. package/src/utils/webpackBuild.ts +0 -38
@@ -41,6 +41,33 @@ it('should populate defaults for config', () => {
41
41
  "minicss": {
42
42
  "useImportModule": true,
43
43
  },
44
+ "pwa": {
45
+ "icon": {
46
+ "dest": "pwa-icons",
47
+ "sizes": [
48
+ 36,
49
+ 48,
50
+ 72,
51
+ 96,
52
+ 144,
53
+ 192,
54
+ 512,
55
+ ],
56
+ },
57
+ "meta": {},
58
+ "sw": {
59
+ "dest": "sw.js",
60
+ "scope": "/",
61
+ "src": "sw.ts",
62
+ },
63
+ "webmanifest": {
64
+ "dest": "/manifest.[hash].json",
65
+ "enabled": false,
66
+ },
67
+ "workbox": {
68
+ "enabled": false,
69
+ },
70
+ },
44
71
  "serverRunner": "process",
45
72
  "transpilation": {
46
73
  "loader": "babel",
@@ -242,6 +269,33 @@ it('should populate defaults for overridable options', () => {
242
269
  "minicss": {
243
270
  "useImportModule": true,
244
271
  },
272
+ "pwa": {
273
+ "icon": {
274
+ "dest": "pwa-icons",
275
+ "sizes": [
276
+ 36,
277
+ 48,
278
+ 72,
279
+ 96,
280
+ 144,
281
+ 192,
282
+ 512,
283
+ ],
284
+ },
285
+ "meta": {},
286
+ "sw": {
287
+ "dest": "sw.js",
288
+ "scope": "/",
289
+ "src": "sw.ts",
290
+ },
291
+ "webmanifest": {
292
+ "dest": "/manifest.[hash].json",
293
+ "enabled": false,
294
+ },
295
+ "workbox": {
296
+ "enabled": false,
297
+ },
298
+ },
245
299
  "serverRunner": "process",
246
300
  "transpilation": {
247
301
  "loader": {
@@ -525,6 +525,189 @@
525
525
  ],
526
526
  "type": "string"
527
527
  },
528
+ "pwa": {
529
+ "title": "PWA configuration (works with `TramvaiPwaModule` from `@tramvai/module-progressive-web-app` library)",
530
+ "default": {},
531
+ "type": "object",
532
+ "properties": {
533
+ "sw": {
534
+ "title": "Service-Worker configuration",
535
+ "default": {},
536
+ "type": "object",
537
+ "properties": {
538
+ "src": {
539
+ "title": "Path to sw.ts file (relative to \"root\" directory)",
540
+ "default": "sw.ts",
541
+ "type": "string"
542
+ },
543
+ "dest": {
544
+ "title": "Name of generated SW file (will be placed in \"output.client\" directory)",
545
+ "default": "sw.js",
546
+ "type": "string"
547
+ },
548
+ "scope": {
549
+ "title": "Scope of SW (see https://developers.google.com/web/ilt/pwa/introduction-to-service-worker#registration_and_scope)",
550
+ "default": "/",
551
+ "type": "string"
552
+ }
553
+ },
554
+ "additionalProperties": false
555
+ },
556
+ "workbox": {
557
+ "title": "Workbox configuration",
558
+ "default": {},
559
+ "type": "object",
560
+ "properties": {
561
+ "enabled": {
562
+ "cli_overridable": "",
563
+ "title": "Connect `InjectManifest` from `workbox-webpack-plugin` library",
564
+ "default": false,
565
+ "anyOf": [
566
+ {
567
+ "type": "object",
568
+ "properties": {
569
+ "development": {
570
+ "type": "boolean"
571
+ },
572
+ "production": {
573
+ "type": "boolean"
574
+ }
575
+ },
576
+ "additionalProperties": false
577
+ },
578
+ {
579
+ "type": "boolean"
580
+ }
581
+ ]
582
+ }
583
+ },
584
+ "additionalProperties": false
585
+ },
586
+ "webmanifest": {
587
+ "title": "WebManifest content (manifest.json or webmanifest will be generated based on this options)",
588
+ "default": {},
589
+ "type": "object",
590
+ "properties": {
591
+ "enabled": {
592
+ "title": "Create webmanifest file",
593
+ "default": false,
594
+ "type": "boolean"
595
+ },
596
+ "dest": {
597
+ "title": "Name of generated manifest file (will be placed in \"output.client\" directory). You can use `[hash]` placeholder for manifest cache busting",
598
+ "default": "/manifest.[hash].json",
599
+ "type": "string"
600
+ },
601
+ "scope": {
602
+ "title": "prefer to use \"pwa.sw.scope\" instead, this field will be generated automatically",
603
+ "type": "string"
604
+ },
605
+ "name": {
606
+ "type": "string"
607
+ },
608
+ "short_name": {
609
+ "type": "string"
610
+ },
611
+ "description": {
612
+ "type": "string"
613
+ },
614
+ "start_url": {
615
+ "type": "string"
616
+ },
617
+ "display": {
618
+ "type": "string"
619
+ },
620
+ "theme_color": {
621
+ "title": "prefer to use \"pwa.meta.themeColor\" instead, this field will be generated automatically",
622
+ "type": "string"
623
+ },
624
+ "background_color": {
625
+ "type": "string"
626
+ },
627
+ "icons": {
628
+ "title": "prefer to use \"pwa.icon\" instead, this field will be generated automatically",
629
+ "type": "array",
630
+ "items": {
631
+ "type": "object",
632
+ "properties": {
633
+ "src": {
634
+ "type": "string"
635
+ },
636
+ "sizes": {
637
+ "type": "string"
638
+ },
639
+ "type": {
640
+ "type": "string"
641
+ }
642
+ },
643
+ "additionalProperties": false
644
+ }
645
+ }
646
+ },
647
+ "additionalProperties": false
648
+ },
649
+ "icon": {
650
+ "title": "PWA icons options",
651
+ "default": {},
652
+ "type": "object",
653
+ "properties": {
654
+ "src": {
655
+ "title": "Path to icon file (relative to \"root\" directory)",
656
+ "type": "string"
657
+ },
658
+ "dest": {
659
+ "title": "Folder for generated icons (will be placed in \"output.client\" directory)",
660
+ "default": "pwa-icons",
661
+ "type": "string"
662
+ },
663
+ "sizes": {
664
+ "title": "Icon sizes",
665
+ "default": [
666
+ 36,
667
+ 48,
668
+ 72,
669
+ 96,
670
+ 144,
671
+ 192,
672
+ 512
673
+ ],
674
+ "type": "array",
675
+ "items": {
676
+ "type": "number"
677
+ }
678
+ }
679
+ },
680
+ "additionalProperties": false
681
+ },
682
+ "meta": {
683
+ "title": "PWA meta options",
684
+ "default": {},
685
+ "type": "object",
686
+ "properties": {
687
+ "viewport": {
688
+ "type": "string"
689
+ },
690
+ "themeColor": {
691
+ "type": "string"
692
+ },
693
+ "mobileApp": {
694
+ "type": "string"
695
+ },
696
+ "mobileAppIOS": {
697
+ "type": "string"
698
+ },
699
+ "appleTitle": {
700
+ "type": "string"
701
+ },
702
+ "appleStatusBarStyle": {
703
+ "type": "string"
704
+ }
705
+ },
706
+ "additionalProperties": false
707
+ }
708
+ },
709
+ "additionalProperties": false
710
+ },
528
711
  "webpack": {
529
712
  "title": "experiments configuration for [webpack](https://webpack.js.org/configuration/experiments/)",
530
713
  "default": {},
@@ -64,6 +64,33 @@ describe('JSON schema для tramvai.json', () => {
64
64
  "minicss": {
65
65
  "useImportModule": true,
66
66
  },
67
+ "pwa": {
68
+ "icon": {
69
+ "dest": "pwa-icons",
70
+ "sizes": [
71
+ 36,
72
+ 48,
73
+ 72,
74
+ 96,
75
+ 144,
76
+ 192,
77
+ 512,
78
+ ],
79
+ },
80
+ "meta": {},
81
+ "sw": {
82
+ "dest": "sw.js",
83
+ "scope": "/",
84
+ "src": "sw.ts",
85
+ },
86
+ "webmanifest": {
87
+ "dest": "/manifest.[hash].json",
88
+ "enabled": false,
89
+ },
90
+ "workbox": {
91
+ "enabled": false,
92
+ },
93
+ },
67
94
  "serverRunner": "process",
68
95
  "transpilation": {
69
96
  "loader": "babel",
@@ -1,5 +1,6 @@
1
1
  // eslint-disable-next-line no-restricted-imports
2
2
  import type { ForkTsCheckerWebpackPluginOptions } from 'fork-ts-checker-webpack-plugin/lib/plugin-options';
3
+ import type { PwaIconOptions, PwaMetaOptions, WebManifestOptions } from '../pwa';
3
4
  import type { CliConfigEntry, Experiments } from './cli';
4
5
  import type { OverridableOption } from './common';
5
6
 
@@ -22,6 +23,60 @@ export interface ApplicationExperiments extends Experiments {
22
23
  * @default "process"
23
24
  */
24
25
  serverRunner?: 'process' | 'thread';
26
+ /**
27
+ * @title PWA configuration (works with `TramvaiPwaModule` from `@tramvai/module-progressive-web-app` library)
28
+ * @default {}
29
+ */
30
+ pwa: {
31
+ /**
32
+ * @title Service-Worker configuration
33
+ * @default {}
34
+ */
35
+ sw?: {
36
+ /**
37
+ * @title Path to sw.ts file (relative to "root" directory)
38
+ * @default "sw.ts"
39
+ */
40
+ src?: string;
41
+ /**
42
+ * @title Name of generated SW file (will be placed in "output.client" directory)
43
+ * @default "sw.js"
44
+ */
45
+ dest?: string;
46
+ /**
47
+ * @title Scope of SW (see https://developers.google.com/web/ilt/pwa/introduction-to-service-worker#registration_and_scope)
48
+ * @default "/"
49
+ */
50
+ scope?: string;
51
+ };
52
+ // @todo optional workbox-window?
53
+ /**
54
+ * @title Workbox configuration
55
+ * @default {}
56
+ */
57
+ workbox?: {
58
+ /**
59
+ * @title Connect `InjectManifest` from `workbox-webpack-plugin` library
60
+ * @default false
61
+ */
62
+ enabled?: OverridableOption<boolean>;
63
+ };
64
+ /**
65
+ * @title WebManifest content (manifest.json or webmanifest will be generated based on this options)
66
+ * @default {}
67
+ */
68
+ webmanifest?: WebManifestOptions;
69
+ /**
70
+ * @title PWA icons options
71
+ * @default {}
72
+ */
73
+ icon?: PwaIconOptions;
74
+ /**
75
+ * @title PWA meta options
76
+ * @default {}
77
+ */
78
+ meta?: PwaMetaOptions;
79
+ };
25
80
  }
26
81
 
27
82
  export interface ApplicationConfigEntry extends CliConfigEntry {
@@ -7,3 +7,5 @@ export interface ImageObject {
7
7
  }
8
8
 
9
9
  export type SvgComponent = ComponentType<SVGProps<SVGElement>>;
10
+
11
+ export * from './pwa/index';
@@ -0,0 +1,64 @@
1
+ export type WebManifestOptions = {
2
+ /**
3
+ * @title Create webmanifest file
4
+ * @default false
5
+ */
6
+ enabled?: boolean;
7
+ /**
8
+ * @title Name of generated manifest file (will be placed in "output.client" directory). You can use `[hash]` placeholder for manifest cache busting
9
+ * @default "/manifest.[hash].json"
10
+ */
11
+ dest?: string;
12
+ /**
13
+ * @title prefer to use "pwa.sw.scope" instead, this field will be generated automatically
14
+ */
15
+ scope?: string;
16
+ name?: string;
17
+ short_name?: string;
18
+ description?: string;
19
+ // @todo - example or default with `/?standalone=true`?
20
+ start_url?: string;
21
+ display?: string;
22
+ /**
23
+ * @title prefer to use "pwa.meta.themeColor" instead, this field will be generated automatically
24
+ */
25
+ theme_color?: string;
26
+ background_color?: string;
27
+ /**
28
+ * @title prefer to use "pwa.icon" instead, this field will be generated automatically
29
+ */
30
+ icons?: Array<PwaIconItem>;
31
+ };
32
+
33
+ export type PwaIconItem = {
34
+ src: string;
35
+ sizes: string;
36
+ type?: string;
37
+ };
38
+
39
+ export type PwaIconOptions = {
40
+ /**
41
+ * @title Path to icon file (relative to "root" directory)
42
+ */
43
+ src: string;
44
+ /**
45
+ * @title Folder for generated icons (will be placed in "output.client" directory)
46
+ * @default "pwa-icons"
47
+ */
48
+ dest?: string;
49
+ /**
50
+ * @title Icon sizes
51
+ * @default [36, 48, 72, 96, 144, 192, 512]
52
+ */
53
+ sizes?: number[];
54
+ // @todo: dest directory
55
+ };
56
+
57
+ export type PwaMetaOptions = {
58
+ viewport?: string;
59
+ themeColor?: string;
60
+ mobileApp?: string;
61
+ mobileAppIOS?: string;
62
+ appleTitle?: string;
63
+ appleStatusBarStyle?: string;
64
+ };
@@ -0,0 +1,17 @@
1
+ import type { ApplicationConfigEntry } from '../../api';
2
+ import type { Validator } from './validator.h';
3
+
4
+ export const checkPwaDependencies: Validator = async ({ packageManager, config }, parameters) => {
5
+ const { target } = parameters;
6
+ const cfg = config.getProject(target) as ApplicationConfigEntry;
7
+
8
+ if (cfg.experiments?.pwa?.icon && packageManager.name !== 'unknown') {
9
+ const sharpInstalled = await packageManager.exists({ name: 'sharp' });
10
+
11
+ if (!sharpInstalled) {
12
+ throw Error('You need to install `sharp` library for PWA icon generation in devDependencies');
13
+ }
14
+ }
15
+
16
+ return { name: 'checkPwaDependencies', status: 'ok' };
17
+ };
@@ -1,5 +0,0 @@
1
- import type { ConfigManager } from '../config/configManager';
2
- import type { Context } from '../models/context';
3
- import type { CliConfigEntry } from '../typings/configEntry/cli';
4
- declare const _default: (configManager: ConfigManager<CliConfigEntry>, config: any, context: Context) => Promise<void>;
5
- export default _default;
@@ -1,32 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- const webpack_1 = tslib_1.__importDefault(require("webpack"));
5
- const rimraf_1 = tslib_1.__importDefault(require("rimraf"));
6
- const npmRequire_1 = require("./npmRequire");
7
- exports.default = (configManager, config, context) => {
8
- rimraf_1.default.sync(`${configManager.buildPath}/*.*`, {});
9
- // eslint-disable-next-line no-async-promise-executor
10
- return new Promise((resolve, reject) => tslib_1.__awaiter(void 0, void 0, void 0, function* () {
11
- var _a;
12
- if ((_a = configManager.imageOptimization) === null || _a === void 0 ? void 0 : _a.enabled) {
13
- yield (0, npmRequire_1.npmRequire)({
14
- cliRootDir: context.cliRootDir,
15
- packageManager: context.cliPackageManager,
16
- packageName: 'image-webpack-loader',
17
- description: 'Устанавливаем зависимости для опции imageOptimization',
18
- });
19
- }
20
- (0, webpack_1.default)(config, (err, stats) => {
21
- if (err || stats.hasErrors()) {
22
- return reject(err ||
23
- new Error(stats
24
- .toJson()
25
- .errors.map((error) => { var _a; return (_a = error.message) !== null && _a !== void 0 ? _a : error; })
26
- .join('\n')));
27
- }
28
- return resolve();
29
- });
30
- }));
31
- };
32
- //# sourceMappingURL=webpackBuild.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"webpackBuild.js","sourceRoot":"","sources":["../../src/utils/webpackBuild.ts"],"names":[],"mappings":";;;AAAA,8DAA8B;AAC9B,4DAA4B;AAE5B,6CAA0C;AAI1C,kBAAe,CAAC,aAA4C,EAAE,MAAM,EAAE,OAAgB,EAAE,EAAE;IACxF,gBAAM,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,SAAS,MAAM,EAAE,EAAE,CAAC,CAAC;IAElD,qDAAqD;IACrD,OAAO,IAAI,OAAO,CAAO,CAAO,OAAO,EAAE,MAAM,EAAE,EAAE;;QACjD,IAAI,MAAA,aAAa,CAAC,iBAAiB,0CAAE,OAAO,EAAE;YAC5C,MAAM,IAAA,uBAAU,EAAC;gBACf,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,cAAc,EAAE,OAAO,CAAC,iBAAiB;gBACzC,WAAW,EAAE,sBAAsB;gBACnC,WAAW,EAAE,uDAAuD;aACrE,CAAC,CAAC;SACJ;QAED,IAAA,iBAAO,EAAC,MAAM,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;YAC7B,IAAI,GAAG,IAAI,KAAK,CAAC,SAAS,EAAE,EAAE;gBAC5B,OAAO,MAAM,CACX,GAAG;oBACD,IAAI,KAAK,CACP,KAAK;yBACF,MAAM,EAAE;yBACR,MAAM,CAAC,GAAG,CAAC,CAAC,KAAU,EAAE,EAAE,WAAC,OAAA,MAAA,KAAK,CAAC,OAAO,mCAAI,KAAK,CAAA,EAAA,CAAC;yBAClD,IAAI,CAAC,IAAI,CAAC,CACd,CACJ,CAAC;aACH;YAED,OAAO,OAAO,EAAE,CAAC;QACnB,CAAC,CAAC,CAAC;IACL,CAAC,CAAA,CAAC,CAAC;AACL,CAAC,CAAC"}
@@ -1,38 +0,0 @@
1
- import webpack from 'webpack';
2
- import rimraf from 'rimraf';
3
- import type { ConfigManager } from '../config/configManager';
4
- import { npmRequire } from './npmRequire';
5
- import type { Context } from '../models/context';
6
- import type { CliConfigEntry } from '../typings/configEntry/cli';
7
-
8
- export default (configManager: ConfigManager<CliConfigEntry>, config, context: Context) => {
9
- rimraf.sync(`${configManager.buildPath}/*.*`, {});
10
-
11
- // eslint-disable-next-line no-async-promise-executor
12
- return new Promise<void>(async (resolve, reject) => {
13
- if (configManager.imageOptimization?.enabled) {
14
- await npmRequire({
15
- cliRootDir: context.cliRootDir,
16
- packageManager: context.cliPackageManager,
17
- packageName: 'image-webpack-loader',
18
- description: 'Устанавливаем зависимости для опции imageOptimization',
19
- });
20
- }
21
-
22
- webpack(config, (err, stats) => {
23
- if (err || stats.hasErrors()) {
24
- return reject(
25
- err ||
26
- new Error(
27
- stats
28
- .toJson()
29
- .errors.map((error: any) => error.message ?? error)
30
- .join('\n')
31
- )
32
- );
33
- }
34
-
35
- return resolve();
36
- });
37
- });
38
- };