@declaro/data 2.0.0-beta.9 → 2.0.0-beta.91

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.
Files changed (109) hide show
  1. package/{LICENSE → LICENSE.md} +1 -1
  2. package/README.md +0 -0
  3. package/dist/browser/index.js +32 -0
  4. package/dist/browser/index.js.map +86 -0
  5. package/dist/node/index.cjs +11547 -0
  6. package/dist/node/index.cjs.map +86 -0
  7. package/dist/node/index.js +11526 -0
  8. package/dist/node/index.js.map +86 -0
  9. package/dist/ts/application/model-controller.d.ts +29 -0
  10. package/dist/ts/application/model-controller.d.ts.map +1 -0
  11. package/dist/ts/application/model-controller.test.d.ts +2 -0
  12. package/dist/ts/application/model-controller.test.d.ts.map +1 -0
  13. package/dist/ts/application/read-only-model-controller.d.ts +20 -0
  14. package/dist/ts/application/read-only-model-controller.d.ts.map +1 -0
  15. package/dist/ts/application/read-only-model-controller.test.d.ts +2 -0
  16. package/dist/ts/application/read-only-model-controller.test.d.ts.map +1 -0
  17. package/dist/ts/domain/events/domain-event.d.ts +41 -0
  18. package/dist/ts/domain/events/domain-event.d.ts.map +1 -0
  19. package/dist/ts/domain/events/domain-event.test.d.ts +2 -0
  20. package/dist/ts/domain/events/domain-event.test.d.ts.map +1 -0
  21. package/dist/ts/domain/events/event-types.d.ts +21 -0
  22. package/dist/ts/domain/events/event-types.d.ts.map +1 -0
  23. package/dist/ts/domain/events/mutation-event.d.ts +6 -0
  24. package/dist/ts/domain/events/mutation-event.d.ts.map +1 -0
  25. package/dist/ts/domain/events/mutation-event.test.d.ts +2 -0
  26. package/dist/ts/domain/events/mutation-event.test.d.ts.map +1 -0
  27. package/dist/ts/domain/events/query-event.d.ts +6 -0
  28. package/dist/ts/domain/events/query-event.d.ts.map +1 -0
  29. package/dist/ts/domain/events/query-event.test.d.ts +2 -0
  30. package/dist/ts/domain/events/query-event.test.d.ts.map +1 -0
  31. package/dist/ts/domain/events/request-event.d.ts +11 -0
  32. package/dist/ts/domain/events/request-event.d.ts.map +1 -0
  33. package/dist/ts/domain/events/request-event.test.d.ts +2 -0
  34. package/dist/ts/domain/events/request-event.test.d.ts.map +1 -0
  35. package/dist/ts/domain/interfaces/repository.d.ts +84 -0
  36. package/dist/ts/domain/interfaces/repository.d.ts.map +1 -0
  37. package/dist/ts/domain/models/pagination.d.ts +28 -0
  38. package/dist/ts/domain/models/pagination.d.ts.map +1 -0
  39. package/dist/ts/domain/services/base-model-service.d.ts +22 -0
  40. package/dist/ts/domain/services/base-model-service.d.ts.map +1 -0
  41. package/dist/ts/domain/services/model-service-args.d.ts +9 -0
  42. package/dist/ts/domain/services/model-service-args.d.ts.map +1 -0
  43. package/dist/ts/domain/services/model-service.d.ts +42 -0
  44. package/dist/ts/domain/services/model-service.d.ts.map +1 -0
  45. package/dist/ts/domain/services/model-service.test.d.ts +2 -0
  46. package/dist/ts/domain/services/model-service.test.d.ts.map +1 -0
  47. package/dist/ts/domain/services/read-only-model-service.d.ts +40 -0
  48. package/dist/ts/domain/services/read-only-model-service.d.ts.map +1 -0
  49. package/dist/ts/domain/services/read-only-model-service.test.d.ts +2 -0
  50. package/dist/ts/domain/services/read-only-model-service.test.d.ts.map +1 -0
  51. package/dist/ts/index.d.ts +18 -0
  52. package/dist/ts/index.d.ts.map +1 -0
  53. package/dist/ts/shared/utils/schema-inference.d.ts +23 -0
  54. package/dist/ts/shared/utils/schema-inference.d.ts.map +1 -0
  55. package/dist/ts/shared/utils/schema-inheritance.d.ts +24 -0
  56. package/dist/ts/shared/utils/schema-inheritance.d.ts.map +1 -0
  57. package/dist/ts/test/domain/services/model-service.test.d.ts +1 -0
  58. package/dist/ts/test/domain/services/model-service.test.d.ts.map +1 -0
  59. package/dist/ts/test/mock/models/mock-book-models.d.ts +42 -0
  60. package/dist/ts/test/mock/models/mock-book-models.d.ts.map +1 -0
  61. package/dist/ts/test/mock/repositories/mock-memory-repository.d.ts +36 -0
  62. package/dist/ts/test/mock/repositories/mock-memory-repository.d.ts.map +1 -0
  63. package/dist/ts/test/mock/repositories/mock-memory-repository.test.d.ts +2 -0
  64. package/dist/ts/test/mock/repositories/mock-memory-repository.test.d.ts.map +1 -0
  65. package/package.json +45 -42
  66. package/src/application/model-controller.test.ts +488 -0
  67. package/src/application/model-controller.ts +92 -0
  68. package/src/application/read-only-model-controller.test.ts +327 -0
  69. package/src/application/read-only-model-controller.ts +61 -0
  70. package/src/domain/events/domain-event.test.ts +82 -0
  71. package/src/domain/events/domain-event.ts +69 -0
  72. package/src/domain/events/event-types.ts +21 -0
  73. package/src/domain/events/mutation-event.test.ts +38 -0
  74. package/src/domain/events/mutation-event.ts +8 -0
  75. package/src/domain/events/query-event.test.ts +28 -0
  76. package/src/domain/events/query-event.ts +8 -0
  77. package/src/domain/events/request-event.test.ts +38 -0
  78. package/src/domain/events/request-event.ts +32 -0
  79. package/src/domain/interfaces/repository.ts +107 -0
  80. package/src/domain/models/pagination.ts +28 -0
  81. package/src/domain/services/base-model-service.ts +50 -0
  82. package/src/domain/services/model-service-args.ts +9 -0
  83. package/src/domain/services/model-service.test.ts +631 -0
  84. package/src/domain/services/model-service.ts +322 -0
  85. package/src/domain/services/read-only-model-service.test.ts +296 -0
  86. package/src/domain/services/read-only-model-service.ts +133 -0
  87. package/src/index.ts +17 -4
  88. package/src/shared/utils/schema-inference.ts +26 -0
  89. package/src/shared/utils/schema-inheritance.ts +28 -0
  90. package/src/test/domain/services/model-service.test.ts +0 -0
  91. package/src/test/mock/models/mock-book-models.ts +78 -0
  92. package/src/test/mock/repositories/mock-memory-repository.test.ts +715 -0
  93. package/src/test/mock/repositories/mock-memory-repository.ts +235 -0
  94. package/dist/databaseConnection.d.ts +0 -24
  95. package/dist/datastoreAbstract.d.ts +0 -37
  96. package/dist/declaro-data.cjs +0 -1
  97. package/dist/declaro-data.mjs +0 -250
  98. package/dist/hydrateEntity.d.ts +0 -8
  99. package/dist/index.d.ts +0 -4
  100. package/dist/serverConnection.d.ts +0 -15
  101. package/dist/trackedStatus.d.ts +0 -15
  102. package/src/databaseConnection.ts +0 -137
  103. package/src/datastoreAbstract.ts +0 -190
  104. package/src/hydrateEntity.ts +0 -36
  105. package/src/placeholder.test.ts +0 -7
  106. package/src/serverConnection.ts +0 -74
  107. package/src/trackedStatus.ts +0 -35
  108. package/tsconfig.json +0 -10
  109. package/vite.config.ts +0 -23
@@ -0,0 +1,235 @@
1
+ import type { AnyModelSchema, IModelEntityMetadata, JSONSchema, Model } from '@declaro/core'
2
+ import type { IRepository } from '../../../domain/interfaces/repository'
3
+ import type { IPaginationInput } from '../../../domain/models/pagination'
4
+ import type {
5
+ InferDetail,
6
+ InferFilters,
7
+ InferInput,
8
+ InferLookup,
9
+ InferSearchResults,
10
+ InferSummary,
11
+ } from '../../../shared/utils/schema-inference'
12
+ import { v4 as uuid } from 'uuid'
13
+ import type { ISearchOptions } from '../../../domain/services/read-only-model-service'
14
+ import type { ICreateOptions, IUpdateOptions } from '../../../domain/services/model-service'
15
+
16
+ export interface IMockMemoryRepositoryArgs<TSchema extends AnyModelSchema> {
17
+ schema: TSchema
18
+ lookup?: (data: InferDetail<TSchema>, lookup: InferLookup<TSchema>) => boolean
19
+ filter?: (data: InferSummary<TSchema>, filters: InferFilters<TSchema>) => boolean
20
+ }
21
+
22
+ export class MockMemoryRepository<TSchema extends AnyModelSchema> implements IRepository<TSchema> {
23
+ protected data = new Map<string, InferDetail<TSchema>>()
24
+ protected trash = new Map<string, InferDetail<TSchema>>()
25
+ protected entityMetadata: IModelEntityMetadata
26
+ protected nextId: number = 0
27
+
28
+ constructor(protected args: IMockMemoryRepositoryArgs<TSchema>) {
29
+ this.entityMetadata = this.args.schema.getEntityMetadata()
30
+ if (!this.entityMetadata?.primaryKey) {
31
+ throw new Error('Primary key must be specified for MockMemoryRepository')
32
+ }
33
+ }
34
+
35
+ async load(input: InferLookup<TSchema>): Promise<InferDetail<TSchema> | null> {
36
+ if (!this.entityMetadata?.primaryKey) {
37
+ throw new Error('Primary key is not defined in the schema metadata')
38
+ }
39
+
40
+ let item: InferDetail<TSchema> | undefined
41
+ if (typeof this.args.lookup === 'function') {
42
+ item = Array.from(this.data.values()).find((data) => this.args.lookup!(data, input))
43
+ } else {
44
+ // Default lookup by primary key
45
+ item = await this.data.get(input[this.entityMetadata.primaryKey])
46
+ }
47
+
48
+ return item || null
49
+ }
50
+ async loadMany(inputs: InferLookup<TSchema>[]): Promise<InferDetail<TSchema>[]> {
51
+ if (!this.entityMetadata?.primaryKey) {
52
+ throw new Error('Primary key is not defined in the schema metadata')
53
+ }
54
+
55
+ const items = await Promise.all(inputs.map((input) => this.data.get(input[this.entityMetadata.primaryKey!])))
56
+ return items
57
+ }
58
+ async search(
59
+ input: InferFilters<TSchema>,
60
+ options?: ISearchOptions<TSchema>,
61
+ ): Promise<InferSearchResults<TSchema>> {
62
+ const pagination = options?.pagination || { page: 1, pageSize: 25 }
63
+ let items = this.applyFilters(input)
64
+
65
+ // Apply sorting if provided
66
+ if (options?.sort && Array.isArray(options.sort)) {
67
+ items = items.sort((a, b) => {
68
+ for (const sortField of options.sort! as any[]) {
69
+ for (const [field, direction] of Object.entries(sortField)) {
70
+ if (!direction || typeof direction !== 'string') continue
71
+
72
+ const aValue = a[field as keyof typeof a]
73
+ const bValue = b[field as keyof typeof b]
74
+
75
+ let comparison = 0
76
+ if (aValue < bValue) comparison = -1
77
+ else if (aValue > bValue) comparison = 1
78
+
79
+ if (comparison !== 0) {
80
+ // Handle different sort directions
81
+ const isDesc = direction.includes('desc')
82
+ return isDesc ? -comparison : comparison
83
+ }
84
+ }
85
+ }
86
+ return 0
87
+ })
88
+ }
89
+
90
+ return {
91
+ results: items.slice(
92
+ ((pagination?.page ?? 1) - 1) * (pagination?.pageSize ?? 25),
93
+ (pagination?.page ?? 1) * (pagination?.pageSize ?? 25),
94
+ ),
95
+ pagination: {
96
+ total: items.length,
97
+ totalPages: Math.ceil(items.length / (pagination?.pageSize ?? 25)),
98
+ ...pagination,
99
+ page: pagination?.page ?? 1,
100
+ pageSize: pagination?.pageSize ?? 25,
101
+ },
102
+ }
103
+ }
104
+ async remove(lookup: InferLookup<TSchema>): Promise<InferSummary<TSchema>> {
105
+ if (!this.entityMetadata?.primaryKey) {
106
+ throw new Error('Primary key is not defined in the schema metadata')
107
+ }
108
+
109
+ const item = await this.data.get(lookup[this.entityMetadata.primaryKey])
110
+ if (!item) {
111
+ throw new Error('Item not found')
112
+ }
113
+ // Move the item to trash
114
+ this.trash.set(lookup[this.entityMetadata.primaryKey], item)
115
+ // Remove the item from data
116
+ this.data.delete(lookup[this.entityMetadata.primaryKey])
117
+ return item
118
+ }
119
+ async restore(lookup: InferLookup<TSchema>): Promise<InferSummary<TSchema>> {
120
+ if (!this.entityMetadata?.primaryKey) {
121
+ throw new Error('Primary key is not defined in the schema metadata')
122
+ }
123
+
124
+ const item = await this.trash.get(lookup[this.entityMetadata.primaryKey])
125
+ if (!item) {
126
+ throw new Error('Item not found in trash')
127
+ }
128
+ this.trash.delete(lookup[this.entityMetadata.primaryKey])
129
+ this.data.set(lookup[this.entityMetadata.primaryKey], item)
130
+ return item
131
+ }
132
+
133
+ async create(input: InferInput<TSchema>): Promise<InferDetail<TSchema>> {
134
+ if (!this.entityMetadata?.primaryKey) {
135
+ throw new Error('Primary key is not defined in the schema metadata')
136
+ }
137
+ const primaryKeyValue = input[this.entityMetadata.primaryKey]
138
+
139
+ if (primaryKeyValue && this.data.has(primaryKeyValue)) {
140
+ throw new Error('Item with the same primary key already exists')
141
+ }
142
+
143
+ const payload = {
144
+ ...(input as any),
145
+ }
146
+
147
+ if (!payload[this.entityMetadata.primaryKey]) {
148
+ // Generate a new primary key if not provided
149
+ payload[this.entityMetadata.primaryKey!] = await this.generatePrimaryKey()
150
+ }
151
+
152
+ this.data.set(payload[this.entityMetadata.primaryKey!], payload as InferDetail<TSchema>)
153
+ return payload as InferDetail<TSchema>
154
+ }
155
+
156
+ async update(lookup: InferLookup<TSchema>, input: InferInput<TSchema>): Promise<InferDetail<TSchema>> {
157
+ if (!this.entityMetadata?.primaryKey) {
158
+ throw new Error('Primary key is not defined in the schema metadata')
159
+ }
160
+ const primaryKeyValue = lookup[this.entityMetadata.primaryKey]
161
+ if (!primaryKeyValue) {
162
+ throw new Error('Primary key value must be provided')
163
+ }
164
+
165
+ const existingItem = this.data.get(primaryKeyValue)
166
+ if (!existingItem) {
167
+ throw new Error('Item not found')
168
+ }
169
+
170
+ const updatedItem = Object.assign({}, existingItem, input) as InferDetail<TSchema>
171
+ this.data.set(primaryKeyValue, updatedItem)
172
+ return updatedItem
173
+ }
174
+
175
+ async count(search: InferFilters<TSchema>, options?: ISearchOptions<TSchema> | undefined): Promise<number> {
176
+ const filteredItems = this.applyFilters(search)
177
+ return filteredItems.length
178
+ }
179
+
180
+ async upsert(input: InferInput<TSchema>, options?: ICreateOptions | IUpdateOptions): Promise<InferDetail<TSchema>> {
181
+ const primaryKeyValue = input[this.entityMetadata.primaryKey]
182
+ let existingItem: InferDetail<TSchema> | undefined = undefined
183
+
184
+ if (primaryKeyValue) {
185
+ existingItem = this.data.get(primaryKeyValue) ?? {}
186
+ }
187
+
188
+ const updatedItem = Object.assign({}, existingItem, input) as InferDetail<TSchema>
189
+ if (!updatedItem[this.entityMetadata.primaryKey!]) {
190
+ updatedItem[this.entityMetadata.primaryKey!] = await this.generatePrimaryKey()
191
+ }
192
+
193
+ this.data.set(updatedItem[this.entityMetadata.primaryKey!], updatedItem)
194
+
195
+ return updatedItem
196
+ }
197
+
198
+ async bulkUpsert(
199
+ inputs: InferInput<TSchema>[],
200
+ options?: ICreateOptions | IUpdateOptions,
201
+ ): Promise<InferDetail<TSchema>[]> {
202
+ return await Promise.all(inputs.map((input) => this.upsert(input, options)))
203
+ }
204
+
205
+ /**
206
+ * Apply filtering logic to all items based on the provided search criteria
207
+ * @param input - The search/filter criteria
208
+ * @returns Filtered array of items
209
+ */
210
+ protected applyFilters(input: InferFilters<TSchema>): InferDetail<TSchema>[] {
211
+ return Array.from(this.data.values()).filter((item) => {
212
+ // Apply filtering logic based on the input
213
+ if (typeof this.args.filter === 'function') {
214
+ return this.args.filter(item, input)
215
+ } else {
216
+ return true
217
+ }
218
+ })
219
+ }
220
+
221
+ protected async generatePrimaryKey() {
222
+ const lookupModel: Model<any, any> = this.args.schema.definition.lookup
223
+ const lookupMeta = await lookupModel.toJSONSchema()
224
+ const primaryKeyMeta = lookupMeta.properties?.[this.entityMetadata.primaryKey!] as JSONSchema
225
+ const type = primaryKeyMeta.type as string
226
+
227
+ if (type === 'string') {
228
+ return uuid()
229
+ } else if (['number', 'integer'].includes(type)) {
230
+ return ++this.nextId
231
+ } else {
232
+ throw new Error(`Unsupported primary key type: ${type}`)
233
+ }
234
+ }
235
+ }
@@ -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
- }