ebay-mcp 1.13.2 → 1.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.de.md +3 -3
- package/README.es.md +3 -3
- package/README.fr.md +3 -3
- package/README.ja.md +3 -3
- package/README.ko.md +3 -3
- package/README.md +163 -41
- package/README.pt-BR.md +3 -3
- package/README.ru.md +3 -3
- package/README.zh-CN.md +3 -3
- package/build/api/account-management/account.js +633 -297
- package/build/api/analytics-and-report/analytics.js +111 -65
- package/build/api/client.js +199 -140
- package/build/api/clientRequestError.js +23 -0
- package/build/api/clientTrading.js +213 -0
- package/build/api/clientTradingError.js +4 -0
- package/build/api/communication/feedback.js +147 -59
- package/build/api/communication/message.js +134 -81
- package/build/api/communication/negotiation.js +65 -53
- package/build/api/communication/notification.js +458 -164
- package/build/api/developer/developer.js +99 -45
- package/build/api/index.js +23 -8
- package/build/api/listing-management/inventory.js +884 -338
- package/build/api/listing-metadata/metadata.js +416 -170
- package/build/api/listing-metadata/taxonomy.js +187 -42
- package/build/api/marketing-and-promotions/marketing.js +1392 -598
- package/build/api/marketing-and-promotions/recommendation.js +49 -24
- package/build/api/order-management/dispute.js +226 -45
- package/build/api/order-management/fulfillment.js +144 -71
- package/build/api/order-management/orderIssueHelpers.js +61 -0
- package/build/api/other/compliance.js +50 -38
- package/build/api/other/edelivery.js +603 -159
- package/build/api/other/finding.js +280 -0
- package/build/api/other/identity.js +30 -15
- package/build/api/other/translation.js +29 -14
- package/build/api/other/vero.js +113 -27
- package/build/api/rateLimitTracker.js +55 -0
- package/build/api/shared/request.js +189 -98
- package/build/api/trading/trading.js +154 -87
- package/build/auth/credentialSession.js +250 -0
- package/build/auth/oauth.js +298 -171
- package/build/auth/{oauth-metadata.js → oauthMetadata.js} +22 -6
- package/build/auth/oauthMiddleware.js +104 -0
- package/build/auth/{scope-utils.js → scopeUtils.js} +101 -28
- package/build/auth/tokenVerifier.js +243 -0
- package/build/auth/tokenVerifierError.js +21 -0
- package/build/config/environment.js +148 -113
- package/build/config/{tool-families.js → toolFamilies.js} +30 -14
- package/build/index.js +25 -19
- package/build/mcp/{http-transport.js → httpTransport.js} +102 -52
- package/build/mcp/readOnlyFilter.js +67 -0
- package/build/mcp/runtime.js +31 -13
- package/build/mcp/{tool-gating.js → toolGating.js} +77 -49
- package/build/mcp/{ui-bridge.js → uiBridge.js} +80 -23
- package/build/schemas/account-management/account.js +144 -6
- package/build/schemas/analytics/analytics.js +33 -19
- package/build/schemas/communication/messages.js +12 -42
- package/build/schemas/developer/developer.js +135 -0
- package/build/schemas/fulfillment/orders.js +183 -21
- package/build/schemas/index.js +27 -19
- package/build/schemas/inventory-management/inventory.js +17 -9
- package/build/schemas/marketing/marketing.js +480 -25
- package/build/schemas/metadata/metadata.js +11 -6
- package/build/schemas/other/finding.js +27 -0
- package/build/schemas/other/otherApis.js +424 -0
- package/build/schemas/taxonomy/taxonomy.js +11 -5
- package/build/scripts/{auto-setup.js → autoSetup.js} +87 -74
- package/build/scripts/{build-ui.js → buildUi.js} +6 -1
- package/build/scripts/{dev-sync.js → devSync.js} +169 -110
- package/build/scripts/diagnostics.js +52 -44
- package/build/scripts/{download-specs.js → downloadSpecs.js} +29 -21
- package/build/scripts/{interactive-setup.js → interactiveSetup.js} +84 -78
- package/build/scripts/setup.js +241 -178
- package/build/scripts/{setup-shared.js → setupShared.js} +29 -7
- package/build/scripts/skills.js +35 -27
- package/build/scripts/updateApiStatusDoc.js +71 -0
- package/build/serverHttp.js +90 -0
- package/build/skills/content.js +124 -118
- package/build/skills/index.js +22 -10
- package/build/skills/install.js +21 -10
- package/build/skills/markers.js +50 -15
- package/build/skills/{registry-snapshot.js → registrySnapshot.js} +8 -2
- package/build/skills/render.js +41 -14
- package/build/skills/targets.js +49 -17
- package/build/tools/categories/account.js +166 -264
- package/build/tools/categories/analytics.js +11 -22
- package/build/tools/categories/browse.js +17 -0
- package/build/tools/categories/communication.js +124 -399
- package/build/tools/categories/connector.js +23 -20
- package/build/tools/categories/developer.js +46 -159
- package/build/tools/categories/fulfillment.js +84 -215
- package/build/tools/categories/index.js +6 -14
- package/build/tools/categories/inventory.js +238 -293
- package/build/tools/categories/marketing.js +677 -39
- package/build/tools/categories/metadata.js +190 -117
- package/build/tools/categories/other.js +81 -208
- package/build/tools/categories/taxonomy.js +29 -20
- package/build/tools/categories/{token-management.js → tokenManagement.js} +187 -192
- package/build/tools/categories/trading.js +16 -47
- package/build/tools/contracts.js +34 -24
- package/build/tools/{define-tool.js → defineTool.js} +44 -29
- package/build/tools/registry.js +87 -29
- package/build/tools/schemas.js +3 -57
- package/build/tools/ui/archetypes.js +1 -0
- package/build/tools/ui/{map-helpers.js → mapHelpers.js} +69 -19
- package/build/tools/ui/maps.js +294 -80
- package/build/types/index.js +1 -1
- package/build/ui/card.html +14 -14
- package/build/ui/chart.html +14 -14
- package/build/ui/stat.html +87 -0
- package/build/ui/table.html +14 -14
- package/build/utils/apiStatusFeed.js +95 -0
- package/build/utils/cliOutput.js +15 -0
- package/build/utils/cliUi.js +108 -0
- package/build/utils/communication/feedback.js +57 -77
- package/build/utils/communication/message.js +69 -98
- package/build/utils/communication/negotiation.js +30 -57
- package/build/utils/communication/notification.js +112 -252
- package/build/utils/{date-converter.js → dateConverter.js} +62 -30
- package/build/utils/effectSchema.js +203 -0
- package/build/utils/effectSchemaAdapter.js +121 -0
- package/build/utils/effectSchemaChainMethods.js +146 -0
- package/build/utils/effectSchemaRefinements.js +104 -0
- package/build/utils/effectSchemaStringMethods.js +63 -0
- package/build/utils/effectSchemaTypes.js +47 -0
- package/build/utils/{env-parser.js → envParser.js} +10 -2
- package/build/utils/errors.js +7 -3
- package/build/utils/http.js +148 -89
- package/build/utils/{llm-client-detector.js → llmClientDetector.js} +295 -274
- package/build/utils/logger.js +127 -51
- package/build/utils/{oauth-helper.js → oauthHelper.js} +127 -90
- package/build/utils/other/compliance.js +18 -38
- package/build/utils/other/identity.js +2 -2
- package/build/utils/other/translation.js +4 -4
- package/build/utils/other/vero.js +36 -20
- package/build/utils/schemaHelpers.js +22 -0
- package/build/utils/scopeHelper.js +270 -0
- package/build/utils/securityChecker.js +316 -0
- package/build/utils/{setup-validator.js → setupValidator.js} +113 -94
- package/build/utils/{setup-wizard.js → setupWizard.js} +57 -46
- package/build/utils/{token-utils.js → tokenUtils.js} +2 -2
- package/build/utils/trading/trading.js +35 -0
- package/build/utils/typeGuards.js +12 -0
- package/build/utils/version.js +65 -29
- package/package.json +10 -8
- package/build/api/client-trading.js +0 -124
- package/build/api/communication/shared.js +0 -59
- package/build/api/shared/query-params.js +0 -16
- package/build/auth/credential-session.js +0 -166
- package/build/auth/oauth-middleware.js +0 -100
- package/build/auth/token-verifier.js +0 -186
- package/build/schemas/other/other-apis.js +0 -390
- package/build/scripts/update-api-status-doc.js +0 -44
- package/build/server-http.js +0 -85
- package/build/tools/definitions/marketing.js +0 -1381
- package/build/tools/tool-handlers/marketing.js +0 -312
- package/build/utils/account-management/account.js +0 -818
- package/build/utils/api-status-feed.js +0 -84
- package/build/utils/cli-ui.js +0 -47
- package/build/utils/order-management/dispute.js +0 -369
- package/build/utils/order-management/fulfillment.js +0 -205
- package/build/utils/other/edelivery.js +0 -235
- package/build/utils/schema-helpers.js +0 -13
- package/build/utils/scope-helper.js +0 -207
- package/build/utils/security-checker.js +0 -248
- package/build/utils/type-guards.js +0 -6
- /package/build/auth/{oauth-types.js → oauthTypes.js} +0 -0
- /package/build/{server-http.d.ts → serverHttp.d.ts} +0 -0
- /package/build/tools/ui/{view-models.js → viewModels.js} +0 -0
- /package/build/types/{ebay-enums.js → ebayEnums.js} +0 -0
|
@@ -1,110 +1,101 @@
|
|
|
1
|
-
import { z } from '
|
|
2
|
-
import { idSchema } from '
|
|
1
|
+
import { z } from '../../utils/effectSchema.js';
|
|
2
|
+
import { idSchema } from '../../utils/schemaHelpers.js';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
* Based on: src/api/communication/notification.ts
|
|
4
|
+
* Effect-backed schemas for Notification API input validation.
|
|
6
5
|
* OpenAPI spec: docs/sell-apps/communication/commerce_notification_v1_oas3.json
|
|
7
|
-
* Types from: src/types/commerce_notification_v1_oas3.ts
|
|
8
6
|
*/
|
|
9
|
-
|
|
7
|
+
/** Optional positive page size accepted by Notification list endpoints. */
|
|
10
8
|
const limitSchema = z
|
|
11
|
-
.
|
|
12
|
-
invalid_type_error: 'limit must be a
|
|
9
|
+
.number({
|
|
10
|
+
invalid_type_error: 'limit must be a number',
|
|
13
11
|
description: 'Maximum number of items to return per page (10-100)',
|
|
14
12
|
})
|
|
13
|
+
.positive('limit must be a positive number')
|
|
15
14
|
.optional();
|
|
16
|
-
|
|
15
|
+
/** Optional continuation cursor accepted by Notification list endpoints. */
|
|
17
16
|
const continuationTokenSchema = z
|
|
18
17
|
.string({
|
|
19
18
|
message: 'Continuation token must be a string',
|
|
20
|
-
invalid_type_error: '
|
|
19
|
+
invalid_type_error: 'continuationToken must be a string',
|
|
21
20
|
description: 'Token for pagination',
|
|
22
21
|
})
|
|
23
22
|
.optional();
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
23
|
+
/** Destination delivery configuration schema shared by destination write tools. */
|
|
24
|
+
const deliveryConfigSchema = z
|
|
25
|
+
.object({
|
|
26
|
+
endpoint: z
|
|
27
|
+
.string({
|
|
28
|
+
invalid_type_error: 'endpoint must be a string',
|
|
29
|
+
description: 'HTTPS endpoint URL',
|
|
30
|
+
})
|
|
31
|
+
.url({
|
|
32
|
+
message: 'endpoint must be a valid URL',
|
|
33
|
+
})
|
|
34
|
+
.optional(),
|
|
35
|
+
verificationToken: z
|
|
36
|
+
.string({
|
|
37
|
+
invalid_type_error: 'verificationToken must be a string',
|
|
38
|
+
description: 'Verification token (32-80 alphanumeric, underscore, hyphen characters)',
|
|
39
|
+
})
|
|
40
|
+
.min(32, 'verificationToken must be at least 32 characters')
|
|
41
|
+
.max(80, 'verificationToken must be at most 80 characters')
|
|
42
|
+
.regex(/^[a-zA-Z0-9_-]+$/, 'verificationToken can only contain alphanumeric, underscore, and hyphen characters')
|
|
43
|
+
.optional(),
|
|
44
|
+
})
|
|
45
|
+
.optional();
|
|
46
|
+
/** Subscription payload detail schema shared by subscription write tools. */
|
|
47
|
+
const payloadSchema = z
|
|
48
|
+
.object({
|
|
49
|
+
deliveryProtocol: z
|
|
50
|
+
.string({
|
|
51
|
+
invalid_type_error: 'deliveryProtocol must be a string',
|
|
52
|
+
description: 'Delivery protocol',
|
|
53
|
+
})
|
|
54
|
+
.optional(),
|
|
55
|
+
format: z
|
|
56
|
+
.string({
|
|
57
|
+
invalid_type_error: 'format must be a string',
|
|
58
|
+
description: 'Payload format',
|
|
59
|
+
})
|
|
60
|
+
.optional(),
|
|
61
|
+
schemaVersion: z
|
|
62
|
+
.string({
|
|
63
|
+
invalid_type_error: 'schemaVersion must be a string',
|
|
64
|
+
description: 'Schema version for the notification topic',
|
|
65
|
+
})
|
|
66
|
+
.optional(),
|
|
67
|
+
})
|
|
68
|
+
.optional();
|
|
69
|
+
/** Schema for getPublicKey input. */
|
|
36
70
|
export const getPublicKeySchema = z.object({
|
|
37
|
-
|
|
71
|
+
publicKeyId: idSchema('Public key ID', 'The unique identifier for the public key'),
|
|
38
72
|
});
|
|
39
|
-
/**
|
|
40
|
-
* Schema for getConfig method
|
|
41
|
-
* Endpoint: GET /config
|
|
42
|
-
*/
|
|
73
|
+
/** Schema for getConfig input. */
|
|
43
74
|
export const getConfigSchema = z.object({});
|
|
44
|
-
/**
|
|
45
|
-
* Schema for updateConfig method
|
|
46
|
-
* Endpoint: PUT /config
|
|
47
|
-
* Body: ConfigType - alertEmail
|
|
48
|
-
*/
|
|
75
|
+
/** Schema for updateConfig input. */
|
|
49
76
|
export const updateConfigSchema = z.object({
|
|
50
|
-
|
|
77
|
+
alertEmail: z
|
|
51
78
|
.string({
|
|
52
|
-
invalid_type_error: '
|
|
79
|
+
invalid_type_error: 'alertEmail must be a string',
|
|
53
80
|
description: 'Email address for Notification API alerts',
|
|
54
81
|
})
|
|
55
82
|
.email({
|
|
56
|
-
message: '
|
|
83
|
+
message: 'alertEmail must be a valid email address',
|
|
57
84
|
})
|
|
58
85
|
.optional(),
|
|
59
86
|
});
|
|
60
|
-
/**
|
|
61
|
-
* Schema for getDestinations method
|
|
62
|
-
* Endpoint: GET /destination
|
|
63
|
-
* Query: DestinationParams - continuation_token, limit
|
|
64
|
-
*/
|
|
87
|
+
/** Schema for getDestinations input. */
|
|
65
88
|
export const getDestinationsSchema = z.object({
|
|
66
|
-
|
|
89
|
+
continuationToken: continuationTokenSchema,
|
|
67
90
|
limit: limitSchema,
|
|
68
91
|
});
|
|
69
|
-
/**
|
|
70
|
-
* Schema for getDestination method
|
|
71
|
-
* Endpoint: GET /destination/{destination_id}
|
|
72
|
-
* Path: destination_id (required)
|
|
73
|
-
*/
|
|
92
|
+
/** Schema for getDestination input. */
|
|
74
93
|
export const getDestinationSchema = z.object({
|
|
75
|
-
|
|
94
|
+
destinationId: idSchema('Destination ID', 'The unique identifier for the destination'),
|
|
76
95
|
});
|
|
77
|
-
/**
|
|
78
|
-
* Schema for createDestination method
|
|
79
|
-
* Endpoint: POST /destination
|
|
80
|
-
* Body: DestinationRequest - deliveryConfig, name, status
|
|
81
|
-
*/
|
|
96
|
+
/** Schema for createDestination input. */
|
|
82
97
|
export const createDestinationSchema = z.object({
|
|
83
|
-
|
|
84
|
-
.object({
|
|
85
|
-
endpoint: z
|
|
86
|
-
.string({
|
|
87
|
-
invalid_type_error: 'endpoint must be a string',
|
|
88
|
-
description: 'HTTPS endpoint URL (no internal IPs or localhost)',
|
|
89
|
-
})
|
|
90
|
-
.url({
|
|
91
|
-
message: 'endpoint must be a valid URL',
|
|
92
|
-
})
|
|
93
|
-
.optional(),
|
|
94
|
-
verification_token: z
|
|
95
|
-
.string({
|
|
96
|
-
invalid_type_error: 'verification_token must be a string',
|
|
97
|
-
description: 'Verification token (32-80 alphanumeric, underscore, hyphen characters)',
|
|
98
|
-
})
|
|
99
|
-
.min(32, 'verification_token must be at least 32 characters')
|
|
100
|
-
.max(80, 'verification_token must be at most 80 characters')
|
|
101
|
-
.regex(/^[a-zA-Z0-9_-]+$/, 'verification_token can only contain alphanumeric, underscore, and hyphen characters')
|
|
102
|
-
.optional(),
|
|
103
|
-
}, {
|
|
104
|
-
invalid_type_error: 'delivery_config must be an object',
|
|
105
|
-
description: 'Delivery configuration with endpoint and verification token',
|
|
106
|
-
})
|
|
107
|
-
.optional(),
|
|
98
|
+
deliveryConfig: deliveryConfigSchema,
|
|
108
99
|
name: z
|
|
109
100
|
.string({
|
|
110
101
|
invalid_type_error: 'name must be a string',
|
|
@@ -118,36 +109,10 @@ export const createDestinationSchema = z.object({
|
|
|
118
109
|
})
|
|
119
110
|
.optional(),
|
|
120
111
|
});
|
|
121
|
-
/**
|
|
122
|
-
* Schema for updateDestination method
|
|
123
|
-
* Endpoint: PUT /destination/{destination_id}
|
|
124
|
-
* Path: destination_id (required)
|
|
125
|
-
* Body: DestinationRequest
|
|
126
|
-
*/
|
|
112
|
+
/** Schema for updateDestination input. */
|
|
127
113
|
export const updateDestinationSchema = z.object({
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
.object({
|
|
131
|
-
endpoint: z
|
|
132
|
-
.string({
|
|
133
|
-
invalid_type_error: 'endpoint must be a string',
|
|
134
|
-
description: 'HTTPS endpoint URL',
|
|
135
|
-
})
|
|
136
|
-
.url({
|
|
137
|
-
message: 'endpoint must be a valid URL',
|
|
138
|
-
})
|
|
139
|
-
.optional(),
|
|
140
|
-
verification_token: z
|
|
141
|
-
.string({
|
|
142
|
-
invalid_type_error: 'verification_token must be a string',
|
|
143
|
-
description: 'Verification token (32-80 characters)',
|
|
144
|
-
})
|
|
145
|
-
.min(32)
|
|
146
|
-
.max(80)
|
|
147
|
-
.regex(/^[a-zA-Z0-9_-]+$/)
|
|
148
|
-
.optional(),
|
|
149
|
-
})
|
|
150
|
-
.optional(),
|
|
114
|
+
destinationId: idSchema('Destination ID', 'The unique identifier for the destination'),
|
|
115
|
+
deliveryConfig: deliveryConfigSchema,
|
|
151
116
|
name: z
|
|
152
117
|
.string({
|
|
153
118
|
invalid_type_error: 'name must be a string',
|
|
@@ -161,117 +126,51 @@ export const updateDestinationSchema = z.object({
|
|
|
161
126
|
})
|
|
162
127
|
.optional(),
|
|
163
128
|
});
|
|
164
|
-
/**
|
|
165
|
-
* Schema for deleteDestination method
|
|
166
|
-
* Endpoint: DELETE /destination/{destination_id}
|
|
167
|
-
* Path: destination_id (required)
|
|
168
|
-
*/
|
|
129
|
+
/** Schema for deleteDestination input. */
|
|
169
130
|
export const deleteDestinationSchema = z.object({
|
|
170
|
-
|
|
131
|
+
destinationId: idSchema('Destination ID', 'The unique identifier for the destination'),
|
|
171
132
|
});
|
|
172
|
-
/**
|
|
173
|
-
* Schema for getSubscriptions method
|
|
174
|
-
* Endpoint: GET /subscription
|
|
175
|
-
* Query: SubscriptionParams - continuation_token, limit
|
|
176
|
-
*/
|
|
133
|
+
/** Schema for getSubscriptions input. */
|
|
177
134
|
export const getSubscriptionsSchema = z.object({
|
|
178
135
|
limit: limitSchema,
|
|
179
|
-
|
|
136
|
+
continuationToken: continuationTokenSchema,
|
|
180
137
|
});
|
|
181
|
-
/**
|
|
182
|
-
* Schema for createSubscription method
|
|
183
|
-
* Endpoint: POST /subscription
|
|
184
|
-
* Body: CreateSubscriptionRequest - destinationId, payload, status, topicId
|
|
185
|
-
*/
|
|
138
|
+
/** Schema for createSubscription input. */
|
|
186
139
|
export const createSubscriptionSchema = z.object({
|
|
187
|
-
|
|
140
|
+
destinationId: z
|
|
188
141
|
.string({
|
|
189
|
-
invalid_type_error: '
|
|
142
|
+
invalid_type_error: 'destinationId must be a string',
|
|
190
143
|
description: 'The unique identifier of the destination endpoint',
|
|
191
144
|
})
|
|
192
145
|
.optional(),
|
|
193
|
-
payload:
|
|
194
|
-
.object({
|
|
195
|
-
delivery_protocol: z
|
|
196
|
-
.string({
|
|
197
|
-
invalid_type_error: 'delivery_protocol must be a string',
|
|
198
|
-
description: 'Delivery protocol (currently only HTTPS is supported)',
|
|
199
|
-
})
|
|
200
|
-
.optional(),
|
|
201
|
-
format: z
|
|
202
|
-
.string({
|
|
203
|
-
invalid_type_error: 'format must be a string',
|
|
204
|
-
description: 'Payload format (currently only JSON is supported)',
|
|
205
|
-
})
|
|
206
|
-
.optional(),
|
|
207
|
-
schema_version: z
|
|
208
|
-
.string({
|
|
209
|
-
invalid_type_error: 'schema_version must be a string',
|
|
210
|
-
description: 'Schema version for the notification topic',
|
|
211
|
-
})
|
|
212
|
-
.optional(),
|
|
213
|
-
}, {
|
|
214
|
-
invalid_type_error: 'payload must be an object',
|
|
215
|
-
description: 'Payload configuration',
|
|
216
|
-
})
|
|
217
|
-
.optional(),
|
|
146
|
+
payload: payloadSchema,
|
|
218
147
|
status: z
|
|
219
148
|
.string({
|
|
220
149
|
invalid_type_error: 'status must be a string',
|
|
221
150
|
description: 'Status: ENABLED or DISABLED',
|
|
222
151
|
})
|
|
223
152
|
.optional(),
|
|
224
|
-
|
|
153
|
+
topicId: z
|
|
225
154
|
.string({
|
|
226
|
-
invalid_type_error: '
|
|
155
|
+
invalid_type_error: 'topicId must be a string',
|
|
227
156
|
description: 'The unique identifier of the notification topic',
|
|
228
157
|
})
|
|
229
158
|
.optional(),
|
|
230
159
|
});
|
|
231
|
-
/**
|
|
232
|
-
* Schema for getSubscription method
|
|
233
|
-
* Endpoint: GET /subscription/{subscription_id}
|
|
234
|
-
* Path: subscription_id (required)
|
|
235
|
-
*/
|
|
160
|
+
/** Schema for getSubscription input. */
|
|
236
161
|
export const getSubscriptionSchema = z.object({
|
|
237
|
-
|
|
162
|
+
subscriptionId: idSchema('Subscription ID', 'The unique identifier for the subscription'),
|
|
238
163
|
});
|
|
239
|
-
/**
|
|
240
|
-
* Schema for updateSubscription method
|
|
241
|
-
* Endpoint: PUT /subscription/{subscription_id}
|
|
242
|
-
* Path: subscription_id (required)
|
|
243
|
-
* Body: UpdateSubscriptionRequest - destinationId, payload, status
|
|
244
|
-
*/
|
|
164
|
+
/** Schema for updateSubscription input. */
|
|
245
165
|
export const updateSubscriptionSchema = z.object({
|
|
246
|
-
|
|
247
|
-
|
|
166
|
+
subscriptionId: idSchema('Subscription ID', 'The unique identifier for the subscription'),
|
|
167
|
+
destinationId: z
|
|
248
168
|
.string({
|
|
249
|
-
invalid_type_error: '
|
|
169
|
+
invalid_type_error: 'destinationId must be a string',
|
|
250
170
|
description: 'The unique identifier of the destination',
|
|
251
171
|
})
|
|
252
172
|
.optional(),
|
|
253
|
-
payload:
|
|
254
|
-
.object({
|
|
255
|
-
delivery_protocol: z
|
|
256
|
-
.string({
|
|
257
|
-
invalid_type_error: 'delivery_protocol must be a string',
|
|
258
|
-
description: 'Delivery protocol',
|
|
259
|
-
})
|
|
260
|
-
.optional(),
|
|
261
|
-
format: z
|
|
262
|
-
.string({
|
|
263
|
-
invalid_type_error: 'format must be a string',
|
|
264
|
-
description: 'Payload format',
|
|
265
|
-
})
|
|
266
|
-
.optional(),
|
|
267
|
-
schema_version: z
|
|
268
|
-
.string({
|
|
269
|
-
invalid_type_error: 'schema_version must be a string',
|
|
270
|
-
description: 'Schema version',
|
|
271
|
-
})
|
|
272
|
-
.optional(),
|
|
273
|
-
})
|
|
274
|
-
.optional(),
|
|
173
|
+
payload: payloadSchema,
|
|
275
174
|
status: z
|
|
276
175
|
.string({
|
|
277
176
|
invalid_type_error: 'status must be a string',
|
|
@@ -279,85 +178,46 @@ export const updateSubscriptionSchema = z.object({
|
|
|
279
178
|
})
|
|
280
179
|
.optional(),
|
|
281
180
|
});
|
|
282
|
-
/**
|
|
283
|
-
* Schema for deleteSubscription method
|
|
284
|
-
* Endpoint: DELETE /subscription/{subscription_id}
|
|
285
|
-
* Path: subscription_id (required)
|
|
286
|
-
*/
|
|
181
|
+
/** Schema for deleteSubscription input. */
|
|
287
182
|
export const deleteSubscriptionSchema = z.object({
|
|
288
|
-
|
|
183
|
+
subscriptionId: idSchema('Subscription ID', 'The unique identifier for the subscription'),
|
|
289
184
|
});
|
|
290
|
-
/**
|
|
291
|
-
* Schema for disableSubscription method
|
|
292
|
-
* Endpoint: POST /subscription/{subscription_id}/disable
|
|
293
|
-
* Path: subscription_id (required)
|
|
294
|
-
*/
|
|
185
|
+
/** Schema for disableSubscription input. */
|
|
295
186
|
export const disableSubscriptionSchema = z.object({
|
|
296
|
-
|
|
187
|
+
subscriptionId: idSchema('Subscription ID', 'The unique identifier for the subscription'),
|
|
297
188
|
});
|
|
298
|
-
/**
|
|
299
|
-
* Schema for enableSubscription method
|
|
300
|
-
* Endpoint: POST /subscription/{subscription_id}/enable
|
|
301
|
-
* Path: subscription_id (required)
|
|
302
|
-
*/
|
|
189
|
+
/** Schema for enableSubscription input. */
|
|
303
190
|
export const enableSubscriptionSchema = z.object({
|
|
304
|
-
|
|
191
|
+
subscriptionId: idSchema('Subscription ID', 'The unique identifier for the subscription'),
|
|
305
192
|
});
|
|
306
|
-
/**
|
|
307
|
-
* Schema for testSubscription method
|
|
308
|
-
* Endpoint: POST /subscription/{subscription_id}/test
|
|
309
|
-
* Path: subscription_id (required)
|
|
310
|
-
*/
|
|
193
|
+
/** Schema for testSubscription input. */
|
|
311
194
|
export const testSubscriptionSchema = z.object({
|
|
312
|
-
|
|
195
|
+
subscriptionId: idSchema('Subscription ID', 'The unique identifier for the subscription'),
|
|
313
196
|
});
|
|
314
|
-
/**
|
|
315
|
-
* Schema for getTopic method
|
|
316
|
-
* Endpoint: GET /topic/{topic_id}
|
|
317
|
-
* Path: topic_id (required)
|
|
318
|
-
*/
|
|
197
|
+
/** Schema for getTopic input. */
|
|
319
198
|
export const getTopicSchema = z.object({
|
|
320
|
-
|
|
199
|
+
topicId: idSchema('Topic ID', 'The unique identifier for the topic'),
|
|
321
200
|
});
|
|
322
|
-
/**
|
|
323
|
-
* Schema for getTopics method
|
|
324
|
-
* Endpoint: GET /topic
|
|
325
|
-
* Query: TopicParams - continuation_token, limit
|
|
326
|
-
*/
|
|
201
|
+
/** Schema for getTopics input. */
|
|
327
202
|
export const getTopicsSchema = z.object({
|
|
328
203
|
limit: limitSchema,
|
|
329
|
-
|
|
204
|
+
continuationToken: continuationTokenSchema,
|
|
330
205
|
});
|
|
331
|
-
/**
|
|
332
|
-
* Schema for createSubscriptionFilter method
|
|
333
|
-
* Endpoint: POST /subscription/{subscription_id}/filter
|
|
334
|
-
* Path: subscription_id (required)
|
|
335
|
-
* Body: CreateSubscriptionFilterRequest - filterSchema
|
|
336
|
-
*/
|
|
206
|
+
/** Schema for createSubscriptionFilter input. */
|
|
337
207
|
export const createSubscriptionFilterSchema = z.object({
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
.record(z.
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
})
|
|
344
|
-
.optional(),
|
|
208
|
+
subscriptionId: idSchema('Subscription ID', 'The unique identifier for the subscription'),
|
|
209
|
+
filterSchema: z
|
|
210
|
+
.record(z.string(), z.unknown())
|
|
211
|
+
.optional()
|
|
212
|
+
.describe('Valid JSON Schema Core document (version 2020-12 or later) to filter notifications'),
|
|
345
213
|
});
|
|
346
|
-
/**
|
|
347
|
-
* Schema for getSubscriptionFilter method
|
|
348
|
-
* Endpoint: GET /subscription/{subscription_id}/filter/{filter_id}
|
|
349
|
-
* Path: subscription_id (required), filter_id (required)
|
|
350
|
-
*/
|
|
214
|
+
/** Schema for getSubscriptionFilter input. */
|
|
351
215
|
export const getSubscriptionFilterSchema = z.object({
|
|
352
|
-
|
|
353
|
-
|
|
216
|
+
subscriptionId: idSchema('Subscription ID', 'The unique identifier for the subscription'),
|
|
217
|
+
filterId: idSchema('Filter ID', 'The unique identifier for the filter'),
|
|
354
218
|
});
|
|
355
|
-
/**
|
|
356
|
-
* Schema for deleteSubscriptionFilter method
|
|
357
|
-
* Endpoint: DELETE /subscription/{subscription_id}/filter/{filter_id}
|
|
358
|
-
* Path: subscription_id (required), filter_id (required)
|
|
359
|
-
*/
|
|
219
|
+
/** Schema for deleteSubscriptionFilter input. */
|
|
360
220
|
export const deleteSubscriptionFilterSchema = z.object({
|
|
361
|
-
|
|
362
|
-
|
|
221
|
+
subscriptionId: idSchema('Subscription ID', 'The unique identifier for the subscription'),
|
|
222
|
+
filterId: idSchema('Filter ID', 'The unique identifier for the filter'),
|
|
363
223
|
});
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
+
import { Data, Effect } from 'effect';
|
|
2
|
+
/** Utility functions for date/timestamp conversion and validation. */
|
|
3
|
+
/** Tagged failure returned when user-supplied date input cannot be parsed. */
|
|
4
|
+
export class DateConversionError extends Data.TaggedError('DateConversionError') {
|
|
5
|
+
}
|
|
6
|
+
/** Return a tagged date-conversion failure for invalid user input. */
|
|
7
|
+
const invalidDateInput = (input, message) => Effect.fail(new DateConversionError({ input, message }));
|
|
1
8
|
/**
|
|
2
|
-
*
|
|
3
|
-
*/
|
|
4
|
-
/**
|
|
5
|
-
* Convert a date string or Date object to Unix timestamp (milliseconds)
|
|
9
|
+
* Convert a date string or Date object to Unix timestamp (milliseconds).
|
|
6
10
|
*
|
|
7
11
|
* Supported formats:
|
|
8
12
|
* - ISO 8601: "2025-01-15T10:30:00Z" or "2025-01-15T10:30:00.000Z"
|
|
@@ -12,39 +16,43 @@
|
|
|
12
16
|
* - Relative time: "in 2 hours", "in 7200 seconds"
|
|
13
17
|
*
|
|
14
18
|
* @param dateInput - Date string, Date object, or Unix timestamp
|
|
15
|
-
* @returns Unix timestamp in milliseconds
|
|
16
|
-
*
|
|
19
|
+
* @returns An Effect that succeeds with a Unix timestamp in milliseconds.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* const timestamp = await Effect.runPromise(convertToTimestamp('2026-01-15T10:30:00Z'));
|
|
24
|
+
* ```
|
|
17
25
|
*/
|
|
18
|
-
export
|
|
26
|
+
export const convertToTimestamp = (dateInput) => {
|
|
19
27
|
// If already a number, handle as timestamp
|
|
20
28
|
if (typeof dateInput === 'number') {
|
|
21
29
|
// If appears to be seconds (less than year 2100 in milliseconds)
|
|
22
|
-
if (dateInput <
|
|
30
|
+
if (dateInput < 4_102_444_800_000) {
|
|
23
31
|
// Could be seconds, check if reasonable
|
|
24
32
|
const now = Date.now();
|
|
25
33
|
const asSeconds = dateInput * 1000;
|
|
26
34
|
// If multiplying by 1000 gives reasonable future date, it's seconds
|
|
27
35
|
if (asSeconds > now - 100 * 365 * 24 * 60 * 60 * 1000) {
|
|
28
|
-
return Math.floor(asSeconds);
|
|
36
|
+
return Effect.succeed(Math.floor(asSeconds));
|
|
29
37
|
}
|
|
30
38
|
}
|
|
31
39
|
// Already milliseconds
|
|
32
|
-
return Math.floor(dateInput);
|
|
40
|
+
return Effect.succeed(Math.floor(dateInput));
|
|
33
41
|
}
|
|
34
42
|
// If Date object
|
|
35
43
|
if (dateInput instanceof Date) {
|
|
36
44
|
const timestamp = dateInput.getTime();
|
|
37
|
-
if (isNaN(timestamp)) {
|
|
38
|
-
|
|
45
|
+
if (Number.isNaN(timestamp)) {
|
|
46
|
+
return invalidDateInput(dateInput, 'Invalid Date object');
|
|
39
47
|
}
|
|
40
|
-
return timestamp;
|
|
48
|
+
return Effect.succeed(timestamp);
|
|
41
49
|
}
|
|
42
50
|
// If string, try parsing
|
|
43
51
|
if (typeof dateInput === 'string') {
|
|
44
52
|
// Handle relative time: "in X hours/minutes/seconds"
|
|
45
53
|
const relativeMatch = /^in\s+(\d+)\s+(hours?|minutes?|seconds?|days?)$/i.exec(dateInput);
|
|
46
54
|
if (relativeMatch) {
|
|
47
|
-
const amount = parseInt(relativeMatch[1], 10);
|
|
55
|
+
const amount = Number.parseInt(relativeMatch[1], 10);
|
|
48
56
|
const unit = relativeMatch[2].toLowerCase();
|
|
49
57
|
let multiplier = 1000; // Default to seconds
|
|
50
58
|
if (unit.startsWith('minute'))
|
|
@@ -53,17 +61,17 @@ export function convertToTimestamp(dateInput) {
|
|
|
53
61
|
multiplier = 60 * 60 * 1000;
|
|
54
62
|
else if (unit.startsWith('day'))
|
|
55
63
|
multiplier = 24 * 60 * 60 * 1000;
|
|
56
|
-
return Date.now() + amount * multiplier;
|
|
64
|
+
return Effect.succeed(Date.now() + amount * multiplier);
|
|
57
65
|
}
|
|
58
66
|
// Try parsing as ISO date or other standard format
|
|
59
67
|
const parsed = Date.parse(dateInput);
|
|
60
|
-
if (isNaN(parsed)) {
|
|
61
|
-
|
|
68
|
+
if (Number.isNaN(parsed)) {
|
|
69
|
+
return invalidDateInput(dateInput, `Invalid date format: ${dateInput}. Supported formats: ISO 8601, Unix timestamp, or relative time (e.g., "in 2 hours")`);
|
|
62
70
|
}
|
|
63
|
-
return parsed;
|
|
71
|
+
return Effect.succeed(parsed);
|
|
64
72
|
}
|
|
65
|
-
|
|
66
|
-
}
|
|
73
|
+
return invalidDateInput(dateInput, `Unsupported date input type: ${typeof dateInput}`);
|
|
74
|
+
};
|
|
67
75
|
/**
|
|
68
76
|
* Calculate expiry timestamp from duration in seconds
|
|
69
77
|
* Useful for eBay token responses which provide expires_in in seconds
|
|
@@ -71,30 +79,45 @@ export function convertToTimestamp(dateInput) {
|
|
|
71
79
|
* @param expiresInSeconds - Duration in seconds (e.g., 7200 for 2 hours)
|
|
72
80
|
* @param fromTimestamp - Optional base timestamp (defaults to now)
|
|
73
81
|
* @returns Expiry timestamp in milliseconds
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```ts
|
|
85
|
+
* const expiry = calculateExpiry(7200, Date.UTC(2026, 0, 1));
|
|
86
|
+
* ```
|
|
74
87
|
*/
|
|
75
|
-
export
|
|
88
|
+
export const calculateExpiry = (expiresInSeconds, fromTimestamp) => {
|
|
76
89
|
const baseTime = fromTimestamp ?? Date.now();
|
|
77
90
|
return baseTime + expiresInSeconds * 1000;
|
|
78
|
-
}
|
|
91
|
+
};
|
|
79
92
|
/**
|
|
80
93
|
* Check if a timestamp is expired
|
|
81
94
|
*
|
|
82
95
|
* @param expiryTimestamp - Expiry timestamp in milliseconds
|
|
83
96
|
* @param bufferSeconds - Optional buffer time in seconds (default: 60)
|
|
84
97
|
* @returns true if expired (or will expire within buffer time)
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```ts
|
|
101
|
+
* const expired = isExpired(Date.now() - 1, 0);
|
|
102
|
+
* ```
|
|
85
103
|
*/
|
|
86
|
-
export
|
|
104
|
+
export const isExpired = (expiryTimestamp, bufferSeconds = 60) => {
|
|
87
105
|
const now = Date.now();
|
|
88
106
|
const buffer = bufferSeconds * 1000;
|
|
89
107
|
return now + buffer >= expiryTimestamp;
|
|
90
|
-
}
|
|
108
|
+
};
|
|
91
109
|
/**
|
|
92
110
|
* Get human-readable time remaining until expiry
|
|
93
111
|
*
|
|
94
112
|
* @param expiryTimestamp - Expiry timestamp in milliseconds
|
|
95
113
|
* @returns Human-readable string (e.g., "2 hours 15 minutes")
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```ts
|
|
117
|
+
* const remaining = getTimeRemaining(Date.now() + 120_000);
|
|
118
|
+
* ```
|
|
96
119
|
*/
|
|
97
|
-
export
|
|
120
|
+
export const getTimeRemaining = (expiryTimestamp) => {
|
|
98
121
|
const now = Date.now();
|
|
99
122
|
const diff = expiryTimestamp - now;
|
|
100
123
|
if (diff <= 0) {
|
|
@@ -117,17 +140,26 @@ export function getTimeRemaining(expiryTimestamp) {
|
|
|
117
140
|
return `${minutes} minute${minutes > 1 ? 's' : ''}${remainingSeconds > 0 ? ` ${remainingSeconds} second${remainingSeconds > 1 ? 's' : ''}` : ''}`;
|
|
118
141
|
}
|
|
119
142
|
return `${seconds} second${seconds > 1 ? 's' : ''}`;
|
|
120
|
-
}
|
|
143
|
+
};
|
|
121
144
|
/**
|
|
122
145
|
* Validate access and refresh token expiry timestamps and return renewal guidance.
|
|
146
|
+
*
|
|
147
|
+
* @param accessTokenExpiry - Access-token expiry timestamp in milliseconds.
|
|
148
|
+
* @param refreshTokenExpiry - Refresh-token expiry timestamp in milliseconds.
|
|
149
|
+
* @returns Token validity flags, remaining-time labels, warnings, and recommendations.
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```ts
|
|
153
|
+
* const validation = validateTokenExpiry(accessTokenExpiry, refreshTokenExpiry);
|
|
154
|
+
* ```
|
|
123
155
|
*/
|
|
124
|
-
export
|
|
156
|
+
export const validateTokenExpiry = (accessTokenExpiry, refreshTokenExpiry) => {
|
|
125
157
|
const warnings = [];
|
|
126
158
|
const recommendations = [];
|
|
127
159
|
const accessExpired = isExpired(accessTokenExpiry, 0);
|
|
128
160
|
const accessExpiringSoon = isExpired(accessTokenExpiry, 300); // 5 minutes
|
|
129
161
|
const refreshExpired = isExpired(refreshTokenExpiry, 0);
|
|
130
|
-
const refreshExpiringSoon = isExpired(refreshTokenExpiry,
|
|
162
|
+
const refreshExpiringSoon = isExpired(refreshTokenExpiry, 86_400); // 1 day
|
|
131
163
|
let accessTokenStatus = 'valid';
|
|
132
164
|
let refreshTokenStatus = 'valid';
|
|
133
165
|
if (accessExpired) {
|
|
@@ -152,7 +184,7 @@ export function validateTokenExpiry(accessTokenExpiry, refreshTokenExpiry) {
|
|
|
152
184
|
recommendations.push('Consider prompting user to re-authorize before refresh token expires');
|
|
153
185
|
}
|
|
154
186
|
return {
|
|
155
|
-
valid: !accessExpired
|
|
187
|
+
valid: !(accessExpired || refreshExpired),
|
|
156
188
|
accessTokenStatus,
|
|
157
189
|
refreshTokenStatus,
|
|
158
190
|
accessTokenRemaining: getTimeRemaining(accessTokenExpiry),
|
|
@@ -160,4 +192,4 @@ export function validateTokenExpiry(accessTokenExpiry, refreshTokenExpiry) {
|
|
|
160
192
|
warnings,
|
|
161
193
|
recommendations,
|
|
162
194
|
};
|
|
163
|
-
}
|
|
195
|
+
};
|