@thorprovider/adapters 4.2.0 → 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/PROVIDER_IMPLEMENTATION_ANALYSIS.md +659 -0
- package/README.md +19 -0
- package/dist/index.d.mts +249 -2
- package/dist/index.d.ts +249 -2
- package/dist/index.js +1450 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1448 -2
- package/dist/index.mjs.map +1 -1
- package/docs/RETRY_SOLUTION_SUMMARY.md +26 -11
- package/docs/authentication.md +115 -62
- package/docs/capabilities-system.md +34 -2
- package/docs/category-customization.md +37 -29
- package/docs/fetch-reliability-solution.md +127 -278
- package/docs/getting-started.md +43 -29
- package/docs/profile-management.md +68 -38
- package/docs/providers-overview.md +14 -0
- package/docs/services-overview.md +20 -2
- package/package.json +10 -6
- package/quick-reference.md +34 -0
- package/src/factory/index.ts +4 -0
- package/src/index.ts +3 -0
- package/src/providers/index.ts +3 -0
- package/src/providers/medusa/admin.test.ts +404 -0
- package/src/providers/medusa/admin.ts +442 -0
- package/src/providers/medusa/auth.test.ts +137 -0
- package/src/providers/medusa/auth.ts +96 -1
- package/src/providers/medusa/index.ts +21 -1
- package/src/providers/shopify/auth.ts +6 -0
- package/src/providers/stelorder/client.test-helpers.ts +3 -0
- package/src/providers/stelorder/client.test.ts +58 -0
- package/src/providers/stelorder/client.ts +326 -0
- package/src/providers/stelorder/index.test.ts +48 -0
- package/src/providers/stelorder/index.ts +685 -0
- package/src/providers/stelorder/live-smoke.test.ts +54 -0
- package/src/providers/stelorder/transforms.test.ts +103 -0
- package/src/providers/stelorder/transforms.ts +631 -0
- package/src/resilience/README.md +70 -48
- package/src/types/capabilities.types.ts +51 -0
- package/vitest.config.ts +13 -0
- package/vitest.setup.ts +6 -0
- package/.turbo/turbo-build.log +0 -18
- package/dist/.tsbuildinfo +0 -1
- package/src/core/errors.js +0 -161
- package/src/core/fetch-utils.js +0 -240
- package/src/core/logger.js +0 -63
- package/src/metadata/channel-scope-validation.js +0 -136
- package/src/metadata/channel-scope.js +0 -174
- package/src/metadata/index.js +0 -31
- package/src/providers/medusa/auth.js +0 -601
- package/src/providers/medusa/index.js +0 -2485
- package/src/providers/medusa/payment.js +0 -265
- package/src/providers/medusa/transforms.js +0 -505
- package/src/types/capabilities.types.js +0 -141
- package/src/types/provider.js +0 -9
- package/src/utils/payment-utils.js +0 -152
package/src/core/errors.js
DELETED
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* @thorprovider/adapters v2.0
|
|
4
|
-
* Core errors
|
|
5
|
-
*/
|
|
6
|
-
var __extends = (this && this.__extends) || (function () {
|
|
7
|
-
var extendStatics = function (d, b) {
|
|
8
|
-
extendStatics = Object.setPrototypeOf ||
|
|
9
|
-
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
10
|
-
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
11
|
-
return extendStatics(d, b);
|
|
12
|
-
};
|
|
13
|
-
return function (d, b) {
|
|
14
|
-
if (typeof b !== "function" && b !== null)
|
|
15
|
-
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
16
|
-
extendStatics(d, b);
|
|
17
|
-
function __() { this.constructor = d; }
|
|
18
|
-
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
19
|
-
};
|
|
20
|
-
})();
|
|
21
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
-
exports.ProviderAPIError = exports.ResourceNotFoundError = exports.ConfigurationError = exports.ProviderNotFoundError = exports.CommerceError = void 0;
|
|
23
|
-
exports.extractErrorMessage = extractErrorMessage;
|
|
24
|
-
/**
|
|
25
|
-
* Base error class for commerce providers
|
|
26
|
-
*/
|
|
27
|
-
var CommerceError = /** @class */ (function (_super) {
|
|
28
|
-
__extends(CommerceError, _super);
|
|
29
|
-
function CommerceError(message, code, status) {
|
|
30
|
-
var _this = _super.call(this, message) || this;
|
|
31
|
-
_this.code = code;
|
|
32
|
-
_this.status = status;
|
|
33
|
-
_this.name = 'CommerceError';
|
|
34
|
-
return _this;
|
|
35
|
-
}
|
|
36
|
-
return CommerceError;
|
|
37
|
-
}(Error));
|
|
38
|
-
exports.CommerceError = CommerceError;
|
|
39
|
-
/**
|
|
40
|
-
* Provider not found error
|
|
41
|
-
*/
|
|
42
|
-
var ProviderNotFoundError = /** @class */ (function (_super) {
|
|
43
|
-
__extends(ProviderNotFoundError, _super);
|
|
44
|
-
function ProviderNotFoundError(providerName) {
|
|
45
|
-
var _this = _super.call(this, "Provider not found: ".concat(providerName), 'PROVIDER_NOT_FOUND') || this;
|
|
46
|
-
_this.name = 'ProviderNotFoundError';
|
|
47
|
-
return _this;
|
|
48
|
-
}
|
|
49
|
-
return ProviderNotFoundError;
|
|
50
|
-
}(CommerceError));
|
|
51
|
-
exports.ProviderNotFoundError = ProviderNotFoundError;
|
|
52
|
-
/**
|
|
53
|
-
* Configuration error
|
|
54
|
-
*/
|
|
55
|
-
var ConfigurationError = /** @class */ (function (_super) {
|
|
56
|
-
__extends(ConfigurationError, _super);
|
|
57
|
-
function ConfigurationError(message) {
|
|
58
|
-
var _this = _super.call(this, message, 'CONFIGURATION_ERROR') || this;
|
|
59
|
-
_this.name = 'ConfigurationError';
|
|
60
|
-
return _this;
|
|
61
|
-
}
|
|
62
|
-
return ConfigurationError;
|
|
63
|
-
}(CommerceError));
|
|
64
|
-
exports.ConfigurationError = ConfigurationError;
|
|
65
|
-
/**
|
|
66
|
-
* Resource not found error
|
|
67
|
-
*/
|
|
68
|
-
var ResourceNotFoundError = /** @class */ (function (_super) {
|
|
69
|
-
__extends(ResourceNotFoundError, _super);
|
|
70
|
-
function ResourceNotFoundError(resource, identifier) {
|
|
71
|
-
var _this = _super.call(this, "".concat(resource, " not found: ").concat(identifier), 'RESOURCE_NOT_FOUND', 404) || this;
|
|
72
|
-
_this.name = 'ResourceNotFoundError';
|
|
73
|
-
return _this;
|
|
74
|
-
}
|
|
75
|
-
return ResourceNotFoundError;
|
|
76
|
-
}(CommerceError));
|
|
77
|
-
exports.ResourceNotFoundError = ResourceNotFoundError;
|
|
78
|
-
/**
|
|
79
|
-
* API error from provider
|
|
80
|
-
*/
|
|
81
|
-
var ProviderAPIError = /** @class */ (function (_super) {
|
|
82
|
-
__extends(ProviderAPIError, _super);
|
|
83
|
-
function ProviderAPIError(message, provider, status) {
|
|
84
|
-
var _this = _super.call(this, message, 'PROVIDER_API_ERROR', status) || this;
|
|
85
|
-
_this.provider = provider;
|
|
86
|
-
_this.name = 'ProviderAPIError';
|
|
87
|
-
return _this;
|
|
88
|
-
}
|
|
89
|
-
return ProviderAPIError;
|
|
90
|
-
}(CommerceError));
|
|
91
|
-
exports.ProviderAPIError = ProviderAPIError;
|
|
92
|
-
/**
|
|
93
|
-
* Extract error message from various error types
|
|
94
|
-
* Handles standard Error objects, API responses, and unknown error types
|
|
95
|
-
*/
|
|
96
|
-
function extractErrorMessage(error) {
|
|
97
|
-
var _a, _b, _c, _d, _e, _f;
|
|
98
|
-
// Standard Error object
|
|
99
|
-
if (error instanceof Error && error.message) {
|
|
100
|
-
// Don't return generic messages if there's more data
|
|
101
|
-
if (error.message !== 'An unknown error occurred.') {
|
|
102
|
-
return error.message;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
// Object with message property
|
|
106
|
-
if (typeof error === 'object' && error !== null) {
|
|
107
|
-
var err = error;
|
|
108
|
-
// Check for response body (common in fetch errors)
|
|
109
|
-
if (err.body) {
|
|
110
|
-
if (typeof err.body === 'string')
|
|
111
|
-
return err.body;
|
|
112
|
-
if (err.body.message)
|
|
113
|
-
return String(err.body.message);
|
|
114
|
-
if ((_a = err.body.error) === null || _a === void 0 ? void 0 : _a.message)
|
|
115
|
-
return String(err.body.error.message);
|
|
116
|
-
}
|
|
117
|
-
// Check for response object
|
|
118
|
-
if (err.response) {
|
|
119
|
-
if ((_b = err.response.data) === null || _b === void 0 ? void 0 : _b.message)
|
|
120
|
-
return String(err.response.data.message);
|
|
121
|
-
if ((_c = err.response.data) === null || _c === void 0 ? void 0 : _c.error)
|
|
122
|
-
return String(err.response.data.error);
|
|
123
|
-
if (err.response.statusText)
|
|
124
|
-
return "".concat(err.response.status || '', " ").concat(err.response.statusText).trim();
|
|
125
|
-
}
|
|
126
|
-
// Check for data property
|
|
127
|
-
if ((_d = err.data) === null || _d === void 0 ? void 0 : _d.message)
|
|
128
|
-
return String(err.data.message);
|
|
129
|
-
if ((_e = err.data) === null || _e === void 0 ? void 0 : _e.error)
|
|
130
|
-
return String(err.data.error);
|
|
131
|
-
// Check for error property
|
|
132
|
-
if ((_f = err.error) === null || _f === void 0 ? void 0 : _f.message)
|
|
133
|
-
return String(err.error.message);
|
|
134
|
-
// Check for statusText with status code
|
|
135
|
-
if (err.status && err.statusText) {
|
|
136
|
-
return "HTTP ".concat(err.status, ": ").concat(err.statusText);
|
|
137
|
-
}
|
|
138
|
-
if (err.status && !err.statusText) {
|
|
139
|
-
return "HTTP ".concat(err.status, " Error");
|
|
140
|
-
}
|
|
141
|
-
// Check for message property (not generic)
|
|
142
|
-
if (err.message && err.message !== 'An unknown error occurred.') {
|
|
143
|
-
return String(err.message);
|
|
144
|
-
}
|
|
145
|
-
// Try to stringify the error object
|
|
146
|
-
try {
|
|
147
|
-
var stringified = JSON.stringify(error);
|
|
148
|
-
if (stringified !== '{}')
|
|
149
|
-
return stringified;
|
|
150
|
-
}
|
|
151
|
-
catch (_g) {
|
|
152
|
-
// Ignore JSON.stringify errors
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
// String error
|
|
156
|
-
if (typeof error === 'string') {
|
|
157
|
-
return error;
|
|
158
|
-
}
|
|
159
|
-
// Fallback
|
|
160
|
-
return 'An unknown error occurred';
|
|
161
|
-
}
|
package/src/core/fetch-utils.js
DELETED
|
@@ -1,240 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* @thorprovider/adapters v2.0
|
|
4
|
-
* Fetch Utilities - Retry logic, timeouts, and error handling
|
|
5
|
-
*
|
|
6
|
-
* This module provides enhanced fetch capabilities with:
|
|
7
|
-
* - Automatic retries with exponential backoff
|
|
8
|
-
* - Configurable timeouts
|
|
9
|
-
* - Better error handling for network failures
|
|
10
|
-
*/
|
|
11
|
-
var __assign = (this && this.__assign) || function () {
|
|
12
|
-
__assign = Object.assign || function(t) {
|
|
13
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
14
|
-
s = arguments[i];
|
|
15
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
16
|
-
t[p] = s[p];
|
|
17
|
-
}
|
|
18
|
-
return t;
|
|
19
|
-
};
|
|
20
|
-
return __assign.apply(this, arguments);
|
|
21
|
-
};
|
|
22
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
23
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
24
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
25
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
26
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
27
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
28
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
29
|
-
});
|
|
30
|
-
};
|
|
31
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
32
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
33
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
34
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
35
|
-
function step(op) {
|
|
36
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
37
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
38
|
-
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;
|
|
39
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
40
|
-
switch (op[0]) {
|
|
41
|
-
case 0: case 1: t = op; break;
|
|
42
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
43
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
44
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
45
|
-
default:
|
|
46
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
47
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
48
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
49
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
50
|
-
if (t[2]) _.ops.pop();
|
|
51
|
-
_.trys.pop(); continue;
|
|
52
|
-
}
|
|
53
|
-
op = body.call(thisArg, _);
|
|
54
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
55
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
59
|
-
exports.fetchWithRetry = fetchWithRetry;
|
|
60
|
-
exports.createFetchWithRetry = createFetchWithRetry;
|
|
61
|
-
var logger_1 = require("./logger");
|
|
62
|
-
var logger = (0, logger_1.createLogger)('FetchUtils');
|
|
63
|
-
var DEFAULT_RETRY_CONFIG = {
|
|
64
|
-
maxRetries: 3,
|
|
65
|
-
initialDelayMs: 300,
|
|
66
|
-
backoffMultiplier: 2,
|
|
67
|
-
maxDelayMs: 5000,
|
|
68
|
-
timeoutMs: 10000, // 10 seconds
|
|
69
|
-
retryableStatusCodes: [408, 429, 500, 502, 503, 504],
|
|
70
|
-
};
|
|
71
|
-
/**
|
|
72
|
-
* Sleep utility for delays between retries
|
|
73
|
-
*/
|
|
74
|
-
function sleep(ms) {
|
|
75
|
-
return new Promise(function (resolve) { return setTimeout(resolve, ms); });
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Calculate delay for exponential backoff
|
|
79
|
-
*/
|
|
80
|
-
function calculateDelay(attempt, config) {
|
|
81
|
-
var delay = config.initialDelayMs * Math.pow(config.backoffMultiplier, attempt);
|
|
82
|
-
return Math.min(delay, config.maxDelayMs);
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Check if error is retryable
|
|
86
|
-
*/
|
|
87
|
-
function isRetryableError(error, config) {
|
|
88
|
-
var _a, _b;
|
|
89
|
-
// Network errors (fetch failed, connection refused, etc.)
|
|
90
|
-
if (error.name === 'TypeError' || ((_a = error.message) === null || _a === void 0 ? void 0 : _a.includes('fetch failed'))) {
|
|
91
|
-
return true;
|
|
92
|
-
}
|
|
93
|
-
// Timeout errors
|
|
94
|
-
if (error.name === 'AbortError' || ((_b = error.message) === null || _b === void 0 ? void 0 : _b.includes('timeout'))) {
|
|
95
|
-
return true;
|
|
96
|
-
}
|
|
97
|
-
// HTTP status codes
|
|
98
|
-
if (error.status && config.retryableStatusCodes.includes(error.status)) {
|
|
99
|
-
return true;
|
|
100
|
-
}
|
|
101
|
-
return false;
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Enhanced fetch with retry logic and timeout
|
|
105
|
-
*
|
|
106
|
-
* @example
|
|
107
|
-
* ```typescript
|
|
108
|
-
* import { fetchWithRetry } from '@thorprovider/adapters/core/fetch-utils';
|
|
109
|
-
*
|
|
110
|
-
* // Basic usage with defaults (3 retries, 10s timeout)
|
|
111
|
-
* const response = await fetchWithRetry('https://api.example.com/products');
|
|
112
|
-
*
|
|
113
|
-
* // Custom configuration
|
|
114
|
-
* const response = await fetchWithRetry(
|
|
115
|
-
* 'https://api.example.com/products',
|
|
116
|
-
* {
|
|
117
|
-
* method: 'POST',
|
|
118
|
-
* body: JSON.stringify({ name: 'Product' }),
|
|
119
|
-
* },
|
|
120
|
-
* {
|
|
121
|
-
* maxRetries: 5,
|
|
122
|
-
* timeoutMs: 15000, // 15 seconds
|
|
123
|
-
* initialDelayMs: 500,
|
|
124
|
-
* }
|
|
125
|
-
* );
|
|
126
|
-
* ```
|
|
127
|
-
*/
|
|
128
|
-
function fetchWithRetry(url, init, retryConfig) {
|
|
129
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
130
|
-
var config, lastError, _loop_1, attempt, state_1;
|
|
131
|
-
return __generator(this, function (_a) {
|
|
132
|
-
switch (_a.label) {
|
|
133
|
-
case 0:
|
|
134
|
-
config = __assign(__assign({}, DEFAULT_RETRY_CONFIG), retryConfig);
|
|
135
|
-
_loop_1 = function (attempt) {
|
|
136
|
-
var controller_1, timeoutId, fetchOptions, response, error, error_1, shouldRetry, delay;
|
|
137
|
-
return __generator(this, function (_b) {
|
|
138
|
-
switch (_b.label) {
|
|
139
|
-
case 0:
|
|
140
|
-
_b.trys.push([0, 2, , 6]);
|
|
141
|
-
controller_1 = new AbortController();
|
|
142
|
-
timeoutId = setTimeout(function () { return controller_1.abort(); }, config.timeoutMs);
|
|
143
|
-
fetchOptions = __assign(__assign({}, init), { signal: controller_1.signal });
|
|
144
|
-
logger.debug('Fetch attempt', {
|
|
145
|
-
url: url,
|
|
146
|
-
attempt: attempt + 1,
|
|
147
|
-
maxAttempts: config.maxRetries + 1,
|
|
148
|
-
timeout: config.timeoutMs,
|
|
149
|
-
});
|
|
150
|
-
return [4 /*yield*/, fetch(url, fetchOptions)];
|
|
151
|
-
case 1:
|
|
152
|
-
response = _b.sent();
|
|
153
|
-
// Clear timeout
|
|
154
|
-
clearTimeout(timeoutId);
|
|
155
|
-
// Check if status code is retryable
|
|
156
|
-
if (!response.ok && config.retryableStatusCodes.includes(response.status)) {
|
|
157
|
-
error = new Error("HTTP ".concat(response.status, ": ").concat(response.statusText));
|
|
158
|
-
error.status = response.status;
|
|
159
|
-
throw error;
|
|
160
|
-
}
|
|
161
|
-
// Success!
|
|
162
|
-
logger.debug('Fetch successful', { url: url, attempt: attempt + 1 });
|
|
163
|
-
return [2 /*return*/, { value: response }];
|
|
164
|
-
case 2:
|
|
165
|
-
error_1 = _b.sent();
|
|
166
|
-
lastError = error_1;
|
|
167
|
-
// Clear timeout if it exists
|
|
168
|
-
if (error_1.name === 'AbortError') {
|
|
169
|
-
lastError = new Error("Request timeout after ".concat(config.timeoutMs, "ms"));
|
|
170
|
-
lastError.name = 'TimeoutError';
|
|
171
|
-
}
|
|
172
|
-
shouldRetry = attempt < config.maxRetries && isRetryableError(error_1, config);
|
|
173
|
-
if (!shouldRetry) return [3 /*break*/, 4];
|
|
174
|
-
delay = calculateDelay(attempt, config);
|
|
175
|
-
logger.warn('Fetch failed, retrying...', {
|
|
176
|
-
url: url,
|
|
177
|
-
attempt: attempt + 1,
|
|
178
|
-
maxAttempts: config.maxRetries + 1,
|
|
179
|
-
nextRetryIn: "".concat(delay, "ms"),
|
|
180
|
-
error: error_1.message,
|
|
181
|
-
});
|
|
182
|
-
return [4 /*yield*/, sleep(delay)];
|
|
183
|
-
case 3:
|
|
184
|
-
_b.sent();
|
|
185
|
-
return [3 /*break*/, 5];
|
|
186
|
-
case 4:
|
|
187
|
-
logger.error('Fetch failed after all retries', {
|
|
188
|
-
url: url,
|
|
189
|
-
totalAttempts: attempt + 1,
|
|
190
|
-
error: error_1.message,
|
|
191
|
-
});
|
|
192
|
-
return [2 /*return*/, "break"];
|
|
193
|
-
case 5: return [3 /*break*/, 6];
|
|
194
|
-
case 6: return [2 /*return*/];
|
|
195
|
-
}
|
|
196
|
-
});
|
|
197
|
-
};
|
|
198
|
-
attempt = 0;
|
|
199
|
-
_a.label = 1;
|
|
200
|
-
case 1:
|
|
201
|
-
if (!(attempt <= config.maxRetries)) return [3 /*break*/, 4];
|
|
202
|
-
return [5 /*yield**/, _loop_1(attempt)];
|
|
203
|
-
case 2:
|
|
204
|
-
state_1 = _a.sent();
|
|
205
|
-
if (typeof state_1 === "object")
|
|
206
|
-
return [2 /*return*/, state_1.value];
|
|
207
|
-
if (state_1 === "break")
|
|
208
|
-
return [3 /*break*/, 4];
|
|
209
|
-
_a.label = 3;
|
|
210
|
-
case 3:
|
|
211
|
-
attempt++;
|
|
212
|
-
return [3 /*break*/, 1];
|
|
213
|
-
case 4:
|
|
214
|
-
// All retries exhausted, throw the last error
|
|
215
|
-
throw lastError;
|
|
216
|
-
}
|
|
217
|
-
});
|
|
218
|
-
});
|
|
219
|
-
}
|
|
220
|
-
/**
|
|
221
|
-
* Create a fetch function with custom retry configuration
|
|
222
|
-
* Useful for creating a configured fetch instance
|
|
223
|
-
*
|
|
224
|
-
* @example
|
|
225
|
-
* ```typescript
|
|
226
|
-
* import { createFetchWithRetry } from '@thorprovider/adapters/core/fetch-utils';
|
|
227
|
-
*
|
|
228
|
-
* // Create configured fetch
|
|
229
|
-
* const customFetch = createFetchWithRetry({
|
|
230
|
-
* maxRetries: 5,
|
|
231
|
-
* timeoutMs: 15000,
|
|
232
|
-
* });
|
|
233
|
-
*
|
|
234
|
-
* // Use it like regular fetch
|
|
235
|
-
* const response = await customFetch('https://api.example.com/products');
|
|
236
|
-
* ```
|
|
237
|
-
*/
|
|
238
|
-
function createFetchWithRetry(retryConfig) {
|
|
239
|
-
return function (url, init) { return fetchWithRetry(url, init, retryConfig); };
|
|
240
|
-
}
|
package/src/core/logger.js
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* @thorprovider/adapters v2.0
|
|
4
|
-
* Core logger utility
|
|
5
|
-
*/
|
|
6
|
-
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
7
|
-
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
8
|
-
if (ar || !(i in from)) {
|
|
9
|
-
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
10
|
-
ar[i] = from[i];
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
return to.concat(ar || Array.prototype.slice.call(from));
|
|
14
|
-
};
|
|
15
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
-
exports.createLogger = createLogger;
|
|
17
|
-
/**
|
|
18
|
-
* Create a logger instance
|
|
19
|
-
*/
|
|
20
|
-
function createLogger(namespace, enabled) {
|
|
21
|
-
if (enabled === void 0) { enabled = false; }
|
|
22
|
-
var log = function (level, message) {
|
|
23
|
-
var args = [];
|
|
24
|
-
for (var _i = 2; _i < arguments.length; _i++) {
|
|
25
|
-
args[_i - 2] = arguments[_i];
|
|
26
|
-
}
|
|
27
|
-
if (!enabled && level !== 'error')
|
|
28
|
-
return;
|
|
29
|
-
var timestamp = new Date().toISOString();
|
|
30
|
-
var prefix = "[".concat(timestamp, "] [@thorprovider/adapters:").concat(namespace, "] ").concat(level.toUpperCase(), ":");
|
|
31
|
-
console[level].apply(console, __spreadArray([prefix, message], args, false));
|
|
32
|
-
};
|
|
33
|
-
return {
|
|
34
|
-
debug: function (message) {
|
|
35
|
-
var args = [];
|
|
36
|
-
for (var _i = 1; _i < arguments.length; _i++) {
|
|
37
|
-
args[_i - 1] = arguments[_i];
|
|
38
|
-
}
|
|
39
|
-
return log.apply(void 0, __spreadArray(['debug', message], args, false));
|
|
40
|
-
},
|
|
41
|
-
info: function (message) {
|
|
42
|
-
var args = [];
|
|
43
|
-
for (var _i = 1; _i < arguments.length; _i++) {
|
|
44
|
-
args[_i - 1] = arguments[_i];
|
|
45
|
-
}
|
|
46
|
-
return log.apply(void 0, __spreadArray(['info', message], args, false));
|
|
47
|
-
},
|
|
48
|
-
warn: function (message) {
|
|
49
|
-
var args = [];
|
|
50
|
-
for (var _i = 1; _i < arguments.length; _i++) {
|
|
51
|
-
args[_i - 1] = arguments[_i];
|
|
52
|
-
}
|
|
53
|
-
return log.apply(void 0, __spreadArray(['warn', message], args, false));
|
|
54
|
-
},
|
|
55
|
-
error: function (message) {
|
|
56
|
-
var args = [];
|
|
57
|
-
for (var _i = 1; _i < arguments.length; _i++) {
|
|
58
|
-
args[_i - 1] = arguments[_i];
|
|
59
|
-
}
|
|
60
|
-
return log.apply(void 0, __spreadArray(['error', message], args, false));
|
|
61
|
-
},
|
|
62
|
-
};
|
|
63
|
-
}
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Channel Scope Validation — Pure TypeScript (no external deps)
|
|
4
|
-
*
|
|
5
|
-
* Validates channel-scope metadata before it is written to the backend.
|
|
6
|
-
* Keeps all validation logic in L2 so that L5 starters don't duplicate checks.
|
|
7
|
-
*
|
|
8
|
-
* @module metadata/channel-scope-validation
|
|
9
|
-
*/
|
|
10
|
-
var __extends = (this && this.__extends) || (function () {
|
|
11
|
-
var extendStatics = function (d, b) {
|
|
12
|
-
extendStatics = Object.setPrototypeOf ||
|
|
13
|
-
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
14
|
-
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
15
|
-
return extendStatics(d, b);
|
|
16
|
-
};
|
|
17
|
-
return function (d, b) {
|
|
18
|
-
if (typeof b !== "function" && b !== null)
|
|
19
|
-
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
20
|
-
extendStatics(d, b);
|
|
21
|
-
function __() { this.constructor = d; }
|
|
22
|
-
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
23
|
-
};
|
|
24
|
-
})();
|
|
25
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.ChannelScopeValidationError = void 0;
|
|
27
|
-
exports.validateChannelId = validateChannelId;
|
|
28
|
-
exports.validateEntityId = validateEntityId;
|
|
29
|
-
exports.validateAssignedBy = validateAssignedBy;
|
|
30
|
-
exports.validateChannelScopeAssignment = validateChannelScopeAssignment;
|
|
31
|
-
exports.assertEntityBelongsToChannel = assertEntityBelongsToChannel;
|
|
32
|
-
var channel_scope_1 = require("./channel-scope");
|
|
33
|
-
// ────────────────────────────────────────────────────────────────────
|
|
34
|
-
// Errors
|
|
35
|
-
// ────────────────────────────────────────────────────────────────────
|
|
36
|
-
/**
|
|
37
|
-
* Thrown when channel-scope validation fails.
|
|
38
|
-
*
|
|
39
|
-
* Consumers can catch this specific type to provide user-friendly feedback
|
|
40
|
-
* without leaking internal details.
|
|
41
|
-
*/
|
|
42
|
-
var ChannelScopeValidationError = /** @class */ (function (_super) {
|
|
43
|
-
__extends(ChannelScopeValidationError, _super);
|
|
44
|
-
function ChannelScopeValidationError(message, field, value) {
|
|
45
|
-
var _this = _super.call(this, message) || this;
|
|
46
|
-
_this.name = 'ChannelScopeValidationError';
|
|
47
|
-
_this.field = field;
|
|
48
|
-
_this.value = value;
|
|
49
|
-
return _this;
|
|
50
|
-
}
|
|
51
|
-
return ChannelScopeValidationError;
|
|
52
|
-
}(Error));
|
|
53
|
-
exports.ChannelScopeValidationError = ChannelScopeValidationError;
|
|
54
|
-
// ────────────────────────────────────────────────────────────────────
|
|
55
|
-
// Validation functions
|
|
56
|
-
// ────────────────────────────────────────────────────────────────────
|
|
57
|
-
/**
|
|
58
|
-
* Validate that a channel ID is a non-empty string.
|
|
59
|
-
*
|
|
60
|
-
* Does **not** enforce a specific prefix (e.g. `"sc_"`) because different
|
|
61
|
-
* backends use different conventions:
|
|
62
|
-
* - Medusa: `"sc_01HXXX"`
|
|
63
|
-
* - Shopify: `"gid://shopify/Channel/789"`
|
|
64
|
-
* - WooCommerce: `"1"` (numeric string)
|
|
65
|
-
*
|
|
66
|
-
* @throws {ChannelScopeValidationError}
|
|
67
|
-
*/
|
|
68
|
-
function validateChannelId(channelId) {
|
|
69
|
-
if (typeof channelId !== 'string' || channelId.trim().length === 0) {
|
|
70
|
-
throw new ChannelScopeValidationError('Channel ID must be a non-empty string', 'channelId', channelId);
|
|
71
|
-
}
|
|
72
|
-
// Sanity upper-bound for ID length (guards against payload abuse)
|
|
73
|
-
if (channelId.length > 256) {
|
|
74
|
-
throw new ChannelScopeValidationError('Channel ID exceeds maximum length (256)', 'channelId', channelId);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Validate that an entity ID is a non-empty string.
|
|
79
|
-
*
|
|
80
|
-
* @throws {ChannelScopeValidationError}
|
|
81
|
-
*/
|
|
82
|
-
function validateEntityId(entityId, label) {
|
|
83
|
-
if (label === void 0) { label = 'entityId'; }
|
|
84
|
-
if (typeof entityId !== 'string' || entityId.trim().length === 0) {
|
|
85
|
-
throw new ChannelScopeValidationError("".concat(label, " must be a non-empty string"), label, entityId);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Validate that the `assignedBy` value (if provided) is a reasonable string.
|
|
90
|
-
*
|
|
91
|
-
* @throws {ChannelScopeValidationError}
|
|
92
|
-
*/
|
|
93
|
-
function validateAssignedBy(assignedBy) {
|
|
94
|
-
if (assignedBy === undefined || assignedBy === null)
|
|
95
|
-
return;
|
|
96
|
-
if (typeof assignedBy !== 'string') {
|
|
97
|
-
throw new ChannelScopeValidationError('assignedBy must be a string', 'assignedBy', assignedBy);
|
|
98
|
-
}
|
|
99
|
-
if (assignedBy.length > 512) {
|
|
100
|
-
throw new ChannelScopeValidationError('assignedBy exceeds maximum length (512)', 'assignedBy', assignedBy);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Full validation for a channel-scope assignment operation.
|
|
105
|
-
*
|
|
106
|
-
* Call before writing channel scope metadata to any entity.
|
|
107
|
-
*
|
|
108
|
-
* @throws {ChannelScopeValidationError} with descriptive field + value
|
|
109
|
-
*
|
|
110
|
-
* @example
|
|
111
|
-
* ```typescript
|
|
112
|
-
* validateChannelScopeAssignment('cus_123', 'sc_01HXXX', 'admin@store.com');
|
|
113
|
-
* // If no error, safe to proceed
|
|
114
|
-
* ```
|
|
115
|
-
*/
|
|
116
|
-
function validateChannelScopeAssignment(entityId, channelId, assignedBy) {
|
|
117
|
-
validateEntityId(entityId, 'entityId');
|
|
118
|
-
validateChannelId(channelId);
|
|
119
|
-
validateAssignedBy(assignedBy);
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Validate that an entity is currently scoped to the expected channel.
|
|
123
|
-
*
|
|
124
|
-
* Useful as a guard before performing operations that should only
|
|
125
|
-
* affect entities within the caller's channel (e.g. a dropshipper editing
|
|
126
|
-
* a customer that must belong to their channel).
|
|
127
|
-
*
|
|
128
|
-
* @throws {ChannelScopeValidationError} if entity does not belong to expectedChannelId
|
|
129
|
-
*/
|
|
130
|
-
function assertEntityBelongsToChannel(entity, expectedChannelId) {
|
|
131
|
-
var _a;
|
|
132
|
-
var actual = (_a = entity.metadata) === null || _a === void 0 ? void 0 : _a[channel_scope_1.CHANNEL_SCOPE_KEY];
|
|
133
|
-
if (actual !== expectedChannelId) {
|
|
134
|
-
throw new ChannelScopeValidationError("Entity \"".concat(entity.id, "\" does not belong to channel \"").concat(expectedChannelId, "\" (actual: \"").concat(actual !== null && actual !== void 0 ? actual : 'none', "\")"), channel_scope_1.CHANNEL_SCOPE_KEY, actual);
|
|
135
|
-
}
|
|
136
|
-
}
|