s3db.js 10.0.6 → 10.0.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "s3db.js",
3
- "version": "10.0.6",
3
+ "version": "10.0.8",
4
4
  "description": "Use AWS S3, the world's most reliable document storage, as a database with this ORM.",
5
5
  "main": "dist/s3db.cjs.js",
6
6
  "module": "dist/s3db.es.js",
@@ -475,6 +475,7 @@ export class Database extends EventEmitter {
475
475
  metadata.resources[name] = {
476
476
  currentVersion: version,
477
477
  partitions: resource.config.partitions || {},
478
+ createdBy: existingResource?.createdBy || resource.config.createdBy || 'user',
478
479
  versions: {
479
480
  ...existingResource?.versions, // Preserve previous versions
480
481
  [version]: {
@@ -906,6 +907,7 @@ export class Database extends EventEmitter {
906
907
  * @param {boolean} [config.autoDecrypt=true] - Auto-decrypt secret fields
907
908
  * @param {Function|number} [config.idGenerator] - Custom ID generator or size
908
909
  * @param {number} [config.idSize=22] - Size for auto-generated IDs
910
+ * @param {string} [config.createdBy='user'] - Who created this resource ('user', 'plugin', or plugin name)
909
911
  * @returns {Promise<Resource>} The created or updated resource
910
912
  */
911
913
  async createResource({ name, attributes, behavior = 'user-managed', hooks, ...config }) {
@@ -968,7 +970,8 @@ export class Database extends EventEmitter {
968
970
  idGenerator: config.idGenerator,
969
971
  idSize: config.idSize,
970
972
  asyncEvents: config.asyncEvents,
971
- events: config.events || {}
973
+ events: config.events || {},
974
+ createdBy: config.createdBy || 'user'
972
975
  });
973
976
  resource.database = this;
974
977
  this.resources[name] = resource;
@@ -113,7 +113,15 @@ export class CachePlugin extends Plugin {
113
113
  }
114
114
 
115
115
  shouldCacheResource(resourceName) {
116
- // Skip plugin resources by default (unless explicitly included)
116
+ // Get resource metadata to check createdBy
117
+ const resourceMetadata = this.database.savedMetadata?.resources?.[resourceName];
118
+
119
+ // Skip plugin-created resources by default (unless explicitly included)
120
+ if (resourceMetadata?.createdBy && resourceMetadata.createdBy !== 'user' && !this.config.include) {
121
+ return false;
122
+ }
123
+
124
+ // Legacy: Skip plugin resources by name pattern (unless explicitly included)
117
125
  if (resourceName.startsWith('plg_') && !this.config.include) {
118
126
  return false;
119
127
  }
@@ -144,7 +144,8 @@ export class EventualConsistencyPlugin extends Plugin {
144
144
  behavior: 'body-overflow',
145
145
  timestamps: true,
146
146
  partitions: partitionConfig,
147
- asyncPartitions: true // Use async partitions for better performance
147
+ asyncPartitions: true, // Use async partitions for better performance
148
+ createdBy: 'EventualConsistencyPlugin'
148
149
  })
149
150
  );
150
151
 
@@ -165,7 +166,8 @@ export class EventualConsistencyPlugin extends Plugin {
165
166
  workerId: 'string|optional'
166
167
  },
167
168
  behavior: 'body-only',
168
- timestamps: false
169
+ timestamps: false,
170
+ createdBy: 'EventualConsistencyPlugin'
169
171
  })
170
172
  );
171
173
 
@@ -309,7 +311,8 @@ export class EventualConsistencyPlugin extends Plugin {
309
311
  byCohort: {
310
312
  fields: { cohort: 'string' }
311
313
  }
312
- }
314
+ },
315
+ createdBy: 'EventualConsistencyPlugin'
313
316
  })
314
317
  );
315
318
 
@@ -917,6 +920,29 @@ export class EventualConsistencyPlugin extends Plugin {
917
920
  if (this.config.enableAnalytics && transactionsToUpdate.length > 0) {
918
921
  await this.updateAnalytics(transactionsToUpdate);
919
922
  }
923
+
924
+ // Invalidate cache for this record after consolidation
925
+ if (this.targetResource.cache && typeof this.targetResource.cache.delete === 'function') {
926
+ try {
927
+ const cacheKey = await this.targetResource.cacheKeyFor({ id: originalId });
928
+ await this.targetResource.cache.delete(cacheKey);
929
+
930
+ if (this.config.verbose) {
931
+ console.log(
932
+ `[EventualConsistency] ${this.config.resource}.${this.config.field} - ` +
933
+ `Cache invalidated for ${originalId}`
934
+ );
935
+ }
936
+ } catch (cacheErr) {
937
+ // Log but don't fail consolidation if cache invalidation fails
938
+ if (this.config.verbose) {
939
+ console.warn(
940
+ `[EventualConsistency] ${this.config.resource}.${this.config.field} - ` +
941
+ `Failed to invalidate cache for ${originalId}: ${cacheErr?.message}`
942
+ );
943
+ }
944
+ }
945
+ }
920
946
  }
921
947
 
922
948
  return consolidatedValue;
@@ -136,7 +136,8 @@ export class Resource extends AsyncEventEmitter {
136
136
  versioningEnabled = false,
137
137
  events = {},
138
138
  asyncEvents = true,
139
- asyncPartitions = true
139
+ asyncPartitions = true,
140
+ createdBy = 'user'
140
141
  } = config;
141
142
 
142
143
  // Set instance properties
@@ -179,6 +180,7 @@ export class Resource extends AsyncEventEmitter {
179
180
  allNestedObjectsOptional,
180
181
  asyncEvents,
181
182
  asyncPartitions,
183
+ createdBy,
182
184
  };
183
185
 
184
186
  // Initialize hooks system