@slates/cli 1.0.0-rc.5 → 1.0.0-rc.9
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 +6 -6
- package/src/commands/auth.test.ts +24 -0
- package/src/commands/auth.ts +12 -3
- package/src/commands/config.ts +1 -1
- package/src/commands/profiles.ts +14 -6
- package/src/commands/repl.ts +1 -1
- package/src/commands/test.ts +3 -3
- package/src/commands/tools.ts +1 -1
- package/src/lib/context.ts +3 -3
- package/src/lib/integration.test.ts +10 -2
- package/src/lib/integration.ts +5 -3
- package/src/lib/oauth.ts +20 -4
- package/src/lib/prompts.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@slates/cli",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.9",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -20,14 +20,14 @@
|
|
|
20
20
|
},
|
|
21
21
|
"scripts": {
|
|
22
22
|
"test": "vitest run --passWithNoTests",
|
|
23
|
-
"
|
|
24
|
-
"
|
|
23
|
+
"typecheck": "tsc --noEmit",
|
|
24
|
+
"biome:check": "biome check --write src"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@inquirer/prompts": "^7.4.0",
|
|
28
|
-
"@slates/client": "1.0.0-rc.
|
|
29
|
-
"@slates/oauth-microsoft": "1.0.0-rc.
|
|
30
|
-
"@slates/profiles": "1.0.0-rc.
|
|
28
|
+
"@slates/client": "1.0.0-rc.11",
|
|
29
|
+
"@slates/oauth-microsoft": "1.0.0-rc.4",
|
|
30
|
+
"@slates/profiles": "1.0.0-rc.9",
|
|
31
31
|
"sade": "^1.8.1"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
@@ -8,6 +8,30 @@ describe('normalizeCallbackRedirectUriForIntegration', () => {
|
|
|
8
8
|
).toBe('http://localhost:45873/callback');
|
|
9
9
|
});
|
|
10
10
|
|
|
11
|
+
it('normalizes Intercom loopback redirects to localhost', () => {
|
|
12
|
+
expect(
|
|
13
|
+
normalizeCallbackRedirectUriForIntegration('intercom', 'http://127.0.0.1:45873/callback')
|
|
14
|
+
).toBe('http://localhost:45873/callback');
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('normalizes Typeform loopback redirects to localhost', () => {
|
|
18
|
+
expect(
|
|
19
|
+
normalizeCallbackRedirectUriForIntegration('typeform', 'http://127.0.0.1:45873/callback')
|
|
20
|
+
).toBe('http://localhost:45873/callback');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('normalizes Xero loopback redirects to localhost', () => {
|
|
24
|
+
expect(
|
|
25
|
+
normalizeCallbackRedirectUriForIntegration('xero', 'http://127.0.0.1:45873/callback')
|
|
26
|
+
).toBe('http://localhost:45873/callback');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('normalizes Zendesk loopback redirects to localhost', () => {
|
|
30
|
+
expect(
|
|
31
|
+
normalizeCallbackRedirectUriForIntegration('zendesk', 'http://127.0.0.1:45873/callback')
|
|
32
|
+
).toBe('http://localhost:45873/callback');
|
|
33
|
+
});
|
|
34
|
+
|
|
11
35
|
it('leaves unrelated integration redirects unchanged', () => {
|
|
12
36
|
expect(
|
|
13
37
|
normalizeCallbackRedirectUriForIntegration('attio', 'http://127.0.0.1:45873/callback')
|
package/src/commands/auth.ts
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
normalizeMicrosoftRedirectUri,
|
|
4
4
|
normalizeMicrosoftRedirectUriForIntegration
|
|
5
5
|
} from '@slates/oauth-microsoft';
|
|
6
|
-
import { SlatesOAuthCredentialRecord, SlatesStoredAuth } from '@slates/profiles';
|
|
6
|
+
import type { SlatesOAuthCredentialRecord, SlatesStoredAuth } from '@slates/profiles';
|
|
7
7
|
import {
|
|
8
8
|
chooseAuthMethod,
|
|
9
9
|
createClientContext,
|
|
@@ -17,16 +17,24 @@ import {
|
|
|
17
17
|
promptForObjectSchema,
|
|
18
18
|
promptForString
|
|
19
19
|
} from '../lib/prompts';
|
|
20
|
-
import { JsonInput, WithProfile } from '../lib/types';
|
|
20
|
+
import type { JsonInput, WithProfile } from '../lib/types';
|
|
21
21
|
|
|
22
22
|
type JsonObject = Record<string, any>;
|
|
23
23
|
let NOTION_INTEGRATION_KEY = 'notion';
|
|
24
24
|
let SALESFORCE_INTEGRATION_KEY = 'salesforce';
|
|
25
|
+
let INTERCOM_INTEGRATION_KEY = 'intercom';
|
|
26
|
+
let TYPEFORM_INTEGRATION_KEY = 'typeform';
|
|
27
|
+
let XERO_INTEGRATION_KEY = 'xero';
|
|
28
|
+
let ZENDESK_INTEGRATION_KEY = 'zendesk';
|
|
25
29
|
let HUBSPOT_INTEGRATION_KEY = 'hubspot';
|
|
26
30
|
let HUBSPOT_DEVELOPER_PLATFORM_OAUTH_METHOD_ID = 'developer_platform_oauth';
|
|
27
31
|
let LOOPBACK_REDIRECT_NORMALIZED_INTEGRATIONS = new Set([
|
|
32
|
+
INTERCOM_INTEGRATION_KEY,
|
|
28
33
|
NOTION_INTEGRATION_KEY,
|
|
29
|
-
SALESFORCE_INTEGRATION_KEY
|
|
34
|
+
SALESFORCE_INTEGRATION_KEY,
|
|
35
|
+
TYPEFORM_INTEGRATION_KEY,
|
|
36
|
+
XERO_INTEGRATION_KEY,
|
|
37
|
+
ZENDESK_INTEGRATION_KEY
|
|
30
38
|
]);
|
|
31
39
|
|
|
32
40
|
type AuthSetupOptions = WithProfile &
|
|
@@ -345,6 +353,7 @@ let runAuthSetup = async (opts: AuthSetupOptions): Promise<SlatesStoredAuth> =>
|
|
|
345
353
|
clientId,
|
|
346
354
|
clientSecret,
|
|
347
355
|
scopes,
|
|
356
|
+
callbackParams: callbackResult.callbackParams,
|
|
348
357
|
callbackState: callbackState ?? undefined
|
|
349
358
|
});
|
|
350
359
|
|
package/src/commands/config.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createClientContext } from '../lib/context';
|
|
2
2
|
import { parseJsonObject, promptForObjectSchema } from '../lib/prompts';
|
|
3
|
-
import { JsonInput, WithProfile } from '../lib/types';
|
|
3
|
+
import type { JsonInput, WithProfile } from '../lib/types';
|
|
4
4
|
|
|
5
5
|
export let getConfig = async (opts: WithProfile) => {
|
|
6
6
|
let { profile } = await createClientContext(opts);
|
package/src/commands/profiles.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { input } from '@inquirer/prompts';
|
|
2
|
-
import { createSlatesClientFromProfile, openSlatesCliStore } from '@slates/profiles';
|
|
2
|
+
import { createSlatesClientFromProfile, type openSlatesCliStore } from '@slates/profiles';
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import { chooseProfile, openIntegrationStore, syncProfileMetadata } from '../lib/context';
|
|
5
|
-
import { WithProfile } from '../lib/types';
|
|
5
|
+
import type { WithProfile } from '../lib/types';
|
|
6
6
|
|
|
7
7
|
let normalizeEntry = (rootDir: string, entry: string) => {
|
|
8
8
|
let absolute = path.isAbsolute(entry) ? entry : path.resolve(process.cwd(), entry);
|
|
@@ -12,7 +12,9 @@ let normalizeEntry = (rootDir: string, entry: string) => {
|
|
|
12
12
|
: absolute;
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
-
let getNextSetupProfileName = async (
|
|
15
|
+
let getNextSetupProfileName = async (
|
|
16
|
+
store: Awaited<ReturnType<typeof openSlatesCliStore>>
|
|
17
|
+
) => {
|
|
16
18
|
let names = new Set(store.listProfiles().map(profile => profile.name));
|
|
17
19
|
if (!names.has('default')) {
|
|
18
20
|
return 'default';
|
|
@@ -41,10 +43,14 @@ let createProfile = async (
|
|
|
41
43
|
|
|
42
44
|
let defaultName =
|
|
43
45
|
opts.name ??
|
|
44
|
-
(opts.initializeConfig
|
|
46
|
+
(opts.initializeConfig
|
|
47
|
+
? await getNextSetupProfileName(store)
|
|
48
|
+
: `profile-${store.listProfiles().length + 1}`);
|
|
45
49
|
let name =
|
|
46
50
|
opts.name ??
|
|
47
|
-
(interactive
|
|
51
|
+
(interactive
|
|
52
|
+
? await input({ message: 'Profile name', default: defaultName })
|
|
53
|
+
: defaultName);
|
|
48
54
|
let defaultEntry = opts.entry ?? integration.entry;
|
|
49
55
|
let entry =
|
|
50
56
|
opts.entry ??
|
|
@@ -56,7 +62,9 @@ let createProfile = async (
|
|
|
56
62
|
: defaultEntry);
|
|
57
63
|
let exportName =
|
|
58
64
|
opts.exportName ??
|
|
59
|
-
(interactive
|
|
65
|
+
(interactive
|
|
66
|
+
? await input({ message: 'Export name (optional)', default: 'provider' })
|
|
67
|
+
: 'provider');
|
|
60
68
|
|
|
61
69
|
let profile = store.upsertProfile({
|
|
62
70
|
name,
|
package/src/commands/repl.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { input } from '@inquirer/prompts';
|
|
2
2
|
import { print } from '../lib/prompts';
|
|
3
|
-
import { WithProfile } from '../lib/types';
|
|
3
|
+
import type { WithProfile } from '../lib/types';
|
|
4
4
|
import { listAuth, setupAuth } from './auth';
|
|
5
5
|
import { getConfig, setConfig } from './config';
|
|
6
6
|
import { getProfile } from './profiles';
|
package/src/commands/test.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { writeFile } from 'fs/promises';
|
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import { chooseProfile } from '../lib/context';
|
|
5
5
|
import { listWorkspaceIntegrations } from '../lib/integration';
|
|
6
|
-
import { WithProfile } from '../lib/types';
|
|
6
|
+
import type { WithProfile } from '../lib/types';
|
|
7
7
|
|
|
8
8
|
let runVitest = async (opts: {
|
|
9
9
|
cwd: string;
|
|
@@ -43,7 +43,7 @@ export let runVitestWithProfile = async (opts: WithProfile & { vitestArgs: strin
|
|
|
43
43
|
|
|
44
44
|
await writeFile(
|
|
45
45
|
contextPath,
|
|
46
|
-
JSON.stringify(
|
|
46
|
+
`${JSON.stringify(
|
|
47
47
|
{
|
|
48
48
|
integration: integration.relativeDir,
|
|
49
49
|
profileId: profile.id,
|
|
@@ -53,7 +53,7 @@ export let runVitestWithProfile = async (opts: WithProfile & { vitestArgs: strin
|
|
|
53
53
|
},
|
|
54
54
|
null,
|
|
55
55
|
2
|
|
56
|
-
)
|
|
56
|
+
)}\n`,
|
|
57
57
|
'utf-8'
|
|
58
58
|
);
|
|
59
59
|
|
package/src/commands/tools.ts
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
syncProfileMetadata
|
|
6
6
|
} from '../lib/context';
|
|
7
7
|
import { parseJsonObject, promptForObjectSchema } from '../lib/prompts';
|
|
8
|
-
import { JsonInput, WithProfile } from '../lib/types';
|
|
8
|
+
import type { JsonInput, WithProfile } from '../lib/types';
|
|
9
9
|
|
|
10
10
|
export let listTools = async (opts: WithProfile) => {
|
|
11
11
|
let { store, profile, client } = await createClientContext(opts);
|
package/src/lib/context.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { select } from '@inquirer/prompts';
|
|
2
|
-
import { SlatesProtocolClient } from '@slates/client';
|
|
2
|
+
import type { SlatesProtocolClient } from '@slates/client';
|
|
3
3
|
import {
|
|
4
4
|
createSlatesClientFromProfile,
|
|
5
5
|
openSlatesCliStore,
|
|
6
|
-
|
|
7
|
-
type
|
|
6
|
+
type SlatesCliStore,
|
|
7
|
+
type SlatesProfileRecord
|
|
8
8
|
} from '@slates/profiles';
|
|
9
9
|
import { resolveIntegration } from './integration';
|
|
10
10
|
import { promptForObjectSchema } from './prompts';
|
|
@@ -26,7 +26,11 @@ describe('resolveIntegration', () => {
|
|
|
26
26
|
JSON.stringify({ main: 'src/index.ts' }, null, 2),
|
|
27
27
|
'utf-8'
|
|
28
28
|
);
|
|
29
|
-
await writeFile(
|
|
29
|
+
await writeFile(
|
|
30
|
+
path.join(integrationDir, 'src', 'index.ts'),
|
|
31
|
+
'export let provider = {};\n',
|
|
32
|
+
'utf-8'
|
|
33
|
+
);
|
|
30
34
|
|
|
31
35
|
let resolved = await resolveIntegration('demo', { cwd });
|
|
32
36
|
|
|
@@ -44,7 +48,11 @@ describe('resolveIntegration', () => {
|
|
|
44
48
|
JSON.stringify({ source: 'src/index.ts' }, null, 2),
|
|
45
49
|
'utf-8'
|
|
46
50
|
);
|
|
47
|
-
await writeFile(
|
|
51
|
+
await writeFile(
|
|
52
|
+
path.join(integrationDir, 'src', 'index.ts'),
|
|
53
|
+
'export let provider = {};\n',
|
|
54
|
+
'utf-8'
|
|
55
|
+
);
|
|
48
56
|
|
|
49
57
|
let resolved = await resolveIntegration('./custom/demo', { cwd });
|
|
50
58
|
|
package/src/lib/integration.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { access, readFile, readdir } from 'fs/promises';
|
|
2
|
-
import path from 'path';
|
|
3
1
|
import { resolveSlatesCliRoot } from '@slates/profiles';
|
|
2
|
+
import { access, readdir, readFile } from 'fs/promises';
|
|
3
|
+
import path from 'path';
|
|
4
4
|
|
|
5
5
|
export interface ResolvedIntegration {
|
|
6
6
|
input: string;
|
|
@@ -142,7 +142,9 @@ export let listWorkspaceIntegrations = async (opts: { cwd?: string } = {}) => {
|
|
|
142
142
|
);
|
|
143
143
|
|
|
144
144
|
integrations.push(
|
|
145
|
-
...chunk.filter(
|
|
145
|
+
...chunk.filter(
|
|
146
|
+
(integration): integration is WorkspaceIntegrationSummary => integration !== null
|
|
147
|
+
)
|
|
146
148
|
);
|
|
147
149
|
}
|
|
148
150
|
|
package/src/lib/oauth.ts
CHANGED
|
@@ -34,7 +34,11 @@ export let createOAuthCallbackListener = async () => {
|
|
|
34
34
|
return new Promise<{
|
|
35
35
|
redirectUri: string;
|
|
36
36
|
state: string;
|
|
37
|
-
wait: () => Promise<{
|
|
37
|
+
wait: () => Promise<{
|
|
38
|
+
code: string;
|
|
39
|
+
state: string;
|
|
40
|
+
callbackParams: Record<string, string>;
|
|
41
|
+
}>;
|
|
38
42
|
}>((resolve, reject) => {
|
|
39
43
|
let expectedState = randomUUID();
|
|
40
44
|
let settled = false;
|
|
@@ -79,7 +83,11 @@ export let createOAuthCallbackListener = async () => {
|
|
|
79
83
|
res.end('Authentication complete. You can close this window.');
|
|
80
84
|
server.close();
|
|
81
85
|
settled = true;
|
|
82
|
-
waiter.resolve({
|
|
86
|
+
waiter.resolve({
|
|
87
|
+
code,
|
|
88
|
+
state,
|
|
89
|
+
callbackParams: Object.fromEntries(url.searchParams.entries())
|
|
90
|
+
});
|
|
83
91
|
} catch (error) {
|
|
84
92
|
server.close();
|
|
85
93
|
settled = true;
|
|
@@ -88,9 +96,17 @@ export let createOAuthCallbackListener = async () => {
|
|
|
88
96
|
});
|
|
89
97
|
|
|
90
98
|
let waiter = (() => {
|
|
91
|
-
let resolvePromise!: (value: {
|
|
99
|
+
let resolvePromise!: (value: {
|
|
100
|
+
code: string;
|
|
101
|
+
state: string;
|
|
102
|
+
callbackParams: Record<string, string>;
|
|
103
|
+
}) => void;
|
|
92
104
|
let rejectPromise!: (error: unknown) => void;
|
|
93
|
-
let promise = new Promise<{
|
|
105
|
+
let promise = new Promise<{
|
|
106
|
+
code: string;
|
|
107
|
+
state: string;
|
|
108
|
+
callbackParams: Record<string, string>;
|
|
109
|
+
}>((resolveFn, rejectFn) => {
|
|
94
110
|
resolvePromise = resolveFn;
|
|
95
111
|
rejectPromise = rejectFn;
|
|
96
112
|
});
|
package/src/lib/prompts.ts
CHANGED