commit ce9f4c53c66fc33f66a6934b8ed574077417c3dc
parent 80a92ae669bba1521c8eeb731dc0c14bb35c0d2e
Author: finwo <finwo@pm.me>
Date: Wed, 4 Feb 2026 15:47:35 +0100
Passing types into sub-entities
Diffstat:
19 files changed, 181 insertions(+), 1 deletion(-)
diff --git a/.gitignore b/.gitignore
@@ -0,0 +1 @@
+node_modules/
diff --git a/README.md b/README.md
@@ -8,7 +8,7 @@ Intended usage:
// model/user.ts
-import { Document, ID, Version, String, Index, CompositeIndex } from '@finwo/query-engine/types';
+import { Document, ID, Version, String, Index, CompositeIndex } from '@finwo/query-engine/decorators';
@Document({ adapter?: customAdapterInstance })
@CompositeIndex('otherIndexName', {
diff --git a/package-lock.json b/package-lock.json
@@ -0,0 +1,44 @@
+{
+ "name": "query-engine.ts",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "devDependencies": {
+ "@types/node": "^25.2.0",
+ "typescript": "^5.9.3"
+ }
+ },
+ "node_modules/@types/node": {
+ "version": "25.2.0",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-25.2.0.tgz",
+ "integrity": "sha512-DZ8VwRFUNzuqJ5khrvwMXHmvPe+zGayJhr2CDNiKB1WBE1ST8Djl00D0IC4vvNmHMdj6DlbYRIaFE7WHjlDl5w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~7.16.0"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.9.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
+ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "7.16.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
+ "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
+ "dev": true,
+ "license": "MIT"
+ }
+ }
+}
diff --git a/package.json b/package.json
@@ -0,0 +1,6 @@
+{
+ "devDependencies": {
+ "@types/node": "^25.2.0",
+ "typescript": "^5.9.3"
+ }
+}
diff --git a/src/adapter/abstract.ts b/src/adapter/abstract.ts
@@ -0,0 +1 @@
+export abstract class AbstractAdapter {}
diff --git a/src/adapter/level.ts b/src/adapter/level.ts
@@ -0,0 +1,5 @@
+import {AbstractAdapter} from "./abstract";
+
+export class LevelAdapter extends AbstractAdapter {
+
+}
diff --git a/src/decorators/composite-index.ts b/src/decorators/composite-index.ts
@@ -0,0 +1,9 @@
+export function CompositeIndex(): ClassDecorator {
+ return targetConstructor => {
+ // map.set(targetConstructor, {
+ // type : targetConstructor,
+ // fn : targetConstructor,
+ // value : EMPTY_VALUE,
+ // });
+ };
+}
diff --git a/src/decorators/document.ts b/src/decorators/document.ts
@@ -0,0 +1,10 @@
+
+export function Document(): ClassDecorator {
+ return targetConstructor => {
+ // map.set(targetConstructor, {
+ // type : targetConstructor,
+ // fn : targetConstructor,
+ // value : EMPTY_VALUE,
+ // });
+ };
+}
diff --git a/src/decorators/id.ts b/src/decorators/id.ts
@@ -0,0 +1,8 @@
+export function ID(): ParameterDecorator {
+ return function(target: any, propertyKey: string | symbol | undefined, index: number) {
+ // TBD
+ // const paramTypes: any[] = Reflect.getMetadata('design:paramtypes', target);
+ // paramTypes[index] = identifier;
+ // Reflect.defineMetadata('design:paramtypes', paramTypes, target);
+ };
+}
diff --git a/src/decorators/idx.ts b/src/decorators/idx.ts
@@ -0,0 +1,8 @@
+export function Index(): ParameterDecorator {
+ return function(target: any, propertyKey: string | symbol | undefined, index: number) {
+ // TBD
+ // const paramTypes: any[] = Reflect.getMetadata('design:paramtypes', target);
+ // paramTypes[index] = identifier;
+ // Reflect.defineMetadata('design:paramtypes', paramTypes, target);
+ };
+}
diff --git a/src/decorators/index.ts b/src/decorators/index.ts
@@ -0,0 +1,6 @@
+export * from './composite-index';
+export * from './document';
+export * from './id';
+export * from './idx';
+export * from './string';
+export * from './version';
diff --git a/src/decorators/string.ts b/src/decorators/string.ts
@@ -0,0 +1,8 @@
+export function String(): ParameterDecorator {
+ return function(target: any, propertyKey: string | symbol | undefined, index: number) {
+ // TBD
+ // const paramTypes: any[] = Reflect.getMetadata('design:paramtypes', target);
+ // paramTypes[index] = identifier;
+ // Reflect.defineMetadata('design:paramtypes', paramTypes, target);
+ };
+}
diff --git a/src/decorators/version.ts b/src/decorators/version.ts
@@ -0,0 +1,8 @@
+export function Version(): ParameterDecorator {
+ return function(target: any, propertyKey: string | symbol | undefined, index: number) {
+ // TBD
+ // const paramTypes: any[] = Reflect.getMetadata('design:paramtypes', target);
+ // paramTypes[index] = identifier;
+ // Reflect.defineMetadata('design:paramtypes', paramTypes, target);
+ };
+}
diff --git a/src/index.ts b/src/index.ts
@@ -0,0 +1,39 @@
+import {AbstractAdapter} from "./adapter/abstract";
+import {Constructable} from "./types/constructable";
+
+export type DocumentDefinition = {
+ model: Constructable<{}>
+}
+
+export class Query<P extends Constructable<{}>> {
+ constructor(protected documentType: P) {
+ // TBD
+ }
+}
+
+export class QueryEngine<DocumentDefinitions extends Record<string, DocumentDefinition>> {
+ protected documents: DocumentDefinitions;
+
+ constructor(options: {
+ defaultAdapter?: AbstractAdapter,
+ documents?: DocumentDefinitions,
+ } = {
+
+ }) {
+ // Sanitize inputs
+ if ('object' !== typeof options) options = {};
+ options = Object.assign({ documents: {} }, options || {});
+ if ('object' !== typeof options.documents) options.documents = {} as DocumentDefinitions;
+ options.documents = Object.assign({}, options.documents || {} as DocumentDefinitions);
+
+ // clean enough
+ this.documents = options.documents;
+ }
+
+ query<M extends keyof DocumentDefinitions>(documentType: M): Query<DocumentDefinitions[M]['model']> {
+ return new Query(this.documents[documentType].model);
+ }
+
+}
+
+
diff --git a/src/test.ts b/src/test.ts
@@ -0,0 +1,25 @@
+import {QueryEngine} from ".";
+
+class User {}
+class Post {}
+class Book {}
+
+const queryEngine = new QueryEngine({
+ documents: {
+ user: {
+ model: User
+ },
+ post: {
+ model: Post
+ },
+ book: {
+ model: Book
+ },
+ }
+});
+
+const query = queryEngine.query('user');
+
+query
+
+console.log({ queryEngine });
diff --git a/src/types/abstract-constructable.ts b/src/types/abstract-constructable.ts
@@ -0,0 +1 @@
+export type AbstractConstructable<T> = NewableFunction & { prototype: T };
diff --git a/src/types/abstract-document.ts b/src/types/abstract-document.ts
diff --git a/src/types/constructable.ts b/src/types/constructable.ts
@@ -0,0 +1 @@
+export type Constructable<T> = new (...args: any[]) => T;
diff --git a/tsconfig.json b/tsconfig.json