@b2bc-devkit/sheetorm 1.1.0 → 1.2.3

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 (150) hide show
  1. package/package.json +171 -86
  2. package/readme.md +57 -17
  3. package/dist/npm/SheetOrm.d.ts +0 -41
  4. package/dist/npm/SheetOrm.d.ts.map +0 -1
  5. package/dist/npm/SheetOrm.js +0 -41
  6. package/dist/npm/SheetOrm.js.map +0 -1
  7. package/dist/npm/core/Decorators.d.ts +0 -145
  8. package/dist/npm/core/Decorators.d.ts.map +0 -1
  9. package/dist/npm/core/Decorators.js +0 -226
  10. package/dist/npm/core/Decorators.js.map +0 -1
  11. package/dist/npm/core/Record.d.ts +0 -178
  12. package/dist/npm/core/Record.d.ts.map +0 -1
  13. package/dist/npm/core/Record.js +0 -313
  14. package/dist/npm/core/Record.js.map +0 -1
  15. package/dist/npm/core/RecordConstructor.d.ts +0 -20
  16. package/dist/npm/core/RecordConstructor.d.ts.map +0 -1
  17. package/dist/npm/core/RecordConstructor.js +0 -2
  18. package/dist/npm/core/RecordConstructor.js.map +0 -1
  19. package/dist/npm/core/RecordStatic.d.ts +0 -23
  20. package/dist/npm/core/RecordStatic.d.ts.map +0 -1
  21. package/dist/npm/core/RecordStatic.js +0 -2
  22. package/dist/npm/core/RecordStatic.js.map +0 -1
  23. package/dist/npm/core/Registry.d.ts +0 -101
  24. package/dist/npm/core/Registry.d.ts.map +0 -1
  25. package/dist/npm/core/Registry.js +0 -226
  26. package/dist/npm/core/Registry.js.map +0 -1
  27. package/dist/npm/core/SheetRepository.d.ts +0 -331
  28. package/dist/npm/core/SheetRepository.d.ts.map +0 -1
  29. package/dist/npm/core/SheetRepository.js +0 -1041
  30. package/dist/npm/core/SheetRepository.js.map +0 -1
  31. package/dist/npm/core/cache/MemoryCache.d.ts +0 -67
  32. package/dist/npm/core/cache/MemoryCache.d.ts.map +0 -1
  33. package/dist/npm/core/cache/MemoryCache.js +0 -112
  34. package/dist/npm/core/cache/MemoryCache.js.map +0 -1
  35. package/dist/npm/core/types/Entity.d.ts +0 -21
  36. package/dist/npm/core/types/Entity.d.ts.map +0 -1
  37. package/dist/npm/core/types/Entity.js +0 -2
  38. package/dist/npm/core/types/Entity.js.map +0 -1
  39. package/dist/npm/core/types/FieldDefinition.d.ts +0 -21
  40. package/dist/npm/core/types/FieldDefinition.d.ts.map +0 -1
  41. package/dist/npm/core/types/FieldDefinition.js +0 -2
  42. package/dist/npm/core/types/FieldDefinition.js.map +0 -1
  43. package/dist/npm/core/types/FieldType.d.ts +0 -12
  44. package/dist/npm/core/types/FieldType.d.ts.map +0 -1
  45. package/dist/npm/core/types/FieldType.js +0 -2
  46. package/dist/npm/core/types/FieldType.js.map +0 -1
  47. package/dist/npm/core/types/Filter.d.ts +0 -16
  48. package/dist/npm/core/types/Filter.d.ts.map +0 -1
  49. package/dist/npm/core/types/Filter.js +0 -2
  50. package/dist/npm/core/types/Filter.js.map +0 -1
  51. package/dist/npm/core/types/FilterOperator.d.ts +0 -16
  52. package/dist/npm/core/types/FilterOperator.d.ts.map +0 -1
  53. package/dist/npm/core/types/FilterOperator.js +0 -2
  54. package/dist/npm/core/types/FilterOperator.js.map +0 -1
  55. package/dist/npm/core/types/GroupResult.d.ts +0 -14
  56. package/dist/npm/core/types/GroupResult.d.ts.map +0 -1
  57. package/dist/npm/core/types/GroupResult.js +0 -2
  58. package/dist/npm/core/types/GroupResult.js.map +0 -1
  59. package/dist/npm/core/types/ICacheProvider.d.ts +0 -20
  60. package/dist/npm/core/types/ICacheProvider.d.ts.map +0 -1
  61. package/dist/npm/core/types/ICacheProvider.js +0 -2
  62. package/dist/npm/core/types/ICacheProvider.js.map +0 -1
  63. package/dist/npm/core/types/ISheetAdapter.d.ts +0 -53
  64. package/dist/npm/core/types/ISheetAdapter.d.ts.map +0 -1
  65. package/dist/npm/core/types/ISheetAdapter.js +0 -2
  66. package/dist/npm/core/types/ISheetAdapter.js.map +0 -1
  67. package/dist/npm/core/types/ISpreadsheetAdapter.d.ts +0 -41
  68. package/dist/npm/core/types/ISpreadsheetAdapter.d.ts.map +0 -1
  69. package/dist/npm/core/types/ISpreadsheetAdapter.js +0 -2
  70. package/dist/npm/core/types/ISpreadsheetAdapter.js.map +0 -1
  71. package/dist/npm/core/types/IndexDefinition.d.ts +0 -16
  72. package/dist/npm/core/types/IndexDefinition.d.ts.map +0 -1
  73. package/dist/npm/core/types/IndexDefinition.js +0 -2
  74. package/dist/npm/core/types/IndexDefinition.js.map +0 -1
  75. package/dist/npm/core/types/LifecycleHooks.d.ts +0 -32
  76. package/dist/npm/core/types/LifecycleHooks.d.ts.map +0 -1
  77. package/dist/npm/core/types/LifecycleHooks.js +0 -2
  78. package/dist/npm/core/types/LifecycleHooks.js.map +0 -1
  79. package/dist/npm/core/types/PaginatedResult.d.ts +0 -18
  80. package/dist/npm/core/types/PaginatedResult.d.ts.map +0 -1
  81. package/dist/npm/core/types/PaginatedResult.js +0 -2
  82. package/dist/npm/core/types/PaginatedResult.js.map +0 -1
  83. package/dist/npm/core/types/QueryOptions.d.ts +0 -21
  84. package/dist/npm/core/types/QueryOptions.d.ts.map +0 -1
  85. package/dist/npm/core/types/QueryOptions.js +0 -2
  86. package/dist/npm/core/types/QueryOptions.js.map +0 -1
  87. package/dist/npm/core/types/SortClause.d.ts +0 -10
  88. package/dist/npm/core/types/SortClause.d.ts.map +0 -1
  89. package/dist/npm/core/types/SortClause.js +0 -2
  90. package/dist/npm/core/types/SortClause.js.map +0 -1
  91. package/dist/npm/core/types/SystemColumns.d.ts +0 -16
  92. package/dist/npm/core/types/SystemColumns.d.ts.map +0 -1
  93. package/dist/npm/core/types/SystemColumns.js +0 -16
  94. package/dist/npm/core/types/SystemColumns.js.map +0 -1
  95. package/dist/npm/core/types/TableSchema.d.ts +0 -24
  96. package/dist/npm/core/types/TableSchema.d.ts.map +0 -1
  97. package/dist/npm/core/types/TableSchema.js +0 -2
  98. package/dist/npm/core/types/TableSchema.js.map +0 -1
  99. package/dist/npm/index/IndexMeta.d.ts +0 -16
  100. package/dist/npm/index/IndexMeta.d.ts.map +0 -1
  101. package/dist/npm/index/IndexMeta.js +0 -2
  102. package/dist/npm/index/IndexMeta.js.map +0 -1
  103. package/dist/npm/index/IndexStore.d.ts +0 -397
  104. package/dist/npm/index/IndexStore.d.ts.map +0 -1
  105. package/dist/npm/index/IndexStore.js +0 -1102
  106. package/dist/npm/index/IndexStore.js.map +0 -1
  107. package/dist/npm/index.d.ts +0 -115
  108. package/dist/npm/index.d.ts.map +0 -1
  109. package/dist/npm/index.js +0 -367
  110. package/dist/npm/index.js.map +0 -1
  111. package/dist/npm/query/Query.d.ts +0 -176
  112. package/dist/npm/query/Query.d.ts.map +0 -1
  113. package/dist/npm/query/Query.js +0 -270
  114. package/dist/npm/query/Query.js.map +0 -1
  115. package/dist/npm/query/QueryEngine.d.ts +0 -140
  116. package/dist/npm/query/QueryEngine.d.ts.map +0 -1
  117. package/dist/npm/query/QueryEngine.js +0 -453
  118. package/dist/npm/query/QueryEngine.js.map +0 -1
  119. package/dist/npm/storage/GoogleSheetAdapter.d.ts +0 -119
  120. package/dist/npm/storage/GoogleSheetAdapter.d.ts.map +0 -1
  121. package/dist/npm/storage/GoogleSheetAdapter.js +0 -238
  122. package/dist/npm/storage/GoogleSheetAdapter.js.map +0 -1
  123. package/dist/npm/storage/GoogleSpreadsheetAdapter.d.ts +0 -65
  124. package/dist/npm/storage/GoogleSpreadsheetAdapter.d.ts.map +0 -1
  125. package/dist/npm/storage/GoogleSpreadsheetAdapter.js +0 -119
  126. package/dist/npm/storage/GoogleSpreadsheetAdapter.js.map +0 -1
  127. package/dist/npm/testing/ParityCatalog.d.ts +0 -38
  128. package/dist/npm/testing/ParityCatalog.d.ts.map +0 -1
  129. package/dist/npm/testing/ParityCatalog.js +0 -404
  130. package/dist/npm/testing/ParityCatalog.js.map +0 -1
  131. package/dist/npm/testing/RuntimeBenchmark.d.ts +0 -37
  132. package/dist/npm/testing/RuntimeBenchmark.d.ts.map +0 -1
  133. package/dist/npm/testing/RuntimeBenchmark.js +0 -449
  134. package/dist/npm/testing/RuntimeBenchmark.js.map +0 -1
  135. package/dist/npm/testing/RuntimeParity.d.ts +0 -62
  136. package/dist/npm/testing/RuntimeParity.d.ts.map +0 -1
  137. package/dist/npm/testing/RuntimeParity.js +0 -4126
  138. package/dist/npm/testing/RuntimeParity.js.map +0 -1
  139. package/dist/npm/utils/Serialization.d.ts +0 -111
  140. package/dist/npm/utils/Serialization.d.ts.map +0 -1
  141. package/dist/npm/utils/Serialization.js +0 -281
  142. package/dist/npm/utils/Serialization.js.map +0 -1
  143. package/dist/npm/utils/SheetOrmLogger.d.ts +0 -31
  144. package/dist/npm/utils/SheetOrmLogger.d.ts.map +0 -1
  145. package/dist/npm/utils/SheetOrmLogger.js +0 -42
  146. package/dist/npm/utils/SheetOrmLogger.js.map +0 -1
  147. package/dist/npm/utils/Uuid.d.ts +0 -29
  148. package/dist/npm/utils/Uuid.d.ts.map +0 -1
  149. package/dist/npm/utils/Uuid.js +0 -86
  150. package/dist/npm/utils/Uuid.js.map +0 -1
package/package.json CHANGED
@@ -1,86 +1,171 @@
1
- {
2
- "name": "@b2bc-devkit/sheetorm",
3
- "version": "1.1.0",
4
- "description": "TypeScript ORM for Google Sheets (Google Apps Script runtime)",
5
- "type": "module",
6
- "license": "GPL-3.0-or-later",
7
- "scripts": {
8
- "build": "node scripts/build.mjs",
9
- "build:npm": "node scripts/build-npm.mjs",
10
- "lint": "eslint .",
11
- "format": "prettier . --write",
12
- "test": "jest --verbose",
13
- "login": "clasp login"
14
- },
15
- "files": [
16
- "dist/npm/**/*"
17
- ],
18
- "main": "./dist/npm/SheetOrm.js",
19
- "module": "./dist/npm/SheetOrm.js",
20
- "types": "./dist/npm/SheetOrm.d.ts",
21
- "exports": {
22
- ".": {
23
- "import": "./dist/npm/SheetOrm.js",
24
- "types": "./dist/npm/SheetOrm.d.ts"
25
- },
26
- "./SheetOrm": {
27
- "import": "./dist/npm/SheetOrm.js",
28
- "types": "./dist/npm/SheetOrm.d.ts"
29
- },
30
- "./core/Record": {
31
- "import": "./dist/npm/core/Record.js",
32
- "types": "./dist/npm/core/Record.d.ts"
33
- },
34
- "./core/Decorators": {
35
- "import": "./dist/npm/core/Decorators.js",
36
- "types": "./dist/npm/core/Decorators.d.ts"
37
- },
38
- "./query/Query": {
39
- "import": "./dist/npm/query/Query.js",
40
- "types": "./dist/npm/query/Query.d.ts"
41
- },
42
- "./index/IndexStore": {
43
- "import": "./dist/npm/index/IndexStore.js",
44
- "types": "./dist/npm/index/IndexStore.d.ts"
45
- },
46
- "./core/Registry": {
47
- "import": "./dist/npm/core/Registry.js",
48
- "types": "./dist/npm/core/Registry.d.ts"
49
- },
50
- "./package.json": "./package.json"
51
- },
52
- "repository": {
53
- "type": "git",
54
- "url": "https://github.com/b2bc-devkit/SheetORM.git"
55
- },
56
- "homepage": "https://github.com/b2bc-devkit/SheetORM#readme",
57
- "bugs": {
58
- "url": "https://github.com/b2bc-devkit/SheetORM/issues"
59
- },
60
- "publishConfig": {
61
- "access": "public"
62
- },
63
- "devDependencies": {
64
- "@b2bc-devkit/gas-class-entrypoints": "^1.0.0",
65
- "@babel/core": "^7.29.0",
66
- "@babel/plugin-transform-class-properties": "^7.28.6",
67
- "@babel/plugin-transform-nullish-coalescing-operator": "^7.28.6",
68
- "@babel/plugin-transform-numeric-separator": "^7.28.6",
69
- "@babel/plugin-transform-optional-chaining": "^7.28.6",
70
- "@google/clasp": "^3.3.0",
71
- "@rollup/plugin-babel": "^7.0.0",
72
- "@types/google-apps-script": "^2.0.8",
73
- "@types/jest": "^30.0.0",
74
- "@typescript-eslint/eslint-plugin": "^8.57.1",
75
- "@typescript-eslint/parser": "^8.57.1",
76
- "eslint": "^10.0.3",
77
- "eslint-config-prettier": "^10.1.8",
78
- "eslint-plugin-googleappsscript": "^1.0.5",
79
- "jest": "^30.3.0",
80
- "prettier": "^3.8.1",
81
- "terser": "^5.44.1",
82
- "ts-jest": "^29.4.6",
83
- "typescript": "^6.0.2",
84
- "vite": "^8.0.8"
85
- }
86
- }
1
+ {
2
+ "name": "@b2bc-devkit/sheetorm",
3
+ "version": "1.2.3",
4
+ "description": "TypeScript ORM for Google Sheets (Google Apps Script runtime)",
5
+ "type": "module",
6
+ "license": "GPL-3.0-or-later",
7
+ "scripts": {
8
+ "build": "wireit",
9
+ "build:npm": "wireit",
10
+ "lint": "wireit",
11
+ "knip": "wireit",
12
+ "trivy:scan": "wireit",
13
+ "format": "prettier . --write",
14
+ "test": "wireit",
15
+ "login": "clasp login"
16
+ },
17
+ "wireit": {
18
+ "knip": {
19
+ "command": "knip",
20
+ "files": [
21
+ "src/**/*.ts",
22
+ "tests/**/*.ts",
23
+ "examples/**/*.ts",
24
+ "scripts/**/*.mjs",
25
+ "knip.json",
26
+ "package.json",
27
+ "tsconfig.json",
28
+ "tsconfig.gas.json",
29
+ "tsconfig.npm.json",
30
+ "tsconfig.test.json",
31
+ "vite.config.mjs",
32
+ "eslint.config.cjs",
33
+ "jest.config.cjs"
34
+ ],
35
+ "output": []
36
+ },
37
+ "trivy:scan": {
38
+ "command": "npx @b2bc-devkit/trivy-scan fs --config trivy.yaml .",
39
+ "files": [
40
+ "package-lock.json",
41
+ "trivy.yaml"
42
+ ],
43
+ "output": []
44
+ },
45
+ "build": {
46
+ "command": "node scripts/build.mjs",
47
+ "dependencies": [
48
+ "knip",
49
+ "trivy:scan"
50
+ ],
51
+ "files": [
52
+ "src/**/*.ts",
53
+ "scripts/build.mjs",
54
+ "tsconfig.json",
55
+ "tsconfig.gas.json",
56
+ "vite.config.mjs",
57
+ "appsscript.json"
58
+ ],
59
+ "output": [
60
+ "build/**",
61
+ "Code.js"
62
+ ]
63
+ },
64
+ "build:npm": {
65
+ "command": "node scripts/build-npm.mjs",
66
+ "dependencies": [
67
+ "knip",
68
+ "trivy:scan"
69
+ ],
70
+ "files": [
71
+ "src/**/*.ts",
72
+ "scripts/build-npm.mjs",
73
+ "tsconfig.json",
74
+ "tsconfig.npm.json"
75
+ ],
76
+ "output": [
77
+ "dist/npm/**"
78
+ ]
79
+ },
80
+ "lint": {
81
+ "command": "eslint .",
82
+ "files": [
83
+ "src/**/*.ts",
84
+ "tests/**/*.ts",
85
+ "examples/**/*.ts",
86
+ "scripts/**/*.mjs",
87
+ "eslint.config.cjs",
88
+ "package.json"
89
+ ],
90
+ "output": []
91
+ },
92
+ "test": {
93
+ "command": "jest --verbose",
94
+ "files": [
95
+ "src/**/*.ts",
96
+ "tests/**/*.ts",
97
+ "jest.config.cjs",
98
+ "tsconfig.test.json",
99
+ "package.json"
100
+ ],
101
+ "output": []
102
+ }
103
+ },
104
+ "files": [
105
+ "dist/npm/**/*"
106
+ ],
107
+ "main": "./dist/npm/SheetOrm.js",
108
+ "module": "./dist/npm/SheetOrm.js",
109
+ "types": "./dist/npm/SheetOrm.d.ts",
110
+ "exports": {
111
+ ".": {
112
+ "import": "./dist/npm/SheetOrm.js",
113
+ "types": "./dist/npm/SheetOrm.d.ts"
114
+ },
115
+ "./SheetOrm": {
116
+ "import": "./dist/npm/SheetOrm.js",
117
+ "types": "./dist/npm/SheetOrm.d.ts"
118
+ },
119
+ "./core/Record": {
120
+ "import": "./dist/npm/core/Record.js",
121
+ "types": "./dist/npm/core/Record.d.ts"
122
+ },
123
+ "./core/Decorators": {
124
+ "import": "./dist/npm/core/Decorators.js",
125
+ "types": "./dist/npm/core/Decorators.d.ts"
126
+ },
127
+ "./query/Query": {
128
+ "import": "./dist/npm/query/Query.js",
129
+ "types": "./dist/npm/query/Query.d.ts"
130
+ },
131
+ "./index/IndexStore": {
132
+ "import": "./dist/npm/index/IndexStore.js",
133
+ "types": "./dist/npm/index/IndexStore.d.ts"
134
+ },
135
+ "./core/Registry": {
136
+ "import": "./dist/npm/core/Registry.js",
137
+ "types": "./dist/npm/core/Registry.d.ts"
138
+ },
139
+ "./package.json": "./package.json"
140
+ },
141
+ "repository": {
142
+ "type": "git",
143
+ "url": "git+https://github.com/b2bc-devkit/SheetORM.git"
144
+ },
145
+ "homepage": "https://github.com/b2bc-devkit/SheetORM#readme",
146
+ "bugs": {
147
+ "url": "https://github.com/b2bc-devkit/SheetORM/issues"
148
+ },
149
+ "publishConfig": {
150
+ "access": "public"
151
+ },
152
+ "devDependencies": {
153
+ "@b2bc-devkit/gas-class-entrypoints": "^1.0.0",
154
+ "@google/clasp": "^3.3.0",
155
+ "@types/google-apps-script": "^2.0.8",
156
+ "@types/jest": "^30.0.0",
157
+ "@typescript-eslint/eslint-plugin": "^8.57.1",
158
+ "@typescript-eslint/parser": "^8.57.1",
159
+ "eslint": "^10.0.3",
160
+ "eslint-config-prettier": "^10.1.8",
161
+ "eslint-plugin-googleappsscript": "^1.0.5",
162
+ "jest": "^30.3.0",
163
+ "knip": "^6.25.0",
164
+ "prettier": "^3.8.1",
165
+ "terser": "^5.44.1",
166
+ "ts-jest": "^29.4.6",
167
+ "typescript": "^6.0.3",
168
+ "vite": "^8.0.8",
169
+ "wireit": "^0.14.13"
170
+ }
171
+ }
package/readme.md CHANGED
@@ -28,6 +28,8 @@ extend `Record`, and everything just works.
28
28
  - **Batch operations** — `beginBatch` / `commitBatch` / `rollbackBatch` for safe bulk writes
29
29
  - **Pagination & grouping** — `select()` returns `PaginatedResult<T>`, `groupBy()` returns `GroupResult<T>`
30
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
31
33
  - **Zero runtime dependencies** — Bundles into a single `Code.js` via Vite
32
34
 
33
35
  ## Quick Start
@@ -94,7 +96,7 @@ class ArchivedCar extends Record {
94
96
  }
95
97
  ```
96
98
 
97
- ### 5. Protect a sheet
99
+ ### 4. Protect a sheet
98
100
 
99
101
  SheetORM can automatically protect auto-created sheets using the Google Sheets Protection API. Override
100
102
  `isProtected()` and `protectedFor()` on your model class:
@@ -123,6 +125,27 @@ view-only access. If `protectedFor()` returns an empty array, only the owner can
123
125
  Protection is applied **once** during sheet creation. Existing sheets are never re-protected on subsequent
124
126
  saves.
125
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
+
126
149
  ### Available decorators
127
150
 
128
151
  SheetORM supports three TypeScript property decorators on `Record` models.
@@ -202,7 +225,7 @@ class Car extends Record {
202
225
 
203
226
  Use decorators only when you need schema metadata or indexing behaviour.
204
227
 
205
- ### 4. Use it
228
+ ### 6. Use it
206
229
 
207
230
  ```ts
208
231
  // Create — table auto-created on first save
@@ -296,15 +319,16 @@ examples/
296
319
  Extend `Record` to define a model. Declare fields as plain class properties — they are auto-discovered. Use
297
320
  decorators and an optional static property to customize behavior:
298
321
 
299
- | Decorator / property | Description |
300
- | ----------------------------- | ---------------------------------------------------------------------------- |
301
- | `@Required()` | Shorthand for marking a field as required |
302
- | `@Field(options?)` | Explicit field with options (required, type, defaultValue) |
303
- | `@Indexed(options?)` | Secondary index (implies `@Field`); auto-creates `idx_{ClassName}s` |
304
- | `static get tableName()` | Sheet name (defaults to `tbl_{ClassName}s` — e.g. `tbl_Cars` for `Car`) |
305
- | `static get indexTableName()` | Combined index sheet name (defaults to `idx_{ClassName}s` — e.g. `idx_Cars`) |
306
- | `static isProtected()` | Return `true` to protect the sheet on creation (default: `false`) |
307
- | `static protectedFor()` | Email addresses of allowed editors (default: `[]`) |
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`) |
308
332
 
309
333
  #### `@Required()`
310
334
 
@@ -388,6 +412,20 @@ Query.from(Car).where("year", ">=", 2023).execute();
388
412
  Query.from("Car").where("make", "=", "Toyota").first();
389
413
  ```
390
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
+
391
429
  ### Filter operators
392
430
 
393
431
  `=`, `!=`, `<`, `>`, `<=`, `>=`, `contains`, `startsWith`, `in`, `search`
@@ -415,11 +453,11 @@ const ids = indexStore.searchCombined("idx_Cars", "model", "320i");
415
453
  npm test
416
454
  ```
417
455
 
418
- Runs **337 unit and benchmark tests** across 11 test suites using Jest + ts-jest with in-memory mock adapters:
456
+ Runs **340 unit and benchmark tests** across 11 test suites using Jest + ts-jest with in-memory mock adapters:
419
457
 
420
458
  | Suite | Tests | Description |
421
459
  | -------------------------- | ----- | -------------------------------------------- |
422
- | `record.test.ts` | 78 | ActiveRecord API (save, find, query, Query) |
460
+ | `record.test.ts` | 81 | ActiveRecord API (save, find, query, Query) |
423
461
  | `query-engine.test.ts` | 60 | Filter, sort, paginate, group |
424
462
  | `serialization.test.ts` | 47 | Row ↔ Entity conversion |
425
463
  | `index-store.test.ts` | 44 | Secondary index CRUD |
@@ -480,7 +518,8 @@ npm test
480
518
 
481
519
  Run in Google Apps Script (real Sheets API):
482
520
 
483
- - `runTestsStageOne()` / `runTestsStageTwo()` / `runTestsStageThree()` — staged runtime parity suite
521
+ - `runTestsStageOne()` / `runTestsStageTwo()` / `runTestsStageThree()` / `runTestsStageFour()` — staged
522
+ runtime parity suite
484
523
  - `validateTests()` — validates mapping only (fast drift check)
485
524
 
486
525
  ### GAS Runtime Benchmark
@@ -500,9 +539,10 @@ callable as triggers). Everything else is an internal implementation detail bund
500
539
 
501
540
  | Function | Purpose |
502
541
  | ---------------------- | ------------------------------------------------------------------------------------------------ |
503
- | `runTestsStageOne()` | Stage-one parity tests (basic CRUD + query) against the active spreadsheet. |
504
- | `runTestsStageTwo()` | Stage-two parity tests (indexes + search). |
505
- | `runTestsStageThree()` | Stage-three parity tests (advanced queries + pagination). |
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). |
506
546
  | `validateTests()` | Checks Jest ↔ GAS handler mapping parity — no Sheets API calls, fails immediately on drift. |
507
547
  | `runBenchmark()` | Write/read/query/delete cycle for Cars + Workers (100 records each); logs per-operation timings. |
508
548
  | `removeAllSheets()` | Deletes every sheet in the active spreadsheet (destructive — use with caution). |
@@ -1,41 +0,0 @@
1
- /**
2
- * @module SheetOrm
3
- *
4
- * NPM package entry point for the SheetORM library.
5
- *
6
- * Re-exports the core public API surface as static members of a single
7
- * namespace class. Consumer code imports from this module:
8
- *
9
- * ```ts
10
- * import { SheetOrm } from "sheetorm";
11
- * const { Record, Query, Decorators, IndexStore, Registry } = SheetOrm;
12
- * ```
13
- *
14
- * This file is referenced by `tsconfig.npm.json` and the npm build
15
- * script; it does **not** include GAS-specific helpers (e.g. demos,
16
- * test runners) that live in `index.ts`.
17
- */
18
- import { Decorators } from "./core/Decorators.js";
19
- import { Record } from "./core/Record.js";
20
- import { Registry } from "./core/Registry.js";
21
- import { IndexStore } from "./index/IndexStore.js";
22
- import { Query } from "./query/Query.js";
23
- /**
24
- * Top-level namespace class that bundles every public SheetORM artifact.
25
- *
26
- * Designed as a single default import so consumers can destructure
27
- * only the parts they need without deep import paths.
28
- */
29
- export declare class SheetOrm {
30
- /** ActiveRecord base class — extend this to define entity models. */
31
- static readonly Record: typeof Record;
32
- /** Fluent query builder for filtering, sorting, and paginating records. */
33
- static readonly Query: typeof Query;
34
- /** Property decorators: `@Field`, `@Indexed`, `@Required`. */
35
- static readonly Decorators: typeof Decorators;
36
- /** Secondary-index manager with n-gram text search. */
37
- static readonly IndexStore: typeof IndexStore;
38
- /** Singleton registry that tracks all registered entity classes. */
39
- static readonly Registry: typeof Registry;
40
- }
41
- //# sourceMappingURL=SheetOrm.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SheetOrm.d.ts","sourceRoot":"","sources":["../../src/SheetOrm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEzC;;;;;GAKG;AACH,qBAAa,QAAQ;IACnB,qEAAqE;IACrE,MAAM,CAAC,QAAQ,CAAC,MAAM,gBAAU;IAChC,2EAA2E;IAC3E,MAAM,CAAC,QAAQ,CAAC,KAAK,eAAS;IAC9B,8DAA8D;IAC9D,MAAM,CAAC,QAAQ,CAAC,UAAU,oBAAc;IACxC,uDAAuD;IACvD,MAAM,CAAC,QAAQ,CAAC,UAAU,oBAAc;IACxC,oEAAoE;IACpE,MAAM,CAAC,QAAQ,CAAC,QAAQ,kBAAY;CACrC"}
@@ -1,41 +0,0 @@
1
- /**
2
- * @module SheetOrm
3
- *
4
- * NPM package entry point for the SheetORM library.
5
- *
6
- * Re-exports the core public API surface as static members of a single
7
- * namespace class. Consumer code imports from this module:
8
- *
9
- * ```ts
10
- * import { SheetOrm } from "sheetorm";
11
- * const { Record, Query, Decorators, IndexStore, Registry } = SheetOrm;
12
- * ```
13
- *
14
- * This file is referenced by `tsconfig.npm.json` and the npm build
15
- * script; it does **not** include GAS-specific helpers (e.g. demos,
16
- * test runners) that live in `index.ts`.
17
- */
18
- import { Decorators } from "./core/Decorators.js";
19
- import { Record } from "./core/Record.js";
20
- import { Registry } from "./core/Registry.js";
21
- import { IndexStore } from "./index/IndexStore.js";
22
- import { Query } from "./query/Query.js";
23
- /**
24
- * Top-level namespace class that bundles every public SheetORM artifact.
25
- *
26
- * Designed as a single default import so consumers can destructure
27
- * only the parts they need without deep import paths.
28
- */
29
- export class SheetOrm {
30
- }
31
- /** ActiveRecord base class — extend this to define entity models. */
32
- SheetOrm.Record = Record;
33
- /** Fluent query builder for filtering, sorting, and paginating records. */
34
- SheetOrm.Query = Query;
35
- /** Property decorators: `@Field`, `@Indexed`, `@Required`. */
36
- SheetOrm.Decorators = Decorators;
37
- /** Secondary-index manager with n-gram text search. */
38
- SheetOrm.IndexStore = IndexStore;
39
- /** Singleton registry that tracks all registered entity classes. */
40
- SheetOrm.Registry = Registry;
41
- //# sourceMappingURL=SheetOrm.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SheetOrm.js","sourceRoot":"","sources":["../../src/SheetOrm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEzC;;;;;GAKG;AACH,MAAM,OAAO,QAAQ;;AACnB,qEAAqE;AACrD,eAAM,GAAG,MAAM,CAAC;AAChC,2EAA2E;AAC3D,cAAK,GAAG,KAAK,CAAC;AAC9B,8DAA8D;AAC9C,mBAAU,GAAG,UAAU,CAAC;AACxC,uDAAuD;AACvC,mBAAU,GAAG,UAAU,CAAC;AACxC,oEAAoE;AACpD,iBAAQ,GAAG,QAAQ,CAAC"}
@@ -1,145 +0,0 @@
1
- /**
2
- * Decorator-based metadata system for declaring Record model fields and indexes.
3
- *
4
- * Provides three property decorators:
5
- * - `@Indexed()` — mark a field for secondary indexing (lookups via IndexStore).
6
- * - `@Required()` — shorthand for `@Field({ required: true })`.
7
- * - `@Field()` — override field metadata (type, required, defaultValue, etc.).
8
- *
9
- * And two discovery helpers:
10
- * - `getFields(ctor)` — return all FieldDefinition[] for a class.
11
- * - `getIndexes(ctor)` — return all IndexDefinition[] for a class.
12
- *
13
- * Metadata is stored in module-scoped Maps keyed by constructor:
14
- * - `indexedMeta` — primary @Indexed entries.
15
- * - `fieldMeta` — primary @Field / @Required / @Indexed field patches.
16
- * - `fieldsCache` — derived FieldDefinition[] (invalidated on decoration).
17
- * - `indexesCache` — derived IndexDefinition[] (invalidated on decoration).
18
- *
19
- * @module Decorators
20
- */
21
- import type { FieldDefinition } from "./types/FieldDefinition.js";
22
- import type { FieldType } from "./types/FieldType.js";
23
- import type { IndexDefinition } from "./types/IndexDefinition.js";
24
- /** Constructor shape accepted by the decorators (any class that produces an object). */
25
- interface DecoratedModelCtor {
26
- new (): object;
27
- }
28
- /**
29
- * Mark a field as indexed for faster lookups via IndexStore.
30
- *
31
- * When a Record subclass has fields decorated with `@Indexed()`, SheetORM
32
- * creates a combined index sheet (e.g. `idx_Cars`) and maintains index entries
33
- * during save/delete operations. The `search` filter operator leverages the
34
- * index for n-gram full-text search.
35
- *
36
- * @param options.unique - Enforce unique values across all entities (default: false).
37
- * @param options.type - Storage type hint for the index ("string" | "number" | "date").
38
- * @returns A standard TypeScript property decorator.
39
- *
40
- * @example
41
- * class Car extends Record {
42
- * @Indexed({ unique: true })
43
- * vin!: string;
44
- *
45
- * @Indexed()
46
- * make!: string;
47
- * }
48
- */
49
- declare function Indexed(options?: {
50
- unique?: boolean;
51
- type?: "string" | "number" | "date";
52
- }): PropertyDecorator;
53
- /**
54
- * Mark a field as required — shorthand for `@Field({ required: true })`.
55
- *
56
- * Required fields are validated during save(); an error is thrown if the
57
- * value is null, undefined, or an empty string.
58
- *
59
- * @example
60
- * class User extends Record {
61
- * @Required()
62
- * email!: string;
63
- * }
64
- */
65
- declare function Required(): PropertyDecorator;
66
- /**
67
- * Override field metadata: storage type, required flag, default value, or
68
- * reference table name.
69
- *
70
- * Fields that do not carry any decorator are still auto-discovered from a
71
- * temporary instance's own properties. Use `@Field()` when you need to
72
- * explicitly set the storage type or a default value.
73
- *
74
- * @param options.type - Storage type ("string" | "number" | "boolean" | "date" | "json" | "reference").
75
- * @param options.required - Validate non-empty on save (default: false).
76
- * @param options.defaultValue - Fallback value when the field is undefined.
77
- * @param options.referenceTable - Related table name (for "reference" type fields).
78
- *
79
- * @example
80
- * class Product extends Record {
81
- * @Field({ type: "number", defaultValue: 0 })
82
- * price!: number;
83
- *
84
- * @Field({ type: "json" })
85
- * metadata!: Record<string, unknown>;
86
- * }
87
- */
88
- declare function Field(options?: {
89
- type?: FieldType;
90
- required?: boolean;
91
- defaultValue?: unknown;
92
- referenceTable?: string;
93
- }): PropertyDecorator;
94
- /**
95
- * Discover all user-defined fields for a Record subclass.
96
- *
97
- * Merges two sources:
98
- * 1. **Own properties** from a temporary instance — captures ESNext [[Define]]
99
- * class fields that become own properties without a decorator.
100
- * 2. **Decorator metadata** from `@Indexed` / `@Field` / `@Required` — captures
101
- * fields declared with [[Set]] semantics (TypeScript `useDefineForClassFields: false`).
102
- *
103
- * Results are cached per constructor and invalidated whenever a decorator fires.
104
- *
105
- * @param ctor - Model constructor to inspect.
106
- * @returns Array of FieldDefinition objects (one per user-defined property).
107
- */
108
- declare function getFields(ctor: DecoratedModelCtor): FieldDefinition[];
109
- /**
110
- * Get all index definitions for a Record subclass (from `@Indexed` decorators).
111
- *
112
- * @param ctor - Model constructor to inspect.
113
- * @returns Array of IndexDefinition objects.
114
- */
115
- declare function getIndexes(ctor: DecoratedModelCtor): IndexDefinition[];
116
- /**
117
- * Reset derived decorator caches (fieldsCache and indexesCache).
118
- *
119
- * Called by `Registry.reset()` during testing to ensure a clean state.
120
- * Primary metadata (`fieldMeta` and `indexedMeta`) is set at class-definition
121
- * time by decorators and must NOT be cleared here — only derived caches.
122
- */
123
- declare function resetDecoratorCaches(): void;
124
- /**
125
- * Public decorator utility class.
126
- *
127
- * Wraps the three property decorators and two discovery functions
128
- * as static methods, following the SheetORM one-export-per-file pattern.
129
- */
130
- export declare class Decorators {
131
- /** Property decorator: mark a field for secondary indexing. */
132
- static Indexed: typeof Indexed;
133
- /** Property decorator: mark a field as required (shorthand). */
134
- static Required: typeof Required;
135
- /** Property decorator: set explicit field metadata. */
136
- static Field: typeof Field;
137
- /** Discover all field definitions for a model class. */
138
- static getFields: typeof getFields;
139
- /** Discover all index definitions for a model class. */
140
- static getIndexes: typeof getIndexes;
141
- /** Reset derived caches (for testing). */
142
- static resetDecoratorCaches: typeof resetDecoratorCaches;
143
- }
144
- export {};
145
- //# sourceMappingURL=Decorators.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Decorators.d.ts","sourceRoot":"","sources":["../../../src/core/Decorators.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAElE,wFAAwF;AACxF,UAAU,kBAAkB;IAC1B,QAAQ,MAAM,CAAC;CAChB;AAmDD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,iBAAS,OAAO,CAAC,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAA;CAAE,GAAG,iBAAiB,CAYvG;AAED;;;;;;;;;;;GAWG;AACH,iBAAS,QAAQ,IAAI,iBAAiB,CAKrC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,iBAAS,KAAK,CAAC,OAAO,CAAC,EAAE;IACvB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,GAAG,iBAAiB,CAKpB;AAID;;;;;;;;;;;;;GAaG;AACH,iBAAS,SAAS,CAAC,IAAI,EAAE,kBAAkB,GAAG,eAAe,EAAE,CAgC9D;AAED;;;;;GAKG;AACH,iBAAS,UAAU,CAAC,IAAI,EAAE,kBAAkB,GAAG,eAAe,EAAE,CAK/D;AAED;;;;;;GAMG;AACH,iBAAS,oBAAoB,IAAI,IAAI,CAGpC;AAED;;;;;GAKG;AACH,qBAAa,UAAU;IACrB,+DAA+D;IAC/D,MAAM,CAAC,OAAO,iBAAW;IAEzB,gEAAgE;IAChE,MAAM,CAAC,QAAQ,kBAAY;IAE3B,uDAAuD;IACvD,MAAM,CAAC,KAAK,eAAS;IAErB,wDAAwD;IACxD,MAAM,CAAC,SAAS,mBAAa;IAE7B,wDAAwD;IACxD,MAAM,CAAC,UAAU,oBAAc;IAE/B,0CAA0C;IAC1C,MAAM,CAAC,oBAAoB,8BAAwB;CACpD"}