UNPKG

@nextplus/js-sdk

Version:

A TypeScript SDK for interacting with the NextPlus API, automatically generated from OpenAPI specifications.

224 lines (222 loc) 7.79 kB
import { sdk_exports } from "./chunk-TU3VOZVD.js"; import { UserModelService } from "./chunk-VAV5HKXV.js"; import { __publicField, createClient } from "./chunk-FXXZNC42.js"; // src/index.ts import debug from "debug"; var log = debug("nextplus:sdk"); var accessToken = { token: null, created: null, ttl: 0 }; var setAccessToken = (token, created = /* @__PURE__ */ new Date(), ttl = 1209600) => { accessToken.token = token; accessToken.created = created; accessToken.ttl = ttl; }; var getAccessToken = () => { return accessToken; }; var isTokenValid = () => { if (!accessToken.token || !accessToken.created) { return false; } const now = /* @__PURE__ */ new Date(); const tokenAge = now.getTime() - accessToken.created.getTime(); const tokenTtlMs = accessToken.ttl * 1e3; return tokenAge < tokenTtlMs; }; var NextPlusSDK = class { constructor(options) { __publicField(this, "client"); __publicField(this, "credentials"); __publicField(this, "returnType", "data"); if (!options.email && !options.username) { throw new Error("Either email or username must be provided"); } if (options.email && options.username) { throw new Error("Provide either email or username, not both"); } this.credentials = { email: options.email, username: options.username, password: options.password }; this.returnType = options.returnType || "data"; if (options.baseURL.endsWith("/")) { options.baseURL = options.baseURL.slice(0, -1); } if (!options.baseURL.endsWith("/api")) { options.baseURL = options.baseURL + "/api"; } this.client = createClient({ baseUrl: options.baseURL }); this.client.interceptors.request.use(this.authRequestInterceptor.bind(this)); this.createServiceProxies(); } // Wrap plain developer inputs into the right container (body/query) // and stringify complex query params when required by LoopBack (filter/where) normalizeOptions(methodName, rawOptions) { const options = rawOptions && typeof rawOptions === "object" ? { ...rawOptions } : {}; const method = methodName.toString().toLowerCase(); const isFind = method.includes("find") && !method.includes("count"); const isCount = method.includes("count"); const shouldUseBody = /(create|update|replace|patch|login|upsert)/i.test(methodName.toString()); const topLevelKeys = ["filter", "where", "fields", "order", "limit", "offset", "include"]; const hasTopLevelFilterBits = topLevelKeys.some((k) => Object.prototype.hasOwnProperty.call(options, k)); if (isFind) { options.query = options.query || {}; if (options.filter && typeof options.filter === "object") { options.query.filter = JSON.stringify(options.filter); delete options.filter; } else if (hasTopLevelFilterBits) { const filterObject = {}; if (options.where !== void 0) filterObject.where = options.where; if (options.fields !== void 0) filterObject.fields = options.fields; if (options.order !== void 0) filterObject.order = options.order; if (options.limit !== void 0) filterObject.limit = options.limit; if (options.offset !== void 0) filterObject.offset = options.offset; if (options.include !== void 0) filterObject.include = options.include; if (Object.keys(filterObject).length > 0) { options.query.filter = typeof filterObject === "string" ? filterObject : JSON.stringify(filterObject); } topLevelKeys.forEach((k) => delete options[k]); } } else if (isCount) { options.query = options.query || {}; if (options.where !== void 0) { const whereVal = options.where; options.query.where = typeof whereVal === "string" ? whereVal : JSON.stringify(whereVal); delete options.where; } } else if (shouldUseBody) { if (options.body === void 0) { const bodyCandidate = { ...options }; delete bodyCandidate.client; delete bodyCandidate.query; delete bodyCandidate.path; if (Object.keys(bodyCandidate).length > 0) { options.body = bodyCandidate; Object.keys(options).forEach((k) => { if (!["body", "client", "query", "path"].includes(k)) delete options[k]; }); } } } if (options.query && typeof options.query === "object") { Object.keys(options.query).forEach((key) => { const val = options.query[key]; if (val && (Array.isArray(val) || typeof val === "object")) { options.query[key] = JSON.stringify(val); } }); } return options; } async authRequestInterceptor(request, _options) { if (request.url.includes("/UserModels/login")) { return request; } await this.ensureValidToken(); const token = getAccessToken(); if (token.token) { request.headers.set("Authorization", token.token); } return request; } async ensureValidToken() { if (!isTokenValid()) { log("Token expired or missing, refreshing..."); await this.login(); } } async login() { try { const loginBody = { password: this.credentials.password, forceLogin: true }; if (this.credentials.email) { loginBody.email = this.credentials.email; } else if (this.credentials.username) { loginBody.username = this.credentials.username; } const response = await UserModelService.login({ client: this.client, body: loginBody }); if (response.data) { const token = response.data.id; const ttl = response.data.ttl || 1209600; if (token) { setAccessToken(token, /* @__PURE__ */ new Date(), ttl); log("Login successful, access token set"); return true; } } throw new Error("Login failed - no token received"); } catch (error) { console.error("Login failed:", error); throw error; } } createServiceProxies() { const serviceNames = Object.keys(sdk_exports).filter( (key) => key.endsWith("Service") && typeof sdk_exports[key] === "function" ); serviceNames.forEach((serviceName) => { const ServiceClass = sdk_exports[serviceName]; this[serviceName] = this.createServiceProxy(ServiceClass); }); } createServiceProxy(ServiceClass) { const self = this; return new Proxy(ServiceClass, { get(target, prop) { if (typeof target[prop] === "function") { return async function(...args) { if (!args[0]) args[0] = {}; args[0] = self.normalizeOptions(String(prop), args[0]); if (!args[0].client) args[0].client = self.client; const result = await target[prop].apply(target, args); if (self.returnType === "data" && result && typeof result === "object" && "data" in result) { return result.data; } if (self.returnType === "data" && result && typeof result === "object" && "error" in result) { const error = new Error(result.error.error.message || result.error.error.code || "Unknown error"); if (result.error.error.details) { error.details = result.error.error.details; } throw error; } return result; }; } return target[prop]; } }); } // Manual login method (optional, for explicit control) async manualLogin() { return this.login(); } }; var configure = (options) => { return new NextPlusSDK(options); }; var createSDK = (options) => { return new NextPlusSDK(options); }; export { NextPlusSDK, configure, createSDK };