meteorjs-decorators 1.0.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/LICENSE +201 -0
- package/README.md +159 -0
- package/dist/controllers/base.controller.d.ts +3 -0
- package/dist/controllers/base.controller.js +6 -0
- package/dist/decorators/auth-guard.decorator.d.ts +1 -0
- package/dist/decorators/auth-guard.decorator.js +15 -0
- package/dist/decorators/controller.decorator.d.ts +3 -0
- package/dist/decorators/controller.decorator.js +50 -0
- package/dist/decorators/dto.decorator.d.ts +3 -0
- package/dist/decorators/dto.decorator.js +14 -0
- package/dist/decorators/entity.decorator.d.ts +3 -0
- package/dist/decorators/entity.decorator.js +27 -0
- package/dist/decorators/inject.decorator.d.ts +5 -0
- package/dist/decorators/inject.decorator.js +16 -0
- package/dist/decorators/injectable.decorator.d.ts +2 -0
- package/dist/decorators/injectable.decorator.js +55 -0
- package/dist/decorators/method.decorator.d.ts +1 -0
- package/dist/decorators/method.decorator.js +19 -0
- package/dist/decorators/permissions.decorator.d.ts +1 -0
- package/dist/decorators/permissions.decorator.js +24 -0
- package/dist/decorators/publication.decorator.d.ts +4 -0
- package/dist/decorators/publication.decorator.js +54 -0
- package/dist/decorators/reactive-dto.decorator.d.ts +4 -0
- package/dist/decorators/reactive-dto.decorator.js +48 -0
- package/dist/decorators/validate.decorator.d.ts +3 -0
- package/dist/decorators/validate.decorator.js +54 -0
- package/dist/dtos/delete-response.dto.d.ts +6 -0
- package/dist/dtos/delete-response.dto.js +12 -0
- package/dist/dtos/pagination-request.dto.d.ts +5 -0
- package/dist/dtos/pagination-request.dto.js +36 -0
- package/dist/dtos/request.dto.d.ts +3 -0
- package/dist/dtos/request.dto.js +7 -0
- package/dist/dtos/response.dto.d.ts +10 -0
- package/dist/dtos/response.dto.js +20 -0
- package/dist/entities/base.entity.d.ts +7 -0
- package/dist/entities/base.entity.js +6 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +38 -0
- package/dist/publications/base.publication.d.ts +4 -0
- package/dist/publications/base.publication.js +6 -0
- package/dist/types/type.interface.d.ts +3 -0
- package/dist/types/type.interface.js +2 -0
- package/dist/utils/container.d.ts +26 -0
- package/dist/utils/container.js +96 -0
- package/dist/utils/forward-ref.d.ts +6 -0
- package/dist/utils/forward-ref.js +16 -0
- package/dist/utils/module.d.ts +6 -0
- package/dist/utils/module.js +64 -0
- package/package.json +26 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Publication = Publication;
|
|
4
|
+
require("reflect-metadata");
|
|
5
|
+
const container_1 = require("../utils/container");
|
|
6
|
+
const forward_ref_1 = require("../utils/forward-ref");
|
|
7
|
+
const inject_decorator_1 = require("./inject.decorator");
|
|
8
|
+
function Publication(name) {
|
|
9
|
+
return function (constructor) {
|
|
10
|
+
const paramTypes = Reflect.getMetadata('design:paramtypes', constructor) || [];
|
|
11
|
+
const injectTokens = (0, inject_decorator_1.getInjectTokens)(constructor);
|
|
12
|
+
// TODO: each publicatinon should be added to the module.
|
|
13
|
+
const resolveContainer = () => {
|
|
14
|
+
let current = constructor;
|
|
15
|
+
while (current && !current.__container) {
|
|
16
|
+
current = Object.getPrototypeOf(current);
|
|
17
|
+
}
|
|
18
|
+
return current?.__container || container_1.Container;
|
|
19
|
+
};
|
|
20
|
+
const buildInstance = () => {
|
|
21
|
+
const container = resolveContainer();
|
|
22
|
+
const args = paramTypes.map((type, index) => {
|
|
23
|
+
const injectionToken = resolveInjectionToken(type, injectTokens[index], constructor.name, index);
|
|
24
|
+
return container.get(injectionToken);
|
|
25
|
+
});
|
|
26
|
+
return new constructor(...args);
|
|
27
|
+
};
|
|
28
|
+
console.log('registering publication: ', name);
|
|
29
|
+
Meteor.publish(name, function (...args) {
|
|
30
|
+
const instance = buildInstance();
|
|
31
|
+
instance.__context = this;
|
|
32
|
+
return instance.init(...args);
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function resolveInjectionToken(reflectedType, customToken, targetName, index) {
|
|
37
|
+
if (customToken) {
|
|
38
|
+
return unwrapToken(customToken);
|
|
39
|
+
}
|
|
40
|
+
if (!reflectedType) {
|
|
41
|
+
throw new Error(`Cannot resolve dependency for ${targetName}. Parameter at index ${index} is undefined. ` +
|
|
42
|
+
'Consider using @Inject with forwardRef to resolve circular dependencies.');
|
|
43
|
+
}
|
|
44
|
+
return reflectedType.name;
|
|
45
|
+
}
|
|
46
|
+
function unwrapToken(token) {
|
|
47
|
+
if (typeof token === 'string') {
|
|
48
|
+
return token;
|
|
49
|
+
}
|
|
50
|
+
if (token instanceof forward_ref_1.ForwardRef) {
|
|
51
|
+
return token.get().name;
|
|
52
|
+
}
|
|
53
|
+
return token().name;
|
|
54
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { ResponseDto } from '../dtos/response.dto';
|
|
3
|
+
import { Type } from '../types/type.interface';
|
|
4
|
+
export declare function ReactiveDto(dto: Type<ResponseDto>): (_target: any, _propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ReactiveDto = ReactiveDto;
|
|
4
|
+
require("reflect-metadata");
|
|
5
|
+
function ReactiveDto(dto) {
|
|
6
|
+
return function (_target, _propertyKey, descriptor) {
|
|
7
|
+
const originalMethod = descriptor.value;
|
|
8
|
+
descriptor.value = function (...args) {
|
|
9
|
+
const cursor = originalMethod.apply(this, args);
|
|
10
|
+
const subscription = this?.__context;
|
|
11
|
+
if (!subscription || !cursor || typeof cursor.observe !== 'function') {
|
|
12
|
+
return cursor;
|
|
13
|
+
}
|
|
14
|
+
const collectionName = getCollectionName(cursor);
|
|
15
|
+
if (!collectionName) {
|
|
16
|
+
throw new Meteor.Error('publication-error', 'Cannot resolve collection name for reactive publication.');
|
|
17
|
+
}
|
|
18
|
+
const toDto = (doc) => ({
|
|
19
|
+
...new dto().build(doc),
|
|
20
|
+
});
|
|
21
|
+
const handle = cursor.observe({
|
|
22
|
+
added(doc) {
|
|
23
|
+
subscription.added(collectionName, doc._id, toDto(doc));
|
|
24
|
+
},
|
|
25
|
+
changed(newDoc) {
|
|
26
|
+
subscription.changed(collectionName, newDoc._id, toDto(newDoc));
|
|
27
|
+
},
|
|
28
|
+
removed(oldDoc) {
|
|
29
|
+
subscription.removed(collectionName, oldDoc._id);
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
subscription.onStop(() => {
|
|
33
|
+
if (typeof handle?.stop === 'function') {
|
|
34
|
+
handle.stop();
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
subscription.ready();
|
|
38
|
+
};
|
|
39
|
+
return descriptor;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function getCollectionName(cursor) {
|
|
43
|
+
return cursor?._cursorDescription?.collectionName
|
|
44
|
+
|| cursor?._collection?._name
|
|
45
|
+
|| cursor?.collection?._name
|
|
46
|
+
|| cursor?.collectionName
|
|
47
|
+
|| cursor?.name;
|
|
48
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Validate = Validate;
|
|
4
|
+
const class_transformer_1 = require("class-transformer");
|
|
5
|
+
const class_validator_1 = require("class-validator");
|
|
6
|
+
function Validate(...dtos) {
|
|
7
|
+
return function (target, propertyKey, descriptor) {
|
|
8
|
+
const originalMethod = descriptor.value;
|
|
9
|
+
descriptor.value = function (...args) {
|
|
10
|
+
const STRING_TYPE = 'string';
|
|
11
|
+
const BOOLEAN_TYPE = 'boolean';
|
|
12
|
+
const NUMBER_TYPE = 'number';
|
|
13
|
+
const OBJECT_TYPE = 'object';
|
|
14
|
+
const ARRAY_TYPE = 'array';
|
|
15
|
+
for (let i = 0; i < args.length; i++) {
|
|
16
|
+
if (dtos.length < i + 1) {
|
|
17
|
+
continue; // do not validate rest of parameters
|
|
18
|
+
}
|
|
19
|
+
let validation = true;
|
|
20
|
+
switch (typeof dtos[i] === 'string' ? dtos[i] : 'object') {
|
|
21
|
+
case STRING_TYPE:
|
|
22
|
+
validation = typeof args[i] === STRING_TYPE;
|
|
23
|
+
break;
|
|
24
|
+
case BOOLEAN_TYPE:
|
|
25
|
+
validation = typeof args[i] === BOOLEAN_TYPE;
|
|
26
|
+
break;
|
|
27
|
+
case NUMBER_TYPE:
|
|
28
|
+
validation = typeof args[i] === NUMBER_TYPE;
|
|
29
|
+
break;
|
|
30
|
+
case OBJECT_TYPE:
|
|
31
|
+
case ARRAY_TYPE:
|
|
32
|
+
const requestDto = (0, class_transformer_1.plainToInstance)(dtos[i], args[i]); // Transform argument into DTO class
|
|
33
|
+
const errors = (0, class_validator_1.validateSync)(requestDto);
|
|
34
|
+
if (errors.length > 0) {
|
|
35
|
+
const details = errors
|
|
36
|
+
.flatMap((error) => Object.values(error.constraints ?? {}).map((message) => `${error.property}: ${message}`))
|
|
37
|
+
.join('; ');
|
|
38
|
+
throw new Meteor.Error('validation-error', 'Validation failed', details || 'Validation failed');
|
|
39
|
+
}
|
|
40
|
+
// Replace object argument with validated DTO
|
|
41
|
+
args[i] = requestDto;
|
|
42
|
+
break;
|
|
43
|
+
default:
|
|
44
|
+
throw new Meteor.Error('validation-error', 'Validation failed', `Parameter ${i + 1} has not a valid type.`);
|
|
45
|
+
}
|
|
46
|
+
if (validation === false) {
|
|
47
|
+
throw new Meteor.Error('validation-error', 'Validation failed', `Parameter ${i + 1} is not ${STRING_TYPE} type`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return originalMethod.apply(this, args);
|
|
51
|
+
};
|
|
52
|
+
return descriptor;
|
|
53
|
+
};
|
|
54
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DeleteResponse = void 0;
|
|
4
|
+
const response_dto_1 = require("./response.dto");
|
|
5
|
+
class DeleteResponse extends response_dto_1.ResponseDto {
|
|
6
|
+
build() {
|
|
7
|
+
this.status = 200;
|
|
8
|
+
this.message = 'Record deleted!';
|
|
9
|
+
return this.send();
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
exports.DeleteResponse = DeleteResponse;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
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;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.PaginationRequestDto = void 0;
|
|
13
|
+
const class_transformer_1 = require("class-transformer");
|
|
14
|
+
const class_validator_1 = require("class-validator");
|
|
15
|
+
const request_dto_1 = require("./request.dto");
|
|
16
|
+
class PaginationRequestDto extends request_dto_1.RequestDto {
|
|
17
|
+
constructor() {
|
|
18
|
+
super(...arguments);
|
|
19
|
+
this.page = 1;
|
|
20
|
+
this.limit = 10;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.PaginationRequestDto = PaginationRequestDto;
|
|
24
|
+
__decorate([
|
|
25
|
+
(0, class_transformer_1.Type)(() => Number),
|
|
26
|
+
(0, class_validator_1.IsInt)(),
|
|
27
|
+
(0, class_validator_1.Min)(1),
|
|
28
|
+
__metadata("design:type", Number)
|
|
29
|
+
], PaginationRequestDto.prototype, "page", void 0);
|
|
30
|
+
__decorate([
|
|
31
|
+
(0, class_transformer_1.Type)(() => Number),
|
|
32
|
+
(0, class_validator_1.IsInt)(),
|
|
33
|
+
(0, class_validator_1.Min)(1),
|
|
34
|
+
(0, class_validator_1.Max)(100),
|
|
35
|
+
__metadata("design:type", Number)
|
|
36
|
+
], PaginationRequestDto.prototype, "limit", void 0);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare abstract class ResponseDto {
|
|
2
|
+
abstract build(...args: unknown[]): ResponseDto;
|
|
3
|
+
protected send(): this;
|
|
4
|
+
/**
|
|
5
|
+
* Method to return undefined values from dto with NULL values.
|
|
6
|
+
* This helps to keep the original structure.
|
|
7
|
+
* @private
|
|
8
|
+
*/
|
|
9
|
+
private preserveNulls;
|
|
10
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ResponseDto = void 0;
|
|
4
|
+
class ResponseDto {
|
|
5
|
+
send() {
|
|
6
|
+
this.preserveNulls();
|
|
7
|
+
return this;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Method to return undefined values from dto with NULL values.
|
|
11
|
+
* This helps to keep the original structure.
|
|
12
|
+
* @private
|
|
13
|
+
*/
|
|
14
|
+
preserveNulls() {
|
|
15
|
+
for (const [field, value] of Object.entries(this)) {
|
|
16
|
+
this[field] = value ?? null;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.ResponseDto = ResponseDto;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export * from './controllers/base.controller';
|
|
2
|
+
export * from './decorators/auth-guard.decorator';
|
|
3
|
+
export * from './decorators/controller.decorator';
|
|
4
|
+
export * from './decorators/dto.decorator';
|
|
5
|
+
export * from './decorators/entity.decorator';
|
|
6
|
+
export * from './decorators/inject.decorator';
|
|
7
|
+
export * from './decorators/injectable.decorator';
|
|
8
|
+
export * from './decorators/method.decorator';
|
|
9
|
+
export * from './decorators/permissions.decorator';
|
|
10
|
+
export * from './decorators/publication.decorator';
|
|
11
|
+
export * from './decorators/reactive-dto.decorator';
|
|
12
|
+
export * from './decorators/validate.decorator';
|
|
13
|
+
export * from './dtos/delete-response.dto';
|
|
14
|
+
export * from './dtos/pagination-request.dto';
|
|
15
|
+
export * from './dtos/request.dto';
|
|
16
|
+
export * from './dtos/response.dto';
|
|
17
|
+
export * from './entities/base.entity';
|
|
18
|
+
export * from './publications/base.publication';
|
|
19
|
+
export * from './types/type.interface';
|
|
20
|
+
export * from './utils/container';
|
|
21
|
+
export * from './utils/forward-ref';
|
|
22
|
+
export * from './utils/module';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
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("./controllers/base.controller"), exports);
|
|
18
|
+
__exportStar(require("./decorators/auth-guard.decorator"), exports);
|
|
19
|
+
__exportStar(require("./decorators/controller.decorator"), exports);
|
|
20
|
+
__exportStar(require("./decorators/dto.decorator"), exports);
|
|
21
|
+
__exportStar(require("./decorators/entity.decorator"), exports);
|
|
22
|
+
__exportStar(require("./decorators/inject.decorator"), exports);
|
|
23
|
+
__exportStar(require("./decorators/injectable.decorator"), exports);
|
|
24
|
+
__exportStar(require("./decorators/method.decorator"), exports);
|
|
25
|
+
__exportStar(require("./decorators/permissions.decorator"), exports);
|
|
26
|
+
__exportStar(require("./decorators/publication.decorator"), exports);
|
|
27
|
+
__exportStar(require("./decorators/reactive-dto.decorator"), exports);
|
|
28
|
+
__exportStar(require("./decorators/validate.decorator"), exports);
|
|
29
|
+
__exportStar(require("./dtos/delete-response.dto"), exports);
|
|
30
|
+
__exportStar(require("./dtos/pagination-request.dto"), exports);
|
|
31
|
+
__exportStar(require("./dtos/request.dto"), exports);
|
|
32
|
+
__exportStar(require("./dtos/response.dto"), exports);
|
|
33
|
+
__exportStar(require("./entities/base.entity"), exports);
|
|
34
|
+
__exportStar(require("./publications/base.publication"), exports);
|
|
35
|
+
__exportStar(require("./types/type.interface"), exports);
|
|
36
|
+
__exportStar(require("./utils/container"), exports);
|
|
37
|
+
__exportStar(require("./utils/forward-ref"), exports);
|
|
38
|
+
__exportStar(require("./utils/module"), exports);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ForwardRef } from './forward-ref';
|
|
2
|
+
export interface ContainerAware {
|
|
3
|
+
__container?: ModuleContainer;
|
|
4
|
+
}
|
|
5
|
+
export declare class ModuleContainer {
|
|
6
|
+
private instances;
|
|
7
|
+
private factories;
|
|
8
|
+
private proxies;
|
|
9
|
+
private resolving;
|
|
10
|
+
private parent?;
|
|
11
|
+
constructor(parent?: ModuleContainer);
|
|
12
|
+
set<T>(token: string, value: T | ForwardRef<T>): void;
|
|
13
|
+
register<T>(token: string, factory: () => T): void;
|
|
14
|
+
get<T>(token: string): T;
|
|
15
|
+
has(token: string): boolean;
|
|
16
|
+
clear(): void;
|
|
17
|
+
private getProxy;
|
|
18
|
+
}
|
|
19
|
+
export declare class Container {
|
|
20
|
+
private static rootContainer;
|
|
21
|
+
static set<T>(token: string, value: T | ForwardRef<T>): void;
|
|
22
|
+
static register<T>(token: string, factory: () => T): void;
|
|
23
|
+
static get<T>(token: string): T;
|
|
24
|
+
static has(token: string): boolean;
|
|
25
|
+
static createChildContainer(): ModuleContainer;
|
|
26
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Container = exports.ModuleContainer = void 0;
|
|
4
|
+
const forward_ref_1 = require("./forward-ref");
|
|
5
|
+
class ModuleContainer {
|
|
6
|
+
constructor(parent) {
|
|
7
|
+
this.instances = new Map();
|
|
8
|
+
this.factories = new Map();
|
|
9
|
+
this.proxies = new Map();
|
|
10
|
+
this.resolving = new Set();
|
|
11
|
+
this.parent = parent;
|
|
12
|
+
}
|
|
13
|
+
set(token, value) {
|
|
14
|
+
this.instances.set(token, value);
|
|
15
|
+
}
|
|
16
|
+
register(token, factory) {
|
|
17
|
+
this.factories.set(token, factory);
|
|
18
|
+
}
|
|
19
|
+
get(token) {
|
|
20
|
+
if (this.instances.has(token)) {
|
|
21
|
+
const instance = this.instances.get(token);
|
|
22
|
+
if (instance instanceof forward_ref_1.ForwardRef) {
|
|
23
|
+
return instance.get();
|
|
24
|
+
}
|
|
25
|
+
return instance;
|
|
26
|
+
}
|
|
27
|
+
if (this.resolving.has(token)) {
|
|
28
|
+
return this.getProxy(token);
|
|
29
|
+
}
|
|
30
|
+
if (this.factories.has(token)) {
|
|
31
|
+
this.resolving.add(token);
|
|
32
|
+
const instance = this.factories.get(token)();
|
|
33
|
+
this.resolving.delete(token);
|
|
34
|
+
this.instances.set(token, instance);
|
|
35
|
+
return instance;
|
|
36
|
+
}
|
|
37
|
+
if (this.parent) {
|
|
38
|
+
return this.parent.get(token);
|
|
39
|
+
}
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
has(token) {
|
|
43
|
+
return this.instances.has(token) || this.factories.has(token) || (this.parent?.has(token) ?? false);
|
|
44
|
+
}
|
|
45
|
+
clear() {
|
|
46
|
+
this.instances.clear();
|
|
47
|
+
this.factories.clear();
|
|
48
|
+
this.proxies.clear();
|
|
49
|
+
this.resolving.clear();
|
|
50
|
+
}
|
|
51
|
+
getProxy(token) {
|
|
52
|
+
if (!this.proxies.has(token)) {
|
|
53
|
+
const handler = {
|
|
54
|
+
get: (_target, prop) => {
|
|
55
|
+
const instance = this.instances.get(token);
|
|
56
|
+
if (!instance) {
|
|
57
|
+
throw new Error(`Circular dependency detected for token ${token}.`);
|
|
58
|
+
}
|
|
59
|
+
const value = instance[prop];
|
|
60
|
+
return typeof value === 'function' ? value.bind(instance) : value;
|
|
61
|
+
},
|
|
62
|
+
set: (_target, prop, value) => {
|
|
63
|
+
const instance = this.instances.get(token);
|
|
64
|
+
if (!instance) {
|
|
65
|
+
throw new Error(`Circular dependency detected for token ${token}.`);
|
|
66
|
+
}
|
|
67
|
+
instance[prop] = value;
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
this.proxies.set(token, new Proxy({}, handler));
|
|
72
|
+
}
|
|
73
|
+
return this.proxies.get(token);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
exports.ModuleContainer = ModuleContainer;
|
|
77
|
+
// Global container for backward compatibility
|
|
78
|
+
class Container {
|
|
79
|
+
static set(token, value) {
|
|
80
|
+
this.rootContainer.set(token, value);
|
|
81
|
+
}
|
|
82
|
+
static register(token, factory) {
|
|
83
|
+
this.rootContainer.register(token, factory);
|
|
84
|
+
}
|
|
85
|
+
static get(token) {
|
|
86
|
+
return this.rootContainer.get(token);
|
|
87
|
+
}
|
|
88
|
+
static has(token) {
|
|
89
|
+
return this.rootContainer.has(token);
|
|
90
|
+
}
|
|
91
|
+
static createChildContainer() {
|
|
92
|
+
return new ModuleContainer(this.rootContainer);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
exports.Container = Container;
|
|
96
|
+
Container.rootContainer = new ModuleContainer();
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ForwardRef = void 0;
|
|
4
|
+
exports.forwardRef = forwardRef;
|
|
5
|
+
class ForwardRef {
|
|
6
|
+
constructor(fn) {
|
|
7
|
+
this.fn = fn;
|
|
8
|
+
}
|
|
9
|
+
get() {
|
|
10
|
+
return this.fn();
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
exports.ForwardRef = ForwardRef;
|
|
14
|
+
function forwardRef(fn) {
|
|
15
|
+
return new ForwardRef(fn);
|
|
16
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Module = Module;
|
|
4
|
+
require("reflect-metadata");
|
|
5
|
+
const container_1 = require("./container");
|
|
6
|
+
function Module(config) {
|
|
7
|
+
return function (target) {
|
|
8
|
+
// Create a container for this module
|
|
9
|
+
const moduleContainer = container_1.Container.createChildContainer();
|
|
10
|
+
// Handle imports first
|
|
11
|
+
if (config.imports) {
|
|
12
|
+
config.imports.forEach(importedModule => {
|
|
13
|
+
// Don't instantiate modules directly, just register them
|
|
14
|
+
if (importedModule.forwardRef) {
|
|
15
|
+
console.log('importedModule4: ', importedModule.forwardRef.get());
|
|
16
|
+
moduleContainer.set(importedModule.forwardRef.get().name, importedModule.forwardRef.get());
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
moduleContainer.set(importedModule.name, importedModule);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
const resolveProvider = (providerClass) => {
|
|
24
|
+
if (container_1.Container.has(providerClass.name)) {
|
|
25
|
+
moduleContainer.set(providerClass.name, container_1.Container.get(providerClass.name));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const paramTypes = Reflect.getMetadata('design:paramtypes', providerClass) || [];
|
|
29
|
+
const args = paramTypes.map((type) => moduleContainer.get(type.name));
|
|
30
|
+
moduleContainer.set(providerClass.name, new providerClass(...args));
|
|
31
|
+
};
|
|
32
|
+
// Then handle providers
|
|
33
|
+
if (config.providers) {
|
|
34
|
+
config.providers.forEach(provider => {
|
|
35
|
+
if (typeof provider === 'function') {
|
|
36
|
+
resolveProvider(provider);
|
|
37
|
+
}
|
|
38
|
+
else if (provider.forwardRef) {
|
|
39
|
+
resolveProvider(provider.forwardRef.get());
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
// Handle controllers
|
|
44
|
+
if (config.controllers) {
|
|
45
|
+
config.controllers.forEach(controller => {
|
|
46
|
+
if (typeof controller === 'function') {
|
|
47
|
+
let instance;
|
|
48
|
+
if (container_1.Container.has(controller.name)) {
|
|
49
|
+
instance = container_1.Container.get(controller.name);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
const paramTypes = Reflect.getMetadata('design:paramtypes', controller) || [];
|
|
53
|
+
const args = paramTypes.map((type) => moduleContainer.get(type.name));
|
|
54
|
+
instance = new controller(...args);
|
|
55
|
+
}
|
|
56
|
+
moduleContainer.set(controller.name, instance);
|
|
57
|
+
controller.__container = moduleContainer;
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
// Store the container in the module class
|
|
62
|
+
target.__container = moduleContainer;
|
|
63
|
+
};
|
|
64
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "meteorjs-decorators",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Meteor decorators to make your Meteor app with NestJS-style pattern.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"author": "Ivan Cabrera",
|
|
8
|
+
"license": "Apache-2.0",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsc -p tsconfig.json",
|
|
14
|
+
"prepublishOnly": "npm run build"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"class-transformer": "^0.5.1",
|
|
18
|
+
"class-validator": "^0.14.1",
|
|
19
|
+
"reflect-metadata": "^0.2.2"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/meteor": "^2.0.0",
|
|
23
|
+
"mongodb": "^6.13.1",
|
|
24
|
+
"typescript": "^5.4.5"
|
|
25
|
+
}
|
|
26
|
+
}
|