magically-sdk
Version:
Official SDK for Magically - Build mobile apps with AI
194 lines (193 loc) • 6.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.MagicallyData = void 0;
const APIClient_1 = require("./APIClient");
class MagicallyData {
constructor(config, auth) {
this.config = config;
this.auth = auth;
this.apiClient = new APIClient_1.APIClient(config, 'MagicallyData');
}
/**
* Check if a query is public (doesn't require authentication)
*/
isPublicQuery(filter) {
return filter?.isPublic === true;
}
/**
* Check if an aggregate pipeline is public (doesn't require authentication)
*/
isPublicAggregate(pipeline) {
return pipeline?.[0]?.$match?.isPublic === true;
}
/**
* Check if a raw operation is public (read-only with isPublic filter)
*/
isPublicRawOperation(operation, query) {
const readOperations = ['find', 'findOne', 'count', 'countDocuments', 'distinct'];
return readOperations.includes(operation) && query?.isPublic === true;
}
/**
* Query data from a collection with type safety
* @param collection - Collection name
* @param filter - MongoDB filter object (optional)
* @param options - Query options (sort, limit, skip)
*/
async query(collection, filter, options) {
try {
// In edge environment, API key is used automatically
// Otherwise, get user token
const token = this.apiClient.isEdgeEnvironment()
? null
: await this.auth.getValidToken();
const result = await this.apiClient.request(`/api/project/${this.config.projectId}/data/query`, {
method: 'POST',
body: {
collection,
filter: filter || {},
sort: options?.sort || {},
limit: options?.limit || 100,
skip: options?.skip || 0,
},
operation: `query:${collection}`
}, token);
return {
data: result.data || [],
total: result.total || 0
};
}
catch (error) {
throw error;
}
}
/**
* Insert data into a collection with type safety
*/
async insert(collection, data, options = {}) {
try {
const token = this.apiClient.isEdgeEnvironment()
? null
: await this.auth.getValidToken();
const result = await this.apiClient.request(`/api/project/${this.config.projectId}/data/insert`, {
method: 'POST',
body: {
collection,
data,
upsert: options.upsert || false,
},
operation: `insert:${collection}`
}, token);
return result.data;
}
catch (error) {
throw error;
}
}
/**
* Update existing data in a collection (fails if not found)
*/
async update(collection, filter, data) {
try {
const token = this.apiClient.isEdgeEnvironment()
? null
: await this.auth.getValidToken();
const result = await this.apiClient.request(`/api/project/${this.config.projectId}/data/raw`, {
method: 'POST',
body: {
collection,
operation: 'findOneAndUpdate',
query: filter,
update: { $set: data },
options: { returnDocument: 'after' }
},
operation: `update:${collection}`
}, token);
if (!result.result) {
throw new Error('Document not found for update');
}
return result.result;
}
catch (error) {
throw error;
}
}
/**
* Delete data from a collection
*/
async delete(collection, filter) {
try {
const token = this.apiClient.isEdgeEnvironment()
? null
: await this.auth.getValidToken();
const result = await this.apiClient.request(`/api/project/${this.config.projectId}/data/raw`, {
method: 'POST',
body: {
collection,
operation: 'deleteMany',
query: filter,
},
operation: `delete:${collection}`
}, token);
return { deletedCount: result.result.deletedCount || 0 };
}
catch (error) {
throw error;
}
}
/**
* Run aggregation query with type safety
*/
async aggregate(collection, pipeline) {
try {
const token = this.apiClient.isEdgeEnvironment()
? null
: await this.auth.getValidToken();
const result = await this.apiClient.request(`/api/project/${this.config.projectId}/data/aggregate`, {
method: 'POST',
body: {
collection,
pipeline,
allowDiskUse: false
},
operation: `aggregate:${collection}`
}, token);
return result.data;
}
catch (error) {
throw error;
}
}
/**
* Run raw MongoDB operations with type safety and validation
*/
async raw(collection, operation, options = {}) {
// Validate allowed operations for security
const allowedOperations = [
'find', 'findOne', 'count', 'countDocuments', 'distinct',
'aggregate', 'findOneAndUpdate', 'updateOne', 'updateMany',
'deleteOne', 'deleteMany', 'insertOne', 'insertMany'
];
if (!allowedOperations.includes(operation)) {
throw new Error(`Operation '${operation}' is not allowed. Allowed operations: ${allowedOperations.join(', ')}`);
}
try {
const token = this.apiClient.isEdgeEnvironment()
? null
: await this.auth.getValidToken();
const result = await this.apiClient.request(`/api/project/${this.config.projectId}/data/raw`, {
method: 'POST',
body: {
collection,
operation,
...options
},
operation: `raw:${operation}:${collection}`
}, token);
return result.result;
}
catch (error) {
throw error;
}
}
}
exports.MagicallyData = MagicallyData;