libmodulor 0.26.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/README.md +1 -1
- package/dist/esm/apps/Helper/src/i18n.js +4 -4
- package/dist/esm/apps/Helper/src/lib/layers/project.js +7 -7
- package/dist/esm/apps/Helper/src/lib/layers/uc.js +1 -1
- package/dist/esm/apps/Helper/src/ucds/CreateAppUCD.js +5 -10
- package/dist/esm/apps/Helper/src/ucds/CreateProductUCD.js +5 -10
- package/dist/esm/apps/Helper/src/ucds/CreateTargetUCD.js +6 -11
- package/dist/esm/apps/Helper/src/ucds/TestAppUCD.js +5 -8
- package/dist/esm/convention.d.ts +1 -1
- package/dist/esm/convention.js +1 -1
- package/dist/esm/dt/DataType.d.ts +2 -1
- package/dist/esm/dt/DataTypes.d.ts +1 -1
- package/dist/esm/dt/DataTypes.js +1 -0
- package/dist/esm/dt/final/TErrorCode.d.ts +7 -0
- package/dist/esm/dt/final/TErrorCode.js +9 -0
- package/dist/esm/dt/index.d.ts +1 -0
- package/dist/esm/dt/index.js +1 -0
- package/dist/esm/error/CustomError.d.ts +1 -1
- package/dist/esm/error/CustomError.js +2 -2
- package/dist/esm/error/ForbiddenAsNotFoundError.js +1 -1
- package/dist/esm/error/ForbiddenError.js +1 -1
- package/dist/esm/error/IllegalArgumentError.js +2 -2
- package/dist/esm/error/InternalServerError.js +1 -1
- package/dist/esm/error/NotFoundError.js +1 -1
- package/dist/esm/error/UnauthorizedError.js +1 -1
- package/dist/esm/error/UnavailableError.d.ts +6 -0
- package/dist/esm/error/UnavailableError.js +9 -0
- package/dist/esm/error/funcs.js +2 -0
- package/dist/esm/error/index.d.ts +1 -0
- package/dist/esm/error/index.js +1 -0
- package/dist/esm/i18n/locales/de.js +8 -0
- package/dist/esm/i18n/locales/en.js +8 -0
- package/dist/esm/i18n/locales/es.js +8 -0
- package/dist/esm/i18n/locales/fr.js +8 -0
- package/dist/esm/i18n/types.d.ts +1 -1
- package/dist/esm/products/Helper/i18n.d.ts +8 -0
- package/dist/esm/std/impl/SimpleHTTPAPICaller.js +1 -1
- package/dist/esm/target/lib/cli/CommandExecutor.js +2 -2
- package/dist/esm/target/lib/cli/renderer.d.ts +2 -1
- package/dist/esm/target/lib/cli/renderer.js +10 -11
- package/dist/esm/target/lib/server/AuthenticationChecker.d.ts +3 -3
- package/dist/esm/target/lib/server/AuthenticationChecker.js +5 -5
- package/dist/esm/target/node-core-cli/NodeCoreCLIManager.js +1 -1
- package/dist/esm/target/react-web-pure/UCForm.d.ts +1 -1
- package/dist/esm/target/react-web-pure/UCForm.js +3 -2
- package/dist/esm/testing/workers/checkers/AppI18nChecker.js +4 -2
- package/dist/esm/uc/data-store.d.ts +9 -1
- package/dist/esm/uc/data-store.js +33 -1
- package/dist/esm/uc/impl/CloudflareD1UCDataStore.d.ts +2 -2
- package/dist/esm/uc/impl/CloudflareD1UCDataStore.js +7 -0
- package/dist/esm/uc/impl/InMemoryUCDataStore.d.ts +8 -3
- package/dist/esm/uc/impl/InMemoryUCDataStore.js +19 -3
- package/dist/esm/uc/impl/KnexUCDataStore.d.ts +2 -2
- package/dist/esm/uc/impl/KnexUCDataStore.js +10 -2
- package/dist/esm/uc/impl/SimpleUCManager.d.ts +4 -4
- package/dist/esm/uc/impl/SimpleUCManager.js +10 -10
- package/dist/esm/uc/settings/consts.js +1 -0
- package/dist/esm/uc/settings.d.ts +8 -1
- package/dist/esm/uc/workers/UCExecChecker.d.ts +3 -3
- package/dist/esm/uc/workers/UCExecChecker.js +5 -5
- package/dist/esm/utils/index.d.ts +1 -1
- package/dist/esm/utils/index.js +1 -1
- package/dist/esm/utils/ioc/bindCommon.js +4 -4
- package/dist/esm/utils/ioc/bindFactory.d.ts +2 -0
- package/dist/esm/utils/ioc/bindFactory.js +9 -0
- package/package.json +21 -20
- package/dist/esm/apps/Helper/src/lib/app.d.ts +0 -6
- package/dist/esm/apps/Helper/src/lib/app.js +0 -12
- package/dist/esm/apps/Helper/src/lib/project.d.ts +0 -3
- package/dist/esm/apps/Helper/src/lib/project.js +0 -163
- package/dist/esm/bundlers/vite/StripUCDLifecycleServerPlugin.d.ts +0 -2
- package/dist/esm/bundlers/vite/StripUCDLifecycleServerPlugin.js +0 -18
- package/dist/esm/products/Helper/cli-node-core/container.d.ts +0 -3
- package/dist/esm/products/Helper/cli-node-core/container.js +0 -26
- package/dist/esm/products/Helper/cli-node-core/index.d.ts +0 -1
- package/dist/esm/products/Helper/cli-node-core/index.js +0 -9
- package/dist/esm/products/Helper/container.d.ts +0 -3
- package/dist/esm/products/Helper/container.js +0 -26
- package/dist/esm/products/Helper/index.d.ts +0 -1
- package/dist/esm/products/Helper/index.js +0 -16
- package/dist/esm/target/lib/react/common.d.ts +0 -6
- package/dist/esm/target/lib/react/common.js +0 -1
- package/dist/esm/target/lib/server/RequestHandler.d.ts +0 -14
- package/dist/esm/target/lib/server/RequestHandler.js +0 -1
- package/dist/esm/target/lib/server-node/stop.d.ts +0 -2
- package/dist/esm/target/lib/server-node/stop.js +0 -18
- package/dist/esm/target/node-express-server/lib/AuthCookieCreator.d.ts +0 -21
- package/dist/esm/target/node-express-server/lib/AuthCookieCreator.js +0 -50
- package/dist/esm/target/node-express-server/middlewares/AuthenticationCheckerMiddlewareBuilder.d.ts +0 -21
- package/dist/esm/target/node-express-server/middlewares/AuthenticationCheckerMiddlewareBuilder.js +0 -61
- package/dist/esm/target/node-express-server/middlewares/ErrorMiddlewareBuilder.d.ts +0 -12
- package/dist/esm/target/node-express-server/middlewares/ErrorMiddlewareBuilder.js +0 -35
- package/dist/esm/target/node-express-server/middlewares/HelmetMiddlewareBuilder.d.ts +0 -12
- package/dist/esm/target/node-express-server/middlewares/HelmetMiddlewareBuilder.js +0 -39
- package/dist/esm/target/node-express-server/middlewares/PublicApiKeyCheckerMiddlewareBuilder.d.ts +0 -18
- package/dist/esm/target/node-express-server/middlewares/PublicApiKeyCheckerMiddlewareBuilder.js +0 -44
- package/dist/esm/target/node-express-server/middlewares/RequestCheckerMiddlewareBuilder.d.ts +0 -12
- package/dist/esm/target/node-express-server/middlewares/RequestCheckerMiddlewareBuilder.js +0 -36
- package/dist/esm/target/node-express-server/middlewares/RequestHandlerMiddlewareBuilder.d.ts +0 -23
- package/dist/esm/target/node-express-server/middlewares/RequestHandlerMiddlewareBuilder.js +0 -154
- package/dist/esm/target/node-express-server/middlewares/RequestLoggerMiddlewareBuilder.d.ts +0 -13
- package/dist/esm/target/node-express-server/middlewares/RequestLoggerMiddlewareBuilder.js +0 -46
- package/dist/esm/testing/impl/SimpleAppDocsEmitter.d.ts +0 -7
- package/dist/esm/testing/impl/SimpleAppDocsEmitter.js +0 -180
- package/dist/esm/testing/impl/SimpleAppTesterConfigurator.d.ts +0 -14
- package/dist/esm/testing/impl/SimpleAppTesterConfigurator.js +0 -35
- package/dist/esm/uc/utils/stripUCDLifecycleServer.d.ts +0 -15
- package/dist/esm/uc/utils/stripUCDLifecycleServer.js +0 -77
- package/dist/esm/uc/utils/ucifcoIsForArray.d.ts +0 -8
- package/dist/esm/uc/utils/ucifcoIsForArray.js +0 -13
- package/dist/esm/utils/bundling/vite/StripUCDLifecycleServerPlugin.d.ts +0 -2
- package/dist/esm/utils/bundling/vite/StripUCDLifecycleServerPlugin.js +0 -18
- package/dist/esm/utils/http/toFormData.d.ts +0 -3
- package/dist/esm/utils/http/toFormData.js +0 -4
- package/dist/esm/utils/http/toJSON.d.ts +0 -3
- package/dist/esm/utils/http/toJSON.js +0 -3
- package/dist/esm/utils/http/toQueryParams.d.ts +0 -2
- package/dist/esm/utils/http/toQueryParams.js +0 -4
- package/dist/esm/utils/ioc/ContainerPrinter.d.ts +0 -15
- package/dist/esm/utils/ioc/ContainerPrinter.js +0 -58
- package/dist/esm/utils/ioc/bindProvider.d.ts +0 -2
- package/dist/esm/utils/ioc/bindProvider.js +0 -9
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { PRODUCT_NAME_PLACEHOLDER } from '../../convention.js';
|
|
2
|
-
export class SimpleAppTesterConfigurator {
|
|
3
|
-
async authSettersConfig() {
|
|
4
|
-
return undefined;
|
|
5
|
-
}
|
|
6
|
-
async bindImplementations(ctx) {
|
|
7
|
-
const { container } = ctx;
|
|
8
|
-
container.bind('ProductManifest').toConstantValue({
|
|
9
|
-
appReg: [{ name: ctx.appManifest.name }],
|
|
10
|
-
name: PRODUCT_NAME_PLACEHOLDER,
|
|
11
|
-
});
|
|
12
|
-
}
|
|
13
|
-
async clearExecution(ctx) {
|
|
14
|
-
const { container } = ctx;
|
|
15
|
-
await container.get('UCDataStore').clear();
|
|
16
|
-
}
|
|
17
|
-
async flows() {
|
|
18
|
-
return [];
|
|
19
|
-
}
|
|
20
|
-
async inputFillers() {
|
|
21
|
-
return undefined;
|
|
22
|
-
}
|
|
23
|
-
async opts() {
|
|
24
|
-
return undefined;
|
|
25
|
-
}
|
|
26
|
-
async seed(_ctx) {
|
|
27
|
-
// Nothing to do
|
|
28
|
-
}
|
|
29
|
-
async sideEffects(_ctx) {
|
|
30
|
-
return undefined;
|
|
31
|
-
}
|
|
32
|
-
async specificAssertions() {
|
|
33
|
-
return undefined;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { UCDefSourceRaw } from '../def.js';
|
|
2
|
-
/**
|
|
3
|
-
* Strip the server part of the UCD
|
|
4
|
-
*
|
|
5
|
-
* To be used by bundlers when building for the web for example, or any other clients (e.g. React Native).
|
|
6
|
-
*
|
|
7
|
-
* WARNING : This implementation is very naive and will have unexpected behaviors when the UCD has a specific shape.
|
|
8
|
-
* For instance, if there is another `server: {` occurence than the lifecycle.server definition, it will be wrongly replaced.
|
|
9
|
-
*
|
|
10
|
-
* TODO : Make this implementation more robust (let's try not to use an AST parser though, to keep things fast and simple).
|
|
11
|
-
*
|
|
12
|
-
* @param source
|
|
13
|
-
* @returns
|
|
14
|
-
*/
|
|
15
|
-
export declare function stripUCDLifecycleServer(source: UCDefSourceRaw): UCDefSourceRaw;
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { UC_MAIN_SERVER_SUFFIX } from '../../convention.js';
|
|
2
|
-
const CORE_SERVER_MAINS = ['IdleServerMain'];
|
|
3
|
-
const TOKEN_IMPORT = 'import';
|
|
4
|
-
const TOKEN_IMPORT_END = ';';
|
|
5
|
-
const TOKEN_LIFECYCLE_SERVER = 'server: {';
|
|
6
|
-
const TOKEN_LIFECYCLE_SERVER_END = '},';
|
|
7
|
-
const TOKEN_LIFECYCLE_SERVER_REPLACE = 'server: true,';
|
|
8
|
-
/**
|
|
9
|
-
* Strip the server part of the UCD
|
|
10
|
-
*
|
|
11
|
-
* To be used by bundlers when building for the web for example, or any other clients (e.g. React Native).
|
|
12
|
-
*
|
|
13
|
-
* WARNING : This implementation is very naive and will have unexpected behaviors when the UCD has a specific shape.
|
|
14
|
-
* For instance, if there is another `server: {` occurence than the lifecycle.server definition, it will be wrongly replaced.
|
|
15
|
-
*
|
|
16
|
-
* TODO : Make this implementation more robust (let's try not to use an AST parser though, to keep things fast and simple).
|
|
17
|
-
*
|
|
18
|
-
* @param source
|
|
19
|
-
* @returns
|
|
20
|
-
*/
|
|
21
|
-
export function stripUCDLifecycleServer(source) {
|
|
22
|
-
const occurrences = [
|
|
23
|
-
...source.matchAll(new RegExp(UC_MAIN_SERVER_SUFFIX, 'g')),
|
|
24
|
-
];
|
|
25
|
-
const count = occurrences.length;
|
|
26
|
-
const toReplace = [];
|
|
27
|
-
let occIdx = 0;
|
|
28
|
-
for (const occ of occurrences) {
|
|
29
|
-
if (count === 3 && occIdx === 1) {
|
|
30
|
-
// Skip the 2nd occurrence as it is part of the import of the 1st (Rrrrh very hacky...)
|
|
31
|
-
occIdx += 1;
|
|
32
|
-
continue;
|
|
33
|
-
}
|
|
34
|
-
const toRep = { end: 0, start: 0, str: '' };
|
|
35
|
-
let cursor = occ.index;
|
|
36
|
-
let expr = '';
|
|
37
|
-
while (!expr.startsWith(TOKEN_IMPORT) &&
|
|
38
|
-
!expr.startsWith(TOKEN_LIFECYCLE_SERVER)) {
|
|
39
|
-
expr = `${source[cursor]}${expr}`;
|
|
40
|
-
cursor -= 1;
|
|
41
|
-
}
|
|
42
|
-
toRep.start = cursor;
|
|
43
|
-
cursor = occ.index;
|
|
44
|
-
while (!expr.endsWith(TOKEN_IMPORT_END) &&
|
|
45
|
-
!expr.endsWith(TOKEN_LIFECYCLE_SERVER_END)) {
|
|
46
|
-
expr = `${expr}${source[cursor]}`;
|
|
47
|
-
cursor += 1;
|
|
48
|
-
}
|
|
49
|
-
toRep.end = cursor;
|
|
50
|
-
toRep.str = source.substring(toRep.start, toRep.end).trim();
|
|
51
|
-
toReplace.push(toRep);
|
|
52
|
-
occIdx += 1;
|
|
53
|
-
}
|
|
54
|
-
// Flip the items to replace in order to remove the usage before the imports
|
|
55
|
-
// This is related to the edge case of IdleServerMain that we remove from the imports list,
|
|
56
|
-
// while for specific ServerMain, we remove the entire import instruction.
|
|
57
|
-
toReplace.reverse();
|
|
58
|
-
let cleaned = source;
|
|
59
|
-
for (const { str } of toReplace) {
|
|
60
|
-
if (str.startsWith(TOKEN_LIFECYCLE_SERVER)) {
|
|
61
|
-
cleaned = cleaned.replaceAll(str, TOKEN_LIFECYCLE_SERVER_REPLACE);
|
|
62
|
-
continue;
|
|
63
|
-
}
|
|
64
|
-
if (str.startsWith(TOKEN_IMPORT)) {
|
|
65
|
-
for (const coreServerMain of CORE_SERVER_MAINS) {
|
|
66
|
-
if (str.includes(coreServerMain)) {
|
|
67
|
-
cleaned = cleaned.replace(new RegExp(`${coreServerMain},?`), '');
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
cleaned = cleaned.replaceAll(str, '');
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
if (cleaned.includes(UC_MAIN_SERVER_SUFFIX)) {
|
|
74
|
-
throw new Error(`Stripping UCD server lifecycle did not complete successfully. The output still contains references to ${UC_MAIN_SERVER_SUFFIX} : ${cleaned}`);
|
|
75
|
-
}
|
|
76
|
-
return cleaned;
|
|
77
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { UCInputFieldChangeOperator } from '../input-field.js';
|
|
2
|
-
/**
|
|
3
|
-
* Check whether a {@link UCInputFieldChangeOperator} is for an array or not.
|
|
4
|
-
*
|
|
5
|
-
* @param op
|
|
6
|
-
* @returns
|
|
7
|
-
*/
|
|
8
|
-
export declare function ucifcoIsForArray(op: UCInputFieldChangeOperator): op is UCInputFieldChangeOperator.ADD | UCInputFieldChangeOperator.REMOVE;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { UCInputFieldChangeOperator } from '../input-field.js';
|
|
2
|
-
/**
|
|
3
|
-
* Check whether a {@link UCInputFieldChangeOperator} is for an array or not.
|
|
4
|
-
*
|
|
5
|
-
* @param op
|
|
6
|
-
* @returns
|
|
7
|
-
*/
|
|
8
|
-
export function ucifcoIsForArray(op) {
|
|
9
|
-
return [
|
|
10
|
-
UCInputFieldChangeOperator.ADD,
|
|
11
|
-
UCInputFieldChangeOperator.REMOVE,
|
|
12
|
-
].includes(op);
|
|
13
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { UC_DEF_FILE_NAME_SUFFIX } from '../../../convention.js';
|
|
2
|
-
import { stripUCDLifecycleServer } from '../../../uc/index.js';
|
|
3
|
-
export const StripUCDLifecycleServerPlugin = {
|
|
4
|
-
// Why enforce ?
|
|
5
|
-
// Otherwise Rollup parses the file and strips trailing commas.
|
|
6
|
-
// We need them to strip correctly (although the implementation will be made more robust).
|
|
7
|
-
enforce: 'pre',
|
|
8
|
-
name: 'strip-ucd-lifecycle-server',
|
|
9
|
-
transform: (src, id) => {
|
|
10
|
-
if (id.match(new RegExp(`${UC_DEF_FILE_NAME_SUFFIX}$`)) === null) {
|
|
11
|
-
return;
|
|
12
|
-
}
|
|
13
|
-
const code = stripUCDLifecycleServer(src);
|
|
14
|
-
return {
|
|
15
|
-
code,
|
|
16
|
-
};
|
|
17
|
-
},
|
|
18
|
-
};
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { type Container } from 'inversify';
|
|
2
|
-
import type { Logger, Worker } from '../../std/index.js';
|
|
3
|
-
interface Input {
|
|
4
|
-
container: Container;
|
|
5
|
-
}
|
|
6
|
-
interface Output {
|
|
7
|
-
bindingLines: string[];
|
|
8
|
-
}
|
|
9
|
-
export declare class ContainerPrinter implements Worker<Input, Promise<Output>> {
|
|
10
|
-
private logger;
|
|
11
|
-
constructor(logger: Logger);
|
|
12
|
-
exec({ container }: Input): Promise<Output>;
|
|
13
|
-
private symToString;
|
|
14
|
-
}
|
|
15
|
-
export {};
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
-
};
|
|
7
|
-
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
-
};
|
|
10
|
-
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
|
-
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
|
-
};
|
|
13
|
-
import { inject, injectable } from 'inversify';
|
|
14
|
-
import { fmtPadEndFor } from '../terminal/fmt.js';
|
|
15
|
-
let ContainerPrinter = class ContainerPrinter {
|
|
16
|
-
logger;
|
|
17
|
-
constructor(logger) {
|
|
18
|
-
this.logger = logger;
|
|
19
|
-
}
|
|
20
|
-
async exec({ container }) {
|
|
21
|
-
// See https://github.com/inversify/InversifyJS/issues/1584
|
|
22
|
-
// @ts-ignore
|
|
23
|
-
const dictionary = container._bindingDictionary._map;
|
|
24
|
-
const entries = [];
|
|
25
|
-
const keys = [...dictionary.keys()].map(this.symToString);
|
|
26
|
-
const keyPadEnd = fmtPadEndFor(keys);
|
|
27
|
-
const serviceIdentifierPadEnd = fmtPadEndFor([...dictionary.values()].flatMap((bindings) => bindings.map((b) => this.symToString(b.serviceIdentifier))));
|
|
28
|
-
for (const [key, bindings] of dictionary) {
|
|
29
|
-
const name = `\x1b[1m${this.symToString(key).padEnd(keyPadEnd)}\x1b[0m`;
|
|
30
|
-
const implementations = bindings
|
|
31
|
-
.map((b) => {
|
|
32
|
-
const serviceIdentifier = this.symToString(b.serviceIdentifier).padEnd(serviceIdentifierPadEnd);
|
|
33
|
-
const value = b.implementationType?.name ?? '{}';
|
|
34
|
-
const tags = `[type: ${b.type}] [scope: ${b.scope}]`;
|
|
35
|
-
return `${serviceIdentifier} <-- ${value} ${tags}`;
|
|
36
|
-
})
|
|
37
|
-
.join(' / ');
|
|
38
|
-
entries.push(`${name} : ${implementations}`);
|
|
39
|
-
}
|
|
40
|
-
this.logger.debug('Container bindings');
|
|
41
|
-
const sorted = entries.sort((a, b) => a.localeCompare(b));
|
|
42
|
-
for (const e of sorted) {
|
|
43
|
-
this.logger.debug(e);
|
|
44
|
-
}
|
|
45
|
-
return {
|
|
46
|
-
bindingLines: sorted,
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
symToString(sym) {
|
|
50
|
-
return typeof sym === 'string' ? sym : (sym.name ?? 'UnnamedClass');
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
ContainerPrinter = __decorate([
|
|
54
|
-
injectable(),
|
|
55
|
-
__param(0, inject('Logger')),
|
|
56
|
-
__metadata("design:paramtypes", [Object])
|
|
57
|
-
], ContainerPrinter);
|
|
58
|
-
export { ContainerPrinter };
|