@ronas-it/nx-generators 0.4.0 → 0.5.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 (126) hide show
  1. package/README.md +45 -12
  2. package/generators.json +5 -0
  3. package/package.json +1 -1
  4. package/src/generators/code-checks/generator.js +2 -15
  5. package/src/generators/code-checks/generator.js.map +1 -1
  6. package/src/generators/expo-app/app-files/app/_layout.tsx.template +43 -0
  7. package/src/generators/expo-app/{files → app-files}/app/index.tsx.template +3 -2
  8. package/src/generators/expo-app/generator.js +16 -17
  9. package/src/generators/expo-app/generator.js.map +1 -1
  10. package/src/generators/next-app/files/app/[locale]/layout.tsx.template +1 -1
  11. package/src/generators/next-app/files/app/[locale]/page.tsx.template +2 -2
  12. package/src/generators/next-app/files/app/[locale]/providers.tsx.template +1 -1
  13. package/src/generators/next-app/files/middleware.ts.template +1 -1
  14. package/src/generators/next-app/generator.js +8 -4
  15. package/src/generators/next-app/generator.js.map +1 -1
  16. package/src/generators/repo-config/generator.js +2 -1
  17. package/src/generators/repo-config/generator.js.map +1 -1
  18. package/src/shared/dependencies.d.ts +62 -0
  19. package/src/shared/dependencies.js +68 -0
  20. package/src/shared/dependencies.js.map +1 -0
  21. package/src/shared/enums/base-generator-type.d.ts +4 -0
  22. package/src/shared/enums/base-generator-type.js +9 -0
  23. package/src/shared/enums/base-generator-type.js.map +1 -0
  24. package/src/shared/enums/index.d.ts +1 -0
  25. package/src/shared/enums/index.js +5 -0
  26. package/src/shared/enums/index.js.map +1 -0
  27. package/src/shared/generators/api-client/generator.d.ts +6 -0
  28. package/src/shared/generators/api-client/generator.js +35 -0
  29. package/src/shared/generators/api-client/generator.js.map +1 -0
  30. package/src/shared/generators/api-client/index.d.ts +1 -0
  31. package/src/shared/generators/api-client/index.js +5 -0
  32. package/src/shared/generators/api-client/index.js.map +1 -0
  33. package/src/shared/generators/api-client/lib-files/shared/data-access/api-client/src/configuration.ts.template +15 -0
  34. package/src/shared/generators/api-client/lib-files/shared/data-access/api-client/src/index.ts.template +3 -0
  35. package/src/shared/generators/api-client/lib-files/shared/data-access/api-client/src/service.ts.template +4 -0
  36. package/src/shared/generators/api-client/lib-files/shared/data-access/api-client/src/utils/api-creator.ts.template +6 -0
  37. package/src/shared/generators/api-client/lib-files/shared/data-access/api-client/src/utils/base-query.ts.template +6 -0
  38. package/src/shared/generators/api-client/lib-files/shared/data-access/api-client/src/utils/index.ts.template +2 -0
  39. package/src/shared/generators/app-env/generator.d.ts +6 -0
  40. package/src/shared/generators/app-env/generator.js +25 -0
  41. package/src/shared/generators/app-env/generator.js.map +1 -0
  42. package/src/shared/generators/app-env/index.d.ts +1 -0
  43. package/src/shared/generators/app-env/index.js +5 -0
  44. package/src/shared/generators/app-env/index.js.map +1 -0
  45. package/src/shared/generators/app-env/lib-files/shared/utils/app-env/src/app-env.ts.template +5 -0
  46. package/src/shared/generators/app-env/lib-files/shared/utils/app-env/src/env.d.ts.template +9 -0
  47. package/src/shared/generators/app-env/lib-files/shared/utils/app-env/src/env.js.template +28 -0
  48. package/src/shared/generators/app-env/lib-files/shared/utils/app-env/src/index.ts.template +3 -0
  49. package/src/shared/generators/auth/generator.d.ts +6 -0
  50. package/src/shared/generators/auth/generator.js +36 -0
  51. package/src/shared/generators/auth/generator.js.map +1 -0
  52. package/src/shared/generators/auth/index.d.ts +1 -0
  53. package/src/shared/generators/auth/index.js +5 -0
  54. package/src/shared/generators/auth/index.js.map +1 -0
  55. package/src/shared/generators/auth/lib-files/shared/data-access/api/src/lib/auth/api.ts.template +78 -0
  56. package/src/shared/generators/auth/lib-files/shared/data-access/api/src/lib/auth/index.ts.template +2 -0
  57. package/src/shared/generators/auth/lib-files/shared/data-access/api/src/lib/auth/models/forgot-password-request.ts.template +10 -0
  58. package/src/shared/generators/auth/lib-files/shared/data-access/api/src/lib/auth/models/index.ts.template +6 -0
  59. package/src/shared/generators/auth/lib-files/shared/data-access/api/src/lib/auth/models/login-request.ts.template +13 -0
  60. package/src/shared/generators/auth/lib-files/shared/data-access/api/src/lib/auth/models/login-response.ts.template +15 -0
  61. package/src/shared/generators/auth/lib-files/shared/data-access/api/src/lib/auth/models/refresh-token-response.ts.template +16 -0
  62. package/src/shared/generators/auth/lib-files/shared/data-access/api/src/lib/auth/models/register-request.ts.template +19 -0
  63. package/src/shared/generators/auth/lib-files/shared/data-access/api/src/lib/auth/models/restore-password-request.ts.template +14 -0
  64. package/src/shared/generators/auth/lib-files/shared/data-access/api/src/lib/user/index.ts.template +1 -0
  65. package/src/shared/generators/auth/lib-files/shared/data-access/api/src/lib/user/models/index.ts.template +1 -0
  66. package/src/shared/generators/auth/lib-files/shared/data-access/api/src/lib/user/models/user.ts.template +15 -0
  67. package/src/shared/generators/auth/lib-files/shared/data-access/auth/src/index.ts.template +1 -0
  68. package/src/shared/generators/auth/lib-files/shared/data-access/auth/src/lib/index.ts.template +1 -0
  69. package/src/shared/generators/auth/lib-files/shared/data-access/auth/src/lib/store/index.ts.template +2 -0
  70. package/src/shared/generators/auth/lib-files/shared/data-access/auth/src/lib/store/listener.ts.template +93 -0
  71. package/src/shared/generators/auth/lib-files/shared/data-access/auth/src/lib/store/slice.ts.template +50 -0
  72. package/src/shared/generators/index.d.ts +7 -0
  73. package/src/shared/generators/index.js +11 -0
  74. package/src/shared/generators/index.js.map +1 -0
  75. package/src/shared/generators/rn-styles/generator.d.ts +6 -0
  76. package/src/shared/generators/rn-styles/generator.js +36 -0
  77. package/src/shared/generators/rn-styles/generator.js.map +1 -0
  78. package/src/shared/generators/rn-styles/index.d.ts +1 -0
  79. package/src/shared/generators/rn-styles/index.js +5 -0
  80. package/src/shared/generators/rn-styles/index.js.map +1 -0
  81. package/src/shared/generators/rn-styles/lib-files/shared/ui/styles/src/lib/extended-stylesheet.ts.template +44 -0
  82. package/src/shared/generators/rn-styles/lib-files/shared/ui/styles/src/lib/index.ts.template +3 -0
  83. package/src/shared/generators/rn-styles/lib-files/shared/ui/styles/src/lib/styles.ts.template +30 -0
  84. package/src/shared/generators/rn-styles/lib-files/shared/ui/styles/src/lib/variables.ts.template +38 -0
  85. package/src/shared/generators/storage/generator.d.ts +6 -0
  86. package/src/shared/generators/storage/generator.js +25 -0
  87. package/src/shared/generators/storage/generator.js.map +1 -0
  88. package/src/shared/generators/storage/index.d.ts +1 -0
  89. package/src/shared/generators/storage/index.js +5 -0
  90. package/src/shared/generators/storage/index.js.map +1 -0
  91. package/src/shared/generators/storage/lib-files/shared/data-access/storage/src/index.ts.template +1 -0
  92. package/src/shared/generators/storage/lib-files/shared/data-access/storage/src/service.ts.template +9 -0
  93. package/src/shared/generators/store/expo-app/lib-files/shared/data-access/store/src/index.ts.template +1 -0
  94. package/src/shared/generators/store/expo-app/lib-files/shared/data-access/store/src/store.ts.template +36 -0
  95. package/src/shared/generators/store/generator.d.ts +8 -0
  96. package/src/shared/generators/store/generator.js +34 -0
  97. package/src/shared/generators/store/generator.js.map +1 -0
  98. package/src/shared/generators/store/index.d.ts +1 -0
  99. package/src/shared/generators/store/index.js +5 -0
  100. package/src/shared/generators/store/index.js.map +1 -0
  101. package/src/shared/generators/store/next-app/lib-files/shared/data-access/store/src/index.ts.template +1 -0
  102. package/src/shared/generators/store/next-app/lib-files/shared/data-access/store/src/store.ts.template +18 -0
  103. package/src/shared/generators/ui-kitten/generator.d.ts +7 -0
  104. package/src/shared/generators/ui-kitten/generator.js +48 -0
  105. package/src/shared/generators/ui-kitten/generator.js.map +1 -0
  106. package/src/shared/generators/ui-kitten/index.d.ts +1 -0
  107. package/src/shared/generators/ui-kitten/index.js +5 -0
  108. package/src/shared/generators/ui-kitten/index.js.map +1 -0
  109. package/src/shared/generators/ui-kitten/lib-files/shared/features/user-theme-provider/src/index.ts.template +1 -0
  110. package/src/shared/generators/ui-kitten/lib-files/shared/features/user-theme-provider/src/lib/component.tsx.template +39 -0
  111. package/src/shared/generators/ui-kitten/lib-files/shared/features/user-theme-provider/src/lib/config.ts.template +5 -0
  112. package/src/shared/generators/ui-kitten/lib-files/shared/features/user-theme-provider/src/lib/index.ts.template +1 -0
  113. package/src/shared/generators/ui-kitten/lib-files/shared/ui/styles/src/lib/create-adaptive-styles.ts.template +39 -0
  114. package/src/shared/generators/ui-kitten/lib-files/shared/ui/styles/src/lib/eva-theme/hooks/index.ts.template +1 -0
  115. package/src/shared/generators/ui-kitten/lib-files/shared/ui/styles/src/lib/eva-theme/hooks/use-app-theme.ts.template +4 -0
  116. package/src/shared/generators/ui-kitten/lib-files/shared/ui/styles/src/lib/eva-theme/index.ts.template +3 -0
  117. package/src/shared/generators/ui-kitten/lib-files/shared/ui/styles/src/lib/eva-theme/mapping.ts.template +336 -0
  118. package/src/shared/generators/ui-kitten/lib-files/shared/ui/styles/src/lib/eva-theme/theme.ts.template +44 -0
  119. package/src/shared/generators/ui-kitten/schema.d.ts +5 -0
  120. package/src/shared/generators/ui-kitten/schema.json +33 -0
  121. package/src/generators/expo-app/files/app/_layout.tsx.template +0 -23
  122. /package/src/generators/expo-app/{files → app-files}/.env.development.template +0 -0
  123. /package/src/generators/expo-app/{files → app-files}/README.md.template +0 -0
  124. /package/src/generators/expo-app/{files → app-files}/app.config.ts.template +0 -0
  125. /package/src/generators/expo-app/{files → app-files}/eas.json.template +0 -0
  126. /package/src/generators/expo-app/{files → app-files}/metro.config.js.template +0 -0
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runApiClientGenerator = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const child_process_1 = require("child_process");
6
+ const fs_1 = require("fs");
7
+ const path = require("path");
8
+ const devkit_1 = require("@nx/devkit");
9
+ const dependencies_1 = require("../../dependencies");
10
+ const utils_1 = require("../../utils");
11
+ function runApiClientGenerator(tree, options) {
12
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
13
+ const appRoot = `apps/${options.directory}`;
14
+ const libRoot = `libs/${options.directory}`;
15
+ const libPath = `@${options.name}/${options.directory}`;
16
+ // Generate shared libs
17
+ (0, child_process_1.execSync)(`npx nx g react-lib ${options.directory}/shared/data-access/api-client`, { stdio: 'inherit' });
18
+ const appPackagePath = `${appRoot}/package.json`;
19
+ // Remove unnecessary files and files that will be replaced
20
+ tree.delete(`${libRoot}/shared/data-access/api-client/src/index.ts`);
21
+ // Add lib files
22
+ (0, devkit_1.generateFiles)(tree, path.join(__dirname, '/lib-files'), libRoot, Object.assign(Object.assign({}, options), { formatName: utils_1.formatName,
23
+ formatAppIdentifier: utils_1.formatAppIdentifier, formatDirectory: () => libPath }));
24
+ // Add dependencies
25
+ (0, devkit_1.addDependenciesToPackageJson)(tree, dependencies_1.dependencies['api-client'], {});
26
+ if ((0, fs_1.existsSync)(appPackagePath)) {
27
+ (0, devkit_1.addDependenciesToPackageJson)(tree, dependencies_1.dependencies['api-client'], {}, appPackagePath);
28
+ }
29
+ yield (0, devkit_1.formatFiles)(tree);
30
+ console.warn(`\nPlease set api endpoint in ${libPath}/shared/data-access/api-client/src/configuration.ts`);
31
+ });
32
+ }
33
+ exports.runApiClientGenerator = runApiClientGenerator;
34
+ exports.default = runApiClientGenerator;
35
+ //# sourceMappingURL=generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../../plugin/src/shared/generators/api-client/generator.ts"],"names":[],"mappings":";;;;AAAA,iDAAyC;AACzC,2BAAgC;AAChC,6BAA6B;AAC7B,uCAKoB;AACpB,qDAAkD;AAClD,uCAA8D;AAE9D,SAAsB,qBAAqB,CACzC,IAAU,EACV,OAA4C;;QAE5C,MAAM,OAAO,GAAG,QAAQ,OAAO,CAAC,SAAS,EAAE,CAAC;QAC5C,MAAM,OAAO,GAAG,QAAQ,OAAO,CAAC,SAAS,EAAE,CAAC;QAC5C,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;QAExD,uBAAuB;QACvB,IAAA,wBAAQ,EAAC,sBAAsB,OAAO,CAAC,SAAS,gCAAgC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QAExG,MAAM,cAAc,GAAG,GAAG,OAAO,eAAe,CAAC;QAEjD,2DAA2D;QAC3D,IAAI,CAAC,MAAM,CAAC,GAAG,OAAO,6CAA6C,CAAC,CAAC;QAErE,gBAAgB;QAChB,IAAA,sBAAa,EAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,EAAE,OAAO,kCAC1D,OAAO,KACV,UAAU,EAAV,kBAAU;YACV,mBAAmB,EAAnB,2BAAmB,EACnB,eAAe,EAAE,GAAG,EAAE,CAAC,OAAO,IAC9B,CAAC;QAEH,mBAAmB;QACnB,IAAA,qCAA4B,EAAC,IAAI,EAAE,2BAAY,CAAC,YAAY,CAAC,EAAE,EAAE,CAAC,CAAC;QAEnE,IAAI,IAAA,eAAU,EAAC,cAAc,CAAC,EAAE,CAAC;YAC/B,IAAA,qCAA4B,EAAC,IAAI,EAAE,2BAAY,CAAC,YAAY,CAAC,EAAE,EAAE,EAAE,cAAc,CAAC,CAAC;QACrF,CAAC;QAED,MAAM,IAAA,oBAAW,EAAC,IAAI,CAAC,CAAC;QAExB,OAAO,CAAC,IAAI,CAAC,gCAAgC,OAAO,qDAAqD,CAAC,CAAC;IAC7G,CAAC;CAAA;AAlCD,sDAkCC;AAED,kBAAe,qBAAqB,CAAC"}
@@ -0,0 +1 @@
1
+ export * from './generator';
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./generator"), exports);
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../plugin/src/shared/generators/api-client/index.ts"],"names":[],"mappings":";;;AAAA,sDAA4B"}
@@ -0,0 +1,15 @@
1
+ import { appEnv } from '<%= formatDirectory() %>/shared/utils/app-env';
2
+
3
+ export const configuration = {
4
+ // TODO: Add development, production url, when API will be ready
5
+ apiURL: appEnv.select({
6
+ development: '',
7
+ production: '',
8
+ }),
9
+ auth: {
10
+ refreshTokenRoute: '/auth/refresh',
11
+ // TODO: Add routes, when confirmation functionality will be ready
12
+ unauthorizedRoutes: ['/login', '/register', '/auth/forgot-password', '/auth/restore-password', '/auth/token/check'],
13
+ logoutRoute: '/auth/logout',
14
+ },
15
+ };
@@ -0,0 +1,3 @@
1
+ export * from './configuration';
2
+ export * from './service';
3
+ export * from './utils';
@@ -0,0 +1,4 @@
1
+ import { ApiService } from '@ronas-it/axios-api-client';
2
+ import { configuration } from './configuration';
3
+
4
+ export const apiService = new ApiService(configuration.apiURL);
@@ -0,0 +1,6 @@
1
+ import { createApiCreator } from '@ronas-it/rtkq-entity-api';
2
+ import { axiosBaseQuery } from './base-query';
3
+
4
+ export const createAppApi = createApiCreator({
5
+ baseQuery: axiosBaseQuery,
6
+ });
@@ -0,0 +1,6 @@
1
+ import { BaseQueryFunction, createAxiosBaseQuery } from '@ronas-it/rtkq-entity-api';
2
+ import { apiService } from '../service';
3
+
4
+ export const axiosBaseQuery: BaseQueryFunction = createAxiosBaseQuery({
5
+ getHttpClient: () => apiService.httpClient,
6
+ });
@@ -0,0 +1,2 @@
1
+ export * from './api-creator';
2
+ export * from './base-query';
@@ -0,0 +1,6 @@
1
+ import { Tree } from '@nx/devkit';
2
+ export declare function runAppEnvGenerator(tree: Tree, options: {
3
+ name: string;
4
+ directory: string;
5
+ }): Promise<void>;
6
+ export default runAppEnvGenerator;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runAppEnvGenerator = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const child_process_1 = require("child_process");
6
+ const path = require("path");
7
+ const devkit_1 = require("@nx/devkit");
8
+ const utils_1 = require("../../utils");
9
+ function runAppEnvGenerator(tree, options) {
10
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
11
+ const libRoot = `libs/${options.directory}`;
12
+ const libPath = `@${options.name}/${options.directory}`;
13
+ // Generate shared libs
14
+ (0, child_process_1.execSync)(`npx nx g react-lib ${options.directory}/shared/utils/app-env`, { stdio: 'inherit' });
15
+ // Remove unnecessary files and files that will be replaced
16
+ tree.delete(`${libRoot}/shared/utils/app-env/src/index.ts`);
17
+ // Add lib files
18
+ (0, devkit_1.generateFiles)(tree, path.join(__dirname, 'lib-files'), libRoot, Object.assign(Object.assign({}, options), { formatName: utils_1.formatName,
19
+ formatAppIdentifier: utils_1.formatAppIdentifier, formatDirectory: () => libPath }));
20
+ yield (0, devkit_1.formatFiles)(tree);
21
+ });
22
+ }
23
+ exports.runAppEnvGenerator = runAppEnvGenerator;
24
+ exports.default = runAppEnvGenerator;
25
+ //# sourceMappingURL=generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../../plugin/src/shared/generators/app-env/generator.ts"],"names":[],"mappings":";;;;AAAA,iDAAyC;AACzC,6BAA6B;AAC7B,uCAIoB;AACpB,uCAA8D;AAE9D,SAAsB,kBAAkB,CACtC,IAAU,EACV,OAA4C;;QAE5C,MAAM,OAAO,GAAG,QAAQ,OAAO,CAAC,SAAS,EAAE,CAAC;QAC5C,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;QAExD,uBAAuB;QACvB,IAAA,wBAAQ,EAAC,sBAAsB,OAAO,CAAC,SAAS,uBAAuB,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QAE/F,2DAA2D;QAC3D,IAAI,CAAC,MAAM,CAAC,GAAG,OAAO,oCAAoC,CAAC,CAAC;QAE5D,gBAAgB;QAChB,IAAA,sBAAa,EAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,EAAE,OAAO,kCACzD,OAAO,KACV,UAAU,EAAV,kBAAU;YACV,mBAAmB,EAAnB,2BAAmB,EACnB,eAAe,EAAE,GAAG,EAAE,CAAC,OAAO,IAC9B,CAAC;QAEH,MAAM,IAAA,oBAAW,EAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;CAAA;AAtBD,gDAsBC;AAED,kBAAe,kBAAkB,CAAC"}
@@ -0,0 +1 @@
1
+ export * from './generator';
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./generator"), exports);
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../plugin/src/shared/generators/app-env/index.ts"],"names":[],"mappings":";;;AAAA,sDAA4B"}
@@ -0,0 +1,5 @@
1
+ import { AppEnv } from './env';
2
+
3
+ export type AppEnvName = 'development' | 'production';
4
+
5
+ export const appEnv = new AppEnv<AppEnvName>(process.env.EXPO_PUBLIC_APP_ENV as AppEnvName || process.env.NEXT_PUBLIC_APP_ENV);
@@ -0,0 +1,9 @@
1
+ export class AppEnv<TEnv extends string | number> {
2
+ private readonly env: TEnv;
3
+
4
+ public get current(): TEnv;
5
+
6
+ constructor(env: TEnv);
7
+
8
+ public select<TValue>(options: Record<TEnv, TValue> | Record<'default', TValue>): TValue;
9
+ }
@@ -0,0 +1,28 @@
1
+ const defaultOptionName = 'default';
2
+
3
+ class AppEnv {
4
+ get current() {
5
+ return this.env;
6
+ }
7
+
8
+ constructor(env) {
9
+ this.env = env;
10
+
11
+ if (!this.env) {
12
+ throw new Error('Got empty current environment name! Please make sure you have set NEXT_PUBLIC_APP_ENV (Next.js) or EXPO_PUBLIC_APP_ENV (RN) env variable.');
13
+ }
14
+ }
15
+
16
+ select(options) {
17
+ const envKeys = Object.keys(options);
18
+ const shouldUseDefault = !envKeys.includes(this.current);
19
+
20
+ if (shouldUseDefault && !envKeys.includes(defaultOptionName)) {
21
+ throw new Error(`Missing value for environment '${this.current}' and '${defaultOptionName}' option was not set.`);
22
+ }
23
+
24
+ return shouldUseDefault ? options[defaultOptionName] : options[this.current];
25
+ }
26
+ }
27
+
28
+ module.exports = { AppEnv };
@@ -0,0 +1,3 @@
1
+ export * from './env';
2
+ export * from './env.js';
3
+ export * from './app-env';
@@ -0,0 +1,6 @@
1
+ import { Tree } from '@nx/devkit';
2
+ export declare function runAuthGenerator(tree: Tree, options: {
3
+ name: string;
4
+ directory: string;
5
+ }): Promise<void>;
6
+ export default runAuthGenerator;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runAuthGenerator = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const child_process_1 = require("child_process");
6
+ const path = require("path");
7
+ const devkit_1 = require("@nx/devkit");
8
+ const dependencies_1 = require("../../dependencies");
9
+ const utils_1 = require("../../utils");
10
+ const fs_1 = require("fs");
11
+ function runAuthGenerator(tree, options) {
12
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
13
+ const appRoot = `apps/${options.directory}`;
14
+ const libRoot = `libs/${options.directory}`;
15
+ const libPath = `@${options.name}/${options.directory}`;
16
+ // Generate shared libs
17
+ (0, child_process_1.execSync)(`npx nx g react-lib ${options.directory}/shared/data-access/api`, { stdio: 'inherit' });
18
+ (0, child_process_1.execSync)(`npx nx g react-lib ${options.directory}/shared/data-access/auth`, { stdio: 'inherit' });
19
+ const appPackagePath = `${appRoot}/package.json`;
20
+ // Remove unnecessary files and files that will be replaced
21
+ tree.delete(`${libRoot}/shared/data-access/api/src/index.ts`);
22
+ tree.delete(`${libRoot}/shared/data-access/auth/src/index.ts`);
23
+ // Add lib files
24
+ (0, devkit_1.generateFiles)(tree, path.join(__dirname, '/lib-files'), libRoot, Object.assign(Object.assign({}, options), { formatName: utils_1.formatName,
25
+ formatAppIdentifier: utils_1.formatAppIdentifier, formatDirectory: () => libPath }));
26
+ // Add dependencies
27
+ (0, devkit_1.addDependenciesToPackageJson)(tree, dependencies_1.dependencies['auth'], dependencies_1.devDependencies['auth']);
28
+ if ((0, fs_1.existsSync)(appPackagePath)) {
29
+ (0, devkit_1.addDependenciesToPackageJson)(tree, dependencies_1.dependencies['auth'], dependencies_1.devDependencies['auth'], appPackagePath);
30
+ }
31
+ yield (0, devkit_1.formatFiles)(tree);
32
+ });
33
+ }
34
+ exports.runAuthGenerator = runAuthGenerator;
35
+ exports.default = runAuthGenerator;
36
+ //# sourceMappingURL=generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../../plugin/src/shared/generators/auth/generator.ts"],"names":[],"mappings":";;;;AAAA,iDAAyC;AACzC,6BAA6B;AAC7B,uCAKoB;AACpB,qDAAmE;AACnE,uCAA8D;AAC9D,2BAAgC;AAEhC,SAAsB,gBAAgB,CACpC,IAAU,EACV,OAA4C;;QAE5C,MAAM,OAAO,GAAG,QAAQ,OAAO,CAAC,SAAS,EAAE,CAAC;QAC5C,MAAM,OAAO,GAAG,QAAQ,OAAO,CAAC,SAAS,EAAE,CAAC;QAC5C,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;QAExD,uBAAuB;QACvB,IAAA,wBAAQ,EAAC,sBAAsB,OAAO,CAAC,SAAS,yBAAyB,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QACjG,IAAA,wBAAQ,EAAC,sBAAsB,OAAO,CAAC,SAAS,0BAA0B,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QAElG,MAAM,cAAc,GAAG,GAAG,OAAO,eAAe,CAAC;QAEjD,2DAA2D;QAC3D,IAAI,CAAC,MAAM,CAAC,GAAG,OAAO,sCAAsC,CAAC,CAAC;QAC9D,IAAI,CAAC,MAAM,CAAC,GAAG,OAAO,uCAAuC,CAAC,CAAC;QAE/D,gBAAgB;QAChB,IAAA,sBAAa,EAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,EAAE,OAAO,kCAC1D,OAAO,KACV,UAAU,EAAV,kBAAU;YACV,mBAAmB,EAAnB,2BAAmB,EACnB,eAAe,EAAE,GAAG,EAAE,CAAC,OAAO,IAC9B,CAAC;QAED,mBAAmB;QACnB,IAAA,qCAA4B,EAAC,IAAI,EAAE,2BAAY,CAAC,MAAM,CAAC,EAAE,8BAAe,CAAC,MAAM,CAAC,CAAC,CAAC;QAElF,IAAI,IAAA,eAAU,EAAC,cAAc,CAAC,EAAE,CAAC;YAC/B,IAAA,qCAA4B,EAAC,IAAI,EAAE,2BAAY,CAAC,MAAM,CAAC,EAAE,8BAAe,CAAC,MAAM,CAAC,EAAE,cAAc,CAAC,CAAC;QACpG,CAAC;QAEH,MAAM,IAAA,oBAAW,EAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;CAAA;AAlCD,4CAkCC;AAED,kBAAe,gBAAgB,CAAC"}
@@ -0,0 +1 @@
1
+ export * from './generator';
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./generator"), exports);
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../plugin/src/shared/generators/auth/index.ts"],"names":[],"mappings":";;;AAAA,sDAA4B"}
@@ -0,0 +1,78 @@
1
+ import { prepareRequestParams } from '@ronas-it/rtkq-entity-api';
2
+ import { plainToInstance } from 'class-transformer';
3
+ import { createAppApi } from '<%= formatDirectory() %>/shared/data-access/api-client';
4
+ import {
5
+ ForgotPasswordRequest,
6
+ LoginRequest,
7
+ LogInResponse,
8
+ RefreshTokenResponse,
9
+ RegisterRequest,
10
+ RestorePasswordRequest,
11
+ } from './models';
12
+
13
+ export const authApi = createAppApi({
14
+ reducerPath: 'auth',
15
+ endpoints: (builder) => ({
16
+ login: builder.mutation<LogInResponse, LoginRequest>({
17
+ query: (params) => {
18
+ const request = prepareRequestParams(params, LoginRequest);
19
+
20
+ return {
21
+ method: 'POST',
22
+ url: '/login',
23
+ data: request,
24
+ };
25
+ },
26
+ transformResponse: (response) => plainToInstance(LogInResponse, response),
27
+ transformErrorResponse: (response) => ({ ...response, skipToast: true }),
28
+ }),
29
+ register: builder.mutation<LogInResponse, RegisterRequest>({
30
+ query: (params) => {
31
+ const request = prepareRequestParams(params, RegisterRequest);
32
+
33
+ return {
34
+ method: 'POST',
35
+ url: '/register',
36
+ data: request,
37
+ };
38
+ },
39
+ transformResponse: (response) => plainToInstance(LogInResponse, response),
40
+ transformErrorResponse: (response) => ({ ...response, skipToast: true }),
41
+ }),
42
+ refreshToken: builder.mutation<RefreshTokenResponse, void>({
43
+ query: () => ({
44
+ method: 'GET',
45
+ url: '/auth/refresh',
46
+ }),
47
+ }),
48
+ forgotPassword: builder.mutation<void, ForgotPasswordRequest>({
49
+ query: (params) => {
50
+ const request = prepareRequestParams(params, ForgotPasswordRequest);
51
+
52
+ return {
53
+ method: 'POST',
54
+ url: '/auth/forgot-password',
55
+ data: request,
56
+ };
57
+ },
58
+ transformErrorResponse: (response) => ({ ...response, skipToast: true }),
59
+ }),
60
+ restorePassword: builder.mutation<void, RestorePasswordRequest>({
61
+ query: (params) => {
62
+ const request = prepareRequestParams(params, RestorePasswordRequest);
63
+
64
+ return {
65
+ method: 'POST',
66
+ url: '/auth/restore-password',
67
+ params: request,
68
+ };
69
+ },
70
+ }),
71
+ logout: builder.mutation<void, void>({
72
+ query: () => ({
73
+ method: 'POST',
74
+ url: '/auth/logout',
75
+ }),
76
+ }),
77
+ }),
78
+ });
@@ -0,0 +1,2 @@
1
+ export * from './api';
2
+ export * from './models';
@@ -0,0 +1,10 @@
1
+ import { Expose } from 'class-transformer';
2
+
3
+ export class ForgotPasswordRequest {
4
+ @Expose()
5
+ public email: string;
6
+
7
+ constructor(request: Partial<ForgotPasswordRequest> = {}) {
8
+ Object.assign(this, request);
9
+ }
10
+ }
@@ -0,0 +1,6 @@
1
+ export * from './login-response';
2
+ export * from './refresh-token-response';
3
+ export * from './register-request';
4
+ export * from './login-request';
5
+ export * from './forgot-password-request';
6
+ export * from './restore-password-request';
@@ -0,0 +1,13 @@
1
+ import { Expose } from 'class-transformer';
2
+
3
+ export class LoginRequest {
4
+ @Expose()
5
+ public email: string;
6
+
7
+ @Expose()
8
+ public password: string;
9
+
10
+ constructor(request: Partial<LoginRequest> = {}) {
11
+ Object.assign(this, request);
12
+ }
13
+ }
@@ -0,0 +1,15 @@
1
+ import { Expose, Type } from 'class-transformer';
2
+ import { User } from '../../user';
3
+ import { RefreshTokenResponse } from './refresh-token-response';
4
+
5
+ export class LogInResponse extends RefreshTokenResponse {
6
+ @Expose()
7
+ @Type(() => User)
8
+ public user: User;
9
+
10
+ constructor(partial: Partial<LogInResponse> = {}) {
11
+ super(partial);
12
+
13
+ Object.assign(this, partial);
14
+ }
15
+ }
@@ -0,0 +1,16 @@
1
+ import { Expose } from 'class-transformer';
2
+
3
+ export class RefreshTokenResponse {
4
+ @Expose()
5
+ public token: string;
6
+
7
+ @Expose()
8
+ public ttl: number;
9
+
10
+ @Expose({ name: 'refresh_ttl' })
11
+ public refreshTtl: string;
12
+
13
+ constructor(partial: Partial<RefreshTokenResponse>) {
14
+ Object.assign(this, partial);
15
+ }
16
+ }
@@ -0,0 +1,19 @@
1
+ import { Expose } from 'class-transformer';
2
+
3
+ export class RegisterRequest {
4
+ @Expose()
5
+ public username: string;
6
+
7
+ @Expose()
8
+ public email: string;
9
+
10
+ @Expose()
11
+ public password: string;
12
+
13
+ @Expose()
14
+ public confirm: string;
15
+
16
+ constructor(partial: Partial<RegisterRequest>) {
17
+ Object.assign(this, partial);
18
+ }
19
+ }
@@ -0,0 +1,14 @@
1
+ import { Expose } from 'class-transformer';
2
+
3
+ export class RestorePasswordRequest {
4
+ @Expose()
5
+ public password: string;
6
+
7
+ @Expose()
8
+ public token: string;
9
+
10
+ constructor(partial: Partial<RestorePasswordRequest>) {
11
+ Object.assign(this, partial);
12
+ }
13
+ }
14
+
@@ -0,0 +1,15 @@
1
+ import { BaseEntity } from '@ronas-it/rtkq-entity-api';
2
+ import { Expose } from 'class-transformer';
3
+
4
+ export class User extends BaseEntity<number> {
5
+ @Expose()
6
+ public username: string;
7
+
8
+ @Expose()
9
+ public email: string;
10
+
11
+ constructor(model: Partial<User>) {
12
+ super(model);
13
+ Object.assign(this, model);
14
+ }
15
+ }
@@ -0,0 +1,2 @@
1
+ export * from './listener';
2
+ export * from './slice';
@@ -0,0 +1,93 @@
1
+ import { createListenerMiddleware, isAnyOf } from '@reduxjs/toolkit';
2
+ import {
3
+ onRequestRefreshTokenInterceptor,
4
+ onResponseRefreshTokenInterceptor,
5
+ RefreshTokenInterceptorOptions,
6
+ tokenInterceptor,
7
+ } from '@ronas-it/axios-api-client';
8
+ import { storeActions } from '@ronas-it/rtkq-entity-api';
9
+ import { DateTime } from 'luxon';
10
+ import { authApi, LogInResponse } from '<%= formatDirectory() %>/shared/data-access/api';
11
+ import { apiService, configuration } from '<%= formatDirectory() %>/shared/data-access/api-client';
12
+ import { appStorageService } from '<%= formatDirectory() %>/shared/data-access/storage';
13
+ import { authActions, authReducerPath, authSelectors, AuthState } from './slice';
14
+
15
+ export const authListenerMiddleware = createListenerMiddleware<{ [authReducerPath]: AuthState }>();
16
+
17
+ authListenerMiddleware.startListening({
18
+ actionCreator: storeActions.init,
19
+ effect: async (_, { dispatch, getState }) => {
20
+ const isAuthenticated = await appStorageService.isAuthenticated.get();
21
+ const tokenExpiresAt = await appStorageService.tokenExpiresAt.get();
22
+ const token = await appStorageService.token.get();
23
+
24
+ dispatch(authActions.setIsAuthenticated(isAuthenticated === 'true'));
25
+ dispatch(authActions.setTokenExpiresAt(tokenExpiresAt ? DateTime.fromISO(tokenExpiresAt) : null));
26
+ dispatch(authActions.setToken(token ?? null));
27
+
28
+ apiService.useInterceptors({
29
+ request: [[tokenInterceptor({ getToken: () => authSelectors.token(getState()) ?? '' })]],
30
+ });
31
+
32
+ dispatch(authActions.setIsAppReady(true));
33
+ },
34
+ });
35
+
36
+ authListenerMiddleware.startListening({
37
+ matcher: authApi.internalActions.middlewareRegistered.match,
38
+ effect: async (_, { dispatch, getState }) => {
39
+ const options: RefreshTokenInterceptorOptions = {
40
+ configuration: configuration.auth,
41
+ getIsAuthenticated: () => authSelectors.isAuthenticated(getState()),
42
+ runTokenRefreshRequest: async () => {
43
+ const { token, ttl } = await dispatch(authApi.endpoints.refreshToken.initiate()).unwrap();
44
+ dispatch(authActions.saveToken({ token, ttl }));
45
+
46
+ return token;
47
+ },
48
+ onError: () => {
49
+ return dispatch(authApi.endpoints.logout.initiate()).unwrap();
50
+ },
51
+ };
52
+
53
+ apiService.useInterceptors({
54
+ request: [[onRequestRefreshTokenInterceptor(options)]],
55
+ response: [[null, onResponseRefreshTokenInterceptor(options)]],
56
+ });
57
+ },
58
+ });
59
+
60
+ authListenerMiddleware.startListening({
61
+ matcher: isAnyOf(authApi.endpoints.login.matchFulfilled, authApi.endpoints.register.matchFulfilled),
62
+ effect: async ({ payload: { token, ttl } }: { payload: LogInResponse }, { dispatch }) => {
63
+ dispatch(authActions.saveToken({ token, ttl }));
64
+ appStorageService.isAuthenticated.set('true');
65
+ dispatch(authActions.setIsAuthenticated(true));
66
+ },
67
+ });
68
+
69
+ authListenerMiddleware.startListening({
70
+ matcher: isAnyOf(authApi.endpoints.logout.matchFulfilled, authApi.endpoints.logout.matchRejected),
71
+ effect: async (_, { dispatch }) => {
72
+ appStorageService.isAuthenticated.remove();
73
+ appStorageService.tokenExpiresAt.remove();
74
+ appStorageService.token.remove();
75
+
76
+ dispatch(authActions.setIsAuthenticated(false));
77
+ dispatch(authActions.setTokenExpiresAt(null));
78
+ dispatch(authActions.setToken(null));
79
+ },
80
+ });
81
+
82
+ authListenerMiddleware.startListening({
83
+ actionCreator: authActions.saveToken,
84
+ effect: async ({ payload: { token, ttl } }, { dispatch }) => {
85
+ const tokenExpires = DateTime.local().plus({ minutes: ttl });
86
+
87
+ appStorageService.tokenExpiresAt.set(tokenExpires.toISO());
88
+ appStorageService.token.set(token);
89
+
90
+ dispatch(authActions.setToken(token));
91
+ dispatch(authActions.setTokenExpiresAt(tokenExpires));
92
+ },
93
+ });
@@ -0,0 +1,50 @@
1
+ import { PayloadAction, createSlice, createAction } from '@reduxjs/toolkit';
2
+ import { DateTime } from 'luxon';
3
+
4
+ export interface AuthState {
5
+ isAuthenticated: boolean | null;
6
+ isAppReady: boolean;
7
+ token: string | null;
8
+ tokenExpiresAt: DateTime | null;
9
+ }
10
+
11
+ const initialState: AuthState = {
12
+ isAuthenticated: null,
13
+ isAppReady: false,
14
+ token: null,
15
+ tokenExpiresAt: null,
16
+ };
17
+
18
+ const authSlice = createSlice({
19
+ name: 'authState',
20
+ initialState,
21
+ reducers: {
22
+ setIsAuthenticated(state, { payload }: PayloadAction<boolean>) {
23
+ state.isAuthenticated = payload;
24
+ },
25
+ setToken(state, { payload }: PayloadAction<string | null>) {
26
+ state.token = payload;
27
+ },
28
+ setIsAppReady(state, { payload }: PayloadAction<boolean>) {
29
+ state.isAppReady = payload;
30
+ },
31
+ setTokenExpiresAt(state, { payload }: PayloadAction<DateTime | null>) {
32
+ state.tokenExpiresAt = payload;
33
+ },
34
+ },
35
+ selectors: {
36
+ isAuthenticated: (state) => state.isAuthenticated,
37
+ isAppReady: (state) => state.isAppReady,
38
+ token: (state) => state.token,
39
+ tokenExpiresAt: (state) => state.tokenExpiresAt,
40
+ },
41
+ });
42
+
43
+ export const authActions = {
44
+ ...authSlice.actions,
45
+ saveToken: createAction<{ token: string | null; ttl: number }>('authState/saveToken'),
46
+ };
47
+
48
+ export const authReducer = authSlice.reducer;
49
+ export const authReducerPath = authSlice.name;
50
+ export const authSelectors = authSlice.selectors;