ebay-mcp 1.18.0 → 1.18.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -35
- package/build/api/account-management/accountV2.js +22 -22
- package/build/api/account-management/finances.js +10 -10
- package/build/api/analytics-and-report/analytics.js +1 -1
- package/build/api/{client.js → client/ebayApiClient.js} +37 -41
- package/build/api/{clientTrading.js → client/tradingApiClient.js} +22 -22
- package/build/api/communication/feedback.js +21 -21
- package/build/api/communication/message.js +23 -23
- package/build/api/communication/negotiation.js +7 -7
- package/build/api/communication/notification.js +52 -52
- package/build/api/developer/developer.js +3 -3
- package/build/api/{index.js → ebaySellerApi.js} +4 -4
- package/build/api/listing-management/feedReportTasks.js +6 -6
- package/build/api/listing-management/feedRequest.js +6 -6
- package/build/api/listing-management/feedSchedules.js +4 -4
- package/build/api/listing-management/feedTasks.js +2 -2
- package/build/api/listing-management/items.js +22 -22
- package/build/api/listing-management/locations.js +4 -4
- package/build/api/listing-management/media.js +14 -14
- package/build/api/listing-management/mediaAttach.js +14 -14
- package/build/api/listing-management/mediaResources.js +15 -13
- package/build/api/listing-management/offerFormat.js +1 -1
- package/build/api/listing-management/offers.js +23 -23
- package/build/api/listing-management/stores.js +9 -9
- package/build/api/listing-metadata/metadata.js +10 -10
- package/build/api/marketing-and-promotions/ads.js +34 -34
- package/build/api/marketing-and-promotions/campaigns.js +19 -19
- package/build/api/marketing-and-promotions/promotions.js +22 -22
- package/build/api/marketing-and-promotions/reports.js +7 -7
- package/build/api/order-management/dispute.js +11 -9
- package/build/api/order-management/fulfillment.js +4 -4
- package/build/api/order-management/logistics.js +7 -7
- package/build/api/other/browseMappers.js +15 -13
- package/build/api/other/browseValidators.js +4 -4
- package/build/api/other/edelivery.js +19 -19
- package/build/api/other/finding.js +13 -13
- package/build/api/other/translation.js +2 -2
- package/build/api/other/vero.js +2 -2
- package/build/api/shared/download.js +7 -7
- package/build/api/shared/request.js +28 -19
- package/build/api/trading/listingFormat.js +37 -30
- package/build/api/trading/trading.js +33 -33
- package/build/auth/credentialSession.js +5 -5
- package/build/auth/oauth.js +3 -3
- package/build/auth/oauthHelper.js +24 -24
- package/build/auth/oauthMetadata.js +4 -4
- package/build/auth/oauthMiddleware.js +16 -16
- package/build/auth/scopeUtils.js +2 -2
- package/build/auth/tokenVerifier.js +23 -23
- package/build/config/environment.js +4 -45
- package/build/config/oauthScopes.js +132 -0
- package/build/index.js +5 -5
- package/build/mcp/httpTransport.js +32 -20
- package/build/mcp/runtime.js +12 -12
- package/build/mcp/toolGating.js +6 -12
- package/build/mcp/uiBridge.js +3 -3
- package/build/schemas/account-management/account.js +2 -52
- package/build/schemas/account-management/accountV2.js +2 -2
- package/build/schemas/account-management/finances.js +1 -1
- package/build/schemas/analytics/analytics.js +2 -48
- package/build/schemas/communication/messages.js +2 -46
- package/build/schemas/developer/developer.js +1 -27
- package/build/schemas/fulfillment/logistics.js +1 -1
- package/build/schemas/fulfillment/orders.js +2 -47
- package/build/schemas/inventory-management/feed.js +1 -1
- package/build/schemas/inventory-management/inventory.js +2 -50
- package/build/schemas/inventory-management/media.js +2 -2
- package/build/schemas/inventory-management/mediaDocuments.js +1 -1
- package/build/schemas/inventory-management/stores.js +1 -1
- package/build/schemas/marketing/ads.js +2 -2
- package/build/schemas/marketing/campaigns.js +2 -2
- package/build/schemas/marketing/common.js +2 -2
- package/build/schemas/marketing/marketing.js +0 -1
- package/build/schemas/marketing/promotions.js +2 -2
- package/build/schemas/marketing/reports.js +2 -2
- package/build/schemas/metadata/metadata.js +2 -90
- package/build/schemas/metadata/shipping.js +1 -1
- package/build/schemas/other/browse.js +2 -2
- package/build/schemas/other/finding.js +2 -2
- package/build/schemas/other/otherApis.js +2 -114
- package/build/schemas/taxonomy/categoryTree.js +1 -1
- package/build/schemas/taxonomy/charity.js +1 -1
- package/build/schemas/taxonomy/taxonomy.js +2 -69
- package/build/scripts/autoSetup.js +3 -3
- package/build/scripts/{buildUi.js → buildMcpApps.js} +13 -13
- package/build/scripts/devSync.js +19 -68
- package/build/scripts/diagnostics.js +15 -16
- package/build/scripts/interactiveSetup.js +25 -25
- package/build/scripts/scopeHelper.js +2 -2
- package/build/scripts/securityChecker.js +20 -20
- package/build/scripts/setup.js +76 -76
- package/build/scripts/setupShared.js +5 -30
- package/build/scripts/setupValidator.js +9 -9
- package/build/scripts/setupWizard.js +23 -23
- package/build/scripts/skills.js +14 -17
- package/build/scripts/specRefs.js +1 -1
- package/build/scripts/specSources.js +144 -0
- package/build/serverHttp.js +4 -7
- package/build/skills/content.js +13 -13
- package/build/skills/install.js +9 -9
- package/build/skills/render.js +2 -2
- package/build/tools/categories/communication.js +1 -1
- package/build/tools/categories/connector.js +19 -16
- package/build/tools/categories/fulfillment.js +4 -4
- package/build/tools/categories/inventory.js +1 -1
- package/build/tools/categories/metadata.js +1 -1
- package/build/tools/categories/taxonomy.js +1 -1
- package/build/tools/categories/tokenManagement.js +8 -8
- package/build/tools/contracts.js +2 -2
- package/build/tools/defineTool.js +27 -12
- package/build/tools/registry.js +2 -2
- package/build/tools/schemas.js +2 -2
- package/build/tools/ui/mapHelpers.js +12 -12
- package/build/tools/ui/maps.js +101 -97
- package/build/tools/ui/viewModels.js +2 -2
- package/build/utils/apiStatusFeed.js +12 -12
- package/build/utils/communication/feedback.js +3 -3
- package/build/utils/communication/message.js +3 -3
- package/build/utils/communication/negotiation.js +3 -3
- package/build/utils/communication/notification.js +3 -3
- package/build/utils/entryModule.js +33 -0
- package/build/utils/envFile.js +47 -0
- package/build/utils/envParser.js +5 -5
- package/build/utils/errors.js +4 -4
- package/build/utils/http.js +38 -38
- package/build/utils/localFeedFiles.js +3 -3
- package/build/utils/logRedaction.js +21 -0
- package/build/utils/logger.js +49 -35
- package/build/utils/other/compliance.js +3 -3
- package/build/utils/other/identity.js +3 -3
- package/build/utils/other/translation.js +3 -3
- package/build/utils/other/vero.js +3 -3
- package/build/utils/schemaHelpers.js +2 -2
- package/build/utils/tokenUtils.js +2 -2
- package/build/utils/trading/trading.js +1 -1
- package/build/utils/version.js +1 -1
- package/build/utils/zodIssues.js +14 -0
- package/package.json +8 -11
- package/README.de.md +0 -426
- package/README.es.md +0 -426
- package/README.fr.md +0 -426
- package/README.ja.md +0 -426
- package/README.ko.md +0 -426
- package/README.pt-BR.md +0 -426
- package/README.ru.md +0 -426
- package/README.zh-CN.md +0 -426
- package/build/schemas/index.js +0 -76
- package/build/schemas/marketing/jsonSchemas.js +0 -118
- package/build/scripts/downloadSpecs.js +0 -117
- package/build/scripts/updateApiStatusDoc.js +0 -71
- package/build/utils/effectSchema.js +0 -203
- package/build/utils/effectSchemaAdapter.js +0 -121
- package/build/utils/effectSchemaChainMethods.js +0 -146
- package/build/utils/effectSchemaRefinements.js +0 -104
- package/build/utils/effectSchemaStringMethods.js +0 -63
- package/build/utils/effectSchemaTypes.js +0 -47
- package/docs/auth/production_scopes.json +0 -111
- package/docs/auth/sandbox_scopes.json +0 -142
- /package/build/api/{clientRequestError.js → client/ebayClientRequestError.js} +0 -0
- /package/build/api/{rateLimitTracker.js → client/rateLimitTracker.js} +0 -0
- /package/build/api/{clientTradingError.js → client/tradingApiFailure.js} +0 -0
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import * as fs from 'fs';
|
|
2
|
-
import * as path from 'path';
|
|
3
|
-
import { getErrorMessage } from '../utils/errors.js';
|
|
4
|
-
import { httpRequest } from '../utils/http.js';
|
|
5
|
-
import { Effect, Either } from 'effect';
|
|
6
|
-
import { fileURLToPath } from 'url';
|
|
7
|
-
import { dirname } from 'path';
|
|
8
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
-
const __dirname = dirname(__filename);
|
|
10
|
-
const DOCS_DIR = path.resolve(__dirname, '../../docs');
|
|
11
|
-
const README_PATH = path.resolve(__dirname, '../../docs/sell-apps/README.md');
|
|
12
|
-
const getUrlsFromReadme = (content) => {
|
|
13
|
-
// Regex to find URLs that end with .json, specifically for OpenAPI specs
|
|
14
|
-
// This assumes the README will directly link to the JSON spec files, but is less strict to allow for variations.
|
|
15
|
-
const urlRegex = /(https:\/\/[^\s)]+\.json)/g;
|
|
16
|
-
const urls = Array.from(content.matchAll(urlRegex)).map((match) => match[1]);
|
|
17
|
-
console.log('Found URLs:', urls);
|
|
18
|
-
return urls;
|
|
19
|
-
};
|
|
20
|
-
const getFolderName = (specUrl) => {
|
|
21
|
-
const fileName = path.basename(specUrl);
|
|
22
|
-
// mapping from file name to folder name
|
|
23
|
-
// This mapping is based on the README.md structure and common API groupings
|
|
24
|
-
const folderMap = {
|
|
25
|
-
// Application Settings
|
|
26
|
-
'developer_analytics_v1_beta_oas3.json': 'application-settings',
|
|
27
|
-
'developer_key_management_v1_oas3.json': 'application-settings',
|
|
28
|
-
'developer_client_registration_v1_oas3.json': 'application-settings',
|
|
29
|
-
// Selling Apps - Listing Management
|
|
30
|
-
'sell_inventory_v1_oas3.json': 'sell-apps/listing-management',
|
|
31
|
-
'sell_feed_v1_oas3.json': 'sell-apps/listing-management',
|
|
32
|
-
'commerce_media_v1_beta_oas3.json': 'sell-apps/listing-management',
|
|
33
|
-
'sell_stores_v1_oas3.json': 'sell-apps/listing-management',
|
|
34
|
-
// Selling Apps - Listing Metadata & Taxonomy
|
|
35
|
-
'sell_metadata_v1_oas3.json': 'sell-apps/listing-metadata',
|
|
36
|
-
'commerce_taxonomy_v1_oas3.json': 'sell-apps/listing-metadata',
|
|
37
|
-
'commerce_charity_v1_oas3.json': 'sell-apps/listing-metadata',
|
|
38
|
-
// Selling Apps - Account Management
|
|
39
|
-
'sell_account_v1_oas3.json': 'sell-apps/account-management',
|
|
40
|
-
'sell_account_v2_oas3.json': 'sell-apps/account-management',
|
|
41
|
-
'sell_finances_v1_oas3.json': 'sell-apps/account-management',
|
|
42
|
-
// Selling Apps - Communication & Negotiation
|
|
43
|
-
'commerce_message_v1_oas3.json': 'sell-apps/communication',
|
|
44
|
-
'commerce_notification_v1_oas3.json': 'sell-apps/communication',
|
|
45
|
-
'sell_negotiation_v1_oas3.json': 'sell-apps/communication',
|
|
46
|
-
'commerce_feedback_v1_beta_oas3.json': 'sell-apps/communication',
|
|
47
|
-
// Selling Apps - Order Management
|
|
48
|
-
'sell_fulfillment_v1_oas3.json': 'sell-apps/order-management',
|
|
49
|
-
'sell_logistics_v1_oas3.json': 'sell-apps/order-management',
|
|
50
|
-
// Selling Apps - Marketing & Promotions
|
|
51
|
-
'sell_marketing_v1_oas3.json': 'sell-apps/marketing-and-promotions',
|
|
52
|
-
'sell_recommendation_v1_oas3.json': 'sell-apps/marketing-and-promotions',
|
|
53
|
-
'sell_analytics_v1_oas3.json': 'sell-apps/analytics-and-report',
|
|
54
|
-
// Selling Apps - Other Selling APIs
|
|
55
|
-
'commerce_translation_v1_beta_oas3.json': 'sell-apps/other-apis',
|
|
56
|
-
'sell_compliance_v1_oas3.json': 'sell-apps/other-apis',
|
|
57
|
-
'commerce_identity_v1_oas3.json': 'sell-apps/other-apis',
|
|
58
|
-
'sell_edelivery_international_shipping_oas3.json': 'sell-apps/other-apis',
|
|
59
|
-
'commerce_vero_v1_oas3.json': 'sell-apps/other-apis',
|
|
60
|
-
// Buying Apps - Inventory Discovery & Refresh
|
|
61
|
-
'buy_browse_v1_oas3.json': 'buy-apps/inventory-discovery',
|
|
62
|
-
'buy_feed_v1_beta_oas3.json': 'buy-apps/inventory-discovery',
|
|
63
|
-
'buy_feed_v1_oas3.json': 'buy-apps/inventory-discovery',
|
|
64
|
-
// commerce_notification_v1_oas3.json is already mapped under sell-apps,
|
|
65
|
-
// but it's also relevant here. We'll prioritize the first mapping or create a symlink if needed.
|
|
66
|
-
// Buying Apps - Marketing & Discounts
|
|
67
|
-
'buy_deal_v1_oas3.json': 'buy-apps/marketing-and-discounts',
|
|
68
|
-
'buy_marketing_v1_beta_oas3.json': 'buy-apps/marketing-and-discounts',
|
|
69
|
-
// Buying Apps - Marketplace Metadata
|
|
70
|
-
// commerce_taxonomy_v1_oas3.json is already mapped under sell-apps
|
|
71
|
-
'commerce_catalog_v1_beta_oas3.json': 'buy-apps/marketplace-metadata',
|
|
72
|
-
// commerce_charity_v1_oas3.json is already mapped under sell-apps
|
|
73
|
-
// Buying Apps - Checkout & Bidding
|
|
74
|
-
'buy_order_v2_oas3.json': 'buy-apps/checkout-and-bidding',
|
|
75
|
-
'buy_offer_v1_beta_oas3.json': 'buy-apps/checkout-and-bidding',
|
|
76
|
-
// Buying Apps - Other Buying APIs
|
|
77
|
-
// commerce_translation_v1_beta_oas3.json is already mapped under sell-apps
|
|
78
|
-
// commerce_identity_v1_oas3.json is already mapped under sell-apps
|
|
79
|
-
};
|
|
80
|
-
// Default to 'other-apis' if not found in map, or use the mapped folder
|
|
81
|
-
return folderMap[fileName] || 'other-apis';
|
|
82
|
-
};
|
|
83
|
-
const downloadFile = async (url, folderPath, fileName) => {
|
|
84
|
-
const downloaded = await Effect.runPromise(Effect.either(Effect.tryPromise({
|
|
85
|
-
try: async () => {
|
|
86
|
-
const response = await httpRequest({ url, responseType: 'arraybuffer' });
|
|
87
|
-
const filePath = path.join(folderPath, fileName);
|
|
88
|
-
fs.mkdirSync(folderPath, { recursive: true });
|
|
89
|
-
fs.writeFileSync(filePath, response.data);
|
|
90
|
-
},
|
|
91
|
-
catch: (error) => error,
|
|
92
|
-
})));
|
|
93
|
-
if (Either.isLeft(downloaded)) {
|
|
94
|
-
console.error(`Failed to download ${url}:`, getErrorMessage(downloaded.left));
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
console.log(`Downloaded ${fileName} to ${folderPath}`);
|
|
98
|
-
};
|
|
99
|
-
const main = async () => {
|
|
100
|
-
const readme = Effect.runSync(Effect.either(Effect.try({
|
|
101
|
-
try: () => fs.readFileSync(README_PATH, 'utf-8'),
|
|
102
|
-
catch: (error) => error,
|
|
103
|
-
})));
|
|
104
|
-
if (Either.isLeft(readme)) {
|
|
105
|
-
console.error('Failed to read README.md:', getErrorMessage(readme.left));
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
const urls = getUrlsFromReadme(readme.right);
|
|
109
|
-
for (const url of urls) {
|
|
110
|
-
console.log(`Processing URL: ${url}`);
|
|
111
|
-
const fileName = path.basename(url);
|
|
112
|
-
const folderName = getFolderName(url);
|
|
113
|
-
const folderPath = path.join(DOCS_DIR, folderName);
|
|
114
|
-
await downloadFile(url, folderPath, fileName);
|
|
115
|
-
}
|
|
116
|
-
};
|
|
117
|
-
void main();
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Fetches the eBay API Status RSS feed and writes the latest items to docs/API_STATUS.md.
|
|
3
|
-
* Used by the GitHub Action to keep an in-repo snapshot. Run with: npx tsx src/scripts/updateApiStatusDoc.ts
|
|
4
|
-
*/
|
|
5
|
-
import { writeFileSync } from 'node:fs';
|
|
6
|
-
import { join } from 'node:path';
|
|
7
|
-
import { getApiStatusFeed } from '../utils/apiStatusFeed.js';
|
|
8
|
-
import { getErrorMessage } from '../utils/errors.js';
|
|
9
|
-
import { Data, Effect, Either } from 'effect';
|
|
10
|
-
import process from 'node:process';
|
|
11
|
-
const DEFAULT_LIMIT = 15;
|
|
12
|
-
const OUT_PATH = join(process.cwd(), 'docs', 'API_STATUS.md');
|
|
13
|
-
/** Tagged failure raised while updating the checked-in API status snapshot. */
|
|
14
|
-
class ApiStatusDocUpdateError extends Data.TaggedError('ApiStatusDocUpdateError') {
|
|
15
|
-
}
|
|
16
|
-
function escapeCell(s) {
|
|
17
|
-
return s.replace(/\|/g, '\\|').replace(/\n/g, ' ');
|
|
18
|
-
}
|
|
19
|
-
function buildMarkdown(items) {
|
|
20
|
-
const lines = [
|
|
21
|
-
'# eBay API Status (latest)',
|
|
22
|
-
'',
|
|
23
|
-
'Auto-updated snapshot from the [eBay API Status RSS feed](https://developer.ebay.com/rss/api-status).',
|
|
24
|
-
'Full list: [developer.ebay.com/support/api-status](https://developer.ebay.com/support/api-status).',
|
|
25
|
-
'',
|
|
26
|
-
`*Last updated: ${new Date().toISOString()}*`,
|
|
27
|
-
'',
|
|
28
|
-
'| Title | API | Site | Status | Last updated | Link |',
|
|
29
|
-
'|-------|-----|------|--------|--------------|------|',
|
|
30
|
-
];
|
|
31
|
-
for (const item of items) {
|
|
32
|
-
const link = item.link ? `[Details](${item.link})` : '';
|
|
33
|
-
lines.push(`| ${escapeCell(item.title)} | ${escapeCell(item.api)} | ${escapeCell(item.site)} | ${escapeCell(item.status)} | ${escapeCell(item.lastUpdated)} | ${link} |`);
|
|
34
|
-
}
|
|
35
|
-
lines.push('', '---', '', '*Generated by [ebay-mcp](https://github.com/YosefHayim/ebay-mcp) API status sync.*');
|
|
36
|
-
return lines.join('\n');
|
|
37
|
-
}
|
|
38
|
-
const updateApiStatusDoc = () => Effect.gen(function* () {
|
|
39
|
-
const { items, error } = yield* getApiStatusFeed({ limit: DEFAULT_LIMIT }).pipe(Effect.mapError((cause) => new ApiStatusDocUpdateError({
|
|
40
|
-
message: 'Failed to fetch API status feed',
|
|
41
|
-
cause,
|
|
42
|
-
})));
|
|
43
|
-
if (error && items.length === 0) {
|
|
44
|
-
return yield* Effect.fail(new ApiStatusDocUpdateError({
|
|
45
|
-
message: `Failed to fetch API status feed: ${error}`,
|
|
46
|
-
cause: error,
|
|
47
|
-
}));
|
|
48
|
-
}
|
|
49
|
-
const markdown = buildMarkdown(items);
|
|
50
|
-
yield* Effect.try({
|
|
51
|
-
try: () => writeFileSync(OUT_PATH, markdown, 'utf8'),
|
|
52
|
-
catch: (cause) => new ApiStatusDocUpdateError({
|
|
53
|
-
message: `Failed to write API status doc to ${OUT_PATH}`,
|
|
54
|
-
cause,
|
|
55
|
-
}),
|
|
56
|
-
});
|
|
57
|
-
return items.length;
|
|
58
|
-
});
|
|
59
|
-
async function main() {
|
|
60
|
-
const count = await Effect.runPromise(updateApiStatusDoc());
|
|
61
|
-
console.log(`Wrote ${count} items to ${OUT_PATH}`);
|
|
62
|
-
}
|
|
63
|
-
void Effect.runPromise(Effect.either(Effect.tryPromise({
|
|
64
|
-
try: main,
|
|
65
|
-
catch: (error) => error,
|
|
66
|
-
}))).then((result) => {
|
|
67
|
-
if (Either.isLeft(result)) {
|
|
68
|
-
console.error(getErrorMessage(result.left, String(result.left)));
|
|
69
|
-
process.exitCode = 1;
|
|
70
|
-
}
|
|
71
|
-
});
|
|
@@ -1,203 +0,0 @@
|
|
|
1
|
-
import { Effect, Schema } from 'effect';
|
|
2
|
-
import { z as zod } from 'zod';
|
|
3
|
-
import { attachEffectSchema, enumValues, getRequiredEffectSchema, literalUnion, objectEffectSchema, } from './effectSchemaAdapter.js';
|
|
4
|
-
import { EffectSchemaDecodeError, getParseMessage, getState, } from './effectSchemaTypes.js';
|
|
5
|
-
/**
|
|
6
|
-
* Returns true when a schema was created by this module and carries Effect metadata.
|
|
7
|
-
*
|
|
8
|
-
* @param schema - Unknown schema-like value to inspect.
|
|
9
|
-
* @returns Whether the value has an attached Effect Schema.
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* ```ts
|
|
13
|
-
* const backed = isEffectBackedSchema(z.string());
|
|
14
|
-
* ```
|
|
15
|
-
*/
|
|
16
|
-
export const isEffectBackedSchema = (schema) => getState(schema) !== undefined;
|
|
17
|
-
/**
|
|
18
|
-
* Reads the Effect Schema attached to a schema created by this module.
|
|
19
|
-
*
|
|
20
|
-
* @param schema - Effect-backed schema whose Effect metadata should be returned.
|
|
21
|
-
* @returns The attached Effect Schema, or `undefined` when the value is not backed.
|
|
22
|
-
*
|
|
23
|
-
* @example
|
|
24
|
-
* ```ts
|
|
25
|
-
* const schema = getEffectSchema(z.string());
|
|
26
|
-
* ```
|
|
27
|
-
*/
|
|
28
|
-
export const getEffectSchema = (schema) => getState(schema)?.schema;
|
|
29
|
-
/**
|
|
30
|
-
* Builds an Effect object schema from an MCP raw-shape object.
|
|
31
|
-
*
|
|
32
|
-
* @param shape - Tool input raw shape where every field was created by this module.
|
|
33
|
-
* @returns Effect Schema that decodes the whole argument object.
|
|
34
|
-
*
|
|
35
|
-
* @example
|
|
36
|
-
* ```ts
|
|
37
|
-
* const argsSchema = effectStructFromShape({ sku: z.string() });
|
|
38
|
-
* ```
|
|
39
|
-
*/
|
|
40
|
-
export const effectStructFromShape = (shape) => objectEffectSchema(shape);
|
|
41
|
-
/**
|
|
42
|
-
* Decodes unknown input through the Effect Schema attached to a schema value.
|
|
43
|
-
*
|
|
44
|
-
* @param schema - Effect-backed schema to decode with.
|
|
45
|
-
* @param value - Unknown runtime value from the MCP/client boundary.
|
|
46
|
-
* @returns Effect producing the decoded value or a tagged decode error.
|
|
47
|
-
*
|
|
48
|
-
* @example
|
|
49
|
-
* ```ts
|
|
50
|
-
* const decoded = await Effect.runPromise(decodeEffectSchema(z.object({ sku: z.string() }), args));
|
|
51
|
-
* ```
|
|
52
|
-
*/
|
|
53
|
-
export const decodeEffectSchema = (schema, value) => {
|
|
54
|
-
const effectSchema = getEffectSchema(schema);
|
|
55
|
-
if (!effectSchema || Schema.isPropertySignature(effectSchema)) {
|
|
56
|
-
return Effect.fail(new EffectSchemaDecodeError({
|
|
57
|
-
cause: schema,
|
|
58
|
-
message: 'Schema does not carry a decodable Effect Schema',
|
|
59
|
-
}));
|
|
60
|
-
}
|
|
61
|
-
const decodableSchema = effectSchema;
|
|
62
|
-
return Schema.decodeUnknown(decodableSchema)(value).pipe(Effect.map((decoded) => decoded), Effect.mapError((error) => new EffectSchemaDecodeError({
|
|
63
|
-
cause: error,
|
|
64
|
-
message: getParseMessage(error),
|
|
65
|
-
})));
|
|
66
|
-
};
|
|
67
|
-
/**
|
|
68
|
-
* Synchronously decodes unknown input through an attached Effect Schema.
|
|
69
|
-
*
|
|
70
|
-
* @param schema - Effect-backed schema to decode with.
|
|
71
|
-
* @param value - Unknown runtime value from the MCP/client boundary.
|
|
72
|
-
* @returns Decoded value produced by the attached Effect Schema.
|
|
73
|
-
*
|
|
74
|
-
* @example
|
|
75
|
-
* ```ts
|
|
76
|
-
* const args = decodeEffectSchemaSync(z.object({ sku: z.string() }), rawArgs);
|
|
77
|
-
* ```
|
|
78
|
-
*/
|
|
79
|
-
export const decodeEffectSchemaSync = (schema, value) => Effect.runSync(decodeEffectSchema(schema, value));
|
|
80
|
-
/**
|
|
81
|
-
* Zod-shaped schema factory backed by Effect Schema metadata.
|
|
82
|
-
*
|
|
83
|
-
* @example
|
|
84
|
-
* ```ts
|
|
85
|
-
* const schema = z.object({
|
|
86
|
-
* sku: z.string().describe('Seller-defined SKU'),
|
|
87
|
-
* limit: z.number().int().positive().optional(),
|
|
88
|
-
* });
|
|
89
|
-
* ```
|
|
90
|
-
*/
|
|
91
|
-
export const z = {
|
|
92
|
-
array(schema, options) {
|
|
93
|
-
const effectSchema = Schema.Array(getRequiredEffectSchema(schema));
|
|
94
|
-
const baseSchema = options?.description
|
|
95
|
-
? effectSchema.annotations({ description: options.description })
|
|
96
|
-
: effectSchema;
|
|
97
|
-
return attachEffectSchema(zod.array(schema, options), {
|
|
98
|
-
kind: 'array',
|
|
99
|
-
requiredSchema: baseSchema,
|
|
100
|
-
schema: baseSchema,
|
|
101
|
-
});
|
|
102
|
-
},
|
|
103
|
-
boolean(options) {
|
|
104
|
-
const baseSchema = options?.description
|
|
105
|
-
? Schema.Boolean.annotations({ description: options.description })
|
|
106
|
-
: Schema.Boolean;
|
|
107
|
-
return attachEffectSchema(zod.boolean(options), {
|
|
108
|
-
kind: 'boolean',
|
|
109
|
-
requiredSchema: baseSchema,
|
|
110
|
-
schema: baseSchema,
|
|
111
|
-
});
|
|
112
|
-
},
|
|
113
|
-
custom(check, params) {
|
|
114
|
-
const effectSchema = check
|
|
115
|
-
? Schema.filter((value) => check(value))(Schema.Unknown)
|
|
116
|
-
: Schema.Unknown;
|
|
117
|
-
return attachEffectSchema(zod.custom(check, params), {
|
|
118
|
-
kind: 'unknown',
|
|
119
|
-
requiredSchema: effectSchema,
|
|
120
|
-
schema: effectSchema,
|
|
121
|
-
});
|
|
122
|
-
},
|
|
123
|
-
enum(values) {
|
|
124
|
-
const effectSchema = literalUnion(values);
|
|
125
|
-
return attachEffectSchema(zod.enum(values), {
|
|
126
|
-
kind: 'string',
|
|
127
|
-
requiredSchema: effectSchema,
|
|
128
|
-
schema: effectSchema,
|
|
129
|
-
});
|
|
130
|
-
},
|
|
131
|
-
nativeEnum(enumLike) {
|
|
132
|
-
const effectSchema = literalUnion(enumValues(enumLike));
|
|
133
|
-
return attachEffectSchema(zod.nativeEnum(enumLike), {
|
|
134
|
-
kind: 'string',
|
|
135
|
-
requiredSchema: effectSchema,
|
|
136
|
-
schema: effectSchema,
|
|
137
|
-
});
|
|
138
|
-
},
|
|
139
|
-
never() {
|
|
140
|
-
const effectSchema = Schema.Never;
|
|
141
|
-
return attachEffectSchema(zod.never(), {
|
|
142
|
-
kind: 'unknown',
|
|
143
|
-
requiredSchema: effectSchema,
|
|
144
|
-
schema: effectSchema,
|
|
145
|
-
});
|
|
146
|
-
},
|
|
147
|
-
number(options) {
|
|
148
|
-
const effectSchema = Schema.Number;
|
|
149
|
-
return attachEffectSchema(zod.number(options), {
|
|
150
|
-
kind: 'number',
|
|
151
|
-
requiredSchema: effectSchema,
|
|
152
|
-
schema: effectSchema,
|
|
153
|
-
});
|
|
154
|
-
},
|
|
155
|
-
object(shape, options) {
|
|
156
|
-
const effectSchema = objectEffectSchema(shape);
|
|
157
|
-
const baseSchema = options?.description
|
|
158
|
-
? effectSchema.annotations({ description: options.description })
|
|
159
|
-
: effectSchema;
|
|
160
|
-
return attachEffectSchema(zod.object(shape, options), {
|
|
161
|
-
kind: 'object',
|
|
162
|
-
requiredSchema: baseSchema,
|
|
163
|
-
schema: baseSchema,
|
|
164
|
-
});
|
|
165
|
-
},
|
|
166
|
-
record(keyOrValue, valueSchema) {
|
|
167
|
-
const schema = valueSchema ?? keyOrValue;
|
|
168
|
-
const effectSchema = Schema.Record({
|
|
169
|
-
key: valueSchema ? getRequiredEffectSchema(keyOrValue) : Schema.String,
|
|
170
|
-
value: getRequiredEffectSchema(schema),
|
|
171
|
-
});
|
|
172
|
-
return attachEffectSchema(valueSchema ? zod.record(keyOrValue, valueSchema) : zod.record(schema), {
|
|
173
|
-
kind: 'record',
|
|
174
|
-
requiredSchema: effectSchema,
|
|
175
|
-
schema: effectSchema,
|
|
176
|
-
});
|
|
177
|
-
},
|
|
178
|
-
string(options) {
|
|
179
|
-
const baseSchema = options?.description
|
|
180
|
-
? Schema.String.annotations({ description: options.description })
|
|
181
|
-
: Schema.String;
|
|
182
|
-
return attachEffectSchema(zod.string(options), {
|
|
183
|
-
kind: 'string',
|
|
184
|
-
requiredSchema: baseSchema,
|
|
185
|
-
schema: baseSchema,
|
|
186
|
-
});
|
|
187
|
-
},
|
|
188
|
-
union(options) {
|
|
189
|
-
const effectSchema = Schema.Union(...options.map((option) => getRequiredEffectSchema(option)));
|
|
190
|
-
return attachEffectSchema(zod.union(options), {
|
|
191
|
-
kind: 'unknown',
|
|
192
|
-
requiredSchema: effectSchema,
|
|
193
|
-
schema: effectSchema,
|
|
194
|
-
});
|
|
195
|
-
},
|
|
196
|
-
unknown() {
|
|
197
|
-
return attachEffectSchema(zod.unknown(), {
|
|
198
|
-
kind: 'unknown',
|
|
199
|
-
requiredSchema: Schema.Unknown,
|
|
200
|
-
schema: Schema.Unknown,
|
|
201
|
-
});
|
|
202
|
-
},
|
|
203
|
-
};
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import { Schema } from 'effect';
|
|
2
|
-
import { attachChainableEffectMethods } from './effectSchemaChainMethods.js';
|
|
3
|
-
import { EFFECT_SCHEMA_STATE, } from './effectSchemaTypes.js';
|
|
4
|
-
const getEffectState = (schema) => {
|
|
5
|
-
if (!(typeof schema === 'object' && schema !== null && EFFECT_SCHEMA_STATE in schema)) {
|
|
6
|
-
return;
|
|
7
|
-
}
|
|
8
|
-
return schema[EFFECT_SCHEMA_STATE];
|
|
9
|
-
};
|
|
10
|
-
const buildObjectEffectSchema = (shape) => {
|
|
11
|
-
const effectShape = {};
|
|
12
|
-
for (const [key, fieldSchema] of Object.entries(shape)) {
|
|
13
|
-
effectShape[key] = getFieldEffectSchema(fieldSchema);
|
|
14
|
-
}
|
|
15
|
-
return Schema.Struct(effectShape);
|
|
16
|
-
};
|
|
17
|
-
/**
|
|
18
|
-
* Reads the required Effect Schema for an adapter-backed schema value.
|
|
19
|
-
*
|
|
20
|
-
* @param schema - Schema value created by the adapter.
|
|
21
|
-
* @returns Required Effect Schema, or `Schema.Unknown` when metadata is missing.
|
|
22
|
-
*
|
|
23
|
-
* @example
|
|
24
|
-
* ```ts
|
|
25
|
-
* const effectSchema = getRequiredEffectSchema(z.string().optional());
|
|
26
|
-
* ```
|
|
27
|
-
*/
|
|
28
|
-
export const getRequiredEffectSchema = (schema) => {
|
|
29
|
-
const state = getEffectState(schema);
|
|
30
|
-
if (!state) {
|
|
31
|
-
return Schema.Unknown;
|
|
32
|
-
}
|
|
33
|
-
return state.requiredSchema;
|
|
34
|
-
};
|
|
35
|
-
/**
|
|
36
|
-
* Reads the field-level Effect Schema for an adapter-backed schema value.
|
|
37
|
-
*
|
|
38
|
-
* @param schema - Schema value created by the adapter.
|
|
39
|
-
* @returns Current field Effect Schema, preserving optional/default wrappers when present.
|
|
40
|
-
*
|
|
41
|
-
* @example
|
|
42
|
-
* ```ts
|
|
43
|
-
* const fieldSchema = getFieldEffectSchema(z.string().optional());
|
|
44
|
-
* ```
|
|
45
|
-
*/
|
|
46
|
-
export const getFieldEffectSchema = (schema) => {
|
|
47
|
-
const state = getEffectState(schema);
|
|
48
|
-
if (!state) {
|
|
49
|
-
return Schema.Unknown;
|
|
50
|
-
}
|
|
51
|
-
return state.schema;
|
|
52
|
-
};
|
|
53
|
-
/**
|
|
54
|
-
* Builds an Effect object schema from an adapter-backed raw shape.
|
|
55
|
-
*
|
|
56
|
-
* @param shape - Zod-compatible raw shape whose fields carry Effect metadata.
|
|
57
|
-
* @returns Effect Schema struct for the object shape.
|
|
58
|
-
*
|
|
59
|
-
* @example
|
|
60
|
-
* ```ts
|
|
61
|
-
* const effectSchema = objectEffectSchema({ sku: z.string() });
|
|
62
|
-
* ```
|
|
63
|
-
*/
|
|
64
|
-
export const objectEffectSchema = (shape) => buildObjectEffectSchema(shape);
|
|
65
|
-
/**
|
|
66
|
-
* Extracts string values from a TypeScript enum-like object.
|
|
67
|
-
*
|
|
68
|
-
* @param enumLike - Enum-like object accepted by `z.nativeEnum`.
|
|
69
|
-
* @returns Non-empty tuple of unique string enum values.
|
|
70
|
-
*
|
|
71
|
-
* @example
|
|
72
|
-
* ```ts
|
|
73
|
-
* const values = enumValues(MarketplaceId);
|
|
74
|
-
* ```
|
|
75
|
-
*/
|
|
76
|
-
export const enumValues = (enumLike) => {
|
|
77
|
-
const values = Object.values(enumLike).filter((value) => typeof value === 'string');
|
|
78
|
-
const [first, ...rest] = [...new Set(values)];
|
|
79
|
-
if (!first) {
|
|
80
|
-
return [''];
|
|
81
|
-
}
|
|
82
|
-
return [first, ...rest];
|
|
83
|
-
};
|
|
84
|
-
/**
|
|
85
|
-
* Builds an Effect literal union from string values.
|
|
86
|
-
*
|
|
87
|
-
* @param values - Non-empty list of literal string values.
|
|
88
|
-
* @returns Effect Schema accepting exactly those values.
|
|
89
|
-
*
|
|
90
|
-
* @example
|
|
91
|
-
* ```ts
|
|
92
|
-
* const schema = literalUnion(['ACTIVE', 'PAUSED']);
|
|
93
|
-
* ```
|
|
94
|
-
*/
|
|
95
|
-
export const literalUnion = (values) => Schema.Literal(...values);
|
|
96
|
-
/**
|
|
97
|
-
* Attaches Effect Schema metadata to a Zod-compatible schema carrier.
|
|
98
|
-
*
|
|
99
|
-
* @param zodSchema - Zod schema object exposed to MCP SDK and JSON-schema tooling.
|
|
100
|
-
* @param state - Effect metadata used for runtime decode and chained refinements.
|
|
101
|
-
* @returns The same schema carrier with hidden Effect metadata attached.
|
|
102
|
-
*
|
|
103
|
-
* @example
|
|
104
|
-
* ```ts
|
|
105
|
-
* const schema = attachEffectSchema(zod.string(), {
|
|
106
|
-
* kind: 'string',
|
|
107
|
-
* requiredSchema: Schema.String,
|
|
108
|
-
* schema: Schema.String,
|
|
109
|
-
* });
|
|
110
|
-
* ```
|
|
111
|
-
*/
|
|
112
|
-
export const attachEffectSchema = (zodSchema, state) => {
|
|
113
|
-
const schema = zodSchema;
|
|
114
|
-
Object.defineProperty(schema, EFFECT_SCHEMA_STATE, {
|
|
115
|
-
configurable: false,
|
|
116
|
-
enumerable: false,
|
|
117
|
-
value: state,
|
|
118
|
-
});
|
|
119
|
-
attachChainableEffectMethods(schema, state, attachEffectSchema, buildObjectEffectSchema);
|
|
120
|
-
return schema;
|
|
121
|
-
};
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import { Schema } from 'effect';
|
|
2
|
-
import { annotateSchema, defaultValueGetter, refineInt, refineMax, refineMin, refinePositive, } from './effectSchemaRefinements.js';
|
|
3
|
-
import { attachStringEffectMethods } from './effectSchemaStringMethods.js';
|
|
4
|
-
const patchDescribeMethod = (schema, state, attachEffectSchema) => {
|
|
5
|
-
if (typeof schema.describe !== 'function') {
|
|
6
|
-
return;
|
|
7
|
-
}
|
|
8
|
-
const describe = schema.describe.bind(schema);
|
|
9
|
-
schema.describe = (description) => attachEffectSchema(describe(description), {
|
|
10
|
-
...state,
|
|
11
|
-
requiredSchema: annotateSchema(state.requiredSchema, description),
|
|
12
|
-
schema: annotateSchema(state.schema, description),
|
|
13
|
-
});
|
|
14
|
-
};
|
|
15
|
-
const patchOptionalMethod = (schema, state, attachEffectSchema) => {
|
|
16
|
-
if (typeof schema.optional !== 'function') {
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
const optional = schema.optional.bind(schema);
|
|
20
|
-
schema.optional = () => attachEffectSchema(optional(), {
|
|
21
|
-
...state,
|
|
22
|
-
schema: Schema.optional(state.requiredSchema),
|
|
23
|
-
});
|
|
24
|
-
};
|
|
25
|
-
const patchDefaultMethod = (schema, state, attachEffectSchema) => {
|
|
26
|
-
if (typeof schema.default !== 'function') {
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
const defaultSchema = schema.default.bind(schema);
|
|
30
|
-
schema.default = (value) => attachEffectSchema(defaultSchema(value), {
|
|
31
|
-
...state,
|
|
32
|
-
schema: Schema.optionalWith(state.requiredSchema, { default: defaultValueGetter(value) }),
|
|
33
|
-
});
|
|
34
|
-
};
|
|
35
|
-
const patchPassthroughMethod = (schema, state, attachEffectSchema) => {
|
|
36
|
-
if (typeof schema.passthrough !== 'function') {
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
const passthrough = schema.passthrough.bind(schema);
|
|
40
|
-
schema.passthrough = () => {
|
|
41
|
-
const passthroughEffectSchema = Schema.extend(state.requiredSchema, Schema.Record({ key: Schema.String, value: Schema.Unknown }));
|
|
42
|
-
return attachEffectSchema(passthrough(), {
|
|
43
|
-
kind: state.kind,
|
|
44
|
-
requiredSchema: passthroughEffectSchema,
|
|
45
|
-
schema: passthroughEffectSchema,
|
|
46
|
-
});
|
|
47
|
-
};
|
|
48
|
-
};
|
|
49
|
-
const patchExtendMethod = (schema, state, attachEffectSchema, buildObjectEffectSchema) => {
|
|
50
|
-
if (typeof schema.extend !== 'function') {
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
const extend = schema.extend.bind(schema);
|
|
54
|
-
schema.extend = (shape) => {
|
|
55
|
-
const extensionEffectSchema = buildObjectEffectSchema(shape);
|
|
56
|
-
const effectSchema = Schema.extend(state.requiredSchema, extensionEffectSchema);
|
|
57
|
-
return attachEffectSchema(extend(shape), {
|
|
58
|
-
kind: state.kind,
|
|
59
|
-
requiredSchema: effectSchema,
|
|
60
|
-
schema: effectSchema,
|
|
61
|
-
});
|
|
62
|
-
};
|
|
63
|
-
};
|
|
64
|
-
const patchMinMethod = (schema, state, attachEffectSchema) => {
|
|
65
|
-
if (typeof schema.min !== 'function') {
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
const min = schema.min.bind(schema);
|
|
69
|
-
schema.min = (value, message) => {
|
|
70
|
-
const effectSchema = refineMin(state.requiredSchema, state.kind, value);
|
|
71
|
-
return attachEffectSchema(min(value, message), {
|
|
72
|
-
...state,
|
|
73
|
-
requiredSchema: effectSchema,
|
|
74
|
-
schema: effectSchema,
|
|
75
|
-
});
|
|
76
|
-
};
|
|
77
|
-
};
|
|
78
|
-
const patchMaxMethod = (schema, state, attachEffectSchema) => {
|
|
79
|
-
if (typeof schema.max !== 'function') {
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
const max = schema.max.bind(schema);
|
|
83
|
-
schema.max = (value, message) => {
|
|
84
|
-
const effectSchema = refineMax(state.requiredSchema, state.kind, value);
|
|
85
|
-
return attachEffectSchema(max(value, message), {
|
|
86
|
-
...state,
|
|
87
|
-
requiredSchema: effectSchema,
|
|
88
|
-
schema: effectSchema,
|
|
89
|
-
});
|
|
90
|
-
};
|
|
91
|
-
};
|
|
92
|
-
const patchPositiveMethod = (schema, state, attachEffectSchema) => {
|
|
93
|
-
if (typeof schema.positive !== 'function') {
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
const positive = schema.positive.bind(schema);
|
|
97
|
-
schema.positive = (message) => {
|
|
98
|
-
const effectSchema = refinePositive(state.requiredSchema, state.kind);
|
|
99
|
-
return attachEffectSchema(positive(message), {
|
|
100
|
-
...state,
|
|
101
|
-
requiredSchema: effectSchema,
|
|
102
|
-
schema: effectSchema,
|
|
103
|
-
});
|
|
104
|
-
};
|
|
105
|
-
};
|
|
106
|
-
const patchIntMethod = (schema, state, attachEffectSchema) => {
|
|
107
|
-
if (typeof schema.int !== 'function') {
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
const int = schema.int.bind(schema);
|
|
111
|
-
schema.int = (message) => {
|
|
112
|
-
const effectSchema = refineInt(state.requiredSchema, state.kind);
|
|
113
|
-
return attachEffectSchema(int(message), {
|
|
114
|
-
...state,
|
|
115
|
-
requiredSchema: effectSchema,
|
|
116
|
-
schema: effectSchema,
|
|
117
|
-
});
|
|
118
|
-
};
|
|
119
|
-
};
|
|
120
|
-
/**
|
|
121
|
-
* Rebinds chainable Zod compatibility methods so Effect metadata stays attached.
|
|
122
|
-
*
|
|
123
|
-
* @param schemaCarrier - Zod-compatible schema carrier receiving patched chain methods.
|
|
124
|
-
* @param state - Effect metadata that belongs to the current schema carrier.
|
|
125
|
-
* @param attachEffectSchema - Adapter function used to attach metadata to returned schemas.
|
|
126
|
-
* @param buildObjectEffectSchema - Object-shape builder used by `.extend()`.
|
|
127
|
-
* @returns Nothing; the schema carrier is patched in place.
|
|
128
|
-
*
|
|
129
|
-
* @example
|
|
130
|
-
* ```ts
|
|
131
|
-
* attachChainableEffectMethods(schema, state, attachEffectSchema, objectEffectSchema);
|
|
132
|
-
* ```
|
|
133
|
-
*/
|
|
134
|
-
export const attachChainableEffectMethods = (schemaCarrier, state, attachEffectSchema, buildObjectEffectSchema) => {
|
|
135
|
-
const schema = schemaCarrier;
|
|
136
|
-
patchDescribeMethod(schema, state, attachEffectSchema);
|
|
137
|
-
patchOptionalMethod(schema, state, attachEffectSchema);
|
|
138
|
-
patchDefaultMethod(schema, state, attachEffectSchema);
|
|
139
|
-
patchPassthroughMethod(schema, state, attachEffectSchema);
|
|
140
|
-
patchExtendMethod(schema, state, attachEffectSchema, buildObjectEffectSchema);
|
|
141
|
-
patchMinMethod(schema, state, attachEffectSchema);
|
|
142
|
-
patchMaxMethod(schema, state, attachEffectSchema);
|
|
143
|
-
patchPositiveMethod(schema, state, attachEffectSchema);
|
|
144
|
-
patchIntMethod(schema, state, attachEffectSchema);
|
|
145
|
-
attachStringEffectMethods(schema, state, attachEffectSchema);
|
|
146
|
-
};
|