@application-kit/module-manifest 0.0.0-stage → 0.1.1

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 (61) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/LICENSE +21 -0
  3. package/README.md +89 -2
  4. package/dist/cjs/ability-grants-manifest.interface.d.ts +4 -0
  5. package/dist/cjs/ability-grants-manifest.interface.js +2 -0
  6. package/dist/cjs/collect-modules.d.ts +6 -0
  7. package/dist/cjs/collect-modules.js +25 -0
  8. package/dist/cjs/consumer-module-manifest.interface.d.ts +4 -0
  9. package/dist/cjs/consumer-module-manifest.interface.js +2 -0
  10. package/dist/cjs/errors/duplicate-module-name.error.d.ts +3 -0
  11. package/dist/cjs/errors/duplicate-module-name.error.js +10 -0
  12. package/dist/cjs/errors/index.d.ts +1 -0
  13. package/dist/cjs/errors/index.js +17 -0
  14. package/dist/cjs/index.d.ts +6 -0
  15. package/dist/cjs/index.js +22 -0
  16. package/dist/cjs/module-manifest.interface.d.ts +6 -0
  17. package/dist/cjs/module-manifest.interface.js +2 -0
  18. package/dist/cjs/nest/create-module-registry-provider.d.ts +5 -0
  19. package/dist/cjs/nest/create-module-registry-provider.js +12 -0
  20. package/dist/cjs/nest/index.d.ts +1 -0
  21. package/dist/cjs/nest/index.js +17 -0
  22. package/dist/cjs/package.json +3 -0
  23. package/dist/cjs/process-module-manifest.interface.d.ts +5 -0
  24. package/dist/cjs/process-module-manifest.interface.js +2 -0
  25. package/dist/cjs/vite-plugin/errors/index.d.ts +1 -0
  26. package/dist/cjs/vite-plugin/errors/index.js +17 -0
  27. package/dist/cjs/vite-plugin/errors/missing-module-entries-placeholder.error.d.ts +3 -0
  28. package/dist/cjs/vite-plugin/errors/missing-module-entries-placeholder.error.js +10 -0
  29. package/dist/cjs/vite-plugin/index.d.ts +2 -0
  30. package/dist/cjs/vite-plugin/index.js +18 -0
  31. package/dist/cjs/vite-plugin/vite-plugin-module-entries.d.ts +9 -0
  32. package/dist/cjs/vite-plugin/vite-plugin-module-entries.js +42 -0
  33. package/dist/esm/ability-grants-manifest.interface.d.ts +4 -0
  34. package/dist/esm/ability-grants-manifest.interface.js +1 -0
  35. package/dist/esm/collect-modules.d.ts +6 -0
  36. package/dist/esm/collect-modules.js +19 -0
  37. package/dist/esm/consumer-module-manifest.interface.d.ts +4 -0
  38. package/dist/esm/consumer-module-manifest.interface.js +1 -0
  39. package/dist/esm/errors/duplicate-module-name.error.d.ts +3 -0
  40. package/dist/esm/errors/duplicate-module-name.error.js +6 -0
  41. package/dist/esm/errors/index.d.ts +1 -0
  42. package/dist/esm/errors/index.js +1 -0
  43. package/dist/esm/index.d.ts +6 -0
  44. package/dist/esm/index.js +6 -0
  45. package/dist/esm/module-manifest.interface.d.ts +6 -0
  46. package/dist/esm/module-manifest.interface.js +1 -0
  47. package/dist/esm/nest/create-module-registry-provider.d.ts +5 -0
  48. package/dist/esm/nest/create-module-registry-provider.js +8 -0
  49. package/dist/esm/nest/index.d.ts +1 -0
  50. package/dist/esm/nest/index.js +1 -0
  51. package/dist/esm/process-module-manifest.interface.d.ts +5 -0
  52. package/dist/esm/process-module-manifest.interface.js +1 -0
  53. package/dist/esm/vite-plugin/errors/index.d.ts +1 -0
  54. package/dist/esm/vite-plugin/errors/index.js +1 -0
  55. package/dist/esm/vite-plugin/errors/missing-module-entries-placeholder.error.d.ts +3 -0
  56. package/dist/esm/vite-plugin/errors/missing-module-entries-placeholder.error.js +6 -0
  57. package/dist/esm/vite-plugin/index.d.ts +2 -0
  58. package/dist/esm/vite-plugin/index.js +2 -0
  59. package/dist/esm/vite-plugin/vite-plugin-module-entries.d.ts +9 -0
  60. package/dist/esm/vite-plugin/vite-plugin-module-entries.js +33 -0
  61. package/package.json +105 -3
package/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ # @application-kit/module-manifest
2
+
3
+ ## 0.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 8e10f98: Peer-зависимости принимают Nest 12, `@nestjs/graphql` и `@nestjs/mercurius` 14, `@nestjs/cqrs` 12 и `nestjs-pino` 5. `PinoLoggerConfig` задаёт `forRoutes` явно: с маршрутом nestjs-pino 5 по умолчанию запросы на Fastify не логировались.
8
+
9
+ ## 0.1.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 2db129d: Первый выпуск: контракты манифестов модуля (web, CLI, консьюмер, гранты с типом карты параметром), сборщики `collectWebModules`, `collectClientWebModules`, `collectProcessModules` с `DuplicateModuleNameError`; вход `/nest` — `createModuleRegistryProvider` с типом навигации параметром; вход `/vite-plugin` — `vitePluginModuleEntries` для клиентских entry модулей по раскладке.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 application-kit
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,90 @@
1
- # Temporary Holding Version
1
+ # @application-kit/module-manifest
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Манифест модуля продукта: модуль сообщает сборке о себе файлами в своём корне, а приложение подключает его одной
4
+ строкой в реестре процесса. Пакет даёт контракты этих файлов, сборщики модулей процесса с проверкой дублей имён,
5
+ SSR-реестр клиентских модулей для NestJS и Vite-плагин, который находит клиентские entry по раскладке. Имён модулей,
6
+ типа навигации и карты грантов продукта в пакете нет: реестры ведёт приложение, типы приходят параметрами.
7
+
8
+ ## Установка
9
+
10
+ ```sh
11
+ yarn add @application-kit/module-manifest
12
+ ```
13
+
14
+ Peer-зависимости: `@nestjs/common`; для входа `/nest` — `@libs-for-dev/vue-modular-application` и `vue-router`; для входа
15
+ `/vite-plugin` — `vite` (только типы).
16
+
17
+ ## Входы
18
+
19
+ | Вход | Для чего | Тянет |
20
+ |------|----------|-------|
21
+ | `@application-kit/module-manifest` | контракты манифестов, сборщики `collect*Modules`, `DuplicateModuleNameError` | ничего (типы `@nestjs/common`) |
22
+ | `@application-kit/module-manifest/nest` | `createModuleRegistryProvider` — SSR-реестр клиентских модулей | `@libs-for-dev/vue-modular-application` |
23
+ | `@application-kit/module-manifest/vite-plugin` | `vitePluginModuleEntries` — script-теги клиентских entry в `index.html` | `node:fs`, `node:path` (типы `vite`) |
24
+
25
+ Импорт любого входа не имеет побочных эффектов и не требует окружения. Входы разделены по рантайм-графу: сборщики грузят
26
+ CLI- и консьюмер-процессы, и корень с `ModuleRegistry` втянул бы в них Vue, а `vite.config` — Nest.
27
+
28
+ ## Файлы модуля
29
+
30
+ | Файл в корне модуля | Контракт | Процесс |
31
+ |---------------------|----------|---------|
32
+ | `module.manifest.ts` | `ModuleManifestInterface` — `name`, `web`, `clientModuleToken?` | web |
33
+ | `module.cli.ts` | `ProcessModuleManifestInterface` — `name`, `module` | CLI |
34
+ | `module.consumers.ts` | `ConsumerModuleManifestInterface` — плюс `queues` | консьюмер |
35
+ | `module.grants.ts` | `AbilityGrantsManifestInterface<TGrants>` — `name`, `grants` | web и браузер |
36
+
37
+ Файл на процесс, а не поля одного манифеста: конфиги модулей валидируют окружение на импорте, и общий манифест тянул бы
38
+ в процесс чужой граф с чужим окружением. `name` равен имени папки модуля — по нему модуль включают из окружения.
39
+
40
+ ## Сборка процесса
41
+
42
+ ```ts
43
+ import { collectProcessModules, collectWebModules } from '@application-kit/module-manifest'
44
+
45
+ @Module({ imports: [CommonWebModule, ...collectWebModules(MODULE_MANIFESTS)] })
46
+ export class AppModule {}
47
+
48
+ @Module({ imports: [ConsoleModule, ...collectProcessModules(CLI_MANIFESTS)] })
49
+ export class CliModule {}
50
+ ```
51
+
52
+ Сборщики сохраняют порядок регистрации и бросают `DuplicateModuleNameError`, если имя встречается дважды: включение
53
+ по имени иначе стало бы неоднозначным. `collectClientWebModules` отдаёт web-модули только тех модулей, у которых есть
54
+ `clientModuleToken`, — их импортирует оболочка, чтобы резолвить клиентские модули.
55
+
56
+ ## SSR-реестр клиентских модулей
57
+
58
+ ```ts
59
+ import { collectClientWebModules } from '@application-kit/module-manifest'
60
+ import { createModuleRegistryProvider } from '@application-kit/module-manifest/nest'
61
+
62
+ @Module({
63
+ imports: collectClientWebModules(MODULE_MANIFESTS),
64
+ providers: [createModuleRegistryProvider(MODULE_MANIFESTS, () => new ClientVueModule())],
65
+ })
66
+ export class ClientModule {}
67
+ ```
68
+
69
+ Провайдер `ModuleRegistry` собирает оболочку первой, затем клиентские модули по токенам манифестов в порядке
70
+ регистрации — тот же порядок, что у script-тегов в браузере. Тип навигации реестра (`TNavigation`) выводится из
71
+ клиентского модуля оболочки (`ClientModuleInterface<RouteRecordRaw[], TNavigation>` из `vue-modular-application`).
72
+
73
+ ## Клиентские entry
74
+
75
+ ```ts
76
+ import { vitePluginModuleEntries } from '@application-kit/module-manifest/vite-plugin'
77
+
78
+ export default defineConfig({
79
+ plugins: [vitePluginModuleEntries({ modulesDirectory: path.resolve(root, 'src/modules'), root })],
80
+ })
81
+ ```
82
+
83
+ Плагин заменяет в `index.html` плейсхолдер `<!-- module-entries -->` (`MODULE_ENTRIES_PLACEHOLDER`) script-тегами
84
+ файлов `<modulesDirectory>/<name>/user-interface/client/app/entry.<name>.ts` в порядке имён модулей. Entry с чужим
85
+ именем не принимается — опечатка не оставит модуль без клиента молча. Нет плейсхолдера — сборка падает с
86
+ `MissingModuleEntriesPlaceholderError`. Список берётся из раскладки, а не из манифестов: манифест тянет Nest-модуль и в
87
+ процесс Vite не импортируется.
88
+
89
+ Без Vite — те же шаги функциями: `findModuleEntries(modulesDirectory)` отдаёт пути entry в порядке имён модулей,
90
+ `injectModuleEntries(html, { modulesDirectory, root })` — разметку с тегами на месте плейсхолдера.
@@ -0,0 +1,4 @@
1
+ export interface AbilityGrantsManifestInterface<TGrants> {
2
+ readonly grants: TGrants;
3
+ readonly name: string;
4
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,6 @@
1
+ import type { Type } from '@nestjs/common';
2
+ import type { ModuleManifestInterface } from './module-manifest.interface.js';
3
+ import type { ProcessModuleManifestInterface } from './process-module-manifest.interface.js';
4
+ export declare const collectProcessModules: (manifests: readonly ProcessModuleManifestInterface[]) => Type[];
5
+ export declare const collectWebModules: (manifests: readonly ModuleManifestInterface[]) => Type[];
6
+ export declare const collectClientWebModules: (manifests: readonly ModuleManifestInterface[]) => Type[];
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.collectClientWebModules = exports.collectWebModules = exports.collectProcessModules = void 0;
4
+ const duplicate_module_name_error_js_1 = require("./errors/duplicate-module-name.error.js");
5
+ const assertUniqueModuleNames = (manifests) => {
6
+ const seen = new Set();
7
+ for (const { name } of manifests) {
8
+ if (seen.has(name)) {
9
+ throw new duplicate_module_name_error_js_1.DuplicateModuleNameError(name);
10
+ }
11
+ seen.add(name);
12
+ }
13
+ };
14
+ const collectProcessModules = (manifests) => {
15
+ assertUniqueModuleNames(manifests);
16
+ return manifests.map((manifest) => manifest.module);
17
+ };
18
+ exports.collectProcessModules = collectProcessModules;
19
+ const collectWebModules = (manifests) => {
20
+ assertUniqueModuleNames(manifests);
21
+ return manifests.map((manifest) => manifest.web);
22
+ };
23
+ exports.collectWebModules = collectWebModules;
24
+ const collectClientWebModules = (manifests) => (0, exports.collectWebModules)(manifests.filter((manifest) => manifest.clientModuleToken !== undefined));
25
+ exports.collectClientWebModules = collectClientWebModules;
@@ -0,0 +1,4 @@
1
+ import type { ProcessModuleManifestInterface } from './process-module-manifest.interface.js';
2
+ export interface ConsumerModuleManifestInterface extends ProcessModuleManifestInterface {
3
+ readonly queues: readonly string[];
4
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,3 @@
1
+ export declare class DuplicateModuleNameError extends Error {
2
+ constructor(name: string, options?: ErrorOptions);
3
+ }
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DuplicateModuleNameError = void 0;
4
+ class DuplicateModuleNameError extends Error {
5
+ constructor(name, options) {
6
+ super(`Module manifest "${name}" is registered twice`, options);
7
+ this.name = 'DuplicateModuleNameError';
8
+ }
9
+ }
10
+ exports.DuplicateModuleNameError = DuplicateModuleNameError;
@@ -0,0 +1 @@
1
+ export * from './duplicate-module-name.error.js';
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./duplicate-module-name.error.js"), exports);
@@ -0,0 +1,6 @@
1
+ export * from './errors/index.js';
2
+ export * from './ability-grants-manifest.interface.js';
3
+ export * from './collect-modules.js';
4
+ export * from './consumer-module-manifest.interface.js';
5
+ export * from './module-manifest.interface.js';
6
+ export * from './process-module-manifest.interface.js';
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./errors/index.js"), exports);
18
+ __exportStar(require("./ability-grants-manifest.interface.js"), exports);
19
+ __exportStar(require("./collect-modules.js"), exports);
20
+ __exportStar(require("./consumer-module-manifest.interface.js"), exports);
21
+ __exportStar(require("./module-manifest.interface.js"), exports);
22
+ __exportStar(require("./process-module-manifest.interface.js"), exports);
@@ -0,0 +1,6 @@
1
+ import type { InjectionToken, Type } from '@nestjs/common';
2
+ export interface ModuleManifestInterface {
3
+ readonly clientModuleToken?: InjectionToken;
4
+ readonly name: string;
5
+ readonly web: Type;
6
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,5 @@
1
+ import type { ClientModuleInterface } from '@libs-for-dev/vue-modular-application';
2
+ import type { Provider } from '@nestjs/common';
3
+ import type { RouteRecordRaw } from 'vue-router';
4
+ import type { ModuleManifestInterface } from '../module-manifest.interface.js';
5
+ export declare const createModuleRegistryProvider: <TNavigation>(manifests: readonly ModuleManifestInterface[], createHostModule: () => ClientModuleInterface<RouteRecordRaw[], TNavigation>) => Provider;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createModuleRegistryProvider = void 0;
4
+ const vue_modular_application_1 = require("@libs-for-dev/vue-modular-application");
5
+ const collectClientModuleTokens = (manifests) => manifests
6
+ .flatMap((manifest) => (manifest.clientModuleToken === undefined ? [] : [manifest.clientModuleToken]));
7
+ const createModuleRegistryProvider = (manifests, createHostModule) => ({
8
+ inject: collectClientModuleTokens(manifests),
9
+ provide: vue_modular_application_1.ModuleRegistry,
10
+ useFactory: (...clientModules) => new vue_modular_application_1.ModuleRegistry([createHostModule(), ...clientModules]),
11
+ });
12
+ exports.createModuleRegistryProvider = createModuleRegistryProvider;
@@ -0,0 +1 @@
1
+ export * from './create-module-registry-provider.js';
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./create-module-registry-provider.js"), exports);
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -0,0 +1,5 @@
1
+ import type { Type } from '@nestjs/common';
2
+ export interface ProcessModuleManifestInterface {
3
+ readonly module: Type;
4
+ readonly name: string;
5
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1 @@
1
+ export * from './missing-module-entries-placeholder.error.js';
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./missing-module-entries-placeholder.error.js"), exports);
@@ -0,0 +1,3 @@
1
+ export declare class MissingModuleEntriesPlaceholderError extends Error {
2
+ constructor(placeholder: string, options?: ErrorOptions);
3
+ }
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MissingModuleEntriesPlaceholderError = void 0;
4
+ class MissingModuleEntriesPlaceholderError extends Error {
5
+ constructor(placeholder, options) {
6
+ super(`index.html has no "${placeholder}" placeholder for module client entries`, options);
7
+ this.name = 'MissingModuleEntriesPlaceholderError';
8
+ }
9
+ }
10
+ exports.MissingModuleEntriesPlaceholderError = MissingModuleEntriesPlaceholderError;
@@ -0,0 +1,2 @@
1
+ export * from './errors/index.js';
2
+ export * from './vite-plugin-module-entries.js';
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./errors/index.js"), exports);
18
+ __exportStar(require("./vite-plugin-module-entries.js"), exports);
@@ -0,0 +1,9 @@
1
+ import type { Plugin } from 'vite';
2
+ export declare const MODULE_ENTRIES_PLACEHOLDER = "<!-- module-entries -->";
3
+ export interface ModuleEntriesOptionsInterface {
4
+ modulesDirectory: string;
5
+ root: string;
6
+ }
7
+ export declare const findModuleEntries: (modulesDirectory: string) => Promise<string[]>;
8
+ export declare const injectModuleEntries: (source: string, { modulesDirectory, root }: ModuleEntriesOptionsInterface) => Promise<string>;
9
+ export declare const vitePluginModuleEntries: (options: ModuleEntriesOptionsInterface) => Plugin;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.vitePluginModuleEntries = exports.injectModuleEntries = exports.findModuleEntries = exports.MODULE_ENTRIES_PLACEHOLDER = void 0;
7
+ const promises_1 = require("node:fs/promises");
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const missing_module_entries_placeholder_error_js_1 = require("./errors/missing-module-entries-placeholder.error.js");
10
+ exports.MODULE_ENTRIES_PLACEHOLDER = '<!-- module-entries -->';
11
+ const CLIENT_ENTRY_DIRECTORY = node_path_1.default.join('user-interface', 'client', 'app');
12
+ const moduleEntryOf = (modulesDirectory, file) => {
13
+ const [name = ''] = node_path_1.default.relative(modulesDirectory, file.parentPath).split(node_path_1.default.sep);
14
+ const entry = node_path_1.default.join(modulesDirectory, name, CLIENT_ENTRY_DIRECTORY, `entry.${name}.ts`);
15
+ return file.isFile() && node_path_1.default.join(file.parentPath, file.name) === entry ? entry : null;
16
+ };
17
+ const findModuleEntries = async (modulesDirectory) => {
18
+ const files = await (0, promises_1.readdir)(modulesDirectory, { recursive: true, withFileTypes: true });
19
+ const entries = files.flatMap((file) => {
20
+ const entry = moduleEntryOf(modulesDirectory, file);
21
+ return entry === null ? [] : [entry];
22
+ });
23
+ return entries.toSorted((left, right) => left.localeCompare(right));
24
+ };
25
+ exports.findModuleEntries = findModuleEntries;
26
+ const injectModuleEntries = async (source, { modulesDirectory, root }) => {
27
+ if (!source.includes(exports.MODULE_ENTRIES_PLACEHOLDER)) {
28
+ throw new missing_module_entries_placeholder_error_js_1.MissingModuleEntriesPlaceholderError(exports.MODULE_ENTRIES_PLACEHOLDER);
29
+ }
30
+ const entries = await (0, exports.findModuleEntries)(modulesDirectory);
31
+ const tags = entries.map((entry) => `<script type="module" src="/${node_path_1.default.relative(root, entry)}"></script>`);
32
+ return source.replace(exports.MODULE_ENTRIES_PLACEHOLDER, () => tags.join('\n '));
33
+ };
34
+ exports.injectModuleEntries = injectModuleEntries;
35
+ const vitePluginModuleEntries = (options) => ({
36
+ name: 'module-entries',
37
+ transformIndexHtml: {
38
+ handler: async (source) => (0, exports.injectModuleEntries)(source, options),
39
+ order: 'pre',
40
+ },
41
+ });
42
+ exports.vitePluginModuleEntries = vitePluginModuleEntries;
@@ -0,0 +1,4 @@
1
+ export interface AbilityGrantsManifestInterface<TGrants> {
2
+ readonly grants: TGrants;
3
+ readonly name: string;
4
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ import type { Type } from '@nestjs/common';
2
+ import type { ModuleManifestInterface } from './module-manifest.interface.js';
3
+ import type { ProcessModuleManifestInterface } from './process-module-manifest.interface.js';
4
+ export declare const collectProcessModules: (manifests: readonly ProcessModuleManifestInterface[]) => Type[];
5
+ export declare const collectWebModules: (manifests: readonly ModuleManifestInterface[]) => Type[];
6
+ export declare const collectClientWebModules: (manifests: readonly ModuleManifestInterface[]) => Type[];
@@ -0,0 +1,19 @@
1
+ import { DuplicateModuleNameError } from './errors/duplicate-module-name.error.js';
2
+ const assertUniqueModuleNames = (manifests) => {
3
+ const seen = new Set();
4
+ for (const { name } of manifests) {
5
+ if (seen.has(name)) {
6
+ throw new DuplicateModuleNameError(name);
7
+ }
8
+ seen.add(name);
9
+ }
10
+ };
11
+ export const collectProcessModules = (manifests) => {
12
+ assertUniqueModuleNames(manifests);
13
+ return manifests.map((manifest) => manifest.module);
14
+ };
15
+ export const collectWebModules = (manifests) => {
16
+ assertUniqueModuleNames(manifests);
17
+ return manifests.map((manifest) => manifest.web);
18
+ };
19
+ export const collectClientWebModules = (manifests) => collectWebModules(manifests.filter((manifest) => manifest.clientModuleToken !== undefined));
@@ -0,0 +1,4 @@
1
+ import type { ProcessModuleManifestInterface } from './process-module-manifest.interface.js';
2
+ export interface ConsumerModuleManifestInterface extends ProcessModuleManifestInterface {
3
+ readonly queues: readonly string[];
4
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ export declare class DuplicateModuleNameError extends Error {
2
+ constructor(name: string, options?: ErrorOptions);
3
+ }
@@ -0,0 +1,6 @@
1
+ export class DuplicateModuleNameError extends Error {
2
+ constructor(name, options) {
3
+ super(`Module manifest "${name}" is registered twice`, options);
4
+ this.name = 'DuplicateModuleNameError';
5
+ }
6
+ }
@@ -0,0 +1 @@
1
+ export * from './duplicate-module-name.error.js';
@@ -0,0 +1 @@
1
+ export * from './duplicate-module-name.error.js';
@@ -0,0 +1,6 @@
1
+ export * from './errors/index.js';
2
+ export * from './ability-grants-manifest.interface.js';
3
+ export * from './collect-modules.js';
4
+ export * from './consumer-module-manifest.interface.js';
5
+ export * from './module-manifest.interface.js';
6
+ export * from './process-module-manifest.interface.js';
@@ -0,0 +1,6 @@
1
+ export * from './errors/index.js';
2
+ export * from './ability-grants-manifest.interface.js';
3
+ export * from './collect-modules.js';
4
+ export * from './consumer-module-manifest.interface.js';
5
+ export * from './module-manifest.interface.js';
6
+ export * from './process-module-manifest.interface.js';
@@ -0,0 +1,6 @@
1
+ import type { InjectionToken, Type } from '@nestjs/common';
2
+ export interface ModuleManifestInterface {
3
+ readonly clientModuleToken?: InjectionToken;
4
+ readonly name: string;
5
+ readonly web: Type;
6
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ import type { ClientModuleInterface } from '@libs-for-dev/vue-modular-application';
2
+ import type { Provider } from '@nestjs/common';
3
+ import type { RouteRecordRaw } from 'vue-router';
4
+ import type { ModuleManifestInterface } from '../module-manifest.interface.js';
5
+ export declare const createModuleRegistryProvider: <TNavigation>(manifests: readonly ModuleManifestInterface[], createHostModule: () => ClientModuleInterface<RouteRecordRaw[], TNavigation>) => Provider;
@@ -0,0 +1,8 @@
1
+ import { ModuleRegistry } from '@libs-for-dev/vue-modular-application';
2
+ const collectClientModuleTokens = (manifests) => manifests
3
+ .flatMap((manifest) => (manifest.clientModuleToken === undefined ? [] : [manifest.clientModuleToken]));
4
+ export const createModuleRegistryProvider = (manifests, createHostModule) => ({
5
+ inject: collectClientModuleTokens(manifests),
6
+ provide: ModuleRegistry,
7
+ useFactory: (...clientModules) => new ModuleRegistry([createHostModule(), ...clientModules]),
8
+ });
@@ -0,0 +1 @@
1
+ export * from './create-module-registry-provider.js';
@@ -0,0 +1 @@
1
+ export * from './create-module-registry-provider.js';
@@ -0,0 +1,5 @@
1
+ import type { Type } from '@nestjs/common';
2
+ export interface ProcessModuleManifestInterface {
3
+ readonly module: Type;
4
+ readonly name: string;
5
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export * from './missing-module-entries-placeholder.error.js';
@@ -0,0 +1 @@
1
+ export * from './missing-module-entries-placeholder.error.js';
@@ -0,0 +1,3 @@
1
+ export declare class MissingModuleEntriesPlaceholderError extends Error {
2
+ constructor(placeholder: string, options?: ErrorOptions);
3
+ }
@@ -0,0 +1,6 @@
1
+ export class MissingModuleEntriesPlaceholderError extends Error {
2
+ constructor(placeholder, options) {
3
+ super(`index.html has no "${placeholder}" placeholder for module client entries`, options);
4
+ this.name = 'MissingModuleEntriesPlaceholderError';
5
+ }
6
+ }
@@ -0,0 +1,2 @@
1
+ export * from './errors/index.js';
2
+ export * from './vite-plugin-module-entries.js';
@@ -0,0 +1,2 @@
1
+ export * from './errors/index.js';
2
+ export * from './vite-plugin-module-entries.js';
@@ -0,0 +1,9 @@
1
+ import type { Plugin } from 'vite';
2
+ export declare const MODULE_ENTRIES_PLACEHOLDER = "<!-- module-entries -->";
3
+ export interface ModuleEntriesOptionsInterface {
4
+ modulesDirectory: string;
5
+ root: string;
6
+ }
7
+ export declare const findModuleEntries: (modulesDirectory: string) => Promise<string[]>;
8
+ export declare const injectModuleEntries: (source: string, { modulesDirectory, root }: ModuleEntriesOptionsInterface) => Promise<string>;
9
+ export declare const vitePluginModuleEntries: (options: ModuleEntriesOptionsInterface) => Plugin;
@@ -0,0 +1,33 @@
1
+ import { readdir } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { MissingModuleEntriesPlaceholderError } from './errors/missing-module-entries-placeholder.error.js';
4
+ export const MODULE_ENTRIES_PLACEHOLDER = '<!-- module-entries -->';
5
+ const CLIENT_ENTRY_DIRECTORY = path.join('user-interface', 'client', 'app');
6
+ const moduleEntryOf = (modulesDirectory, file) => {
7
+ const [name = ''] = path.relative(modulesDirectory, file.parentPath).split(path.sep);
8
+ const entry = path.join(modulesDirectory, name, CLIENT_ENTRY_DIRECTORY, `entry.${name}.ts`);
9
+ return file.isFile() && path.join(file.parentPath, file.name) === entry ? entry : null;
10
+ };
11
+ export const findModuleEntries = async (modulesDirectory) => {
12
+ const files = await readdir(modulesDirectory, { recursive: true, withFileTypes: true });
13
+ const entries = files.flatMap((file) => {
14
+ const entry = moduleEntryOf(modulesDirectory, file);
15
+ return entry === null ? [] : [entry];
16
+ });
17
+ return entries.toSorted((left, right) => left.localeCompare(right));
18
+ };
19
+ export const injectModuleEntries = async (source, { modulesDirectory, root }) => {
20
+ if (!source.includes(MODULE_ENTRIES_PLACEHOLDER)) {
21
+ throw new MissingModuleEntriesPlaceholderError(MODULE_ENTRIES_PLACEHOLDER);
22
+ }
23
+ const entries = await findModuleEntries(modulesDirectory);
24
+ const tags = entries.map((entry) => `<script type="module" src="/${path.relative(root, entry)}"></script>`);
25
+ return source.replace(MODULE_ENTRIES_PLACEHOLDER, () => tags.join('\n '));
26
+ };
27
+ export const vitePluginModuleEntries = (options) => ({
28
+ name: 'module-entries',
29
+ transformIndexHtml: {
30
+ handler: async (source) => injectModuleEntries(source, options),
31
+ order: 'pre',
32
+ },
33
+ });
package/package.json CHANGED
@@ -1,6 +1,108 @@
1
1
  {
2
2
  "name": "@application-kit/module-manifest",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.1.1",
4
+ "description": "Манифест модуля продукта: контракты web-, CLI-, консьюмер- и грант-манифестов, сборщики модулей процесса с проверкой дублей, SSR-реестр клиентских модулей для NestJS и Vite-плагин клиентских entry по раскладке",
5
+ "keywords": [
6
+ "manifest",
7
+ "modules",
8
+ "nestjs",
9
+ "vite-plugin"
10
+ ],
11
+ "homepage": "https://gitlab.com/application-kit/application-kit/-/tree/main/packages/module-manifest",
12
+ "bugs": "https://gitlab.com/application-kit/application-kit/-/issues",
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://gitlab.com/application-kit/application-kit.git",
16
+ "directory": "packages/module-manifest"
17
+ },
18
+ "license": "MIT",
19
+ "author": {
20
+ "name": "application-kit"
21
+ },
22
+ "sideEffects": false,
23
+ "type": "module",
24
+ "exports": {
25
+ ".": {
26
+ "import": {
27
+ "types": "./dist/esm/index.d.ts",
28
+ "default": "./dist/esm/index.js"
29
+ },
30
+ "require": {
31
+ "types": "./dist/cjs/index.d.ts",
32
+ "default": "./dist/cjs/index.js"
33
+ }
34
+ },
35
+ "./nest": {
36
+ "import": {
37
+ "types": "./dist/esm/nest/index.d.ts",
38
+ "default": "./dist/esm/nest/index.js"
39
+ },
40
+ "require": {
41
+ "types": "./dist/cjs/nest/index.d.ts",
42
+ "default": "./dist/cjs/nest/index.js"
43
+ }
44
+ },
45
+ "./package.json": "./package.json",
46
+ "./vite-plugin": {
47
+ "import": {
48
+ "types": "./dist/esm/vite-plugin/index.d.ts",
49
+ "default": "./dist/esm/vite-plugin/index.js"
50
+ },
51
+ "require": {
52
+ "types": "./dist/cjs/vite-plugin/index.d.ts",
53
+ "default": "./dist/cjs/vite-plugin/index.js"
54
+ }
55
+ }
56
+ },
57
+ "main": "./dist/cjs/index.js",
58
+ "module": "./dist/esm/index.js",
59
+ "types": "./dist/cjs/index.d.ts",
60
+ "files": [
61
+ "dist"
62
+ ],
63
+ "scripts": {
64
+ "build": "rm -rf ./dist && node ../../scripts/barrels.mjs create ./src --entry-only=nest,vite-plugin && tsc --project tsconfig.build.json && tsc --project tsconfig.build.cjs.json && node ../../scripts/barrels.mjs clean ./src && node ../../scripts/mark-cjs.mjs ./dist/cjs",
65
+ "lint:tsc": "tsc --noEmit --pretty --project .",
66
+ "test:mutation": "stryker run",
67
+ "test:unit": "vitest run"
68
+ },
69
+ "devDependencies": {
70
+ "@libs-for-dev/vue-modular-application": "1.0.0",
71
+ "@nestjs/common": "^12.0.0",
72
+ "@nestjs/core": "^12.0.0",
73
+ "@nestjs/testing": "^12.0.0",
74
+ "@stryker-mutator/core": "^10.0.0",
75
+ "@stryker-mutator/vitest-runner": "^10.0.0",
76
+ "@types/node": "^26.2.0",
77
+ "reflect-metadata": "^0.2.2",
78
+ "rxjs": "^7.8.2",
79
+ "typescript": "^6.0.3",
80
+ "vite": "^8.2.1",
81
+ "vitest": "^5.0.0",
82
+ "vue": "^3.5.41",
83
+ "vue-router": "^5.2.0"
84
+ },
85
+ "peerDependencies": {
86
+ "@libs-for-dev/vue-modular-application": "^1.0.0",
87
+ "@nestjs/common": "^11.0.0 || ^12.0.0",
88
+ "vite": "^8.0.0",
89
+ "vue-router": "^5.0.0"
90
+ },
91
+ "peerDependenciesMeta": {
92
+ "@libs-for-dev/vue-modular-application": {
93
+ "optional": true
94
+ },
95
+ "vite": {
96
+ "optional": true
97
+ },
98
+ "vue-router": {
99
+ "optional": true
100
+ }
101
+ },
102
+ "engines": {
103
+ "node": ">=24"
104
+ },
105
+ "publishConfig": {
106
+ "access": "public"
107
+ }
6
108
  }