@zapier/zapier-sdk-cli 0.8.4 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -0
- package/README.md +35 -51
- package/dist/cli.cjs +950 -433
- package/dist/cli.mjs +951 -434
- package/dist/index.cjs +729 -336
- package/dist/index.mjs +730 -337
- package/dist/package.json +1 -1
- package/dist/src/plugins/add/ast-generator.d.ts +37 -0
- package/dist/src/plugins/add/ast-generator.js +403 -0
- package/dist/src/plugins/add/index.d.ts +13 -0
- package/dist/src/plugins/add/index.js +120 -0
- package/dist/src/plugins/add/schemas.d.ts +18 -0
- package/dist/src/plugins/add/schemas.js +19 -0
- package/dist/src/plugins/getLoginConfigPath/index.d.ts +15 -0
- package/dist/src/plugins/getLoginConfigPath/index.js +19 -0
- package/dist/src/plugins/getLoginConfigPath/schemas.d.ts +3 -0
- package/dist/src/plugins/getLoginConfigPath/schemas.js +5 -0
- package/dist/src/plugins/index.d.ts +2 -2
- package/dist/src/plugins/index.js +2 -2
- package/dist/src/sdk.js +3 -3
- package/dist/src/utils/cli-generator-utils.d.ts +2 -1
- package/dist/src/utils/cli-generator-utils.js +11 -5
- package/dist/src/utils/cli-generator.js +65 -65
- package/dist/src/utils/parameter-resolver.d.ts +4 -1
- package/dist/src/utils/parameter-resolver.js +92 -15
- package/dist/src/utils/schema-formatter.d.ts +5 -1
- package/dist/src/utils/schema-formatter.js +48 -18
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/src/plugins/add/ast-generator.ts +777 -0
- package/src/plugins/add/index.test.ts +58 -0
- package/src/plugins/add/index.ts +187 -0
- package/src/plugins/add/schemas.ts +26 -0
- package/src/plugins/getLoginConfigPath/index.ts +45 -0
- package/src/plugins/getLoginConfigPath/schemas.ts +10 -0
- package/src/plugins/index.ts +2 -2
- package/src/sdk.ts +4 -4
- package/src/utils/cli-generator-utils.ts +17 -5
- package/src/utils/cli-generator.ts +90 -79
- package/src/utils/parameter-resolver.ts +155 -21
- package/src/utils/schema-formatter.ts +68 -33
- package/tsup.config.ts +1 -1
- package/dist/src/plugins/generateTypes/index.d.ts +0 -21
- package/dist/src/plugins/generateTypes/index.js +0 -312
- package/dist/src/plugins/generateTypes/schemas.d.ts +0 -18
- package/dist/src/plugins/generateTypes/schemas.js +0 -14
- package/dist/src/plugins/getConfigPath/index.d.ts +0 -15
- package/dist/src/plugins/getConfigPath/index.js +0 -19
- package/dist/src/plugins/getConfigPath/schemas.d.ts +0 -3
- package/dist/src/plugins/getConfigPath/schemas.js +0 -5
- package/src/plugins/generateTypes/index.ts +0 -444
- package/src/plugins/generateTypes/schemas.ts +0 -23
- package/src/plugins/getConfigPath/index.ts +0 -42
- package/src/plugins/getConfigPath/schemas.ts +0 -8
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { AddSchema } from "./schemas";
|
|
3
|
+
import { DEFAULT_CONFIG_PATH } from "@zapier/zapier-sdk";
|
|
4
|
+
|
|
5
|
+
describe("Add plugin", () => {
|
|
6
|
+
describe("schema validation", () => {
|
|
7
|
+
it("should accept valid options with authenticationIds", () => {
|
|
8
|
+
const result = AddSchema.safeParse({
|
|
9
|
+
appKeys: ["slack", "gmail"],
|
|
10
|
+
authenticationIds: ["123", "456"],
|
|
11
|
+
configPath: DEFAULT_CONFIG_PATH,
|
|
12
|
+
typesOutput: "src/types",
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
expect(result.success).toBe(true);
|
|
16
|
+
if (result.success) {
|
|
17
|
+
expect(result.data.authenticationIds).toEqual(["123", "456"]);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("should accept options without authenticationIds", () => {
|
|
22
|
+
const result = AddSchema.safeParse({
|
|
23
|
+
appKeys: ["slack"],
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
expect(result.success).toBe(true);
|
|
27
|
+
if (result.success) {
|
|
28
|
+
expect(result.data.authenticationIds).toBeUndefined();
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("should reject invalid authenticationIds type", () => {
|
|
33
|
+
const result = AddSchema.safeParse({
|
|
34
|
+
appKeys: ["slack"],
|
|
35
|
+
authenticationIds: "123", // Should be array
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
expect(result.success).toBe(false);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("should reject authenticationIds with non-string items", () => {
|
|
42
|
+
const result = AddSchema.safeParse({
|
|
43
|
+
appKeys: ["slack"],
|
|
44
|
+
authenticationIds: [123, 456], // Should be strings
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
expect(result.success).toBe(false);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("should require at least one appKey", () => {
|
|
51
|
+
const result = AddSchema.safeParse({
|
|
52
|
+
appKeys: [],
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
expect(result.success).toBe(false);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
});
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Plugin,
|
|
3
|
+
GetSdkType,
|
|
4
|
+
GetContextType,
|
|
5
|
+
ListActionsPluginProvides,
|
|
6
|
+
ListAppsPluginProvides,
|
|
7
|
+
ListInputFieldsPluginProvides,
|
|
8
|
+
ListAuthenticationsPluginProvides,
|
|
9
|
+
ManifestPluginProvides,
|
|
10
|
+
} from "@zapier/zapier-sdk";
|
|
11
|
+
import { createFunction } from "@zapier/zapier-sdk";
|
|
12
|
+
import { AddSchema, type AddOptions } from "./schemas";
|
|
13
|
+
import { AstTypeGenerator } from "./ast-generator";
|
|
14
|
+
import { mkdir, access, writeFile } from "fs/promises";
|
|
15
|
+
import { resolve, join } from "path";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Detect the best default directory for TypeScript types
|
|
19
|
+
* Looks for src or lib directories, falls back to current directory
|
|
20
|
+
*/
|
|
21
|
+
async function detectTypesOutputDirectory(): Promise<string> {
|
|
22
|
+
// Check for common source directories in priority order
|
|
23
|
+
const candidates = ["src", "lib"];
|
|
24
|
+
|
|
25
|
+
for (const candidate of candidates) {
|
|
26
|
+
try {
|
|
27
|
+
await access(candidate);
|
|
28
|
+
return join(candidate, "zapier", "apps");
|
|
29
|
+
} catch {
|
|
30
|
+
// Directory doesn't exist, continue to next candidate
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Fall back to current directory
|
|
35
|
+
return "./zapier/apps/";
|
|
36
|
+
}
|
|
37
|
+
export interface AddPluginProvides {
|
|
38
|
+
add: (options: AddOptions) => Promise<void>;
|
|
39
|
+
context: {
|
|
40
|
+
meta: {
|
|
41
|
+
add: {
|
|
42
|
+
inputSchema: typeof AddSchema;
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export const addPlugin: Plugin<
|
|
49
|
+
GetSdkType<
|
|
50
|
+
ListAppsPluginProvides &
|
|
51
|
+
ListActionsPluginProvides &
|
|
52
|
+
ListInputFieldsPluginProvides &
|
|
53
|
+
ListAuthenticationsPluginProvides &
|
|
54
|
+
ManifestPluginProvides
|
|
55
|
+
>,
|
|
56
|
+
GetContextType<ManifestPluginProvides>,
|
|
57
|
+
AddPluginProvides
|
|
58
|
+
> = ({ sdk, context }) => {
|
|
59
|
+
const add = createFunction(async function add(options: AddOptions) {
|
|
60
|
+
const {
|
|
61
|
+
appKeys,
|
|
62
|
+
authenticationIds,
|
|
63
|
+
configPath,
|
|
64
|
+
typesOutput = await detectTypesOutputDirectory(),
|
|
65
|
+
} = options;
|
|
66
|
+
|
|
67
|
+
const resolvedTypesOutput = resolve(typesOutput);
|
|
68
|
+
|
|
69
|
+
// Ensure types output directory exists
|
|
70
|
+
await mkdir(resolvedTypesOutput, { recursive: true });
|
|
71
|
+
|
|
72
|
+
// Get apps using listApps (which respects existing manifest for version locking)
|
|
73
|
+
console.log(`📦 Looking up ${appKeys.length} app(s)...`);
|
|
74
|
+
const appsIterator = sdk.listApps({ appKeys }).items();
|
|
75
|
+
const apps = [];
|
|
76
|
+
for await (const app of appsIterator) {
|
|
77
|
+
apps.push(app);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (apps.length === 0) {
|
|
81
|
+
console.warn("⚠️ No apps found");
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Fetch authentications if provided
|
|
86
|
+
let authentications = [];
|
|
87
|
+
if (authenticationIds && authenticationIds.length > 0) {
|
|
88
|
+
console.log(
|
|
89
|
+
`🔐 Looking up ${authenticationIds.length} authentication(s)...`,
|
|
90
|
+
);
|
|
91
|
+
const authsIterator = sdk
|
|
92
|
+
.listAuthentications({ authenticationIds })
|
|
93
|
+
.items();
|
|
94
|
+
for await (const auth of authsIterator) {
|
|
95
|
+
authentications.push(auth);
|
|
96
|
+
}
|
|
97
|
+
console.log(`🔐 Found ${authentications.length} authentication(s)`);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Process each app
|
|
101
|
+
for (const app of apps) {
|
|
102
|
+
const appSlugAndKey = app.slug ? `${app.slug} (${app.key})` : app.key;
|
|
103
|
+
console.log(`📦 Adding ${appSlugAndKey}...`);
|
|
104
|
+
|
|
105
|
+
try {
|
|
106
|
+
if (!app.version) {
|
|
107
|
+
console.warn(
|
|
108
|
+
`⚠️ Invalid implementation ID format for '${appSlugAndKey}': ${app.implementation_id}. Expected format: <implementationName>@<version>. Skipping...`,
|
|
109
|
+
);
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Update manifest using manifest plugin's function
|
|
114
|
+
const [manifestKey] = await context.updateManifestEntry(
|
|
115
|
+
app.key,
|
|
116
|
+
{
|
|
117
|
+
implementationName: app.key,
|
|
118
|
+
version: app.version,
|
|
119
|
+
},
|
|
120
|
+
configPath,
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
console.log(
|
|
124
|
+
`📝 Locked ${appSlugAndKey} to ${app.key}@${app.version} using key '${manifestKey}'`,
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
// Find matching authentication for this app if authentications were provided
|
|
128
|
+
let authenticationId: number | undefined;
|
|
129
|
+
if (authentications.length > 0) {
|
|
130
|
+
// Match authentication by app_key
|
|
131
|
+
const matchingAuth = authentications.find((auth) => {
|
|
132
|
+
return auth.app_key === app.key;
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
if (matchingAuth) {
|
|
136
|
+
authenticationId = matchingAuth.id;
|
|
137
|
+
console.log(
|
|
138
|
+
`🔐 Using authentication ${authenticationId} (${matchingAuth.title}) for ${appSlugAndKey}`,
|
|
139
|
+
);
|
|
140
|
+
} else {
|
|
141
|
+
console.warn(
|
|
142
|
+
`⚠️ No matching authentication found for ${appSlugAndKey}`,
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Generate types using the manifest key for consistency
|
|
148
|
+
const typesPath = join(resolvedTypesOutput, `${manifestKey}.d.ts`);
|
|
149
|
+
|
|
150
|
+
try {
|
|
151
|
+
// Use AST-based generator directly
|
|
152
|
+
const generator = new AstTypeGenerator();
|
|
153
|
+
const typeDefinitions = await generator.generateTypes({
|
|
154
|
+
appKey: manifestKey,
|
|
155
|
+
authenticationId,
|
|
156
|
+
sdk,
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// Write to file
|
|
160
|
+
await writeFile(typesPath, typeDefinitions, "utf8");
|
|
161
|
+
console.log(`🔧 Generated types for ${manifestKey} at ${typesPath}`);
|
|
162
|
+
} catch (error) {
|
|
163
|
+
console.warn(
|
|
164
|
+
`⚠️ Failed to generate types for ${appSlugAndKey}: ${error}`,
|
|
165
|
+
);
|
|
166
|
+
// Continue even if type generation fails
|
|
167
|
+
}
|
|
168
|
+
} catch (error) {
|
|
169
|
+
console.warn(`⚠️ Failed to process ${appSlugAndKey}: ${error}`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
console.log(`✅ Added ${apps.length} app(s) to manifest`);
|
|
174
|
+
}, AddSchema);
|
|
175
|
+
|
|
176
|
+
return {
|
|
177
|
+
add,
|
|
178
|
+
context: {
|
|
179
|
+
meta: {
|
|
180
|
+
add: {
|
|
181
|
+
categories: ["utility"],
|
|
182
|
+
inputSchema: AddSchema,
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
};
|
|
187
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { DEFAULT_CONFIG_PATH } from "@zapier/zapier-sdk";
|
|
3
|
+
|
|
4
|
+
export const AddSchema = z.object({
|
|
5
|
+
appKeys: z
|
|
6
|
+
.array(z.string().min(1, "App key cannot be empty"))
|
|
7
|
+
.min(1, "At least one app key is required"),
|
|
8
|
+
authenticationIds: z
|
|
9
|
+
.array(z.string())
|
|
10
|
+
.optional()
|
|
11
|
+
.describe("Authentication IDs to use for type generation"),
|
|
12
|
+
configPath: z
|
|
13
|
+
.string()
|
|
14
|
+
.optional()
|
|
15
|
+
.describe(
|
|
16
|
+
`Path to Zapier config file (defaults to '${DEFAULT_CONFIG_PATH}')`,
|
|
17
|
+
),
|
|
18
|
+
typesOutput: z
|
|
19
|
+
.string()
|
|
20
|
+
.optional()
|
|
21
|
+
.describe(
|
|
22
|
+
"Directory for TypeScript type files (defaults to (src|lib|.)/zapier/apps/)",
|
|
23
|
+
),
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export type AddOptions = z.infer<typeof AddSchema>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { Plugin } from "@zapier/zapier-sdk";
|
|
2
|
+
import {
|
|
3
|
+
GetLoginConfigPathSchema,
|
|
4
|
+
type GetLoginConfigPathOptions,
|
|
5
|
+
} from "./schemas";
|
|
6
|
+
import { createFunction } from "@zapier/zapier-sdk";
|
|
7
|
+
import { getConfigPath } from "@zapier/zapier-sdk-cli-login";
|
|
8
|
+
|
|
9
|
+
export interface GetLoginConfigPathPluginProvides {
|
|
10
|
+
getLoginConfigPath: (options?: GetLoginConfigPathOptions) => Promise<string>;
|
|
11
|
+
context: {
|
|
12
|
+
meta: {
|
|
13
|
+
getLoginConfigPath: {
|
|
14
|
+
inputSchema: typeof GetLoginConfigPathSchema;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const getLoginConfigPathPlugin: Plugin<
|
|
21
|
+
{}, // requires no existing SDK methods
|
|
22
|
+
{}, // requires no context
|
|
23
|
+
GetLoginConfigPathPluginProvides
|
|
24
|
+
> = () => {
|
|
25
|
+
const getLoginConfigPathWithSdk = createFunction(
|
|
26
|
+
async function getLoginConfigPathWithSdk(
|
|
27
|
+
_options?: GetLoginConfigPathOptions,
|
|
28
|
+
): Promise<string> {
|
|
29
|
+
return getConfigPath();
|
|
30
|
+
},
|
|
31
|
+
GetLoginConfigPathSchema,
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
getLoginConfigPath: getLoginConfigPathWithSdk,
|
|
36
|
+
context: {
|
|
37
|
+
meta: {
|
|
38
|
+
getLoginConfigPath: {
|
|
39
|
+
categories: ["utility"],
|
|
40
|
+
inputSchema: GetLoginConfigPathSchema,
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
// Get login config path schema - simple command with no parameters
|
|
4
|
+
export const GetLoginConfigPathSchema = z
|
|
5
|
+
.object({})
|
|
6
|
+
.describe("Show the path to the login configuration file");
|
|
7
|
+
|
|
8
|
+
export type GetLoginConfigPathOptions = z.infer<
|
|
9
|
+
typeof GetLoginConfigPathSchema
|
|
10
|
+
>;
|
package/src/plugins/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { loginPlugin } from "./login";
|
|
2
2
|
export { logoutPlugin } from "./logout";
|
|
3
3
|
export { mcpPlugin } from "./mcp";
|
|
4
|
-
export { generateTypesPlugin } from "./generateTypes";
|
|
5
4
|
export { bundleCodePlugin } from "./bundleCode";
|
|
6
|
-
export {
|
|
5
|
+
export { getLoginConfigPathPlugin } from "./getLoginConfigPath";
|
|
6
|
+
export { addPlugin } from "./add";
|
package/src/sdk.ts
CHANGED
|
@@ -7,9 +7,9 @@ import {
|
|
|
7
7
|
loginPlugin,
|
|
8
8
|
logoutPlugin,
|
|
9
9
|
mcpPlugin,
|
|
10
|
-
generateTypesPlugin,
|
|
11
10
|
bundleCodePlugin,
|
|
12
|
-
|
|
11
|
+
getLoginConfigPathPlugin,
|
|
12
|
+
addPlugin,
|
|
13
13
|
} from "./plugins/index";
|
|
14
14
|
|
|
15
15
|
export interface ZapierCliSdkOptions {
|
|
@@ -29,9 +29,9 @@ export function createZapierCliSdk(
|
|
|
29
29
|
});
|
|
30
30
|
|
|
31
31
|
// Add CLI-specific plugins before registry
|
|
32
|
-
sdk = sdk.addPlugin(generateTypesPlugin);
|
|
33
32
|
sdk = sdk.addPlugin(bundleCodePlugin);
|
|
34
|
-
sdk = sdk.addPlugin(
|
|
33
|
+
sdk = sdk.addPlugin(getLoginConfigPathPlugin);
|
|
34
|
+
sdk = sdk.addPlugin(addPlugin);
|
|
35
35
|
sdk = sdk.addPlugin(mcpPlugin);
|
|
36
36
|
sdk = sdk.addPlugin(loginPlugin);
|
|
37
37
|
sdk = sdk.addPlugin(logoutPlugin);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import {
|
|
2
|
+
import { isPositional, type FunctionRegistryEntry } from "@zapier/zapier-sdk";
|
|
3
3
|
|
|
4
4
|
// ============================================================================
|
|
5
5
|
// Types
|
|
@@ -20,14 +20,17 @@ export interface CliParameter {
|
|
|
20
20
|
// Schema Analysis
|
|
21
21
|
// ============================================================================
|
|
22
22
|
|
|
23
|
-
export function analyzeZodSchema(
|
|
23
|
+
export function analyzeZodSchema(
|
|
24
|
+
schema: z.ZodSchema,
|
|
25
|
+
functionInfo?: FunctionRegistryEntry,
|
|
26
|
+
): CliParameter[] {
|
|
24
27
|
const parameters: CliParameter[] = [];
|
|
25
28
|
|
|
26
29
|
if (schema instanceof z.ZodObject) {
|
|
27
30
|
const shape = schema.shape;
|
|
28
31
|
|
|
29
|
-
for (const [key, fieldSchema] of Object.entries(shape)) {
|
|
30
|
-
const param = analyzeZodField(key, fieldSchema
|
|
32
|
+
for (const [key, fieldSchema] of Object.entries<z.ZodSchema>(shape)) {
|
|
33
|
+
const param = analyzeZodField(key, fieldSchema, functionInfo);
|
|
31
34
|
if (param) {
|
|
32
35
|
parameters.push(param);
|
|
33
36
|
}
|
|
@@ -40,6 +43,7 @@ export function analyzeZodSchema(schema: z.ZodSchema): CliParameter[] {
|
|
|
40
43
|
function analyzeZodField(
|
|
41
44
|
name: string,
|
|
42
45
|
schema: z.ZodSchema,
|
|
46
|
+
functionInfo?: FunctionRegistryEntry,
|
|
43
47
|
): CliParameter | null {
|
|
44
48
|
let baseSchema = schema;
|
|
45
49
|
let required = true;
|
|
@@ -77,6 +81,14 @@ function analyzeZodField(
|
|
|
77
81
|
paramType = "string";
|
|
78
82
|
}
|
|
79
83
|
|
|
84
|
+
// Check if this parameter has a resolver
|
|
85
|
+
let paramHasResolver = false;
|
|
86
|
+
|
|
87
|
+
// Check function-specific resolvers first
|
|
88
|
+
if (functionInfo?.resolvers?.[name]) {
|
|
89
|
+
paramHasResolver = true;
|
|
90
|
+
}
|
|
91
|
+
|
|
80
92
|
// Extract resolver metadata
|
|
81
93
|
return {
|
|
82
94
|
name,
|
|
@@ -85,7 +97,7 @@ function analyzeZodField(
|
|
|
85
97
|
description: schema.description,
|
|
86
98
|
default: defaultValue,
|
|
87
99
|
choices,
|
|
88
|
-
hasResolver:
|
|
100
|
+
hasResolver: paramHasResolver,
|
|
89
101
|
isPositional: isPositional(schema),
|
|
90
102
|
};
|
|
91
103
|
}
|