@armoury/fivem-framework-common 1.0.14 → 1.0.16

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.
@@ -15,7 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
16
16
  };
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.APP_INITIALIZER = exports.Config = exports.DecorationType = exports.Decorate = void 0;
18
+ exports.APP_INITIALIZER = exports.ResourceRef = exports.Resource = exports.Config = exports.DecorationType = exports.Decorate = void 0;
19
19
  exports.bootstrapWithProviders = bootstrapWithProviders;
20
20
  require("reflect-metadata");
21
21
  const injection_js_1 = require("injection-js");
@@ -28,9 +28,39 @@ __exportStar(require("../utils"), exports);
28
28
  __exportStar(require("../utils/utils"), exports);
29
29
  var config_decorator_1 = require("./config.decorator");
30
30
  Object.defineProperty(exports, "Config", { enumerable: true, get: function () { return config_decorator_1.Config; } });
31
+ var resource_decorator_1 = require("./resource.decorator");
32
+ Object.defineProperty(exports, "Resource", { enumerable: true, get: function () { return resource_decorator_1.Resource; } });
33
+ Object.defineProperty(exports, "ResourceRef", { enumerable: true, get: function () { return resource_decorator_1.ResourceRef; } });
31
34
  const decorator_utils_2 = require("../decorators/decorator.utils");
32
35
  const config_decorator_2 = require("./config.decorator");
36
+ const resource_decorator_2 = require("./resource.decorator");
33
37
  exports.APP_INITIALIZER = new injection_js_1.InjectionToken('APP_INITIALIZER');
38
+ function flattenProviders(providers) {
39
+ const flattened = [];
40
+ for (const provider of providers) {
41
+ if (Array.isArray(provider)) {
42
+ flattened.push(...flattenProviders(provider));
43
+ }
44
+ else {
45
+ flattened.push(provider);
46
+ }
47
+ }
48
+ return flattened;
49
+ }
50
+ function getProviderToken(provider) {
51
+ if (typeof provider === 'function') {
52
+ return provider;
53
+ }
54
+ if (provider && typeof provider === 'object' && 'provide' in provider) {
55
+ return provider.provide;
56
+ }
57
+ return undefined;
58
+ }
59
+ function getProviderTokens(providers) {
60
+ return flattenProviders(providers)
61
+ .map(getProviderToken)
62
+ .filter((token) => token !== undefined);
63
+ }
34
64
  function getProviderClasses(providers) {
35
65
  const classes = [];
36
66
  for (const provider of providers) {
@@ -48,20 +78,40 @@ function getProviderClasses(providers) {
48
78
  }
49
79
  return classes;
50
80
  }
51
- async function bootstrapWithProviders(entryPoint, parentProviders, options = {}, decorationType = decorator_utils_2.DecorationType.SERVER, readConfigValue) {
81
+ function hasProviderForToken(providers, token) {
82
+ for (const provider of providers) {
83
+ if (Array.isArray(provider)) {
84
+ if (hasProviderForToken(provider, token)) {
85
+ return true;
86
+ }
87
+ continue;
88
+ }
89
+ if (provider === token || (provider && typeof provider === 'object' && 'provide' in provider && provider.provide === token)) {
90
+ return true;
91
+ }
92
+ }
93
+ return false;
94
+ }
95
+ async function bootstrapWithProviders(entryPoint, parentProviders, options = {}, decorationType = decorator_utils_2.DecorationType.SERVER, readConfigValue, readResourceExports, defaultEagerProviders = []) {
52
96
  var _a, _b;
53
97
  const eagerProviders = (_a = options.eager) !== null && _a !== void 0 ? _a : [];
54
- const providers = [
55
- ...((_b = options.providers) !== null && _b !== void 0 ? _b : []),
56
- ...eagerProviders,
57
- ];
98
+ const optionProviders = (_b = options.providers) !== null && _b !== void 0 ? _b : [];
99
+ const platformDefaultProviders = flattenProviders(defaultEagerProviders);
100
+ const activeDefaultEagerProviders = platformDefaultProviders.filter((defaultProvider) => {
101
+ const token = getProviderToken(defaultProvider);
102
+ return token === undefined || !hasProviderForToken([...parentProviders, ...optionProviders], token);
103
+ });
104
+ const eagerRegistrations = eagerProviders.filter((eagerProvider) => !hasProviderForToken([...parentProviders, ...optionProviders], eagerProvider));
105
+ const providers = [...activeDefaultEagerProviders, ...optionProviders, ...eagerRegistrations];
106
+ const eagerTokens = [...new Set([...getProviderTokens(platformDefaultProviders), ...eagerProviders])];
58
107
  const configTargets = [entryPoint, ...getProviderClasses(parentProviders), ...getProviderClasses(providers)];
59
108
  const configProviders = (0, config_decorator_2.createConfigProviders)(configTargets, readConfigValue);
109
+ const resourceProviders = (0, resource_decorator_2.createResourceProviders)(configTargets, readResourceExports);
60
110
  const parentInjector = injection_js_1.ReflectiveInjector.resolveAndCreate(parentProviders);
61
- const injector = injection_js_1.ReflectiveInjector.resolveAndCreate([...configProviders, ...providers, entryPoint], parentInjector);
111
+ const injector = injection_js_1.ReflectiveInjector.resolveAndCreate([...configProviders, ...resourceProviders, ...providers, entryPoint], parentInjector);
62
112
  const instance = injector.get(entryPoint);
63
113
  (0, decorator_utils_2.Decorate)(instance, entryPoint.prototype, [...parentProviders, ...providers], decorationType);
64
- eagerProviders.forEach((provider) => injector.get(provider));
114
+ eagerTokens.forEach((token) => injector.get(token));
65
115
  const initializers = injector.get(exports.APP_INITIALIZER, []);
66
116
  await Promise.all(initializers.map((initializer) => initializer()));
67
117
  return instance;
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ResourceRef = void 0;
4
+ exports.Resource = Resource;
5
+ exports.createResourceProviders = createResourceProviders;
6
+ const injection_js_1 = require("injection-js");
7
+ const RESOURCE_PARAMETERS_METADATA = 'arm_resource_parameters';
8
+ class ResourceRef {
9
+ constructor(resourceName, readExports) {
10
+ this.resourceName = resourceName;
11
+ this.readExports = readExports;
12
+ }
13
+ get instance() {
14
+ const resourceExports = this.readExports(this.resourceName);
15
+ if (resourceExports === null || resourceExports === undefined) {
16
+ throw new Error(`Resource '${this.resourceName}' is not available or exposes no exports.`);
17
+ }
18
+ return resourceExports;
19
+ }
20
+ }
21
+ exports.ResourceRef = ResourceRef;
22
+ function Resource(resourceName) {
23
+ if (!resourceName.trim()) {
24
+ throw new Error('Resource name must not be empty.');
25
+ }
26
+ const token = new injection_js_1.InjectionToken(`Resource(${resourceName})`);
27
+ const inject = (0, injection_js_1.Inject)(token);
28
+ return (target, propertyKey, parameterIndex) => {
29
+ var _a;
30
+ if (propertyKey !== undefined) {
31
+ throw new Error('Resource can only decorate constructor parameters.');
32
+ }
33
+ inject(target, propertyKey, parameterIndex);
34
+ const bindings = (_a = Reflect.getOwnMetadata(RESOURCE_PARAMETERS_METADATA, target)) !== null && _a !== void 0 ? _a : [];
35
+ Reflect.defineMetadata(RESOURCE_PARAMETERS_METADATA, [...bindings, { token, resourceName }], target);
36
+ };
37
+ }
38
+ function createResourceProviders(targets, readExports) {
39
+ var _a;
40
+ const bindings = new Map();
41
+ for (const target of targets) {
42
+ let constructor = target;
43
+ while (constructor && constructor !== Function.prototype) {
44
+ const constructorBindings = (_a = Reflect.getOwnMetadata(RESOURCE_PARAMETERS_METADATA, constructor)) !== null && _a !== void 0 ? _a : [];
45
+ constructorBindings.forEach((binding) => bindings.set(binding.token, binding));
46
+ constructor = Object.getPrototypeOf(constructor);
47
+ }
48
+ }
49
+ return [...bindings.values()].map(({ token, resourceName }) => ({
50
+ provide: token,
51
+ useFactory: () => new ResourceRef(resourceName, readExports),
52
+ }));
53
+ }
@@ -7,9 +7,37 @@ export { Decorate, DecorationType } from '../decorators/decorator.utils';
7
7
  export * from '../utils';
8
8
  export * from '../utils/utils';
9
9
  export { Config } from './config.decorator';
10
+ export { Resource, ResourceRef } from './resource.decorator';
10
11
  import { Decorate, DecorationType } from '../decorators/decorator.utils';
11
12
  import { createConfigProviders } from './config.decorator';
13
+ import { createResourceProviders } from './resource.decorator';
12
14
  export const APP_INITIALIZER = new InjectionToken('APP_INITIALIZER');
15
+ function flattenProviders(providers) {
16
+ const flattened = [];
17
+ for (const provider of providers) {
18
+ if (Array.isArray(provider)) {
19
+ flattened.push(...flattenProviders(provider));
20
+ }
21
+ else {
22
+ flattened.push(provider);
23
+ }
24
+ }
25
+ return flattened;
26
+ }
27
+ function getProviderToken(provider) {
28
+ if (typeof provider === 'function') {
29
+ return provider;
30
+ }
31
+ if (provider && typeof provider === 'object' && 'provide' in provider) {
32
+ return provider.provide;
33
+ }
34
+ return undefined;
35
+ }
36
+ function getProviderTokens(providers) {
37
+ return flattenProviders(providers)
38
+ .map(getProviderToken)
39
+ .filter((token) => token !== undefined);
40
+ }
13
41
  function getProviderClasses(providers) {
14
42
  const classes = [];
15
43
  for (const provider of providers) {
@@ -27,20 +55,40 @@ function getProviderClasses(providers) {
27
55
  }
28
56
  return classes;
29
57
  }
30
- export async function bootstrapWithProviders(entryPoint, parentProviders, options = {}, decorationType = DecorationType.SERVER, readConfigValue) {
58
+ function hasProviderForToken(providers, token) {
59
+ for (const provider of providers) {
60
+ if (Array.isArray(provider)) {
61
+ if (hasProviderForToken(provider, token)) {
62
+ return true;
63
+ }
64
+ continue;
65
+ }
66
+ if (provider === token || (provider && typeof provider === 'object' && 'provide' in provider && provider.provide === token)) {
67
+ return true;
68
+ }
69
+ }
70
+ return false;
71
+ }
72
+ export async function bootstrapWithProviders(entryPoint, parentProviders, options = {}, decorationType = DecorationType.SERVER, readConfigValue, readResourceExports, defaultEagerProviders = []) {
31
73
  var _a, _b;
32
74
  const eagerProviders = (_a = options.eager) !== null && _a !== void 0 ? _a : [];
33
- const providers = [
34
- ...((_b = options.providers) !== null && _b !== void 0 ? _b : []),
35
- ...eagerProviders,
36
- ];
75
+ const optionProviders = (_b = options.providers) !== null && _b !== void 0 ? _b : [];
76
+ const platformDefaultProviders = flattenProviders(defaultEagerProviders);
77
+ const activeDefaultEagerProviders = platformDefaultProviders.filter((defaultProvider) => {
78
+ const token = getProviderToken(defaultProvider);
79
+ return token === undefined || !hasProviderForToken([...parentProviders, ...optionProviders], token);
80
+ });
81
+ const eagerRegistrations = eagerProviders.filter((eagerProvider) => !hasProviderForToken([...parentProviders, ...optionProviders], eagerProvider));
82
+ const providers = [...activeDefaultEagerProviders, ...optionProviders, ...eagerRegistrations];
83
+ const eagerTokens = [...new Set([...getProviderTokens(platformDefaultProviders), ...eagerProviders])];
37
84
  const configTargets = [entryPoint, ...getProviderClasses(parentProviders), ...getProviderClasses(providers)];
38
85
  const configProviders = createConfigProviders(configTargets, readConfigValue);
86
+ const resourceProviders = createResourceProviders(configTargets, readResourceExports);
39
87
  const parentInjector = ReflectiveInjector.resolveAndCreate(parentProviders);
40
- const injector = ReflectiveInjector.resolveAndCreate([...configProviders, ...providers, entryPoint], parentInjector);
88
+ const injector = ReflectiveInjector.resolveAndCreate([...configProviders, ...resourceProviders, ...providers, entryPoint], parentInjector);
41
89
  const instance = injector.get(entryPoint);
42
90
  Decorate(instance, entryPoint.prototype, [...parentProviders, ...providers], decorationType);
43
- eagerProviders.forEach((provider) => injector.get(provider));
91
+ eagerTokens.forEach((token) => injector.get(token));
44
92
  const initializers = injector.get(APP_INITIALIZER, []);
45
93
  await Promise.all(initializers.map((initializer) => initializer()));
46
94
  return instance;
@@ -0,0 +1,47 @@
1
+ import { Inject, InjectionToken } from 'injection-js';
2
+ const RESOURCE_PARAMETERS_METADATA = 'arm_resource_parameters';
3
+ export class ResourceRef {
4
+ constructor(resourceName, readExports) {
5
+ this.resourceName = resourceName;
6
+ this.readExports = readExports;
7
+ }
8
+ get instance() {
9
+ const resourceExports = this.readExports(this.resourceName);
10
+ if (resourceExports === null || resourceExports === undefined) {
11
+ throw new Error(`Resource '${this.resourceName}' is not available or exposes no exports.`);
12
+ }
13
+ return resourceExports;
14
+ }
15
+ }
16
+ export function Resource(resourceName) {
17
+ if (!resourceName.trim()) {
18
+ throw new Error('Resource name must not be empty.');
19
+ }
20
+ const token = new InjectionToken(`Resource(${resourceName})`);
21
+ const inject = Inject(token);
22
+ return (target, propertyKey, parameterIndex) => {
23
+ var _a;
24
+ if (propertyKey !== undefined) {
25
+ throw new Error('Resource can only decorate constructor parameters.');
26
+ }
27
+ inject(target, propertyKey, parameterIndex);
28
+ const bindings = (_a = Reflect.getOwnMetadata(RESOURCE_PARAMETERS_METADATA, target)) !== null && _a !== void 0 ? _a : [];
29
+ Reflect.defineMetadata(RESOURCE_PARAMETERS_METADATA, [...bindings, { token, resourceName }], target);
30
+ };
31
+ }
32
+ export function createResourceProviders(targets, readExports) {
33
+ var _a;
34
+ const bindings = new Map();
35
+ for (const target of targets) {
36
+ let constructor = target;
37
+ while (constructor && constructor !== Function.prototype) {
38
+ const constructorBindings = (_a = Reflect.getOwnMetadata(RESOURCE_PARAMETERS_METADATA, constructor)) !== null && _a !== void 0 ? _a : [];
39
+ constructorBindings.forEach((binding) => bindings.set(binding.token, binding));
40
+ constructor = Object.getPrototypeOf(constructor);
41
+ }
42
+ }
43
+ return [...bindings.values()].map(({ token, resourceName }) => ({
44
+ provide: token,
45
+ useFactory: () => new ResourceRef(resourceName, readExports),
46
+ }));
47
+ }
@@ -6,8 +6,10 @@ export { Decorate, DecorationType } from '../decorators/decorator.utils';
6
6
  export * from '../utils';
7
7
  export * from '../utils/utils';
8
8
  export { Config } from './config.decorator';
9
+ export { Resource, ResourceRef } from './resource.decorator';
9
10
  import { DecorationType } from '../decorators/decorator.utils';
10
11
  import { ConfigValueReader } from './config.decorator';
12
+ import { ResourceExportsReader } from './resource.decorator';
11
13
  export type AppInitializer = () => void | Promise<void>;
12
14
  export declare const APP_INITIALIZER: InjectionToken<AppInitializer[]>;
13
15
  export interface BootstrapOptions {
@@ -18,4 +20,4 @@ export interface BootstrapOptions {
18
20
  }
19
21
  export declare function bootstrapWithProviders<T extends {
20
22
  new (...args: any[]): any;
21
- } & Provider>(entryPoint: T, parentProviders: Provider[], options: BootstrapOptions | undefined, decorationType: DecorationType | undefined, readConfigValue: ConfigValueReader): Promise<InstanceType<T>>;
23
+ } & Provider>(entryPoint: T, parentProviders: Provider[], options: BootstrapOptions | undefined, decorationType: DecorationType | undefined, readConfigValue: ConfigValueReader, readResourceExports: ResourceExportsReader, defaultEagerProviders?: Provider[]): Promise<InstanceType<T>>;
@@ -0,0 +1,10 @@
1
+ import { Provider } from 'injection-js';
2
+ export type ResourceExportsReader = (resourceName: string) => unknown;
3
+ export declare class ResourceRef<T = Record<string, (...args: any[]) => any>> {
4
+ readonly resourceName: string;
5
+ private readonly readExports;
6
+ constructor(resourceName: string, readExports: ResourceExportsReader);
7
+ get instance(): T;
8
+ }
9
+ export declare function Resource<T = Record<string, (...args: any[]) => any>>(resourceName: string): ParameterDecorator;
10
+ export declare function createResourceProviders(targets: Function[], readExports: ResourceExportsReader): Provider[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@armoury/fivem-framework-common",
3
- "version": "1.0.14",
3
+ "version": "1.0.16",
4
4
  "description": "Shared APIs for the Armoury FiveM framework",
5
5
  "main": "dist/cjs/common/index.js",
6
6
  "module": "dist/esm/common/index.js",