@slates/profiles 1.0.0-rc.4 → 1.0.0-rc.5
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/dist/index.cjs +11 -6
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.module.js +11 -6
- package/package.json +4 -4
- package/src/client.ts +15 -7
- package/src/store.test.ts +111 -0
package/dist/index.cjs
CHANGED
|
@@ -378,20 +378,25 @@ var createSlatesClientFromProfile = async (profile, opts = {}) => {
|
|
|
378
378
|
} : null
|
|
379
379
|
}
|
|
380
380
|
});
|
|
381
|
-
if (firstAuth) {
|
|
381
|
+
if (firstAuth && opts.autoRefresh !== false) {
|
|
382
382
|
attachAutoRefresh(client, profile, firstAuth, opts.store);
|
|
383
383
|
}
|
|
384
384
|
return client;
|
|
385
385
|
};
|
|
386
386
|
var EXPIRY_BUFFER_MS = 60 * 1e3;
|
|
387
|
-
var
|
|
388
|
-
if (auth.authType !== "auth.oauth") return false;
|
|
389
|
-
if (!auth.clientId || !auth.clientSecret) return false;
|
|
390
|
-
if (typeof auth.output?.refreshToken !== "string" || !auth.output.refreshToken) return false;
|
|
387
|
+
var hasExpiredOrExpiringOutput = (auth) => {
|
|
391
388
|
if (typeof auth.output?.expiresAt !== "string" || !auth.output.expiresAt) return false;
|
|
392
389
|
let expiresAt = Date.parse(auth.output.expiresAt);
|
|
393
390
|
return Number.isFinite(expiresAt) && expiresAt <= Date.now() + EXPIRY_BUFFER_MS;
|
|
394
391
|
};
|
|
392
|
+
var shouldRefreshAuth = (auth) => {
|
|
393
|
+
if (!hasExpiredOrExpiringOutput(auth)) return false;
|
|
394
|
+
if (auth.authType === "auth.oauth") {
|
|
395
|
+
if (!auth.clientId || !auth.clientSecret) return false;
|
|
396
|
+
if (typeof auth.output?.refreshToken !== "string" || !auth.output.refreshToken) return false;
|
|
397
|
+
}
|
|
398
|
+
return true;
|
|
399
|
+
};
|
|
395
400
|
var attachAutoRefresh = (client, profile, storedAuth, store) => {
|
|
396
401
|
let baseRequest = client.request.bind(client);
|
|
397
402
|
let inflightRefresh = null;
|
|
@@ -400,7 +405,7 @@ var attachAutoRefresh = (client, profile, storedAuth, store) => {
|
|
|
400
405
|
await inflightRefresh;
|
|
401
406
|
return;
|
|
402
407
|
}
|
|
403
|
-
if (!
|
|
408
|
+
if (!shouldRefreshAuth(storedAuth)) {
|
|
404
409
|
return;
|
|
405
410
|
}
|
|
406
411
|
inflightRefresh = (async () => {
|
package/dist/index.d.cts
CHANGED
|
@@ -120,6 +120,7 @@ declare let openSlatesCliStore: (opts?: {
|
|
|
120
120
|
declare let createSlatesClientFromProfile: (profile: SlatesProfileRecord, opts?: {
|
|
121
121
|
cwd?: string;
|
|
122
122
|
store?: SlatesCliStore;
|
|
123
|
+
autoRefresh?: boolean;
|
|
123
124
|
}) => Promise<_slates_client.SlatesProtocolClient>;
|
|
124
125
|
|
|
125
126
|
export { SlatesCliStore, type SlatesCliStoreData, type SlatesCliStoreScope, type SlatesLocalProfileTarget, type SlatesOAuthCredentialRecord, type SlatesProfileRecord, type SlatesProfileTarget, type SlatesStoredAuth, createSlatesClientFromProfile, openSlatesCliStore, resolveSlatesCliDir, resolveSlatesCliProfilesDir, resolveSlatesCliRoot };
|
package/dist/index.d.ts
CHANGED
|
@@ -120,6 +120,7 @@ declare let openSlatesCliStore: (opts?: {
|
|
|
120
120
|
declare let createSlatesClientFromProfile: (profile: SlatesProfileRecord, opts?: {
|
|
121
121
|
cwd?: string;
|
|
122
122
|
store?: SlatesCliStore;
|
|
123
|
+
autoRefresh?: boolean;
|
|
123
124
|
}) => Promise<_slates_client.SlatesProtocolClient>;
|
|
124
125
|
|
|
125
126
|
export { SlatesCliStore, type SlatesCliStoreData, type SlatesCliStoreScope, type SlatesLocalProfileTarget, type SlatesOAuthCredentialRecord, type SlatesProfileRecord, type SlatesProfileTarget, type SlatesStoredAuth, createSlatesClientFromProfile, openSlatesCliStore, resolveSlatesCliDir, resolveSlatesCliProfilesDir, resolveSlatesCliRoot };
|
package/dist/index.module.js
CHANGED
|
@@ -337,20 +337,25 @@ var createSlatesClientFromProfile = async (profile, opts = {}) => {
|
|
|
337
337
|
} : null
|
|
338
338
|
}
|
|
339
339
|
});
|
|
340
|
-
if (firstAuth) {
|
|
340
|
+
if (firstAuth && opts.autoRefresh !== false) {
|
|
341
341
|
attachAutoRefresh(client, profile, firstAuth, opts.store);
|
|
342
342
|
}
|
|
343
343
|
return client;
|
|
344
344
|
};
|
|
345
345
|
var EXPIRY_BUFFER_MS = 60 * 1e3;
|
|
346
|
-
var
|
|
347
|
-
if (auth.authType !== "auth.oauth") return false;
|
|
348
|
-
if (!auth.clientId || !auth.clientSecret) return false;
|
|
349
|
-
if (typeof auth.output?.refreshToken !== "string" || !auth.output.refreshToken) return false;
|
|
346
|
+
var hasExpiredOrExpiringOutput = (auth) => {
|
|
350
347
|
if (typeof auth.output?.expiresAt !== "string" || !auth.output.expiresAt) return false;
|
|
351
348
|
let expiresAt = Date.parse(auth.output.expiresAt);
|
|
352
349
|
return Number.isFinite(expiresAt) && expiresAt <= Date.now() + EXPIRY_BUFFER_MS;
|
|
353
350
|
};
|
|
351
|
+
var shouldRefreshAuth = (auth) => {
|
|
352
|
+
if (!hasExpiredOrExpiringOutput(auth)) return false;
|
|
353
|
+
if (auth.authType === "auth.oauth") {
|
|
354
|
+
if (!auth.clientId || !auth.clientSecret) return false;
|
|
355
|
+
if (typeof auth.output?.refreshToken !== "string" || !auth.output.refreshToken) return false;
|
|
356
|
+
}
|
|
357
|
+
return true;
|
|
358
|
+
};
|
|
354
359
|
var attachAutoRefresh = (client, profile, storedAuth, store) => {
|
|
355
360
|
let baseRequest = client.request.bind(client);
|
|
356
361
|
let inflightRefresh = null;
|
|
@@ -359,7 +364,7 @@ var attachAutoRefresh = (client, profile, storedAuth, store) => {
|
|
|
359
364
|
await inflightRefresh;
|
|
360
365
|
return;
|
|
361
366
|
}
|
|
362
|
-
if (!
|
|
367
|
+
if (!shouldRefreshAuth(storedAuth)) {
|
|
363
368
|
return;
|
|
364
369
|
}
|
|
365
370
|
inflightRefresh = (async () => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@slates/profiles",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.5",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -31,11 +31,11 @@
|
|
|
31
31
|
"typecheck": "tsc --noEmit"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@slates/client": "1.0.0-rc.
|
|
35
|
-
"@slates/proto": "1.0.0-rc.
|
|
34
|
+
"@slates/client": "1.0.0-rc.7",
|
|
35
|
+
"@slates/proto": "1.0.0-rc.9"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@slates/provider": "1.0.0-rc.
|
|
38
|
+
"@slates/provider": "1.0.0-rc.11",
|
|
39
39
|
"@slates/tsconfig": "1.0.0-rc.1",
|
|
40
40
|
"typescript": "5.8.2",
|
|
41
41
|
"vitest": "^3.1.2",
|
package/src/client.ts
CHANGED
|
@@ -43,7 +43,7 @@ let loadSlateFromProfile = async (
|
|
|
43
43
|
|
|
44
44
|
export let createSlatesClientFromProfile = async (
|
|
45
45
|
profile: SlatesProfileRecord,
|
|
46
|
-
opts: { cwd?: string; store?: SlatesCliStore } = {}
|
|
46
|
+
opts: { cwd?: string; store?: SlatesCliStore; autoRefresh?: boolean } = {}
|
|
47
47
|
) => {
|
|
48
48
|
let firstAuth = Object.values(profile.auth)[0];
|
|
49
49
|
let slate = await loadSlateFromProfile(profile, opts);
|
|
@@ -61,7 +61,7 @@ export let createSlatesClientFromProfile = async (
|
|
|
61
61
|
}
|
|
62
62
|
});
|
|
63
63
|
|
|
64
|
-
if (firstAuth) {
|
|
64
|
+
if (firstAuth && opts.autoRefresh !== false) {
|
|
65
65
|
attachAutoRefresh(client, profile, firstAuth, opts.store);
|
|
66
66
|
}
|
|
67
67
|
|
|
@@ -70,16 +70,24 @@ export let createSlatesClientFromProfile = async (
|
|
|
70
70
|
|
|
71
71
|
let EXPIRY_BUFFER_MS = 60 * 1000;
|
|
72
72
|
|
|
73
|
-
let
|
|
74
|
-
if (auth.authType !== 'auth.oauth') return false;
|
|
75
|
-
if (!auth.clientId || !auth.clientSecret) return false;
|
|
76
|
-
if (typeof auth.output?.refreshToken !== 'string' || !auth.output.refreshToken) return false;
|
|
73
|
+
let hasExpiredOrExpiringOutput = (auth: SlatesStoredAuth) => {
|
|
77
74
|
if (typeof auth.output?.expiresAt !== 'string' || !auth.output.expiresAt) return false;
|
|
78
75
|
|
|
79
76
|
let expiresAt = Date.parse(auth.output.expiresAt);
|
|
80
77
|
return Number.isFinite(expiresAt) && expiresAt <= Date.now() + EXPIRY_BUFFER_MS;
|
|
81
78
|
};
|
|
82
79
|
|
|
80
|
+
let shouldRefreshAuth = (auth: SlatesStoredAuth) => {
|
|
81
|
+
if (!hasExpiredOrExpiringOutput(auth)) return false;
|
|
82
|
+
|
|
83
|
+
if (auth.authType === 'auth.oauth') {
|
|
84
|
+
if (!auth.clientId || !auth.clientSecret) return false;
|
|
85
|
+
if (typeof auth.output?.refreshToken !== 'string' || !auth.output.refreshToken) return false;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return true;
|
|
89
|
+
};
|
|
90
|
+
|
|
83
91
|
let attachAutoRefresh = (
|
|
84
92
|
client: ReturnType<typeof createSlatesClient>,
|
|
85
93
|
profile: SlatesProfileRecord,
|
|
@@ -95,7 +103,7 @@ let attachAutoRefresh = (
|
|
|
95
103
|
return;
|
|
96
104
|
}
|
|
97
105
|
|
|
98
|
-
if (!
|
|
106
|
+
if (!shouldRefreshAuth(storedAuth)) {
|
|
99
107
|
return;
|
|
100
108
|
}
|
|
101
109
|
|
package/src/store.test.ts
CHANGED
|
@@ -413,4 +413,115 @@ export let provider = Slate.create({
|
|
|
413
413
|
token: 'expired-token-refreshed'
|
|
414
414
|
});
|
|
415
415
|
});
|
|
416
|
+
|
|
417
|
+
it('refreshes expired custom auth automatically in the profile-backed client', async () => {
|
|
418
|
+
let cwd = await createTempDir();
|
|
419
|
+
let entry = path.join(cwd, 'custom-slate.mjs');
|
|
420
|
+
await writeFile(
|
|
421
|
+
entry,
|
|
422
|
+
`
|
|
423
|
+
import { Slate, SlateAuth, SlateConfig, SlateSpecification, SlateTool } from '@slates/provider';
|
|
424
|
+
import { z } from 'zod';
|
|
425
|
+
|
|
426
|
+
let config = SlateConfig.create(z.object({})).getDefaultConfig(() => ({}));
|
|
427
|
+
let auth = SlateAuth.create()
|
|
428
|
+
.output(
|
|
429
|
+
z.object({
|
|
430
|
+
token: z.string(),
|
|
431
|
+
expiresAt: z.string().optional()
|
|
432
|
+
})
|
|
433
|
+
)
|
|
434
|
+
.addCustomAuth({
|
|
435
|
+
type: 'auth.custom',
|
|
436
|
+
key: 'custom',
|
|
437
|
+
name: 'Custom',
|
|
438
|
+
inputSchema: z.object({
|
|
439
|
+
tokenPrefix: z.string()
|
|
440
|
+
}),
|
|
441
|
+
getOutput: async ctx => ({
|
|
442
|
+
output: {
|
|
443
|
+
token: \`\${ctx.input.tokenPrefix}-initial\`,
|
|
444
|
+
expiresAt: new Date(Date.now() + 60 * 60 * 1000).toISOString()
|
|
445
|
+
}
|
|
446
|
+
}),
|
|
447
|
+
handleTokenRefresh: async ctx => ({
|
|
448
|
+
output: {
|
|
449
|
+
token: \`\${ctx.input.tokenPrefix}-refreshed\`,
|
|
450
|
+
expiresAt: new Date(Date.now() + 60 * 60 * 1000).toISOString()
|
|
451
|
+
}
|
|
452
|
+
})
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
let spec = SlateSpecification.create({
|
|
456
|
+
key: 'custom-demo',
|
|
457
|
+
name: 'Custom Demo',
|
|
458
|
+
description: 'Custom auth test slate',
|
|
459
|
+
config,
|
|
460
|
+
auth
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
let tool = SlateTool.create(spec, {
|
|
464
|
+
key: 'whoami',
|
|
465
|
+
name: 'Who Am I'
|
|
466
|
+
})
|
|
467
|
+
.input(z.object({}))
|
|
468
|
+
.output(
|
|
469
|
+
z.object({
|
|
470
|
+
token: z.string()
|
|
471
|
+
})
|
|
472
|
+
)
|
|
473
|
+
.handleInvocation(async ctx => ({
|
|
474
|
+
output: {
|
|
475
|
+
token: ctx.auth.token
|
|
476
|
+
}
|
|
477
|
+
}))
|
|
478
|
+
.build();
|
|
479
|
+
|
|
480
|
+
export let provider = Slate.create({
|
|
481
|
+
spec,
|
|
482
|
+
tools: [tool],
|
|
483
|
+
triggers: []
|
|
484
|
+
});
|
|
485
|
+
`,
|
|
486
|
+
'utf-8'
|
|
487
|
+
);
|
|
488
|
+
|
|
489
|
+
let store = await SlatesCliStore.open({
|
|
490
|
+
cwd,
|
|
491
|
+
scope: {
|
|
492
|
+
key: 'integrations/demo',
|
|
493
|
+
name: 'demo'
|
|
494
|
+
}
|
|
495
|
+
});
|
|
496
|
+
let profile = store.upsertProfile({
|
|
497
|
+
name: 'Demo',
|
|
498
|
+
target: {
|
|
499
|
+
type: 'local',
|
|
500
|
+
entry: './custom-slate.mjs',
|
|
501
|
+
exportName: 'provider'
|
|
502
|
+
}
|
|
503
|
+
});
|
|
504
|
+
store.setProfileConfig(profile.id, {});
|
|
505
|
+
store.upsertAuth(profile.id, {
|
|
506
|
+
authMethodId: 'custom',
|
|
507
|
+
authType: 'auth.custom',
|
|
508
|
+
input: {
|
|
509
|
+
tokenPrefix: 'custom-token'
|
|
510
|
+
},
|
|
511
|
+
output: {
|
|
512
|
+
token: 'expired-token',
|
|
513
|
+
expiresAt: new Date(Date.now() - 60 * 1000).toISOString()
|
|
514
|
+
},
|
|
515
|
+
scopes: []
|
|
516
|
+
});
|
|
517
|
+
await store.save();
|
|
518
|
+
|
|
519
|
+
let client = await createSlatesClientFromProfile(profile, { cwd, store });
|
|
520
|
+
let result = await client.invokeTool('whoami', {});
|
|
521
|
+
|
|
522
|
+
expect(result.output).toEqual({ token: 'custom-token-refreshed' });
|
|
523
|
+
expect(store.getAuth(profile.id, 'custom')?.output).toMatchObject({
|
|
524
|
+
token: 'custom-token-refreshed'
|
|
525
|
+
});
|
|
526
|
+
});
|
|
416
527
|
});
|