quickbase-js 2.0.0 → 2.1.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 +165 -4
- package/dist/auth/index.d.ts +1 -0
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +5 -0
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/ticket.d.ts +71 -0
- package/dist/auth/ticket.d.ts.map +1 -0
- package/dist/auth/ticket.js +160 -0
- package/dist/auth/ticket.js.map +1 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +9 -0
- package/dist/core/config.js.map +1 -1
- package/dist/core/index.d.ts +2 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/types.d.ts +17 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/quickbase.esm.js +6 -2
- package/dist/quickbase.esm.js.map +4 -4
- package/dist/quickbase.min.js +6 -2
- package/dist/quickbase.min.js.map +4 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
* ```
|
|
21
21
|
*/
|
|
22
22
|
export { QuickbaseError, RateLimitError, AuthenticationError, AuthorizationError, NotFoundError, ValidationError, TimeoutError, ServerError, } from './core/index.js';
|
|
23
|
-
export { UserTokenStrategy, TempTokenStrategy, SsoTokenStrategy,
|
|
23
|
+
export { UserTokenStrategy, TempTokenStrategy, SsoTokenStrategy, TicketStrategy, // XML-API-TICKET: Remove if XML API discontinued
|
|
24
|
+
createAuthStrategy, } from './auth/index.js';
|
|
24
25
|
export { SlidingWindowThrottle, NoOpThrottle } from './client/index.js';
|
|
25
26
|
export * from './generated/types.js';
|
|
26
27
|
export { createApiMethods } from './generated/client.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAkBH,OAAO,EACL,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,kBAAkB,EAClB,aAAa,EACb,eAAe,EACf,YAAY,EACZ,WAAW,GACZ,MAAM,iBAAiB,CAAC;AAIzB,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EAAE,iDAAiD;AACjE,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AAIzB,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAIxE,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAIzD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAE5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAmBzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,MAAM,UAAU,YAAY,CAAC,MAAuB;IAClD,MAAM,cAAc,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,YAAY,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IAElD,MAAM,WAAW,GAAG;QAClB,KAAK,EAAE,cAAc,CAAC,KAAK;QAC3B,OAAO,EAAE,cAAc,CAAC,OAAO;QAC/B,QAAQ,EAAE,cAAc,CAAC,QAAQ;QACjC,MAAM;KACP,CAAC;IAEF,MAAM,IAAI,GAAG,kBAAkB,CAAC,cAAc,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IAClE,MAAM,QAAQ,GAAG,cAAc,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC;IAElE,MAAM,QAAQ,GAAG,qBAAqB,CAAC;QACrC,MAAM,EAAE,cAAc;QACtB,IAAI;QACJ,QAAQ;QACR,MAAM;KACP,CAAC,CAAC;IAEH,2BAA2B;IAC3B,MAAM,UAAU,GAAG,gBAAgB,CAAC,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC,YAAY,CAAC,CAAC;IAEnF,OAAO;QACL,GAAG,UAAU;QACb,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,SAAS,EAAE,GAAG,EAAE,CAAC,cAAc;KAChC,CAAC;AACJ,CAAC;AAED,iBAAiB;AACjB,eAAe,YAAY,CAAC"}
|
package/dist/quickbase.esm.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* QuickBase JS SDK v2.
|
|
2
|
+
* QuickBase JS SDK v2.1.0
|
|
3
3
|
* https://github.com/DrewBradfordXYZ/quickbase-js#readme
|
|
4
4
|
* @license MIT
|
|
5
5
|
*/
|
|
6
|
-
var te=Object.defineProperty;var re=(t,r,e)=>r in t?te(t,r,{enumerable:!0,configurable:!0,writable:!0,value:e}):t[r]=e;var i=(t,r,e)=>re(t,typeof r!="symbol"?r+"":r,e);var l={baseUrl:"https://api.quickbase.com/v1",timeout:3e4,debug:!1,retry:{maxAttempts:3,initialDelayMs:1e3,maxDelayMs:3e4,multiplier:2},proactiveThrottle:{enabled:!1,requestsPer10Seconds:100},tempTokenLifespanMs:29e4,autoPaginate:!1,convertDates:!0};var h=class t extends Error{constructor(e,o,n){super(e,{cause:n?.cause});i(this,"statusCode");i(this,"description");i(this,"rayId");this.name="QuickbaseError",this.statusCode=o,this.description=n?.description,this.rayId=n?.rayId,Error.captureStackTrace&&Error.captureStackTrace(this,t)}toJSON(){return{name:this.name,message:this.message,statusCode:this.statusCode,description:this.description,rayId:this.rayId}}},y=class extends h{constructor(e,o){super(o||`Rate limited. Retry after ${e.retryAfter??"unknown"} seconds`,429,{rayId:e.qbApiRay||e.cfRay});i(this,"retryAfter");i(this,"rateLimitInfo");this.name="RateLimitError",this.retryAfter=e.retryAfter,this.rateLimitInfo=e}toJSON(){return{...super.toJSON(),retryAfter:this.retryAfter,rateLimitInfo:this.rateLimitInfo}}},R=class extends h{constructor(r,e){super(r,401,e),this.name="AuthenticationError"}},I=class extends h{constructor(r,e){super(r,403,e),this.name="AuthorizationError"}},C=class extends h{constructor(r,e){super(r,404,e),this.name="NotFoundError"}},D=class extends h{constructor(e,o){super(e,400,o);i(this,"errors");this.name="ValidationError",this.errors=o?.errors}toJSON(){return{...super.toJSON(),errors:this.errors}}},b=class extends h{constructor(e,o){super(`Request timed out after ${e}ms`,0,o);i(this,"timeoutMs");this.name="TimeoutError",this.timeoutMs=e}toJSON(){return{...super.toJSON(),timeoutMs:this.timeoutMs}}},x=class extends h{constructor(r,e,o){super(e,r,o),this.name="ServerError"}};async function $(t,r){let e=t.headers.get("qb-api-ray")||t.headers.get("cf-ray")||void 0,o=null;try{o=await t.json()}catch{}let n=o?.message||t.statusText||"Unknown error",a=o?.description;switch(t.status){case 400:return new D(n,{description:a,rayId:e,errors:o?.errors});case 401:return new R(n,{rayId:e});case 403:return new I(n,{rayId:e});case 404:return new C(n,{rayId:e});case 429:{let s=t.headers.get("Retry-After"),u={timestamp:new Date,requestUrl:r,httpStatus:429,retryAfter:s?parseInt(s,10):void 0,cfRay:t.headers.get("cf-ray")||void 0,tid:t.headers.get("tid")||void 0,qbApiRay:t.headers.get("qb-api-ray")||void 0,attempt:1};return new y(u,n)}default:return t.status>=500?new x(t.status,n,{description:a,rayId:e}):new h(n,t.status,{description:a,rayId:e})}}function q(t){return t instanceof y||t instanceof x||t instanceof b}var F=class{constructor(r=!1,e="quickbase-js"){i(this,"enabled");i(this,"prefix");this.enabled=r,this.prefix=e}formatMessage(r,e){return`[${new Date().toISOString()}] [${this.prefix}] [${r}] ${e}`}debug(r,e){this.enabled&&(e!==void 0?console.log(this.formatMessage("DEBUG",r),e):console.log(this.formatMessage("DEBUG",r)))}info(r,e){this.enabled&&(e!==void 0?console.info(this.formatMessage("INFO",r),e):console.info(this.formatMessage("INFO",r)))}warn(r,e){e!==void 0?console.warn(this.formatMessage("WARN",r),e):console.warn(this.formatMessage("WARN",r))}error(r,e){e!==void 0?console.error(this.formatMessage("ERROR",r),e):console.error(this.formatMessage("ERROR",r))}rateLimit(r){this.enabled&&this.debug(`Rate limited (attempt ${r.attempt}): ${r.url} - Status ${r.status}, Retry-After: ${r.retryAfter??"not specified"}s`+(r.rayId?`, Ray: ${r.rayId}`:""))}timing(r,e,o){this.enabled&&this.debug(`${r} ${e} completed in ${o}ms`)}retry(r,e,o,n){this.enabled&&this.debug(`Retry ${r}/${e} in ${o}ms: ${n}`)}token(r,e){if(this.enabled){let o=e?` for dbid: ${e}`:"";this.debug(`Token ${r}${o}`)}}};function O(t){return new F(t)}function j(t){oe(t);let r={maxAttempts:t.rateLimit?.retry?.maxAttempts??l.retry.maxAttempts,initialDelayMs:t.rateLimit?.retry?.initialDelayMs??l.retry.initialDelayMs,maxDelayMs:t.rateLimit?.retry?.maxDelayMs??l.retry.maxDelayMs,multiplier:t.rateLimit?.retry?.multiplier??l.retry.multiplier},e={enabled:t.rateLimit?.proactiveThrottle?.enabled??l.proactiveThrottle.enabled,requestsPer10Seconds:t.rateLimit?.proactiveThrottle?.requestsPer10Seconds??l.proactiveThrottle.requestsPer10Seconds};return{realm:t.realm,baseUrl:t.baseUrl??l.baseUrl,timeout:t.timeout??l.timeout,debug:t.debug??l.debug,fetchApi:t.fetchApi??globalThis.fetch.bind(globalThis),auth:t.auth,retry:r,proactiveThrottle:e,onRateLimit:t.rateLimit?.onRateLimit,autoPaginate:t.autoPaginate??l.autoPaginate,convertDates:t.convertDates??l.convertDates}}function oe(t){if(!t.realm)throw new Error("QuickBase realm is required");if(typeof t.realm!="string")throw new Error("QuickBase realm must be a string");if(t.realm.includes("."))throw new Error('Realm should be just the subdomain (e.g., "mycompany" not "mycompany.quickbase.com")');if(!t.auth)throw new Error("Authentication configuration is required");if(ne(t.auth),t.timeout!==void 0&&(typeof t.timeout!="number"||t.timeout<=0))throw new Error("Timeout must be a positive number");t.rateLimit?.retry&&se(t.rateLimit.retry),t.rateLimit?.proactiveThrottle&&ae(t.rateLimit.proactiveThrottle)}function ne(t){switch(t.type){case"user-token":if(!t.userToken)throw new Error("User token is required for user-token auth");break;case"temp-token":break;case"sso":if(!t.samlToken)throw new Error("SAML token is required for SSO auth");break;default:throw new Error(`Unknown auth type: ${t.type}`)}}function se(t){if(t.maxAttempts!==void 0&&(typeof t.maxAttempts!="number"||t.maxAttempts<0))throw new Error("maxAttempts must be a non-negative number");if(t.initialDelayMs!==void 0&&(typeof t.initialDelayMs!="number"||t.initialDelayMs<0))throw new Error("initialDelayMs must be a non-negative number");if(t.maxDelayMs!==void 0&&(typeof t.maxDelayMs!="number"||t.maxDelayMs<0))throw new Error("maxDelayMs must be a non-negative number");if(t.multiplier!==void 0&&(typeof t.multiplier!="number"||t.multiplier<1))throw new Error("multiplier must be a number >= 1")}function ae(t){if(t.requestsPer10Seconds!==void 0&&(typeof t.requestsPer10Seconds!="number"||t.requestsPer10Seconds<=0))throw new Error("requestsPer10Seconds must be a positive number")}function Q(t){return`${t}.quickbase.com`}var ie=/^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d{1,3})?(Z|[+-]\d{2}:?\d{2})?)?$/;function K(t){return ie.test(t)}function v(t,r){if(!r||t===null||t===void 0||typeof t!="object")return t;if(Array.isArray(t))return t.map(o=>v(o,r));if(t instanceof Date)return t;let e={};for(let[o,n]of Object.entries(t))typeof n=="string"&&K(n)?e[o]=new Date(n):n instanceof Date?e[o]=n:typeof n=="object"&&n!==null?e[o]=v(n,r):e[o]=n;return e}var A=class{constructor(r,e){i(this,"userToken");i(this,"logger");this.userToken=r,this.logger=e.logger}async getToken(r){return this.userToken}getAuthorizationHeader(r){return`QB-USER-TOKEN ${r}`}async handleAuthError(r){return this.logger.debug("Auth error with user token - cannot refresh"),!1}invalidate(r){}};var P=class{constructor(r){i(this,"cache",new Map);i(this,"defaultLifespanMs");this.defaultLifespanMs=r}get(r){let e=this.cache.get(r);return e?Date.now()>=e.expiresAt-1e4?(this.cache.delete(r),null):e.token:null}set(r,e,o){let n=Date.now()+(o??this.defaultLifespanMs);this.cache.set(r,{token:e,expiresAt:n})}delete(r){return this.cache.delete(r)}clear(){this.cache.clear()}has(r){return this.get(r)!==null}getTimeToExpiry(r){let e=this.cache.get(r);if(!e)return null;let o=e.expiresAt-Date.now();return o>0?o:null}get size(){return this.cleanup(),this.cache.size}cleanup(){let r=Date.now();for(let[e,o]of this.cache)r>=o.expiresAt&&this.cache.delete(e)}};var E=class{constructor(r,e,o){i(this,"userToken");i(this,"appToken");i(this,"realm");i(this,"baseUrl");i(this,"fetchApi");i(this,"logger");i(this,"cache");i(this,"pendingFetches",new Map);this.userToken=r,this.appToken=o?.appToken,this.realm=e.realm,this.baseUrl=e.baseUrl,this.fetchApi=e.fetchApi,this.logger=e.logger,this.cache=new P(o?.tokenLifespanMs??l.tempTokenLifespanMs)}async getToken(r){if(!r)throw new Error("Database ID (dbid) is required for temporary token authentication");let e=this.cache.get(r);if(e)return this.logger.token("cache-hit",r),e;this.logger.token("cache-miss",r);let o=this.pendingFetches.get(r);if(o)return this.logger.debug(`Waiting for existing token fetch for dbid: ${r}`),o;let n=this.fetchToken(r);this.pendingFetches.set(r,n);try{return await n}finally{this.pendingFetches.delete(r)}}async fetchToken(r){this.logger.token("fetch",r);let e=`${this.baseUrl}/auth/temporary/${r}`,o={"QB-Realm-Hostname":`${this.realm}.quickbase.com`,"Content-Type":"application/json"};this.userToken&&(o.Authorization=`QB-USER-TOKEN ${this.userToken}`),this.appToken&&(o["QB-App-Token"]=this.appToken);let n=await this.fetchApi(e,{method:"GET",headers:o,credentials:"include"});if(!n.ok){let u=await n.text();throw new R(`Failed to fetch temporary token for ${r}: ${n.status} ${u}`,{rayId:n.headers.get("qb-api-ray")||void 0})}let s=(await n.json()).temporaryAuthorization;if(!s)throw new R(`No temporary token in response for ${r}`);return this.cache.set(r,s),this.logger.debug(`Cached new token for dbid: ${r}`),s}getAuthorizationHeader(r){return`QB-TEMP-TOKEN ${r}`}async handleAuthError(r){if(!r)return this.logger.debug("Auth error without dbid - cannot refresh temp token"),!1;this.invalidate(r);try{return this.logger.token("refresh",r),await this.getToken(r),!0}catch(e){return this.logger.error(`Failed to refresh temp token for ${r}`,e),!1}}invalidate(r){r?(this.logger.token("expire",r),this.cache.delete(r)):this.cache.clear()}};var S=class{constructor(r,e,o){i(this,"samlToken");i(this,"realm");i(this,"baseUrl");i(this,"fetchApi");i(this,"logger");i(this,"cache");i(this,"pendingExchange",null);this.samlToken=r,this.realm=e.realm,this.baseUrl=e.baseUrl,this.fetchApi=e.fetchApi,this.logger=e.logger,this.cache=new P(o?.tokenLifespanMs??l.tempTokenLifespanMs)}get cacheKey(){return"__sso__"}async getToken(r){let e=this.cache.get(this.cacheKey);if(e)return this.logger.token("cache-hit"),e;if(this.logger.token("cache-miss"),this.pendingExchange)return this.logger.debug("Waiting for existing SSO token exchange"),this.pendingExchange;let o=this.exchangeToken();this.pendingExchange=o;try{return await o}finally{this.pendingExchange=null}}async exchangeToken(){this.logger.token("fetch");let r=`${this.baseUrl}/auth/oauth/token`,e=new URLSearchParams({grant_type:"urn:ietf:params:oauth:grant-type:token-exchange",requested_token_type:"urn:quickbase:params:oauth:token-type:temp_token",subject_token:this.samlToken,subject_token_type:"urn:ietf:params:oauth:token-type:saml2"}),o=await this.fetchApi(r,{method:"POST",headers:{"QB-Realm-Hostname":`${this.realm}.quickbase.com`,"Content-Type":"application/x-www-form-urlencoded"},body:e.toString()});if(!o.ok){let s=await o.text();throw new R(`SSO token exchange failed: ${o.status} ${s}`,{rayId:o.headers.get("qb-api-ray")||void 0})}let a=(await o.json()).access_token;if(!a)throw new R("No access_token in SSO exchange response");return this.cache.set(this.cacheKey,a),this.logger.debug("Cached new SSO token"),a}getAuthorizationHeader(r){return`QB-TEMP-TOKEN ${r}`}async handleAuthError(r){this.invalidate();try{return this.logger.token("refresh"),await this.getToken(),!0}catch(e){return this.logger.error("Failed to refresh SSO token",e),!1}}invalidate(r){this.logger.token("expire"),this.cache.clear()}};function N(t,r){switch(t.type){case"user-token":return new A(t.userToken,r);case"temp-token":return new E(t.userToken,r,{appToken:t.appToken,tokenLifespanMs:t.tokenLifespanMs});case"sso":return new S(t.samlToken,r);default:throw new Error(`Unknown auth type: ${t.type}`)}}function _(t,r,e){let o=t.headers.get("Retry-After");return{timestamp:new Date,requestUrl:r,httpStatus:t.status,retryAfter:o?parseInt(o,10):void 0,cfRay:t.headers.get("cf-ray")||void 0,tid:t.headers.get("tid")||void 0,qbApiRay:t.headers.get("qb-api-ray")||void 0,attempt:e}}function B(t){return new Promise(r=>setTimeout(r,t))}function ue(t){if(t.dbid)return t.dbid;if(t.query?.tableId)return String(t.query.tableId);if(t.query?.appId)return String(t.query.appId);let r=t.path.match(/\/tables\/([^/?]+)/);if(r)return r[1];let e=t.path.match(/\/apps\/([^/?]+)/);if(e)return e[1];if(t.body&&typeof t.body=="object"){let o=t.body;if(typeof o.from=="string")return o.from;if(typeof o.to=="string")return o.to}}function J(t,r,e){let o=t.endsWith("/")?t:`${t}/`,n=r.startsWith("/")?r.slice(1):r,a=new URL(n,o);if(e)for(let[s,u]of Object.entries(e))u!==void 0&&a.searchParams.set(s,String(u));return a.toString()}async function pe(t,r,e,o){let n=await t.getToken(e),a=t.getAuthorizationHeader(n);return{"Content-Type":"application/json","QB-Realm-Hostname":r,Authorization:a,...o}}async function de(t,r,e){let{config:o,auth:n,throttle:a,logger:s}=r,u=J(o.baseUrl,t.path,t.query),m=Q(o.realm),d=await pe(n,m,e.dbid,t.headers);await a.acquire();let p={method:t.method,headers:d,credentials:"omit"};t.body!==void 0&&(p.body=JSON.stringify(t.body));let c=new AbortController,g=setTimeout(()=>c.abort(),o.timeout);p.signal=c.signal;let T=Date.now();try{let f=await o.fetchApi(u,p),w=Date.now()-T;return s.timing(t.method,t.path,w),f}catch(f){throw f instanceof Error&&f.name==="AbortError"?new b(o.timeout):f}finally{clearTimeout(g)}}async function le(t,r,e,o){let{config:n,logger:a}=o;if(t.ok)return t;if(t.status===429){let s=_(t,r,e.attempt);throw a.rateLimit({url:r,status:429,retryAfter:s.retryAfter,attempt:e.attempt,rayId:s.qbApiRay||s.cfRay}),n.onRateLimit&&n.onRateLimit(s),new y(s)}throw await $(t,r)}async function V(t,r){let{config:e,auth:o,logger:n}=r,a=e.retry.maxAttempts,s=ue(t),u={methodName:`${t.method} ${t.path}`,attempt:1,maxAttempts:a,dbid:s,startTime:Date.now()},m=null;for(let d=1;d<=a;d++){u.attempt=d;try{let p=await de(t,r,u),c=J(e.baseUrl,t.path,t.query);await le(p,c,u,r);let g=await p.json();return v(g,e.convertDates)}catch(p){if(m=p,!q(p)||d>=a)throw p;if(p instanceof h&&p.statusCode===401){if(!await o.handleAuthError(s))throw p;n.debug("Token refreshed, retrying request");continue}let c,g;p instanceof y?(c=p.retryAfter?p.retryAfter*1e3:M(d,e.retry),g="Rate limited (429)"):p instanceof b?(c=M(d,e.retry),g="Timeout"):p instanceof h&&p.statusCode>=500?(c=M(d,e.retry),g=`Server error (${p.statusCode})`):(c=M(d,e.retry),g="Retryable error"),n.retry(d,a,c,g),await B(c)}}throw m||new Error("Request failed")}function M(t,r){let e=r.initialDelayMs*Math.pow(r.multiplier,t-1),o=e*.1*(Math.random()*2-1);return Math.min(e+o,r.maxDelayMs)}function z(t){return{execute:r=>V(r,t)}}var U=class{constructor(r=100){i(this,"requestsPer10Seconds");i(this,"timestamps",[]);this.requestsPer10Seconds=r}async acquire(){let r=Date.now(),e=r-1e4;for(;this.timestamps.length>0&&this.timestamps[0]<e;)this.timestamps.shift();if(this.timestamps.length>=this.requestsPer10Seconds){let n=this.timestamps[0]+1e4-r;if(n>0)return await this.sleep(n),this.acquire()}this.timestamps.push(Date.now())}getWindowCount(){let r=Date.now()-1e4;return this.timestamps.filter(e=>e>=r).length}getRemaining(){return Math.max(0,this.requestsPer10Seconds-this.getWindowCount())}reset(){this.timestamps.length=0}sleep(r){return new Promise(e=>setTimeout(e,r))}},G=class{async acquire(){}getWindowCount(){return 0}getRemaining(){return 1/0}reset(){}};function H(t){return t.enabled?new U(t.requestsPer10Seconds):new G}function Z(t){return t.totalRecords!==void 0&&t.skip!==void 0?"skip":t.nextPageToken!==void 0||t.nextToken!==void 0?"token":"none"}function X(t,r,e){let{metadata:o}=t;if(r==="skip")return o.totalRecords!==void 0&&e<o.totalRecords;if(r==="token"){let n=o.nextPageToken??o.nextToken;return n!==void 0&&n!==""}return!1}function Y(t){for(let r of Object.keys(t))if(Array.isArray(t[r]))return r;return"data"}function ee(t){if(!t||typeof t!="object")return!1;let r=t;if(!r.metadata||typeof r.metadata!="object"||!Object.values(r).some(Array.isArray))return!1;let o=r.metadata;return o.totalRecords!==void 0||o.numRecords!==void 0||o.nextPageToken!==void 0||o.nextToken!==void 0}var L=class{constructor(r,e){i(this,"executor");i(this,"paginatedExecutor");i(this,"defaultAutoPaginate");this.executor=r,this.paginatedExecutor=e?.paginatedExecutor,this.defaultAutoPaginate=e?.autoPaginate??!1}then(r,e){return(this.defaultAutoPaginate?this.all():this.executor()).then(r,e)}async all(){return this.paginate({})}async paginate(r={}){if(!this.paginatedExecutor)return this.executor();let{limit:e,skip:o=0}=r,n=[],a=null,s="none",u=o,m,d=await this.paginatedExecutor({skip:o});if(!ee(d))return d;a=d,s=Z(d.metadata);let p=Y(d),c=d[p]||[];for(e!==void 0&&c.length>e?n=c.slice(0,e):n=[...c],s==="skip"?u=o+c.length:s==="token"&&(m=d.metadata.nextPageToken??d.metadata.nextToken);X(a,s,n.length)&&!(e!==void 0&&n.length>=e);){let T;if(s==="skip")T=await this.paginatedExecutor({skip:u});else if(s==="token"&&m){let w=a.metadata.nextPageToken!==void 0?"nextPageToken":"nextToken";T=await this.paginatedExecutor({[w]:m})}else break;a=T;let f=T[p]||[];if(f.length===0)break;if(e!==void 0){let w=e-n.length;n=n.concat(f.slice(0,w))}else n=n.concat(f);if(s==="skip")u+=f.length;else if(s==="token"&&(m=T.metadata.nextPageToken??T.metadata.nextToken,!m))break}let g={...a,[p]:n,metadata:{...a.metadata,numRecords:n.length,skip:o}};return s==="token"&&(delete g.metadata.nextPageToken,delete g.metadata.nextToken),g}async noPaginate(){return this.executor()}toPromise(){return this.then()}};function k(t,r){return new L(t,r)}function W(t,r=!1){return{createApp(e){return t({method:"POST",path:"/apps",body:e})},getApp(e){return t({method:"GET",path:`/apps/${e.appId}`})},updateApp(e,o){return t({method:"POST",path:`/apps/${e.appId}`,body:o})},deleteApp(e,o){return t({method:"DELETE",path:`/apps/${e.appId}`,body:o})},getAppEvents(e){return t({method:"GET",path:`/apps/${e.appId}/events`})},copyApp(e,o){return t({method:"POST",path:`/apps/${e.appId}/copy`,body:o})},getAppTables(e){return t({method:"GET",path:"/tables",query:{appId:e.appId}})},createTable(e,o){return t({method:"POST",path:"/tables",query:{appId:e.appId},body:o})},getTable(e){return t({method:"GET",path:`/tables/${e.tableId}`,query:{appId:e.appId}})},updateTable(e,o){return t({method:"POST",path:`/tables/${e.tableId}`,query:{appId:e.appId},body:o})},deleteTable(e){return t({method:"DELETE",path:`/tables/${e.tableId}`,query:{appId:e.appId}})},getRelationships(e){return k(()=>t({method:"GET",path:`/tables/${e.tableId}/relationships`,query:{skip:e.skip}}),{paginatedExecutor:a=>t({method:"GET",path:`/tables/${e.tableId}/relationships`,query:{skip:e.skip,...a}}),autoPaginate:r})},createRelationship(e,o){return t({method:"POST",path:`/tables/${e.tableId}/relationship`,body:o})},updateRelationship(e,o){return t({method:"POST",path:`/tables/${e.tableId}/relationship/${e.relationshipId}`,body:o})},deleteRelationship(e){return t({method:"DELETE",path:`/tables/${e.tableId}/relationship/${e.relationshipId}`})},getTableReports(e){return t({method:"GET",path:"/reports",query:{tableId:e.tableId}})},getReport(e){return t({method:"GET",path:`/reports/${e.reportId}`,query:{tableId:e.tableId}})},runReport(e,o){return k(()=>t({method:"POST",path:`/reports/${e.reportId}/run`,query:{tableId:e.tableId,skip:e.skip,top:e.top},body:o}),{paginatedExecutor:s=>{let u=o,m=s.skip!==void 0||s.nextPageToken||s.nextToken?{...u||{},options:{...u?.options||{},...s.skip!==void 0?{skip:s.skip}:{}},...s.nextPageToken?{nextPageToken:s.nextPageToken}:{},...s.nextToken?{nextToken:s.nextToken}:{}}:o;return t({method:"POST",path:`/reports/${e.reportId}/run`,query:{tableId:e.tableId,skip:e.skip,top:e.top},body:m})},autoPaginate:r})},getFields(e){return t({method:"GET",path:"/fields",query:{tableId:e.tableId,includeFieldPerms:e.includeFieldPerms}})},createField(e,o){return t({method:"POST",path:"/fields",query:{tableId:e.tableId},body:o})},deleteFields(e,o){return t({method:"DELETE",path:"/fields",query:{tableId:e.tableId},body:o})},getField(e){return t({method:"GET",path:`/fields/${e.fieldId}`,query:{tableId:e.tableId,includeFieldPerms:e.includeFieldPerms}})},updateField(e,o){return t({method:"POST",path:`/fields/${e.fieldId}`,query:{tableId:e.tableId},body:o})},getFieldsUsage(e){return t({method:"GET",path:"/fields/usage",query:{tableId:e.tableId,skip:e.skip,top:e.top}})},getFieldUsage(e){return t({method:"GET",path:`/fields/usage/${e.fieldId}`,query:{tableId:e.tableId}})},runFormula(e){return t({method:"POST",path:"/formula/run",body:e})},upsert(e){return k(()=>t({method:"POST",path:"/records",body:e}),{paginatedExecutor:a=>{let s=e,u=a.skip!==void 0||a.nextPageToken||a.nextToken?{...s||{},options:{...s?.options||{},...a.skip!==void 0?{skip:a.skip}:{}},...a.nextPageToken?{nextPageToken:a.nextPageToken}:{},...a.nextToken?{nextToken:a.nextToken}:{}}:e;return t({method:"POST",path:"/records",body:u})},autoPaginate:r})},deleteRecords(e){return t({method:"DELETE",path:"/records",body:e})},runQuery(e){return k(()=>t({method:"POST",path:"/records/query",body:e}),{paginatedExecutor:a=>{let s=e,u=a.skip!==void 0||a.nextPageToken||a.nextToken?{...s||{},options:{...s?.options||{},...a.skip!==void 0?{skip:a.skip}:{}},...a.nextPageToken?{nextPageToken:a.nextPageToken}:{},...a.nextToken?{nextToken:a.nextToken}:{}}:e;return t({method:"POST",path:"/records/query",body:u})},autoPaginate:r})},getTempTokenDBID(e){return t({method:"GET",path:`/auth/temporary/${e.dbid}`})},exchangeSsoToken(e){return t({method:"POST",path:"/auth/oauth/token",body:e})},cloneUserToken(e){return t({method:"POST",path:"/usertoken/clone",body:e})},transferUserToken(e){return t({method:"POST",path:"/usertoken/transfer",body:e})},deactivateUserToken(){return t({method:"POST",path:"/usertoken/deactivate"})},deleteUserToken(){return t({method:"DELETE",path:"/usertoken"})},downloadFile(e){return t({method:"GET",path:`/files/${e.tableId}/${e.recordId}/${e.fieldId}/${e.versionNumber}`})},deleteFile(e){return t({method:"DELETE",path:`/files/${e.tableId}/${e.recordId}/${e.fieldId}/${e.versionNumber}`})},getUsers(e,o){return k(()=>t({method:"POST",path:"/users",query:{accountId:e.accountId},body:o}),{paginatedExecutor:s=>{let u=o,m=s.skip!==void 0||s.nextPageToken||s.nextToken?{...u||{},options:{...u?.options||{},...s.skip!==void 0?{skip:s.skip}:{}},...s.nextPageToken?{nextPageToken:s.nextPageToken}:{},...s.nextToken?{nextToken:s.nextToken}:{}}:o;return t({method:"POST",path:"/users",query:{accountId:e.accountId},body:m})},autoPaginate:r})},denyUsers(e,o){return t({method:"PUT",path:"/users/deny",query:{accountId:e.accountId},body:o})},denyUsersAndGroups(e,o){return t({method:"PUT",path:`/users/deny/${e.shouldDeleteFromGroups}`,query:{accountId:e.accountId},body:o})},undenyUsers(e,o){return t({method:"PUT",path:"/users/undeny",query:{accountId:e.accountId},body:o})},addMembersToGroup(e,o){return t({method:"POST",path:`/groups/${e.gid}/members`,body:o})},removeMembersFromGroup(e,o){return t({method:"DELETE",path:`/groups/${e.gid}/members`,body:o})},addManagersToGroup(e,o){return t({method:"POST",path:`/groups/${e.gid}/managers`,body:o})},removeManagersFromGroup(e,o){return t({method:"DELETE",path:`/groups/${e.gid}/managers`,body:o})},addSubgroupsToGroup(e,o){return t({method:"POST",path:`/groups/${e.gid}/subgroups`,body:o})},removeSubgroupsFromGroup(e,o){return t({method:"DELETE",path:`/groups/${e.gid}/subgroups`,body:o})},audit(e){return t({method:"POST",path:"/audit",body:e})},platformAnalyticReads(e){return t({method:"GET",path:"/analytics/reads",query:{day:e.day}})},platformAnalyticEventSummaries(e,o){return k(()=>t({method:"POST",path:"/analytics/events/summaries",query:{accountId:e.accountId},body:o}),{paginatedExecutor:s=>{let u=o,m=s.skip!==void 0||s.nextPageToken||s.nextToken?{...u||{},options:{...u?.options||{},...s.skip!==void 0?{skip:s.skip}:{}},...s.nextPageToken?{nextPageToken:s.nextPageToken}:{},...s.nextToken?{nextToken:s.nextToken}:{}}:o;return t({method:"POST",path:"/analytics/events/summaries",query:{accountId:e.accountId},body:m})},autoPaginate:r})},exportSolution(e){return t({method:"GET",path:`/solutions/${e.solutionId}`})},updateSolution(e,o){return t({method:"PUT",path:`/solutions/${e.solutionId}`,body:o})},createSolution(e){return t({method:"POST",path:"/solutions",body:e})},exportSolutionToRecord(e){return t({method:"GET",path:`/solutions/${e.solutionId}/torecord`,query:{tableId:e.tableId,fieldId:e.fieldId}})},createSolutionFromRecord(e){return t({method:"GET",path:"/solutions/fromrecord",query:{tableId:e.tableId,fieldId:e.fieldId,recordId:e.recordId}})},updateSolutionToRecord(e){return t({method:"GET",path:`/solutions/${e.solutionId}/fromrecord`,query:{tableId:e.tableId,fieldId:e.fieldId,recordId:e.recordId}})},changesetSolution(e,o){return t({method:"PUT",path:`/solutions/${e.solutionId}/changeset`,body:o})},changesetSolutionFromRecord(e){return t({method:"GET",path:`/solutions/${e.solutionId}/changeset/fromrecord`,query:{tableId:e.tableId,fieldId:e.fieldId,recordId:e.recordId}})},generateDocument(e){return t({method:"GET",path:`/docTemplates/${e.templateId}/generate`,query:{tableId:e.tableId,recordId:e.recordId,filename:e.filename,format:e.format,margin:e.margin,unit:e.unit,pageSize:e.pageSize,orientation:e.orientation,realm:e.realm}})}}}function me(t){let r=j(t),e=O(r.debug),o={realm:r.realm,baseUrl:r.baseUrl,fetchApi:r.fetchApi,logger:e},n=N(r.auth,o),a=H(r.proactiveThrottle),s=z({config:r,auth:n,throttle:a,logger:e});return{...W(s.execute,r.autoPaginate),request:s.execute,getConfig:()=>r}}var Et=me;export{R as AuthenticationError,I as AuthorizationError,G as NoOpThrottle,C as NotFoundError,h as QuickbaseError,y as RateLimitError,x as ServerError,U as SlidingWindowThrottle,S as SsoTokenStrategy,E as TempTokenStrategy,b as TimeoutError,A as UserTokenStrategy,D as ValidationError,W as createApiMethods,N as createAuthStrategy,me as createClient,Et as default};
|
|
6
|
+
var re=Object.defineProperty;var ne=(t,r,e)=>r in t?re(t,r,{enumerable:!0,configurable:!0,writable:!0,value:e}):t[r]=e;var i=(t,r,e)=>ne(t,typeof r!="symbol"?r+"":r,e);var l={baseUrl:"https://api.quickbase.com/v1",timeout:3e4,debug:!1,retry:{maxAttempts:3,initialDelayMs:1e3,maxDelayMs:3e4,multiplier:2},proactiveThrottle:{enabled:!1,requestsPer10Seconds:100},tempTokenLifespanMs:29e4,autoPaginate:!1,convertDates:!0};var h=class t extends Error{constructor(e,n,o){super(e,{cause:o?.cause});i(this,"statusCode");i(this,"description");i(this,"rayId");this.name="QuickbaseError",this.statusCode=n,this.description=o?.description,this.rayId=o?.rayId,Error.captureStackTrace&&Error.captureStackTrace(this,t)}toJSON(){return{name:this.name,message:this.message,statusCode:this.statusCode,description:this.description,rayId:this.rayId}}},y=class extends h{constructor(e,n){super(n||`Rate limited. Retry after ${e.retryAfter??"unknown"} seconds`,429,{rayId:e.qbApiRay||e.cfRay});i(this,"retryAfter");i(this,"rateLimitInfo");this.name="RateLimitError",this.retryAfter=e.retryAfter,this.rateLimitInfo=e}toJSON(){return{...super.toJSON(),retryAfter:this.retryAfter,rateLimitInfo:this.rateLimitInfo}}},f=class extends h{constructor(r,e){super(r,401,e),this.name="AuthenticationError"}},v=class extends h{constructor(r,e){super(r,403,e),this.name="AuthorizationError"}},C=class extends h{constructor(r,e){super(r,404,e),this.name="NotFoundError"}},U=class extends h{constructor(e,n){super(e,400,n);i(this,"errors");this.name="ValidationError",this.errors=n?.errors}toJSON(){return{...super.toJSON(),errors:this.errors}}},k=class extends h{constructor(e,n){super(`Request timed out after ${e}ms`,0,n);i(this,"timeoutMs");this.name="TimeoutError",this.timeoutMs=e}toJSON(){return{...super.toJSON(),timeoutMs:this.timeoutMs}}},x=class extends h{constructor(r,e,n){super(e,r,n),this.name="ServerError"}};async function O(t,r){let e=t.headers.get("qb-api-ray")||t.headers.get("cf-ray")||void 0,n=null;try{n=await t.json()}catch{}let o=n?.message||t.statusText||"Unknown error",a=n?.description;switch(t.status){case 400:return new U(o,{description:a,rayId:e,errors:n?.errors});case 401:return new f(o,{rayId:e});case 403:return new v(o,{rayId:e});case 404:return new C(o,{rayId:e});case 429:{let s=t.headers.get("Retry-After"),u={timestamp:new Date,requestUrl:r,httpStatus:429,retryAfter:s?parseInt(s,10):void 0,cfRay:t.headers.get("cf-ray")||void 0,tid:t.headers.get("tid")||void 0,qbApiRay:t.headers.get("qb-api-ray")||void 0,attempt:1};return new y(u,o)}default:return t.status>=500?new x(t.status,o,{description:a,rayId:e}):new h(o,t.status,{description:a,rayId:e})}}function F(t){return t instanceof y||t instanceof x||t instanceof k}var M=class{constructor(r=!1,e="quickbase-js"){i(this,"enabled");i(this,"prefix");this.enabled=r,this.prefix=e}formatMessage(r,e){return`[${new Date().toISOString()}] [${this.prefix}] [${r}] ${e}`}debug(r,e){this.enabled&&(e!==void 0?console.log(this.formatMessage("DEBUG",r),e):console.log(this.formatMessage("DEBUG",r)))}info(r,e){this.enabled&&(e!==void 0?console.info(this.formatMessage("INFO",r),e):console.info(this.formatMessage("INFO",r)))}warn(r,e){e!==void 0?console.warn(this.formatMessage("WARN",r),e):console.warn(this.formatMessage("WARN",r))}error(r,e){e!==void 0?console.error(this.formatMessage("ERROR",r),e):console.error(this.formatMessage("ERROR",r))}rateLimit(r){this.enabled&&this.debug(`Rate limited (attempt ${r.attempt}): ${r.url} - Status ${r.status}, Retry-After: ${r.retryAfter??"not specified"}s`+(r.rayId?`, Ray: ${r.rayId}`:""))}timing(r,e,n){this.enabled&&this.debug(`${r} ${e} completed in ${n}ms`)}retry(r,e,n,o){this.enabled&&this.debug(`Retry ${r}/${e} in ${n}ms: ${o}`)}token(r,e){if(this.enabled){let n=e?` for dbid: ${e}`:"";this.debug(`Token ${r}${n}`)}}};function j(t){return new M(t)}function Q(t){oe(t);let r={maxAttempts:t.rateLimit?.retry?.maxAttempts??l.retry.maxAttempts,initialDelayMs:t.rateLimit?.retry?.initialDelayMs??l.retry.initialDelayMs,maxDelayMs:t.rateLimit?.retry?.maxDelayMs??l.retry.maxDelayMs,multiplier:t.rateLimit?.retry?.multiplier??l.retry.multiplier},e={enabled:t.rateLimit?.proactiveThrottle?.enabled??l.proactiveThrottle.enabled,requestsPer10Seconds:t.rateLimit?.proactiveThrottle?.requestsPer10Seconds??l.proactiveThrottle.requestsPer10Seconds};return{realm:t.realm,baseUrl:t.baseUrl??l.baseUrl,timeout:t.timeout??l.timeout,debug:t.debug??l.debug,fetchApi:t.fetchApi??globalThis.fetch.bind(globalThis),auth:t.auth,retry:r,proactiveThrottle:e,onRateLimit:t.rateLimit?.onRateLimit,autoPaginate:t.autoPaginate??l.autoPaginate,convertDates:t.convertDates??l.convertDates}}function oe(t){if(!t.realm)throw new Error("QuickBase realm is required");if(typeof t.realm!="string")throw new Error("QuickBase realm must be a string");if(t.realm.includes("."))throw new Error('Realm should be just the subdomain (e.g., "mycompany" not "mycompany.quickbase.com")');if(!t.auth)throw new Error("Authentication configuration is required");if(se(t.auth),t.timeout!==void 0&&(typeof t.timeout!="number"||t.timeout<=0))throw new Error("Timeout must be a positive number");t.rateLimit?.retry&&ae(t.rateLimit.retry),t.rateLimit?.proactiveThrottle&&ie(t.rateLimit.proactiveThrottle)}function se(t){switch(t.type){case"user-token":if(!t.userToken)throw new Error("User token is required for user-token auth");break;case"temp-token":break;case"sso":if(!t.samlToken)throw new Error("SAML token is required for SSO auth");break;case"ticket":if(!t.username)throw new Error("Username is required for ticket auth");if(!t.password)throw new Error("Password is required for ticket auth");break;default:throw new Error(`Unknown auth type: ${t.type}`)}}function ae(t){if(t.maxAttempts!==void 0&&(typeof t.maxAttempts!="number"||t.maxAttempts<0))throw new Error("maxAttempts must be a non-negative number");if(t.initialDelayMs!==void 0&&(typeof t.initialDelayMs!="number"||t.initialDelayMs<0))throw new Error("initialDelayMs must be a non-negative number");if(t.maxDelayMs!==void 0&&(typeof t.maxDelayMs!="number"||t.maxDelayMs<0))throw new Error("maxDelayMs must be a non-negative number");if(t.multiplier!==void 0&&(typeof t.multiplier!="number"||t.multiplier<1))throw new Error("multiplier must be a number >= 1")}function ie(t){if(t.requestsPer10Seconds!==void 0&&(typeof t.requestsPer10Seconds!="number"||t.requestsPer10Seconds<=0))throw new Error("requestsPer10Seconds must be a positive number")}function N(t){return`${t}.quickbase.com`}var ue=/^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d{1,3})?(Z|[+-]\d{2}:?\d{2})?)?$/;function J(t){return ue.test(t)}function D(t,r){if(!r||t===null||t===void 0||typeof t!="object")return t;if(Array.isArray(t))return t.map(n=>D(n,r));if(t instanceof Date)return t;let e={};for(let[n,o]of Object.entries(t))typeof o=="string"&&J(o)?e[n]=new Date(o):o instanceof Date?e[n]=o:typeof o=="object"&&o!==null?e[n]=D(o,r):e[n]=o;return e}var A=class{constructor(r,e){i(this,"userToken");i(this,"logger");this.userToken=r,this.logger=e.logger}async getToken(r){return this.userToken}getAuthorizationHeader(r){return`QB-USER-TOKEN ${r}`}async handleAuthError(r){return this.logger.debug("Auth error with user token - cannot refresh"),!1}invalidate(r){}};var P=class{constructor(r){i(this,"cache",new Map);i(this,"defaultLifespanMs");this.defaultLifespanMs=r}get(r){let e=this.cache.get(r);return e?Date.now()>=e.expiresAt-1e4?(this.cache.delete(r),null):e.token:null}set(r,e,n){let o=Date.now()+(n??this.defaultLifespanMs);this.cache.set(r,{token:e,expiresAt:o})}delete(r){return this.cache.delete(r)}clear(){this.cache.clear()}has(r){return this.get(r)!==null}getTimeToExpiry(r){let e=this.cache.get(r);if(!e)return null;let n=e.expiresAt-Date.now();return n>0?n:null}get size(){return this.cleanup(),this.cache.size}cleanup(){let r=Date.now();for(let[e,n]of this.cache)r>=n.expiresAt&&this.cache.delete(e)}};var E=class{constructor(r,e,n){i(this,"userToken");i(this,"appToken");i(this,"realm");i(this,"baseUrl");i(this,"fetchApi");i(this,"logger");i(this,"cache");i(this,"pendingFetches",new Map);this.userToken=r,this.appToken=n?.appToken,this.realm=e.realm,this.baseUrl=e.baseUrl,this.fetchApi=e.fetchApi,this.logger=e.logger,this.cache=new P(n?.tokenLifespanMs??l.tempTokenLifespanMs)}async getToken(r){if(!r)throw new Error("Database ID (dbid) is required for temporary token authentication");let e=this.cache.get(r);if(e)return this.logger.token("cache-hit",r),e;this.logger.token("cache-miss",r);let n=this.pendingFetches.get(r);if(n)return this.logger.debug(`Waiting for existing token fetch for dbid: ${r}`),n;let o=this.fetchToken(r);this.pendingFetches.set(r,o);try{return await o}finally{this.pendingFetches.delete(r)}}async fetchToken(r){this.logger.token("fetch",r);let e=`${this.baseUrl}/auth/temporary/${r}`,n={"QB-Realm-Hostname":`${this.realm}.quickbase.com`,"Content-Type":"application/json"};this.userToken&&(n.Authorization=`QB-USER-TOKEN ${this.userToken}`),this.appToken&&(n["QB-App-Token"]=this.appToken);let o=await this.fetchApi(e,{method:"GET",headers:n,credentials:"include"});if(!o.ok){let u=await o.text();throw new f(`Failed to fetch temporary token for ${r}: ${o.status} ${u}`,{rayId:o.headers.get("qb-api-ray")||void 0})}let s=(await o.json()).temporaryAuthorization;if(!s)throw new f(`No temporary token in response for ${r}`);return this.cache.set(r,s),this.logger.debug(`Cached new token for dbid: ${r}`),s}getAuthorizationHeader(r){return`QB-TEMP-TOKEN ${r}`}async handleAuthError(r){if(!r)return this.logger.debug("Auth error without dbid - cannot refresh temp token"),!1;this.invalidate(r);try{return this.logger.token("refresh",r),await this.getToken(r),!0}catch(e){return this.logger.error(`Failed to refresh temp token for ${r}`,e),!1}}invalidate(r){r?(this.logger.token("expire",r),this.cache.delete(r)):this.cache.clear()}};var w=class{constructor(r,e,n){i(this,"samlToken");i(this,"realm");i(this,"baseUrl");i(this,"fetchApi");i(this,"logger");i(this,"cache");i(this,"pendingExchange",null);this.samlToken=r,this.realm=e.realm,this.baseUrl=e.baseUrl,this.fetchApi=e.fetchApi,this.logger=e.logger,this.cache=new P(n?.tokenLifespanMs??l.tempTokenLifespanMs)}get cacheKey(){return"__sso__"}async getToken(r){let e=this.cache.get(this.cacheKey);if(e)return this.logger.token("cache-hit"),e;if(this.logger.token("cache-miss"),this.pendingExchange)return this.logger.debug("Waiting for existing SSO token exchange"),this.pendingExchange;let n=this.exchangeToken();this.pendingExchange=n;try{return await n}finally{this.pendingExchange=null}}async exchangeToken(){this.logger.token("fetch");let r=`${this.baseUrl}/auth/oauth/token`,e=new URLSearchParams({grant_type:"urn:ietf:params:oauth:grant-type:token-exchange",requested_token_type:"urn:quickbase:params:oauth:token-type:temp_token",subject_token:this.samlToken,subject_token_type:"urn:ietf:params:oauth:token-type:saml2"}),n=await this.fetchApi(r,{method:"POST",headers:{"QB-Realm-Hostname":`${this.realm}.quickbase.com`,"Content-Type":"application/x-www-form-urlencoded"},body:e.toString()});if(!n.ok){let s=await n.text();throw new f(`SSO token exchange failed: ${n.status} ${s}`,{rayId:n.headers.get("qb-api-ray")||void 0})}let a=(await n.json()).access_token;if(!a)throw new f("No access_token in SSO exchange response");return this.cache.set(this.cacheKey,a),this.logger.debug("Cached new SSO token"),a}getAuthorizationHeader(r){return`QB-TEMP-TOKEN ${r}`}async handleAuthError(r){this.invalidate();try{return this.logger.token("refresh"),await this.getToken(),!0}catch(e){return this.logger.error("Failed to refresh SSO token",e),!1}}invalidate(r){this.logger.token("expire"),this.cache.clear()}};var S=class{constructor(r,e,n,o){i(this,"username");i(this,"password");i(this,"hours");i(this,"realm");i(this,"fetchApi");i(this,"logger");i(this,"ticket",null);i(this,"userId",null);i(this,"authenticated",!1);i(this,"pendingAuth",null);this.username=r,this.password=e,this.hours=Math.min(Math.max(n?.hours??12,1),4380),this.realm=o.realm,this.fetchApi=o.fetchApi,this.logger=o.logger}async getToken(r){if(this.ticket)return this.ticket;if(this.authenticated)throw new Error("Ticket expired; create a new client with fresh credentials");if(this.pendingAuth)return this.pendingAuth;this.pendingAuth=this.authenticate();try{return await this.pendingAuth}finally{this.pendingAuth=null}}getAuthorizationHeader(r){return`QB-TICKET ${r}`}async handleAuthError(r){return this.ticket=null,this.logger.debug("Ticket auth error - cannot refresh (password was cleared)"),!1}invalidate(r){this.ticket=null}getUserId(){return this.userId}async authenticate(){if(!this.password)throw new Error("Ticket expired; create a new client with fresh credentials");let r=`https://${this.realm}.quickbase.com/db/main`,e=`<qdbapi>
|
|
7
|
+
<username>${this.escapeXml(this.username)}</username>
|
|
8
|
+
<password>${this.escapeXml(this.password)}</password>
|
|
9
|
+
<hours>${this.hours}</hours>
|
|
10
|
+
</qdbapi>`;this.logger.debug(`Authenticating via API_Authenticate for ${this.username}`);let o=await(await this.fetchApi(r,{method:"POST",headers:{"Content-Type":"application/xml","QUICKBASE-ACTION":"API_Authenticate"},body:e})).text(),a=this.parseXmlResponse(o);if(a.errcode!==0){let s=a.errdetail||a.errtext||"Unknown error";throw new Error(`Authentication failed: ${s} (code: ${a.errcode})`)}if(!a.ticket)throw new Error("No ticket returned from API_Authenticate");return this.ticket=a.ticket,this.userId=a.userid,this.authenticated=!0,this.password=null,this.logger.debug(`Authenticated successfully, userId: ${this.userId}`),this.ticket}parseXmlResponse(r){let e=n=>r.match(new RegExp(`<${n}>([^<]*)</${n}>`))?.[1]??"";return{ticket:e("ticket"),userid:e("userid"),errcode:parseInt(e("errcode"),10)||0,errtext:e("errtext"),errdetail:e("errdetail")||void 0}}escapeXml(r){return r.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}};function _(t,r){switch(t.type){case"user-token":return new A(t.userToken,r);case"temp-token":return new E(t.userToken,r,{appToken:t.appToken,tokenLifespanMs:t.tokenLifespanMs});case"sso":return new w(t.samlToken,r);case"ticket":return new S(t.username,t.password,{hours:t.hours},r);default:throw new Error(`Unknown auth type: ${t.type}`)}}function B(t,r,e){let n=t.headers.get("Retry-After");return{timestamp:new Date,requestUrl:r,httpStatus:t.status,retryAfter:n?parseInt(n,10):void 0,cfRay:t.headers.get("cf-ray")||void 0,tid:t.headers.get("tid")||void 0,qbApiRay:t.headers.get("qb-api-ray")||void 0,attempt:e}}function z(t){return new Promise(r=>setTimeout(r,t))}function pe(t){if(t.dbid)return t.dbid;if(t.query?.tableId)return String(t.query.tableId);if(t.query?.appId)return String(t.query.appId);let r=t.path.match(/\/tables\/([^/?]+)/);if(r)return r[1];let e=t.path.match(/\/apps\/([^/?]+)/);if(e)return e[1];if(t.body&&typeof t.body=="object"){let n=t.body;if(typeof n.from=="string")return n.from;if(typeof n.to=="string")return n.to}}function X(t,r,e){let n=t.endsWith("/")?t:`${t}/`,o=r.startsWith("/")?r.slice(1):r,a=new URL(o,n);if(e)for(let[s,u]of Object.entries(e))u!==void 0&&a.searchParams.set(s,String(u));return a.toString()}async function de(t,r,e,n){let o=await t.getToken(e),a=t.getAuthorizationHeader(o);return{"Content-Type":"application/json","QB-Realm-Hostname":r,Authorization:a,...n}}async function le(t,r,e){let{config:n,auth:o,throttle:a,logger:s}=r,u=X(n.baseUrl,t.path,t.query),m=N(n.realm),d=await de(o,m,e.dbid,t.headers);await a.acquire();let p={method:t.method,headers:d,credentials:"omit"};t.body!==void 0&&(p.body=JSON.stringify(t.body));let c=new AbortController,g=setTimeout(()=>c.abort(),n.timeout);p.signal=c.signal;let T=Date.now();try{let R=await n.fetchApi(u,p),I=Date.now()-T;return s.timing(t.method,t.path,I),R}catch(R){throw R instanceof Error&&R.name==="AbortError"?new k(n.timeout):R}finally{clearTimeout(g)}}async function me(t,r,e,n){let{config:o,logger:a}=n;if(t.ok)return t;if(t.status===429){let s=B(t,r,e.attempt);throw a.rateLimit({url:r,status:429,retryAfter:s.retryAfter,attempt:e.attempt,rayId:s.qbApiRay||s.cfRay}),o.onRateLimit&&o.onRateLimit(s),new y(s)}throw await O(t,r)}async function V(t,r){let{config:e,auth:n,logger:o}=r,a=e.retry.maxAttempts,s=pe(t),u={methodName:`${t.method} ${t.path}`,attempt:1,maxAttempts:a,dbid:s,startTime:Date.now()},m=null;for(let d=1;d<=a;d++){u.attempt=d;try{let p=await le(t,r,u),c=X(e.baseUrl,t.path,t.query);await me(p,c,u,r);let g=await p.json();return D(g,e.convertDates)}catch(p){if(m=p,!F(p)||d>=a)throw p;if(p instanceof h&&p.statusCode===401){if(!await n.handleAuthError(s))throw p;o.debug("Token refreshed, retrying request");continue}let c,g;p instanceof y?(c=p.retryAfter?p.retryAfter*1e3:$(d,e.retry),g="Rate limited (429)"):p instanceof k?(c=$(d,e.retry),g="Timeout"):p instanceof h&&p.statusCode>=500?(c=$(d,e.retry),g=`Server error (${p.statusCode})`):(c=$(d,e.retry),g="Retryable error"),o.retry(d,a,c,g),await z(c)}}throw m||new Error("Request failed")}function $(t,r){let e=r.initialDelayMs*Math.pow(r.multiplier,t-1),n=e*.1*(Math.random()*2-1);return Math.min(e+n,r.maxDelayMs)}function H(t){return{execute:r=>V(r,t)}}var G=class{constructor(r=100){i(this,"requestsPer10Seconds");i(this,"timestamps",[]);this.requestsPer10Seconds=r}async acquire(){let r=Date.now(),e=r-1e4;for(;this.timestamps.length>0&&this.timestamps[0]<e;)this.timestamps.shift();if(this.timestamps.length>=this.requestsPer10Seconds){let o=this.timestamps[0]+1e4-r;if(o>0)return await this.sleep(o),this.acquire()}this.timestamps.push(Date.now())}getWindowCount(){let r=Date.now()-1e4;return this.timestamps.filter(e=>e>=r).length}getRemaining(){return Math.max(0,this.requestsPer10Seconds-this.getWindowCount())}reset(){this.timestamps.length=0}sleep(r){return new Promise(e=>setTimeout(e,r))}},q=class{async acquire(){}getWindowCount(){return 0}getRemaining(){return 1/0}reset(){}};function K(t){return t.enabled?new G(t.requestsPer10Seconds):new q}function Z(t){return t.totalRecords!==void 0&&t.skip!==void 0?"skip":t.nextPageToken!==void 0||t.nextToken!==void 0?"token":"none"}function Y(t,r,e){let{metadata:n}=t;if(r==="skip")return n.totalRecords!==void 0&&e<n.totalRecords;if(r==="token"){let o=n.nextPageToken??n.nextToken;return o!==void 0&&o!==""}return!1}function ee(t){for(let r of Object.keys(t))if(Array.isArray(t[r]))return r;return"data"}function te(t){if(!t||typeof t!="object")return!1;let r=t;if(!r.metadata||typeof r.metadata!="object"||!Object.values(r).some(Array.isArray))return!1;let n=r.metadata;return n.totalRecords!==void 0||n.numRecords!==void 0||n.nextPageToken!==void 0||n.nextToken!==void 0}var L=class{constructor(r,e){i(this,"executor");i(this,"paginatedExecutor");i(this,"defaultAutoPaginate");this.executor=r,this.paginatedExecutor=e?.paginatedExecutor,this.defaultAutoPaginate=e?.autoPaginate??!1}then(r,e){return(this.defaultAutoPaginate?this.all():this.executor()).then(r,e)}async all(){return this.paginate({})}async paginate(r={}){if(!this.paginatedExecutor)return this.executor();let{limit:e,skip:n=0}=r,o=[],a=null,s="none",u=n,m,d=await this.paginatedExecutor({skip:n});if(!te(d))return d;a=d,s=Z(d.metadata);let p=ee(d),c=d[p]||[];for(e!==void 0&&c.length>e?o=c.slice(0,e):o=[...c],s==="skip"?u=n+c.length:s==="token"&&(m=d.metadata.nextPageToken??d.metadata.nextToken);Y(a,s,o.length)&&!(e!==void 0&&o.length>=e);){let T;if(s==="skip")T=await this.paginatedExecutor({skip:u});else if(s==="token"&&m){let I=a.metadata.nextPageToken!==void 0?"nextPageToken":"nextToken";T=await this.paginatedExecutor({[I]:m})}else break;a=T;let R=T[p]||[];if(R.length===0)break;if(e!==void 0){let I=e-o.length;o=o.concat(R.slice(0,I))}else o=o.concat(R);if(s==="skip")u+=R.length;else if(s==="token"&&(m=T.metadata.nextPageToken??T.metadata.nextToken,!m))break}let g={...a,[p]:o,metadata:{...a.metadata,numRecords:o.length,skip:n}};return s==="token"&&(delete g.metadata.nextPageToken,delete g.metadata.nextToken),g}async noPaginate(){return this.executor()}toPromise(){return this.then()}};function b(t,r){return new L(t,r)}function W(t,r=!1){return{createApp(e){return t({method:"POST",path:"/apps",body:e})},getApp(e){return t({method:"GET",path:`/apps/${e.appId}`})},updateApp(e,n){return t({method:"POST",path:`/apps/${e.appId}`,body:n})},deleteApp(e,n){return t({method:"DELETE",path:`/apps/${e.appId}`,body:n})},getAppEvents(e){return t({method:"GET",path:`/apps/${e.appId}/events`})},copyApp(e,n){return t({method:"POST",path:`/apps/${e.appId}/copy`,body:n})},getAppTables(e){return t({method:"GET",path:"/tables",query:{appId:e.appId}})},createTable(e,n){return t({method:"POST",path:"/tables",query:{appId:e.appId},body:n})},getTable(e){return t({method:"GET",path:`/tables/${e.tableId}`,query:{appId:e.appId}})},updateTable(e,n){return t({method:"POST",path:`/tables/${e.tableId}`,query:{appId:e.appId},body:n})},deleteTable(e){return t({method:"DELETE",path:`/tables/${e.tableId}`,query:{appId:e.appId}})},getRelationships(e){return b(()=>t({method:"GET",path:`/tables/${e.tableId}/relationships`,query:{skip:e.skip}}),{paginatedExecutor:a=>t({method:"GET",path:`/tables/${e.tableId}/relationships`,query:{skip:e.skip,...a}}),autoPaginate:r})},createRelationship(e,n){return t({method:"POST",path:`/tables/${e.tableId}/relationship`,body:n})},updateRelationship(e,n){return t({method:"POST",path:`/tables/${e.tableId}/relationship/${e.relationshipId}`,body:n})},deleteRelationship(e){return t({method:"DELETE",path:`/tables/${e.tableId}/relationship/${e.relationshipId}`})},getTableReports(e){return t({method:"GET",path:"/reports",query:{tableId:e.tableId}})},getReport(e){return t({method:"GET",path:`/reports/${e.reportId}`,query:{tableId:e.tableId}})},runReport(e,n){return b(()=>t({method:"POST",path:`/reports/${e.reportId}/run`,query:{tableId:e.tableId,skip:e.skip,top:e.top},body:n}),{paginatedExecutor:s=>{let u=n,m=s.skip!==void 0||s.nextPageToken||s.nextToken?{...u||{},options:{...u?.options||{},...s.skip!==void 0?{skip:s.skip}:{}},...s.nextPageToken?{nextPageToken:s.nextPageToken}:{},...s.nextToken?{nextToken:s.nextToken}:{}}:n;return t({method:"POST",path:`/reports/${e.reportId}/run`,query:{tableId:e.tableId,skip:e.skip,top:e.top},body:m})},autoPaginate:r})},getFields(e){return t({method:"GET",path:"/fields",query:{tableId:e.tableId,includeFieldPerms:e.includeFieldPerms}})},createField(e,n){return t({method:"POST",path:"/fields",query:{tableId:e.tableId},body:n})},deleteFields(e,n){return t({method:"DELETE",path:"/fields",query:{tableId:e.tableId},body:n})},getField(e){return t({method:"GET",path:`/fields/${e.fieldId}`,query:{tableId:e.tableId,includeFieldPerms:e.includeFieldPerms}})},updateField(e,n){return t({method:"POST",path:`/fields/${e.fieldId}`,query:{tableId:e.tableId},body:n})},getFieldsUsage(e){return t({method:"GET",path:"/fields/usage",query:{tableId:e.tableId,skip:e.skip,top:e.top}})},getFieldUsage(e){return t({method:"GET",path:`/fields/usage/${e.fieldId}`,query:{tableId:e.tableId}})},runFormula(e){return t({method:"POST",path:"/formula/run",body:e})},upsert(e){return b(()=>t({method:"POST",path:"/records",body:e}),{paginatedExecutor:a=>{let s=e,u=a.skip!==void 0||a.nextPageToken||a.nextToken?{...s||{},options:{...s?.options||{},...a.skip!==void 0?{skip:a.skip}:{}},...a.nextPageToken?{nextPageToken:a.nextPageToken}:{},...a.nextToken?{nextToken:a.nextToken}:{}}:e;return t({method:"POST",path:"/records",body:u})},autoPaginate:r})},deleteRecords(e){return t({method:"DELETE",path:"/records",body:e})},runQuery(e){return b(()=>t({method:"POST",path:"/records/query",body:e}),{paginatedExecutor:a=>{let s=e,u=a.skip!==void 0||a.nextPageToken||a.nextToken?{...s||{},options:{...s?.options||{},...a.skip!==void 0?{skip:a.skip}:{}},...a.nextPageToken?{nextPageToken:a.nextPageToken}:{},...a.nextToken?{nextToken:a.nextToken}:{}}:e;return t({method:"POST",path:"/records/query",body:u})},autoPaginate:r})},getTempTokenDBID(e){return t({method:"GET",path:`/auth/temporary/${e.dbid}`})},exchangeSsoToken(e){return t({method:"POST",path:"/auth/oauth/token",body:e})},cloneUserToken(e){return t({method:"POST",path:"/usertoken/clone",body:e})},transferUserToken(e){return t({method:"POST",path:"/usertoken/transfer",body:e})},deactivateUserToken(){return t({method:"POST",path:"/usertoken/deactivate"})},deleteUserToken(){return t({method:"DELETE",path:"/usertoken"})},downloadFile(e){return t({method:"GET",path:`/files/${e.tableId}/${e.recordId}/${e.fieldId}/${e.versionNumber}`})},deleteFile(e){return t({method:"DELETE",path:`/files/${e.tableId}/${e.recordId}/${e.fieldId}/${e.versionNumber}`})},getUsers(e,n){return b(()=>t({method:"POST",path:"/users",query:{accountId:e.accountId},body:n}),{paginatedExecutor:s=>{let u=n,m=s.skip!==void 0||s.nextPageToken||s.nextToken?{...u||{},options:{...u?.options||{},...s.skip!==void 0?{skip:s.skip}:{}},...s.nextPageToken?{nextPageToken:s.nextPageToken}:{},...s.nextToken?{nextToken:s.nextToken}:{}}:n;return t({method:"POST",path:"/users",query:{accountId:e.accountId},body:m})},autoPaginate:r})},denyUsers(e,n){return t({method:"PUT",path:"/users/deny",query:{accountId:e.accountId},body:n})},denyUsersAndGroups(e,n){return t({method:"PUT",path:`/users/deny/${e.shouldDeleteFromGroups}`,query:{accountId:e.accountId},body:n})},undenyUsers(e,n){return t({method:"PUT",path:"/users/undeny",query:{accountId:e.accountId},body:n})},addMembersToGroup(e,n){return t({method:"POST",path:`/groups/${e.gid}/members`,body:n})},removeMembersFromGroup(e,n){return t({method:"DELETE",path:`/groups/${e.gid}/members`,body:n})},addManagersToGroup(e,n){return t({method:"POST",path:`/groups/${e.gid}/managers`,body:n})},removeManagersFromGroup(e,n){return t({method:"DELETE",path:`/groups/${e.gid}/managers`,body:n})},addSubgroupsToGroup(e,n){return t({method:"POST",path:`/groups/${e.gid}/subgroups`,body:n})},removeSubgroupsFromGroup(e,n){return t({method:"DELETE",path:`/groups/${e.gid}/subgroups`,body:n})},audit(e){return t({method:"POST",path:"/audit",body:e})},platformAnalyticReads(e){return t({method:"GET",path:"/analytics/reads",query:{day:e.day}})},platformAnalyticEventSummaries(e,n){return b(()=>t({method:"POST",path:"/analytics/events/summaries",query:{accountId:e.accountId},body:n}),{paginatedExecutor:s=>{let u=n,m=s.skip!==void 0||s.nextPageToken||s.nextToken?{...u||{},options:{...u?.options||{},...s.skip!==void 0?{skip:s.skip}:{}},...s.nextPageToken?{nextPageToken:s.nextPageToken}:{},...s.nextToken?{nextToken:s.nextToken}:{}}:n;return t({method:"POST",path:"/analytics/events/summaries",query:{accountId:e.accountId},body:m})},autoPaginate:r})},exportSolution(e){return t({method:"GET",path:`/solutions/${e.solutionId}`})},updateSolution(e,n){return t({method:"PUT",path:`/solutions/${e.solutionId}`,body:n})},createSolution(e){return t({method:"POST",path:"/solutions",body:e})},exportSolutionToRecord(e){return t({method:"GET",path:`/solutions/${e.solutionId}/torecord`,query:{tableId:e.tableId,fieldId:e.fieldId}})},createSolutionFromRecord(e){return t({method:"GET",path:"/solutions/fromrecord",query:{tableId:e.tableId,fieldId:e.fieldId,recordId:e.recordId}})},updateSolutionToRecord(e){return t({method:"GET",path:`/solutions/${e.solutionId}/fromrecord`,query:{tableId:e.tableId,fieldId:e.fieldId,recordId:e.recordId}})},changesetSolution(e,n){return t({method:"PUT",path:`/solutions/${e.solutionId}/changeset`,body:n})},changesetSolutionFromRecord(e){return t({method:"GET",path:`/solutions/${e.solutionId}/changeset/fromrecord`,query:{tableId:e.tableId,fieldId:e.fieldId,recordId:e.recordId}})},generateDocument(e){return t({method:"GET",path:`/docTemplates/${e.templateId}/generate`,query:{tableId:e.tableId,recordId:e.recordId,filename:e.filename,format:e.format,margin:e.margin,unit:e.unit,pageSize:e.pageSize,orientation:e.orientation,realm:e.realm}})}}}function ce(t){let r=Q(t),e=j(r.debug),n={realm:r.realm,baseUrl:r.baseUrl,fetchApi:r.fetchApi,logger:e},o=_(r.auth,n),a=K(r.proactiveThrottle),s=H({config:r,auth:o,throttle:a,logger:e});return{...W(s.execute,r.autoPaginate),request:s.execute,getConfig:()=>r}}var Ct=ce;export{f as AuthenticationError,v as AuthorizationError,q as NoOpThrottle,C as NotFoundError,h as QuickbaseError,y as RateLimitError,x as ServerError,G as SlidingWindowThrottle,w as SsoTokenStrategy,E as TempTokenStrategy,S as TicketStrategy,k as TimeoutError,A as UserTokenStrategy,U as ValidationError,W as createApiMethods,_ as createAuthStrategy,ce as createClient,Ct as default};
|
|
7
11
|
//# sourceMappingURL=quickbase.esm.js.map
|