UNPKG

@lighttable/lighttable

Version:

Universal SDK to access LightTable (compatible with Node.js, React, Next.js, Vite).

965 lines (725 loc) 24.4 kB
const axios = require('axios'); class LightTable { constructor({ baseUrl, store, token = null,system = null }) { this.baseUrl = (baseUrl || 'https://lb01.genielabel.com/sdk/v1/lighttable').replace(/\/$/, ''); if (!store) throw new Error("`store` est requis"); this.store = store; this.system = system; // Vérifie si un token existe déjà dans localStorage if (!token && typeof window !== 'undefined' && window.localStorage) { token = localStorage.getItem('lighttable_token_' + store); } this.token = token; } setToken(token) { this.token = token; } _headers() { return { 'Content-Type': 'application/json', 'x-store-id': this.store, ...(this.token ? { Authorization: `Bearer ${this.token}` } : {}) }; } async authOtp({ type, phone, email }) { if (!type || (type === 'phone' && !phone) || (type === 'email' && !email)) { throw new Error("`type` et `phone` ou `email` sont requis"); } if (this.system) { const res = await this.system.post(`${this.baseUrl}/auth-otp`, { type, phone, email }, { headers: this._headers() }); return res.data; } const res = await axios.post(`${this.baseUrl}/auth-otp`, { type, phone, email }, { headers: this._headers() }); return res.data; } async getSignedUrl(key) { if (this.system) { const res = await this.system.post(`${this.baseUrl}/signed-url`, { key}, { headers: this._headers() }); return res.data; } const res = await axios.post(`${this.baseUrl}/signed-url`, { key}, { headers: this._headers() }); return res.data.url; } async verifyOtp({ code, phone, email }) { if (!code || (!phone && !email)) { throw new Error("`code` et `phone` ou `email` sont requis"); } if (this.system) { const res = await this.system.post(`${this.baseUrl}/auth-otp/verify`, { code, phone, email }, { // le store est requis ici aussi params: {}, headers: { ...this._headers(), 'x-store-id': this.store } }); if (res.data?.token) { this.token = res.data.token; // Environnement navigateur : stocker dans localStorage if (typeof window !== 'undefined' && window.localStorage) { localStorage.setItem('lighttable_token', this.token); } } return res.data; } const res = await axios.post(`${this.baseUrl}/auth-otp/verify`, { code, phone, email }, { // le store est requis ici aussi params: {}, headers: { ...this._headers(), 'x-store-id': this.store } }); if (res.data?.token) { this.token = res.data.token; // Environnement navigateur : stocker dans localStorage if (typeof window !== 'undefined' && window.localStorage) { localStorage.setItem('lighttable_token', this.token); } } return res.data; } async getMe() { if (this.system) { const res = await this.system.get(`${this.baseUrl}/me`, { headers: { ...this._headers(), 'x-store-id': this.store } }); return res.data; } const res = await axios.get(`${this.baseUrl}/me`, { headers: { ...this._headers(), 'x-store-id': this.store } }); return res.data; } async updateMe(payload) { if (this.system) { const res = await this.system.put(`${this.baseUrl}/me`, payload, { headers: { ...this._headers(), 'x-store-id': this.store } }); return res.data; } const res = await axios.put(`${this.baseUrl}/me`, payload, { headers: { ...this._headers(), 'x-store-id': this.store } }); return res.data; } async runFuction(payload) { if (this.system) { const res = await this.system.post(`${this.baseUrl}/function`, payload, { headers: { ...this._headers(), 'x-store-id': this.store } }); return res.data; } const res = await axios.post(`${this.baseUrl}/function`, payload, { headers: { ...this._headers(), 'x-store-id': this.store } }); return res.data; } async checkout(payload) { if (this.system) { const res = await this.system.post(`${this.baseUrl}/checkout`, payload, { headers: { ...this._headers(), 'x-store-id': this.store } }); return res.data; } const res = await axios.post(`${this.baseUrl}/checkout`, payload, { headers: { ...this._headers(), 'x-store-id': this.store } }); return res.data; } collection(name) { if (!name) throw new Error("Nom de collection ID requis"); /** * QueryBuilder chaînable pour toutes les options Mongoose : * .filter(obj) // filtre (query) * .sort(obj) // tri * .limit(n) // limite * .skip(n) // décalage * .select(str|obj) // projection * .populate(str|obj)// jointure * .lean() // lean * .exec() // exécute la requête * * Exemple : * collection('maCollection') * .find() * .filter({ statut: 'actif' }) * .sort({ createdAt: -1 }) * .limit(10) * .skip(20) * .select('nom age') * .populate('profile') * .lean() * .exec() */ class QueryBuilder { constructor(operation, initialArgs = []) { this.operation = operation; this.args = initialArgs.length ? initialArgs : [{}]; } sort(sortObj) { this.args[0].sort = sortObj; return this; } limit(limitVal) { this.args[0].limit = limitVal; return this; } skip(skipVal) { this.args[0].skip = skipVal; return this; } filter(filterObj) { this.args[0].filter = filterObj; return this; } select(selectVal) { this.args[0].select = selectVal; return this; } populate(populateVal) { this.args[0].populate = populateVal; return this; } lean() { this.args[0].lean = true; return this; } async exec() { return await call(this.operation, this.args); } then(res, rej) { return this.exec().then(res, rej); } catch(rej) { return this.exec().catch(rej); } } const call = async (operation, args = []) => { let finalArgs = args; let params; if (["find", "findOne" ].includes(operation) && args.length === 1 && typeof args[0] === "object" && args[0] !== null) { let { filter = {}, limit, skip, page, sort, ...rest } = args[0]; if (page !== undefined && limit !== undefined) { skip = (page - 1) * limit; } params = rest; let query = filter; let options = {}; if (limit !== undefined) options.limit = limit * 1; if (skip !== undefined) options.skip = skip; if (sort !== undefined) options.sort = sort; finalArgs = [query, options]; } if (this.system) { const res = await this.system.post(`${this.baseUrl}`, { operation, args: finalArgs, params, collection: name }, { headers: { ...this._headers(), 'x-store-id': this.store } }); return res.data.data; } const res = await axios.post(`${this.baseUrl}`, { operation, args: finalArgs, params, collection: name }, { headers: { ...this._headers(), 'x-store-id': this.store } }); return res.data.data; }; const operations = [ 'find', 'findOne', 'count', 'countDocuments', 'findOneAndUpdate', 'findById', 'findByIdAndUpdate', 'deleteOne', 'deleteMany', 'updateOne', 'updateMany', 'save', 'insertMany', 'aggregate', 'distinct', 'create', ]; const model = {}; for (const op of operations) { if (["find", "findOne"].includes(op)) { model[op] = (args = {}) => new QueryBuilder(op, [args]); } else { model[op] = (...args) => call(op, args); } } return model; } products(name) { class QueryBuilder { constructor(operation, initialArgs = []) { this.operation = operation; this.args = initialArgs.length ? initialArgs : [{}]; } sort(sortObj) { this.args[0].sort = sortObj; return this; } limit(limitVal) { this.args[0].limit = limitVal; return this; } skip(skipVal) { this.args[0].skip = skipVal; return this; } filter(filterObj) { this.args[0].filter = filterObj; return this; } select(selectVal) { this.args[0].select = selectVal; return this; } mainImageSize(val) { this.args[0].mainImageSize = val; return this; } thumbnailSize(val) { this.args[0].thumbnailSize = val; return this; } lean() { this.args[0].lean = true; return this; } async exec() { return await call(this.operation, this.args); } then(res, rej) { return this.exec().then(res, rej); } catch(rej) { return this.exec().catch(rej); } } const call = async (operation, args = []) => { let finalArgs = args; let params; if (["find", "findOne" ].includes(operation) && args.length === 1 && typeof args[0] === "object" && args[0] !== null) { let { filter = {}, limit, skip, page, sort, ...rest } = args[0]; if (page !== undefined && limit !== undefined) { skip = (page - 1) * limit; } params = rest; let query = filter; let options = { }; if (limit !== undefined) options.limit = limit * 1; if (skip !== undefined) options.skip = skip; if (sort !== undefined) options.sort = sort; finalArgs = [query, options]; } delete params.thumbnailSize delete params.mainImageSize if (this.system) { const res = await this.system.post(`${this.baseUrl}`, { operation, args: finalArgs, params, products: true, }, { headers: { ...this._headers(), 'x-store-id': this.store } }); return res.data.data; } const res = await axios.post(`${this.baseUrl}`, { operation, args: finalArgs, params, products: true, }, { headers: { ...this._headers(), 'x-store-id': this.store } }); return res.data.data; }; const operations = [ 'find', 'findOne', 'count', 'countDocuments' ]; const model = {}; for (const op of operations) { if (["find", "findOne" ].includes(op)) { model[op] = (args = {}) => new QueryBuilder(op, [args]); } else { model[op] = (...args) => call(op, args); } } return model; } services(name) { /** * QueryBuilder chaînable pour toutes les options Mongoose : * .filter(obj) // filtre (query) * .sort(obj) // tri * .limit(n) // limite * .skip(n) // décalage * .select(str|obj) // projection * .populate(str|obj)// jointure * .lean() // lean * .exec() // exécute la requête * * Exemple : * collection('maCollection') * .find() * .filter({ statut: 'actif' }) * .sort({ createdAt: -1 }) * .limit(10) * .skip(20) * .select('nom age') * .populate('profile') * .lean() * .exec() */ class QueryBuilder { constructor(operation, initialArgs = []) { this.operation = operation; this.args = initialArgs.length ? initialArgs : [{}]; } sort(sortObj) { this.args[0].sort = sortObj; return this; } limit(limitVal) { this.args[0].limit = limitVal; return this; } skip(skipVal) { this.args[0].skip = skipVal; return this; } filter(filterObj) { this.args[0].filter = filterObj; return this; } select(selectVal) { this.args[0].select = selectVal; return this; } lean() { this.args[0].lean = true; return this; } async exec() { return await call(this.operation, this.args); } then(res, rej) { return this.exec().then(res, rej); } catch(rej) { return this.exec().catch(rej); } } const call = async (operation, args = []) => { let finalArgs = args; let params; if (["find", "findOne" ].includes(operation) && args.length === 1 && typeof args[0] === "object" && args[0] !== null) { let { filter = {}, limit, skip, page, sort, ...rest } = args[0]; if (page !== undefined && limit !== undefined) { skip = (page - 1) * limit; } params = rest; let query = filter; let options = { }; if (limit !== undefined) options.limit = limit * 1; if (skip !== undefined) options.skip = skip; if (sort !== undefined) options.sort = sort; finalArgs = [query, options]; } if (this.system) { const res = await this.system.post(`${this.baseUrl}`, { operation, args: finalArgs, params, services: true }, { headers: { ...this._headers(), 'x-store-id': this.store } }); return res.data.data; } const res = await axios.post(`${this.baseUrl}`, { operation, args: finalArgs, params, services: true }, { headers: { ...this._headers(), 'x-store-id': this.store } }); return res.data.data; }; const operations = [ 'find', 'findOne', 'count', ]; const model = {}; for (const op of operations) { if (["find", "findOne" ].includes(op)) { model[op] = (args = {}) => new QueryBuilder(op, [args]); } else { model[op] = (...args) => call(op, args); } } return model; } orders(name) { /** * QueryBuilder chaînable pour toutes les options Mongoose : * .filter(obj) // filtre (query) * .sort(obj) // tri * .limit(n) // limite * .skip(n) // décalage * .select(str|obj) // projection * .populate(str|obj)// jointure * .lean() // lean * .exec() // exécute la requête * * Exemple : * collection('maCollection') * .find() * .filter({ statut: 'actif' }) * .sort({ createdAt: -1 }) * .limit(10) * .skip(20) * .select('nom age') * .populate('profile') * .lean() * .exec() */ class QueryBuilder { constructor(operation, initialArgs = []) { this.operation = operation; this.args = initialArgs.length ? initialArgs : [{}]; } sort(sortObj) { this.args[0].sort = sortObj; return this; } limit(limitVal) { this.args[0].limit = limitVal; return this; } skip(skipVal) { this.args[0].skip = skipVal; return this; } filter(filterObj) { this.args[0].filter = filterObj; return this; } select(selectVal) { this.args[0].select = selectVal; return this; } lean() { this.args[0].lean = true; return this; } async exec() { return await call(this.operation, this.args); } then(res, rej) { return this.exec().then(res, rej); } catch(rej) { return this.exec().catch(rej); } } const call = async (operation, args = []) => { let finalArgs = args; let params; if (["find", "findOne" ].includes(operation) && args.length === 1 && typeof args[0] === "object" && args[0] !== null) { let { filter = {}, limit, skip, page, sort, ...rest } = args[0]; if (page !== undefined && limit !== undefined) { skip = (page - 1) * limit; } params = rest; let query = filter; let options = { }; if (limit !== undefined) options.limit = limit * 1; if (skip !== undefined) options.skip = skip; if (sort !== undefined) options.sort = sort; finalArgs = [query, options]; } if (this.system) { const res = await this.system.post(`${this.baseUrl}`, { operation, args: finalArgs, params, orders: true }, { headers: { ...this._headers(), 'x-store-id': this.store } }); return res.data.data; } const res = await axios.post(`${this.baseUrl}`, { operation, args: finalArgs, params, orders: true }, { headers: { ...this._headers(), 'x-store-id': this.store } }); return res.data.data; }; const operations = [ 'find', 'findOne', 'count', 'countDocuments' ]; const model = {}; for (const op of operations) { if (["find", "findOne"].includes(op)) { model[op] = (args = {}) => new QueryBuilder(op, [args]); } else { model[op] = (...args) => call(op, args); } } return model; } invoices(name) { //if (!name) throw new Error("Nom de collection requis"); /** * QueryBuilder chaînable pour toutes les options Mongoose : * .filter(obj) // filtre (query) * .sort(obj) // tri * .limit(n) // limite * .skip(n) // décalage * .select(str|obj) // projection * .populate(str|obj)// jointure * .lean() // lean * .exec() // exécute la requête * * Exemple : * collection('maCollection') * .find() * .filter({ statut: 'actif' }) * .sort({ createdAt: -1 }) * .limit(10) * .skip(20) * .select('nom age') * .populate('profile') * .lean() * .exec() */ class QueryBuilder { constructor(operation, initialArgs = []) { this.operation = operation; this.args = initialArgs.length ? initialArgs : [{}]; } sort(sortObj) { this.args[0].sort = sortObj; return this; } limit(limitVal) { this.args[0].limit = limitVal; return this; } skip(skipVal) { this.args[0].skip = skipVal; return this; } filter(filterObj) { this.args[0].filter = filterObj; return this; } select(selectVal) { this.args[0].select = selectVal; return this; } lean() { this.args[0].lean = true; return this; } async exec() { return await call(this.operation, this.args); } then(res, rej) { return this.exec().then(res, rej); } catch(rej) { return this.exec().catch(rej); } } const call = async (operation, args = []) => { let finalArgs = args; let params; if (["find", "findOne" ].includes(operation) && args.length === 1 && typeof args[0] === "object" && args[0] !== null) { let { filter = {}, limit, skip, page, sort, ...rest } = args[0]; if (page !== undefined && limit !== undefined) { skip = (page - 1) * limit; } params = rest; let query = filter; let options = { }; if (limit !== undefined) options.limit = limit * 1; if (skip !== undefined) options.skip = skip; if (sort !== undefined) options.sort = sort; finalArgs = [query, options]; } if (this.system) { const res = await this.system.post(`${this.baseUrl}`, { operation, args: finalArgs, params, invoices: true }, { headers: { ...this._headers(), 'x-store-id': this.store } }); return res.data.data; } const res = await axios.post(`${this.baseUrl}`, { operation, args: finalArgs, params, invoices: true }, { headers: { ...this._headers(), 'x-store-id': this.store } }); return res.data.data; }; const operations = [ 'find', 'findOne', 'count', 'countDocuments' ]; const model = {}; for (const op of operations) { if (["find", "findOne" ].includes(op)) { model[op] = (args = {}) => new QueryBuilder(op, [args]); } else { model[op] = (...args) => call(op, args); } } return model; } categories(name) { //if (!name) throw new Error("Nom de collection requis"); /** * QueryBuilder chaînable pour toutes les options Mongoose : * .filter(obj) // filtre (query) * .sort(obj) // tri * .limit(n) // limite * .skip(n) // décalage * .select(str|obj) // projection * .populate(str|obj)// jointure * .lean() // lean * .exec() // exécute la requête * * Exemple : * collection('maCollection') * .find() * .filter({ statut: 'actif' }) * .sort({ createdAt: -1 }) * .limit(10) * .skip(20) * .select('nom age') * .populate('profile') * .lean() * .exec() */ class QueryBuilder { constructor(operation, initialArgs = []) { this.operation = operation; this.args = initialArgs.length ? initialArgs : [{}]; } sort(sortObj) { this.args[0].sort = sortObj; return this; } limit(limitVal) { this.args[0].limit = limitVal; return this; } skip(skipVal) { this.args[0].skip = skipVal; return this; } filter(filterObj) { this.args[0].filter = filterObj; return this; } select(selectVal) { this.args[0].select = selectVal; return this; } mainImageSize(val) { this.args[0].mainImageSize = val; return this; } thumbnailSize(val) { this.args[0].thumbnailSize = val; return this; } lean() { this.args[0].lean = true; return this; } async exec() { return await call(this.operation, this.args); } then(res, rej) { return this.exec().then(res, rej); } catch(rej) { return this.exec().catch(rej); } } const call = async (operation, args = []) => { let finalArgs = args; let params; if (["find", "findOne" ].includes(operation) && args.length === 1 && typeof args[0] === "object" && args[0] !== null) { let { filter = {}, limit, skip, page, sort, ...rest } = args[0]; if (page !== undefined && limit !== undefined) { skip = (page - 1) * limit; } params = rest; let query = filter; let options = { }; if (limit !== undefined) options.limit = limit * 1; if (skip !== undefined) options.skip = skip; if (sort !== undefined) options.sort = sort; finalArgs = [query, options]; } delete params.thumbnailSize delete params.mainImageSize if (this.system) { const res = await this.system.post(`${this.baseUrl}`, { operation, args: finalArgs, params, categories: true, }, { headers: { ...this._headers(), 'x-store-id': this.store } }); return res.data.data; } const res = await axios.post(`${this.baseUrl}`, { operation, args: finalArgs, params, categories: true, }, { headers: { ...this._headers(), 'x-store-id': this.store } }); return res.data.data; }; const operations = [ 'find', 'findOne', 'count', 'countDocuments' ]; const model = {}; for (const op of operations) { if (["find", "findOne" ].includes(op)) { model[op] = (args = {}) => new QueryBuilder(op, [args]); } else { model[op] = (...args) => call(op, args); } } return model; } } module.exports = LightTable;