@slates/profiles 1.0.0-rc.2 → 1.0.0-rc.21

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 CHANGED
@@ -82,11 +82,13 @@ var resolveSlatesCliRoot = (cwd = process.cwd()) => {
82
82
  return cwd;
83
83
  }
84
84
  };
85
- var resolveSlatesCliDir = (cwd = process.cwd()) => import_path.default.join(resolveSlatesCliRoot(cwd), CLI_DIR_NAME);
86
- var resolveSlatesCliProfilesDir = (cwd = process.cwd()) => import_path.default.join(resolveSlatesCliDir(cwd), PROFILES_DIR_NAME);
85
+ var resolveSlatesCliDirFromRoot = (rootDir) => import_path.default.join(rootDir, CLI_DIR_NAME);
86
+ var resolveSlatesCliProfilesDirFromRoot = (rootDir) => import_path.default.join(resolveSlatesCliDirFromRoot(rootDir), PROFILES_DIR_NAME);
87
+ var resolveSlatesCliDir = (cwd = process.cwd()) => resolveSlatesCliDirFromRoot(resolveSlatesCliRoot(cwd));
88
+ var resolveSlatesCliProfilesDir = (cwd = process.cwd()) => resolveSlatesCliProfilesDirFromRoot(resolveSlatesCliRoot(cwd));
87
89
  var normalizeScopeKey = (scopeKey) => import_path.default.posix.normalize(scopeKey.replace(/\\/g, "/")).replace(/^\.?\//, "");
88
90
  var splitScopeKey = (scopeKey) => normalizeScopeKey(scopeKey).split("/").filter(Boolean).filter((segment) => segment !== "." && segment !== "..");
89
- var resolveScopedStoreDir = (rootDir, scopeKey) => import_path.default.join(resolveSlatesCliProfilesDir(rootDir), ...splitScopeKey(scopeKey));
91
+ var resolveScopedStoreDir = (rootDir, scopeKey) => import_path.default.join(resolveSlatesCliProfilesDirFromRoot(rootDir), ...splitScopeKey(scopeKey));
90
92
  var resolveScopedStorePath = (rootDir, scopeKey) => import_path.default.join(resolveScopedStoreDir(rootDir, scopeKey), STORE_FILE_NAME);
91
93
  var inferRootDirFromStorePath = (storePath) => {
92
94
  let normalized = import_path.default.resolve(storePath);
@@ -99,7 +101,7 @@ var inferRootDirFromStorePath = (storePath) => {
99
101
  return import_path.default.join(import_path.default.sep, ...rootParts);
100
102
  };
101
103
  var resolveScopeKeyFromStorePath = (rootDir, storePath) => {
102
- let profilesDir = resolveSlatesCliProfilesDir(rootDir);
104
+ let profilesDir = resolveSlatesCliProfilesDirFromRoot(rootDir);
103
105
  let relativeDir = import_path.default.relative(profilesDir, import_path.default.dirname(storePath));
104
106
  if (!relativeDir || relativeDir.startsWith("..") || import_path.default.isAbsolute(relativeDir)) {
105
107
  return null;
@@ -130,7 +132,7 @@ var isProfileInScope = (rootDir, scopeKey, profile) => {
130
132
  return relative !== "" && !relative.startsWith("..") && !import_path.default.isAbsolute(relative);
131
133
  };
132
134
  var loadMigratedLegacyStore = async (rootDir, scopeKey) => {
133
- let legacyStorePath = import_path.default.join(resolveSlatesCliDir(rootDir), STORE_FILE_NAME);
135
+ let legacyStorePath = import_path.default.join(resolveSlatesCliDirFromRoot(rootDir), STORE_FILE_NAME);
134
136
  let legacy = await readStoreData(legacyStorePath);
135
137
  if (!legacy) {
136
138
  return createEmptyStore();
@@ -149,22 +151,25 @@ var loadMigratedLegacyStore = async (rootDir, scopeKey) => {
149
151
  };
150
152
  };
151
153
  var SlatesCliStore = class _SlatesCliStore {
152
- constructor(rootDir, dirPath, storePath, scope, data) {
154
+ constructor(rootDir, cliDir, dirPath, storePath, scope, data) {
153
155
  this.rootDir = rootDir;
156
+ this.cliDir = cliDir;
154
157
  this.dirPath = dirPath;
155
158
  this.storePath = storePath;
156
159
  this.scope = scope;
157
160
  this.data = data;
158
161
  }
159
162
  rootDir;
163
+ cliDir;
160
164
  dirPath;
161
165
  storePath;
162
166
  scope;
163
167
  data;
164
168
  static async open(opts = {}) {
165
- let rootDir = opts.storePath ? inferRootDirFromStorePath(opts.storePath) : resolveSlatesCliRoot(opts.cwd);
166
- let cliDir = resolveSlatesCliDir(rootDir);
167
- let scopeKey = opts.storePath ? resolveScopeKeyFromStorePath(rootDir, opts.storePath) : opts.scope?.key ? normalizeScopeKey(opts.scope.key) : null;
169
+ let storageRootDir = opts.storePath ? inferRootDirFromStorePath(opts.storePath) : resolveSlatesCliRoot(opts.cwd);
170
+ let rootDir = opts.rootDir ?? storageRootDir;
171
+ let cliDir = resolveSlatesCliDirFromRoot(storageRootDir);
172
+ let scopeKey = opts.storePath ? resolveScopeKeyFromStorePath(storageRootDir, opts.storePath) : opts.scope?.key ? normalizeScopeKey(opts.scope.key) : null;
168
173
  let dirPath = opts.storePath ? import_path.default.dirname(opts.storePath) : scopeKey ? resolveScopedStoreDir(rootDir, scopeKey) : cliDir;
169
174
  let storePath = opts.storePath ?? (scopeKey ? resolveScopedStorePath(rootDir, scopeKey) : import_path.default.join(cliDir, STORE_FILE_NAME));
170
175
  await ensureDir(cliDir);
@@ -176,12 +181,14 @@ var SlatesCliStore = class _SlatesCliStore {
176
181
  currentProfileId: parsed.currentProfileId ?? null,
177
182
  profiles: parsed.profiles ?? {},
178
183
  oauthCredentials: parsed.oauthCredentials ?? {}
179
- } : scopeKey ? await loadMigratedLegacyStore(rootDir, scopeKey) : createEmptyStore();
184
+ } : opts.storePath ? createEmptyStore() : scopeKey ? await loadMigratedLegacyStore(rootDir, scopeKey) : createEmptyStore();
180
185
  if (!parsed) {
181
- await (0, import_promises.writeFile)(storePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
186
+ await (0, import_promises.writeFile)(storePath, `${JSON.stringify(data, null, 2)}
187
+ `, "utf-8");
182
188
  }
183
189
  return new _SlatesCliStore(
184
190
  rootDir,
191
+ cliDir,
185
192
  dirPath,
186
193
  storePath,
187
194
  scopeKey ? { key: scopeKey, name: opts.scope?.name } : null,
@@ -190,9 +197,10 @@ var SlatesCliStore = class _SlatesCliStore {
190
197
  }
191
198
  async save() {
192
199
  await ensureDir(this.dirPath);
193
- await ensureDir(resolveSlatesCliDir(this.rootDir));
194
- await ensureGitIgnore(resolveSlatesCliDir(this.rootDir));
195
- await (0, import_promises.writeFile)(this.storePath, JSON.stringify(this.data, null, 2) + "\n", "utf-8");
200
+ await ensureDir(this.cliDir);
201
+ await ensureGitIgnore(this.cliDir);
202
+ await (0, import_promises.writeFile)(this.storePath, `${JSON.stringify(this.data, null, 2)}
203
+ `, "utf-8");
196
204
  }
197
205
  listProfiles() {
198
206
  return Object.values(this.data.profiles).sort((a, b) => a.name.localeCompare(b.name));
@@ -336,15 +344,18 @@ var SlatesCliStore = class _SlatesCliStore {
336
344
  var openSlatesCliStore = async (opts = {}) => SlatesCliStore.open(opts);
337
345
 
338
346
  // src/client.ts
339
- var resolveEntryPath = (entry, cwd) => {
347
+ var resolveEntryPath = (entry, opts = {}) => {
340
348
  if (import_path2.default.isAbsolute(entry)) return entry;
341
- return import_path2.default.resolve(resolveSlatesCliRoot(cwd), entry);
349
+ return import_path2.default.resolve(opts.rootDir ?? resolveSlatesCliRoot(opts.cwd), entry);
342
350
  };
343
- var loadSlateFromProfile = async (profile, cwd) => {
351
+ var loadSlateFromProfile = async (profile, opts = {}) => {
344
352
  if (profile.target.type !== "local") {
345
353
  throw new Error(`Unsupported profile target type: ${profile.target.type}`);
346
354
  }
347
- let modulePath = resolveEntryPath(profile.target.entry, cwd);
355
+ let modulePath = resolveEntryPath(profile.target.entry, {
356
+ cwd: opts.cwd,
357
+ rootDir: opts.store?.rootDir
358
+ });
348
359
  let loaded = await import((0, import_url.pathToFileURL)(modulePath).href);
349
360
  let exportName = profile.target.exportName;
350
361
  let slate = (exportName ? loaded[exportName] : void 0) ?? loaded.provider ?? loaded.slate ?? loaded.default;
@@ -357,7 +368,7 @@ var loadSlateFromProfile = async (profile, cwd) => {
357
368
  };
358
369
  var createSlatesClientFromProfile = async (profile, opts = {}) => {
359
370
  let firstAuth = Object.values(profile.auth)[0];
360
- let slate = await loadSlateFromProfile(profile, opts.cwd);
371
+ let slate = await loadSlateFromProfile(profile, opts);
361
372
  let client = (0, import_client.createSlatesClient)({
362
373
  transport: (0, import_client.createLocalSlateTransport)({ slate }),
363
374
  state: {
@@ -369,20 +380,26 @@ var createSlatesClientFromProfile = async (profile, opts = {}) => {
369
380
  } : null
370
381
  }
371
382
  });
372
- if (firstAuth) {
383
+ if (firstAuth && opts.autoRefresh !== false) {
373
384
  attachAutoRefresh(client, profile, firstAuth, opts.store);
374
385
  }
375
386
  return client;
376
387
  };
377
388
  var EXPIRY_BUFFER_MS = 60 * 1e3;
378
- var shouldRefreshOAuthAuth = (auth) => {
379
- if (auth.authType !== "auth.oauth") return false;
380
- if (!auth.clientId || !auth.clientSecret) return false;
381
- if (typeof auth.output?.refreshToken !== "string" || !auth.output.refreshToken) return false;
389
+ var hasExpiredOrExpiringOutput = (auth) => {
382
390
  if (typeof auth.output?.expiresAt !== "string" || !auth.output.expiresAt) return false;
383
391
  let expiresAt = Date.parse(auth.output.expiresAt);
384
392
  return Number.isFinite(expiresAt) && expiresAt <= Date.now() + EXPIRY_BUFFER_MS;
385
393
  };
394
+ var shouldRefreshAuth = (auth) => {
395
+ if (!hasExpiredOrExpiringOutput(auth)) return false;
396
+ if (auth.authType === "auth.oauth") {
397
+ if (!auth.clientId || !auth.clientSecret) return false;
398
+ if (typeof auth.output?.refreshToken !== "string" || !auth.output.refreshToken)
399
+ return false;
400
+ }
401
+ return true;
402
+ };
386
403
  var attachAutoRefresh = (client, profile, storedAuth, store) => {
387
404
  let baseRequest = client.request.bind(client);
388
405
  let inflightRefresh = null;
@@ -391,7 +408,7 @@ var attachAutoRefresh = (client, profile, storedAuth, store) => {
391
408
  await inflightRefresh;
392
409
  return;
393
410
  }
394
- if (!shouldRefreshOAuthAuth(storedAuth)) {
411
+ if (!shouldRefreshAuth(storedAuth)) {
395
412
  return;
396
413
  }
397
414
  inflightRefresh = (async () => {
package/dist/index.d.cts CHANGED
@@ -66,13 +66,15 @@ declare let resolveSlatesCliDir: (cwd?: string) => string;
66
66
  declare let resolveSlatesCliProfilesDir: (cwd?: string) => string;
67
67
  declare class SlatesCliStore {
68
68
  readonly rootDir: string;
69
+ readonly cliDir: string;
69
70
  readonly dirPath: string;
70
71
  readonly storePath: string;
71
72
  readonly scope: SlatesCliStoreScope | null;
72
73
  readonly data: SlatesCliStoreData;
73
- constructor(rootDir: string, dirPath: string, storePath: string, scope: SlatesCliStoreScope | null, data: SlatesCliStoreData);
74
+ constructor(rootDir: string, cliDir: string, dirPath: string, storePath: string, scope: SlatesCliStoreScope | null, data: SlatesCliStoreData);
74
75
  static open(opts?: {
75
76
  cwd?: string;
77
+ rootDir?: string;
76
78
  scope?: SlatesCliStoreScope;
77
79
  storePath?: string;
78
80
  }): Promise<SlatesCliStore>;
@@ -110,6 +112,7 @@ declare class SlatesCliStore {
110
112
  }
111
113
  declare let openSlatesCliStore: (opts?: {
112
114
  cwd?: string;
115
+ rootDir?: string;
113
116
  scope?: SlatesCliStoreScope;
114
117
  storePath?: string;
115
118
  }) => Promise<SlatesCliStore>;
@@ -117,6 +120,7 @@ declare let openSlatesCliStore: (opts?: {
117
120
  declare let createSlatesClientFromProfile: (profile: SlatesProfileRecord, opts?: {
118
121
  cwd?: string;
119
122
  store?: SlatesCliStore;
123
+ autoRefresh?: boolean;
120
124
  }) => Promise<_slates_client.SlatesProtocolClient>;
121
125
 
122
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
@@ -66,13 +66,15 @@ declare let resolveSlatesCliDir: (cwd?: string) => string;
66
66
  declare let resolveSlatesCliProfilesDir: (cwd?: string) => string;
67
67
  declare class SlatesCliStore {
68
68
  readonly rootDir: string;
69
+ readonly cliDir: string;
69
70
  readonly dirPath: string;
70
71
  readonly storePath: string;
71
72
  readonly scope: SlatesCliStoreScope | null;
72
73
  readonly data: SlatesCliStoreData;
73
- constructor(rootDir: string, dirPath: string, storePath: string, scope: SlatesCliStoreScope | null, data: SlatesCliStoreData);
74
+ constructor(rootDir: string, cliDir: string, dirPath: string, storePath: string, scope: SlatesCliStoreScope | null, data: SlatesCliStoreData);
74
75
  static open(opts?: {
75
76
  cwd?: string;
77
+ rootDir?: string;
76
78
  scope?: SlatesCliStoreScope;
77
79
  storePath?: string;
78
80
  }): Promise<SlatesCliStore>;
@@ -110,6 +112,7 @@ declare class SlatesCliStore {
110
112
  }
111
113
  declare let openSlatesCliStore: (opts?: {
112
114
  cwd?: string;
115
+ rootDir?: string;
113
116
  scope?: SlatesCliStoreScope;
114
117
  storePath?: string;
115
118
  }) => Promise<SlatesCliStore>;
@@ -117,6 +120,7 @@ declare let openSlatesCliStore: (opts?: {
117
120
  declare let createSlatesClientFromProfile: (profile: SlatesProfileRecord, opts?: {
118
121
  cwd?: string;
119
122
  store?: SlatesCliStore;
123
+ autoRefresh?: boolean;
120
124
  }) => Promise<_slates_client.SlatesProtocolClient>;
121
125
 
122
126
  export { SlatesCliStore, type SlatesCliStoreData, type SlatesCliStoreScope, type SlatesLocalProfileTarget, type SlatesOAuthCredentialRecord, type SlatesProfileRecord, type SlatesProfileTarget, type SlatesStoredAuth, createSlatesClientFromProfile, openSlatesCliStore, resolveSlatesCliDir, resolveSlatesCliProfilesDir, resolveSlatesCliRoot };
@@ -41,11 +41,13 @@ var resolveSlatesCliRoot = (cwd = process.cwd()) => {
41
41
  return cwd;
42
42
  }
43
43
  };
44
- var resolveSlatesCliDir = (cwd = process.cwd()) => path.join(resolveSlatesCliRoot(cwd), CLI_DIR_NAME);
45
- var resolveSlatesCliProfilesDir = (cwd = process.cwd()) => path.join(resolveSlatesCliDir(cwd), PROFILES_DIR_NAME);
44
+ var resolveSlatesCliDirFromRoot = (rootDir) => path.join(rootDir, CLI_DIR_NAME);
45
+ var resolveSlatesCliProfilesDirFromRoot = (rootDir) => path.join(resolveSlatesCliDirFromRoot(rootDir), PROFILES_DIR_NAME);
46
+ var resolveSlatesCliDir = (cwd = process.cwd()) => resolveSlatesCliDirFromRoot(resolveSlatesCliRoot(cwd));
47
+ var resolveSlatesCliProfilesDir = (cwd = process.cwd()) => resolveSlatesCliProfilesDirFromRoot(resolveSlatesCliRoot(cwd));
46
48
  var normalizeScopeKey = (scopeKey) => path.posix.normalize(scopeKey.replace(/\\/g, "/")).replace(/^\.?\//, "");
47
49
  var splitScopeKey = (scopeKey) => normalizeScopeKey(scopeKey).split("/").filter(Boolean).filter((segment) => segment !== "." && segment !== "..");
48
- var resolveScopedStoreDir = (rootDir, scopeKey) => path.join(resolveSlatesCliProfilesDir(rootDir), ...splitScopeKey(scopeKey));
50
+ var resolveScopedStoreDir = (rootDir, scopeKey) => path.join(resolveSlatesCliProfilesDirFromRoot(rootDir), ...splitScopeKey(scopeKey));
49
51
  var resolveScopedStorePath = (rootDir, scopeKey) => path.join(resolveScopedStoreDir(rootDir, scopeKey), STORE_FILE_NAME);
50
52
  var inferRootDirFromStorePath = (storePath) => {
51
53
  let normalized = path.resolve(storePath);
@@ -58,7 +60,7 @@ var inferRootDirFromStorePath = (storePath) => {
58
60
  return path.join(path.sep, ...rootParts);
59
61
  };
60
62
  var resolveScopeKeyFromStorePath = (rootDir, storePath) => {
61
- let profilesDir = resolveSlatesCliProfilesDir(rootDir);
63
+ let profilesDir = resolveSlatesCliProfilesDirFromRoot(rootDir);
62
64
  let relativeDir = path.relative(profilesDir, path.dirname(storePath));
63
65
  if (!relativeDir || relativeDir.startsWith("..") || path.isAbsolute(relativeDir)) {
64
66
  return null;
@@ -89,7 +91,7 @@ var isProfileInScope = (rootDir, scopeKey, profile) => {
89
91
  return relative !== "" && !relative.startsWith("..") && !path.isAbsolute(relative);
90
92
  };
91
93
  var loadMigratedLegacyStore = async (rootDir, scopeKey) => {
92
- let legacyStorePath = path.join(resolveSlatesCliDir(rootDir), STORE_FILE_NAME);
94
+ let legacyStorePath = path.join(resolveSlatesCliDirFromRoot(rootDir), STORE_FILE_NAME);
93
95
  let legacy = await readStoreData(legacyStorePath);
94
96
  if (!legacy) {
95
97
  return createEmptyStore();
@@ -108,22 +110,25 @@ var loadMigratedLegacyStore = async (rootDir, scopeKey) => {
108
110
  };
109
111
  };
110
112
  var SlatesCliStore = class _SlatesCliStore {
111
- constructor(rootDir, dirPath, storePath, scope, data) {
113
+ constructor(rootDir, cliDir, dirPath, storePath, scope, data) {
112
114
  this.rootDir = rootDir;
115
+ this.cliDir = cliDir;
113
116
  this.dirPath = dirPath;
114
117
  this.storePath = storePath;
115
118
  this.scope = scope;
116
119
  this.data = data;
117
120
  }
118
121
  rootDir;
122
+ cliDir;
119
123
  dirPath;
120
124
  storePath;
121
125
  scope;
122
126
  data;
123
127
  static async open(opts = {}) {
124
- let rootDir = opts.storePath ? inferRootDirFromStorePath(opts.storePath) : resolveSlatesCliRoot(opts.cwd);
125
- let cliDir = resolveSlatesCliDir(rootDir);
126
- let scopeKey = opts.storePath ? resolveScopeKeyFromStorePath(rootDir, opts.storePath) : opts.scope?.key ? normalizeScopeKey(opts.scope.key) : null;
128
+ let storageRootDir = opts.storePath ? inferRootDirFromStorePath(opts.storePath) : resolveSlatesCliRoot(opts.cwd);
129
+ let rootDir = opts.rootDir ?? storageRootDir;
130
+ let cliDir = resolveSlatesCliDirFromRoot(storageRootDir);
131
+ let scopeKey = opts.storePath ? resolveScopeKeyFromStorePath(storageRootDir, opts.storePath) : opts.scope?.key ? normalizeScopeKey(opts.scope.key) : null;
127
132
  let dirPath = opts.storePath ? path.dirname(opts.storePath) : scopeKey ? resolveScopedStoreDir(rootDir, scopeKey) : cliDir;
128
133
  let storePath = opts.storePath ?? (scopeKey ? resolveScopedStorePath(rootDir, scopeKey) : path.join(cliDir, STORE_FILE_NAME));
129
134
  await ensureDir(cliDir);
@@ -135,12 +140,14 @@ var SlatesCliStore = class _SlatesCliStore {
135
140
  currentProfileId: parsed.currentProfileId ?? null,
136
141
  profiles: parsed.profiles ?? {},
137
142
  oauthCredentials: parsed.oauthCredentials ?? {}
138
- } : scopeKey ? await loadMigratedLegacyStore(rootDir, scopeKey) : createEmptyStore();
143
+ } : opts.storePath ? createEmptyStore() : scopeKey ? await loadMigratedLegacyStore(rootDir, scopeKey) : createEmptyStore();
139
144
  if (!parsed) {
140
- await writeFile(storePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
145
+ await writeFile(storePath, `${JSON.stringify(data, null, 2)}
146
+ `, "utf-8");
141
147
  }
142
148
  return new _SlatesCliStore(
143
149
  rootDir,
150
+ cliDir,
144
151
  dirPath,
145
152
  storePath,
146
153
  scopeKey ? { key: scopeKey, name: opts.scope?.name } : null,
@@ -149,9 +156,10 @@ var SlatesCliStore = class _SlatesCliStore {
149
156
  }
150
157
  async save() {
151
158
  await ensureDir(this.dirPath);
152
- await ensureDir(resolveSlatesCliDir(this.rootDir));
153
- await ensureGitIgnore(resolveSlatesCliDir(this.rootDir));
154
- await writeFile(this.storePath, JSON.stringify(this.data, null, 2) + "\n", "utf-8");
159
+ await ensureDir(this.cliDir);
160
+ await ensureGitIgnore(this.cliDir);
161
+ await writeFile(this.storePath, `${JSON.stringify(this.data, null, 2)}
162
+ `, "utf-8");
155
163
  }
156
164
  listProfiles() {
157
165
  return Object.values(this.data.profiles).sort((a, b) => a.name.localeCompare(b.name));
@@ -295,15 +303,18 @@ var SlatesCliStore = class _SlatesCliStore {
295
303
  var openSlatesCliStore = async (opts = {}) => SlatesCliStore.open(opts);
296
304
 
297
305
  // src/client.ts
298
- var resolveEntryPath = (entry, cwd) => {
306
+ var resolveEntryPath = (entry, opts = {}) => {
299
307
  if (path2.isAbsolute(entry)) return entry;
300
- return path2.resolve(resolveSlatesCliRoot(cwd), entry);
308
+ return path2.resolve(opts.rootDir ?? resolveSlatesCliRoot(opts.cwd), entry);
301
309
  };
302
- var loadSlateFromProfile = async (profile, cwd) => {
310
+ var loadSlateFromProfile = async (profile, opts = {}) => {
303
311
  if (profile.target.type !== "local") {
304
312
  throw new Error(`Unsupported profile target type: ${profile.target.type}`);
305
313
  }
306
- let modulePath = resolveEntryPath(profile.target.entry, cwd);
314
+ let modulePath = resolveEntryPath(profile.target.entry, {
315
+ cwd: opts.cwd,
316
+ rootDir: opts.store?.rootDir
317
+ });
307
318
  let loaded = await import(pathToFileURL(modulePath).href);
308
319
  let exportName = profile.target.exportName;
309
320
  let slate = (exportName ? loaded[exportName] : void 0) ?? loaded.provider ?? loaded.slate ?? loaded.default;
@@ -316,7 +327,7 @@ var loadSlateFromProfile = async (profile, cwd) => {
316
327
  };
317
328
  var createSlatesClientFromProfile = async (profile, opts = {}) => {
318
329
  let firstAuth = Object.values(profile.auth)[0];
319
- let slate = await loadSlateFromProfile(profile, opts.cwd);
330
+ let slate = await loadSlateFromProfile(profile, opts);
320
331
  let client = createSlatesClient({
321
332
  transport: createLocalSlateTransport({ slate }),
322
333
  state: {
@@ -328,20 +339,26 @@ var createSlatesClientFromProfile = async (profile, opts = {}) => {
328
339
  } : null
329
340
  }
330
341
  });
331
- if (firstAuth) {
342
+ if (firstAuth && opts.autoRefresh !== false) {
332
343
  attachAutoRefresh(client, profile, firstAuth, opts.store);
333
344
  }
334
345
  return client;
335
346
  };
336
347
  var EXPIRY_BUFFER_MS = 60 * 1e3;
337
- var shouldRefreshOAuthAuth = (auth) => {
338
- if (auth.authType !== "auth.oauth") return false;
339
- if (!auth.clientId || !auth.clientSecret) return false;
340
- if (typeof auth.output?.refreshToken !== "string" || !auth.output.refreshToken) return false;
348
+ var hasExpiredOrExpiringOutput = (auth) => {
341
349
  if (typeof auth.output?.expiresAt !== "string" || !auth.output.expiresAt) return false;
342
350
  let expiresAt = Date.parse(auth.output.expiresAt);
343
351
  return Number.isFinite(expiresAt) && expiresAt <= Date.now() + EXPIRY_BUFFER_MS;
344
352
  };
353
+ var shouldRefreshAuth = (auth) => {
354
+ if (!hasExpiredOrExpiringOutput(auth)) return false;
355
+ if (auth.authType === "auth.oauth") {
356
+ if (!auth.clientId || !auth.clientSecret) return false;
357
+ if (typeof auth.output?.refreshToken !== "string" || !auth.output.refreshToken)
358
+ return false;
359
+ }
360
+ return true;
361
+ };
345
362
  var attachAutoRefresh = (client, profile, storedAuth, store) => {
346
363
  let baseRequest = client.request.bind(client);
347
364
  let inflightRefresh = null;
@@ -350,7 +367,7 @@ var attachAutoRefresh = (client, profile, storedAuth, store) => {
350
367
  await inflightRefresh;
351
368
  return;
352
369
  }
353
- if (!shouldRefreshOAuthAuth(storedAuth)) {
370
+ if (!shouldRefreshAuth(storedAuth)) {
354
371
  return;
355
372
  }
356
373
  inflightRefresh = (async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@slates/profiles",
3
- "version": "1.0.0-rc.2",
3
+ "version": "1.0.0-rc.21",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -26,16 +26,16 @@
26
26
  "unpkg": "./dist/index.module.js",
27
27
  "scripts": {
28
28
  "test": "vitest run --passWithNoTests",
29
- "lint": "prettier src/**/*.ts --check",
30
29
  "build": "tsup --config ../../tsup.packages.config.ts --external async_hooks",
31
- "typecheck": "tsc --noEmit"
30
+ "typecheck": "tsc --noEmit",
31
+ "biome:check": "biome check --write src"
32
32
  },
33
33
  "dependencies": {
34
- "@slates/client": "1.0.0-rc.2",
35
- "@slates/proto": "1.0.0-rc.7"
34
+ "@slates/client": "1.0.0-rc.23",
35
+ "@slates/proto": "1.0.0-rc.19"
36
36
  },
37
37
  "devDependencies": {
38
- "@slates/provider": "1.0.0-rc.8",
38
+ "@slates/provider": "1.0.0-rc.23",
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
@@ -1,20 +1,26 @@
1
1
  import { createLocalSlateTransport, createSlatesClient } from '@slates/client';
2
2
  import path from 'path';
3
3
  import { pathToFileURL } from 'url';
4
- import { resolveSlatesCliRoot, SlatesCliStore } from './store';
5
- import { SlatesProfileRecord, SlatesStoredAuth } from './types';
4
+ import { resolveSlatesCliRoot, type SlatesCliStore } from './store';
5
+ import type { SlatesProfileRecord, SlatesStoredAuth } from './types';
6
6
 
7
- let resolveEntryPath = (entry: string, cwd?: string) => {
7
+ let resolveEntryPath = (entry: string, opts: { cwd?: string; rootDir?: string } = {}) => {
8
8
  if (path.isAbsolute(entry)) return entry;
9
- return path.resolve(resolveSlatesCliRoot(cwd), entry);
9
+ return path.resolve(opts.rootDir ?? resolveSlatesCliRoot(opts.cwd), entry);
10
10
  };
11
11
 
12
- let loadSlateFromProfile = async (profile: SlatesProfileRecord, cwd?: string) => {
12
+ let loadSlateFromProfile = async (
13
+ profile: SlatesProfileRecord,
14
+ opts: { cwd?: string; store?: SlatesCliStore } = {}
15
+ ) => {
13
16
  if (profile.target.type !== 'local') {
14
17
  throw new Error(`Unsupported profile target type: ${(profile.target as any).type}`);
15
18
  }
16
19
 
17
- let modulePath = resolveEntryPath(profile.target.entry, cwd);
20
+ let modulePath = resolveEntryPath(profile.target.entry, {
21
+ cwd: opts.cwd,
22
+ rootDir: opts.store?.rootDir
23
+ });
18
24
  let loaded = await import(pathToFileURL(modulePath).href);
19
25
  let exportName = profile.target.exportName;
20
26
 
@@ -37,10 +43,10 @@ let loadSlateFromProfile = async (profile: SlatesProfileRecord, cwd?: string) =>
37
43
 
38
44
  export let createSlatesClientFromProfile = async (
39
45
  profile: SlatesProfileRecord,
40
- opts: { cwd?: string; store?: SlatesCliStore } = {}
46
+ opts: { cwd?: string; store?: SlatesCliStore; autoRefresh?: boolean } = {}
41
47
  ) => {
42
48
  let firstAuth = Object.values(profile.auth)[0];
43
- let slate = await loadSlateFromProfile(profile, opts.cwd);
49
+ let slate = await loadSlateFromProfile(profile, opts);
44
50
  let client = createSlatesClient({
45
51
  transport: createLocalSlateTransport({ slate }),
46
52
  state: {
@@ -55,7 +61,7 @@ export let createSlatesClientFromProfile = async (
55
61
  }
56
62
  });
57
63
 
58
- if (firstAuth) {
64
+ if (firstAuth && opts.autoRefresh !== false) {
59
65
  attachAutoRefresh(client, profile, firstAuth, opts.store);
60
66
  }
61
67
 
@@ -64,16 +70,25 @@ export let createSlatesClientFromProfile = async (
64
70
 
65
71
  let EXPIRY_BUFFER_MS = 60 * 1000;
66
72
 
67
- let shouldRefreshOAuthAuth = (auth: SlatesStoredAuth) => {
68
- if (auth.authType !== 'auth.oauth') return false;
69
- if (!auth.clientId || !auth.clientSecret) return false;
70
- if (typeof auth.output?.refreshToken !== 'string' || !auth.output.refreshToken) return false;
73
+ let hasExpiredOrExpiringOutput = (auth: SlatesStoredAuth) => {
71
74
  if (typeof auth.output?.expiresAt !== 'string' || !auth.output.expiresAt) return false;
72
75
 
73
76
  let expiresAt = Date.parse(auth.output.expiresAt);
74
77
  return Number.isFinite(expiresAt) && expiresAt <= Date.now() + EXPIRY_BUFFER_MS;
75
78
  };
76
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)
86
+ return false;
87
+ }
88
+
89
+ return true;
90
+ };
91
+
77
92
  let attachAutoRefresh = (
78
93
  client: ReturnType<typeof createSlatesClient>,
79
94
  profile: SlatesProfileRecord,
@@ -89,7 +104,7 @@ let attachAutoRefresh = (
89
104
  return;
90
105
  }
91
106
 
92
- if (!shouldRefreshOAuthAuth(storedAuth)) {
107
+ if (!shouldRefreshAuth(storedAuth)) {
93
108
  return;
94
109
  }
95
110
 
package/src/store.test.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { mkdir, mkdtemp, rm, writeFile } from 'fs/promises';
1
+ import { access, mkdir, mkdtemp, rm, writeFile } from 'fs/promises';
2
2
  import { tmpdir } from 'os';
3
3
  import path from 'path';
4
4
  import { afterEach, describe, expect, it } from 'vitest';
@@ -55,7 +55,56 @@ describe('@slates/profiles store', () => {
55
55
  expect(reopenedProfile.config).toEqual({ prefix: 'Hello' });
56
56
  expect(reopened.getAuth(profile.id, 'token_auth')?.output).toEqual({ token: 'abc' });
57
57
  expect(reopened.scope?.key).toBe('integrations/demo');
58
- expect(reopened.storePath).toBe(path.join(cwd, '.slates-cli', 'profiles', 'integrations', 'demo', 'store.json'));
58
+ expect(reopened.cliDir).toBe(path.join(cwd, '.slates-cli'));
59
+ expect(reopened.storePath).toBe(
60
+ path.join(cwd, '.slates-cli', 'profiles', 'integrations', 'demo', 'store.json')
61
+ );
62
+ });
63
+
64
+ it('opens an external scoped store with a separate logical root', async () => {
65
+ let workspaceRoot = await createTempDir();
66
+ let storageRoot = await createTempDir();
67
+ let storePath = path.join(
68
+ storageRoot,
69
+ '.slates-cli',
70
+ 'profiles',
71
+ 'integrations',
72
+ 'demo',
73
+ 'store.json'
74
+ );
75
+
76
+ let store = await SlatesCliStore.open({
77
+ storePath,
78
+ rootDir: workspaceRoot
79
+ });
80
+
81
+ let profile = store.upsertProfile({
82
+ name: 'Demo',
83
+ target: {
84
+ type: 'local',
85
+ entry: 'integrations/demo/src/index.ts',
86
+ exportName: 'provider'
87
+ }
88
+ });
89
+ store.setCurrentProfile(profile.id);
90
+ await store.save();
91
+
92
+ let reopened = await SlatesCliStore.open({
93
+ storePath,
94
+ rootDir: workspaceRoot
95
+ });
96
+
97
+ expect(reopened.rootDir).toBe(workspaceRoot);
98
+ expect(reopened.cliDir).toBe(path.join(storageRoot, '.slates-cli'));
99
+ expect(reopened.scope?.key).toBe('integrations/demo');
100
+ expect(reopened.getProfile()?.target.entry).toBe('integrations/demo/src/index.ts');
101
+
102
+ await expect(
103
+ access(path.join(storageRoot, '.slates-cli', '.gitignore'))
104
+ ).resolves.toBeUndefined();
105
+ await expect(access(path.join(workspaceRoot, '.slates-cli'))).rejects.toMatchObject({
106
+ code: 'ENOENT'
107
+ });
59
108
  });
60
109
 
61
110
  it('migrates matching legacy profiles into an integration-scoped store', async () => {
@@ -182,6 +231,62 @@ export let provider = Slate.create({
182
231
  expect(provider.provider.name).toBe('Demo Slate');
183
232
  });
184
233
 
234
+ it('resolves profile entry paths against the store root when the store lives elsewhere', async () => {
235
+ let workspaceRoot = await createTempDir();
236
+ let storageRoot = await createTempDir();
237
+ let entry = path.join(workspaceRoot, 'integrations', 'demo-slate.mjs');
238
+ await mkdir(path.dirname(entry), { recursive: true });
239
+ await writeFile(
240
+ entry,
241
+ `
242
+ import { Slate, SlateAuth, SlateConfig, SlateSpecification } from '@slates/provider';
243
+ import { z } from 'zod';
244
+
245
+ let config = SlateConfig.create(z.object({})).getDefaultConfig(() => ({}));
246
+ let auth = SlateAuth.create();
247
+
248
+ export let provider = Slate.create({
249
+ spec: SlateSpecification.create({
250
+ key: 'external-demo',
251
+ name: 'External Demo',
252
+ description: 'Store root resolution test',
253
+ config,
254
+ auth
255
+ }),
256
+ tools: [],
257
+ triggers: []
258
+ });
259
+ `,
260
+ 'utf-8'
261
+ );
262
+
263
+ let store = await SlatesCliStore.open({
264
+ storePath: path.join(
265
+ storageRoot,
266
+ '.slates-cli',
267
+ 'profiles',
268
+ 'integrations',
269
+ 'demo',
270
+ 'store.json'
271
+ ),
272
+ rootDir: workspaceRoot
273
+ });
274
+ let profile = store.upsertProfile({
275
+ name: 'Demo',
276
+ target: {
277
+ type: 'local',
278
+ entry: 'integrations/demo-slate.mjs',
279
+ exportName: 'provider'
280
+ }
281
+ });
282
+
283
+ let client = await createSlatesClientFromProfile(profile, { store });
284
+ let provider = await client.identify();
285
+
286
+ expect(provider.provider.id).toBe('external-demo');
287
+ expect(provider.provider.name).toBe('External Demo');
288
+ });
289
+
185
290
  it('stores OAuth client credentials per integration', async () => {
186
291
  let cwd = await createTempDir();
187
292
  let store = await SlatesCliStore.open({
@@ -202,7 +307,9 @@ export let provider = Slate.create({
202
307
 
203
308
  let reopened = await SlatesCliStore.open({ storePath: store.storePath });
204
309
  expect(reopened.getOAuthCredential(credential.id)?.clientId).toBe('client-id');
205
- expect(reopened.getOAuthCredential('Primary OAuth App')?.clientSecret).toBe('client-secret');
310
+ expect(reopened.getOAuthCredential('Primary OAuth App')?.clientSecret).toBe(
311
+ 'client-secret'
312
+ );
206
313
  });
207
314
 
208
315
  it('refreshes expired OAuth auth automatically in the profile-backed client', async () => {
@@ -312,4 +419,115 @@ export let provider = Slate.create({
312
419
  token: 'expired-token-refreshed'
313
420
  });
314
421
  });
422
+
423
+ it('refreshes expired custom auth automatically in the profile-backed client', async () => {
424
+ let cwd = await createTempDir();
425
+ let entry = path.join(cwd, 'custom-slate.mjs');
426
+ await writeFile(
427
+ entry,
428
+ `
429
+ import { Slate, SlateAuth, SlateConfig, SlateSpecification, SlateTool } from '@slates/provider';
430
+ import { z } from 'zod';
431
+
432
+ let config = SlateConfig.create(z.object({})).getDefaultConfig(() => ({}));
433
+ let auth = SlateAuth.create()
434
+ .output(
435
+ z.object({
436
+ token: z.string(),
437
+ expiresAt: z.string().optional()
438
+ })
439
+ )
440
+ .addCustomAuth({
441
+ type: 'auth.custom',
442
+ key: 'custom',
443
+ name: 'Custom',
444
+ inputSchema: z.object({
445
+ tokenPrefix: z.string()
446
+ }),
447
+ getOutput: async ctx => ({
448
+ output: {
449
+ token: \`\${ctx.input.tokenPrefix}-initial\`,
450
+ expiresAt: new Date(Date.now() + 60 * 60 * 1000).toISOString()
451
+ }
452
+ }),
453
+ handleTokenRefresh: async ctx => ({
454
+ output: {
455
+ token: \`\${ctx.input.tokenPrefix}-refreshed\`,
456
+ expiresAt: new Date(Date.now() + 60 * 60 * 1000).toISOString()
457
+ }
458
+ })
459
+ });
460
+
461
+ let spec = SlateSpecification.create({
462
+ key: 'custom-demo',
463
+ name: 'Custom Demo',
464
+ description: 'Custom auth test slate',
465
+ config,
466
+ auth
467
+ });
468
+
469
+ let tool = SlateTool.create(spec, {
470
+ key: 'whoami',
471
+ name: 'Who Am I'
472
+ })
473
+ .input(z.object({}))
474
+ .output(
475
+ z.object({
476
+ token: z.string()
477
+ })
478
+ )
479
+ .handleInvocation(async ctx => ({
480
+ output: {
481
+ token: ctx.auth.token
482
+ }
483
+ }))
484
+ .build();
485
+
486
+ export let provider = Slate.create({
487
+ spec,
488
+ tools: [tool],
489
+ triggers: []
490
+ });
491
+ `,
492
+ 'utf-8'
493
+ );
494
+
495
+ let store = await SlatesCliStore.open({
496
+ cwd,
497
+ scope: {
498
+ key: 'integrations/demo',
499
+ name: 'demo'
500
+ }
501
+ });
502
+ let profile = store.upsertProfile({
503
+ name: 'Demo',
504
+ target: {
505
+ type: 'local',
506
+ entry: './custom-slate.mjs',
507
+ exportName: 'provider'
508
+ }
509
+ });
510
+ store.setProfileConfig(profile.id, {});
511
+ store.upsertAuth(profile.id, {
512
+ authMethodId: 'custom',
513
+ authType: 'auth.custom',
514
+ input: {
515
+ tokenPrefix: 'custom-token'
516
+ },
517
+ output: {
518
+ token: 'expired-token',
519
+ expiresAt: new Date(Date.now() - 60 * 1000).toISOString()
520
+ },
521
+ scopes: []
522
+ });
523
+ await store.save();
524
+
525
+ let client = await createSlatesClientFromProfile(profile, { cwd, store });
526
+ let result = await client.invokeTool('whoami', {});
527
+
528
+ expect(result.output).toEqual({ token: 'custom-token-refreshed' });
529
+ expect(store.getAuth(profile.id, 'custom')?.output).toMatchObject({
530
+ token: 'custom-token-refreshed'
531
+ });
532
+ });
315
533
  });
package/src/store.ts CHANGED
@@ -2,7 +2,7 @@ import { execFileSync } from 'child_process';
2
2
  import { randomUUID } from 'crypto';
3
3
  import { mkdir, readFile, writeFile } from 'fs/promises';
4
4
  import path from 'path';
5
- import {
5
+ import type {
6
6
  SlatesCliStoreData,
7
7
  SlatesCliStoreScope,
8
8
  SlatesOAuthCredentialRecord,
@@ -56,11 +56,16 @@ export let resolveSlatesCliRoot = (cwd: string = process.cwd()) => {
56
56
  }
57
57
  };
58
58
 
59
+ let resolveSlatesCliDirFromRoot = (rootDir: string) => path.join(rootDir, CLI_DIR_NAME);
60
+
61
+ let resolveSlatesCliProfilesDirFromRoot = (rootDir: string) =>
62
+ path.join(resolveSlatesCliDirFromRoot(rootDir), PROFILES_DIR_NAME);
63
+
59
64
  export let resolveSlatesCliDir = (cwd: string = process.cwd()) =>
60
- path.join(resolveSlatesCliRoot(cwd), CLI_DIR_NAME);
65
+ resolveSlatesCliDirFromRoot(resolveSlatesCliRoot(cwd));
61
66
 
62
67
  export let resolveSlatesCliProfilesDir = (cwd: string = process.cwd()) =>
63
- path.join(resolveSlatesCliDir(cwd), PROFILES_DIR_NAME);
68
+ resolveSlatesCliProfilesDirFromRoot(resolveSlatesCliRoot(cwd));
64
69
 
65
70
  let normalizeScopeKey = (scopeKey: string) =>
66
71
  path.posix.normalize(scopeKey.replace(/\\/g, '/')).replace(/^\.?\//, '');
@@ -72,7 +77,7 @@ let splitScopeKey = (scopeKey: string) =>
72
77
  .filter(segment => segment !== '.' && segment !== '..');
73
78
 
74
79
  let resolveScopedStoreDir = (rootDir: string, scopeKey: string) =>
75
- path.join(resolveSlatesCliProfilesDir(rootDir), ...splitScopeKey(scopeKey));
80
+ path.join(resolveSlatesCliProfilesDirFromRoot(rootDir), ...splitScopeKey(scopeKey));
76
81
 
77
82
  let resolveScopedStorePath = (rootDir: string, scopeKey: string) =>
78
83
  path.join(resolveScopedStoreDir(rootDir, scopeKey), STORE_FILE_NAME);
@@ -91,7 +96,7 @@ let inferRootDirFromStorePath = (storePath: string) => {
91
96
  };
92
97
 
93
98
  let resolveScopeKeyFromStorePath = (rootDir: string, storePath: string) => {
94
- let profilesDir = resolveSlatesCliProfilesDir(rootDir);
99
+ let profilesDir = resolveSlatesCliProfilesDirFromRoot(rootDir);
95
100
  let relativeDir = path.relative(profilesDir, path.dirname(storePath));
96
101
  if (!relativeDir || relativeDir.startsWith('..') || path.isAbsolute(relativeDir)) {
97
102
  return null;
@@ -138,7 +143,7 @@ let loadMigratedLegacyStore = async (
138
143
  rootDir: string,
139
144
  scopeKey: string
140
145
  ): Promise<SlatesCliStoreData> => {
141
- let legacyStorePath = path.join(resolveSlatesCliDir(rootDir), STORE_FILE_NAME);
146
+ let legacyStorePath = path.join(resolveSlatesCliDirFromRoot(rootDir), STORE_FILE_NAME);
142
147
  let legacy = await readStoreData<SlatesLegacyCliStoreData>(legacyStorePath);
143
148
  if (!legacy) {
144
149
  return createEmptyStore();
@@ -166,6 +171,7 @@ let loadMigratedLegacyStore = async (
166
171
  export class SlatesCliStore {
167
172
  constructor(
168
173
  readonly rootDir: string,
174
+ readonly cliDir: string,
169
175
  readonly dirPath: string,
170
176
  readonly storePath: string,
171
177
  readonly scope: SlatesCliStoreScope | null,
@@ -173,14 +179,20 @@ export class SlatesCliStore {
173
179
  ) {}
174
180
 
175
181
  static async open(
176
- opts: { cwd?: string; scope?: SlatesCliStoreScope; storePath?: string } = {}
182
+ opts: {
183
+ cwd?: string;
184
+ rootDir?: string;
185
+ scope?: SlatesCliStoreScope;
186
+ storePath?: string;
187
+ } = {}
177
188
  ) {
178
- let rootDir = opts.storePath
189
+ let storageRootDir = opts.storePath
179
190
  ? inferRootDirFromStorePath(opts.storePath)
180
191
  : resolveSlatesCliRoot(opts.cwd);
181
- let cliDir = resolveSlatesCliDir(rootDir);
192
+ let rootDir = opts.rootDir ?? storageRootDir;
193
+ let cliDir = resolveSlatesCliDirFromRoot(storageRootDir);
182
194
  let scopeKey = opts.storePath
183
- ? resolveScopeKeyFromStorePath(rootDir, opts.storePath)
195
+ ? resolveScopeKeyFromStorePath(storageRootDir, opts.storePath)
184
196
  : opts.scope?.key
185
197
  ? normalizeScopeKey(opts.scope.key)
186
198
  : null;
@@ -207,16 +219,19 @@ export class SlatesCliStore {
207
219
  profiles: parsed.profiles ?? {},
208
220
  oauthCredentials: parsed.oauthCredentials ?? {}
209
221
  }
210
- : scopeKey
211
- ? await loadMigratedLegacyStore(rootDir, scopeKey)
212
- : createEmptyStore();
222
+ : opts.storePath
223
+ ? createEmptyStore()
224
+ : scopeKey
225
+ ? await loadMigratedLegacyStore(rootDir, scopeKey)
226
+ : createEmptyStore();
213
227
 
214
228
  if (!parsed) {
215
- await writeFile(storePath, JSON.stringify(data, null, 2) + '\n', 'utf-8');
229
+ await writeFile(storePath, `${JSON.stringify(data, null, 2)}\n`, 'utf-8');
216
230
  }
217
231
 
218
232
  return new SlatesCliStore(
219
233
  rootDir,
234
+ cliDir,
220
235
  dirPath,
221
236
  storePath,
222
237
  scopeKey ? { key: scopeKey, name: opts.scope?.name } : null,
@@ -226,9 +241,9 @@ export class SlatesCliStore {
226
241
 
227
242
  async save() {
228
243
  await ensureDir(this.dirPath);
229
- await ensureDir(resolveSlatesCliDir(this.rootDir));
230
- await ensureGitIgnore(resolveSlatesCliDir(this.rootDir));
231
- await writeFile(this.storePath, JSON.stringify(this.data, null, 2) + '\n', 'utf-8');
244
+ await ensureDir(this.cliDir);
245
+ await ensureGitIgnore(this.cliDir);
246
+ await writeFile(this.storePath, `${JSON.stringify(this.data, null, 2)}\n`, 'utf-8');
232
247
  }
233
248
 
234
249
  listProfiles() {
@@ -418,5 +433,10 @@ export class SlatesCliStore {
418
433
  }
419
434
 
420
435
  export let openSlatesCliStore = async (
421
- opts: { cwd?: string; scope?: SlatesCliStoreScope; storePath?: string } = {}
436
+ opts: {
437
+ cwd?: string;
438
+ rootDir?: string;
439
+ scope?: SlatesCliStoreScope;
440
+ storePath?: string;
441
+ } = {}
422
442
  ) => SlatesCliStore.open(opts);
package/src/types.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { SlatesJsonObject } from '@slates/client';
2
- import { SlateAuthenticationMethod, SlatesAction } from '@slates/proto';
1
+ import type { SlatesJsonObject } from '@slates/client';
2
+ import type { SlateAuthenticationMethod, SlatesAction } from '@slates/proto';
3
3
 
4
4
  export interface SlatesStoredAuth {
5
5
  id: string;