instant-cli 1.0.23-branch-codex-cli-args-combinators.25394030897.1 → 1.0.23-branch-codex-cli-args-combinators.25395572961.1
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/.turbo/turbo-build.log +1 -1
- package/__tests__/args.test.ts +89 -45
- package/__tests__/oauthMock.ts +3 -2
- package/dist/commands/auth/client/add.d.ts.map +1 -1
- package/dist/commands/auth/client/add.js +57 -28
- package/dist/commands/auth/client/add.js.map +1 -1
- package/dist/commands/auth/client/shared.d.ts +0 -4
- package/dist/commands/auth/client/shared.d.ts.map +1 -1
- package/dist/commands/auth/client/shared.js +0 -4
- package/dist/commands/auth/client/shared.js.map +1 -1
- package/dist/commands/auth/client/update.d.ts.map +1 -1
- package/dist/commands/auth/client/update.js +59 -29
- package/dist/commands/auth/client/update.js.map +1 -1
- package/dist/commands/auth/origin/add.d.ts.map +1 -1
- package/dist/commands/auth/origin/add.js +8 -4
- package/dist/commands/auth/origin/add.js.map +1 -1
- package/dist/lib/args.d.ts +42 -29
- package/dist/lib/args.d.ts.map +1 -1
- package/dist/lib/args.js +91 -73
- package/dist/lib/args.js.map +1 -1
- package/dist/lib/oauth.d.ts.map +1 -1
- package/dist/lib/oauth.js +2 -1
- package/dist/lib/oauth.js.map +1 -1
- package/package.json +4 -4
- package/src/commands/auth/client/add.ts +88 -78
- package/src/commands/auth/client/shared.ts +0 -12
- package/src/commands/auth/client/update.ts +106 -98
- package/src/commands/auth/origin/add.ts +12 -8
- package/src/lib/args.ts +175 -120
- package/src/lib/oauth.ts +3 -2
|
@@ -95,8 +95,9 @@ const addOriginHandler = Effect.fn(function* (
|
|
|
95
95
|
const handleGenericOrigin = Effect.fn(function* (
|
|
96
96
|
opts: Record<string, unknown>,
|
|
97
97
|
) {
|
|
98
|
-
const
|
|
99
|
-
|
|
98
|
+
const args = Args.from(opts);
|
|
99
|
+
const url = yield* args.text('url').pipe(
|
|
100
|
+
Args.prompt({
|
|
100
101
|
prompt: 'Website URL:',
|
|
101
102
|
placeholder: 'example.com',
|
|
102
103
|
modifyOutput: UI.modifiers.piped([
|
|
@@ -120,8 +121,9 @@ const handleGenericOrigin = Effect.fn(function* (
|
|
|
120
121
|
});
|
|
121
122
|
|
|
122
123
|
const handleVercelOrigin = Effect.fn(function* (opts: Record<string, unknown>) {
|
|
123
|
-
const
|
|
124
|
-
|
|
124
|
+
const args = Args.from(opts);
|
|
125
|
+
const project = yield* args.text('project').pipe(
|
|
126
|
+
Args.prompt({
|
|
125
127
|
prompt: 'Vercel project name:',
|
|
126
128
|
placeholder: 'vercel-project-name',
|
|
127
129
|
modifyOutput: UI.modifiers.piped([
|
|
@@ -143,8 +145,9 @@ const handleVercelOrigin = Effect.fn(function* (opts: Record<string, unknown>) {
|
|
|
143
145
|
const handleNetlifyOrigin = Effect.fn(function* (
|
|
144
146
|
opts: Record<string, unknown>,
|
|
145
147
|
) {
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
+
const args = Args.from(opts);
|
|
149
|
+
const site = yield* args.text('site').pipe(
|
|
150
|
+
Args.prompt({
|
|
148
151
|
prompt: 'Netlify site name:',
|
|
149
152
|
placeholder: 'netlify-site-name',
|
|
150
153
|
modifyOutput: UI.modifiers.piped([
|
|
@@ -166,8 +169,9 @@ const handleNetlifyOrigin = Effect.fn(function* (
|
|
|
166
169
|
const handleCustomSchemeOrigin = Effect.fn(function* (
|
|
167
170
|
opts: Record<string, unknown>,
|
|
168
171
|
) {
|
|
169
|
-
const
|
|
170
|
-
|
|
172
|
+
const args = Args.from(opts);
|
|
173
|
+
const scheme = yield* args.text('scheme').pipe(
|
|
174
|
+
Args.prompt({
|
|
171
175
|
prompt: 'App scheme:',
|
|
172
176
|
placeholder: 'app-scheme://',
|
|
173
177
|
modifyOutput: UI.modifiers.piped([
|
package/src/lib/args.ts
CHANGED
|
@@ -4,30 +4,74 @@ import { GlobalOpts } from '../context/globalOpts.ts';
|
|
|
4
4
|
import { UI } from '../ui/index.ts';
|
|
5
5
|
import { runUIEffect } from './ui.ts';
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
*
|
|
12
|
-
* Effect values do not have a natural place to store "this came from
|
|
13
|
-
* --client-id", but the prompt/validation combinators need that flag name for
|
|
14
|
-
* errors. The symbol keeps the metadata private to this module and prevents
|
|
15
|
-
* these helpers from accepting arbitrary Effects.
|
|
16
|
-
*/
|
|
17
|
-
export type ArgEffect<A, E = never, R = never> = Effect.Effect<A, E, R> & {
|
|
18
|
-
readonly [ArgFlag]: string;
|
|
7
|
+
type ActiveArg<A, E, R> = {
|
|
8
|
+
readonly _tag: 'Active';
|
|
9
|
+
readonly provided: boolean;
|
|
10
|
+
readonly value: Effect.Effect<A | undefined, E, R>;
|
|
19
11
|
};
|
|
20
12
|
|
|
21
|
-
|
|
13
|
+
type InactiveArg = {
|
|
14
|
+
readonly _tag: 'Inactive';
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
type ArgState<A, E, R> = ActiveArg<A, E, R> | InactiveArg;
|
|
18
|
+
|
|
19
|
+
export interface Arg<A, E = never, R = never> {
|
|
20
|
+
readonly flag: string;
|
|
21
|
+
readonly state: Effect.Effect<ArgState<A, E, R>, E, R>;
|
|
22
|
+
pipe(): Arg<A, E, R>;
|
|
23
|
+
pipe<B>(ab: (self: Arg<A, E, R>) => B): B;
|
|
24
|
+
pipe<B, C>(ab: (self: Arg<A, E, R>) => B, bc: (b: B) => C): C;
|
|
25
|
+
pipe<B, C, D>(
|
|
26
|
+
ab: (self: Arg<A, E, R>) => B,
|
|
27
|
+
bc: (b: B) => C,
|
|
28
|
+
cd: (c: C) => D,
|
|
29
|
+
): D;
|
|
30
|
+
pipe<B, C, D, F>(
|
|
31
|
+
ab: (self: Arg<A, E, R>) => B,
|
|
32
|
+
bc: (b: B) => C,
|
|
33
|
+
cd: (c: C) => D,
|
|
34
|
+
df: (d: D) => F,
|
|
35
|
+
): F;
|
|
36
|
+
pipe<B, C, D, F, G>(
|
|
37
|
+
ab: (self: Arg<A, E, R>) => B,
|
|
38
|
+
bc: (b: B) => C,
|
|
39
|
+
cd: (c: C) => D,
|
|
40
|
+
df: (d: D) => F,
|
|
41
|
+
fg: (f: F) => G,
|
|
42
|
+
): G;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const keyName = (name: string) => name.replace(/^--/, '');
|
|
46
|
+
|
|
47
|
+
const flagName = (name: string) => {
|
|
48
|
+
const key = keyName(name);
|
|
49
|
+
return key.startsWith('-') ? key : `--${key}`;
|
|
50
|
+
};
|
|
22
51
|
|
|
23
52
|
const makeArg = <A, E, R>(
|
|
24
53
|
flag: string,
|
|
25
|
-
|
|
26
|
-
):
|
|
27
|
-
|
|
54
|
+
state: Effect.Effect<ArgState<A, E, R>, E, R>,
|
|
55
|
+
): Arg<A, E, R> => {
|
|
56
|
+
const arg: Arg<A, E, R> = {
|
|
57
|
+
flag,
|
|
58
|
+
state,
|
|
59
|
+
pipe: function pipe(
|
|
60
|
+
this: Arg<A, E, R>,
|
|
61
|
+
...fns: Array<(value: unknown) => unknown>
|
|
62
|
+
) {
|
|
63
|
+
return fns.reduce<unknown>((value, fn) => fn(value), this);
|
|
64
|
+
} as Arg<A, E, R>['pipe'],
|
|
65
|
+
};
|
|
66
|
+
return arg;
|
|
28
67
|
};
|
|
29
68
|
|
|
30
|
-
const
|
|
69
|
+
const active = <A, E, R>(
|
|
70
|
+
value: Effect.Effect<A | undefined, E, R>,
|
|
71
|
+
provided: boolean,
|
|
72
|
+
): ActiveArg<A, E, R> => ({ _tag: 'Active', provided, value });
|
|
73
|
+
|
|
74
|
+
const inactive: InactiveArg = { _tag: 'Inactive' };
|
|
31
75
|
|
|
32
76
|
const missingMessage = (flag: string) => `Missing required value for ${flag}`;
|
|
33
77
|
|
|
@@ -35,10 +79,47 @@ type MissingOptions = {
|
|
|
35
79
|
message?: string;
|
|
36
80
|
};
|
|
37
81
|
|
|
38
|
-
|
|
39
|
-
|
|
82
|
+
type UnavailableOptions = {
|
|
83
|
+
message?: string;
|
|
84
|
+
otherwise?: string;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
type ArgsReader = {
|
|
88
|
+
text: (name: string) => Arg<string, BadArgsError>;
|
|
89
|
+
bool: (name: string) => Arg<boolean, BadArgsError>;
|
|
90
|
+
has: (name: string) => boolean;
|
|
91
|
+
hasAny: (names: string[]) => boolean;
|
|
92
|
+
isTrue: (name: string) => boolean;
|
|
93
|
+
raw: (name: string) => unknown;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
function from(opts: Record<string, unknown>): ArgsReader {
|
|
97
|
+
const raw = (name: string) => opts[keyName(name)];
|
|
98
|
+
const has = (name: string) =>
|
|
99
|
+
Object.prototype.hasOwnProperty.call(opts, keyName(name));
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
text: (name) => text(opts, name),
|
|
103
|
+
bool: (name) => bool(opts, name),
|
|
104
|
+
has,
|
|
105
|
+
hasAny: (names) => names.some(has),
|
|
106
|
+
isTrue: (name) => {
|
|
107
|
+
const value = raw(name);
|
|
108
|
+
return value === true || value === 'true';
|
|
109
|
+
},
|
|
110
|
+
raw,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
40
113
|
|
|
41
|
-
|
|
114
|
+
function text(opts: Record<string, unknown>, name: string) {
|
|
115
|
+
const key = keyName(name);
|
|
116
|
+
const flag = flagName(key);
|
|
117
|
+
const provided = Object.prototype.hasOwnProperty.call(opts, key);
|
|
118
|
+
|
|
119
|
+
return makeArg(
|
|
120
|
+
flag,
|
|
121
|
+
Effect.succeed(active(readTextValue(opts[key], flag), provided)),
|
|
122
|
+
);
|
|
42
123
|
}
|
|
43
124
|
|
|
44
125
|
function readTextValue(value: unknown, flag: string) {
|
|
@@ -57,9 +138,14 @@ function readTextValue(value: unknown, flag: string) {
|
|
|
57
138
|
}
|
|
58
139
|
|
|
59
140
|
function bool(opts: Record<string, unknown>, name: string) {
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
141
|
+
const key = keyName(name);
|
|
142
|
+
const flag = flagName(key);
|
|
143
|
+
const provided = Object.prototype.hasOwnProperty.call(opts, key);
|
|
144
|
+
|
|
145
|
+
return makeArg(
|
|
146
|
+
flag,
|
|
147
|
+
Effect.succeed(active(readBooleanValue(opts[key], flag), provided)),
|
|
148
|
+
);
|
|
63
149
|
}
|
|
64
150
|
|
|
65
151
|
function readBooleanValue(value: unknown, flag: string) {
|
|
@@ -78,23 +164,49 @@ function uiErrorToBadArgs(e: { message: string }) {
|
|
|
78
164
|
return BadArgsError.make({ message: `UI error: ${e.message}` });
|
|
79
165
|
}
|
|
80
166
|
|
|
81
|
-
function
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
167
|
+
function mapActive<A, B, E, R, E2, R2>(
|
|
168
|
+
arg: Arg<A, E, R>,
|
|
169
|
+
mapValue: (
|
|
170
|
+
value: Effect.Effect<A | undefined, E, R>,
|
|
171
|
+
) => Effect.Effect<B | undefined, E | E2, R | R2>,
|
|
172
|
+
): Arg<B, E | E2, R | R2> {
|
|
173
|
+
return makeArg(
|
|
174
|
+
arg.flag,
|
|
175
|
+
Effect.gen(function* mapArgState() {
|
|
176
|
+
const state = yield* arg.state;
|
|
177
|
+
if (state._tag === 'Inactive') return inactive;
|
|
178
|
+
return active(mapValue(state.value), state.provided);
|
|
179
|
+
}),
|
|
180
|
+
);
|
|
85
181
|
}
|
|
86
182
|
|
|
87
|
-
function
|
|
88
|
-
return function
|
|
89
|
-
arg: ArgEffect<string | undefined, E, R>,
|
|
90
|
-
) {
|
|
91
|
-
const flag = getFlag(arg);
|
|
92
|
-
|
|
183
|
+
function availableWhen(condition: boolean, options?: UnavailableOptions) {
|
|
184
|
+
return function availableWhenArg<A, E, R>(arg: Arg<A, E, R>) {
|
|
93
185
|
return makeArg(
|
|
94
|
-
flag,
|
|
186
|
+
arg.flag,
|
|
187
|
+
Effect.gen(function* gateArgAvailability() {
|
|
188
|
+
const state = yield* arg.state;
|
|
189
|
+
if (condition || state._tag === 'Inactive') return state;
|
|
190
|
+
if (state.provided) {
|
|
191
|
+
return yield* BadArgsError.make({
|
|
192
|
+
message:
|
|
193
|
+
options?.message ??
|
|
194
|
+
options?.otherwise ??
|
|
195
|
+
`${arg.flag} is not compatible with other options`,
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
return inactive;
|
|
199
|
+
}),
|
|
200
|
+
);
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function prompt(prompt: UI.TextInputProps) {
|
|
205
|
+
return function promptArg<E, R>(arg: Arg<string, E, R>) {
|
|
206
|
+
return mapActive(arg, (valueEffect) =>
|
|
95
207
|
Effect.gen(function* promptWhenMissing() {
|
|
96
|
-
const value = yield*
|
|
97
|
-
if (value !== undefined
|
|
208
|
+
const value = yield* valueEffect;
|
|
209
|
+
if (value !== undefined) return value;
|
|
98
210
|
|
|
99
211
|
const { yes } = yield* GlobalOpts;
|
|
100
212
|
if (yes) return undefined;
|
|
@@ -109,25 +221,12 @@ function orPromptIf(condition: boolean, prompt: UI.TextInputProps) {
|
|
|
109
221
|
};
|
|
110
222
|
}
|
|
111
223
|
|
|
112
|
-
function
|
|
113
|
-
return function
|
|
114
|
-
arg
|
|
115
|
-
) {
|
|
116
|
-
return orConfirmIf(true, prompt)(arg);
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function orConfirmIf(condition: boolean, prompt: UI.ConfirmationProps) {
|
|
121
|
-
return function orConfirmIfArg<E, R>(
|
|
122
|
-
arg: ArgEffect<boolean | undefined, E, R>,
|
|
123
|
-
) {
|
|
124
|
-
const flag = getFlag(arg);
|
|
125
|
-
|
|
126
|
-
return makeArg(
|
|
127
|
-
flag,
|
|
224
|
+
function confirm(prompt: UI.ConfirmationProps) {
|
|
225
|
+
return function confirmArg<E, R>(arg: Arg<boolean, E, R>) {
|
|
226
|
+
return mapActive(arg, (valueEffect) =>
|
|
128
227
|
Effect.gen(function* confirmWhenMissing() {
|
|
129
|
-
const value = yield*
|
|
130
|
-
if (value !== undefined
|
|
228
|
+
const value = yield* valueEffect;
|
|
229
|
+
if (value !== undefined) return value;
|
|
131
230
|
|
|
132
231
|
const { yes } = yield* GlobalOpts;
|
|
133
232
|
if (yes) return undefined;
|
|
@@ -141,83 +240,39 @@ function orConfirmIf(condition: boolean, prompt: UI.ConfirmationProps) {
|
|
|
141
240
|
}
|
|
142
241
|
|
|
143
242
|
function required(options?: MissingOptions) {
|
|
144
|
-
return function requiredArg<A, E, R>(arg:
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
flag,
|
|
149
|
-
Effect.gen(function* requireValue() {
|
|
150
|
-
const value = yield* arg;
|
|
151
|
-
if (value !== undefined) return value;
|
|
152
|
-
|
|
153
|
-
return yield* BadArgsError.make({
|
|
154
|
-
message: options?.message ?? missingMessage(flag),
|
|
155
|
-
});
|
|
156
|
-
}),
|
|
157
|
-
);
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
function requiredIf(condition: boolean, options?: MissingOptions) {
|
|
162
|
-
return function requiredIfArg<A, E, R>(
|
|
163
|
-
arg: ArgEffect<A | undefined, E, R>,
|
|
164
|
-
): ArgEffect<A | undefined, E | BadArgsError, R> {
|
|
165
|
-
return condition ? required(options)(arg) : arg;
|
|
166
|
-
};
|
|
167
|
-
}
|
|
243
|
+
return function requiredArg<A, E, R>(arg: Arg<A, E, R>) {
|
|
244
|
+
return Effect.gen(function* requireValue() {
|
|
245
|
+
const state = yield* arg.state;
|
|
246
|
+
if (state._tag === 'Inactive') return undefined as A;
|
|
168
247
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
const flag = getFlag(arg);
|
|
248
|
+
const value = yield* state.value;
|
|
249
|
+
if (value !== undefined) return value;
|
|
172
250
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
if (condition && value !== undefined) {
|
|
178
|
-
return yield* BadArgsError.make({
|
|
179
|
-
message:
|
|
180
|
-
options?.message ??
|
|
181
|
-
`${flag} is not compatible with other options`,
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
return condition ? undefined : value;
|
|
186
|
-
}),
|
|
187
|
-
);
|
|
251
|
+
return yield* BadArgsError.make({
|
|
252
|
+
message: options?.message ?? missingMessage(arg.flag),
|
|
253
|
+
});
|
|
254
|
+
});
|
|
188
255
|
};
|
|
189
256
|
}
|
|
190
257
|
|
|
191
|
-
function
|
|
192
|
-
return function
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
flag,
|
|
197
|
-
Effect.gen(function* validateValueIfPresent() {
|
|
198
|
-
const value = yield* arg;
|
|
199
|
-
if (value === undefined) return undefined;
|
|
200
|
-
|
|
201
|
-
const error = validateValue(value);
|
|
202
|
-
if (error) {
|
|
203
|
-
return yield* BadArgsError.make({ message: error });
|
|
204
|
-
}
|
|
258
|
+
function optional() {
|
|
259
|
+
return function optionalArg<A, E, R>(arg: Arg<A, E, R>) {
|
|
260
|
+
return Effect.gen(function* optionalValue() {
|
|
261
|
+
const state = yield* arg.state;
|
|
262
|
+
if (state._tag === 'Inactive') return undefined;
|
|
205
263
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
);
|
|
264
|
+
return yield* state.value;
|
|
265
|
+
});
|
|
209
266
|
};
|
|
210
267
|
}
|
|
211
268
|
|
|
212
269
|
export const Args = {
|
|
270
|
+
from,
|
|
213
271
|
text,
|
|
214
272
|
bool,
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
orConfirmIf,
|
|
273
|
+
availableWhen,
|
|
274
|
+
prompt,
|
|
275
|
+
confirm,
|
|
219
276
|
required,
|
|
220
|
-
|
|
221
|
-
forbidIf,
|
|
222
|
-
validate,
|
|
277
|
+
optional,
|
|
223
278
|
};
|
package/src/lib/oauth.ts
CHANGED
|
@@ -253,14 +253,15 @@ export const getClientNameAndProvider = Effect.fn(function* (
|
|
|
253
253
|
providerType: typeof ClientTypeSchema.Type,
|
|
254
254
|
opts: Record<string, unknown>,
|
|
255
255
|
) {
|
|
256
|
+
const args = Args.from(opts);
|
|
256
257
|
const { auth, provider } = yield* getOrCreateProvider(providerType);
|
|
257
258
|
const usedClientNames = new Set(
|
|
258
259
|
(auth.oauth_clients ?? []).map((client) => client.client_name),
|
|
259
260
|
);
|
|
260
261
|
const suggestedClientName = findName(providerType, usedClientNames);
|
|
261
262
|
|
|
262
|
-
const clientName = yield*
|
|
263
|
-
Args.
|
|
263
|
+
const clientName = yield* args.text('name').pipe(
|
|
264
|
+
Args.prompt({
|
|
264
265
|
prompt: 'Client Name:',
|
|
265
266
|
defaultValue: suggestedClientName,
|
|
266
267
|
placeholder: suggestedClientName,
|