@b2bc-devkit/sheetorm 1.0.3 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/npm/core/Record.d.ts +17 -0
- package/dist/npm/core/Record.d.ts.map +1 -1
- package/dist/npm/core/Record.js +23 -0
- package/dist/npm/core/Record.js.map +1 -1
- package/dist/npm/core/RecordStatic.d.ts +6 -0
- package/dist/npm/core/RecordStatic.d.ts.map +1 -1
- package/dist/npm/core/Registry.d.ts +1 -0
- package/dist/npm/core/Registry.d.ts.map +1 -1
- package/dist/npm/core/Registry.js +14 -2
- package/dist/npm/core/Registry.js.map +1 -1
- package/dist/npm/core/types/ISpreadsheetAdapter.d.ts +16 -0
- package/dist/npm/core/types/ISpreadsheetAdapter.d.ts.map +1 -1
- package/dist/npm/index.d.ts +5 -3
- package/dist/npm/index.d.ts.map +1 -1
- package/dist/npm/index.js +7 -3
- package/dist/npm/index.js.map +1 -1
- package/dist/npm/storage/GoogleSpreadsheetAdapter.d.ts +16 -0
- package/dist/npm/storage/GoogleSpreadsheetAdapter.d.ts.map +1 -1
- package/dist/npm/storage/GoogleSpreadsheetAdapter.js +32 -0
- package/dist/npm/storage/GoogleSpreadsheetAdapter.js.map +1 -1
- package/dist/npm/testing/ParityCatalog.d.ts.map +1 -1
- package/dist/npm/testing/ParityCatalog.js +7 -0
- package/dist/npm/testing/ParityCatalog.js.map +1 -1
- package/dist/npm/testing/RuntimeParity.d.ts +10 -6
- package/dist/npm/testing/RuntimeParity.d.ts.map +1 -1
- package/dist/npm/testing/RuntimeParity.js +170 -7
- package/dist/npm/testing/RuntimeParity.js.map +1 -1
- package/package.json +4 -4
- package/{README.md → readme.md} +91 -14
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@b2bc-devkit/sheetorm",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "TypeScript ORM for Google Sheets (Google Apps Script runtime)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "GPL-3.0-or-later",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"@babel/plugin-transform-numeric-separator": "^7.28.6",
|
|
69
69
|
"@babel/plugin-transform-optional-chaining": "^7.28.6",
|
|
70
70
|
"@google/clasp": "^3.3.0",
|
|
71
|
-
"@rollup/plugin-babel": "^
|
|
71
|
+
"@rollup/plugin-babel": "^7.0.0",
|
|
72
72
|
"@types/google-apps-script": "^2.0.8",
|
|
73
73
|
"@types/jest": "^30.0.0",
|
|
74
74
|
"@typescript-eslint/eslint-plugin": "^8.57.1",
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
"prettier": "^3.8.1",
|
|
81
81
|
"terser": "^5.44.1",
|
|
82
82
|
"ts-jest": "^29.4.6",
|
|
83
|
-
"typescript": "^
|
|
84
|
-
"vite": "^
|
|
83
|
+
"typescript": "^6.0.2",
|
|
84
|
+
"vite": "^8.0.8"
|
|
85
85
|
}
|
|
86
86
|
}
|
package/{README.md → readme.md}
RENAMED
|
@@ -27,6 +27,9 @@ extend `Record`, and everything just works.
|
|
|
27
27
|
- **Lifecycle hooks** — `beforeSave`, `afterSave`, `beforeDelete`, `afterDelete`
|
|
28
28
|
- **Batch operations** — `beginBatch` / `commitBatch` / `rollbackBatch` for safe bulk writes
|
|
29
29
|
- **Pagination & grouping** — `select()` returns `PaginatedResult<T>`, `groupBy()` returns `GroupResult<T>`
|
|
30
|
+
- **Sheet protection** — Auto-protect sheets on creation via `isProtected()` / `protectedFor()` overrides
|
|
31
|
+
- **Hidden sheets** — Auto-hide sheets on creation via `isHidden()` override; hidden sheets remain accessible
|
|
32
|
+
from the "All sheets" menu
|
|
30
33
|
- **Zero runtime dependencies** — Bundles into a single `Code.js` via Vite
|
|
31
34
|
|
|
32
35
|
## Quick Start
|
|
@@ -93,6 +96,56 @@ class ArchivedCar extends Record {
|
|
|
93
96
|
}
|
|
94
97
|
```
|
|
95
98
|
|
|
99
|
+
### 4. Protect a sheet
|
|
100
|
+
|
|
101
|
+
SheetORM can automatically protect auto-created sheets using the Google Sheets Protection API. Override
|
|
102
|
+
`isProtected()` and `protectedFor()` on your model class:
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
class SecretReport extends Record {
|
|
106
|
+
@Required()
|
|
107
|
+
title: string;
|
|
108
|
+
|
|
109
|
+
body: string;
|
|
110
|
+
|
|
111
|
+
static override isProtected(): boolean {
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
static override protectedFor(): string[] {
|
|
116
|
+
return ["alice@example.com", "bob@example.com"];
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
When `isProtected()` returns `true`, the sheet is protected the first time it is created. The emails returned
|
|
122
|
+
by `protectedFor()` are added as editors — all other users (except the spreadsheet owner) are restricted to
|
|
123
|
+
view-only access. If `protectedFor()` returns an empty array, only the owner can edit.
|
|
124
|
+
|
|
125
|
+
Protection is applied **once** during sheet creation. Existing sheets are never re-protected on subsequent
|
|
126
|
+
saves.
|
|
127
|
+
|
|
128
|
+
### 5. Hide a sheet
|
|
129
|
+
|
|
130
|
+
SheetORM can automatically hide auto-created sheets from the bottom tab bar. Override `isHidden()` on your
|
|
131
|
+
model class:
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
class AuditLog extends Record {
|
|
135
|
+
action: string;
|
|
136
|
+
timestamp: string;
|
|
137
|
+
|
|
138
|
+
static override isHidden(): boolean {
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
When `isHidden()` returns `true`, the sheet is hidden the first time it is created. The sheet tab is removed
|
|
145
|
+
from the bottom tab bar but remains accessible via the "All sheets" menu in Google Sheets.
|
|
146
|
+
|
|
147
|
+
Hiding is applied **once** during sheet creation. Existing sheets are never re-hidden on subsequent saves.
|
|
148
|
+
|
|
96
149
|
### Available decorators
|
|
97
150
|
|
|
98
151
|
SheetORM supports three TypeScript property decorators on `Record` models.
|
|
@@ -172,7 +225,7 @@ class Car extends Record {
|
|
|
172
225
|
|
|
173
226
|
Use decorators only when you need schema metadata or indexing behaviour.
|
|
174
227
|
|
|
175
|
-
###
|
|
228
|
+
### 6. Use it
|
|
176
229
|
|
|
177
230
|
```ts
|
|
178
231
|
// Create — table auto-created on first save
|
|
@@ -266,13 +319,16 @@ examples/
|
|
|
266
319
|
Extend `Record` to define a model. Declare fields as plain class properties — they are auto-discovered. Use
|
|
267
320
|
decorators and an optional static property to customize behavior:
|
|
268
321
|
|
|
269
|
-
| Decorator / property | Description
|
|
270
|
-
| ----------------------------- |
|
|
271
|
-
| `@Required()` | Shorthand for marking a field as required
|
|
272
|
-
| `@Field(options?)` | Explicit field with options (required, type, defaultValue)
|
|
273
|
-
| `@Indexed(options?)` | Secondary index (implies `@Field`); auto-creates `idx_{ClassName}s`
|
|
274
|
-
| `static get tableName()` | Sheet name (defaults to `tbl_{ClassName}s` — e.g. `tbl_Cars` for `Car`)
|
|
275
|
-
| `static get indexTableName()` | Combined index sheet name (defaults to `idx_{ClassName}s` — e.g. `idx_Cars`)
|
|
322
|
+
| Decorator / property | Description |
|
|
323
|
+
| ----------------------------- | ------------------------------------------------------------------------------- |
|
|
324
|
+
| `@Required()` | Shorthand for marking a field as required |
|
|
325
|
+
| `@Field(options?)` | Explicit field with options (required, type, defaultValue) |
|
|
326
|
+
| `@Indexed(options?)` | Secondary index (implies `@Field`); auto-creates `idx_{ClassName}s` |
|
|
327
|
+
| `static get tableName()` | Sheet name (defaults to `tbl_{ClassName}s` — e.g. `tbl_Cars` for `Car`) |
|
|
328
|
+
| `static get indexTableName()` | Combined index sheet name (defaults to `idx_{ClassName}s` — e.g. `idx_Cars`) |
|
|
329
|
+
| `static isProtected()` | Return `true` to protect the sheet on creation (default: `false`) |
|
|
330
|
+
| `static protectedFor()` | Email addresses of allowed editors (default: `[]`) |
|
|
331
|
+
| `static isHidden()` | Return `true` to hide the sheet from the tab bar on creation (default: `false`) |
|
|
276
332
|
|
|
277
333
|
#### `@Required()`
|
|
278
334
|
|
|
@@ -356,6 +412,20 @@ Query.from(Car).where("year", ">=", 2023).execute();
|
|
|
356
412
|
Query.from("Car").where("make", "=", "Toyota").first();
|
|
357
413
|
```
|
|
358
414
|
|
|
415
|
+
#### Query\<T\> methods
|
|
416
|
+
|
|
417
|
+
| Method | Returns | Description |
|
|
418
|
+
| ----------------------- | ------------------ | ------------------------------------- |
|
|
419
|
+
| `and(field, op, value)` | `Query<T>` | Add AND condition |
|
|
420
|
+
| `or(field, op, value)` | `Query<T>` | Add OR condition |
|
|
421
|
+
| `orderBy(field, dir?)` | `Query<T>` | Sort results (`"asc"` \| `"desc"`) |
|
|
422
|
+
| `limit(n)` | `Query<T>` | Maximum number of results |
|
|
423
|
+
| `offset(n)` | `Query<T>` | Skip first n results |
|
|
424
|
+
| `execute()` | `T[]` | Run query and return matching records |
|
|
425
|
+
| `first()` | `T \| null` | Return first matching record |
|
|
426
|
+
| `count()` | `number` | Count matching records |
|
|
427
|
+
| `groupBy(field)` | `GroupResult<T>[]` | Group results by field |
|
|
428
|
+
|
|
359
429
|
### Filter operators
|
|
360
430
|
|
|
361
431
|
`=`, `!=`, `<`, `>`, `<=`, `>=`, `contains`, `startsWith`, `in`, `search`
|
|
@@ -383,11 +453,11 @@ const ids = indexStore.searchCombined("idx_Cars", "model", "320i");
|
|
|
383
453
|
npm test
|
|
384
454
|
```
|
|
385
455
|
|
|
386
|
-
Runs **
|
|
456
|
+
Runs **340 unit and benchmark tests** across 11 test suites using Jest + ts-jest with in-memory mock adapters:
|
|
387
457
|
|
|
388
458
|
| Suite | Tests | Description |
|
|
389
459
|
| -------------------------- | ----- | -------------------------------------------- |
|
|
390
|
-
| `record.test.ts` |
|
|
460
|
+
| `record.test.ts` | 81 | ActiveRecord API (save, find, query, Query) |
|
|
391
461
|
| `query-engine.test.ts` | 60 | Filter, sort, paginate, group |
|
|
392
462
|
| `serialization.test.ts` | 47 | Row ↔ Entity conversion |
|
|
393
463
|
| `index-store.test.ts` | 44 | Secondary index CRUD |
|
|
@@ -448,7 +518,8 @@ npm test
|
|
|
448
518
|
|
|
449
519
|
Run in Google Apps Script (real Sheets API):
|
|
450
520
|
|
|
451
|
-
- `runTestsStageOne()` / `runTestsStageTwo()` / `runTestsStageThree()` — staged
|
|
521
|
+
- `runTestsStageOne()` / `runTestsStageTwo()` / `runTestsStageThree()` / `runTestsStageFour()` — staged
|
|
522
|
+
runtime parity suite
|
|
452
523
|
- `validateTests()` — validates mapping only (fast drift check)
|
|
453
524
|
|
|
454
525
|
### GAS Runtime Benchmark
|
|
@@ -468,9 +539,10 @@ callable as triggers). Everything else is an internal implementation detail bund
|
|
|
468
539
|
|
|
469
540
|
| Function | Purpose |
|
|
470
541
|
| ---------------------- | ------------------------------------------------------------------------------------------------ |
|
|
471
|
-
| `runTestsStageOne()` | Stage-one parity tests
|
|
472
|
-
| `runTestsStageTwo()` | Stage-two parity tests (
|
|
473
|
-
| `runTestsStageThree()` | Stage-three parity tests (
|
|
542
|
+
| `runTestsStageOne()` | Stage-one parity tests: cache, index-store, query, query-engine (~162 tests). |
|
|
543
|
+
| `runTestsStageTwo()` | Stage-two parity tests: serialization, uuid (~52 tests). |
|
|
544
|
+
| `runTestsStageThree()` | Stage-three parity tests: record (~81 tests). |
|
|
545
|
+
| `runTestsStageFour()` | Stage-four parity tests: sheet-repository (~35 tests). |
|
|
474
546
|
| `validateTests()` | Checks Jest ↔ GAS handler mapping parity — no Sheets API calls, fails immediately on drift. |
|
|
475
547
|
| `runBenchmark()` | Write/read/query/delete cycle for Cars + Workers (100 records each); logs per-operation timings. |
|
|
476
548
|
| `removeAllSheets()` | Deletes every sheet in the active spreadsheet (destructive — use with caution). |
|
|
@@ -567,6 +639,11 @@ included in this template):
|
|
|
567
639
|
1. Install `madge` globally with `npm i --global madge`.
|
|
568
640
|
2. Check for circular dependencies with `madge src/index.ts --circular`.
|
|
569
641
|
|
|
642
|
+
## Security
|
|
643
|
+
|
|
644
|
+
To report a vulnerability, see [SECURITY.md](SECURITY.md). Do not open a public GitHub issue for security
|
|
645
|
+
issues — use GitHub's private Security Advisories instead.
|
|
646
|
+
|
|
570
647
|
## License
|
|
571
648
|
|
|
572
649
|
GPL-3.0-or-later — see [license.md](license.md).
|