s3db.js 12.2.3 → 12.3.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/README.md +915 -1669
- package/dist/s3db.cjs.js +610 -50
- package/dist/s3db.cjs.js.map +1 -1
- package/dist/s3db.es.js +610 -50
- package/dist/s3db.es.js.map +1 -1
- package/package.json +1 -1
- package/src/behaviors/body-only.js +15 -5
- package/src/behaviors/body-overflow.js +9 -0
- package/src/behaviors/user-managed.js +8 -1
- package/src/concerns/typescript-generator.js +12 -2
- package/src/plugins/api/utils/openapi-generator.js +21 -2
- package/src/plugins/replicators/bigquery-replicator.class.js +9 -1
- package/src/plugins/replicators/mysql-replicator.class.js +9 -1
- package/src/plugins/replicators/planetscale-replicator.class.js +9 -1
- package/src/plugins/replicators/postgres-replicator.class.js +9 -1
- package/src/plugins/replicators/schema-sync.helper.js +19 -0
- package/src/plugins/replicators/turso-replicator.class.js +9 -1
- package/src/plugins/vector.plugin.js +361 -9
- package/src/resource.class.js +203 -4
- package/src/schema.class.js +223 -33
package/package.json
CHANGED
|
@@ -59,10 +59,15 @@ export async function handleInsert({ resource, data, mappedData }) {
|
|
|
59
59
|
'_v': mappedData._v || String(resource.version)
|
|
60
60
|
};
|
|
61
61
|
metadataOnly._map = JSON.stringify(resource.schema.map);
|
|
62
|
-
|
|
62
|
+
|
|
63
|
+
// Store pluginMap for backwards compatibility when plugins are added/removed
|
|
64
|
+
if (resource.schema.pluginMap && Object.keys(resource.schema.pluginMap).length > 0) {
|
|
65
|
+
metadataOnly._pluginMap = JSON.stringify(resource.schema.pluginMap);
|
|
66
|
+
}
|
|
67
|
+
|
|
63
68
|
// Use the original object for the body
|
|
64
69
|
const body = JSON.stringify(mappedData);
|
|
65
|
-
|
|
70
|
+
|
|
66
71
|
return { mappedData: metadataOnly, body };
|
|
67
72
|
}
|
|
68
73
|
|
|
@@ -70,16 +75,21 @@ export async function handleUpdate({ resource, id, data, mappedData }) {
|
|
|
70
75
|
// For updates, we need to merge with existing data
|
|
71
76
|
// Since we can't easily read the existing body during update,
|
|
72
77
|
// we'll put the update data in the body and let the resource handle merging
|
|
73
|
-
|
|
78
|
+
|
|
74
79
|
// Keep only the version field in metadata
|
|
75
80
|
const metadataOnly = {
|
|
76
81
|
'_v': mappedData._v || String(resource.version)
|
|
77
82
|
};
|
|
78
83
|
metadataOnly._map = JSON.stringify(resource.schema.map);
|
|
79
|
-
|
|
84
|
+
|
|
85
|
+
// Store pluginMap for backwards compatibility when plugins are added/removed
|
|
86
|
+
if (resource.schema.pluginMap && Object.keys(resource.schema.pluginMap).length > 0) {
|
|
87
|
+
metadataOnly._pluginMap = JSON.stringify(resource.schema.pluginMap);
|
|
88
|
+
}
|
|
89
|
+
|
|
80
90
|
// Use the original object for the body
|
|
81
91
|
const body = JSON.stringify(mappedData);
|
|
82
|
-
|
|
92
|
+
|
|
83
93
|
return { mappedData: metadataOnly, body };
|
|
84
94
|
}
|
|
85
95
|
|
|
@@ -90,6 +90,15 @@ export async function handleInsert({ resource, data, mappedData, originalData })
|
|
|
90
90
|
currentSize += attributeSizes._v;
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
// Always include plugin map for backwards compatibility when plugins are added/removed
|
|
94
|
+
// Note: _pluginMap is not in mappedData, it's added separately by behaviors
|
|
95
|
+
if (resource.schema?.pluginMap && Object.keys(resource.schema.pluginMap).length > 0) {
|
|
96
|
+
const pluginMapStr = JSON.stringify(resource.schema.pluginMap);
|
|
97
|
+
const pluginMapSize = calculateUTF8Bytes('_pluginMap') + calculateUTF8Bytes(pluginMapStr);
|
|
98
|
+
metadataFields._pluginMap = pluginMapStr;
|
|
99
|
+
currentSize += pluginMapSize;
|
|
100
|
+
}
|
|
101
|
+
|
|
93
102
|
// Reserve space for $overflow if overflow is possible
|
|
94
103
|
let reservedLimit = effectiveLimit;
|
|
95
104
|
for (const [fieldName, size] of sortedFields) {
|
|
@@ -88,7 +88,14 @@ export async function handleInsert({ resource, data, mappedData, originalData })
|
|
|
88
88
|
data: originalData || data
|
|
89
89
|
});
|
|
90
90
|
// If data exceeds limit, store in body
|
|
91
|
-
|
|
91
|
+
const metadataOnly = { _v: mappedData._v };
|
|
92
|
+
|
|
93
|
+
// Store pluginMap for backwards compatibility when plugins are added/removed
|
|
94
|
+
if (resource.schema?.pluginMap && Object.keys(resource.schema.pluginMap).length > 0) {
|
|
95
|
+
metadataOnly._pluginMap = JSON.stringify(resource.schema.pluginMap);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return { mappedData: metadataOnly, body: JSON.stringify(mappedData) };
|
|
92
99
|
}
|
|
93
100
|
|
|
94
101
|
// If data fits in metadata, store only in metadata
|
|
@@ -190,10 +190,20 @@ export async function generateTypes(database, options = {}) {
|
|
|
190
190
|
const resourceInterfaces = [];
|
|
191
191
|
|
|
192
192
|
for (const [name, resource] of Object.entries(database.resources)) {
|
|
193
|
-
const
|
|
193
|
+
const allAttributes = resource.config?.attributes || resource.attributes || {};
|
|
194
194
|
const timestamps = resource.config?.timestamps || false;
|
|
195
195
|
|
|
196
|
-
|
|
196
|
+
// Filter out plugin attributes - they are internal implementation details
|
|
197
|
+
// and should not be exposed in public TypeScript interfaces
|
|
198
|
+
const pluginAttrNames = resource.schema?._pluginAttributes
|
|
199
|
+
? Object.values(resource.schema._pluginAttributes).flat()
|
|
200
|
+
: [];
|
|
201
|
+
|
|
202
|
+
const userAttributes = Object.fromEntries(
|
|
203
|
+
Object.entries(allAttributes).filter(([name]) => !pluginAttrNames.includes(name))
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
const interfaceDef = generateResourceInterface(name, userAttributes, timestamps);
|
|
197
207
|
lines.push(interfaceDef);
|
|
198
208
|
|
|
199
209
|
resourceInterfaces.push({
|
|
@@ -98,7 +98,17 @@ function generateResourceSchema(resource) {
|
|
|
98
98
|
const properties = {};
|
|
99
99
|
const required = [];
|
|
100
100
|
|
|
101
|
-
const
|
|
101
|
+
const allAttributes = resource.config?.attributes || resource.attributes || {};
|
|
102
|
+
|
|
103
|
+
// Filter out plugin attributes - they are internal implementation details
|
|
104
|
+
// and should not be exposed in public API documentation
|
|
105
|
+
const pluginAttrNames = resource.schema?._pluginAttributes
|
|
106
|
+
? Object.values(resource.schema._pluginAttributes).flat()
|
|
107
|
+
: [];
|
|
108
|
+
|
|
109
|
+
const attributes = Object.fromEntries(
|
|
110
|
+
Object.entries(allAttributes).filter(([name]) => !pluginAttrNames.includes(name))
|
|
111
|
+
);
|
|
102
112
|
|
|
103
113
|
// Extract resource description (supports both string and object format)
|
|
104
114
|
const resourceDescription = resource.config?.description;
|
|
@@ -254,7 +264,16 @@ function generateResourcePaths(resource, version, config = {}) {
|
|
|
254
264
|
}
|
|
255
265
|
|
|
256
266
|
// Create query parameters only for partition fields
|
|
257
|
-
const
|
|
267
|
+
const allAttributes = resource.config?.attributes || resource.attributes || {};
|
|
268
|
+
|
|
269
|
+
// Filter out plugin attributes
|
|
270
|
+
const pluginAttrNames = resource.schema?._pluginAttributes
|
|
271
|
+
? Object.values(resource.schema._pluginAttributes).flat()
|
|
272
|
+
: [];
|
|
273
|
+
|
|
274
|
+
const attributes = Object.fromEntries(
|
|
275
|
+
Object.entries(allAttributes).filter(([name]) => !pluginAttrNames.includes(name))
|
|
276
|
+
);
|
|
258
277
|
|
|
259
278
|
for (const fieldName of partitionFieldsSet) {
|
|
260
279
|
const fieldDef = attributes[fieldName];
|
|
@@ -186,7 +186,15 @@ class BigqueryReplicator extends BaseReplicator {
|
|
|
186
186
|
continue;
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
-
const
|
|
189
|
+
const allAttributes = resource.config.versions[resource.config.currentVersion]?.attributes || {};
|
|
190
|
+
|
|
191
|
+
// Filter out plugin attributes - they are internal and should not be replicated
|
|
192
|
+
const pluginAttrNames = resource.schema?._pluginAttributes
|
|
193
|
+
? Object.values(resource.schema._pluginAttributes).flat()
|
|
194
|
+
: [];
|
|
195
|
+
const attributes = Object.fromEntries(
|
|
196
|
+
Object.entries(allAttributes).filter(([name]) => !pluginAttrNames.includes(name))
|
|
197
|
+
);
|
|
190
198
|
|
|
191
199
|
for (const tableConfig of tableConfigs) {
|
|
192
200
|
const tableName = tableConfig.table;
|
|
@@ -221,7 +221,15 @@ class MySQLReplicator extends BaseReplicator {
|
|
|
221
221
|
continue;
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
-
const
|
|
224
|
+
const allAttributes = resource.config.versions[resource.config.currentVersion]?.attributes || {};
|
|
225
|
+
|
|
226
|
+
// Filter out plugin attributes - they are internal and should not be replicated
|
|
227
|
+
const pluginAttrNames = resource.schema?._pluginAttributes
|
|
228
|
+
? Object.values(resource.schema._pluginAttributes).flat()
|
|
229
|
+
: [];
|
|
230
|
+
const attributes = Object.fromEntries(
|
|
231
|
+
Object.entries(allAttributes).filter(([name]) => !pluginAttrNames.includes(name))
|
|
232
|
+
);
|
|
225
233
|
|
|
226
234
|
for (const tableConfig of tableConfigs) {
|
|
227
235
|
const tableName = tableConfig.table;
|
|
@@ -183,7 +183,15 @@ class PlanetScaleReplicator extends BaseReplicator {
|
|
|
183
183
|
continue;
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
-
const
|
|
186
|
+
const allAttributes = resource.config.versions[resource.config.currentVersion]?.attributes || {};
|
|
187
|
+
|
|
188
|
+
// Filter out plugin attributes - they are internal and should not be replicated
|
|
189
|
+
const pluginAttrNames = resource.schema?._pluginAttributes
|
|
190
|
+
? Object.values(resource.schema._pluginAttributes).flat()
|
|
191
|
+
: [];
|
|
192
|
+
const attributes = Object.fromEntries(
|
|
193
|
+
Object.entries(allAttributes).filter(([name]) => !pluginAttrNames.includes(name))
|
|
194
|
+
);
|
|
187
195
|
|
|
188
196
|
for (const tableConfig of tableConfigs) {
|
|
189
197
|
const tableName = tableConfig.table;
|
|
@@ -225,7 +225,15 @@ class PostgresReplicator extends BaseReplicator {
|
|
|
225
225
|
}
|
|
226
226
|
|
|
227
227
|
// Get resource attributes from current version
|
|
228
|
-
const
|
|
228
|
+
const allAttributes = resource.config.versions[resource.config.currentVersion]?.attributes || {};
|
|
229
|
+
|
|
230
|
+
// Filter out plugin attributes - they are internal and should not be replicated
|
|
231
|
+
const pluginAttrNames = resource.schema?._pluginAttributes
|
|
232
|
+
? Object.values(resource.schema._pluginAttributes).flat()
|
|
233
|
+
: [];
|
|
234
|
+
const attributes = Object.fromEntries(
|
|
235
|
+
Object.entries(allAttributes).filter(([name]) => !pluginAttrNames.includes(name))
|
|
236
|
+
);
|
|
229
237
|
|
|
230
238
|
// Sync each table configured for this resource
|
|
231
239
|
for (const tableConfig of tableConfigs) {
|
|
@@ -7,6 +7,25 @@
|
|
|
7
7
|
|
|
8
8
|
import tryFn from "#src/concerns/try-fn.js";
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Filter out plugin attributes from attributes object
|
|
12
|
+
* Plugin attributes are internal implementation details and should not be replicated
|
|
13
|
+
* @param {Object} attributes - All attributes including plugin attributes
|
|
14
|
+
* @param {Object} resource - Resource instance with schema._pluginAttributes
|
|
15
|
+
* @returns {Object} Filtered attributes (user attributes only)
|
|
16
|
+
*/
|
|
17
|
+
function filterPluginAttributes(attributes, resource) {
|
|
18
|
+
if (!resource?.schema?._pluginAttributes) {
|
|
19
|
+
return attributes;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const pluginAttrNames = Object.values(resource.schema._pluginAttributes).flat();
|
|
23
|
+
|
|
24
|
+
return Object.fromEntries(
|
|
25
|
+
Object.entries(attributes).filter(([name]) => !pluginAttrNames.includes(name))
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
10
29
|
/**
|
|
11
30
|
* Parse s3db field type notation (e.g., 'string|required|maxlength:50')
|
|
12
31
|
*/
|
|
@@ -177,7 +177,15 @@ class TursoReplicator extends BaseReplicator {
|
|
|
177
177
|
continue;
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
-
const
|
|
180
|
+
const allAttributes = resource.config.versions[resource.config.currentVersion]?.attributes || {};
|
|
181
|
+
|
|
182
|
+
// Filter out plugin attributes - they are internal and should not be replicated
|
|
183
|
+
const pluginAttrNames = resource.schema?._pluginAttributes
|
|
184
|
+
? Object.values(resource.schema._pluginAttributes).flat()
|
|
185
|
+
: [];
|
|
186
|
+
const attributes = Object.fromEntries(
|
|
187
|
+
Object.entries(allAttributes).filter(([name]) => !pluginAttrNames.includes(name))
|
|
188
|
+
);
|
|
181
189
|
|
|
182
190
|
for (const tableConfig of tableConfigs) {
|
|
183
191
|
const tableName = tableConfig.table;
|