@slates/cli 1.0.0-rc.2 → 1.0.0-rc.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@slates/cli",
3
- "version": "1.0.0-rc.2",
3
+ "version": "1.0.0-rc.4",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -25,8 +25,9 @@
25
25
  },
26
26
  "dependencies": {
27
27
  "@inquirer/prompts": "^7.4.0",
28
- "@slates/client": "1.0.0-rc.2",
29
- "@slates/profiles": "1.0.0-rc.2",
28
+ "@slates/client": "1.0.0-rc.6",
29
+ "@slates/oauth-microsoft": "1.0.0-rc.1",
30
+ "@slates/profiles": "1.0.0-rc.4",
30
31
  "sade": "^1.8.1"
31
32
  },
32
33
  "devDependencies": {
@@ -1,4 +1,5 @@
1
1
  import { confirm, select } from '@inquirer/prompts';
2
+ import { normalizeMicrosoftRedirectUriForIntegration } from '@slates/oauth-microsoft';
2
3
  import { SlatesOAuthCredentialRecord, SlatesStoredAuth } from '@slates/profiles';
3
4
  import {
4
5
  chooseAuthMethod,
@@ -6,7 +7,7 @@ import {
6
7
  createIntegrationClientContext,
7
8
  openIntegrationStore
8
9
  } from '../lib/context';
9
- import { chooseScopes, createOAuthCallbackListener, openBrowser } from '../lib/oauth';
10
+ import { chooseScopes, createOAuthCallbackListener, printBrowserUrl } from '../lib/oauth';
10
11
  import {
11
12
  parseJsonObject,
12
13
  parseList,
@@ -263,7 +264,11 @@ let runAuthSetup = async (opts: AuthSetupOptions): Promise<SlatesStoredAuth> =>
263
264
 
264
265
  if (authMethod.type === 'auth.oauth') {
265
266
  let callback = await createOAuthCallbackListener();
266
- console.log(`OAuth redirect URL: ${callback.redirectUri}`);
267
+ let redirectUri = normalizeMicrosoftRedirectUriForIntegration(
268
+ opts.integration,
269
+ callback.redirectUri
270
+ );
271
+ console.log(`OAuth redirect URL: ${redirectUri}`);
267
272
 
268
273
  let resolvedOAuthCredentials = await chooseOAuthCredentialsForSetup({
269
274
  store,
@@ -282,7 +287,7 @@ let runAuthSetup = async (opts: AuthSetupOptions): Promise<SlatesStoredAuth> =>
282
287
 
283
288
  let authorizationUrl = await client.getAuthorizationUrl({
284
289
  authenticationMethodId: authMethod.id,
285
- redirectUri: callback.redirectUri,
290
+ redirectUri,
286
291
  state: callback.state,
287
292
  input: authInput,
288
293
  clientId,
@@ -293,7 +298,7 @@ let runAuthSetup = async (opts: AuthSetupOptions): Promise<SlatesStoredAuth> =>
293
298
  callbackState = authorizationUrl.callbackState ?? null;
294
299
  finalInput = authorizationUrl.input ?? authInput;
295
300
 
296
- await openBrowser(authorizationUrl.authorizationUrl);
301
+ printBrowserUrl(authorizationUrl.authorizationUrl);
297
302
  let callbackResult = await callback.wait();
298
303
  if (callbackResult.state !== callback.state) {
299
304
  throw new Error('OAuth state mismatch.');
@@ -303,7 +308,7 @@ let runAuthSetup = async (opts: AuthSetupOptions): Promise<SlatesStoredAuth> =>
303
308
  authenticationMethodId: authMethod.id,
304
309
  code: callbackResult.code,
305
310
  state: callbackResult.state,
306
- redirectUri: callback.redirectUri,
311
+ redirectUri,
307
312
  input: finalInput,
308
313
  clientId,
309
314
  clientSecret,
@@ -47,6 +47,7 @@ export let runVitestWithProfile = async (opts: WithProfile & { vitestArgs: strin
47
47
  {
48
48
  integration: integration.relativeDir,
49
49
  profileId: profile.id,
50
+ rootDir: store.rootDir,
50
51
  storePath: store.storePath,
51
52
  cliDir: store.dirPath
52
53
  },
@@ -64,6 +65,7 @@ export let runVitestWithProfile = async (opts: WithProfile & { vitestArgs: strin
64
65
  SLATES_INTEGRATION: integration.relativeDir,
65
66
  SLATES_PROFILE_ID: profile.id,
66
67
  SLATES_CLI_DIR: store.dirPath,
68
+ SLATES_STORE_ROOT_DIR: store.rootDir,
67
69
  SLATES_STORE_PATH: store.storePath,
68
70
  SLATES_TEST_CONTEXT_PATH: contextPath
69
71
  }
@@ -36,17 +36,24 @@ let isWithinRoot = (rootDir: string, targetPath: string) => {
36
36
 
37
37
  let resolveIntegrationDir = async (input: string, cwd: string) => {
38
38
  let rootDir = resolveSlatesCliRoot(cwd);
39
- let namedPath = path.join(rootDir, 'integrations', input);
39
+ let integrationRoots = [
40
+ path.join(rootDir, 'integrations'),
41
+ path.join(rootDir, 'test-integrations')
42
+ ];
43
+
40
44
  if (!input.includes(path.sep) && !input.includes('/')) {
41
- if (await pathExists(path.join(namedPath, 'package.json'))) {
42
- return { rootDir, dirPath: namedPath };
45
+ for (let root of integrationRoots) {
46
+ let namedPath = path.join(root, input);
47
+ if (await pathExists(path.join(namedPath, 'package.json'))) {
48
+ return { rootDir, dirPath: namedPath };
49
+ }
43
50
  }
44
51
  }
45
52
 
46
53
  let candidate = path.resolve(cwd, input);
47
54
  if (!(await pathExists(path.join(candidate, 'package.json')))) {
48
55
  throw new Error(
49
- `Could not resolve integration "${input}". Pass an integration name from \`integrations/\` or a relative path to an integration directory.`
56
+ `Could not resolve integration "${input}". Pass an integration name from \`integrations/\` or \`test-integrations/\`, or a relative path to an integration directory.`
50
57
  );
51
58
  }
52
59
 
@@ -103,32 +110,41 @@ export let resolveIntegration = async (
103
110
  export let listWorkspaceIntegrations = async (opts: { cwd?: string } = {}) => {
104
111
  let cwd = opts.cwd ?? process.cwd();
105
112
  let rootDir = resolveSlatesCliRoot(cwd);
106
- let integrationsDir = path.join(rootDir, 'integrations');
113
+ let integrationRoots = [
114
+ path.join(rootDir, 'integrations'),
115
+ path.join(rootDir, 'test-integrations')
116
+ ];
117
+
118
+ let integrations: WorkspaceIntegrationSummary[] = [];
119
+
120
+ for (let integrationsDir of integrationRoots) {
121
+ if (!(await pathExists(integrationsDir))) {
122
+ continue;
123
+ }
107
124
 
108
- if (!(await pathExists(integrationsDir))) {
109
- return [];
125
+ let entries = await readdir(integrationsDir, { withFileTypes: true });
126
+ let chunk = await Promise.all(
127
+ entries
128
+ .filter(entry => entry.isDirectory())
129
+ .map(async entry => {
130
+ let dirPath = path.join(integrationsDir, entry.name);
131
+ if (!(await pathExists(path.join(dirPath, 'package.json')))) {
132
+ return null;
133
+ }
134
+
135
+ return {
136
+ rootDir,
137
+ dirPath,
138
+ relativeDir: toPosixPath(path.relative(rootDir, dirPath)),
139
+ name: entry.name
140
+ } satisfies WorkspaceIntegrationSummary;
141
+ })
142
+ );
143
+
144
+ integrations.push(
145
+ ...chunk.filter((integration): integration is WorkspaceIntegrationSummary => integration !== null)
146
+ );
110
147
  }
111
148
 
112
- let entries = await readdir(integrationsDir, { withFileTypes: true });
113
- let integrations = await Promise.all(
114
- entries
115
- .filter(entry => entry.isDirectory())
116
- .map(async entry => {
117
- let dirPath = path.join(integrationsDir, entry.name);
118
- if (!(await pathExists(path.join(dirPath, 'package.json')))) {
119
- return null;
120
- }
121
-
122
- return {
123
- rootDir,
124
- dirPath,
125
- relativeDir: toPosixPath(path.relative(rootDir, dirPath)),
126
- name: entry.name
127
- } satisfies WorkspaceIntegrationSummary;
128
- })
129
- );
130
-
131
- return integrations
132
- .filter((integration): integration is WorkspaceIntegrationSummary => integration !== null)
133
- .sort((a, b) => a.name.localeCompare(b.name));
149
+ return integrations.sort((a, b) => a.relativeDir.localeCompare(b.relativeDir));
134
150
  };
package/src/lib/oauth.ts CHANGED
@@ -1,10 +1,7 @@
1
1
  import { checkbox } from '@inquirer/prompts';
2
- import { execFile } from 'child_process';
3
2
  import { randomUUID } from 'crypto';
4
3
  import { createServer } from 'http';
5
- import { promisify } from 'util';
6
4
 
7
- let execFileAsync = promisify(execFile);
8
5
  let DEFAULT_OAUTH_CALLBACK_PORT = 45873;
9
6
 
10
7
  export let chooseScopes = async (
@@ -21,27 +18,16 @@ export let chooseScopes = async (
21
18
  choices: authMethod.scopes.map((scope: any) => ({
22
19
  name: `${scope.title} (${scope.id})`,
23
20
  value: scope.id,
24
- checked: initialScopes.length > 0 ? initialScopes.includes(scope.id) : true
21
+ checked:
22
+ initialScopes.length > 0
23
+ ? initialScopes.includes(scope.id)
24
+ : scope.defaultChecked ?? true
25
25
  }))
26
26
  })) as string[];
27
27
  };
28
28
 
29
- export let openBrowser = async (url: string) => {
30
- try {
31
- if (process.platform === 'darwin') {
32
- await execFileAsync('open', [url]);
33
- return;
34
- }
35
-
36
- if (process.platform === 'win32') {
37
- await execFileAsync('cmd', ['/c', 'start', '', url]);
38
- return;
39
- }
40
-
41
- await execFileAsync('xdg-open', [url]);
42
- } catch {
43
- console.log(`Open this URL in your browser:\n${url}`);
44
- }
29
+ export let printBrowserUrl = (url: string) => {
30
+ console.log(`Open this URL in your browser:\n${url}`);
45
31
  };
46
32
 
47
33
  export let createOAuthCallbackListener = async () => {