sharetribe-flex-build-sdk 1.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +222 -0
- package/build.js +49 -0
- package/package.json +54 -0
- package/src/api/client.ts +218 -0
- package/src/api/http-client.ts +135 -0
- package/src/api/multipart.ts +78 -0
- package/src/api/transit.ts +96 -0
- package/src/assets.ts +116 -0
- package/src/auth-storage.ts +77 -0
- package/src/deploy.ts +96 -0
- package/src/edn-process.ts +126 -0
- package/src/events.ts +203 -0
- package/src/index.ts +101 -0
- package/src/listing-approval.ts +59 -0
- package/src/notifications.ts +89 -0
- package/src/processes.ts +320 -0
- package/src/sdk-exports.md +25 -0
- package/src/search.ts +273 -0
- package/src/stripe.ts +39 -0
- package/src/types/jsedn.d.ts +9 -0
- package/src/types/transit-js.d.ts +10 -0
- package/src/types.ts +38 -0
- package/tsconfig.json +19 -0
- package/vitest.config.ts +8 -0
package/src/processes.ts
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process management functions
|
|
3
|
+
*
|
|
4
|
+
* Programmatic API for managing Sharetribe transaction processes
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { apiGet, apiPost, apiPostMultipart, apiPostTransit, type MultipartField } from './api/client.js';
|
|
8
|
+
import { keyword, keywordMap } from './api/transit.js';
|
|
9
|
+
|
|
10
|
+
export interface ProcessListItem {
|
|
11
|
+
name: string;
|
|
12
|
+
version?: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface ProcessVersion {
|
|
16
|
+
createdAt: string;
|
|
17
|
+
version: number;
|
|
18
|
+
aliases?: string[];
|
|
19
|
+
transactionCount?: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface ProcessDetails {
|
|
23
|
+
definition: string;
|
|
24
|
+
version: number;
|
|
25
|
+
name: string;
|
|
26
|
+
emailTemplates?: Array<{
|
|
27
|
+
name: string;
|
|
28
|
+
html: string;
|
|
29
|
+
subject: string;
|
|
30
|
+
}>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface CreateProcessResult {
|
|
34
|
+
name: string;
|
|
35
|
+
version: number;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface PushProcessResult {
|
|
39
|
+
version?: number;
|
|
40
|
+
noChanges?: boolean;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface AliasResult {
|
|
44
|
+
alias: string;
|
|
45
|
+
version: number;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Lists all processes for a marketplace
|
|
50
|
+
*
|
|
51
|
+
* @param apiKey - Optional Sharetribe API key. If not provided, reads from ~/.config/flex-cli/auth.edn
|
|
52
|
+
* @param marketplace - Marketplace ID
|
|
53
|
+
* @returns Array of processes with their latest versions
|
|
54
|
+
*/
|
|
55
|
+
export async function listProcesses(
|
|
56
|
+
apiKey: string | undefined,
|
|
57
|
+
marketplace: string
|
|
58
|
+
): Promise<ProcessListItem[]> {
|
|
59
|
+
const response = await apiGet<{ data: Array<{ 'process/name': string; 'process/version'?: number }> }>(
|
|
60
|
+
apiKey,
|
|
61
|
+
'/processes/query',
|
|
62
|
+
{ marketplace }
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
return response.data.map(p => ({
|
|
66
|
+
name: p['process/name'],
|
|
67
|
+
version: p['process/version'],
|
|
68
|
+
}));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Lists all versions of a specific process
|
|
73
|
+
*
|
|
74
|
+
* @param apiKey - Sharetribe API key
|
|
75
|
+
* @param marketplace - Marketplace ID
|
|
76
|
+
* @param processName - Name of the process
|
|
77
|
+
* @returns Array of process versions
|
|
78
|
+
*/
|
|
79
|
+
export async function listProcessVersions(
|
|
80
|
+
apiKey: string | undefined,
|
|
81
|
+
marketplace: string,
|
|
82
|
+
processName: string
|
|
83
|
+
): Promise<ProcessVersion[]> {
|
|
84
|
+
const response = await apiGet<{
|
|
85
|
+
data: Array<{
|
|
86
|
+
'process/createdAt': string;
|
|
87
|
+
'process/version': number;
|
|
88
|
+
'process/aliases'?: string[];
|
|
89
|
+
'process/transactionCount'?: number;
|
|
90
|
+
}>;
|
|
91
|
+
}>(
|
|
92
|
+
apiKey,
|
|
93
|
+
'/processes/query-versions',
|
|
94
|
+
{ marketplace, name: processName }
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
return response.data.map(v => ({
|
|
98
|
+
createdAt: v['process/createdAt'],
|
|
99
|
+
version: v['process/version'],
|
|
100
|
+
aliases: v['process/aliases'],
|
|
101
|
+
transactionCount: v['process/transactionCount'],
|
|
102
|
+
}));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Gets details of a specific process version
|
|
107
|
+
*
|
|
108
|
+
* @param apiKey - Sharetribe API key
|
|
109
|
+
* @param marketplace - Marketplace ID
|
|
110
|
+
* @param processName - Name of the process
|
|
111
|
+
* @param options - Optional version or alias to retrieve
|
|
112
|
+
* @returns Process details including definition and templates
|
|
113
|
+
*/
|
|
114
|
+
export async function getProcess(
|
|
115
|
+
apiKey: string | undefined,
|
|
116
|
+
marketplace: string,
|
|
117
|
+
processName: string,
|
|
118
|
+
options?: { version?: string; alias?: string }
|
|
119
|
+
): Promise<ProcessDetails> {
|
|
120
|
+
const queryParams: Record<string, string> = {
|
|
121
|
+
marketplace,
|
|
122
|
+
name: processName,
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
if (options?.version) {
|
|
126
|
+
queryParams.version = options.version;
|
|
127
|
+
} else if (options?.alias) {
|
|
128
|
+
queryParams.alias = options.alias;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const response = await apiGet<{ data: any }>(apiKey, '/processes/show', queryParams);
|
|
132
|
+
|
|
133
|
+
const emailTemplates = (response.data['process/emailTemplates'] || []).map((t: any) => ({
|
|
134
|
+
name: t['emailTemplate/name'],
|
|
135
|
+
html: t['emailTemplate/html'],
|
|
136
|
+
subject: t['emailTemplate/subject'],
|
|
137
|
+
}));
|
|
138
|
+
|
|
139
|
+
return {
|
|
140
|
+
definition: response.data['process/process'] || response.data.definition,
|
|
141
|
+
version: response.data['process/version'] || response.data.version,
|
|
142
|
+
name: response.data['process/name'] || processName,
|
|
143
|
+
emailTemplates,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Creates a new transaction process
|
|
149
|
+
*
|
|
150
|
+
* @param apiKey - Sharetribe API key
|
|
151
|
+
* @param marketplace - Marketplace ID
|
|
152
|
+
* @param processName - Name for the new process
|
|
153
|
+
* @param definition - Process definition (EDN format)
|
|
154
|
+
* @returns Created process details
|
|
155
|
+
*/
|
|
156
|
+
export async function createProcess(
|
|
157
|
+
apiKey: string | undefined,
|
|
158
|
+
marketplace: string,
|
|
159
|
+
processName: string,
|
|
160
|
+
definition: string
|
|
161
|
+
): Promise<CreateProcessResult> {
|
|
162
|
+
const response = await apiPost<{ data: { 'process/name': string; 'process/version': number } }>(
|
|
163
|
+
apiKey,
|
|
164
|
+
'/processes/create',
|
|
165
|
+
{ marketplace },
|
|
166
|
+
{ name: processName, definition }
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
return {
|
|
170
|
+
name: response.data['process/name'],
|
|
171
|
+
version: response.data['process/version'],
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Pushes a new version of an existing process
|
|
177
|
+
*
|
|
178
|
+
* @param apiKey - Sharetribe API key
|
|
179
|
+
* @param marketplace - Marketplace ID
|
|
180
|
+
* @param processName - Name of the process
|
|
181
|
+
* @param definition - Process definition (EDN format)
|
|
182
|
+
* @param templates - Optional email templates
|
|
183
|
+
* @returns Push result with version number
|
|
184
|
+
*/
|
|
185
|
+
export async function pushProcess(
|
|
186
|
+
apiKey: string | undefined,
|
|
187
|
+
marketplace: string,
|
|
188
|
+
processName: string,
|
|
189
|
+
definition: string,
|
|
190
|
+
templates?: Array<{ name: string; html: string; subject: string }>
|
|
191
|
+
): Promise<PushProcessResult> {
|
|
192
|
+
const fields: MultipartField[] = [
|
|
193
|
+
{ name: 'name', value: processName },
|
|
194
|
+
{ name: 'definition', value: definition },
|
|
195
|
+
];
|
|
196
|
+
|
|
197
|
+
if (templates) {
|
|
198
|
+
for (const template of templates) {
|
|
199
|
+
fields.push({ name: `template-html-${template.name}`, value: template.html });
|
|
200
|
+
fields.push({ name: `template-subject-${template.name}`, value: template.subject });
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const response = await apiPostMultipart<{ data: any; meta?: { result?: string } }>(
|
|
205
|
+
apiKey,
|
|
206
|
+
'/processes/create-version',
|
|
207
|
+
{ marketplace },
|
|
208
|
+
fields
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
if (response.meta?.result === 'no-changes') {
|
|
212
|
+
return { noChanges: true };
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return {
|
|
216
|
+
version: response.data['process/version'] || response.data.version,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Creates a process alias
|
|
222
|
+
*
|
|
223
|
+
* @param apiKey - Sharetribe API key
|
|
224
|
+
* @param marketplace - Marketplace ID
|
|
225
|
+
* @param processName - Name of the process
|
|
226
|
+
* @param version - Version number to point the alias to
|
|
227
|
+
* @param alias - Alias name
|
|
228
|
+
* @returns Created alias details
|
|
229
|
+
*/
|
|
230
|
+
export async function createAlias(
|
|
231
|
+
apiKey: string | undefined,
|
|
232
|
+
marketplace: string,
|
|
233
|
+
processName: string,
|
|
234
|
+
version: number,
|
|
235
|
+
alias: string
|
|
236
|
+
): Promise<AliasResult> {
|
|
237
|
+
const response = await apiPostTransit<{
|
|
238
|
+
data: { 'processAlias/alias': string; 'processAlias/version': number };
|
|
239
|
+
}>(
|
|
240
|
+
apiKey,
|
|
241
|
+
'/aliases/create-alias',
|
|
242
|
+
{ marketplace },
|
|
243
|
+
keywordMap({
|
|
244
|
+
name: keyword(processName),
|
|
245
|
+
version,
|
|
246
|
+
alias: keyword(alias),
|
|
247
|
+
})
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
return {
|
|
251
|
+
alias: response.data['processAlias/alias'],
|
|
252
|
+
version: response.data['processAlias/version'],
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Updates a process alias to point to a different version
|
|
258
|
+
*
|
|
259
|
+
* @param apiKey - Sharetribe API key
|
|
260
|
+
* @param marketplace - Marketplace ID
|
|
261
|
+
* @param processName - Name of the process
|
|
262
|
+
* @param version - Version number to point the alias to
|
|
263
|
+
* @param alias - Alias name
|
|
264
|
+
* @returns Updated alias details
|
|
265
|
+
*/
|
|
266
|
+
export async function updateAlias(
|
|
267
|
+
apiKey: string | undefined,
|
|
268
|
+
marketplace: string,
|
|
269
|
+
processName: string,
|
|
270
|
+
version: number,
|
|
271
|
+
alias: string
|
|
272
|
+
): Promise<AliasResult> {
|
|
273
|
+
const response = await apiPostTransit<{
|
|
274
|
+
data: { 'processAlias/alias': string; 'processAlias/version': number };
|
|
275
|
+
}>(
|
|
276
|
+
apiKey,
|
|
277
|
+
'/aliases/update-alias',
|
|
278
|
+
{ marketplace },
|
|
279
|
+
keywordMap({
|
|
280
|
+
name: keyword(processName),
|
|
281
|
+
version,
|
|
282
|
+
alias: keyword(alias),
|
|
283
|
+
})
|
|
284
|
+
);
|
|
285
|
+
|
|
286
|
+
return {
|
|
287
|
+
alias: response.data['processAlias/alias'],
|
|
288
|
+
version: response.data['processAlias/version'],
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Deletes a process alias
|
|
294
|
+
*
|
|
295
|
+
* @param apiKey - Sharetribe API key
|
|
296
|
+
* @param marketplace - Marketplace ID
|
|
297
|
+
* @param processName - Name of the process
|
|
298
|
+
* @param alias - Alias name to delete
|
|
299
|
+
* @returns Deleted alias name
|
|
300
|
+
*/
|
|
301
|
+
export async function deleteAlias(
|
|
302
|
+
apiKey: string | undefined,
|
|
303
|
+
marketplace: string,
|
|
304
|
+
processName: string,
|
|
305
|
+
alias: string
|
|
306
|
+
): Promise<{ alias: string }> {
|
|
307
|
+
const response = await apiPostTransit<{ data: { 'processAlias/alias': string } }>(
|
|
308
|
+
apiKey,
|
|
309
|
+
'/aliases/delete-alias',
|
|
310
|
+
{ marketplace },
|
|
311
|
+
keywordMap({
|
|
312
|
+
name: keyword(processName),
|
|
313
|
+
alias: keyword(alias),
|
|
314
|
+
})
|
|
315
|
+
);
|
|
316
|
+
|
|
317
|
+
return {
|
|
318
|
+
alias: response.data['processAlias/alias'],
|
|
319
|
+
};
|
|
320
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# SDK Exports Documentation
|
|
2
|
+
|
|
3
|
+
This SDK provides programmatic access to all Sharetribe CLI commands.
|
|
4
|
+
|
|
5
|
+
## Modules
|
|
6
|
+
|
|
7
|
+
- **processes.ts**: Process management (list, create, push, pull, aliases)
|
|
8
|
+
- **search.ts**: Search schema management (list, set, unset) - TODO
|
|
9
|
+
- **assets.ts**: Asset management (pull, push) - TODO
|
|
10
|
+
- **notifications.ts**: Email notifications (preview, send) - TODO
|
|
11
|
+
- **listing-approval.ts**: Listing approval settings - TODO
|
|
12
|
+
- **stripe.ts**: Stripe configuration - TODO
|
|
13
|
+
- **events.ts**: Event webhooks - TODO
|
|
14
|
+
|
|
15
|
+
## Implementation Status
|
|
16
|
+
|
|
17
|
+
✅ Processes - Complete
|
|
18
|
+
⏳ Search - In progress
|
|
19
|
+
⏳ Assets - In progress
|
|
20
|
+
⏳ Notifications - In progress
|
|
21
|
+
⏳ Listing approval - In progress
|
|
22
|
+
⏳ Stripe - In progress
|
|
23
|
+
⏳ Events - In progress
|
|
24
|
+
|
|
25
|
+
Note: For the first release (1.15.0), we're focusing on process management which is the core functionality. Additional commands will be added in future versions while maintaining backward compatibility.
|
package/src/search.ts
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Search schema management functions
|
|
3
|
+
*
|
|
4
|
+
* Programmatic API for managing search schemas
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { apiGet, apiPostTransit } from './api/client.js';
|
|
8
|
+
import { keyword, keywordMap } from './api/transit.js';
|
|
9
|
+
|
|
10
|
+
export interface SearchSchema {
|
|
11
|
+
schemaFor: string;
|
|
12
|
+
scope: string;
|
|
13
|
+
key: string;
|
|
14
|
+
type: string;
|
|
15
|
+
defaultValue?: string | number | boolean | string[];
|
|
16
|
+
doc?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface SetSearchSchemaOptions {
|
|
20
|
+
key: string;
|
|
21
|
+
scope: string;
|
|
22
|
+
type: string;
|
|
23
|
+
doc?: string;
|
|
24
|
+
defaultValue?: string;
|
|
25
|
+
schemaFor?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface UnsetSearchSchemaOptions {
|
|
29
|
+
key: string;
|
|
30
|
+
scope: string;
|
|
31
|
+
schemaFor?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Valid values for schema-for parameter
|
|
36
|
+
*/
|
|
37
|
+
const VALID_SCHEMA_FOR = ['listing', 'userProfile', 'transaction'];
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Valid scopes by schema type
|
|
41
|
+
*/
|
|
42
|
+
const VALID_SCOPES: Record<string, string[]> = {
|
|
43
|
+
listing: ['metadata', 'public'],
|
|
44
|
+
userProfile: ['metadata', 'private', 'protected', 'public'],
|
|
45
|
+
transaction: ['metadata', 'protected'],
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Valid types
|
|
50
|
+
*/
|
|
51
|
+
const VALID_TYPES = ['enum', 'multi-enum', 'boolean', 'long', 'text'];
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Validates and coerces a default value based on type
|
|
55
|
+
*/
|
|
56
|
+
function coerceDefaultValue(value: string, type: string): string | number | boolean | string[] {
|
|
57
|
+
if (type === 'boolean') {
|
|
58
|
+
if (value !== 'true' && value !== 'false') {
|
|
59
|
+
throw new Error(`Default value must be "true" or "false" for boolean type`);
|
|
60
|
+
}
|
|
61
|
+
return value === 'true';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (type === 'long') {
|
|
65
|
+
const num = parseFloat(value);
|
|
66
|
+
if (isNaN(num) || !Number.isInteger(num)) {
|
|
67
|
+
throw new Error(`Default value must be an integer for long type`);
|
|
68
|
+
}
|
|
69
|
+
return num;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (type === 'multi-enum') {
|
|
73
|
+
return value.split(',').map(v => v.trim());
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return value;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Validates search schema parameters for set operation
|
|
81
|
+
*/
|
|
82
|
+
function validateSetParams(opts: SetSearchSchemaOptions): void {
|
|
83
|
+
const errors: string[] = [];
|
|
84
|
+
const schemaFor = opts.schemaFor || 'listing';
|
|
85
|
+
|
|
86
|
+
if (opts.key.includes('.')) {
|
|
87
|
+
errors.push('Key cannot include dots (.) - only top-level keys are allowed');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (!VALID_SCHEMA_FOR.includes(schemaFor)) {
|
|
91
|
+
errors.push(`schema-for must be one of: ${VALID_SCHEMA_FOR.join(', ')}`);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const validScopes = VALID_SCOPES[schemaFor] || [];
|
|
95
|
+
if (!validScopes.includes(opts.scope)) {
|
|
96
|
+
errors.push(`scope must be one of: ${validScopes.join(', ')} for ${schemaFor}`);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (!VALID_TYPES.includes(opts.type)) {
|
|
100
|
+
errors.push(`type must be one of: ${VALID_TYPES.join(', ')}`);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (opts.type === 'text' && schemaFor === 'userProfile') {
|
|
104
|
+
errors.push('text type is not supported for userProfile schema');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (errors.length > 0) {
|
|
108
|
+
throw new Error(errors.join('\n'));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Validates search schema parameters for unset operation
|
|
114
|
+
*/
|
|
115
|
+
function validateUnsetParams(opts: UnsetSearchSchemaOptions): void {
|
|
116
|
+
const errors: string[] = [];
|
|
117
|
+
const schemaFor = opts.schemaFor || 'listing';
|
|
118
|
+
|
|
119
|
+
if (opts.key.includes('.')) {
|
|
120
|
+
errors.push('Key cannot include dots (.) - only top-level keys are allowed');
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (!VALID_SCHEMA_FOR.includes(schemaFor)) {
|
|
124
|
+
errors.push(`schema-for must be one of: ${VALID_SCHEMA_FOR.join(', ')}`);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const validScopes = VALID_SCOPES[schemaFor] || [];
|
|
128
|
+
if (!validScopes.includes(opts.scope)) {
|
|
129
|
+
errors.push(`scope must be one of: ${validScopes.join(', ')} for ${schemaFor}`);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (errors.length > 0) {
|
|
133
|
+
throw new Error(errors.join('\n'));
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Extracts the name from a namespaced key (e.g., "dataSchema.scope/public" -> "public")
|
|
139
|
+
*/
|
|
140
|
+
function extractName(key: string): string {
|
|
141
|
+
return key.split('/').pop() || key;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Converts type and cardinality to type label (e.g., "multi-enum" for enum with many cardinality)
|
|
146
|
+
*/
|
|
147
|
+
function getTypeLabel(valueType: string, cardinality?: string): string {
|
|
148
|
+
const typeName = valueType.split('/').pop() || valueType;
|
|
149
|
+
if (typeName === 'enum' && cardinality === 'dataSchema.cardinality/many') {
|
|
150
|
+
return 'multi-enum';
|
|
151
|
+
}
|
|
152
|
+
return typeName;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Converts default value to display format
|
|
157
|
+
*/
|
|
158
|
+
function formatDefaultValue(value: unknown): string | number | boolean | string[] | undefined {
|
|
159
|
+
if (value === undefined || value === null) {
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
162
|
+
if (Array.isArray(value)) {
|
|
163
|
+
return value;
|
|
164
|
+
}
|
|
165
|
+
return value as string | number | boolean;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Lists all search schemas for a marketplace
|
|
170
|
+
*
|
|
171
|
+
* @param apiKey - Sharetribe API key (optional, reads from auth file if not provided)
|
|
172
|
+
* @param marketplace - Marketplace ID
|
|
173
|
+
* @returns Array of search schemas
|
|
174
|
+
*/
|
|
175
|
+
export async function listSearchSchemas(
|
|
176
|
+
apiKey: string | undefined,
|
|
177
|
+
marketplace: string
|
|
178
|
+
): Promise<SearchSchema[]> {
|
|
179
|
+
const response = await apiGet<{
|
|
180
|
+
data: Array<{
|
|
181
|
+
'dataSchema/key': string;
|
|
182
|
+
'dataSchema/scope': string;
|
|
183
|
+
'dataSchema/valueType': string;
|
|
184
|
+
'dataSchema/cardinality'?: string;
|
|
185
|
+
'dataSchema/defaultValue'?: unknown;
|
|
186
|
+
'dataSchema/doc'?: string;
|
|
187
|
+
'dataSchema/of': string;
|
|
188
|
+
}>;
|
|
189
|
+
}>(
|
|
190
|
+
apiKey,
|
|
191
|
+
'/search-schemas/query',
|
|
192
|
+
{
|
|
193
|
+
marketplace,
|
|
194
|
+
of: 'dataSchema.of/userProfile,dataSchema.of/listing,dataSchema.of/transaction',
|
|
195
|
+
}
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
return response.data.map(s => ({
|
|
199
|
+
schemaFor: extractName(s['dataSchema/of']),
|
|
200
|
+
scope: extractName(s['dataSchema/scope']),
|
|
201
|
+
key: extractName(s['dataSchema/key']),
|
|
202
|
+
type: getTypeLabel(s['dataSchema/valueType'], s['dataSchema/cardinality']),
|
|
203
|
+
defaultValue: formatDefaultValue(s['dataSchema/defaultValue']),
|
|
204
|
+
doc: s['dataSchema/doc'],
|
|
205
|
+
}));
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Sets a search schema field
|
|
210
|
+
*
|
|
211
|
+
* @param apiKey - Sharetribe API key (optional, reads from auth file if not provided)
|
|
212
|
+
* @param marketplace - Marketplace ID
|
|
213
|
+
* @param options - Schema configuration
|
|
214
|
+
* @returns Success confirmation
|
|
215
|
+
*/
|
|
216
|
+
export async function setSearchSchema(
|
|
217
|
+
apiKey: string | undefined,
|
|
218
|
+
marketplace: string,
|
|
219
|
+
options: SetSearchSchemaOptions
|
|
220
|
+
): Promise<{ success: true }> {
|
|
221
|
+
validateSetParams(options);
|
|
222
|
+
|
|
223
|
+
const schemaFor = options.schemaFor || 'listing';
|
|
224
|
+
const isMultiEnum = options.type === 'multi-enum';
|
|
225
|
+
|
|
226
|
+
const bodyObj: Record<string, unknown> = {
|
|
227
|
+
key: keyword(options.key),
|
|
228
|
+
scope: keyword(`dataSchema.scope/${options.scope}`),
|
|
229
|
+
valueType: keyword(`dataSchema.type/${isMultiEnum ? 'enum' : options.type}`),
|
|
230
|
+
cardinality: keyword(isMultiEnum ? 'dataSchema.cardinality/many' : 'dataSchema.cardinality/one'),
|
|
231
|
+
of: keyword(`dataSchema.of/${schemaFor}`),
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
if (options.doc) {
|
|
235
|
+
bodyObj.doc = options.doc;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (options.defaultValue !== undefined) {
|
|
239
|
+
bodyObj.defaultValue = coerceDefaultValue(options.defaultValue, options.type);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
await apiPostTransit(apiKey, '/search-schemas/set', { marketplace }, keywordMap(bodyObj));
|
|
243
|
+
|
|
244
|
+
return { success: true };
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Unsets a search schema field
|
|
249
|
+
*
|
|
250
|
+
* @param apiKey - Sharetribe API key (optional, reads from auth file if not provided)
|
|
251
|
+
* @param marketplace - Marketplace ID
|
|
252
|
+
* @param options - Schema identification
|
|
253
|
+
* @returns Success confirmation
|
|
254
|
+
*/
|
|
255
|
+
export async function unsetSearchSchema(
|
|
256
|
+
apiKey: string | undefined,
|
|
257
|
+
marketplace: string,
|
|
258
|
+
options: UnsetSearchSchemaOptions
|
|
259
|
+
): Promise<{ success: true }> {
|
|
260
|
+
validateUnsetParams(options);
|
|
261
|
+
|
|
262
|
+
const schemaFor = options.schemaFor || 'listing';
|
|
263
|
+
|
|
264
|
+
const bodyObj = {
|
|
265
|
+
key: keyword(options.key),
|
|
266
|
+
scope: keyword(`dataSchema.scope/${options.scope}`),
|
|
267
|
+
of: keyword(`dataSchema.of/${schemaFor}`),
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
await apiPostTransit(apiKey, '/search-schemas/unset', { marketplace }, keywordMap(bodyObj));
|
|
271
|
+
|
|
272
|
+
return { success: true };
|
|
273
|
+
}
|
package/src/stripe.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stripe integration management functions
|
|
3
|
+
*
|
|
4
|
+
* Programmatic API for managing Stripe integration
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { apiPost } from './api/client.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Supported Stripe API versions
|
|
11
|
+
*/
|
|
12
|
+
export const SUPPORTED_STRIPE_VERSIONS = ['2019-12-03', '2019-09-09', '2019-02-19'] as const;
|
|
13
|
+
|
|
14
|
+
export type StripeApiVersion = typeof SUPPORTED_STRIPE_VERSIONS[number];
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Updates Stripe API version
|
|
18
|
+
*
|
|
19
|
+
* @param apiKey - Sharetribe API key (optional, reads from auth file if not provided)
|
|
20
|
+
* @param marketplace - Marketplace ID
|
|
21
|
+
* @param version - Stripe API version
|
|
22
|
+
* @returns Success confirmation
|
|
23
|
+
*/
|
|
24
|
+
export async function updateStripeVersion(
|
|
25
|
+
apiKey: string | undefined,
|
|
26
|
+
marketplace: string,
|
|
27
|
+
version: string
|
|
28
|
+
): Promise<{ success: true }> {
|
|
29
|
+
// Validate version
|
|
30
|
+
if (!SUPPORTED_STRIPE_VERSIONS.includes(version as StripeApiVersion)) {
|
|
31
|
+
throw new Error(
|
|
32
|
+
`--version should be one of: ${SUPPORTED_STRIPE_VERSIONS.join(', ')}. Was ${version}.`
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
await apiPost(apiKey, '/stripe/update-version', { marketplace }, { version });
|
|
37
|
+
|
|
38
|
+
return { success: true };
|
|
39
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for transit-js
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
declare module 'transit-js' {
|
|
6
|
+
export function writer(type: string, options?: { handlers?: any }): any;
|
|
7
|
+
export function reader(type: string): any;
|
|
8
|
+
export function keyword(name: string): any;
|
|
9
|
+
export function map(entries: any[]): any;
|
|
10
|
+
}
|