@mittwald/react-ghostmaker 1.3.0 → 1.4.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/dist/esm/metaData.js +39 -9
- package/dist/esm/polytype.js +3 -0
- package/dist/esm/queries.test.js +112 -0
- package/dist/types/metaData.d.ts +5 -2
- package/dist/types/polytype.d.ts +1 -0
- package/dist/types/queries.test.d.ts +1 -0
- package/package.json +12 -1
package/dist/esm/metaData.js
CHANGED
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
import is from "@sindresorhus/is";
|
|
2
2
|
const store = new Map();
|
|
3
|
+
const testNameConflict = (name) => {
|
|
4
|
+
if (Array.from(store.values()).some((meta) => meta.name === name)) {
|
|
5
|
+
throw new Error(`GhostMakerModel name conflict: A model with the name "${name}" is already registered.`);
|
|
6
|
+
}
|
|
7
|
+
};
|
|
3
8
|
export function GhostMakerModel(options) {
|
|
4
9
|
return function (target) {
|
|
10
|
+
if (options.name) {
|
|
11
|
+
testNameConflict(options.name);
|
|
12
|
+
}
|
|
5
13
|
store.set(target, options);
|
|
6
14
|
};
|
|
7
15
|
}
|
|
8
|
-
const
|
|
16
|
+
const dynamicModels = [];
|
|
9
17
|
export function ghostMakerModel(modelIdentifier) {
|
|
10
|
-
|
|
18
|
+
dynamicModels.push(modelIdentifier);
|
|
11
19
|
}
|
|
12
|
-
const
|
|
13
|
-
for (const identifyModel of
|
|
20
|
+
const getDynamicMetaData = (something) => {
|
|
21
|
+
for (const identifyModel of dynamicModels) {
|
|
14
22
|
const meta = identifyModel(something);
|
|
15
23
|
if (meta) {
|
|
16
24
|
return meta;
|
|
@@ -18,19 +26,41 @@ const getMetaDataFromIdentifiers = (something) => {
|
|
|
18
26
|
}
|
|
19
27
|
};
|
|
20
28
|
export const getMetaData = (something) => {
|
|
21
|
-
return (getMetaDataRecursive(something, undefined,
|
|
29
|
+
return (getMetaDataRecursive(something, undefined, getClass(something)) ??
|
|
30
|
+
getDynamicMetaData(something));
|
|
22
31
|
};
|
|
23
|
-
const getMetaDataRecursive = (something,
|
|
32
|
+
const getMetaDataRecursive = (something, collectedMeta,
|
|
24
33
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
25
34
|
klass) => {
|
|
26
|
-
const currentClass =
|
|
35
|
+
const currentClass = getClass(something);
|
|
27
36
|
const meta = store.get(klass ?? currentClass);
|
|
28
|
-
const mergedMeta = meta ||
|
|
37
|
+
const mergedMeta = meta || collectedMeta ? { ...meta, ...collectedMeta } : undefined;
|
|
29
38
|
if (mergedMeta && "getId" in mergedMeta && "name" in mergedMeta) {
|
|
30
39
|
return mergedMeta;
|
|
31
40
|
}
|
|
32
41
|
if (!klass) {
|
|
33
42
|
return mergedMeta;
|
|
34
43
|
}
|
|
35
|
-
|
|
44
|
+
const prototypes = getProtoypes.current(klass);
|
|
45
|
+
for (const proto of prototypes) {
|
|
46
|
+
const result = getMetaDataRecursive(something, mergedMeta, proto);
|
|
47
|
+
if (result) {
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
function isClass(value) {
|
|
53
|
+
return typeof value === "function" && /class[\s{]/.test(value.toString());
|
|
54
|
+
}
|
|
55
|
+
const getClass = (something) => {
|
|
56
|
+
return isClass(something)
|
|
57
|
+
? something
|
|
58
|
+
: is.object(something)
|
|
59
|
+
? something.constructor
|
|
60
|
+
: undefined;
|
|
61
|
+
};
|
|
62
|
+
export const getProtoypes = {
|
|
63
|
+
current: (something) => {
|
|
64
|
+
return [Object.getPrototypeOf(something)];
|
|
65
|
+
},
|
|
36
66
|
};
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
2
|
+
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
3
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
4
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
5
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
6
|
+
var _, done = false;
|
|
7
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
8
|
+
var context = {};
|
|
9
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
10
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
11
|
+
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
|
|
12
|
+
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
|
|
13
|
+
if (kind === "accessor") {
|
|
14
|
+
if (result === void 0) continue;
|
|
15
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
16
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
17
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
18
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
19
|
+
}
|
|
20
|
+
else if (_ = accept(result)) {
|
|
21
|
+
if (kind === "field") initializers.unshift(_);
|
|
22
|
+
else descriptor[key] = _;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
26
|
+
done = true;
|
|
27
|
+
};
|
|
28
|
+
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
|
29
|
+
var useValue = arguments.length > 2;
|
|
30
|
+
for (var i = 0; i < initializers.length; i++) {
|
|
31
|
+
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
32
|
+
}
|
|
33
|
+
return useValue ? value : void 0;
|
|
34
|
+
};
|
|
35
|
+
import { getMetaData, GhostMakerModel } from "./metaData";
|
|
36
|
+
import { expect, test } from "vitest";
|
|
37
|
+
let GrandParent = (() => {
|
|
38
|
+
let _classDecorators = [GhostMakerModel({
|
|
39
|
+
name: "TheGrandParent",
|
|
40
|
+
getId: (grandParent) => grandParent.id,
|
|
41
|
+
})];
|
|
42
|
+
let _classDescriptor;
|
|
43
|
+
let _classExtraInitializers = [];
|
|
44
|
+
let _classThis;
|
|
45
|
+
var GrandParent = class {
|
|
46
|
+
static { _classThis = this; }
|
|
47
|
+
static {
|
|
48
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
49
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
50
|
+
GrandParent = _classThis = _classDescriptor.value;
|
|
51
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
52
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
53
|
+
}
|
|
54
|
+
id;
|
|
55
|
+
constructor(id) {
|
|
56
|
+
this.id = id;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
return GrandParent = _classThis;
|
|
60
|
+
})();
|
|
61
|
+
let Parent = (() => {
|
|
62
|
+
let _classDecorators = [GhostMakerModel({
|
|
63
|
+
name: "TheParent",
|
|
64
|
+
})];
|
|
65
|
+
let _classDescriptor;
|
|
66
|
+
let _classExtraInitializers = [];
|
|
67
|
+
let _classThis;
|
|
68
|
+
let _classSuper = GrandParent;
|
|
69
|
+
var Parent = class extends _classSuper {
|
|
70
|
+
static { _classThis = this; }
|
|
71
|
+
static {
|
|
72
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
73
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
74
|
+
Parent = _classThis = _classDescriptor.value;
|
|
75
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
76
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
return Parent = _classThis;
|
|
80
|
+
})();
|
|
81
|
+
let Child = (() => {
|
|
82
|
+
let _classDecorators = [GhostMakerModel({
|
|
83
|
+
name: "TheChild",
|
|
84
|
+
})];
|
|
85
|
+
let _classDescriptor;
|
|
86
|
+
let _classExtraInitializers = [];
|
|
87
|
+
let _classThis;
|
|
88
|
+
let _classSuper = Parent;
|
|
89
|
+
var Child = class extends _classSuper {
|
|
90
|
+
static { _classThis = this; }
|
|
91
|
+
static {
|
|
92
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
93
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
94
|
+
Child = _classThis = _classDescriptor.value;
|
|
95
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
96
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
return Child = _classThis;
|
|
100
|
+
})();
|
|
101
|
+
test("getMetaData returns correct names", () => {
|
|
102
|
+
expect(getMetaData(new Child("id"))?.name).toBe("TheChild");
|
|
103
|
+
expect(getMetaData(new Parent("id"))?.name).toBe("TheParent");
|
|
104
|
+
expect(getMetaData(Parent)?.name).toBe("TheParent");
|
|
105
|
+
expect(getMetaData(Child)?.name).toBe("TheChild");
|
|
106
|
+
});
|
|
107
|
+
test("getMetaData returns getId function", () => {
|
|
108
|
+
expect(getMetaData(new Child("id"))?.getId).toBeDefined();
|
|
109
|
+
expect(getMetaData(new Parent("id"))?.getId).toBeDefined();
|
|
110
|
+
expect(getMetaData(Parent)?.getId).toBeDefined();
|
|
111
|
+
expect(getMetaData(Child)?.getId).toBeDefined();
|
|
112
|
+
});
|
package/dist/types/metaData.d.ts
CHANGED
|
@@ -5,7 +5,10 @@ interface GhostMakerModelMeta<T extends DecoratorTarget> {
|
|
|
5
5
|
name?: string;
|
|
6
6
|
}
|
|
7
7
|
export declare function GhostMakerModel<T extends DecoratorTarget>(options: GhostMakerModelMeta<T>): (target: T) => void;
|
|
8
|
-
type
|
|
9
|
-
export declare function ghostMakerModel(modelIdentifier:
|
|
8
|
+
type DynamicModel = (something: unknown) => GhostMakerModelMeta<DecoratorTarget> | void | undefined;
|
|
9
|
+
export declare function ghostMakerModel(modelIdentifier: DynamicModel): void;
|
|
10
10
|
export declare const getMetaData: (something: unknown) => GhostMakerModelMeta<DecoratorTarget> | undefined;
|
|
11
|
+
export declare const getProtoypes: {
|
|
12
|
+
current: (something: unknown) => any[];
|
|
13
|
+
};
|
|
11
14
|
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mittwald/react-ghostmaker",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"author": "Mittwald CM Service GmbH & Co. KG <opensource@mittwald.de>",
|
|
5
5
|
"contributors": [
|
|
6
6
|
"Marco Falkenberg <m.falkenberg@mittwald.de>"
|
|
@@ -27,6 +27,10 @@
|
|
|
27
27
|
"types": "./dist/types/index.d.ts",
|
|
28
28
|
"import": "./dist/esm/index.js"
|
|
29
29
|
},
|
|
30
|
+
"./polytype": {
|
|
31
|
+
"types": "./dist/types/polytype.d.ts",
|
|
32
|
+
"import": "./dist/esm/polytype.js"
|
|
33
|
+
},
|
|
30
34
|
"./package.json": "./package.json"
|
|
31
35
|
},
|
|
32
36
|
"types": "./dist/types/index.d.ts",
|
|
@@ -56,6 +60,7 @@
|
|
|
56
60
|
"globals": "^16.5.0",
|
|
57
61
|
"happy-dom": "^20.0.2",
|
|
58
62
|
"license-checker-rseidelsohn": "^4.4.2",
|
|
63
|
+
"polytype": "^0.17.0",
|
|
59
64
|
"prettier": "^3.6.2",
|
|
60
65
|
"prettier-plugin-jsdoc": "^1.3.3",
|
|
61
66
|
"prettier-plugin-pkgsort": "^0.2.1",
|
|
@@ -68,8 +73,14 @@
|
|
|
68
73
|
},
|
|
69
74
|
"peerDependencies": {
|
|
70
75
|
"@tanstack/react-query": "^5",
|
|
76
|
+
"polytype": "^0.17.0",
|
|
71
77
|
"react": ">=19.2"
|
|
72
78
|
},
|
|
79
|
+
"peerDependenciesMeta": {
|
|
80
|
+
"polytype": {
|
|
81
|
+
"optional": true
|
|
82
|
+
}
|
|
83
|
+
},
|
|
73
84
|
"scripts": {
|
|
74
85
|
"build": "pnpm build:clean && pnpm tsc",
|
|
75
86
|
"build:clean": "rimraf dist",
|