@karmaniverous/entity-manager 5.0.8 → 5.0.10

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 (140) hide show
  1. package/.github/FUNDING.yml +3 -0
  2. package/README.md +1 -2
  3. package/dist/cjs/BaseEntityClient/BaseEntityClient.js +28 -0
  4. package/dist/cjs/BaseQueryBuilder/BaseQueryBuilder.js +62 -0
  5. package/dist/cjs/EntityManager/EntityManager.js +131 -0
  6. package/dist/cjs/EntityManager/ParsedConfig.js +385 -0
  7. package/dist/cjs/EntityManager/addKeys.js +60 -0
  8. package/dist/cjs/EntityManager/createEntityManager.js +46 -0
  9. package/dist/cjs/EntityManager/decodeElement.js +46 -0
  10. package/dist/cjs/EntityManager/decodeGeneratedProperty.js +53 -0
  11. package/dist/cjs/EntityManager/dehydrateIndexItem.js +68 -0
  12. package/dist/cjs/EntityManager/dehydratePageKeyMap.js +93 -0
  13. package/dist/cjs/EntityManager/encodeElement.js +40 -0
  14. package/dist/cjs/EntityManager/encodeGeneratedProperty.js +55 -0
  15. package/dist/cjs/EntityManager/findIndexToken.js +10 -0
  16. package/dist/cjs/EntityManager/getHashKeySpace.js +89 -0
  17. package/dist/cjs/EntityManager/getIndexComponents.js +23 -0
  18. package/dist/cjs/EntityManager/getPrimaryKey.js +76 -0
  19. package/dist/cjs/EntityManager/getShardBump.js +24 -0
  20. package/dist/cjs/EntityManager/query.js +130 -0
  21. package/dist/cjs/EntityManager/rehydrateIndexItem.js +65 -0
  22. package/dist/cjs/EntityManager/rehydratePageKeyMap.js +103 -0
  23. package/dist/cjs/EntityManager/removeKeys.js +51 -0
  24. package/dist/cjs/EntityManager/unwrapIndex.js +59 -0
  25. package/dist/cjs/EntityManager/updateItemHashKey.js +79 -0
  26. package/dist/cjs/EntityManager/updateItemRangeKey.js +65 -0
  27. package/dist/cjs/EntityManager/validateEntityToken.js +17 -0
  28. package/dist/cjs/EntityManager/validateGeneratedProperty.js +23 -0
  29. package/dist/cjs/EntityManager/validateIndexToken.js +16 -0
  30. package/dist/cjs/EntityManager/validateTranscodedProperty.js +16 -0
  31. package/dist/cjs/index.js +15 -0
  32. package/dist/default/lib/EntityManager/EntityManager.js +46 -69
  33. package/dist/default/lib/EntityManager/PrivateEntityManager.js +44 -51
  34. package/dist/index.d.ts +1163 -0
  35. package/dist/mjs/BaseEntityClient/BaseEntityClient.js +26 -0
  36. package/dist/mjs/BaseQueryBuilder/BaseQueryBuilder.js +60 -0
  37. package/dist/mjs/EntityManager/EntityManager.js +129 -0
  38. package/dist/mjs/EntityManager/ParsedConfig.js +383 -0
  39. package/dist/mjs/EntityManager/addKeys.js +58 -0
  40. package/dist/mjs/EntityManager/createEntityManager.js +44 -0
  41. package/dist/mjs/EntityManager/decodeElement.js +44 -0
  42. package/dist/mjs/EntityManager/decodeGeneratedProperty.js +51 -0
  43. package/dist/mjs/EntityManager/dehydrateIndexItem.js +66 -0
  44. package/dist/mjs/EntityManager/dehydratePageKeyMap.js +91 -0
  45. package/dist/mjs/EntityManager/encodeElement.js +38 -0
  46. package/dist/mjs/EntityManager/encodeGeneratedProperty.js +53 -0
  47. package/dist/mjs/EntityManager/findIndexToken.js +8 -0
  48. package/dist/mjs/EntityManager/getHashKeySpace.js +87 -0
  49. package/dist/mjs/EntityManager/getIndexComponents.js +21 -0
  50. package/dist/mjs/EntityManager/getPrimaryKey.js +74 -0
  51. package/dist/mjs/EntityManager/getShardBump.js +22 -0
  52. package/dist/mjs/EntityManager/query.js +128 -0
  53. package/dist/mjs/EntityManager/rehydrateIndexItem.js +63 -0
  54. package/dist/mjs/EntityManager/rehydratePageKeyMap.js +101 -0
  55. package/dist/mjs/EntityManager/removeKeys.js +49 -0
  56. package/dist/mjs/EntityManager/unwrapIndex.js +57 -0
  57. package/dist/mjs/EntityManager/updateItemHashKey.js +77 -0
  58. package/dist/mjs/EntityManager/updateItemRangeKey.js +63 -0
  59. package/dist/mjs/EntityManager/validateEntityToken.js +15 -0
  60. package/dist/mjs/EntityManager/validateGeneratedProperty.js +21 -0
  61. package/dist/mjs/EntityManager/validateIndexToken.js +14 -0
  62. package/dist/mjs/EntityManager/validateTranscodedProperty.js +14 -0
  63. package/dist/mjs/index.js +5 -0
  64. package/docs/.nojekyll +1 -0
  65. package/docs/assets/hierarchy.js +1 -0
  66. package/docs/assets/highlight.css +99 -0
  67. package/docs/assets/icons.js +18 -0
  68. package/docs/assets/icons.svg +1 -0
  69. package/docs/assets/main.js +60 -0
  70. package/docs/assets/navigation.js +1 -0
  71. package/docs/assets/search.js +1 -0
  72. package/docs/assets/style.css +1648 -0
  73. package/docs/classes/index.BaseEntityClient.html +124 -0
  74. package/docs/classes/index.BaseQueryBuilder.html +229 -0
  75. package/docs/classes/index.EntityManager.html +510 -0
  76. package/docs/documents/CHANGELOG.html +1432 -0
  77. package/docs/documents/guides_stan-assistant-guide.html +431 -0
  78. package/docs/functions/index.createEntityManager.html +60 -0
  79. package/docs/hierarchy.html +31 -0
  80. package/docs/index.html +212 -0
  81. package/docs/interfaces/index.BaseConfigMap.html +113 -0
  82. package/docs/interfaces/index.BaseEntityClientOptions.html +82 -0
  83. package/docs/interfaces/index.BaseQueryBuilderOptions.html +92 -0
  84. package/docs/interfaces/index.CapturedConfigMapFrom.html +126 -0
  85. package/docs/interfaces/index.ConfigInput.html +189 -0
  86. package/docs/interfaces/index.ParsedConfig.html +144 -0
  87. package/docs/interfaces/index.ParsedEntityConfig.html +91 -0
  88. package/docs/interfaces/index.ParsedGeneratedPropertiesConfig.html +67 -0
  89. package/docs/interfaces/index.ParsedIndexConfig.html +79 -0
  90. package/docs/interfaces/index.ParsedTranscoder.html +71 -0
  91. package/docs/interfaces/index.QueryOptions.html +180 -0
  92. package/docs/interfaces/index.QueryResult.html +91 -0
  93. package/docs/interfaces/index.ShardBump.html +79 -0
  94. package/docs/interfaces/index.ShardQueryResult.html +93 -0
  95. package/docs/modules/index.html +47 -0
  96. package/docs/modules.html +38 -0
  97. package/docs/sitemap.xml +263 -0
  98. package/docs/types/index.BaseKeyTokens.html +39 -0
  99. package/docs/types/index.Config.html +75 -0
  100. package/docs/types/index.ConfigMap.html +41 -0
  101. package/docs/types/index.ConfigOfClient.html +45 -0
  102. package/docs/types/index.EntitiesFromSchema.html +39 -0
  103. package/docs/types/index.EntityClientItemByToken.html +45 -0
  104. package/docs/types/index.EntityClientRecordByToken.html +43 -0
  105. package/docs/types/index.EntityItem.html +41 -0
  106. package/docs/types/index.EntityItemPartial.html +44 -0
  107. package/docs/types/index.EntityKey.html +40 -0
  108. package/docs/types/index.EntityOfToken.html +39 -0
  109. package/docs/types/index.EntityRecord.html +39 -0
  110. package/docs/types/index.EntityRecordPartial.html +40 -0
  111. package/docs/types/index.EntityToken.html +40 -0
  112. package/docs/types/index.FallbackIndexTokenSet.html +40 -0
  113. package/docs/types/index.HasIndexFor.html +43 -0
  114. package/docs/types/index.HashKeyFrom.html +38 -0
  115. package/docs/types/index.IndexComponentTokens.html +45 -0
  116. package/docs/types/index.IndexHashKeyOf.html +42 -0
  117. package/docs/types/index.IndexRangeKeyOf.html +41 -0
  118. package/docs/types/index.IndexTokensFrom.html +41 -0
  119. package/docs/types/index.IndexTokensOf.html +40 -0
  120. package/docs/types/index.KeysFrom.html +38 -0
  121. package/docs/types/index.PageKey.html +40 -0
  122. package/docs/types/index.PageKeyByIndex.html +46 -0
  123. package/docs/types/index.PresentIndexTokenSet.html +45 -0
  124. package/docs/types/index.Projected.html +39 -0
  125. package/docs/types/index.QueryBuilderQueryOptions.html +45 -0
  126. package/docs/types/index.QueryOptionsByCC.html +49 -0
  127. package/docs/types/index.QueryOptionsByCF.html +47 -0
  128. package/docs/types/index.RangeKeyFrom.html +38 -0
  129. package/docs/types/index.ShardQueryFunction.html +63 -0
  130. package/docs/types/index.ShardQueryMap.html +56 -0
  131. package/docs/types/index.ShardQueryMapByCC.html +49 -0
  132. package/docs/types/index.ShardQueryMapByCF.html +47 -0
  133. package/docs/types/index.ShardedKeysFrom.html +38 -0
  134. package/docs/types/index.StorageItem.html +42 -0
  135. package/docs/types/index.StorageRecord.html +40 -0
  136. package/docs/types/index.TranscodedPropertiesFrom.html +38 -0
  137. package/docs/types/index.UnshardedKeysFrom.html +38 -0
  138. package/docs/types/index.ValidateConfigMap.html +40 -0
  139. package/lib/EntityManager/PrivateEntityManager.js +4 -0
  140. package/package.json +6 -6
@@ -46,11 +46,10 @@ class EntityManager {
46
46
  * @throws {Error} If config is invalid.
47
47
  * @throws {Error} If logger is invalid.
48
48
  */
49
- constructor(_ref) {
50
- let {
51
- config,
52
- logger
53
- } = _ref;
49
+ constructor({
50
+ config,
51
+ logger
52
+ }) {
54
53
  this.#entityManager = new _PrivateEntityManager.PrivateEntityManager({
55
54
  config,
56
55
  logger
@@ -67,8 +66,7 @@ class EntityManager {
67
66
  * @throws {Error} If entityToken is invalid.
68
67
  * @throws {Error} If item is invalid.
69
68
  */
70
- addKeys(entityToken, item) {
71
- let overwrite = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
69
+ addKeys(entityToken, item, overwrite = false) {
72
70
  this.#entityManager.logger.debug(`adding sharded index keys to ${entityToken}${overwrite ? ' with overwrite' : ''}...`, {
73
71
  item
74
72
  });
@@ -93,10 +91,9 @@ class EntityManager {
93
91
  }
94
92
 
95
93
  // Add keys.
96
- (0, _forEach2.default)(keys, (_ref2, key) => {
97
- let {
98
- encode
99
- } = _ref2;
94
+ (0, _forEach2.default)(keys, ({
95
+ encode
96
+ }, key) => {
100
97
  if (overwrite || (0, _isNil2.default)(newItem[key])) newItem[key] = encode(newItem);
101
98
  });
102
99
  this.#entityManager.logger.debug('done', {
@@ -136,8 +133,7 @@ class EntityManager {
136
133
  * @throws {Error} If indexToken is invalid.
137
134
  * @throws {Error} If item is invalid.
138
135
  */
139
- dehydrateIndex(entityToken, indexToken, index) {
140
- let delimiter = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '~';
136
+ dehydrateIndex(entityToken, indexToken, index, delimiter = '~') {
141
137
  // Validate item.
142
138
  this.#entityManager.validateItem(index);
143
139
  const indexComponents = (0, _isArray2.default)(indexToken) ? indexToken : this.#entityManager.getIndexComponents(entityToken, indexToken);
@@ -151,16 +147,7 @@ class EntityManager {
151
147
  ...(decode(index[component] ?? '') ?? {})
152
148
  };
153
149
  }, {});
154
- return (0, _sortedUniqBy2.default)((0, _sortBy2.default)((0, _entries2.default)(indexProperties), _ref3 => {
155
- let [key] = _ref3;
156
- return key;
157
- }), _ref4 => {
158
- let [key] = _ref4;
159
- return key;
160
- }).map(_ref5 => {
161
- let [, value] = _ref5;
162
- return value;
163
- }).join(delimiter);
150
+ return (0, _sortedUniqBy2.default)((0, _sortBy2.default)((0, _entries2.default)(indexProperties), ([key]) => key), ([key]) => key).map(([, value]) => value).join(delimiter);
164
151
  }
165
152
 
166
153
  /**
@@ -191,8 +178,7 @@ class EntityManager {
191
178
  * @throws {Error} If keyToken is invalid.
192
179
  * @throws {Error} If timestamp is invalid.
193
180
  */
194
- getKeySpace(entityToken, keyToken, item) {
195
- let timestamp = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : Date.now();
181
+ getKeySpace(entityToken, keyToken, item, timestamp = Date.now()) {
196
182
  this.#entityManager.logger.debug(`getting shard key space for ${entityToken} on key '${keyToken}' at timestamp ${timestamp}...`, {
197
183
  item
198
184
  });
@@ -242,16 +228,15 @@ class EntityManager {
242
228
  * @param {number} [options.pageSize] - Request page size.
243
229
  * @returns {Promise<ShardedQueryResult>} Sharded query result.
244
230
  */
245
- async query() {
246
- let {
247
- entityToken,
248
- keyToken = 'entityPK',
249
- item = {},
250
- shardQuery,
251
- limit,
252
- pageKeys,
253
- pageSize
254
- } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
231
+ async query({
232
+ entityToken,
233
+ keyToken = 'entityPK',
234
+ item = {},
235
+ shardQuery,
236
+ limit,
237
+ pageKeys,
238
+ pageSize
239
+ } = {}) {
255
240
  // Validate params.
256
241
  this.#entityManager.validateKeyToken(entityToken, keyToken);
257
242
  this.#entityManager.validateItem(item);
@@ -298,39 +283,33 @@ class EntityManager {
298
283
  // iteration in order to keep shardsQueried * pageSize > (limit - items.length) but only just.
299
284
 
300
285
  // Query every shard in pageKeys.
301
- const shardQueryResults = await Promise.all((0, _map2.default)(result.pageKeys, (pageKey, shardedKey) => new Promise(resolve => shardQuery(shardedKey, pageKey, pageSize).then(_ref6 => {
302
- let {
303
- count,
304
- items,
305
- pageKey
306
- } = _ref6;
307
- return resolve({
308
- count,
309
- items,
310
- pageKey,
311
- shardedKey
312
- });
313
- }))));
286
+ const shardQueryResults = await Promise.all((0, _map2.default)(result.pageKeys, (pageKey, shardedKey) => new Promise(resolve => shardQuery(shardedKey, pageKey, pageSize).then(({
287
+ count,
288
+ items,
289
+ pageKey
290
+ }) => resolve({
291
+ count,
292
+ items,
293
+ pageKey,
294
+ shardedKey
295
+ })))));
314
296
 
315
297
  // Reduce shardQueryResults into a single result.
316
- const pageResult = shardQueryResults.reduce((shardedQueryResult, _ref7) => {
317
- let {
318
- count,
319
- items,
320
- pageKey,
321
- shardedKey
322
- } = _ref7;
323
- return {
324
- count: shardedQueryResult.count + count,
325
- items: [...shardedQueryResult.items, ...items],
326
- pageKeys: {
327
- ...shardedQueryResult.pageKeys,
328
- ...((0, _isUndefined2.default)(pageKey) ? {} : {
329
- [shardedKey]: pageKey
330
- })
331
- }
332
- };
333
- }, {
298
+ const pageResult = shardQueryResults.reduce((shardedQueryResult, {
299
+ count,
300
+ items,
301
+ pageKey,
302
+ shardedKey
303
+ }) => ({
304
+ count: shardedQueryResult.count + count,
305
+ items: [...shardedQueryResult.items, ...items],
306
+ pageKeys: {
307
+ ...shardedQueryResult.pageKeys,
308
+ ...((0, _isUndefined2.default)(pageKey) ? {} : {
309
+ [shardedKey]: pageKey
310
+ })
311
+ }
312
+ }), {
334
313
  count: 0,
335
314
  items: [],
336
315
  pageKeys: {}
@@ -357,9 +336,7 @@ class EntityManager {
357
336
  * @throws {Error} If entityToken is invalid.
358
337
  * @throws {Error} If indexToken is invalid.
359
338
  */
360
- rehydrateIndex(entityToken, indexToken) {
361
- let value = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
362
- let delimiter = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '~';
339
+ rehydrateIndex(entityToken, indexToken, value = '', delimiter = '~') {
363
340
  const indexComponents = (0, _isArray2.default)(indexToken) ? indexToken : this.#entityManager.getIndexComponents(entityToken, indexToken);
364
341
  const indexKeys = (0, _sortBy2.default)(indexComponents.reduce((keys, component) => {
365
342
  const {
@@ -137,11 +137,10 @@ class PrivateEntityManager {
137
137
  * @throws {Error} If config is invalid.
138
138
  * @throws {Error} If logger is invalid.
139
139
  */
140
- constructor() {
141
- let {
142
- config = {},
143
- logger = console
144
- } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
140
+ constructor({
141
+ config = {},
142
+ logger = console
143
+ } = {}) {
145
144
  // Validate logger.
146
145
  if (!logger.error || !logger.debug) throw new Error('logger must implement error & debug methods.');
147
146
  this.#logger = logger;
@@ -176,50 +175,46 @@ class PrivateEntityManager {
176
175
  shardKeyToken = 'shardId'
177
176
  } = value;
178
177
  const conformedConfig = {
179
- entities: (0, _mapValues2.default)(entities, _ref => {
180
- let {
181
- defaultLimit = DEFAULT_LIMIT,
182
- defaultPageSize = DEFAULT_PAGE_SIZE,
183
- indexes = {},
184
- keys = {},
185
- sharding: {
186
- bumps = {},
187
- entityKey,
188
- nibbleBits = 1,
189
- nibbles = 0,
190
- timestamp
191
- } = {}
192
- } = _ref;
193
- return {
194
- defaultLimit,
195
- defaultPageSize,
196
- indexes,
197
- keys,
198
- sharding: {
199
- bumps: (0, _fromPairs2.default)((0, _sortBy2.default)((0, _toPairs2.default)(bumps), 0)),
200
- entityKey,
201
- nibbleBits,
202
- nibbles,
203
- timestamp
204
- }
205
- };
206
- }),
207
- shardKeyToken
208
- };
209
-
210
- // Conform & validate entity properties.
211
- (0, _some2.default)(conformedConfig.entities, (_ref2, entityToken) => {
212
- let {
178
+ entities: (0, _mapValues2.default)(entities, ({
179
+ defaultLimit = DEFAULT_LIMIT,
180
+ defaultPageSize = DEFAULT_PAGE_SIZE,
181
+ indexes = {},
182
+ keys = {},
183
+ sharding: {
184
+ bumps = {},
185
+ entityKey,
186
+ nibbleBits = 1,
187
+ nibbles = 0,
188
+ timestamp
189
+ } = {}
190
+ }) => ({
191
+ defaultLimit,
192
+ defaultPageSize,
213
193
  indexes,
214
194
  keys,
215
195
  sharding: {
216
- bumps,
196
+ bumps: (0, _fromPairs2.default)((0, _sortBy2.default)((0, _toPairs2.default)(bumps), 0)),
217
197
  entityKey,
218
198
  nibbleBits,
219
199
  nibbles,
220
200
  timestamp
221
201
  }
222
- } = _ref2;
202
+ })),
203
+ shardKeyToken
204
+ };
205
+
206
+ // Conform & validate entity properties.
207
+ (0, _some2.default)(conformedConfig.entities, ({
208
+ indexes,
209
+ keys,
210
+ sharding: {
211
+ bumps,
212
+ entityKey,
213
+ nibbleBits,
214
+ nibbles,
215
+ timestamp
216
+ }
217
+ }, entityToken) => {
223
218
  // Validate entity index components are entity keys.
224
219
  (0, _some2.default)(indexes, (index, indexToken) => {
225
220
  const invalidIndexComponents = (0, _difference2.default)(index, (0, _keys2.default)(keys));
@@ -242,8 +237,7 @@ class PrivateEntityManager {
242
237
  });
243
238
 
244
239
  // Validate sharding bump values increase monotonically with keys.
245
- (0, _some2.default)((0, _toPairs2.default)(bumps), (_ref3, i, c) => {
246
- let [bump, value] = _ref3;
240
+ (0, _some2.default)((0, _toPairs2.default)(bumps), ([bump, value], i, c) => {
247
241
  const [lastBump, lastValue] = i ? c[i - 1] : [];
248
242
  if (value <= lastValue) throw new Error(`${entityToken} sharding bumps do not monotonically increase from '${lastBump}: ${lastValue}' to '${bump}: ${value}'.)`);else return false;
249
243
  });
@@ -298,6 +292,9 @@ class PrivateEntityManager {
298
292
  return this.config.entities[entityToken];
299
293
  }
300
294
  getIndexComponents(entityToken, indexToken) {
295
+ // When indexToken is undefined/null, return the base table primary key
296
+ // components. This supports queries against the main table (no GSI).
297
+ if (indexToken == null) return ['entityPK', 'entitySK'];
301
298
  const {
302
299
  indexes
303
300
  } = this.getEntityConfig(entityToken);
@@ -312,8 +309,7 @@ class PrivateEntityManager {
312
309
  * @param {number} [timestamp] - Timestamp in milliseconds (defaults to current time).
313
310
  * @returns {{nibbleBits: number, nibbles: number}} Result object.
314
311
  */
315
- getNibbles(entityToken) {
316
- let timestamp = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Date.now();
312
+ getNibbles(entityToken, timestamp = Date.now()) {
317
313
  const {
318
314
  nibbleBits,
319
315
  nibbles,
@@ -334,8 +330,7 @@ class PrivateEntityManager {
334
330
  * @param {number} [timestamp] - Timestamp in milliseconds (defaults to current time).
335
331
  * @returns {string} shard key.
336
332
  */
337
- getShardKey(entityToken, entityKey) {
338
- let timestamp = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : Date.now();
333
+ getShardKey(entityToken, entityKey, timestamp = Date.now()) {
339
334
  // Get nibbles for entityToken at timestamp (validates entityToken)
340
335
  const {
341
336
  nibbleBits,
@@ -356,8 +351,7 @@ class PrivateEntityManager {
356
351
  * @param {number} [timestamp] - Timestamp in milliseconds (defaults to current time).
357
352
  * @returns {string[]} shard key space.
358
353
  */
359
- getShardKeySpace(entityToken) {
360
- let timestamp = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Date.now();
354
+ getShardKeySpace(entityToken, timestamp = Date.now()) {
361
355
  const {
362
356
  nibbleBits,
363
357
  nibbles,
@@ -413,8 +407,7 @@ class PrivateEntityManager {
413
407
  * @param {boolean} [future] - true if timestamp must be in the future.
414
408
  * @returns {boolean} true if timestamp is valid.
415
409
  */
416
- validateTimestamp(timestamp) {
417
- let future = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
410
+ validateTimestamp(timestamp, future = false) {
418
411
  if (!(0, _isInteger2.default)(timestamp) || future && timestamp <= Date.now()) throw new Error(`invalid timestamp (must be an integer${future ? ' in the future' : ''})`);else return true;
419
412
  }
420
413
  }