@b2bc-devkit/sheetorm 1.2.3 → 1.2.4
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/npm/SheetOrm.d.ts +41 -0
- package/dist/npm/SheetOrm.d.ts.map +1 -0
- package/dist/npm/SheetOrm.js +41 -0
- package/dist/npm/SheetOrm.js.map +1 -0
- package/dist/npm/core/Decorators.d.ts +145 -0
- package/dist/npm/core/Decorators.d.ts.map +1 -0
- package/dist/npm/core/Decorators.js +226 -0
- package/dist/npm/core/Decorators.js.map +1 -0
- package/dist/npm/core/Record.d.ts +184 -0
- package/dist/npm/core/Record.d.ts.map +1 -0
- package/dist/npm/core/Record.js +321 -0
- package/dist/npm/core/Record.js.map +1 -0
- package/dist/npm/core/RecordConstructor.d.ts +20 -0
- package/dist/npm/core/RecordConstructor.d.ts.map +1 -0
- package/dist/npm/core/RecordConstructor.js +2 -0
- package/dist/npm/core/RecordConstructor.js.map +1 -0
- package/dist/npm/core/RecordStatic.d.ts +25 -0
- package/dist/npm/core/RecordStatic.d.ts.map +1 -0
- package/dist/npm/core/RecordStatic.js +2 -0
- package/dist/npm/core/RecordStatic.js.map +1 -0
- package/dist/npm/core/Registry.d.ts +101 -0
- package/dist/npm/core/Registry.d.ts.map +1 -0
- package/dist/npm/core/Registry.js +231 -0
- package/dist/npm/core/Registry.js.map +1 -0
- package/dist/npm/core/SheetRepository.d.ts +331 -0
- package/dist/npm/core/SheetRepository.d.ts.map +1 -0
- package/dist/npm/core/SheetRepository.js +1041 -0
- package/dist/npm/core/SheetRepository.js.map +1 -0
- package/dist/npm/core/cache/MemoryCache.d.ts +67 -0
- package/dist/npm/core/cache/MemoryCache.d.ts.map +1 -0
- package/dist/npm/core/cache/MemoryCache.js +112 -0
- package/dist/npm/core/cache/MemoryCache.js.map +1 -0
- package/dist/npm/core/types/Entity.d.ts +21 -0
- package/dist/npm/core/types/Entity.d.ts.map +1 -0
- package/dist/npm/core/types/Entity.js +2 -0
- package/dist/npm/core/types/Entity.js.map +1 -0
- package/dist/npm/core/types/FieldDefinition.d.ts +21 -0
- package/dist/npm/core/types/FieldDefinition.d.ts.map +1 -0
- package/dist/npm/core/types/FieldDefinition.js +2 -0
- package/dist/npm/core/types/FieldDefinition.js.map +1 -0
- package/dist/npm/core/types/FieldType.d.ts +12 -0
- package/dist/npm/core/types/FieldType.d.ts.map +1 -0
- package/dist/npm/core/types/FieldType.js +2 -0
- package/dist/npm/core/types/FieldType.js.map +1 -0
- package/dist/npm/core/types/Filter.d.ts +16 -0
- package/dist/npm/core/types/Filter.d.ts.map +1 -0
- package/dist/npm/core/types/Filter.js +2 -0
- package/dist/npm/core/types/Filter.js.map +1 -0
- package/dist/npm/core/types/FilterOperator.d.ts +16 -0
- package/dist/npm/core/types/FilterOperator.d.ts.map +1 -0
- package/dist/npm/core/types/FilterOperator.js +2 -0
- package/dist/npm/core/types/FilterOperator.js.map +1 -0
- package/dist/npm/core/types/GroupResult.d.ts +14 -0
- package/dist/npm/core/types/GroupResult.d.ts.map +1 -0
- package/dist/npm/core/types/GroupResult.js +2 -0
- package/dist/npm/core/types/GroupResult.js.map +1 -0
- package/dist/npm/core/types/ICacheProvider.d.ts +20 -0
- package/dist/npm/core/types/ICacheProvider.d.ts.map +1 -0
- package/dist/npm/core/types/ICacheProvider.js +2 -0
- package/dist/npm/core/types/ICacheProvider.js.map +1 -0
- package/dist/npm/core/types/ISheetAdapter.d.ts +53 -0
- package/dist/npm/core/types/ISheetAdapter.d.ts.map +1 -0
- package/dist/npm/core/types/ISheetAdapter.js +2 -0
- package/dist/npm/core/types/ISheetAdapter.js.map +1 -0
- package/dist/npm/core/types/ISpreadsheetAdapter.d.ts +49 -0
- package/dist/npm/core/types/ISpreadsheetAdapter.d.ts.map +1 -0
- package/dist/npm/core/types/ISpreadsheetAdapter.js +2 -0
- package/dist/npm/core/types/ISpreadsheetAdapter.js.map +1 -0
- package/dist/npm/core/types/IndexDefinition.d.ts +16 -0
- package/dist/npm/core/types/IndexDefinition.d.ts.map +1 -0
- package/dist/npm/core/types/IndexDefinition.js +2 -0
- package/dist/npm/core/types/IndexDefinition.js.map +1 -0
- package/dist/npm/core/types/LifecycleHooks.d.ts +32 -0
- package/dist/npm/core/types/LifecycleHooks.d.ts.map +1 -0
- package/dist/npm/core/types/LifecycleHooks.js +2 -0
- package/dist/npm/core/types/LifecycleHooks.js.map +1 -0
- package/dist/npm/core/types/PaginatedResult.d.ts +18 -0
- package/dist/npm/core/types/PaginatedResult.d.ts.map +1 -0
- package/dist/npm/core/types/PaginatedResult.js +2 -0
- package/dist/npm/core/types/PaginatedResult.js.map +1 -0
- package/dist/npm/core/types/QueryOptions.d.ts +21 -0
- package/dist/npm/core/types/QueryOptions.d.ts.map +1 -0
- package/dist/npm/core/types/QueryOptions.js +2 -0
- package/dist/npm/core/types/QueryOptions.js.map +1 -0
- package/dist/npm/core/types/SortClause.d.ts +10 -0
- package/dist/npm/core/types/SortClause.d.ts.map +1 -0
- package/dist/npm/core/types/SortClause.js +2 -0
- package/dist/npm/core/types/SortClause.js.map +1 -0
- package/dist/npm/core/types/SystemColumns.d.ts +16 -0
- package/dist/npm/core/types/SystemColumns.d.ts.map +1 -0
- package/dist/npm/core/types/SystemColumns.js +16 -0
- package/dist/npm/core/types/SystemColumns.js.map +1 -0
- package/dist/npm/core/types/TableSchema.d.ts +24 -0
- package/dist/npm/core/types/TableSchema.d.ts.map +1 -0
- package/dist/npm/core/types/TableSchema.js +2 -0
- package/dist/npm/core/types/TableSchema.js.map +1 -0
- package/dist/npm/index/IndexMeta.d.ts +16 -0
- package/dist/npm/index/IndexMeta.d.ts.map +1 -0
- package/dist/npm/index/IndexMeta.js +2 -0
- package/dist/npm/index/IndexMeta.js.map +1 -0
- package/dist/npm/index/IndexStore.d.ts +397 -0
- package/dist/npm/index/IndexStore.d.ts.map +1 -0
- package/dist/npm/index/IndexStore.js +1102 -0
- package/dist/npm/index/IndexStore.js.map +1 -0
- package/dist/npm/index.d.ts +117 -0
- package/dist/npm/index.d.ts.map +1 -0
- package/dist/npm/index.js +371 -0
- package/dist/npm/index.js.map +1 -0
- package/dist/npm/query/Query.d.ts +176 -0
- package/dist/npm/query/Query.d.ts.map +1 -0
- package/dist/npm/query/Query.js +270 -0
- package/dist/npm/query/Query.js.map +1 -0
- package/dist/npm/query/QueryEngine.d.ts +140 -0
- package/dist/npm/query/QueryEngine.d.ts.map +1 -0
- package/dist/npm/query/QueryEngine.js +453 -0
- package/dist/npm/query/QueryEngine.js.map +1 -0
- package/dist/npm/storage/GoogleSheetAdapter.d.ts +119 -0
- package/dist/npm/storage/GoogleSheetAdapter.d.ts.map +1 -0
- package/dist/npm/storage/GoogleSheetAdapter.js +238 -0
- package/dist/npm/storage/GoogleSheetAdapter.js.map +1 -0
- package/dist/npm/storage/GoogleSpreadsheetAdapter.d.ts +71 -0
- package/dist/npm/storage/GoogleSpreadsheetAdapter.d.ts.map +1 -0
- package/dist/npm/storage/GoogleSpreadsheetAdapter.js +131 -0
- package/dist/npm/storage/GoogleSpreadsheetAdapter.js.map +1 -0
- package/dist/npm/testing/ParityCatalog.d.ts +38 -0
- package/dist/npm/testing/ParityCatalog.d.ts.map +1 -0
- package/dist/npm/testing/ParityCatalog.js +407 -0
- package/dist/npm/testing/ParityCatalog.js.map +1 -0
- package/dist/npm/testing/RuntimeBenchmark.d.ts +37 -0
- package/dist/npm/testing/RuntimeBenchmark.d.ts.map +1 -0
- package/dist/npm/testing/RuntimeBenchmark.js +449 -0
- package/dist/npm/testing/RuntimeBenchmark.js.map +1 -0
- package/dist/npm/testing/RuntimeParity.d.ts +66 -0
- package/dist/npm/testing/RuntimeParity.d.ts.map +1 -0
- package/dist/npm/testing/RuntimeParity.js +4193 -0
- package/dist/npm/testing/RuntimeParity.js.map +1 -0
- package/dist/npm/utils/Serialization.d.ts +111 -0
- package/dist/npm/utils/Serialization.d.ts.map +1 -0
- package/dist/npm/utils/Serialization.js +281 -0
- package/dist/npm/utils/Serialization.js.map +1 -0
- package/dist/npm/utils/SheetOrmLogger.d.ts +31 -0
- package/dist/npm/utils/SheetOrmLogger.d.ts.map +1 -0
- package/dist/npm/utils/SheetOrmLogger.js +42 -0
- package/dist/npm/utils/SheetOrmLogger.js.map +1 -0
- package/dist/npm/utils/Uuid.d.ts +29 -0
- package/dist/npm/utils/Uuid.d.ts.map +1 -0
- package/dist/npm/utils/Uuid.js +86 -0
- package/dist/npm/utils/Uuid.js.map +1 -0
- package/package.json +3 -2
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ActiveRecord base class for ORM-managed models.
|
|
3
|
+
*
|
|
4
|
+
* Subclass `Record` to define entities stored in Google Sheets. Fields
|
|
5
|
+
* are auto-discovered from ESNext class field declarations at registration
|
|
6
|
+
* time via the decorator metadata system ({@link Decorators}).
|
|
7
|
+
*
|
|
8
|
+
* Follows the **ActiveRecord** pattern — each instance knows how to
|
|
9
|
+
* `save()` and `delete()` itself, while static methods like `find()`,
|
|
10
|
+
* `where()`, and `query()` provide collection-level operations.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* class Car extends Record {
|
|
15
|
+
* brand = "";
|
|
16
|
+
* year = 0;
|
|
17
|
+
* }
|
|
18
|
+
* const car = Car.create({ brand: "Toyota", year: 2024 }).save();
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @module Record
|
|
22
|
+
*/
|
|
23
|
+
import { Registry } from "./Registry.js";
|
|
24
|
+
import { Query } from "../query/Query.js";
|
|
25
|
+
import { Decorators } from "./Decorators.js";
|
|
26
|
+
/**
|
|
27
|
+
* Cast an unknown class reference to the internal {@link RecordStatic}
|
|
28
|
+
* shape so that `tableName`, `indexTableName`, etc. are available.
|
|
29
|
+
*/
|
|
30
|
+
function asCtor(cls) {
|
|
31
|
+
return cls;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Hydrate raw Entity objects into fully-typed Record instances.
|
|
35
|
+
*
|
|
36
|
+
* Allocates the result array up-front and uses `Object.assign` to copy
|
|
37
|
+
* entity properties onto each freshly-constructed instance.
|
|
38
|
+
*
|
|
39
|
+
* @param ctor - The concrete Record subclass constructor.
|
|
40
|
+
* @param entities - Raw entity rows returned by SheetRepository.
|
|
41
|
+
* @returns An array of hydrated Record subclass instances.
|
|
42
|
+
*/
|
|
43
|
+
function toInstances(ctor, entities) {
|
|
44
|
+
const len = entities.length;
|
|
45
|
+
const result = new Array(len);
|
|
46
|
+
for (let i = 0; i < len; i++) {
|
|
47
|
+
const instance = new ctor();
|
|
48
|
+
Object.assign(instance, entities[i]);
|
|
49
|
+
result[i] = instance;
|
|
50
|
+
}
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Base class for all SheetORM models.
|
|
55
|
+
*
|
|
56
|
+
* Provides both instance-level persistence (`save`, `delete`) and
|
|
57
|
+
* static query helpers (`find`, `where`, `query`, `select`, `groupBy`,
|
|
58
|
+
* `saveAll`). System columns (`__id`, `__createdAt`, `__updatedAt`)
|
|
59
|
+
* are declared here so every subclass inherits them.
|
|
60
|
+
*/
|
|
61
|
+
export class Record {
|
|
62
|
+
/**
|
|
63
|
+
* Convention-based table name derived from the class name.
|
|
64
|
+
* e.g. class `Car` → `"tbl_Cars"`.
|
|
65
|
+
*/
|
|
66
|
+
static get tableName() {
|
|
67
|
+
return "tbl_" + this.name + "s";
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Convention-based combined index table name.
|
|
71
|
+
* e.g. class `Car` → `"idx_Cars"`.
|
|
72
|
+
*/
|
|
73
|
+
static get indexTableName() {
|
|
74
|
+
return "idx_" + this.name + "s";
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Whether the auto-created sheet should be protected.
|
|
78
|
+
* Override in a subclass to return `true` and enable sheet protection.
|
|
79
|
+
*/
|
|
80
|
+
static isProtected() {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Email addresses of editors allowed to edit the protected sheet.
|
|
85
|
+
* Only used when `isProtected()` returns `true`.
|
|
86
|
+
* Override in a subclass to specify allowed editors.
|
|
87
|
+
*/
|
|
88
|
+
static protectedFor() {
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Whether the auto-created sheet should be hidden from the tab bar.
|
|
93
|
+
* Override in a subclass to return `true` and hide the sheet.
|
|
94
|
+
* Hidden sheets are still accessible from the "All sheets" menu.
|
|
95
|
+
*/
|
|
96
|
+
static isHidden() {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
// ─── Static Factory ──────────────────────────────
|
|
100
|
+
/**
|
|
101
|
+
* Create an in-memory instance pre-populated with the given data.
|
|
102
|
+
* The instance is **not** persisted until `save()` is called.
|
|
103
|
+
*
|
|
104
|
+
* @param data - Plain object whose keys map to field names.
|
|
105
|
+
* @returns A new, unsaved Record subclass instance.
|
|
106
|
+
*/
|
|
107
|
+
static create(data) {
|
|
108
|
+
const instance = new this();
|
|
109
|
+
return Object.assign(instance, data);
|
|
110
|
+
}
|
|
111
|
+
// ─── Instance Methods ────────────────────────────
|
|
112
|
+
/**
|
|
113
|
+
* Persist this instance to the underlying Google Sheet.
|
|
114
|
+
*
|
|
115
|
+
* On first save (no `__id`) a new row is inserted; on subsequent
|
|
116
|
+
* saves the existing row is updated in-place. Only fields declared
|
|
117
|
+
* via decorators (or auto-discovered) are written; dynamic index-
|
|
118
|
+
* signature properties are ignored.
|
|
119
|
+
*
|
|
120
|
+
* @returns `this` for fluent chaining.
|
|
121
|
+
*/
|
|
122
|
+
save() {
|
|
123
|
+
const Ctor = this.constructor;
|
|
124
|
+
const fields = Decorators.getFields(Ctor);
|
|
125
|
+
const repo = Registry.getInstance().ensureRepository(Ctor);
|
|
126
|
+
// Build a partial entity containing only declared fields with defined values
|
|
127
|
+
const partial = {};
|
|
128
|
+
for (let i = 0; i < fields.length; i++) {
|
|
129
|
+
const name = fields[i].name;
|
|
130
|
+
const val = this[name];
|
|
131
|
+
if (val !== undefined) {
|
|
132
|
+
partial[name] = val;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
if (this.__id)
|
|
136
|
+
partial.__id = this.__id;
|
|
137
|
+
// Delegate to the repository and hydrate the returned entity (with system columns)
|
|
138
|
+
const saved = repo.save(partial);
|
|
139
|
+
Object.assign(this, saved);
|
|
140
|
+
return this;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Delete this instance's row from the sheet.
|
|
144
|
+
* @returns `true` if the row was found and deleted, `false` if `__id` is missing.
|
|
145
|
+
*/
|
|
146
|
+
delete() {
|
|
147
|
+
if (!this.__id)
|
|
148
|
+
return false;
|
|
149
|
+
const Ctor = this.constructor;
|
|
150
|
+
const repo = Registry.getInstance().ensureRepository(Ctor);
|
|
151
|
+
return repo.delete(this.__id);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Fluent setter — updates a single field and returns `this`.
|
|
155
|
+
* @param field - The field name to set.
|
|
156
|
+
* @param value - The new value.
|
|
157
|
+
*/
|
|
158
|
+
set(field, value) {
|
|
159
|
+
this[field] = value;
|
|
160
|
+
return this;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Read a single field value by name.
|
|
164
|
+
* @param field - The field name to read.
|
|
165
|
+
*/
|
|
166
|
+
get(field) {
|
|
167
|
+
return this[field];
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Serialise this Record to a plain object.
|
|
171
|
+
*
|
|
172
|
+
* Only includes declared class fields (from decorator metadata) plus
|
|
173
|
+
* system columns. Dynamic properties set via the index signature are
|
|
174
|
+
* intentionally excluded to keep JSON output predictable.
|
|
175
|
+
*/
|
|
176
|
+
toJSON() {
|
|
177
|
+
const Ctor = this.constructor;
|
|
178
|
+
const fields = Decorators.getFields(Ctor);
|
|
179
|
+
const result = {
|
|
180
|
+
__id: this.__id,
|
|
181
|
+
__createdAt: this.__createdAt,
|
|
182
|
+
__updatedAt: this.__updatedAt,
|
|
183
|
+
};
|
|
184
|
+
for (let i = 0; i < fields.length; i++) {
|
|
185
|
+
const name = fields[i].name;
|
|
186
|
+
result[name] = this[name];
|
|
187
|
+
}
|
|
188
|
+
return result;
|
|
189
|
+
}
|
|
190
|
+
// ─── Static Query Methods ────────────────────────
|
|
191
|
+
/**
|
|
192
|
+
* Start a fluent query chain with an initial filter.
|
|
193
|
+
* Equivalent to `Record.query().where(field, operator, value)`.
|
|
194
|
+
*/
|
|
195
|
+
static where(field, operator, value) {
|
|
196
|
+
const repo = Registry.getInstance().ensureRepository(asCtor(this));
|
|
197
|
+
return new Query(() => toInstances(this, repo.find())).where(field, operator, value);
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Look up a single record by its UUID primary key.
|
|
201
|
+
* Uses the repository's fast-path cache when available.
|
|
202
|
+
*
|
|
203
|
+
* @returns The hydrated instance, or `null` if not found.
|
|
204
|
+
*/
|
|
205
|
+
static findById(id) {
|
|
206
|
+
const repo = Registry.getInstance().ensureRepository(asCtor(this));
|
|
207
|
+
const entity = repo.findById(id);
|
|
208
|
+
if (!entity)
|
|
209
|
+
return null;
|
|
210
|
+
return Object.assign(new this(), entity);
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Return all records matching the optional query options.
|
|
214
|
+
* Without options, returns every record in the table.
|
|
215
|
+
*/
|
|
216
|
+
static find(options) {
|
|
217
|
+
const repo = Registry.getInstance().ensureRepository(asCtor(this));
|
|
218
|
+
return toInstances(this, repo.find(options));
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Return the first record matching the query options, or `null`.
|
|
222
|
+
*/
|
|
223
|
+
static findOne(options) {
|
|
224
|
+
const repo = Registry.getInstance().ensureRepository(asCtor(this));
|
|
225
|
+
const entity = repo.findOne(options);
|
|
226
|
+
if (!entity)
|
|
227
|
+
return null;
|
|
228
|
+
return Object.assign(new this(), entity);
|
|
229
|
+
}
|
|
230
|
+
/** Count records matching the optional query options. */
|
|
231
|
+
static count(options) {
|
|
232
|
+
const repo = Registry.getInstance().ensureRepository(asCtor(this));
|
|
233
|
+
return repo.count(options);
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Delete all records matching the query options.
|
|
237
|
+
* @returns The number of records deleted.
|
|
238
|
+
*/
|
|
239
|
+
static deleteAll(options) {
|
|
240
|
+
const repo = Registry.getInstance().ensureRepository(asCtor(this));
|
|
241
|
+
return repo.deleteAll(options);
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Start an empty fluent query chain.
|
|
245
|
+
* Call `.where()`, `.orderBy()`, `.limit()`, etc. to build the query.
|
|
246
|
+
*/
|
|
247
|
+
static query() {
|
|
248
|
+
const repo = Registry.getInstance().ensureRepository(asCtor(this));
|
|
249
|
+
return new Query(() => toInstances(this, repo.find()));
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Return a paginated subset of records.
|
|
253
|
+
*
|
|
254
|
+
* @param offset - Number of records to skip (0-based).
|
|
255
|
+
* @param limit - Maximum number of records to return.
|
|
256
|
+
* @param options - Optional filters/sorting.
|
|
257
|
+
* @returns A {@link PaginatedResult} with `items`, `total`, `offset`, `limit`.
|
|
258
|
+
*/
|
|
259
|
+
static select(offset, limit, options) {
|
|
260
|
+
const repo = Registry.getInstance().ensureRepository(asCtor(this));
|
|
261
|
+
const result = repo.select(offset, limit, options);
|
|
262
|
+
return {
|
|
263
|
+
...result,
|
|
264
|
+
items: toInstances(this, result.items),
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Group records by a field value.
|
|
269
|
+
*
|
|
270
|
+
* @param field - The field to group by.
|
|
271
|
+
* @param options - Optional pre-grouping filters.
|
|
272
|
+
* @returns An array of {@link GroupResult}, each with `key` and `items`.
|
|
273
|
+
*/
|
|
274
|
+
static groupBy(field, options) {
|
|
275
|
+
const repo = Registry.getInstance().ensureRepository(asCtor(this));
|
|
276
|
+
const groups = repo.groupBy(field, options);
|
|
277
|
+
return groups.map((g) => ({
|
|
278
|
+
...g,
|
|
279
|
+
items: toInstances(this, g.items),
|
|
280
|
+
}));
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Batch-save multiple records in a single operation.
|
|
284
|
+
*
|
|
285
|
+
* Delegates to `SheetRepository.saveAll()` which uses entity-batch and
|
|
286
|
+
* index-batch optimisations to minimise GAS API calls.
|
|
287
|
+
*
|
|
288
|
+
* @param items - Array of plain data objects.
|
|
289
|
+
* @returns Array of hydrated, persisted Record instances.
|
|
290
|
+
*/
|
|
291
|
+
static saveAll(items) {
|
|
292
|
+
const repo = Registry.getInstance().ensureRepository(asCtor(this));
|
|
293
|
+
const entities = repo.saveAll(items);
|
|
294
|
+
return toInstances(this, entities);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
// ─── Wire up Query.from() resolver ──────────
|
|
298
|
+
// This glue code teaches Query.from(ClassName) how to locate the correct
|
|
299
|
+
// Registry entry and build a data-loader function without creating a
|
|
300
|
+
// circular dependency between Query and Record at import time.
|
|
301
|
+
Query._setFromResolver((classOrName) => {
|
|
302
|
+
const registry = Registry.getInstance();
|
|
303
|
+
let ctor;
|
|
304
|
+
if (typeof classOrName === "string") {
|
|
305
|
+
// Look up by class name — the class must have been imported/registered first
|
|
306
|
+
const found = registry.getClassByName(classOrName);
|
|
307
|
+
if (!found) {
|
|
308
|
+
throw new Error(`Record class "${classOrName}" not found. Ensure the class has been imported.`);
|
|
309
|
+
}
|
|
310
|
+
ctor = found;
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
// Class reference passed directly — ensure it's registered in the Registry
|
|
314
|
+
ctor = classOrName;
|
|
315
|
+
registry.registerClass(ctor);
|
|
316
|
+
}
|
|
317
|
+
// Return a factory function that loads all entities and hydrates them
|
|
318
|
+
const repo = registry.ensureRepository(ctor);
|
|
319
|
+
return () => repo.find().map((e) => Object.assign(new ctor(), e));
|
|
320
|
+
});
|
|
321
|
+
//# sourceMappingURL=Record.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Record.js","sourceRoot":"","sources":["../../../src/core/Record.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Record } from "./Record.js";
|
|
2
|
+
/**
|
|
3
|
+
* Constructor signature for Record subclasses.
|
|
4
|
+
*
|
|
5
|
+
* Used as a generic constraint whenever SheetORM needs to refer to a
|
|
6
|
+
* class that can be `new`-ed and that carries the static `tableName`
|
|
7
|
+
* and `indexTableName` properties (e.g. in SheetRepository's generic
|
|
8
|
+
* parameter).
|
|
9
|
+
*
|
|
10
|
+
* @typeParam T - Concrete Record subclass type.
|
|
11
|
+
*/
|
|
12
|
+
export interface RecordConstructor<T extends Record = Record> {
|
|
13
|
+
/** Parameterless constructor — the ORM instantiates records via `new Ctor()`. */
|
|
14
|
+
new (): T;
|
|
15
|
+
/** Sheet tab name where the entity data is stored (e.g. "tbl_Cars"). */
|
|
16
|
+
tableName: string;
|
|
17
|
+
/** Sheet tab name for the combined secondary index (e.g. "idx_Cars"). */
|
|
18
|
+
indexTableName: string;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=RecordConstructor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RecordConstructor.d.ts","sourceRoot":"","sources":["../../../src/core/RecordConstructor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C;;;;;;;;;GASG;AACH,MAAM,WAAW,iBAAiB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IAC1D,iFAAiF;IACjF,QAAQ,CAAC,CAAC;IAEV,wEAAwE;IACxE,SAAS,EAAE,MAAM,CAAC;IAElB,yEAAyE;IACzE,cAAc,EAAE,MAAM,CAAC;CACxB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RecordConstructor.js","sourceRoot":"","sources":["../../../src/core/RecordConstructor.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Entity } from "./types/Entity.js";
|
|
2
|
+
/**
|
|
3
|
+
* Type-erased static interface for Record classes.
|
|
4
|
+
*
|
|
5
|
+
* Similar to RecordConstructor but produces a generic Entity
|
|
6
|
+
* instead of a specific Record subclass. Used internally by
|
|
7
|
+
* Registry where the concrete type parameter is unknown.
|
|
8
|
+
*/
|
|
9
|
+
export interface RecordStatic {
|
|
10
|
+
/** Parameterless constructor producing an Entity instance. */
|
|
11
|
+
new (): Entity;
|
|
12
|
+
/** Sheet tab name for entity data (e.g. "tbl_Cars"). */
|
|
13
|
+
tableName: string;
|
|
14
|
+
/** Sheet tab name for the combined secondary index (e.g. "idx_Cars"). */
|
|
15
|
+
indexTableName: string;
|
|
16
|
+
/** JavaScript class name (used for Registry class-name lookup). */
|
|
17
|
+
name: string;
|
|
18
|
+
/** Whether the auto-created sheet should be protected. */
|
|
19
|
+
isProtected(): boolean;
|
|
20
|
+
/** Email addresses of editors allowed to edit the protected sheet. */
|
|
21
|
+
protectedFor(): string[];
|
|
22
|
+
/** Whether the auto-created sheet should be hidden from the tab bar. */
|
|
23
|
+
isHidden(): boolean;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=RecordStatic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RecordStatic.d.ts","sourceRoot":"","sources":["../../../src/core/RecordStatic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEhD;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,8DAA8D;IAC9D,QAAQ,MAAM,CAAC;IAEf,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC;IAElB,yEAAyE;IACzE,cAAc,EAAE,MAAM,CAAC;IAEvB,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;IAEb,0DAA0D;IAC1D,WAAW,IAAI,OAAO,CAAC;IAEvB,sEAAsE;IACtE,YAAY,IAAI,MAAM,EAAE,CAAC;IAEzB,wEAAwE;IACxE,QAAQ,IAAI,OAAO,CAAC;CACrB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RecordStatic.js","sourceRoot":"","sources":["../../../src/core/RecordStatic.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global singleton registry that manages the ORM runtime state.
|
|
3
|
+
*
|
|
4
|
+
* Responsibilities:
|
|
5
|
+
* - Holds the single {@link ISpreadsheetAdapter} (defaults to GAS active spreadsheet).
|
|
6
|
+
* - Maintains a per-table {@link SheetRepository} cache so the same repo
|
|
7
|
+
* is reused for the lifetime of the script execution.
|
|
8
|
+
* - Creates and wires up the shared {@link IndexStore} used by all repos.
|
|
9
|
+
* - Keeps a class map so `Query.from("ClassName")` can resolve by name.
|
|
10
|
+
*
|
|
11
|
+
* @module Registry
|
|
12
|
+
*/
|
|
13
|
+
import type { Entity } from "./types/Entity.js";
|
|
14
|
+
import type { ICacheProvider } from "./types/ICacheProvider.js";
|
|
15
|
+
import type { ISpreadsheetAdapter } from "./types/ISpreadsheetAdapter.js";
|
|
16
|
+
import { SheetRepository } from "./SheetRepository.js";
|
|
17
|
+
import { IndexStore } from "../index/IndexStore.js";
|
|
18
|
+
import type { RecordStatic } from "./RecordStatic.js";
|
|
19
|
+
/**
|
|
20
|
+
* Central registry for SheetORM.
|
|
21
|
+
*
|
|
22
|
+
* Accessed via `Registry.getInstance()`. Call `Registry.reset()` in
|
|
23
|
+
* tests to start with a clean slate.
|
|
24
|
+
*/
|
|
25
|
+
export declare class Registry {
|
|
26
|
+
/** Singleton instance (lazy-initialised). */
|
|
27
|
+
private static instance;
|
|
28
|
+
/** The spreadsheet-level adapter (wraps GAS Spreadsheet or mock). */
|
|
29
|
+
private adapter;
|
|
30
|
+
/** Optional entity data cache (defaults to MemoryCache). */
|
|
31
|
+
private cache;
|
|
32
|
+
/** Shared secondary-index manager. */
|
|
33
|
+
private indexStore;
|
|
34
|
+
/** tableName → SheetRepository cache. */
|
|
35
|
+
private repos;
|
|
36
|
+
/** tableName → RecordStatic class map for lookup by table name. */
|
|
37
|
+
private classesByTable;
|
|
38
|
+
/** className → RecordStatic class map for lookup by constructor name. */
|
|
39
|
+
private classesByName;
|
|
40
|
+
/** Return (or create) the singleton Registry instance. */
|
|
41
|
+
static getInstance(): Registry;
|
|
42
|
+
/** Destroy the singleton — used by test suites to reset state between runs. */
|
|
43
|
+
static reset(): void;
|
|
44
|
+
/**
|
|
45
|
+
* Configure the registry with a custom adapter and/or cache.
|
|
46
|
+
* Clears all previously created repos, class maps, and the index store.
|
|
47
|
+
*/
|
|
48
|
+
configure(options: {
|
|
49
|
+
adapter?: ISpreadsheetAdapter;
|
|
50
|
+
cache?: ICacheProvider;
|
|
51
|
+
}): void;
|
|
52
|
+
/**
|
|
53
|
+
* Return the current adapter, falling back to a default
|
|
54
|
+
* GoogleSpreadsheetAdapter (active spreadsheet) if none was configured.
|
|
55
|
+
*/
|
|
56
|
+
private getAdapter;
|
|
57
|
+
/**
|
|
58
|
+
* Lazily create the shared IndexStore.
|
|
59
|
+
* The IndexStore receives its **own** MemoryCache instance so that
|
|
60
|
+
* `cache.clear()` inside it does not wipe the entity data cache.
|
|
61
|
+
*/
|
|
62
|
+
private ensureIndexStore;
|
|
63
|
+
/**
|
|
64
|
+
* Ensure the sheet tab for a given schema exists, and register
|
|
65
|
+
* any declared secondary indexes with the IndexStore.
|
|
66
|
+
*
|
|
67
|
+
* @param schema - The table schema (name, fields, indexes).
|
|
68
|
+
* @param indexStore - The shared IndexStore.
|
|
69
|
+
* @param ctor - The Record subclass constructor (for protection config).
|
|
70
|
+
* @returns The sheet adapter and whether it was freshly created.
|
|
71
|
+
*/
|
|
72
|
+
private ensureTable;
|
|
73
|
+
/**
|
|
74
|
+
* Register a Record subclass so it can be looked up by table name or
|
|
75
|
+
* class name via `getClassByName()`.
|
|
76
|
+
*/
|
|
77
|
+
registerClass(ctor: RecordStatic): void;
|
|
78
|
+
/**
|
|
79
|
+
* Return (or create) the SheetRepository for a given Record subclass.
|
|
80
|
+
*
|
|
81
|
+
* On first call for a table name the method:
|
|
82
|
+
* 1. Registers the class in the class map.
|
|
83
|
+
* 2. Builds a {@link TableSchema} from decorator metadata.
|
|
84
|
+
* 3. Ensures the sheet tab exists (createSheet / insertSheet).
|
|
85
|
+
* 4. Creates a new SheetRepository with all optimisation flags
|
|
86
|
+
* (L1 deferred headers, K2 index skipping, B5 known row count).
|
|
87
|
+
*
|
|
88
|
+
* Subsequent calls return the cached repository instance.
|
|
89
|
+
*/
|
|
90
|
+
ensureRepository<T extends Entity>(ctor: RecordStatic): SheetRepository<T>;
|
|
91
|
+
/**
|
|
92
|
+
* Look up a previously registered Record subclass by constructor name
|
|
93
|
+
* or table name.
|
|
94
|
+
*/
|
|
95
|
+
getClassByName(name: string): RecordStatic | undefined;
|
|
96
|
+
/** Return the shared IndexStore (creates it if needed). */
|
|
97
|
+
getIndexStore(): IndexStore;
|
|
98
|
+
/** Flush both the entity data cache and the index store caches. */
|
|
99
|
+
clearCache(): void;
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=Registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Registry.d.ts","sourceRoot":"","sources":["../../../src/core/Registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAEhE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAE1E,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAIpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAItD;;;;;GAKG;AACH,qBAAa,QAAQ;IACnB,6CAA6C;IAC7C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAyB;IAEhD,qEAAqE;IACrE,OAAO,CAAC,OAAO,CAAoC;IACnD,4DAA4D;IAC5D,OAAO,CAAC,KAAK,CAA+B;IAC5C,sCAAsC;IACtC,OAAO,CAAC,UAAU,CAA2B;IAC7C,yCAAyC;IACzC,OAAO,CAAC,KAAK,CAA8C;IAC3D,mEAAmE;IACnE,OAAO,CAAC,cAAc,CAAmC;IACzD,yEAAyE;IACzE,OAAO,CAAC,aAAa,CAAmC;IAExD,0DAA0D;IAC1D,MAAM,CAAC,WAAW,IAAI,QAAQ;IAO9B,+EAA+E;IAC/E,MAAM,CAAC,KAAK,IAAI,IAAI;IAIpB;;;OAGG;IACH,SAAS,CAAC,OAAO,EAAE;QAAE,OAAO,CAAC,EAAE,mBAAmB,CAAC;QAAC,KAAK,CAAC,EAAE,cAAc,CAAA;KAAE,GAAG,IAAI;IAUnF;;;OAGG;IACH,OAAO,CAAC,UAAU;IAOlB;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAWxB;;;;;;;;OAQG;IACH,OAAO,CAAC,WAAW;IAyEnB;;;OAGG;IACH,aAAa,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IASvC;;;;;;;;;;;OAWG;IACH,gBAAgB,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,eAAe,CAAC,CAAC,CAAC;IAkD1E;;;OAGG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAItD,2DAA2D;IAC3D,aAAa,IAAI,UAAU;IAI3B,mEAAmE;IACnE,UAAU,IAAI,IAAI;CAInB"}
|