netsuite-sdk 0.1.32 → 0.1.33

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/dist/index.js CHANGED
@@ -1,1823 +1,512 @@
1
1
  'use strict';
2
2
 
3
+ var axios = require('axios');
4
+ var http = require('http');
5
+ var https = require('https');
6
+ var OAuthModule = require('oauth-1.0a');
3
7
  var crypto = require('crypto');
4
8
 
5
- var __create = Object.create;
6
- var __defProp = Object.defineProperty;
7
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
8
- var __getOwnPropNames = Object.getOwnPropertyNames;
9
- var __getProtoOf = Object.getPrototypeOf;
10
- var __hasOwnProp = Object.prototype.hasOwnProperty;
11
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
12
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
13
- }) : x)(function(x) {
14
- if (typeof require !== "undefined") return require.apply(this, arguments);
15
- throw Error('Dynamic require of "' + x + '" is not supported');
16
- });
17
- var __commonJS = (cb, mod) => function __require2() {
18
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
19
- };
20
- var __copyProps = (to, from, except, desc) => {
21
- if (from && typeof from === "object" || typeof from === "function") {
22
- for (let key of __getOwnPropNames(from))
23
- if (!__hasOwnProp.call(to, key) && key !== except)
24
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
9
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
+
11
+ function _interopNamespace(e) {
12
+ if (e && e.__esModule) return e;
13
+ var n = Object.create(null);
14
+ if (e) {
15
+ Object.keys(e).forEach(function (k) {
16
+ if (k !== 'default') {
17
+ var d = Object.getOwnPropertyDescriptor(e, k);
18
+ Object.defineProperty(n, k, d.get ? d : {
19
+ enumerable: true,
20
+ get: function () { return e[k]; }
21
+ });
22
+ }
23
+ });
25
24
  }
26
- return to;
27
- };
28
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
29
- // If the importer is in node compatibility mode or this is not an ESM
30
- // file that has been converted to a CommonJS file using a Babel-
31
- // compatible transform (i.e. "__esModule" has not been set), then set
32
- // "default" to the CommonJS "module.exports" for node compatibility.
33
- !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
34
- mod
35
- ));
25
+ n.default = e;
26
+ return Object.freeze(n);
27
+ }
36
28
 
37
- // src/transport/oauth.js
38
- var require_oauth = __commonJS({
39
- "src/transport/oauth.js"(exports$1) {
40
- Object.defineProperty(exports$1, "__esModule", { value: true });
41
- exports$1.createOAuthSigner = createOAuthSigner;
42
- var oauth_1_0a_1 = __require("oauth-1.0a");
43
- var node_crypto_1 = __require("crypto");
44
- function createOAuthSigner(config) {
45
- var oauth = new oauth_1_0a_1.default({
46
- consumer: { key: config.consumerKey, secret: config.consumerSecret },
47
- signature_method: "HMAC-SHA256",
48
- hash_function: function(baseString, key) {
49
- return (0, node_crypto_1.createHmac)("sha256", key).update(baseString).digest("base64");
50
- },
51
- realm: config.realm
52
- });
53
- var token = { key: config.tokenKey, secret: config.tokenSecret };
54
- return function(url, method) {
55
- var requestData = { url, method };
56
- var authorization = oauth.authorize(requestData, token);
57
- return oauth.toHeader(authorization);
58
- };
29
+ var axios__default = /*#__PURE__*/_interopDefault(axios);
30
+ var http__default = /*#__PURE__*/_interopDefault(http);
31
+ var https__default = /*#__PURE__*/_interopDefault(https);
32
+ var OAuthModule__namespace = /*#__PURE__*/_interopNamespace(OAuthModule);
33
+
34
+ // src/transport/http-transport.ts
35
+ var OAuth = OAuthModule__namespace.default || OAuthModule__namespace;
36
+ function createOAuthSigner(config) {
37
+ const oauth = new OAuth({
38
+ consumer: { key: config.consumerKey, secret: config.consumerSecret },
39
+ signature_method: "HMAC-SHA256",
40
+ hash_function: (baseString, key) => crypto.createHmac("sha256", key).update(baseString).digest("base64"),
41
+ realm: config.realm
42
+ });
43
+ const token = { key: config.tokenKey, secret: config.tokenSecret };
44
+ return (url, method) => {
45
+ const requestData = { url, method };
46
+ const authorization = oauth.authorize(requestData, token);
47
+ return oauth.toHeader(authorization);
48
+ };
49
+ }
50
+
51
+ // src/types/errors.ts
52
+ var NetSuiteError = class _NetSuiteError extends Error {
53
+ status;
54
+ code;
55
+ details;
56
+ requestUrl;
57
+ requestMethod;
58
+ constructor(message, status, code, details, requestUrl, requestMethod) {
59
+ super(message);
60
+ this.name = "NetSuiteError";
61
+ this.status = status;
62
+ this.code = code;
63
+ this.details = details;
64
+ this.requestUrl = requestUrl;
65
+ this.requestMethod = requestMethod;
66
+ if (Error.captureStackTrace) {
67
+ Error.captureStackTrace(this, _NetSuiteError);
59
68
  }
60
69
  }
61
- });
62
-
63
- // src/types/errors.js
64
- var require_errors = __commonJS({
65
- "src/types/errors.js"(exports$1) {
66
- var __extends = exports$1 && exports$1.__extends || /* @__PURE__ */ (function() {
67
- var extendStatics = function(d, b) {
68
- extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function(d2, b2) {
69
- d2.__proto__ = b2;
70
- } || function(d2, b2) {
71
- for (var p in b2) if (Object.prototype.hasOwnProperty.call(b2, p)) d2[p] = b2[p];
72
- };
73
- return extendStatics(d, b);
74
- };
75
- return function(d, b) {
76
- if (typeof b !== "function" && b !== null)
77
- throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
78
- extendStatics(d, b);
79
- function __() {
80
- this.constructor = d;
81
- }
82
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
83
- };
84
- })();
85
- Object.defineProperty(exports$1, "__esModule", { value: true });
86
- exports$1.NetSuiteError = void 0;
87
- var NetSuiteError2 = (
88
- /** @class */
89
- (function(_super) {
90
- __extends(NetSuiteError3, _super);
91
- function NetSuiteError3(message, status, code, details, requestUrl, requestMethod) {
92
- var _this = _super.call(this, message) || this;
93
- _this.name = "NetSuiteError";
94
- _this.status = status;
95
- _this.code = code;
96
- _this.details = details;
97
- _this.requestUrl = requestUrl;
98
- _this.requestMethod = requestMethod;
99
- if (Error.captureStackTrace) {
100
- Error.captureStackTrace(_this, NetSuiteError3);
101
- }
102
- return _this;
103
- }
104
- Object.defineProperty(NetSuiteError3.prototype, "isRetryable", {
105
- /** Whether this is a retryable error (5xx, timeout, network) */
106
- get: function() {
107
- return this.status >= 500 || this.code === "TIMEOUT" || this.code === "NETWORK_ERROR";
108
- },
109
- enumerable: false,
110
- configurable: true
111
- });
112
- Object.defineProperty(NetSuiteError3.prototype, "isAuthError", {
113
- /** Whether this is an auth error (401, 403) */
114
- get: function() {
115
- return this.status === 401 || this.status === 403;
116
- },
117
- enumerable: false,
118
- configurable: true
119
- });
120
- NetSuiteError3.isNetSuiteError = function(error) {
121
- return error instanceof NetSuiteError3;
122
- };
123
- return NetSuiteError3;
124
- })(Error)
125
- );
126
- exports$1.NetSuiteError = NetSuiteError2;
70
+ /** Whether this is a retryable error (5xx, timeout, network) */
71
+ get isRetryable() {
72
+ return this.status >= 500 || this.code === "TIMEOUT" || this.code === "NETWORK_ERROR";
73
+ }
74
+ /** Whether this is an auth error (401, 403) */
75
+ get isAuthError() {
76
+ return this.status === 401 || this.status === 403;
77
+ }
78
+ static isNetSuiteError(error) {
79
+ return error instanceof _NetSuiteError;
127
80
  }
128
- });
81
+ };
129
82
 
130
- // src/transport/retry.js
131
- var require_retry = __commonJS({
132
- "src/transport/retry.js"(exports$1) {
133
- var __assign = exports$1 && exports$1.__assign || function() {
134
- __assign = Object.assign || function(t) {
135
- for (var s, i = 1, n = arguments.length; i < n; i++) {
136
- s = arguments[i];
137
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
138
- t[p] = s[p];
139
- }
140
- return t;
141
- };
142
- return __assign.apply(this, arguments);
143
- };
144
- var __awaiter = exports$1 && exports$1.__awaiter || function(thisArg, _arguments, P, generator) {
145
- function adopt(value) {
146
- return value instanceof P ? value : new P(function(resolve) {
147
- resolve(value);
148
- });
149
- }
150
- return new (P || (P = Promise))(function(resolve, reject) {
151
- function fulfilled(value) {
152
- try {
153
- step(generator.next(value));
154
- } catch (e) {
155
- reject(e);
156
- }
157
- }
158
- function rejected(value) {
159
- try {
160
- step(generator["throw"](value));
161
- } catch (e) {
162
- reject(e);
163
- }
164
- }
165
- function step(result) {
166
- result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
167
- }
168
- step((generator = generator.apply(thisArg, _arguments || [])).next());
169
- });
170
- };
171
- var __generator = exports$1 && exports$1.__generator || function(thisArg, body) {
172
- var _ = { label: 0, sent: function() {
173
- if (t[0] & 1) throw t[1];
174
- return t[1];
175
- }, trys: [], ops: [] }, f, y, t, g;
176
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() {
177
- return this;
178
- }), g;
179
- function verb(n) {
180
- return function(v) {
181
- return step([n, v]);
182
- };
183
- }
184
- function step(op) {
185
- if (f) throw new TypeError("Generator is already executing.");
186
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
187
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
188
- if (y = 0, t) op = [op[0] & 2, t.value];
189
- switch (op[0]) {
190
- case 0:
191
- case 1:
192
- t = op;
193
- break;
194
- case 4:
195
- _.label++;
196
- return { value: op[1], done: false };
197
- case 5:
198
- _.label++;
199
- y = op[1];
200
- op = [0];
201
- continue;
202
- case 7:
203
- op = _.ops.pop();
204
- _.trys.pop();
205
- continue;
206
- default:
207
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
208
- _ = 0;
209
- continue;
210
- }
211
- if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
212
- _.label = op[1];
213
- break;
214
- }
215
- if (op[0] === 6 && _.label < t[1]) {
216
- _.label = t[1];
217
- t = op;
218
- break;
219
- }
220
- if (t && _.label < t[2]) {
221
- _.label = t[2];
222
- _.ops.push(op);
223
- break;
224
- }
225
- if (t[2]) _.ops.pop();
226
- _.trys.pop();
227
- continue;
228
- }
229
- op = body.call(thisArg, _);
230
- } catch (e) {
231
- op = [6, e];
232
- y = 0;
233
- } finally {
234
- f = t = 0;
235
- }
236
- if (op[0] & 5) throw op[1];
237
- return { value: op[0] ? op[1] : void 0, done: true };
238
- }
239
- };
240
- Object.defineProperty(exports$1, "__esModule", { value: true });
241
- exports$1.withRetry = withRetry;
242
- var errors_js_1 = require_errors();
243
- var DEFAULT_RETRY_CONFIG = {
244
- maxRetries: 3,
245
- initialDelay: 1e3,
246
- maxDelay: 3e4,
247
- backoffFactor: 2,
248
- shouldRetry: function(error) {
249
- if (error instanceof errors_js_1.NetSuiteError) {
250
- return error.isRetryable;
251
- }
252
- return true;
253
- }
254
- };
255
- function withRetry(fn_1) {
256
- return __awaiter(this, arguments, void 0, function(fn, config) {
257
- var opts, _loop_1, attempt, state_1;
258
- var _a;
259
- if (config === void 0) {
260
- config = {};
261
- }
262
- return __generator(this, function(_b) {
263
- switch (_b.label) {
264
- case 0:
265
- opts = __assign(__assign({}, DEFAULT_RETRY_CONFIG), config);
266
- _loop_1 = function(attempt2) {
267
- var _c, error_1, isLastAttempt, delay_1, jitter_1;
268
- return __generator(this, function(_d) {
269
- switch (_d.label) {
270
- case 0:
271
- _d.trys.push([0, 2, , 4]);
272
- _c = {};
273
- return [4, fn()];
274
- case 1:
275
- return [2, (_c.value = _d.sent(), _c)];
276
- case 2:
277
- error_1 = _d.sent();
278
- isLastAttempt = attempt2 === opts.maxRetries;
279
- if (isLastAttempt || !opts.shouldRetry(error_1, attempt2)) {
280
- throw error_1;
281
- }
282
- (_a = opts.onRetry) === null || _a === void 0 ? void 0 : _a.call(opts, error_1, attempt2 + 1);
283
- delay_1 = Math.min(opts.initialDelay * Math.pow(opts.backoffFactor, attempt2), opts.maxDelay);
284
- jitter_1 = delay_1 * 0.25 * (Math.random() * 2 - 1);
285
- return [4, new Promise(function(resolve) {
286
- return setTimeout(resolve, delay_1 + jitter_1);
287
- })];
288
- case 3:
289
- _d.sent();
290
- return [3, 4];
291
- case 4:
292
- return [
293
- 2
294
- /*return*/
295
- ];
296
- }
297
- });
298
- };
299
- attempt = 0;
300
- _b.label = 1;
301
- case 1:
302
- if (!(attempt <= opts.maxRetries)) return [3, 4];
303
- return [5, _loop_1(attempt)];
304
- case 2:
305
- state_1 = _b.sent();
306
- if (typeof state_1 === "object")
307
- return [2, state_1.value];
308
- _b.label = 3;
309
- case 3:
310
- attempt++;
311
- return [3, 1];
312
- case 4:
313
- throw new Error("Retry loop exited unexpectedly");
314
- }
315
- });
316
- });
83
+ // src/transport/retry.ts
84
+ var DEFAULT_RETRY_CONFIG = {
85
+ maxRetries: 3,
86
+ initialDelay: 1e3,
87
+ maxDelay: 3e4,
88
+ backoffFactor: 2,
89
+ shouldRetry: (error) => {
90
+ if (error instanceof NetSuiteError) {
91
+ return error.isRetryable;
317
92
  }
93
+ return true;
318
94
  }
319
- });
320
-
321
- // src/transport/middleware-chain.js
322
- var require_middleware_chain = __commonJS({
323
- "src/transport/middleware-chain.js"(exports$1) {
324
- Object.defineProperty(exports$1, "__esModule", { value: true });
325
- exports$1.executeMiddlewareChain = executeMiddlewareChain;
326
- function executeMiddlewareChain(middlewares, context, finalHandler) {
327
- var index = 0;
328
- function next() {
329
- if (index >= middlewares.length) {
330
- return finalHandler();
331
- }
332
- var middleware = middlewares[index++];
333
- return middleware(context, next);
95
+ };
96
+ async function withRetry(fn, config = {}) {
97
+ const opts = { ...DEFAULT_RETRY_CONFIG, ...config };
98
+ for (let attempt = 0; attempt <= opts.maxRetries; attempt++) {
99
+ try {
100
+ return await fn();
101
+ } catch (error) {
102
+ const isLastAttempt = attempt === opts.maxRetries;
103
+ if (isLastAttempt || !opts.shouldRetry(error, attempt)) {
104
+ throw error;
334
105
  }
335
- return next();
106
+ opts.onRetry?.(error, attempt + 1);
107
+ const delay = Math.min(
108
+ opts.initialDelay * Math.pow(opts.backoffFactor, attempt),
109
+ opts.maxDelay
110
+ );
111
+ const jitter = delay * 0.25 * (Math.random() * 2 - 1);
112
+ await new Promise((resolve) => setTimeout(resolve, delay + jitter));
336
113
  }
337
114
  }
338
- });
115
+ throw new Error("Retry loop exited unexpectedly");
116
+ }
339
117
 
340
- // src/types/http.js
341
- var require_http = __commonJS({
342
- "src/types/http.js"(exports$1) {
343
- Object.defineProperty(exports$1, "__esModule", { value: true });
344
- exports$1.extractHeaders = extractHeaders;
345
- function extractHeaders(response) {
346
- var headers = {};
347
- if (response.headers) {
348
- for (var _i = 0, _a = Object.entries(response.headers); _i < _a.length; _i++) {
349
- var _b = _a[_i], key = _b[0], value = _b[1];
350
- if (typeof value === "string") {
351
- headers[key] = value;
352
- }
353
- }
354
- }
355
- return headers;
118
+ // src/transport/middleware-chain.ts
119
+ function executeMiddlewareChain(middlewares, context, finalHandler) {
120
+ let index = 0;
121
+ function next() {
122
+ if (index >= middlewares.length) {
123
+ return finalHandler();
356
124
  }
125
+ const middleware = middlewares[index++];
126
+ return middleware(context, next);
357
127
  }
358
- });
128
+ return next();
129
+ }
359
130
 
360
- // src/transport/http-transport.js
361
- var require_http_transport = __commonJS({
362
- "src/transport/http-transport.js"(exports$1) {
363
- var __assign = exports$1 && exports$1.__assign || function() {
364
- __assign = Object.assign || function(t) {
365
- for (var s, i = 1, n = arguments.length; i < n; i++) {
366
- s = arguments[i];
367
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
368
- t[p] = s[p];
369
- }
370
- return t;
371
- };
372
- return __assign.apply(this, arguments);
373
- };
374
- var __awaiter = exports$1 && exports$1.__awaiter || function(thisArg, _arguments, P, generator) {
375
- function adopt(value) {
376
- return value instanceof P ? value : new P(function(resolve) {
377
- resolve(value);
378
- });
379
- }
380
- return new (P || (P = Promise))(function(resolve, reject) {
381
- function fulfilled(value) {
382
- try {
383
- step(generator.next(value));
384
- } catch (e) {
385
- reject(e);
386
- }
387
- }
388
- function rejected(value) {
389
- try {
390
- step(generator["throw"](value));
391
- } catch (e) {
392
- reject(e);
393
- }
394
- }
395
- function step(result) {
396
- result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
397
- }
398
- step((generator = generator.apply(thisArg, _arguments || [])).next());
399
- });
400
- };
401
- var __generator = exports$1 && exports$1.__generator || function(thisArg, body) {
402
- var _ = { label: 0, sent: function() {
403
- if (t[0] & 1) throw t[1];
404
- return t[1];
405
- }, trys: [], ops: [] }, f, y, t, g;
406
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() {
407
- return this;
408
- }), g;
409
- function verb(n) {
410
- return function(v) {
411
- return step([n, v]);
412
- };
413
- }
414
- function step(op) {
415
- if (f) throw new TypeError("Generator is already executing.");
416
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
417
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
418
- if (y = 0, t) op = [op[0] & 2, t.value];
419
- switch (op[0]) {
420
- case 0:
421
- case 1:
422
- t = op;
423
- break;
424
- case 4:
425
- _.label++;
426
- return { value: op[1], done: false };
427
- case 5:
428
- _.label++;
429
- y = op[1];
430
- op = [0];
431
- continue;
432
- case 7:
433
- op = _.ops.pop();
434
- _.trys.pop();
435
- continue;
436
- default:
437
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
438
- _ = 0;
439
- continue;
440
- }
441
- if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
442
- _.label = op[1];
443
- break;
444
- }
445
- if (op[0] === 6 && _.label < t[1]) {
446
- _.label = t[1];
447
- t = op;
448
- break;
449
- }
450
- if (t && _.label < t[2]) {
451
- _.label = t[2];
452
- _.ops.push(op);
453
- break;
454
- }
455
- if (t[2]) _.ops.pop();
456
- _.trys.pop();
457
- continue;
458
- }
459
- op = body.call(thisArg, _);
460
- } catch (e) {
461
- op = [6, e];
462
- y = 0;
463
- } finally {
464
- f = t = 0;
465
- }
466
- if (op[0] & 5) throw op[1];
467
- return { value: op[0] ? op[1] : void 0, done: true };
131
+ // src/types/http.ts
132
+ function extractHeaders(response) {
133
+ const headers = {};
134
+ if (response.headers) {
135
+ for (const [key, value] of Object.entries(response.headers)) {
136
+ if (typeof value === "string") {
137
+ headers[key] = value;
468
138
  }
469
- };
470
- Object.defineProperty(exports$1, "__esModule", { value: true });
471
- exports$1.HttpTransport = void 0;
472
- var axios_1 = __require("axios");
473
- var node_http_1 = __require("http");
474
- var node_https_1 = __require("https");
475
- var oauth_js_1 = require_oauth();
476
- var retry_js_1 = require_retry();
477
- var middleware_chain_js_1 = require_middleware_chain();
478
- var errors_js_1 = require_errors();
479
- var http_js_1 = require_http();
480
- var HttpTransport = (
481
- /** @class */
482
- (function() {
483
- function HttpTransport2(config) {
484
- var _a, _b, _c, _d;
485
- this.middlewares = [];
486
- this.config = {
487
- timeout: (_a = config.timeout) !== null && _a !== void 0 ? _a : 3e4,
488
- maxRetries: (_b = config.maxRetries) !== null && _b !== void 0 ? _b : 3,
489
- retryDelay: (_c = config.retryDelay) !== null && _c !== void 0 ? _c : 1e3,
490
- defaultHeaders: (_d = config.defaultHeaders) !== null && _d !== void 0 ? _d : {},
491
- logger: config.logger
492
- };
493
- this.sign = (0, oauth_js_1.createOAuthSigner)(config.auth);
494
- this.axiosInstance = axios_1.default.create({
495
- timeout: this.config.timeout,
496
- headers: {
497
- "Content-Type": "application/json",
498
- "Accept-Encoding": "gzip, deflate"
499
- },
500
- httpAgent: new node_http_1.default.Agent({ keepAlive: true }),
501
- httpsAgent: new node_https_1.default.Agent({ keepAlive: true }),
502
- maxRedirects: 5,
503
- // Let us handle all status codes in our error handling
504
- validateStatus: function() {
505
- return true;
506
- }
507
- });
508
- }
509
- HttpTransport2.prototype.use = function(middleware) {
510
- this.middlewares.push(middleware);
511
- return this;
512
- };
513
- HttpTransport2.prototype.request = function(url_1) {
514
- return __awaiter(this, arguments, void 0, function(url, options) {
515
- var method, timeout, maxRetries;
516
- var _this = this;
517
- var _a, _b, _c;
518
- if (options === void 0) {
519
- options = {};
520
- }
521
- return __generator(this, function(_d) {
522
- method = (_a = options.method) !== null && _a !== void 0 ? _a : "GET";
523
- timeout = (_b = options.timeout) !== null && _b !== void 0 ? _b : this.config.timeout;
524
- maxRetries = (_c = options.maxRetries) !== null && _c !== void 0 ? _c : this.config.maxRetries;
525
- return [2, (0, retry_js_1.withRetry)(function() {
526
- return __awaiter(_this, void 0, void 0, function() {
527
- var authHeaders, headers, context, response;
528
- var _this2 = this;
529
- return __generator(this, function(_a2) {
530
- switch (_a2.label) {
531
- case 0:
532
- authHeaders = this.sign(url, method);
533
- headers = __assign(__assign(__assign({ "Content-Type": "application/json" }, this.config.defaultHeaders), authHeaders), options.headers);
534
- context = {
535
- url,
536
- method,
537
- headers,
538
- body: options.body,
539
- metadata: {}
540
- };
541
- return [4, (0, middleware_chain_js_1.executeMiddlewareChain)(this.middlewares, context, function() {
542
- return _this2.executeRequest(context, timeout);
543
- })];
544
- case 1:
545
- response = _a2.sent();
546
- return [2, {
547
- data: response.body,
548
- status: response.status,
549
- headers: response.headers,
550
- duration: response.duration
551
- }];
552
- }
553
- });
554
- });
555
- }, {
556
- maxRetries,
557
- initialDelay: this.config.retryDelay,
558
- shouldRetry: function(error) {
559
- if (error instanceof errors_js_1.NetSuiteError) {
560
- return error.isRetryable;
561
- }
562
- return true;
563
- },
564
- onRetry: function(error, attempt) {
565
- var _a2;
566
- (_a2 = _this.config.logger) === null || _a2 === void 0 ? void 0 : _a2.warn("Retry attempt ".concat(attempt, "/").concat(maxRetries), {
567
- url,
568
- method,
569
- error
570
- });
571
- }
572
- })];
573
- });
574
- });
575
- };
576
- HttpTransport2.prototype.executeRequest = function(context, timeout) {
577
- return __awaiter(this, void 0, void 0, function() {
578
- var startTime, response, duration, errorBody, message, code, error_1, duration, axiosError;
579
- var _a, _b, _c, _d, _e, _f, _g, _h;
580
- return __generator(this, function(_j) {
581
- switch (_j.label) {
582
- case 0:
583
- startTime = performance.now();
584
- _j.label = 1;
585
- case 1:
586
- _j.trys.push([1, 3, , 4]);
587
- (_a = this.config.logger) === null || _a === void 0 ? void 0 : _a.debug("".concat(context.method, " ").concat(context.url), {
588
- headers: Object.keys(context.headers)
589
- });
590
- return [4, this.axiosInstance.request({
591
- url: context.url,
592
- method: context.method,
593
- headers: context.headers,
594
- data: context.body && ["POST", "PUT", "PATCH"].includes(context.method) ? context.body : void 0,
595
- timeout
596
- })];
597
- case 2:
598
- response = _j.sent();
599
- duration = Math.round(performance.now() - startTime);
600
- (_b = this.config.logger) === null || _b === void 0 ? void 0 : _b.info("".concat(context.method, " ").concat(context.url, " \u2192 ").concat(response.status), {
601
- duration
602
- });
603
- if (response.status >= 400) {
604
- errorBody = (_c = response.data) !== null && _c !== void 0 ? _c : {};
605
- message = (_f = (_e = (_d = errorBody.detail) !== null && _d !== void 0 ? _d : errorBody.title) !== null && _e !== void 0 ? _e : errorBody.message) !== null && _f !== void 0 ? _f : "HTTP ".concat(response.status);
606
- code = (_h = (_g = errorBody["o:errorCode"]) !== null && _g !== void 0 ? _g : errorBody.code) !== null && _h !== void 0 ? _h : "HTTP_".concat(response.status);
607
- throw new errors_js_1.NetSuiteError(message, response.status, code, errorBody, context.url, context.method);
608
- }
609
- return [2, {
610
- status: response.status,
611
- headers: (0, http_js_1.extractHeaders)(response),
612
- body: response.status === 204 ? void 0 : response.data,
613
- duration
614
- }];
615
- case 3:
616
- error_1 = _j.sent();
617
- if (error_1 instanceof errors_js_1.NetSuiteError) {
618
- throw error_1;
619
- }
620
- duration = Math.round(performance.now() - startTime);
621
- axiosError = error_1;
622
- if (axiosError.code === "ECONNABORTED" || axiosError.code === "ERR_CANCELED") {
623
- throw new errors_js_1.NetSuiteError("Request timed out after ".concat(timeout, "ms"), 504, "TIMEOUT", void 0, context.url, context.method);
624
- }
625
- throw new errors_js_1.NetSuiteError(axiosError.message || "Network error", 0, "NETWORK_ERROR", void 0, context.url, context.method);
626
- case 4:
627
- return [
628
- 2
629
- /*return*/
630
- ];
631
- }
632
- });
633
- });
634
- };
635
- return HttpTransport2;
636
- })()
637
- );
638
- exports$1.HttpTransport = HttpTransport;
139
+ }
639
140
  }
640
- });
141
+ return headers;
142
+ }
641
143
 
642
- // src/suiteql/suiteql-client.js
643
- var require_suiteql_client = __commonJS({
644
- "src/suiteql/suiteql-client.js"(exports$1) {
645
- var __assign = exports$1 && exports$1.__assign || function() {
646
- __assign = Object.assign || function(t) {
647
- for (var s, i = 1, n = arguments.length; i < n; i++) {
648
- s = arguments[i];
649
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
650
- t[p] = s[p];
651
- }
652
- return t;
653
- };
654
- return __assign.apply(this, arguments);
655
- };
656
- var __awaiter = exports$1 && exports$1.__awaiter || function(thisArg, _arguments, P, generator) {
657
- function adopt(value) {
658
- return value instanceof P ? value : new P(function(resolve) {
659
- resolve(value);
660
- });
661
- }
662
- return new (P || (P = Promise))(function(resolve, reject) {
663
- function fulfilled(value) {
664
- try {
665
- step(generator.next(value));
666
- } catch (e) {
667
- reject(e);
668
- }
669
- }
670
- function rejected(value) {
671
- try {
672
- step(generator["throw"](value));
673
- } catch (e) {
674
- reject(e);
675
- }
676
- }
677
- function step(result) {
678
- result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
679
- }
680
- step((generator = generator.apply(thisArg, _arguments || [])).next());
681
- });
682
- };
683
- var __generator = exports$1 && exports$1.__generator || function(thisArg, body) {
684
- var _ = { label: 0, sent: function() {
685
- if (t[0] & 1) throw t[1];
686
- return t[1];
687
- }, trys: [], ops: [] }, f, y, t, g;
688
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() {
689
- return this;
690
- }), g;
691
- function verb(n) {
692
- return function(v) {
693
- return step([n, v]);
694
- };
695
- }
696
- function step(op) {
697
- if (f) throw new TypeError("Generator is already executing.");
698
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
699
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
700
- if (y = 0, t) op = [op[0] & 2, t.value];
701
- switch (op[0]) {
702
- case 0:
703
- case 1:
704
- t = op;
705
- break;
706
- case 4:
707
- _.label++;
708
- return { value: op[1], done: false };
709
- case 5:
710
- _.label++;
711
- y = op[1];
712
- op = [0];
713
- continue;
714
- case 7:
715
- op = _.ops.pop();
716
- _.trys.pop();
717
- continue;
718
- default:
719
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
720
- _ = 0;
721
- continue;
722
- }
723
- if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
724
- _.label = op[1];
725
- break;
726
- }
727
- if (op[0] === 6 && _.label < t[1]) {
728
- _.label = t[1];
729
- t = op;
730
- break;
731
- }
732
- if (t && _.label < t[2]) {
733
- _.label = t[2];
734
- _.ops.push(op);
735
- break;
736
- }
737
- if (t[2]) _.ops.pop();
738
- _.trys.pop();
739
- continue;
740
- }
741
- op = body.call(thisArg, _);
742
- } catch (e) {
743
- op = [6, e];
744
- y = 0;
745
- } finally {
746
- f = t = 0;
747
- }
748
- if (op[0] & 5) throw op[1];
749
- return { value: op[0] ? op[1] : void 0, done: true };
750
- }
751
- };
752
- var __await = exports$1 && exports$1.__await || function(v) {
753
- return this instanceof __await ? (this.v = v, this) : new __await(v);
754
- };
755
- var __asyncGenerator = exports$1 && exports$1.__asyncGenerator || function(thisArg, _arguments, generator) {
756
- if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
757
- var g = generator.apply(thisArg, _arguments || []), i, q = [];
758
- return i = {}, verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function() {
759
- return this;
760
- }, i;
761
- function awaitReturn(f) {
762
- return function(v) {
763
- return Promise.resolve(v).then(f, reject);
764
- };
765
- }
766
- function verb(n, f) {
767
- if (g[n]) {
768
- i[n] = function(v) {
769
- return new Promise(function(a, b) {
770
- q.push([n, v, a, b]) > 1 || resume(n, v);
771
- });
772
- };
773
- if (f) i[n] = f(i[n]);
774
- }
775
- }
776
- function resume(n, v) {
777
- try {
778
- step(g[n](v));
779
- } catch (e) {
780
- settle(q[0][3], e);
781
- }
782
- }
783
- function step(r) {
784
- r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r);
785
- }
786
- function fulfill(value) {
787
- resume("next", value);
788
- }
789
- function reject(value) {
790
- resume("throw", value);
791
- }
792
- function settle(f, v) {
793
- if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]);
794
- }
144
+ // src/transport/http-transport.ts
145
+ var HttpTransport = class {
146
+ sign;
147
+ axiosInstance;
148
+ middlewares = [];
149
+ config;
150
+ constructor(config) {
151
+ this.config = {
152
+ timeout: config.timeout ?? 3e4,
153
+ maxRetries: config.maxRetries ?? 3,
154
+ retryDelay: config.retryDelay ?? 1e3,
155
+ defaultHeaders: config.defaultHeaders ?? {},
156
+ logger: config.logger
795
157
  };
796
- Object.defineProperty(exports$1, "__esModule", { value: true });
797
- exports$1.SuiteQLClient = void 0;
798
- var SuiteQLClient = (
799
- /** @class */
800
- (function() {
801
- function SuiteQLClient2(transport, accountId) {
802
- this.transport = transport;
803
- var normalizedId = accountId.toLowerCase().replace(/_/g, "-");
804
- this.baseUrl = "https://".concat(normalizedId, ".suitetalk.api.netsuite.com/services/rest/query/v1/suiteql");
805
- }
806
- SuiteQLClient2.prototype.query = function(sql_1) {
807
- return __awaiter(this, arguments, void 0, function(sql, options) {
808
- var _a, pageSize, _b, startOffset, _c, maxRows, timeout, allItems, currentOffset, totalResults, pagesFetched, startTime, effectiveLimit, url, response, page, hasMore;
809
- if (options === void 0) {
810
- options = {};
811
- }
812
- return __generator(this, function(_d) {
813
- switch (_d.label) {
814
- case 0:
815
- _a = options.pageSize, pageSize = _a === void 0 ? 1e3 : _a, _b = options.offset, startOffset = _b === void 0 ? 0 : _b, _c = options.maxRows, maxRows = _c === void 0 ? Infinity : _c, timeout = options.timeout;
816
- allItems = [];
817
- currentOffset = startOffset;
818
- totalResults = 0;
819
- pagesFetched = 0;
820
- startTime = performance.now();
821
- _d.label = 1;
822
- case 1:
823
- effectiveLimit = Math.min(pageSize, maxRows - allItems.length);
824
- if (effectiveLimit <= 0)
825
- return [3, 3];
826
- url = "".concat(this.baseUrl, "?limit=").concat(effectiveLimit, "&offset=").concat(currentOffset);
827
- return [4, this.transport.request(url, {
828
- method: "POST",
829
- body: { q: sql },
830
- headers: { Prefer: "transient" },
831
- timeout
832
- })];
833
- case 2:
834
- response = _d.sent();
835
- page = response.data;
836
- totalResults = page.totalResults;
837
- pagesFetched++;
838
- allItems.push.apply(allItems, page.items);
839
- hasMore = page.hasMore || currentOffset + page.items.length < totalResults;
840
- if (!hasMore || allItems.length >= maxRows || page.items.length === 0)
841
- return [3, 3];
842
- currentOffset += page.items.length;
843
- return [3, 1];
844
- case 3:
845
- return [2, {
846
- items: allItems,
847
- totalResults,
848
- pagesFetched,
849
- hasMore: allItems.length < totalResults,
850
- duration: Math.round(performance.now() - startTime)
851
- }];
852
- }
853
- });
854
- });
855
- };
856
- SuiteQLClient2.prototype.queryOne = function(sql, options) {
857
- return __awaiter(this, void 0, void 0, function() {
858
- var result;
859
- var _a;
860
- return __generator(this, function(_b) {
861
- switch (_b.label) {
862
- case 0:
863
- return [4, this.query(sql, __assign(__assign({}, options), { maxRows: 1 }))];
864
- case 1:
865
- result = _b.sent();
866
- return [2, (_a = result.items[0]) !== null && _a !== void 0 ? _a : null];
867
- }
868
- });
869
- });
870
- };
871
- SuiteQLClient2.prototype.queryPages = function(sql_1) {
872
- return __asyncGenerator(this, arguments, function queryPages_1(sql, options) {
873
- var _a, pageSize, _b, startOffset, _c, maxRows, timeout, currentOffset, totalYielded, effectiveLimit, url, response, page, hasMore;
874
- if (options === void 0) {
875
- options = {};
876
- }
877
- return __generator(this, function(_d) {
878
- switch (_d.label) {
879
- case 0:
880
- _a = options.pageSize, pageSize = _a === void 0 ? 1e3 : _a, _b = options.offset, startOffset = _b === void 0 ? 0 : _b, _c = options.maxRows, maxRows = _c === void 0 ? Infinity : _c, timeout = options.timeout;
881
- currentOffset = startOffset;
882
- totalYielded = 0;
883
- _d.label = 1;
884
- case 1:
885
- effectiveLimit = Math.min(pageSize, maxRows - totalYielded);
886
- if (!(effectiveLimit <= 0)) return [3, 3];
887
- return [4, __await(void 0)];
888
- case 2:
889
- return [2, _d.sent()];
890
- case 3:
891
- url = "".concat(this.baseUrl, "?limit=").concat(effectiveLimit, "&offset=").concat(currentOffset);
892
- return [4, __await(this.transport.request(url, {
893
- method: "POST",
894
- body: { q: sql },
895
- headers: { Prefer: "transient" },
896
- timeout
897
- }))];
898
- case 4:
899
- response = _d.sent();
900
- page = response.data;
901
- if (!(page.items.length === 0)) return [3, 6];
902
- return [4, __await(void 0)];
903
- case 5:
904
- return [2, _d.sent()];
905
- case 6:
906
- return [4, __await(page.items)];
907
- case 7:
908
- return [4, _d.sent()];
909
- case 8:
910
- _d.sent();
911
- totalYielded += page.items.length;
912
- hasMore = page.hasMore || currentOffset + page.items.length < page.totalResults;
913
- if (!(!hasMore || totalYielded >= maxRows)) return [3, 10];
914
- return [4, __await(void 0)];
915
- case 9:
916
- return [2, _d.sent()];
917
- case 10:
918
- currentOffset += page.items.length;
919
- return [3, 1];
920
- case 11:
921
- return [
922
- 2
923
- /*return*/
924
- ];
925
- }
926
- });
927
- });
928
- };
929
- return SuiteQLClient2;
930
- })()
931
- );
932
- exports$1.SuiteQLClient = SuiteQLClient;
158
+ this.sign = createOAuthSigner(config.auth);
159
+ this.axiosInstance = axios__default.default.create({
160
+ timeout: this.config.timeout,
161
+ headers: {
162
+ "Content-Type": "application/json",
163
+ "Accept-Encoding": "gzip, deflate"
164
+ },
165
+ httpAgent: new http__default.default.Agent({ keepAlive: true }),
166
+ httpsAgent: new https__default.default.Agent({ keepAlive: true }),
167
+ maxRedirects: 5,
168
+ // Let us handle all status codes in our error handling
169
+ validateStatus: () => true
170
+ });
933
171
  }
934
- });
935
-
936
- // src/records/record-client.js
937
- var require_record_client = __commonJS({
938
- "src/records/record-client.js"(exports$1) {
939
- var __awaiter = exports$1 && exports$1.__awaiter || function(thisArg, _arguments, P, generator) {
940
- function adopt(value) {
941
- return value instanceof P ? value : new P(function(resolve) {
942
- resolve(value);
943
- });
944
- }
945
- return new (P || (P = Promise))(function(resolve, reject) {
946
- function fulfilled(value) {
947
- try {
948
- step(generator.next(value));
949
- } catch (e) {
950
- reject(e);
951
- }
952
- }
953
- function rejected(value) {
954
- try {
955
- step(generator["throw"](value));
956
- } catch (e) {
957
- reject(e);
958
- }
959
- }
960
- function step(result) {
961
- result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
962
- }
963
- step((generator = generator.apply(thisArg, _arguments || [])).next());
964
- });
965
- };
966
- var __generator = exports$1 && exports$1.__generator || function(thisArg, body) {
967
- var _ = { label: 0, sent: function() {
968
- if (t[0] & 1) throw t[1];
969
- return t[1];
970
- }, trys: [], ops: [] }, f, y, t, g;
971
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() {
972
- return this;
973
- }), g;
974
- function verb(n) {
975
- return function(v) {
976
- return step([n, v]);
977
- };
978
- }
979
- function step(op) {
980
- if (f) throw new TypeError("Generator is already executing.");
981
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
982
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
983
- if (y = 0, t) op = [op[0] & 2, t.value];
984
- switch (op[0]) {
985
- case 0:
986
- case 1:
987
- t = op;
988
- break;
989
- case 4:
990
- _.label++;
991
- return { value: op[1], done: false };
992
- case 5:
993
- _.label++;
994
- y = op[1];
995
- op = [0];
996
- continue;
997
- case 7:
998
- op = _.ops.pop();
999
- _.trys.pop();
1000
- continue;
1001
- default:
1002
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
1003
- _ = 0;
1004
- continue;
1005
- }
1006
- if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
1007
- _.label = op[1];
1008
- break;
1009
- }
1010
- if (op[0] === 6 && _.label < t[1]) {
1011
- _.label = t[1];
1012
- t = op;
1013
- break;
1014
- }
1015
- if (t && _.label < t[2]) {
1016
- _.label = t[2];
1017
- _.ops.push(op);
1018
- break;
1019
- }
1020
- if (t[2]) _.ops.pop();
1021
- _.trys.pop();
1022
- continue;
1023
- }
1024
- op = body.call(thisArg, _);
1025
- } catch (e) {
1026
- op = [6, e];
1027
- y = 0;
1028
- } finally {
1029
- f = t = 0;
1030
- }
1031
- if (op[0] & 5) throw op[1];
1032
- return { value: op[0] ? op[1] : void 0, done: true };
1033
- }
1034
- };
1035
- Object.defineProperty(exports$1, "__esModule", { value: true });
1036
- exports$1.RecordClient = void 0;
1037
- var RecordClient = (
1038
- /** @class */
1039
- (function() {
1040
- function RecordClient2(transport, accountId) {
1041
- this.transport = transport;
1042
- var normalizedId = accountId.toLowerCase().replace(/_/g, "-");
1043
- this.baseUrl = "https://".concat(normalizedId, ".suitetalk.api.netsuite.com/services/rest/record/v1");
1044
- }
1045
- RecordClient2.prototype.get = function(recordType, id, options) {
1046
- return __awaiter(this, void 0, void 0, function() {
1047
- var params, qs, url;
1048
- var _a;
1049
- return __generator(this, function(_b) {
1050
- params = new URLSearchParams();
1051
- if ((_a = options === null || options === void 0 ? void 0 : options.fields) === null || _a === void 0 ? void 0 : _a.length) {
1052
- params.set("fields", options.fields.join(","));
1053
- }
1054
- if (options === null || options === void 0 ? void 0 : options.expandSubResources) {
1055
- params.set("expandSubResources", "true");
1056
- }
1057
- qs = params.toString();
1058
- url = "".concat(this.baseUrl, "/").concat(recordType, "/").concat(id).concat(qs ? "?".concat(qs) : "");
1059
- return [2, this.transport.request(url)];
1060
- });
1061
- });
1062
- };
1063
- RecordClient2.prototype.list = function(recordType, options) {
1064
- return __awaiter(this, void 0, void 0, function() {
1065
- var params, _i, _a, _b, key, value, qs, url;
1066
- var _c;
1067
- return __generator(this, function(_d) {
1068
- params = new URLSearchParams();
1069
- if ((options === null || options === void 0 ? void 0 : options.limit) != null)
1070
- params.set("limit", String(options.limit));
1071
- if ((options === null || options === void 0 ? void 0 : options.offset) != null)
1072
- params.set("offset", String(options.offset));
1073
- if ((_c = options === null || options === void 0 ? void 0 : options.fields) === null || _c === void 0 ? void 0 : _c.length)
1074
- params.set("fields", options.fields.join(","));
1075
- if (options === null || options === void 0 ? void 0 : options.expandSubResources)
1076
- params.set("expandSubResources", "true");
1077
- if (options === null || options === void 0 ? void 0 : options.query) {
1078
- for (_i = 0, _a = Object.entries(options.query); _i < _a.length; _i++) {
1079
- _b = _a[_i], key = _b[0], value = _b[1];
1080
- params.set(key, value);
1081
- }
1082
- }
1083
- qs = params.toString();
1084
- url = "".concat(this.baseUrl, "/").concat(recordType).concat(qs ? "?".concat(qs) : "");
1085
- return [2, this.transport.request(url)];
1086
- });
1087
- });
1088
- };
1089
- RecordClient2.prototype.create = function(recordType, body) {
1090
- return __awaiter(this, void 0, void 0, function() {
1091
- return __generator(this, function(_a) {
1092
- return [2, this.transport.request("".concat(this.baseUrl, "/").concat(recordType), {
1093
- method: "POST",
1094
- body
1095
- })];
1096
- });
1097
- });
1098
- };
1099
- RecordClient2.prototype.update = function(recordType, id, body) {
1100
- return __awaiter(this, void 0, void 0, function() {
1101
- return __generator(this, function(_a) {
1102
- return [2, this.transport.request("".concat(this.baseUrl, "/").concat(recordType, "/").concat(id), {
1103
- method: "PATCH",
1104
- body
1105
- })];
1106
- });
1107
- });
1108
- };
1109
- RecordClient2.prototype.replace = function(recordType, id, body) {
1110
- return __awaiter(this, void 0, void 0, function() {
1111
- return __generator(this, function(_a) {
1112
- return [2, this.transport.request("".concat(this.baseUrl, "/").concat(recordType, "/").concat(id), {
1113
- method: "PUT",
1114
- body
1115
- })];
1116
- });
1117
- });
1118
- };
1119
- RecordClient2.prototype.delete = function(recordType, id) {
1120
- return __awaiter(this, void 0, void 0, function() {
1121
- return __generator(this, function(_a) {
1122
- return [2, this.transport.request("".concat(this.baseUrl, "/").concat(recordType, "/").concat(id), {
1123
- method: "DELETE"
1124
- })];
1125
- });
1126
- });
172
+ /** Add a middleware to the chain. Returns `this` for chaining. */
173
+ use(middleware) {
174
+ this.middlewares.push(middleware);
175
+ return this;
176
+ }
177
+ /** Execute an HTTP request with OAuth signing, retry, and middleware. */
178
+ async request(url, options = {}) {
179
+ const method = options.method ?? "GET";
180
+ const timeout = options.timeout ?? this.config.timeout;
181
+ const maxRetries = options.maxRetries ?? this.config.maxRetries;
182
+ return withRetry(
183
+ async () => {
184
+ const authHeaders = this.sign(url, method);
185
+ const headers = {
186
+ "Content-Type": "application/json",
187
+ ...this.config.defaultHeaders,
188
+ ...authHeaders,
189
+ ...options.headers
1127
190
  };
1128
- RecordClient2.prototype.upsert = function(recordType, externalIdField, externalIdValue, body) {
1129
- return __awaiter(this, void 0, void 0, function() {
1130
- return __generator(this, function(_a) {
1131
- return [2, this.transport.request("".concat(this.baseUrl, "/").concat(recordType, "/eid:").concat(externalIdField, "=").concat(externalIdValue), { method: "PUT", body })];
1132
- });
1133
- });
191
+ const context = {
192
+ url,
193
+ method,
194
+ headers,
195
+ body: options.body,
196
+ metadata: {}
1134
197
  };
1135
- return RecordClient2;
1136
- })()
1137
- );
1138
- exports$1.RecordClient = RecordClient;
1139
- }
1140
- });
1141
-
1142
- // src/restlets/restlet-client.js
1143
- var require_restlet_client = __commonJS({
1144
- "src/restlets/restlet-client.js"(exports$1) {
1145
- var __awaiter = exports$1 && exports$1.__awaiter || function(thisArg, _arguments, P, generator) {
1146
- function adopt(value) {
1147
- return value instanceof P ? value : new P(function(resolve) {
1148
- resolve(value);
1149
- });
1150
- }
1151
- return new (P || (P = Promise))(function(resolve, reject) {
1152
- function fulfilled(value) {
1153
- try {
1154
- step(generator.next(value));
1155
- } catch (e) {
1156
- reject(e);
1157
- }
1158
- }
1159
- function rejected(value) {
1160
- try {
1161
- step(generator["throw"](value));
1162
- } catch (e) {
1163
- reject(e);
1164
- }
1165
- }
1166
- function step(result) {
1167
- result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
1168
- }
1169
- step((generator = generator.apply(thisArg, _arguments || [])).next());
1170
- });
1171
- };
1172
- var __generator = exports$1 && exports$1.__generator || function(thisArg, body) {
1173
- var _ = { label: 0, sent: function() {
1174
- if (t[0] & 1) throw t[1];
1175
- return t[1];
1176
- }, trys: [], ops: [] }, f, y, t, g;
1177
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() {
1178
- return this;
1179
- }), g;
1180
- function verb(n) {
1181
- return function(v) {
1182
- return step([n, v]);
198
+ const response = await executeMiddlewareChain(
199
+ this.middlewares,
200
+ context,
201
+ () => this.executeRequest(context, timeout)
202
+ );
203
+ return {
204
+ data: response.body,
205
+ status: response.status,
206
+ headers: response.headers,
207
+ duration: response.duration
1183
208
  };
1184
- }
1185
- function step(op) {
1186
- if (f) throw new TypeError("Generator is already executing.");
1187
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
1188
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
1189
- if (y = 0, t) op = [op[0] & 2, t.value];
1190
- switch (op[0]) {
1191
- case 0:
1192
- case 1:
1193
- t = op;
1194
- break;
1195
- case 4:
1196
- _.label++;
1197
- return { value: op[1], done: false };
1198
- case 5:
1199
- _.label++;
1200
- y = op[1];
1201
- op = [0];
1202
- continue;
1203
- case 7:
1204
- op = _.ops.pop();
1205
- _.trys.pop();
1206
- continue;
1207
- default:
1208
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
1209
- _ = 0;
1210
- continue;
1211
- }
1212
- if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
1213
- _.label = op[1];
1214
- break;
1215
- }
1216
- if (op[0] === 6 && _.label < t[1]) {
1217
- _.label = t[1];
1218
- t = op;
1219
- break;
1220
- }
1221
- if (t && _.label < t[2]) {
1222
- _.label = t[2];
1223
- _.ops.push(op);
1224
- break;
1225
- }
1226
- if (t[2]) _.ops.pop();
1227
- _.trys.pop();
1228
- continue;
209
+ },
210
+ {
211
+ maxRetries,
212
+ initialDelay: this.config.retryDelay,
213
+ shouldRetry: (error) => {
214
+ if (error instanceof NetSuiteError) {
215
+ return error.isRetryable;
1229
216
  }
1230
- op = body.call(thisArg, _);
1231
- } catch (e) {
1232
- op = [6, e];
1233
- y = 0;
1234
- } finally {
1235
- f = t = 0;
217
+ return true;
218
+ },
219
+ onRetry: (error, attempt) => {
220
+ this.config.logger?.warn(`Retry attempt ${attempt}/${maxRetries}`, {
221
+ url,
222
+ method,
223
+ error
224
+ });
1236
225
  }
1237
- if (op[0] & 5) throw op[1];
1238
- return { value: op[0] ? op[1] : void 0, done: true };
1239
226
  }
1240
- };
1241
- Object.defineProperty(exports$1, "__esModule", { value: true });
1242
- exports$1.RestletClient = void 0;
1243
- var RestletClient = (
1244
- /** @class */
1245
- (function() {
1246
- function RestletClient2(transport, accountId) {
1247
- this.transport = transport;
1248
- var normalizedId = accountId.toLowerCase().replace(/_/g, "-");
1249
- this.baseUrl = "https://".concat(normalizedId, ".restlets.api.netsuite.com/app/site/hosting/restlet.nl");
1250
- }
1251
- RestletClient2.prototype.call = function(restlet, options) {
1252
- return __awaiter(this, void 0, void 0, function() {
1253
- var searchParams, _i, _a, _b, key, value, url;
1254
- return __generator(this, function(_c) {
1255
- searchParams = new URLSearchParams({
1256
- script: String(restlet.script),
1257
- deploy: String(restlet.deploy)
1258
- });
1259
- if (restlet.params) {
1260
- for (_i = 0, _a = Object.entries(restlet.params); _i < _a.length; _i++) {
1261
- _b = _a[_i], key = _b[0], value = _b[1];
1262
- searchParams.set(key, String(value));
1263
- }
1264
- }
1265
- url = "".concat(this.baseUrl, "?").concat(searchParams.toString());
1266
- return [2, this.transport.request(url, options)];
1267
- });
1268
- });
1269
- };
1270
- return RestletClient2;
1271
- })()
1272
227
  );
1273
- exports$1.RestletClient = RestletClient;
1274
228
  }
1275
- });
1276
-
1277
- // src/utils/validation.js
1278
- var require_validation = __commonJS({
1279
- "src/utils/validation.js"(exports$1) {
1280
- Object.defineProperty(exports$1, "__esModule", { value: true });
1281
- exports$1.validateConfig = validateConfig2;
1282
- function validateConfig2(config) {
1283
- var errors = [];
1284
- if (!config || typeof config !== "object") {
1285
- return ["Config must be a non-null object"];
229
+ async executeRequest(context, timeout) {
230
+ const startTime = performance.now();
231
+ try {
232
+ this.config.logger?.debug(`${context.method} ${context.url}`, {
233
+ headers: Object.keys(context.headers)
234
+ });
235
+ const response = await this.axiosInstance.request({
236
+ url: context.url,
237
+ method: context.method,
238
+ headers: context.headers,
239
+ data: context.body && ["POST", "PUT", "PATCH"].includes(context.method) ? context.body : void 0,
240
+ timeout
241
+ });
242
+ const duration = Math.round(performance.now() - startTime);
243
+ this.config.logger?.info(`${context.method} ${context.url} \u2192 ${response.status}`, {
244
+ duration
245
+ });
246
+ if (response.status >= 400) {
247
+ const errorBody = response.data ?? {};
248
+ const message = errorBody.detail ?? errorBody.title ?? errorBody.message ?? `HTTP ${response.status}`;
249
+ const code = errorBody["o:errorCode"] ?? errorBody.code ?? `HTTP_${response.status}`;
250
+ throw new NetSuiteError(
251
+ message,
252
+ response.status,
253
+ code,
254
+ errorBody,
255
+ context.url,
256
+ context.method
257
+ );
1286
258
  }
1287
- var c = config;
1288
- if (!c.auth || typeof c.auth !== "object") {
1289
- errors.push("auth is required and must be an object");
1290
- } else {
1291
- var auth = c.auth;
1292
- var requiredFields = ["consumerKey", "consumerSecret", "tokenKey", "tokenSecret", "realm"];
1293
- for (var _i = 0, requiredFields_1 = requiredFields; _i < requiredFields_1.length; _i++) {
1294
- var field = requiredFields_1[_i];
1295
- if (!auth[field] || typeof auth[field] !== "string") {
1296
- errors.push("auth.".concat(field, " is required and must be a non-empty string"));
1297
- }
1298
- }
259
+ return {
260
+ status: response.status,
261
+ headers: extractHeaders(response),
262
+ body: response.status === 204 ? void 0 : response.data,
263
+ duration
264
+ };
265
+ } catch (error) {
266
+ if (error instanceof NetSuiteError) {
267
+ throw error;
1299
268
  }
1300
- if (!c.accountId || typeof c.accountId !== "string") {
1301
- errors.push("accountId is required and must be a non-empty string");
269
+ Math.round(performance.now() - startTime);
270
+ const axiosError = error;
271
+ if (axiosError.code === "ECONNABORTED" || axiosError.code === "ERR_CANCELED") {
272
+ throw new NetSuiteError(
273
+ `Request timed out after ${timeout}ms`,
274
+ 504,
275
+ "TIMEOUT",
276
+ void 0,
277
+ context.url,
278
+ context.method
279
+ );
1302
280
  }
1303
- return errors;
281
+ throw new NetSuiteError(
282
+ axiosError.message || "Network error",
283
+ 0,
284
+ "NETWORK_ERROR",
285
+ void 0,
286
+ context.url,
287
+ context.method
288
+ );
1304
289
  }
1305
290
  }
1306
- });
291
+ };
1307
292
 
1308
- // src/client.js
1309
- var require_client = __commonJS({
1310
- "src/client.js"(exports$1) {
1311
- var __assign = exports$1 && exports$1.__assign || function() {
1312
- __assign = Object.assign || function(t) {
1313
- for (var s, i = 1, n = arguments.length; i < n; i++) {
1314
- s = arguments[i];
1315
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
1316
- t[p] = s[p];
1317
- }
1318
- return t;
1319
- };
1320
- return __assign.apply(this, arguments);
1321
- };
1322
- var __awaiter = exports$1 && exports$1.__awaiter || function(thisArg, _arguments, P, generator) {
1323
- function adopt(value) {
1324
- return value instanceof P ? value : new P(function(resolve) {
1325
- resolve(value);
1326
- });
1327
- }
1328
- return new (P || (P = Promise))(function(resolve, reject) {
1329
- function fulfilled(value) {
1330
- try {
1331
- step(generator.next(value));
1332
- } catch (e) {
1333
- reject(e);
1334
- }
1335
- }
1336
- function rejected(value) {
1337
- try {
1338
- step(generator["throw"](value));
1339
- } catch (e) {
1340
- reject(e);
1341
- }
1342
- }
1343
- function step(result) {
1344
- result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
1345
- }
1346
- step((generator = generator.apply(thisArg, _arguments || [])).next());
293
+ // src/suiteql/suiteql-client.ts
294
+ var SuiteQLClient = class {
295
+ transport;
296
+ baseUrl;
297
+ constructor(transport, accountId) {
298
+ this.transport = transport;
299
+ const normalizedId = accountId.toLowerCase().replace(/_/g, "-");
300
+ this.baseUrl = `https://${normalizedId}.suitetalk.api.netsuite.com/services/rest/query/v1/suiteql`;
301
+ }
302
+ /**
303
+ * Execute a SuiteQL query and return all matching rows.
304
+ * Automatically paginates across multiple pages.
305
+ *
306
+ * @example
307
+ * ```ts
308
+ * const result = await client.suiteql.query<Customer>(
309
+ * 'SELECT id, companyname, email FROM customer WHERE isinactive = \'F\'',
310
+ * { pageSize: 500 }
311
+ * );
312
+ * console.log(result.items); // all rows
313
+ * console.log(result.totalResults); // total count from NetSuite
314
+ * ```
315
+ */
316
+ async query(sql, options = {}) {
317
+ const {
318
+ pageSize = 1e3,
319
+ offset: startOffset = 0,
320
+ maxRows = Infinity,
321
+ timeout
322
+ } = options;
323
+ const allItems = [];
324
+ let currentOffset = startOffset;
325
+ let totalResults = 0;
326
+ let pagesFetched = 0;
327
+ const startTime = performance.now();
328
+ while (true) {
329
+ const effectiveLimit = Math.min(pageSize, maxRows - allItems.length);
330
+ if (effectiveLimit <= 0) break;
331
+ const url = `${this.baseUrl}?limit=${effectiveLimit}&offset=${currentOffset}`;
332
+ const response = await this.transport.request(url, {
333
+ method: "POST",
334
+ body: { q: sql },
335
+ headers: { Prefer: "transient" },
336
+ timeout
1347
337
  });
338
+ const page = response.data;
339
+ totalResults = page.totalResults;
340
+ pagesFetched++;
341
+ allItems.push(...page.items);
342
+ const hasMore = page.hasMore || currentOffset + page.items.length < totalResults;
343
+ if (!hasMore || allItems.length >= maxRows || page.items.length === 0) break;
344
+ currentOffset += page.items.length;
345
+ }
346
+ return {
347
+ items: allItems,
348
+ totalResults,
349
+ pagesFetched,
350
+ hasMore: allItems.length < totalResults,
351
+ duration: Math.round(performance.now() - startTime)
1348
352
  };
1349
- var __generator = exports$1 && exports$1.__generator || function(thisArg, body) {
1350
- var _ = { label: 0, sent: function() {
1351
- if (t[0] & 1) throw t[1];
1352
- return t[1];
1353
- }, trys: [], ops: [] }, f, y, t, g;
1354
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() {
1355
- return this;
1356
- }), g;
1357
- function verb(n) {
1358
- return function(v) {
1359
- return step([n, v]);
1360
- };
1361
- }
1362
- function step(op) {
1363
- if (f) throw new TypeError("Generator is already executing.");
1364
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
1365
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
1366
- if (y = 0, t) op = [op[0] & 2, t.value];
1367
- switch (op[0]) {
1368
- case 0:
1369
- case 1:
1370
- t = op;
1371
- break;
1372
- case 4:
1373
- _.label++;
1374
- return { value: op[1], done: false };
1375
- case 5:
1376
- _.label++;
1377
- y = op[1];
1378
- op = [0];
1379
- continue;
1380
- case 7:
1381
- op = _.ops.pop();
1382
- _.trys.pop();
1383
- continue;
1384
- default:
1385
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
1386
- _ = 0;
1387
- continue;
1388
- }
1389
- if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
1390
- _.label = op[1];
1391
- break;
1392
- }
1393
- if (op[0] === 6 && _.label < t[1]) {
1394
- _.label = t[1];
1395
- t = op;
1396
- break;
1397
- }
1398
- if (t && _.label < t[2]) {
1399
- _.label = t[2];
1400
- _.ops.push(op);
1401
- break;
1402
- }
1403
- if (t[2]) _.ops.pop();
1404
- _.trys.pop();
1405
- continue;
1406
- }
1407
- op = body.call(thisArg, _);
1408
- } catch (e) {
1409
- op = [6, e];
1410
- y = 0;
1411
- } finally {
1412
- f = t = 0;
1413
- }
1414
- if (op[0] & 5) throw op[1];
1415
- return { value: op[0] ? op[1] : void 0, done: true };
1416
- }
1417
- };
1418
- Object.defineProperty(exports$1, "__esModule", { value: true });
1419
- exports$1.NetSuiteClient = void 0;
1420
- var http_transport_js_1 = require_http_transport();
1421
- var suiteql_client_js_1 = require_suiteql_client();
1422
- var record_client_js_1 = require_record_client();
1423
- var restlet_client_js_1 = require_restlet_client();
1424
- var validation_js_1 = require_validation();
1425
- var NetSuiteClient2 = (
1426
- /** @class */
1427
- (function() {
1428
- function NetSuiteClient3(config) {
1429
- var errors = (0, validation_js_1.validateConfig)(config);
1430
- if (errors.length > 0) {
1431
- throw new Error("Invalid NetSuite configuration:\n - ".concat(errors.join("\n - ")));
1432
- }
1433
- this.transport = new http_transport_js_1.HttpTransport(config);
1434
- this.suiteql = new suiteql_client_js_1.SuiteQLClient(this.transport, config.accountId);
1435
- this.records = new record_client_js_1.RecordClient(this.transport, config.accountId);
1436
- this.restlets = new restlet_client_js_1.RestletClient(this.transport, config.accountId);
1437
- }
1438
- NetSuiteClient3.prototype.use = function(middleware) {
1439
- this.transport.use(middleware);
1440
- return this;
1441
- };
1442
- NetSuiteClient3.prototype.request = function(url, options) {
1443
- return __awaiter(this, void 0, void 0, function() {
1444
- return __generator(this, function(_a) {
1445
- return [2, this.transport.request(url, options)];
1446
- });
1447
- });
1448
- };
1449
- NetSuiteClient3.prototype.get = function(url, options) {
1450
- return __awaiter(this, void 0, void 0, function() {
1451
- return __generator(this, function(_a) {
1452
- return [2, this.transport.request(url, __assign(__assign({}, options), { method: "GET" }))];
1453
- });
1454
- });
1455
- };
1456
- NetSuiteClient3.prototype.post = function(url, body, options) {
1457
- return __awaiter(this, void 0, void 0, function() {
1458
- return __generator(this, function(_a) {
1459
- return [2, this.transport.request(url, __assign(__assign({}, options), { method: "POST", body }))];
1460
- });
1461
- });
1462
- };
1463
- NetSuiteClient3.prototype.put = function(url, body, options) {
1464
- return __awaiter(this, void 0, void 0, function() {
1465
- return __generator(this, function(_a) {
1466
- return [2, this.transport.request(url, __assign(__assign({}, options), { method: "PUT", body }))];
1467
- });
1468
- });
1469
- };
1470
- NetSuiteClient3.prototype.patch = function(url, body, options) {
1471
- return __awaiter(this, void 0, void 0, function() {
1472
- return __generator(this, function(_a) {
1473
- return [2, this.transport.request(url, __assign(__assign({}, options), { method: "PATCH", body }))];
1474
- });
1475
- });
1476
- };
1477
- NetSuiteClient3.prototype.delete = function(url, options) {
1478
- return __awaiter(this, void 0, void 0, function() {
1479
- return __generator(this, function(_a) {
1480
- return [2, this.transport.request(url, __assign(__assign({}, options), { method: "DELETE" }))];
1481
- });
1482
- });
1483
- };
1484
- return NetSuiteClient3;
1485
- })()
1486
- );
1487
- exports$1.NetSuiteClient = NetSuiteClient2;
1488
353
  }
1489
- });
1490
-
1491
- // src/suiteql/query-builder.js
1492
- var require_query_builder = __commonJS({
1493
- "src/suiteql/query-builder.js"(exports$1) {
1494
- Object.defineProperty(exports$1, "__esModule", { value: true });
1495
- exports$1.SuiteQLBuilder = void 0;
1496
- exports$1.suiteql = suiteql2;
1497
- var SuiteQLBuilder2 = (
1498
- /** @class */
1499
- (function() {
1500
- function SuiteQLBuilder3() {
1501
- this._select = [];
1502
- this._from = "";
1503
- this._joins = [];
1504
- this._where = [];
1505
- this._groupBy = [];
1506
- this._orderBy = [];
1507
- this._having = [];
1508
- }
1509
- SuiteQLBuilder3.prototype.select = function() {
1510
- var _a;
1511
- var columns = [];
1512
- for (var _i = 0; _i < arguments.length; _i++) {
1513
- columns[_i] = arguments[_i];
1514
- }
1515
- (_a = this._select).push.apply(_a, columns);
1516
- return this;
1517
- };
1518
- SuiteQLBuilder3.prototype.from = function(table, alias) {
1519
- this._from = alias ? "".concat(table, " ").concat(alias) : table;
1520
- return this;
1521
- };
1522
- SuiteQLBuilder3.prototype.join = function(table, condition, type) {
1523
- if (type === void 0) {
1524
- type = "INNER";
1525
- }
1526
- this._joins.push("".concat(type, " JOIN ").concat(table, " ON ").concat(condition));
1527
- return this;
1528
- };
1529
- SuiteQLBuilder3.prototype.leftJoin = function(table, condition) {
1530
- return this.join(table, condition, "LEFT");
1531
- };
1532
- SuiteQLBuilder3.prototype.rightJoin = function(table, condition) {
1533
- return this.join(table, condition, "RIGHT");
1534
- };
1535
- SuiteQLBuilder3.prototype.where = function(condition) {
1536
- this._where.push(condition);
1537
- return this;
1538
- };
1539
- SuiteQLBuilder3.prototype.whereEquals = function(column, value) {
1540
- this._where.push("".concat(column, " = ").concat(escapeValue(value)));
1541
- return this;
1542
- };
1543
- SuiteQLBuilder3.prototype.whereNotEquals = function(column, value) {
1544
- this._where.push("".concat(column, " != ").concat(escapeValue(value)));
1545
- return this;
1546
- };
1547
- SuiteQLBuilder3.prototype.whereIn = function(column, values) {
1548
- var escaped = values.map(escapeValue);
1549
- this._where.push("".concat(column, " IN (").concat(escaped.join(", "), ")"));
1550
- return this;
1551
- };
1552
- SuiteQLBuilder3.prototype.whereNull = function(column) {
1553
- this._where.push("".concat(column, " IS NULL"));
1554
- return this;
1555
- };
1556
- SuiteQLBuilder3.prototype.whereNotNull = function(column) {
1557
- this._where.push("".concat(column, " IS NOT NULL"));
1558
- return this;
1559
- };
1560
- SuiteQLBuilder3.prototype.whereBetween = function(column, start, end) {
1561
- this._where.push("".concat(column, " BETWEEN ").concat(escapeValue(start), " AND ").concat(escapeValue(end)));
1562
- return this;
1563
- };
1564
- SuiteQLBuilder3.prototype.whereLike = function(column, pattern) {
1565
- this._where.push("".concat(column, " LIKE ").concat(escapeValue(pattern)));
1566
- return this;
1567
- };
1568
- SuiteQLBuilder3.prototype.groupBy = function() {
1569
- var _a;
1570
- var columns = [];
1571
- for (var _i = 0; _i < arguments.length; _i++) {
1572
- columns[_i] = arguments[_i];
1573
- }
1574
- (_a = this._groupBy).push.apply(_a, columns);
1575
- return this;
1576
- };
1577
- SuiteQLBuilder3.prototype.having = function(condition) {
1578
- this._having.push(condition);
1579
- return this;
1580
- };
1581
- SuiteQLBuilder3.prototype.orderBy = function(column, direction) {
1582
- if (direction === void 0) {
1583
- direction = "ASC";
1584
- }
1585
- this._orderBy.push("".concat(column, " ").concat(direction));
1586
- return this;
1587
- };
1588
- SuiteQLBuilder3.prototype.build = function() {
1589
- if (this._select.length === 0) {
1590
- throw new Error("SuiteQLBuilder: SELECT clause is required");
1591
- }
1592
- if (!this._from) {
1593
- throw new Error("SuiteQLBuilder: FROM clause is required");
1594
- }
1595
- var parts = [
1596
- "SELECT ".concat(this._select.join(", ")),
1597
- "FROM ".concat(this._from)
1598
- ];
1599
- if (this._joins.length > 0) {
1600
- parts.push(this._joins.join(" "));
1601
- }
1602
- if (this._where.length > 0) {
1603
- parts.push("WHERE ".concat(this._where.join(" AND ")));
1604
- }
1605
- if (this._groupBy.length > 0) {
1606
- parts.push("GROUP BY ".concat(this._groupBy.join(", ")));
1607
- }
1608
- if (this._having.length > 0) {
1609
- parts.push("HAVING ".concat(this._having.join(" AND ")));
1610
- }
1611
- if (this._orderBy.length > 0) {
1612
- parts.push("ORDER BY ".concat(this._orderBy.join(", ")));
1613
- }
1614
- return parts.join(" ");
1615
- };
1616
- SuiteQLBuilder3.prototype.toString = function() {
1617
- return this.build();
1618
- };
1619
- return SuiteQLBuilder3;
1620
- })()
1621
- );
1622
- exports$1.SuiteQLBuilder = SuiteQLBuilder2;
1623
- function escapeValue(value) {
1624
- if (typeof value === "number") {
1625
- return String(value);
1626
- }
1627
- if (typeof value === "boolean") {
1628
- return value ? "'T'" : "'F'";
1629
- }
1630
- var escaped = value.replace(/'/g, "''");
1631
- return "'".concat(escaped, "'");
1632
- }
1633
- function suiteql2() {
1634
- return new SuiteQLBuilder2();
1635
- }
354
+ /**
355
+ * Execute a query and return a single row, or null if not found.
356
+ *
357
+ * @example
358
+ * ```ts
359
+ * const customer = await client.suiteql.queryOne<Customer>(
360
+ * 'SELECT id, companyname FROM customer WHERE id = 123'
361
+ * );
362
+ * ```
363
+ */
364
+ async queryOne(sql, options) {
365
+ const result = await this.query(sql, { ...options, maxRows: 1 });
366
+ return result.items[0] ?? null;
1636
367
  }
1637
- });
1638
-
1639
- // src/utils/response-cache.js
1640
- var require_response_cache = __commonJS({
1641
- "src/utils/response-cache.js"(exports$1) {
1642
- Object.defineProperty(exports$1, "__esModule", { value: true });
1643
- exports$1.ResponseCache = void 0;
1644
- exports$1.createCacheKey = createCacheKey2;
1645
- var ResponseCache2 = (
1646
- /** @class */
1647
- (function() {
1648
- function ResponseCache3() {
1649
- this.cache = /* @__PURE__ */ new Map();
1650
- }
1651
- ResponseCache3.prototype.get = function(key) {
1652
- var entry = this.cache.get(key);
1653
- if (!entry)
1654
- return null;
1655
- if (Date.now() > entry.expiresAt) {
1656
- this.cache.delete(key);
1657
- return null;
1658
- }
1659
- return entry.data;
1660
- };
1661
- ResponseCache3.prototype.set = function(key, data, ttlSeconds) {
1662
- this.cache.set(key, {
1663
- data,
1664
- expiresAt: Date.now() + ttlSeconds * 1e3
1665
- });
1666
- };
1667
- ResponseCache3.prototype.delete = function(key) {
1668
- return this.cache.delete(key);
1669
- };
1670
- ResponseCache3.prototype.clear = function() {
1671
- this.cache.clear();
1672
- };
1673
- Object.defineProperty(ResponseCache3.prototype, "size", {
1674
- /** Get the number of entries (including expired). */
1675
- get: function() {
1676
- return this.cache.size;
1677
- },
1678
- enumerable: false,
1679
- configurable: true
1680
- });
1681
- return ResponseCache3;
1682
- })()
1683
- );
1684
- exports$1.ResponseCache = ResponseCache2;
1685
- function createCacheKey2(url, method, params) {
1686
- var base = "".concat(method, ":").concat(url);
1687
- if (params) {
1688
- return "".concat(base, ":").concat(JSON.stringify(params));
1689
- }
1690
- return base;
368
+ /**
369
+ * Execute a query and yield pages as an async generator.
370
+ * Useful for streaming large result sets without holding everything in memory.
371
+ *
372
+ * @example
373
+ * ```ts
374
+ * for await (const page of client.suiteql.queryPages<Transaction>(
375
+ * 'SELECT id, tranid, total FROM transaction',
376
+ * { pageSize: 500 }
377
+ * )) {
378
+ * await processBatch(page);
379
+ * }
380
+ * ```
381
+ */
382
+ async *queryPages(sql, options = {}) {
383
+ const {
384
+ pageSize = 1e3,
385
+ offset: startOffset = 0,
386
+ maxRows = Infinity,
387
+ timeout
388
+ } = options;
389
+ let currentOffset = startOffset;
390
+ let totalYielded = 0;
391
+ while (true) {
392
+ const effectiveLimit = Math.min(pageSize, maxRows - totalYielded);
393
+ if (effectiveLimit <= 0) return;
394
+ const url = `${this.baseUrl}?limit=${effectiveLimit}&offset=${currentOffset}`;
395
+ const response = await this.transport.request(url, {
396
+ method: "POST",
397
+ body: { q: sql },
398
+ headers: { Prefer: "transient" },
399
+ timeout
400
+ });
401
+ const page = response.data;
402
+ if (page.items.length === 0) return;
403
+ yield page.items;
404
+ totalYielded += page.items.length;
405
+ const hasMore = page.hasMore || currentOffset + page.items.length < page.totalResults;
406
+ if (!hasMore || totalYielded >= maxRows) return;
407
+ currentOffset += page.items.length;
1691
408
  }
1692
409
  }
1693
- });
410
+ };
1694
411
 
1695
- // src/utils/rate-limiter.js
1696
- var require_rate_limiter = __commonJS({
1697
- "src/utils/rate-limiter.js"(exports$1) {
1698
- Object.defineProperty(exports$1, "__esModule", { value: true });
1699
- exports$1.RateLimiter = void 0;
1700
- var RateLimiter2 = (
1701
- /** @class */
1702
- (function() {
1703
- function RateLimiter3(maxRequests, windowMs) {
1704
- if (maxRequests === void 0) {
1705
- maxRequests = 100;
1706
- }
1707
- if (windowMs === void 0) {
1708
- windowMs = 6e4;
1709
- }
1710
- this.timestamps = [];
1711
- this.maxRequests = maxRequests;
1712
- this.windowMs = windowMs;
1713
- }
1714
- RateLimiter3.prototype.canMakeRequest = function() {
1715
- this.pruneExpired();
1716
- return this.timestamps.length < this.maxRequests;
1717
- };
1718
- RateLimiter3.prototype.recordRequest = function() {
1719
- this.pruneExpired();
1720
- this.timestamps.push(Date.now());
1721
- };
1722
- RateLimiter3.prototype.getRemainingRequests = function() {
1723
- this.pruneExpired();
1724
- return Math.max(0, this.maxRequests - this.timestamps.length);
1725
- };
1726
- RateLimiter3.prototype.getTimeUntilNextSlot = function() {
1727
- this.pruneExpired();
1728
- if (this.timestamps.length < this.maxRequests)
1729
- return 0;
1730
- var oldest = this.timestamps[0];
1731
- return Math.max(0, oldest + this.windowMs - Date.now());
1732
- };
1733
- RateLimiter3.prototype.pruneExpired = function() {
1734
- var cutoff = Date.now() - this.windowMs;
1735
- while (this.timestamps.length > 0 && this.timestamps[0] <= cutoff) {
1736
- this.timestamps.shift();
1737
- }
1738
- };
1739
- return RateLimiter3;
1740
- })()
1741
- );
1742
- exports$1.RateLimiter = RateLimiter2;
412
+ // src/records/record-client.ts
413
+ var RecordClient = class {
414
+ transport;
415
+ baseUrl;
416
+ constructor(transport, accountId) {
417
+ this.transport = transport;
418
+ const normalizedId = accountId.toLowerCase().replace(/_/g, "-");
419
+ this.baseUrl = `https://${normalizedId}.suitetalk.api.netsuite.com/services/rest/record/v1`;
1743
420
  }
1744
- });
1745
-
1746
- // src/utils/date.js
1747
- var require_date = __commonJS({
1748
- "src/utils/date.js"(exports$1) {
1749
- Object.defineProperty(exports$1, "__esModule", { value: true });
1750
- exports$1.formatNetSuiteDate = formatNetSuiteDate2;
1751
- exports$1.parseNetSuiteDate = parseNetSuiteDate2;
1752
- function formatNetSuiteDate2(date) {
1753
- var year = date.getFullYear();
1754
- var month = String(date.getMonth() + 1).padStart(2, "0");
1755
- var day = String(date.getDate()).padStart(2, "0");
1756
- return "".concat(year, "-").concat(month, "-").concat(day);
421
+ /** Get a record by type and internal ID */
422
+ async get(recordType, id, options) {
423
+ const params = new URLSearchParams();
424
+ if (options?.fields?.length) {
425
+ params.set("fields", options.fields.join(","));
1757
426
  }
1758
- function parseNetSuiteDate2(dateString) {
1759
- if (dateString.includes("/")) {
1760
- var _a = dateString.split("/"), month_1 = _a[0], day_1 = _a[1], year_1 = _a[2];
1761
- return new Date(Number(year_1), Number(month_1) - 1, Number(day_1));
1762
- }
1763
- var _b = dateString.split("-"), year = _b[0], month = _b[1], day = _b[2];
1764
- return new Date(Number(year), Number(month) - 1, Number(day));
427
+ if (options?.expandSubResources) {
428
+ params.set("expandSubResources", "true");
1765
429
  }
430
+ const qs = params.toString();
431
+ const url = `${this.baseUrl}/${recordType}/${id}${qs ? `?${qs}` : ""}`;
432
+ return this.transport.request(url);
1766
433
  }
1767
- });
1768
-
1769
- // src/utils/error-parser.js
1770
- var require_error_parser = __commonJS({
1771
- "src/utils/error-parser.js"(exports$1) {
1772
- Object.defineProperty(exports$1, "__esModule", { value: true });
1773
- exports$1.parseNetSuiteError = parseNetSuiteError2;
1774
- function parseNetSuiteError2(error) {
1775
- var _a, _b;
1776
- if (!error || typeof error !== "object") {
1777
- return { message: String(error) };
1778
- }
1779
- var e = error;
1780
- if (e.title || e.detail) {
1781
- return {
1782
- message: String((_b = (_a = e.detail) !== null && _a !== void 0 ? _a : e.title) !== null && _b !== void 0 ? _b : "Unknown error"),
1783
- code: e["o:errorCode"],
1784
- details: e
1785
- };
1786
- }
1787
- if (e.message) {
1788
- return {
1789
- message: String(e.message),
1790
- code: e.code
1791
- };
434
+ /** List records of a given type */
435
+ async list(recordType, options) {
436
+ const params = new URLSearchParams();
437
+ if (options?.limit != null) params.set("limit", String(options.limit));
438
+ if (options?.offset != null) params.set("offset", String(options.offset));
439
+ if (options?.fields?.length) params.set("fields", options.fields.join(","));
440
+ if (options?.expandSubResources) params.set("expandSubResources", "true");
441
+ if (options?.query) {
442
+ for (const [key, value] of Object.entries(options.query)) {
443
+ params.set(key, value);
1792
444
  }
1793
- return { message: JSON.stringify(error) };
1794
445
  }
446
+ const qs = params.toString();
447
+ const url = `${this.baseUrl}/${recordType}${qs ? `?${qs}` : ""}`;
448
+ return this.transport.request(url);
1795
449
  }
1796
- });
450
+ /** Create a new record */
451
+ async create(recordType, body) {
452
+ return this.transport.request(`${this.baseUrl}/${recordType}`, {
453
+ method: "POST",
454
+ body
455
+ });
456
+ }
457
+ /** Update an existing record (partial update via PATCH) */
458
+ async update(recordType, id, body) {
459
+ return this.transport.request(`${this.baseUrl}/${recordType}/${id}`, {
460
+ method: "PATCH",
461
+ body
462
+ });
463
+ }
464
+ /** Replace an existing record (full replace via PUT) */
465
+ async replace(recordType, id, body) {
466
+ return this.transport.request(`${this.baseUrl}/${recordType}/${id}`, {
467
+ method: "PUT",
468
+ body
469
+ });
470
+ }
471
+ /** Delete a record */
472
+ async delete(recordType, id) {
473
+ return this.transport.request(`${this.baseUrl}/${recordType}/${id}`, {
474
+ method: "DELETE"
475
+ });
476
+ }
477
+ /** Upsert: create or update based on external ID */
478
+ async upsert(recordType, externalIdField, externalIdValue, body) {
479
+ return this.transport.request(
480
+ `${this.baseUrl}/${recordType}/eid:${externalIdField}=${externalIdValue}`,
481
+ { method: "PUT", body }
482
+ );
483
+ }
484
+ };
1797
485
 
1798
- // src/utils/url-builder.js
1799
- var require_url_builder = __commonJS({
1800
- "src/utils/url-builder.js"(exports$1) {
1801
- Object.defineProperty(exports$1, "__esModule", { value: true });
1802
- exports$1.normalizeAccountId = normalizeAccountId2;
1803
- exports$1.buildSuiteTalkUrl = buildSuiteTalkUrl;
1804
- exports$1.buildRestletUrl = buildRestletUrl;
1805
- function normalizeAccountId2(accountId) {
1806
- return accountId.toLowerCase().replace(/_/g, "-");
1807
- }
1808
- function buildSuiteTalkUrl(accountId) {
1809
- return "https://".concat(normalizeAccountId2(accountId), ".suitetalk.api.netsuite.com");
1810
- }
1811
- function buildRestletUrl(accountId) {
1812
- return "https://".concat(normalizeAccountId2(accountId), ".restlets.api.netsuite.com");
486
+ // src/restlets/restlet-client.ts
487
+ var RestletClient = class {
488
+ transport;
489
+ baseUrl;
490
+ constructor(transport, accountId) {
491
+ this.transport = transport;
492
+ const normalizedId = accountId.toLowerCase().replace(/_/g, "-");
493
+ this.baseUrl = `https://${normalizedId}.restlets.api.netsuite.com/app/site/hosting/restlet.nl`;
494
+ }
495
+ /** Execute a RESTlet call */
496
+ async call(restlet, options) {
497
+ const searchParams = new URLSearchParams({
498
+ script: String(restlet.script),
499
+ deploy: String(restlet.deploy)
500
+ });
501
+ if (restlet.params) {
502
+ for (const [key, value] of Object.entries(restlet.params)) {
503
+ searchParams.set(key, String(value));
504
+ }
1813
505
  }
506
+ const url = `${this.baseUrl}?${searchParams.toString()}`;
507
+ return this.transport.request(url, options);
1814
508
  }
1815
- });
1816
-
1817
- // src/index.ts
1818
- var import_client = __toESM(require_client());
1819
- var import_query_builder = __toESM(require_query_builder());
1820
- var import_errors = __toESM(require_errors());
509
+ };
1821
510
  var SOAP_ONLY_FIELDS = {
1822
511
  assemblyItem: ["taxSchedule"],
1823
512
  inventoryItem: ["taxSchedule"],
@@ -1853,11 +542,13 @@ var NS_NAMESPACES = {
1853
542
  };
1854
543
  function extractSoapOnlyFields(recordType, body) {
1855
544
  const knownSoapFields = SOAP_ONLY_FIELDS[recordType] ?? [];
545
+ const knownLower = knownSoapFields.map((f) => f.toLowerCase());
1856
546
  const soapFields = {};
1857
547
  const restBody = {};
1858
548
  for (const [key, value] of Object.entries(body)) {
1859
- if (knownSoapFields.includes(key)) {
1860
- soapFields[key] = value;
549
+ const idx = knownLower.indexOf(key.toLowerCase());
550
+ if (idx !== -1) {
551
+ soapFields[knownSoapFields[idx]] = value;
1861
552
  } else {
1862
553
  restBody[key] = value;
1863
554
  }
@@ -2044,40 +735,357 @@ var SoapFieldClient = class {
2044
735
  }
2045
736
  };
2046
737
 
2047
- // src/index.ts
2048
- var import_response_cache = __toESM(require_response_cache());
2049
- var import_rate_limiter = __toESM(require_rate_limiter());
2050
- var import_validation = __toESM(require_validation());
2051
- var import_date = __toESM(require_date());
2052
- var import_error_parser = __toESM(require_error_parser());
2053
- var import_url_builder = __toESM(require_url_builder());
2054
- var export_NetSuiteClient = import_client.NetSuiteClient;
2055
- var export_NetSuiteError = import_errors.NetSuiteError;
2056
- var export_RateLimiter = import_rate_limiter.RateLimiter;
2057
- var export_ResponseCache = import_response_cache.ResponseCache;
2058
- var export_SuiteQLBuilder = import_query_builder.SuiteQLBuilder;
2059
- var export_createCacheKey = import_response_cache.createCacheKey;
2060
- var export_formatNetSuiteDate = import_date.formatNetSuiteDate;
2061
- var export_normalizeAccountId = import_url_builder.normalizeAccountId;
2062
- var export_parseNetSuiteDate = import_date.parseNetSuiteDate;
2063
- var export_parseNetSuiteError = import_error_parser.parseNetSuiteError;
2064
- var export_suiteql = import_query_builder.suiteql;
2065
- var export_validateConfig = import_validation.validateConfig;
738
+ // src/utils/validation.ts
739
+ function validateConfig(config) {
740
+ const errors = [];
741
+ if (!config || typeof config !== "object") {
742
+ return ["Config must be a non-null object"];
743
+ }
744
+ const c = config;
745
+ if (!c.auth || typeof c.auth !== "object") {
746
+ errors.push("auth is required and must be an object");
747
+ } else {
748
+ const auth = c.auth;
749
+ const requiredFields = ["consumerKey", "consumerSecret", "tokenKey", "tokenSecret", "realm"];
750
+ for (const field of requiredFields) {
751
+ if (!auth[field] || typeof auth[field] !== "string") {
752
+ errors.push(`auth.${field} is required and must be a non-empty string`);
753
+ }
754
+ }
755
+ }
756
+ if (!c.accountId || typeof c.accountId !== "string") {
757
+ errors.push("accountId is required and must be a non-empty string");
758
+ }
759
+ return errors;
760
+ }
761
+
762
+ // src/client.ts
763
+ var NetSuiteClient = class {
764
+ /** SuiteQL query execution and builder */
765
+ suiteql;
766
+ /** REST Record API CRUD */
767
+ records;
768
+ /** RESTlet caller */
769
+ restlets;
770
+ /** SOAP client for fields not available via REST API */
771
+ soap;
772
+ transport;
773
+ constructor(config) {
774
+ const errors = validateConfig(config);
775
+ if (errors.length > 0) {
776
+ throw new Error(`Invalid NetSuite configuration:
777
+ - ${errors.join("\n - ")}`);
778
+ }
779
+ this.transport = new HttpTransport(config);
780
+ this.suiteql = new SuiteQLClient(this.transport, config.accountId);
781
+ this.records = new RecordClient(this.transport, config.accountId);
782
+ this.restlets = new RestletClient(this.transport, config.accountId);
783
+ this.soap = new SoapFieldClient(config.auth, config.accountId);
784
+ }
785
+ /** Add middleware to all requests. Returns `this` for chaining. */
786
+ use(middleware) {
787
+ this.transport.use(middleware);
788
+ return this;
789
+ }
790
+ /** Make a raw HTTP request (escape hatch for custom endpoints). */
791
+ async request(url, options) {
792
+ return this.transport.request(url, options);
793
+ }
794
+ /** Convenience: GET request */
795
+ async get(url, options) {
796
+ return this.transport.request(url, { ...options, method: "GET" });
797
+ }
798
+ /** Convenience: POST request */
799
+ async post(url, body, options) {
800
+ return this.transport.request(url, { ...options, method: "POST", body });
801
+ }
802
+ /** Convenience: PUT request */
803
+ async put(url, body, options) {
804
+ return this.transport.request(url, { ...options, method: "PUT", body });
805
+ }
806
+ /** Convenience: PATCH request */
807
+ async patch(url, body, options) {
808
+ return this.transport.request(url, { ...options, method: "PATCH", body });
809
+ }
810
+ /** Convenience: DELETE request */
811
+ async delete(url, options) {
812
+ return this.transport.request(url, { ...options, method: "DELETE" });
813
+ }
814
+ };
815
+
816
+ // src/suiteql/query-builder.ts
817
+ var SuiteQLBuilder = class {
818
+ _select = [];
819
+ _from = "";
820
+ _joins = [];
821
+ _where = [];
822
+ _groupBy = [];
823
+ _orderBy = [];
824
+ _having = [];
825
+ /** Add columns to SELECT clause */
826
+ select(...columns) {
827
+ this._select.push(...columns);
828
+ return this;
829
+ }
830
+ /** Set the FROM table, with optional alias */
831
+ from(table, alias) {
832
+ this._from = alias ? `${table} ${alias}` : table;
833
+ return this;
834
+ }
835
+ /** Add a JOIN clause */
836
+ join(table, condition, type = "INNER") {
837
+ this._joins.push(`${type} JOIN ${table} ON ${condition}`);
838
+ return this;
839
+ }
840
+ /** Add a LEFT JOIN clause */
841
+ leftJoin(table, condition) {
842
+ return this.join(table, condition, "LEFT");
843
+ }
844
+ /** Add a RIGHT JOIN clause */
845
+ rightJoin(table, condition) {
846
+ return this.join(table, condition, "RIGHT");
847
+ }
848
+ /** Add a raw WHERE condition */
849
+ where(condition) {
850
+ this._where.push(condition);
851
+ return this;
852
+ }
853
+ /** Add a WHERE column = value condition. Values are escaped. */
854
+ whereEquals(column, value) {
855
+ this._where.push(`${column} = ${escapeValue(value)}`);
856
+ return this;
857
+ }
858
+ /** Add a WHERE column != value condition. Values are escaped. */
859
+ whereNotEquals(column, value) {
860
+ this._where.push(`${column} != ${escapeValue(value)}`);
861
+ return this;
862
+ }
863
+ /** Add a WHERE column IN (...) condition. Values are escaped. */
864
+ whereIn(column, values) {
865
+ const escaped = values.map(escapeValue);
866
+ this._where.push(`${column} IN (${escaped.join(", ")})`);
867
+ return this;
868
+ }
869
+ /** Add a WHERE column IS NULL condition */
870
+ whereNull(column) {
871
+ this._where.push(`${column} IS NULL`);
872
+ return this;
873
+ }
874
+ /** Add a WHERE column IS NOT NULL condition */
875
+ whereNotNull(column) {
876
+ this._where.push(`${column} IS NOT NULL`);
877
+ return this;
878
+ }
879
+ /** Add a WHERE column BETWEEN start AND end condition. Values are escaped. */
880
+ whereBetween(column, start, end) {
881
+ this._where.push(`${column} BETWEEN ${escapeValue(start)} AND ${escapeValue(end)}`);
882
+ return this;
883
+ }
884
+ /** Add a WHERE column LIKE pattern condition. Value is escaped. */
885
+ whereLike(column, pattern) {
886
+ this._where.push(`${column} LIKE ${escapeValue(pattern)}`);
887
+ return this;
888
+ }
889
+ /** Add columns to GROUP BY clause */
890
+ groupBy(...columns) {
891
+ this._groupBy.push(...columns);
892
+ return this;
893
+ }
894
+ /** Add a HAVING condition (used with GROUP BY) */
895
+ having(condition) {
896
+ this._having.push(condition);
897
+ return this;
898
+ }
899
+ /** Add a column to ORDER BY clause */
900
+ orderBy(column, direction = "ASC") {
901
+ this._orderBy.push(`${column} ${direction}`);
902
+ return this;
903
+ }
904
+ /** Build the SQL string. Throws if SELECT or FROM is missing. */
905
+ build() {
906
+ if (this._select.length === 0) {
907
+ throw new Error("SuiteQLBuilder: SELECT clause is required");
908
+ }
909
+ if (!this._from) {
910
+ throw new Error("SuiteQLBuilder: FROM clause is required");
911
+ }
912
+ const parts = [
913
+ `SELECT ${this._select.join(", ")}`,
914
+ `FROM ${this._from}`
915
+ ];
916
+ if (this._joins.length > 0) {
917
+ parts.push(this._joins.join(" "));
918
+ }
919
+ if (this._where.length > 0) {
920
+ parts.push(`WHERE ${this._where.join(" AND ")}`);
921
+ }
922
+ if (this._groupBy.length > 0) {
923
+ parts.push(`GROUP BY ${this._groupBy.join(", ")}`);
924
+ }
925
+ if (this._having.length > 0) {
926
+ parts.push(`HAVING ${this._having.join(" AND ")}`);
927
+ }
928
+ if (this._orderBy.length > 0) {
929
+ parts.push(`ORDER BY ${this._orderBy.join(", ")}`);
930
+ }
931
+ return parts.join(" ");
932
+ }
933
+ /** Alias for build() */
934
+ toString() {
935
+ return this.build();
936
+ }
937
+ };
938
+ function escapeValue(value) {
939
+ if (typeof value === "number") {
940
+ return String(value);
941
+ }
942
+ if (typeof value === "boolean") {
943
+ return value ? "'T'" : "'F'";
944
+ }
945
+ const escaped = value.replace(/'/g, "''");
946
+ return `'${escaped}'`;
947
+ }
948
+ function suiteql() {
949
+ return new SuiteQLBuilder();
950
+ }
951
+
952
+ // src/utils/response-cache.ts
953
+ var ResponseCache = class {
954
+ cache = /* @__PURE__ */ new Map();
955
+ /** Get a cached value, or null if not found or expired. */
956
+ get(key) {
957
+ const entry = this.cache.get(key);
958
+ if (!entry) return null;
959
+ if (Date.now() > entry.expiresAt) {
960
+ this.cache.delete(key);
961
+ return null;
962
+ }
963
+ return entry.data;
964
+ }
965
+ /** Set a cached value with a TTL in seconds. */
966
+ set(key, data, ttlSeconds) {
967
+ this.cache.set(key, {
968
+ data,
969
+ expiresAt: Date.now() + ttlSeconds * 1e3
970
+ });
971
+ }
972
+ /** Delete a specific cache entry. */
973
+ delete(key) {
974
+ return this.cache.delete(key);
975
+ }
976
+ /** Clear all cached entries. */
977
+ clear() {
978
+ this.cache.clear();
979
+ }
980
+ /** Get the number of entries (including expired). */
981
+ get size() {
982
+ return this.cache.size;
983
+ }
984
+ };
985
+ function createCacheKey(url, method, params) {
986
+ const base = `${method}:${url}`;
987
+ if (params) {
988
+ return `${base}:${JSON.stringify(params)}`;
989
+ }
990
+ return base;
991
+ }
992
+
993
+ // src/utils/rate-limiter.ts
994
+ var RateLimiter = class {
995
+ timestamps = [];
996
+ maxRequests;
997
+ windowMs;
998
+ constructor(maxRequests = 100, windowMs = 6e4) {
999
+ this.maxRequests = maxRequests;
1000
+ this.windowMs = windowMs;
1001
+ }
1002
+ /** Check if a request can be made without exceeding the limit. */
1003
+ canMakeRequest() {
1004
+ this.pruneExpired();
1005
+ return this.timestamps.length < this.maxRequests;
1006
+ }
1007
+ /** Record that a request was made. */
1008
+ recordRequest() {
1009
+ this.pruneExpired();
1010
+ this.timestamps.push(Date.now());
1011
+ }
1012
+ /** Get the number of remaining requests in the current window. */
1013
+ getRemainingRequests() {
1014
+ this.pruneExpired();
1015
+ return Math.max(0, this.maxRequests - this.timestamps.length);
1016
+ }
1017
+ /** Get ms until the next request slot opens. Returns 0 if a slot is available. */
1018
+ getTimeUntilNextSlot() {
1019
+ this.pruneExpired();
1020
+ if (this.timestamps.length < this.maxRequests) return 0;
1021
+ const oldest = this.timestamps[0];
1022
+ return Math.max(0, oldest + this.windowMs - Date.now());
1023
+ }
1024
+ pruneExpired() {
1025
+ const cutoff = Date.now() - this.windowMs;
1026
+ while (this.timestamps.length > 0 && this.timestamps[0] <= cutoff) {
1027
+ this.timestamps.shift();
1028
+ }
1029
+ }
1030
+ };
1031
+
1032
+ // src/utils/date.ts
1033
+ function formatNetSuiteDate(date) {
1034
+ const year = date.getFullYear();
1035
+ const month = String(date.getMonth() + 1).padStart(2, "0");
1036
+ const day = String(date.getDate()).padStart(2, "0");
1037
+ return `${year}-${month}-${day}`;
1038
+ }
1039
+ function parseNetSuiteDate(dateString) {
1040
+ if (dateString.includes("/")) {
1041
+ const [month2, day2, year2] = dateString.split("/");
1042
+ return new Date(Number(year2), Number(month2) - 1, Number(day2));
1043
+ }
1044
+ const [year, month, day] = dateString.split("-");
1045
+ return new Date(Number(year), Number(month) - 1, Number(day));
1046
+ }
1047
+
1048
+ // src/utils/error-parser.ts
1049
+ function parseNetSuiteError(error) {
1050
+ if (!error || typeof error !== "object") {
1051
+ return { message: String(error) };
1052
+ }
1053
+ const e = error;
1054
+ if (e.title || e.detail) {
1055
+ return {
1056
+ message: String(e.detail ?? e.title ?? "Unknown error"),
1057
+ code: e["o:errorCode"],
1058
+ details: e
1059
+ };
1060
+ }
1061
+ if (e.message) {
1062
+ return {
1063
+ message: String(e.message),
1064
+ code: e.code
1065
+ };
1066
+ }
1067
+ return { message: JSON.stringify(error) };
1068
+ }
1069
+
1070
+ // src/utils/url-builder.ts
1071
+ function normalizeAccountId(accountId) {
1072
+ return accountId.toLowerCase().replace(/_/g, "-");
1073
+ }
2066
1074
 
2067
- exports.NetSuiteClient = export_NetSuiteClient;
2068
- exports.NetSuiteError = export_NetSuiteError;
2069
- exports.RateLimiter = export_RateLimiter;
2070
- exports.ResponseCache = export_ResponseCache;
1075
+ exports.NetSuiteClient = NetSuiteClient;
1076
+ exports.NetSuiteError = NetSuiteError;
1077
+ exports.RateLimiter = RateLimiter;
1078
+ exports.ResponseCache = ResponseCache;
2071
1079
  exports.SOAP_ONLY_FIELDS = SOAP_ONLY_FIELDS;
2072
1080
  exports.SoapFieldClient = SoapFieldClient;
2073
- exports.SuiteQLBuilder = export_SuiteQLBuilder;
2074
- exports.createCacheKey = export_createCacheKey;
1081
+ exports.SuiteQLBuilder = SuiteQLBuilder;
1082
+ exports.createCacheKey = createCacheKey;
2075
1083
  exports.extractSoapOnlyFields = extractSoapOnlyFields;
2076
- exports.formatNetSuiteDate = export_formatNetSuiteDate;
2077
- exports.normalizeAccountId = export_normalizeAccountId;
2078
- exports.parseNetSuiteDate = export_parseNetSuiteDate;
2079
- exports.parseNetSuiteError = export_parseNetSuiteError;
2080
- exports.suiteql = export_suiteql;
2081
- exports.validateConfig = export_validateConfig;
1084
+ exports.formatNetSuiteDate = formatNetSuiteDate;
1085
+ exports.normalizeAccountId = normalizeAccountId;
1086
+ exports.parseNetSuiteDate = parseNetSuiteDate;
1087
+ exports.parseNetSuiteError = parseNetSuiteError;
1088
+ exports.suiteql = suiteql;
1089
+ exports.validateConfig = validateConfig;
2082
1090
  //# sourceMappingURL=index.js.map
2083
1091
  //# sourceMappingURL=index.js.map