@declaro/data 2.0.0-beta.40 → 2.0.0-beta.43

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.
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2023 Emmert Technology
3
+ Copyright (c) 2025 Emmert Technology LLC
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md ADDED
File without changes
@@ -0,0 +1,4 @@
1
+ var c={};export{c as default};
2
+
3
+ //# debugId=F6326DF22999AEAE64756E2164756E21
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,9 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "sourcesContent": [
5
+ ],
6
+ "mappings": "",
7
+ "debugId": "F6326DF22999AEAE64756E2164756E21",
8
+ "names": []
9
+ }
@@ -0,0 +1,9 @@
1
+ // @bun
2
+ // src/index.ts
3
+ var src_default = {};
4
+ export {
5
+ src_default as default
6
+ };
7
+
8
+ //# debugId=27AF61BEAC19E21964756E2164756E21
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,9 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "sourcesContent": [
5
+ ],
6
+ "mappings": "",
7
+ "debugId": "27AF61BEAC19E21964756E2164756E21",
8
+ "names": []
9
+ }
@@ -0,0 +1,5 @@
1
+ // src/index.ts
2
+ module.exports = {};
3
+
4
+ //# debugId=1B6B05516E522F0C64756E2164756E21
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,9 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "sourcesContent": [
5
+ ],
6
+ "mappings": "",
7
+ "debugId": "1B6B05516E522F0C64756E2164756E21",
8
+ "names": []
9
+ }
File without changes
package/package.json CHANGED
@@ -1,44 +1,37 @@
1
1
  {
2
- "name": "@declaro/data",
3
- "version": "2.0.0-beta.40",
4
- "description": "Database utils",
5
- "main": "dist/declaro-data.cjs",
6
- "module": "dist/declaro-data.mjs",
7
- "types": "dist/index.d.ts",
8
- "author": "Emmert Technology LLC",
9
- "license": "MIT",
10
- "publishConfig": {
11
- "access": "public"
12
- },
13
- "scripts": {
14
- "dev": "vite build --watch",
15
- "build": "vite build",
16
- "preview": "vite preview",
17
- "test": "vitest"
18
- },
19
- "devDependencies": {
20
- "@declaro/core": "^1.0.0",
21
- "@types/uuid": "^9.0.3",
22
- "@vitest/coverage-v8": "^0.32.2",
23
- "vite": "^4.4.2",
24
- "vite-plugin-dts": "^2.3.0",
25
- "vitest": "^0.32.2"
26
- },
27
- "dependencies": {
28
- "@mikro-orm/core": "~5.7.14",
29
- "@mikro-orm/postgresql": "~5.7.14",
30
- "pg-format": "^1.0.4"
31
- },
32
- "peerDependencies": {
33
- "@declaro/core": "^1.0.0-alpha.0"
34
- },
35
- "repository": {
36
- "type": "git",
37
- "url": "git+https://github.com/emmertio/declaro.git#main"
38
- },
39
- "bugs": {
40
- "url": "https://github.com/emmertio/declaro/issues"
41
- },
42
- "homepage": "https://github.com/emmertio/declaro/tree/main#readme",
43
- "gitHead": "97e929b156d8d4f8b622573637411c6da5afb60b"
2
+ "name": "@declaro/data",
3
+ "version": "2.0.0-beta.43",
4
+ "description": "A data-mapper framework for managing application data across integrated systems.",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "dev": "bun run scripts/build.ts --watch",
9
+ "clean": "bun rimraf dist",
10
+ "build:typedefs": "bun tsc --emitDeclarationOnly --outDir dist/ts -p tsconfig.json",
11
+ "build:js": "bun run scripts/build.ts",
12
+ "build": "bun run clean && bun run build:js && bun run build:typedefs",
13
+ "test": "bun test",
14
+ "test:watch": "bun test --watch",
15
+ "typecheck": "bun tsc --noEmit"
16
+ },
17
+ "peerDependencies": {
18
+ "@declaro/core": "^2.0.0-beta.42"
19
+ },
20
+ "devDependencies": {
21
+ "@declaro/core": "^2.0.0-beta.43",
22
+ "typescript": "^5.8.3"
23
+ },
24
+ "author": "Your Name",
25
+ "license": "MIT",
26
+ "files": [
27
+ "dist/**/*",
28
+ "src/**/*"
29
+ ],
30
+ "exports": {
31
+ "import": "./dist/index.js",
32
+ "require": "./dist/index.js",
33
+ "types": "./dist/index.d.ts",
34
+ "bun": "./dist/index.js"
35
+ },
36
+ "gitHead": "d704c43c53588f4d42a4a0c09603a9fab4604c65"
44
37
  }
package/src/index.ts CHANGED
@@ -1,4 +0,0 @@
1
- export * from './databaseConnection'
2
- export * from './serverConnection'
3
- export * from './datastoreAbstract'
4
- export * from './hydrateEntity'
@@ -1,24 +0,0 @@
1
- import type { IDatastoreProvider, BaseModel, BaseModelClass } from '@declaro/core';
2
- import type { EntityManager, FilterQuery, Reference } from "@mikro-orm/core";
3
- import type { RemoveReturnType, UpsertReturnType } from "./datastoreAbstract";
4
- export type DatabaseConnectionOptions = {
5
- populate?: string[];
6
- immutableFields?: string[];
7
- };
8
- export declare class DatabaseConnection<T extends BaseModel<any>> implements IDatastoreProvider<T> {
9
- private repository;
10
- static inject: readonly ["EntityManager", "Reference"];
11
- readonly em: EntityManager;
12
- private hydrator;
13
- private populate;
14
- private immutableFields;
15
- constructor(em: EntityManager, reference: typeof Reference);
16
- setup(model: BaseModelClass<T>, options: DatabaseConnectionOptions): void;
17
- getAll(): Promise<void | any[]>;
18
- getWhere(filter?: FilterQuery<any>): Promise<void | any[]>;
19
- get(id: string | number): Promise<any>;
20
- upsert<T extends BaseModel<any> | BaseModel<any>[]>(data: T): Promise<UpsertReturnType<T>>;
21
- private singleUpsert;
22
- remove(data: T[] | T): Promise<RemoveReturnType>;
23
- private singleRemove;
24
- }
@@ -1,37 +0,0 @@
1
- import type { IDatastoreProvider, BaseModel, BaseModelClass, IStore } from "@declaro/core";
2
- import type { FetchFunc } from '@declaro/core';
3
- import { TrackedStatusStore } from "./trackedStatus";
4
- import type { FilterQuery } from "@mikro-orm/core";
5
- export type TrackedPayload<T> = {
6
- model: T;
7
- requestId: string;
8
- optimistic?: boolean;
9
- };
10
- export type UpsertReturnType<T> = T extends (infer U)[] ? U[] : T;
11
- export type RemoveReturnType = (number | string)[] | number | string | null;
12
- export declare abstract class AbstractStore<T extends BaseModel<any>> implements IStore {
13
- protected connection: IDatastoreProvider<T>;
14
- protected model: BaseModelClass<T>;
15
- protected options?: any;
16
- protected value: T[];
17
- private subscribers;
18
- private hydrated;
19
- trackedStatus: TrackedStatusStore;
20
- protected constructor(connection: IDatastoreProvider<T>, model: BaseModelClass<T>, options?: any);
21
- subscribe(subscription: (value: T[]) => void): (() => void);
22
- setFetch(fetch: FetchFunc): void;
23
- set(value: T[]): void;
24
- get(value: string | number): Promise<T>;
25
- getWhere(filter?: FilterQuery<any>): Promise<T[]>;
26
- getAll(): Promise<T[]>;
27
- hydrate(id?: string | number, filter?: FilterQuery<any>): Promise<void>;
28
- upsert(model: T | T[], optimistic?: boolean): Promise<UpsertReturnType<T>>;
29
- remove(model: T | T[], optimistic?: boolean): Promise<RemoveReturnType>;
30
- trackedUpsert(payload: TrackedPayload<T | T[]>): Promise<UpsertReturnType<T>>;
31
- trackedRemove(payload: TrackedPayload<T | T[]>): Promise<RemoveReturnType>;
32
- insertIntoStore(obj: T): void;
33
- removeFromStore(obj: T): void;
34
- }
35
- export type ActionableStore = AbstractStore<BaseModel<any>> & {
36
- [key: string]: (...args: any[]) => any;
37
- };
@@ -1 +0,0 @@
1
- "use strict";var u=Object.defineProperty;var l=(o,e,t)=>e in o?u(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var n=(o,e,t)=>(l(o,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class h{constructor(e,t){this.em=e,this.reference=t}hydrateEntity(e){const t=this.em.getMetadata().get(e.constructor.name);for(const s in e){const r=t.properties[s];if(e[s]!==void 0&&e[s]!==null&&r&&["m:1","1:1"].includes(r.reference)){const i=r.entity();e[s]=this.reference.createFromPK(i.meta.class,e[s])}}return e}}class c{constructor(e,t){n(this,"repository");n(this,"em");n(this,"hydrator");n(this,"populate");n(this,"immutableFields",[]);this.em=e,this.hydrator=new h(this.em,t)}setup(e,t){this.repository=this.em.getRepository(e),this.populate=t==null?void 0:t.populate,t!=null&&t.immutableFields&&(this.immutableFields=t.immutableFields)}getAll(){return this.repository.findAll({populate:this.populate}).catch(e=>{console.log(e)})}getWhere(e){return this.repository.find(e,{populate:this.populate}).catch(t=>{console.log(t)})}get(e){return this.repository.findOne(e,{populate:this.populate}).catch(t=>{console.log(t)})}async upsert(e){if(Array.isArray(e)){const t=[];for(const s of e){const r=await this.singleUpsert(s);t.push(r)}return t}else return await this.singleUpsert(e)}async singleUpsert(e){let t;const s=this.em.getMetadata().get(e.constructor.name),r={};return Object.keys(e).forEach(i=>{const a=s.properties[i];a&&a.reference!=="m:n"&&(r[i]=e[i])}),e.id?t=await this.em.findOneOrFail(e.constructor.name,e.id):(t=this.em.create(e.constructor.name,r),await this.em.persist(t).flush()),delete e.id,this.immutableFields.forEach(i=>{i in e&&(e[i]=t[i])}),this.em.assign(t,e),await this.em.persist(t).flush(),t}async remove(e){if(Array.isArray(e)){const t=[];for(const s of e)await this.singleRemove(s)&&t.push(s.id);return t}else return await this.singleRemove(e)?e.id:null}async singleRemove(e){try{const t=await this.em.findOneOrFail(e.constructor.name,e.id);return await this.em.remove(t).flush(),!0}catch(t){if(t.constructor.name==="NotFoundError")return!1;throw t}}}n(c,"inject",["EntityManager","Reference"]);class m{constructor(){n(this,"fetch");n(this,"model")}setup(e){this.model=e}setFetch(e){this.fetch=e}getAll(){return this.fetch(`/store/${this.model.name}/getAll`).then(e=>e.json().then(t=>t.map(s=>Object.assign(new this.model,s))))}getWhere(e){return this.fetch(`/store/${this.model.name}/getWhere/${JSON.stringify(e)}`).then(t=>t.json().then(s=>s.map(r=>Object.assign(new this.model,r))))}get(e){return this.fetch(`/store/${this.model.name}/get/${e}`).then(t=>t.json())}upsert(e){return this._callStoreMethod("upsert","POST",e)}remove(e){return this._callStoreMethod("remove","POST",e)}_callStoreMethod(e,t,s=null){let r={};return s&&(r["Content-Type"]="application/json;",r.Accept="application/json;"),this.fetch(`/store/${this.model.name}/${e}`,{method:t,body:s?JSON.stringify(s):null,headers:r}).then(async i=>{const a=await i.json();if(i.ok)return a;throw Error(a.message)})}}class f{constructor(){n(this,"value",{});n(this,"subscribers",[])}subscribe(e){return this.subscribers.push(e),e(this.value),()=>{this.subscribers=this.subscribers.filter(t=>t!==e)}}push(e){this.value={...this.value,[e.requestId]:e},this.subscribers.forEach(t=>t(this.value))}remove(e){const{[e]:t,...s}=this.value;this.value=s,this.subscribers.forEach(r=>r(this.value))}}class d{constructor(e,t,s){n(this,"value",[]);n(this,"subscribers",[]);n(this,"hydrated",!1);n(this,"trackedStatus",new f);this.connection=e,this.model=t,this.options=s,this.connection.setup(this.model,s)}subscribe(e){return this.subscribers.push(e),e(this.value),()=>{this.subscribers=this.subscribers.filter(t=>t!==e)}}setFetch(e){const t=this.connection;t.setFetch&&t.setFetch(e)}set(e){this.value=e,this.subscribers.forEach(t=>t(e))}async get(e){return await this.hydrate(e),typeof this.value>"u"?null:this.value.filter(s=>s.id==e)[0]}async getWhere(e){return await this.hydrate(null,e),this.value}async getAll(){return await this.hydrate(),this.value}async hydrate(e,t){if(!(this.hydrated&&!t)){if(t){const s=await this.connection.getWhere(t);s&&this.set(s)}else if(e){if(!t){const s=await this.connection.get(e);s&&this.set([s])}}else{const s=await this.connection.getAll();s&&this.set(s)}this.hydrated=!0}}async upsert(e,t=!1){if(Array.isArray(e)){const s=e.map(i=>Object.assign(new this.model,i));t&&s.forEach(i=>this.insertIntoStore(i));const r=await this.connection.upsert(s);return r.forEach(i=>this.insertIntoStore(i)),r}else{const s=Object.assign(new this.model,e);t&&this.insertIntoStore(s);const r=await this.connection.upsert(s);return this.insertIntoStore(r),r}}async remove(e,t=!1){if(Array.isArray(e)){const s=e.map(i=>Object.assign(new this.model,i));t&&s.forEach(i=>this.removeFromStore(i));const r=await this.connection.remove(s);return s.forEach(i=>this.removeFromStore(i)),r}else{const s=Object.assign(new this.model,e);t&&this.removeFromStore(s);const r=await this.connection.remove(s);return this.removeFromStore(s),r}}async trackedUpsert(e){try{const t=await this.upsert(e.model);return this.trackedStatus.push({requestId:e.requestId,error:!1,message:"Upserted successfully"}),t}catch(t){this.trackedStatus.push({requestId:e.requestId,error:!0,message:t.message})}}async trackedRemove(e){try{const t=await this.remove(e.model);return this.trackedStatus.push({requestId:e.requestId,error:!1,message:"Removed successfully"}),t}catch(t){this.trackedStatus.push({requestId:e.requestId,error:!0,message:t.message})}}insertIntoStore(e){this.value.some(s=>s.id===e.id)?this.set(this.value.map(s=>s.id===e.id?e:s)):this.set([...this.value,e])}removeFromStore(e){this.set(this.value.filter(t=>t.id!==e.id))}}exports.AbstractStore=d;exports.DatabaseConnection=c;exports.Hydrator=h;exports.ServerConnection=m;
@@ -1,250 +0,0 @@
1
- var a = Object.defineProperty;
2
- var c = (o, e, t) => e in o ? a(o, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : o[e] = t;
3
- var n = (o, e, t) => (c(o, typeof e != "symbol" ? e + "" : e, t), t);
4
- class u {
5
- constructor(e, t) {
6
- this.em = e, this.reference = t;
7
- }
8
- hydrateEntity(e) {
9
- const t = this.em.getMetadata().get(e.constructor.name);
10
- for (const s in e) {
11
- const r = t.properties[s];
12
- if (e[s] !== void 0 && e[s] !== null && r && ["m:1", "1:1"].includes(r.reference)) {
13
- const i = r.entity();
14
- e[s] = this.reference.createFromPK(i.meta.class, e[s]);
15
- }
16
- }
17
- return e;
18
- }
19
- }
20
- class l {
21
- constructor(e, t) {
22
- n(this, "repository");
23
- n(this, "em");
24
- n(this, "hydrator");
25
- n(this, "populate");
26
- n(this, "immutableFields", []);
27
- this.em = e, this.hydrator = new u(this.em, t);
28
- }
29
- setup(e, t) {
30
- this.repository = this.em.getRepository(e), this.populate = t == null ? void 0 : t.populate, t != null && t.immutableFields && (this.immutableFields = t.immutableFields);
31
- }
32
- getAll() {
33
- return this.repository.findAll({ populate: this.populate }).catch((e) => {
34
- console.log(e);
35
- });
36
- }
37
- getWhere(e) {
38
- return this.repository.find(e, { populate: this.populate }).catch((t) => {
39
- console.log(t);
40
- });
41
- }
42
- get(e) {
43
- return this.repository.findOne(e, { populate: this.populate }).catch((t) => {
44
- console.log(t);
45
- });
46
- }
47
- async upsert(e) {
48
- if (Array.isArray(e)) {
49
- const t = [];
50
- for (const s of e) {
51
- const r = await this.singleUpsert(s);
52
- t.push(r);
53
- }
54
- return t;
55
- } else
56
- return await this.singleUpsert(e);
57
- }
58
- async singleUpsert(e) {
59
- let t;
60
- const s = this.em.getMetadata().get(e.constructor.name), r = {};
61
- return Object.keys(e).forEach((i) => {
62
- const h = s.properties[i];
63
- h && h.reference !== "m:n" && (r[i] = e[i]);
64
- }), e.id ? t = await this.em.findOneOrFail(e.constructor.name, e.id) : (t = this.em.create(e.constructor.name, r), await this.em.persist(t).flush()), delete e.id, this.immutableFields.forEach((i) => {
65
- i in e && (e[i] = t[i]);
66
- }), this.em.assign(t, e), await this.em.persist(t).flush(), t;
67
- }
68
- async remove(e) {
69
- if (Array.isArray(e)) {
70
- const t = [];
71
- for (const s of e)
72
- await this.singleRemove(s) && t.push(s.id);
73
- return t;
74
- } else
75
- return await this.singleRemove(e) ? e.id : null;
76
- }
77
- async singleRemove(e) {
78
- try {
79
- const t = await this.em.findOneOrFail(e.constructor.name, e.id);
80
- return await this.em.remove(t).flush(), !0;
81
- } catch (t) {
82
- if (t.constructor.name === "NotFoundError")
83
- return !1;
84
- throw t;
85
- }
86
- }
87
- }
88
- n(l, "inject", ["EntityManager", "Reference"]);
89
- class d {
90
- constructor() {
91
- n(this, "fetch");
92
- n(this, "model");
93
- }
94
- setup(e) {
95
- this.model = e;
96
- }
97
- setFetch(e) {
98
- this.fetch = e;
99
- }
100
- getAll() {
101
- return this.fetch(`/store/${this.model.name}/getAll`).then((e) => e.json().then((t) => t.map((s) => Object.assign(new this.model(), s))));
102
- }
103
- getWhere(e) {
104
- return this.fetch(`/store/${this.model.name}/getWhere/${JSON.stringify(e)}`).then((t) => t.json().then((s) => s.map((r) => Object.assign(new this.model(), r))));
105
- }
106
- get(e) {
107
- return this.fetch(`/store/${this.model.name}/get/${e}`).then((t) => t.json());
108
- }
109
- upsert(e) {
110
- return this._callStoreMethod("upsert", "POST", e);
111
- }
112
- remove(e) {
113
- return this._callStoreMethod("remove", "POST", e);
114
- }
115
- _callStoreMethod(e, t, s = null) {
116
- let r = {};
117
- return s && (r["Content-Type"] = "application/json;", r.Accept = "application/json;"), this.fetch(
118
- `/store/${this.model.name}/${e}`,
119
- {
120
- method: t,
121
- body: s ? JSON.stringify(s) : null,
122
- headers: r
123
- }
124
- ).then(async (i) => {
125
- const h = await i.json();
126
- if (i.ok)
127
- return h;
128
- throw Error(h.message);
129
- });
130
- }
131
- }
132
- class m {
133
- constructor() {
134
- n(this, "value", {});
135
- n(this, "subscribers", []);
136
- }
137
- subscribe(e) {
138
- return this.subscribers.push(e), e(this.value), () => {
139
- this.subscribers = this.subscribers.filter((t) => t !== e);
140
- };
141
- }
142
- push(e) {
143
- this.value = { ...this.value, [e.requestId]: e }, this.subscribers.forEach((t) => t(this.value));
144
- }
145
- remove(e) {
146
- const { [e]: t, ...s } = this.value;
147
- this.value = s, this.subscribers.forEach((r) => r(this.value));
148
- }
149
- }
150
- class p {
151
- constructor(e, t, s) {
152
- n(this, "value", []);
153
- n(this, "subscribers", []);
154
- n(this, "hydrated", !1);
155
- n(this, "trackedStatus", new m());
156
- this.connection = e, this.model = t, this.options = s, this.connection.setup(this.model, s);
157
- }
158
- subscribe(e) {
159
- return this.subscribers.push(e), e(this.value), () => {
160
- this.subscribers = this.subscribers.filter((t) => t !== e);
161
- };
162
- }
163
- setFetch(e) {
164
- const t = this.connection;
165
- t.setFetch && t.setFetch(e);
166
- }
167
- set(e) {
168
- this.value = e, this.subscribers.forEach((t) => t(e));
169
- }
170
- async get(e) {
171
- return await this.hydrate(e), typeof this.value > "u" ? null : this.value.filter((s) => s.id == e)[0];
172
- }
173
- async getWhere(e) {
174
- return await this.hydrate(null, e), this.value;
175
- }
176
- async getAll() {
177
- return await this.hydrate(), this.value;
178
- }
179
- async hydrate(e, t) {
180
- if (!(this.hydrated && !t)) {
181
- if (t) {
182
- const s = await this.connection.getWhere(t);
183
- s && this.set(s);
184
- } else if (e) {
185
- if (!t) {
186
- const s = await this.connection.get(e);
187
- s && this.set([s]);
188
- }
189
- } else {
190
- const s = await this.connection.getAll();
191
- s && this.set(s);
192
- }
193
- this.hydrated = !0;
194
- }
195
- }
196
- async upsert(e, t = !1) {
197
- if (Array.isArray(e)) {
198
- const s = e.map((i) => Object.assign(new this.model(), i));
199
- t && s.forEach((i) => this.insertIntoStore(i));
200
- const r = await this.connection.upsert(s);
201
- return r.forEach((i) => this.insertIntoStore(i)), r;
202
- } else {
203
- const s = Object.assign(new this.model(), e);
204
- t && this.insertIntoStore(s);
205
- const r = await this.connection.upsert(s);
206
- return this.insertIntoStore(r), r;
207
- }
208
- }
209
- async remove(e, t = !1) {
210
- if (Array.isArray(e)) {
211
- const s = e.map((i) => Object.assign(new this.model(), i));
212
- t && s.forEach((i) => this.removeFromStore(i));
213
- const r = await this.connection.remove(s);
214
- return s.forEach((i) => this.removeFromStore(i)), r;
215
- } else {
216
- const s = Object.assign(new this.model(), e);
217
- t && this.removeFromStore(s);
218
- const r = await this.connection.remove(s);
219
- return this.removeFromStore(s), r;
220
- }
221
- }
222
- async trackedUpsert(e) {
223
- try {
224
- const t = await this.upsert(e.model);
225
- return this.trackedStatus.push({ requestId: e.requestId, error: !1, message: "Upserted successfully" }), t;
226
- } catch (t) {
227
- this.trackedStatus.push({ requestId: e.requestId, error: !0, message: t.message });
228
- }
229
- }
230
- async trackedRemove(e) {
231
- try {
232
- const t = await this.remove(e.model);
233
- return this.trackedStatus.push({ requestId: e.requestId, error: !1, message: "Removed successfully" }), t;
234
- } catch (t) {
235
- this.trackedStatus.push({ requestId: e.requestId, error: !0, message: t.message });
236
- }
237
- }
238
- insertIntoStore(e) {
239
- this.value.some((s) => s.id === e.id) ? this.set(this.value.map((s) => s.id === e.id ? e : s)) : this.set([...this.value, e]);
240
- }
241
- removeFromStore(e) {
242
- this.set(this.value.filter((t) => t.id !== e.id));
243
- }
244
- }
245
- export {
246
- p as AbstractStore,
247
- l as DatabaseConnection,
248
- u as Hydrator,
249
- d as ServerConnection
250
- };
@@ -1,8 +0,0 @@
1
- import type { EntityManager, Reference } from "@mikro-orm/core";
2
- import type { BaseModel } from "@declaro/core";
3
- export declare class Hydrator {
4
- private readonly em;
5
- private readonly reference;
6
- constructor(em: EntityManager, reference: typeof Reference);
7
- hydrateEntity<T extends BaseModel<any>>(entity: T): BaseModel<T>;
8
- }
package/dist/index.d.ts DELETED
@@ -1,4 +0,0 @@
1
- export * from './databaseConnection';
2
- export * from './serverConnection';
3
- export * from './datastoreAbstract';
4
- export * from './hydrateEntity';
@@ -1,15 +0,0 @@
1
- import type { IDatastoreProviderWithFetch, BaseModel, BaseModelClass } from '@declaro/core';
2
- import type { FetchFunc } from '@declaro/core';
3
- import type { FilterQuery } from "@mikro-orm/core";
4
- export declare class ServerConnection<T extends BaseModel<any>> implements IDatastoreProviderWithFetch<T> {
5
- private fetch;
6
- private model;
7
- setup(model: BaseModelClass<T>): void;
8
- setFetch(fetch: FetchFunc): void;
9
- getAll(): Promise<any>;
10
- getWhere(filter?: FilterQuery<any>): any;
11
- get(id: string | number): Promise<any>;
12
- upsert(model: T | T[]): Promise<any>;
13
- remove(model: T | T[]): Promise<any>;
14
- _callStoreMethod(method: string, httpMethod: string, payload?: any): Promise<any>;
15
- }
@@ -1,15 +0,0 @@
1
- import type { IStore } from "@declaro/core";
2
- export type RequestStatus = {
3
- requestId: string;
4
- error: boolean;
5
- message: string;
6
- };
7
- export declare class TrackedStatusStore implements IStore {
8
- private value;
9
- private subscribers;
10
- subscribe(subscription: (value: {
11
- [key: string]: RequestStatus;
12
- }) => void): (() => void);
13
- push(status: RequestStatus): void;
14
- remove(requestId: string): void;
15
- }
@@ -1,137 +0,0 @@
1
- import type { IDatastoreProvider, BaseModel, BaseModelClass } from '@declaro/core'
2
- import type { EntityManager, FilterQuery, Reference } from "@mikro-orm/core";
3
- import type { EntityRepository } from '@mikro-orm/postgresql'
4
- import { Hydrator } from "./hydrateEntity";
5
- import type { RemoveReturnType, UpsertReturnType } from "./datastoreAbstract";
6
-
7
- export type DatabaseConnectionOptions = {
8
- populate?: string[];
9
- immutableFields?: string[];
10
- };
11
-
12
-
13
- export class DatabaseConnection<T extends BaseModel<any>> implements IDatastoreProvider<T> {
14
-
15
- private repository : EntityRepository<any>
16
-
17
- public static inject = ['EntityManager', 'Reference'] as const;
18
-
19
- public readonly em: EntityManager;
20
- private hydrator: Hydrator;
21
- private populate;
22
- private immutableFields = [];
23
-
24
- constructor(em : EntityManager, reference: typeof Reference) {
25
- this.em = em;
26
- this.hydrator = new Hydrator(this.em, reference);
27
- }
28
-
29
- setup(model: BaseModelClass<T>, options: DatabaseConnectionOptions) {
30
- this.repository = this.em.getRepository(model);
31
- this.populate = options?.populate;
32
- if (options?.immutableFields) {
33
- this.immutableFields = options.immutableFields;
34
- }
35
- }
36
-
37
- getAll() {
38
- return this.repository.findAll({populate: this.populate}).catch(e => {
39
- console.log(e);
40
- })
41
- }
42
-
43
- getWhere(filter?: FilterQuery<any>) {
44
- return this.repository.find(filter, {populate: this.populate}).catch(e => {
45
- console.log(e);
46
- })
47
- }
48
-
49
- get(id: string | number) {
50
- return this.repository.findOne(id, {populate: this.populate}).catch(e => {
51
- console.log(e);
52
- })
53
- }
54
-
55
- async upsert<T extends BaseModel<any> | BaseModel<any>[]>(data: T): Promise<UpsertReturnType<T>> {
56
- if (Array.isArray(data)) {
57
- const entities: BaseModel<any>[] = [];
58
-
59
- for (const singleData of data) {
60
- const entity = await this.singleUpsert(singleData);
61
- entities.push(entity);
62
- }
63
-
64
- return entities as UpsertReturnType<T>;
65
- } else {
66
- return await this.singleUpsert(data) as UpsertReturnType<T>;
67
- }
68
- }
69
-
70
- private async singleUpsert<T extends BaseModel<any>>(data: T) {
71
- let entity: T;
72
-
73
- // Get entity metadata
74
- const meta = this.em.getMetadata().get(data.constructor.name);
75
-
76
- // Create a shallow copy of data, excluding m:n fields, these are ignored for the
77
- // shallow clone because those aren't stored in the row itself but rather a linking table
78
- const shallowData: Partial<T> = {};
79
- Object.keys(data).forEach((key) => {
80
- const property = meta.properties[key];
81
- if (property && property.reference !== 'm:n') {
82
- shallowData[key] = data[key];
83
- }
84
- });
85
-
86
- if (!data.id) {
87
- // Create new entity with shallow data
88
- entity = this.em.create(data.constructor.name, shallowData as any);
89
- await this.em.persist(entity).flush();
90
- } else {
91
- // Fetch and merge for existing entity
92
- entity = await this.em.findOneOrFail(data.constructor.name, data.id);
93
- }
94
- // NOTE: this is a current hacky workaround to prevent the em.assign call trying to reset the entity's id
95
- // to undefined on an insert. This should probably actually reference the schema metadata to determine the PK
96
- delete data.id;
97
-
98
- this.immutableFields.forEach(f => {
99
- if (f in data) {
100
- data[f] = entity[f];
101
- }
102
- });
103
- // Use em.assign to properly handle m:n relationships for both new and existing entities
104
- this.em.assign(entity, data);
105
- await this.em.persist(entity).flush();
106
-
107
- return entity;
108
- }
109
-
110
- async remove(data: T[] | T): Promise<RemoveReturnType> {
111
- if (Array.isArray(data)) {
112
- const removedIds: (number|string)[] = [];
113
- for (const singleData of data) {
114
- if(await this.singleRemove(singleData)) {
115
- removedIds.push(singleData.id);
116
- }
117
- }
118
- return removedIds;
119
- } else {
120
- return await this.singleRemove(data) ? data.id : null;
121
- }
122
- }
123
-
124
- private async singleRemove<T extends BaseModel<any>>(data: T): Promise<boolean> {
125
- try {
126
- const entity = await this.em.findOneOrFail(data.constructor.name, data.id);
127
- await this.em.remove(entity).flush();
128
- return true;
129
- } catch (e) {
130
- if (e.constructor.name === 'NotFoundError') {
131
- return false;
132
- } else {
133
- throw e;
134
- }
135
- }
136
- }
137
- }
@@ -1,190 +0,0 @@
1
- import type { IDatastoreProvider, IDatastoreProviderWithFetch, BaseModel, BaseModelClass, IStore } from "@declaro/core";
2
- import type { FetchFunc } from '@declaro/core';
3
- import { TrackedStatusStore } from "./trackedStatus";
4
- import type { FilterQuery } from "@mikro-orm/core";
5
-
6
- export type TrackedPayload<T> = {
7
- model: T,
8
- requestId: string,
9
- optimistic?: boolean
10
- }
11
-
12
- export type UpsertReturnType<T> = T extends (infer U)[] ? U[] : T;
13
- export type RemoveReturnType = (number|string)[] | number | string | null;
14
-
15
- export abstract class AbstractStore<T extends BaseModel<any>> implements IStore{
16
- protected value: T[] = [];
17
- private subscribers: Array<(value: T[]) => void> = [];
18
-
19
- private hydrated = false;
20
-
21
- public trackedStatus = new TrackedStatusStore();
22
-
23
- protected constructor(
24
- protected connection: IDatastoreProvider<T>,
25
- protected model: BaseModelClass<T>,
26
- protected options?: any)
27
- {
28
- this.connection.setup(this.model, options);
29
- }
30
-
31
- subscribe(subscription: (value: T[]) => void): (() => void) {
32
- // Add the new subscriber to the subscribers array
33
- this.subscribers.push(subscription);
34
-
35
- // Immediately call the subscription with the current value
36
- subscription(this.value);
37
-
38
- // Return an unsubscribe function
39
- return () => {
40
- // Remove the subscriber from the subscribers array
41
- this.subscribers = this.subscribers.filter(sub => sub !== subscription);
42
- };
43
- }
44
-
45
- setFetch(fetch: FetchFunc) {
46
- const connectionWithFetch = this.connection as IDatastoreProviderWithFetch<T>;
47
-
48
- if (connectionWithFetch.setFetch) {
49
- connectionWithFetch.setFetch(fetch);
50
- }
51
- }
52
-
53
- set(value: T[]) {
54
- // Update the current value
55
- this.value = value;
56
-
57
- // Notify all subscribers of the new value
58
- this.subscribers.forEach(sub => sub(value));
59
- }
60
-
61
- async get(value: string | number) {
62
- await this.hydrate(value)
63
-
64
- if (typeof this.value == 'undefined') {
65
- return null;
66
- }
67
-
68
- const matches = this.value.filter((i: T) => {
69
- return i.id == value;
70
- });
71
- return matches[0];
72
- }
73
-
74
- async getWhere(filter?: FilterQuery<any>) {
75
- await this.hydrate(null, filter);
76
- return this.value;
77
- }
78
-
79
- async getAll() {
80
- await this.hydrate();
81
- return this.value;
82
- }
83
-
84
- async hydrate(id?: string | number, filter?: FilterQuery<any>): Promise<void> {
85
- if (this.hydrated && !filter) {
86
- return;
87
- }
88
- if (filter) {
89
- const v = await this.connection.getWhere(filter);
90
- if (v) {
91
- this.set(v);
92
- }
93
- } else if (!id) {
94
- const v = await this.connection.getAll();
95
- if (v) {
96
- this.set(v);
97
- }
98
- } else if (!filter) {
99
- const v = await this.connection.get(id);
100
- if (v) {
101
- this.set([v]);
102
- }
103
- }
104
- this.hydrated = true;
105
- }
106
-
107
- async upsert(model: T | T[], optimistic: boolean = false): Promise<UpsertReturnType<T>> {
108
- if (Array.isArray(model)) {
109
- const objArray = model.map(m => Object.assign(new this.model(), m));
110
- if (optimistic) {
111
- objArray.forEach(obj => this.insertIntoStore(obj));
112
- }
113
-
114
- const updatedArray: T[] = await this.connection.upsert(objArray);
115
- updatedArray.forEach(obj => this.insertIntoStore(obj));
116
-
117
- return updatedArray as UpsertReturnType<T>;
118
- } else {
119
- const obj = Object.assign(new this.model(), model);
120
- if (optimistic) {
121
- this.insertIntoStore(obj);
122
- }
123
-
124
- const updated: T = await this.connection.upsert(obj);
125
- this.insertIntoStore(updated);
126
-
127
- return updated as UpsertReturnType<T>;
128
- }
129
- }
130
-
131
- async remove(model: T | T[], optimistic: boolean = false): Promise<RemoveReturnType> {
132
- if (Array.isArray(model)) {
133
- const objArray = model.map(m => Object.assign(new this.model(), m));
134
- if (optimistic) {
135
- objArray.forEach(obj => this.removeFromStore(obj));
136
- }
137
-
138
- const result: RemoveReturnType = await this.connection.remove(objArray);
139
- objArray.forEach(obj => this.removeFromStore(obj));
140
- return result;
141
- } else {
142
- const obj = Object.assign(new this.model(), model);
143
- if (optimistic) {
144
- this.removeFromStore(obj);
145
- }
146
-
147
- const result: RemoveReturnType = await this.connection.remove(obj);
148
- this.removeFromStore(obj);
149
- return result;
150
- }
151
- }
152
-
153
- async trackedUpsert(payload: TrackedPayload<T | T[]>): Promise<UpsertReturnType<T>> {
154
- try {
155
- const ret = await this.upsert(payload.model);
156
- this.trackedStatus.push({ requestId: payload.requestId, error: false, message: 'Upserted successfully' });
157
- return ret;
158
- } catch (e) {
159
- this.trackedStatus.push({ requestId: payload.requestId, error: true, message: e.message });
160
- }
161
- }
162
-
163
- async trackedRemove(payload: TrackedPayload<T | T[]>): Promise<RemoveReturnType> {
164
- try {
165
- const ret = await this.remove(payload.model);
166
- this.trackedStatus.push({ requestId: payload.requestId, error: false, message: 'Removed successfully' });
167
- return ret;
168
- } catch (e) {
169
- this.trackedStatus.push({ requestId: payload.requestId, error: true, message: e.message });
170
- }
171
- }
172
-
173
- insertIntoStore(obj: T) {
174
- const exists = this.value.some((i: T) => i.id === obj.id);
175
- if (exists) {
176
- this.set(this.value.map((i: T) => i.id === obj.id ? obj : i));
177
- } else {
178
- this.set([...this.value, obj]);
179
- }
180
- }
181
-
182
- removeFromStore(obj: T) {
183
- this.set(this.value.filter((i: T) => i.id !== obj.id));
184
- }
185
- }
186
-
187
- // this is useful for dynamic references to methods on concrete extensions of this class
188
- export type ActionableStore = AbstractStore<BaseModel<any>> & {
189
- [key: string]: (...args: any[]) => any;
190
- };
@@ -1,36 +0,0 @@
1
- import type { EntityManager, Reference, EntityProperty } from "@mikro-orm/core";
2
- import type { BaseModel } from "@declaro/core";
3
- import type { EntitySchema } from "@mikro-orm/core";
4
-
5
- export class Hydrator {
6
- constructor(
7
- private readonly em: EntityManager,
8
- private readonly reference: typeof Reference,
9
- ) {}
10
-
11
- hydrateEntity<T extends BaseModel<any>>(
12
- entity: T
13
- ): BaseModel<T> {
14
- const metadata = this.em.getMetadata().get(entity.constructor.name);
15
-
16
- for (const prop in entity) {
17
- const property: EntityProperty = metadata.properties[prop];
18
-
19
- // Check if this property is a relation (ManyToOne, OneToOne, etc.)
20
- if (
21
- entity[prop] !== undefined
22
- && entity[prop] !== null
23
- && property && ['m:1', '1:1'].includes(property.reference)
24
- ) {
25
- // in EntitySchema mode Mikro allows the entity to be another schema instead of an EntityName
26
- const entitySchema = property.entity() as EntitySchema;
27
-
28
- // this is force to an 'any' here because Mikro can understand a 'Reference' on an instance of our entity
29
- // even when it's our native entity instead of a Mikro entity (User vs Entity<User>)
30
- entity[prop] = this.reference.createFromPK(entitySchema.meta.class, entity[prop]) as any;
31
- }
32
- }
33
-
34
- return entity;
35
- }
36
- }
@@ -1,7 +0,0 @@
1
- import { describe, it, expect } from 'vitest'
2
-
3
- describe('Placeholder', () => {
4
- it('should pass', () => {
5
- expect(true).toBe(true)
6
- })
7
- })
@@ -1,74 +0,0 @@
1
- import type { IDatastoreProviderWithFetch, BaseModel, BaseModelClass } from '@declaro/core'
2
- import type { FetchFunc } from '@declaro/core'
3
- import type { FilterQuery } from "@mikro-orm/core";
4
-
5
- export class ServerConnection<T extends BaseModel<any>> implements IDatastoreProviderWithFetch<T> {
6
-
7
- private fetch: FetchFunc;
8
- private model: BaseModelClass<T>;
9
-
10
- setup(model: BaseModelClass<T>) {
11
- this.model = model;
12
- }
13
-
14
- setFetch(fetch: FetchFunc) {
15
- this.fetch = fetch;
16
- }
17
-
18
- getAll(): Promise<any> {
19
- return this.fetch(`/store/${this.model.name}/getAll`).then(r => {
20
- return r.json().then((objs: any[]) => {
21
- // turn results back into objects of the correct type
22
- return objs.map(o => Object.assign(new this.model(), o));
23
- });
24
- });
25
- }
26
-
27
- getWhere(filter?: FilterQuery<any>) {
28
- return this.fetch(`/store/${this.model.name}/getWhere/${JSON.stringify(filter)}`).then(r => {
29
- return r.json().then((objs: any[]) => {
30
- // turn results back into objects of the correct type
31
- return objs.map(o => Object.assign(new this.model(), o));
32
- });
33
- });
34
- }
35
-
36
- get(id: string | number): Promise<any> {
37
- return this.fetch(`/store/${this.model.name}/get/${id}`).then(r => {
38
- return r.json();
39
- })
40
- }
41
-
42
- upsert(model: T | T[]): Promise<any> {
43
- return this._callStoreMethod('upsert', 'POST', model);
44
- }
45
-
46
- remove(model: T | T[]): Promise<any> {
47
- return this._callStoreMethod('remove', 'POST', model);
48
- }
49
-
50
- _callStoreMethod(method: string, httpMethod: string, payload: any = null): Promise<any> {
51
- let headers = {};
52
-
53
- if (payload) {
54
- headers['Content-Type'] = 'application/json;'
55
- headers['Accept'] = 'application/json;'
56
- }
57
-
58
- return this.fetch(
59
- `/store/${this.model.name}/${method}`,
60
- {
61
- method: httpMethod,
62
- body: payload ? JSON.stringify(payload) : null,
63
- headers
64
- }
65
- ).then(async r => {
66
- const data = await r.json();
67
- if (!r.ok) {
68
- throw Error(data.message);
69
- } else {
70
- return data;
71
- }
72
- });
73
- }
74
- }
@@ -1,35 +0,0 @@
1
- import type { IStore } from "@declaro/core";
2
-
3
- export type RequestStatus = { requestId: string, error: boolean, message: string }
4
-
5
- export class TrackedStatusStore implements IStore {
6
- private value: { [key: string]: RequestStatus } = {};
7
- private subscribers: Array<(value: { [key: string]: RequestStatus }) => void> = [];
8
-
9
- subscribe(subscription: (value: { [key: string]: RequestStatus }) => void): (() => void) {
10
- // Add the new subscriber to the subscribers array
11
- this.subscribers.push(subscription);
12
-
13
- // Immediately call the subscription with the current value
14
- subscription(this.value);
15
-
16
- // Return an unsubscribe function
17
- return () => {
18
- // Remove the subscriber from the subscribers array
19
- this.subscribers = this.subscribers.filter(sub => sub !== subscription);
20
- };
21
- }
22
-
23
- public push(status: RequestStatus) {
24
- this.value = { ...this.value, [status.requestId]: status };
25
-
26
- this.subscribers.forEach(sub => sub(this.value));
27
- }
28
-
29
- public remove(requestId: string) {
30
- const { [requestId]: removedError, ...rest } = this.value;
31
- this.value = rest;
32
-
33
- this.subscribers.forEach(sub => sub(this.value));
34
- }
35
- }
package/tsconfig.json DELETED
@@ -1,10 +0,0 @@
1
- {
2
- "extends": ["../../tsconfig.json"],
3
- "compilerOptions": {
4
- "sourceMap": true
5
- },
6
- "include": ["src/*.ts", "src/**/*.ts", "src/**/*.d.ts"],
7
- "buildOptions": {
8
- "outDir": "dist"
9
- }
10
- }
package/vite.config.ts DELETED
@@ -1,23 +0,0 @@
1
- import { resolve } from 'path'
2
- import { defineConfig } from 'vitest/config'
3
- import dts from 'vite-plugin-dts'
4
-
5
- const extensions = {
6
- es: 'mjs',
7
- cjs: 'cjs',
8
- }
9
-
10
- export default defineConfig({
11
- build: {
12
- lib: {
13
- entry: resolve(__dirname, 'src/index.ts'),
14
- name: 'DeclaroData',
15
- formats: ['es', 'cjs'],
16
- fileName: (format) => `declaro-data.${extensions[format]}`,
17
- },
18
- },
19
- plugins: [dts()],
20
- optimizeDeps: {
21
- include: ['src/**/*'],
22
- },
23
- })