@sequenceholdings/artifact-studio 0.1.12 → 0.2.0
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/VERSION-PIN.md +54 -0
- package/dist/active-deploy-policy.d.ts +36 -0
- package/dist/active-deploy-policy.js +66 -0
- package/dist/api.js +59 -13
- package/dist/artifact-ignore.d.ts +16 -0
- package/dist/artifact-ignore.js +38 -0
- package/dist/atlas-ui-css-plugin.d.ts +15 -0
- package/dist/atlas-ui-css-plugin.js +69 -0
- package/dist/build-subprocess.d.ts +3 -1
- package/dist/build-subprocess.js +28 -6
- package/dist/build.d.ts +25 -0
- package/dist/build.js +97 -50
- package/dist/child-environment.d.ts +5 -0
- package/dist/child-environment.js +83 -0
- package/dist/cli.d.ts +40 -1
- package/dist/cli.js +173 -87
- package/dist/config.d.ts +0 -9
- package/dist/config.js +0 -18
- package/dist/deployment-validation.d.ts +9 -0
- package/dist/deployment-validation.js +70 -0
- package/dist/git-clone.js +16 -10
- package/dist/peer-versions.d.ts +19 -0
- package/dist/peer-versions.js +44 -0
- package/dist/prepare-build.d.ts +2 -0
- package/dist/prepare-build.js +27 -7
- package/dist/project.d.ts +3 -0
- package/dist/project.js +22 -6
- package/dist/runtime-chunks.d.ts +4 -0
- package/dist/runtime-chunks.js +15 -0
- package/dist/sdk.d.ts +10 -0
- package/dist/source-resolver.d.ts +8 -5
- package/dist/source-resolver.js +81 -32
- package/dist/templates/react-vite/AGENTS.md +90 -0
- package/dist/templates/react-vite/CLAUDE.md +4 -63
- package/dist/templates/react-vite/src/main.tsx +7 -1
- package/dist/templates/react-vite/src/styles.css +11 -0
- package/package.json +18 -5
- package/templates/react-vite/AGENTS.md +90 -0
- package/templates/react-vite/CLAUDE.md +4 -63
- package/templates/react-vite/src/main.tsx +7 -1
- package/templates/react-vite/src/styles.css +11 -0
- package/dist/auth.d.ts +0 -2
- package/dist/auth.js +0 -129
package/dist/build.js
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
import { existsSync } from 'node:fs';
|
|
2
1
|
import { mkdir, writeFile } from 'node:fs/promises';
|
|
3
2
|
import { createRequire } from 'node:module';
|
|
4
|
-
import { dirname, resolve } from 'node:path';
|
|
5
|
-
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { dirname, relative, resolve } from 'node:path';
|
|
6
4
|
import { build as viteBuild } from 'vite';
|
|
5
|
+
import { atlasUiCssResolverPlugin } from './atlas-ui-css-plugin.js';
|
|
7
6
|
import { sha256Hex } from './hash.js';
|
|
7
|
+
import { isArtifactIgnoredPath } from './artifact-ignore.js';
|
|
8
8
|
import { readArtifactStudioSource } from './project.js';
|
|
9
|
+
import { normalizeArtifactPath } from './paths.js';
|
|
10
|
+
import { resolveArtifactStudioPeerVersions, } from './peer-versions.js';
|
|
11
|
+
import { ARTIFACT_RUNTIME_CHUNK_DIR, assertSafeRuntimeChunkFileName } from './runtime-chunks.js';
|
|
9
12
|
/** Keep in sync with `atlas/src/server/services/artifact-studio/limits.ts`. */
|
|
10
13
|
const MAX_DEPLOY_SOURCEMAP_BYTES = 10 * 1024 * 1024;
|
|
11
14
|
const cliRequire = createRequire(import.meta.url);
|
|
12
|
-
const cliDir = dirname(fileURLToPath(import.meta.url));
|
|
13
15
|
const reactDir = dirname(cliRequire.resolve('react/package.json'));
|
|
14
16
|
const reactDomDir = dirname(cliRequire.resolve('react-dom/package.json'));
|
|
15
17
|
// Artifacts (and the `react-vite` scaffold) import `@tanstack/react-query`
|
|
@@ -29,8 +31,6 @@ const atlasUiDist = resolve(atlasUiDir, 'dist');
|
|
|
29
31
|
// `seq-studio dev --link`) work.
|
|
30
32
|
const formRendererDir = dirname(cliRequire.resolve('@sequenceholdings/lattice-form-renderer/package.json'));
|
|
31
33
|
const formRendererDist = resolve(formRendererDir, 'dist');
|
|
32
|
-
const tailwindCssPath = resolve(dirname(cliRequire.resolve('tailwindcss/package.json')), 'index.css');
|
|
33
|
-
const twAnimateCssPath = resolveTwAnimateCssPath();
|
|
34
34
|
/**
|
|
35
35
|
* Import aliases for the Vite build. Artifacts are built against their own
|
|
36
36
|
* source tree, which usually has no installed node_modules, so every bare
|
|
@@ -39,6 +39,10 @@ const twAnimateCssPath = resolveTwAnimateCssPath();
|
|
|
39
39
|
* react-query QueryClient context — so a duplicate copy can't silently break
|
|
40
40
|
* hooks or the provider/consumer link. Exported so it can be regression-tested
|
|
41
41
|
* (a missing/unresolvable peer must fail loudly).
|
|
42
|
+
*
|
|
43
|
+
* **CLI atlas-ui stamp (DES-254):** the atlas-ui a bundle gets is whatever
|
|
44
|
+
* *this* CLI package resolves — not a semver the artifact declares.
|
|
45
|
+
* See `VERSION-PIN.md`.
|
|
42
46
|
*/
|
|
43
47
|
/** Platform + common artifact runtime peers — always aliased over node_modules. */
|
|
44
48
|
export const PEER_RESOLVE_ALIAS = {
|
|
@@ -50,6 +54,13 @@ export const PEER_RESOLVE_ALIAS = {
|
|
|
50
54
|
'@tanstack/react-query': reactQueryDir,
|
|
51
55
|
'react-router-dom': reactRouterDomDir,
|
|
52
56
|
sonner: sonnerDir,
|
|
57
|
+
// v2 token entry points live at the PACKAGE ROOT, not in dist (the generator
|
|
58
|
+
// writes them there and `files` publishes them from there). Without these
|
|
59
|
+
// keys the imports fall through to the bare `atlas-ui` alias below — which
|
|
60
|
+
// prefix-matches and rewrites them to `<dist>/index.mjs/tokens.v2.css`, a
|
|
61
|
+
// path that doesn't exist, so the artifact build fails on a CSS import.
|
|
62
|
+
'@sequenceholdings/atlas-ui/tokens.v2.css': resolve(atlasUiDir, 'tokens.v2.css'),
|
|
63
|
+
'@sequenceholdings/atlas-ui/theme.v2.css': resolve(atlasUiDir, 'theme.v2.css'),
|
|
53
64
|
'@sequenceholdings/atlas-ui/tokens.css': resolve(atlasUiDist, 'tokens.css'),
|
|
54
65
|
'@sequenceholdings/atlas-ui/charts': resolve(atlasUiDist, 'charts.mjs'),
|
|
55
66
|
'@sequenceholdings/atlas-ui': resolve(atlasUiDist, 'index.mjs'),
|
|
@@ -69,8 +80,13 @@ export async function buildArtifactStudioProject(rootDir) {
|
|
|
69
80
|
configFile: false,
|
|
70
81
|
logLevel: 'silent',
|
|
71
82
|
plugins: [
|
|
83
|
+
rejectIgnoredSourcePlugin(root, source.ignorePatterns),
|
|
72
84
|
artifactSdkVirtualModule(),
|
|
73
|
-
atlasUiCssResolverPlugin(
|
|
85
|
+
atlasUiCssResolverPlugin({
|
|
86
|
+
atlasUiDir,
|
|
87
|
+
atlasUiDist,
|
|
88
|
+
formRendererDist,
|
|
89
|
+
}),
|
|
74
90
|
nextStubPlugin(),
|
|
75
91
|
(await import('@tailwindcss/vite')).default(),
|
|
76
92
|
],
|
|
@@ -82,29 +98,77 @@ export async function buildArtifactStudioProject(rootDir) {
|
|
|
82
98
|
sourcemap: true,
|
|
83
99
|
cssCodeSplit: false,
|
|
84
100
|
assetsInlineLimit: Number.MAX_SAFE_INTEGER,
|
|
101
|
+
modulePreload: false,
|
|
85
102
|
rollupOptions: {
|
|
86
103
|
input: resolve(root, 'index.html'),
|
|
87
104
|
output: {
|
|
88
|
-
|
|
89
|
-
|
|
105
|
+
// ESM (not IIFE) so dynamic import() can emit async chunks (REP-87).
|
|
106
|
+
format: 'es',
|
|
107
|
+
entryFileNames: 'bundle.js',
|
|
108
|
+
chunkFileNames: `${ARTIFACT_RUNTIME_CHUNK_DIR}/[name]-[hash].js`,
|
|
109
|
+
assetFileNames: 'assets/[name]-[hash][extname]',
|
|
90
110
|
},
|
|
91
111
|
},
|
|
92
112
|
},
|
|
93
113
|
});
|
|
94
114
|
const output = Array.isArray(result) ? result.flatMap((r) => r.output) : result.output;
|
|
95
|
-
const
|
|
96
|
-
if (!
|
|
115
|
+
const entry = collectEntryJavaScript(output);
|
|
116
|
+
if (!entry)
|
|
97
117
|
throw new Error('Build produced no JavaScript output');
|
|
98
118
|
const css = collectCss(output);
|
|
99
|
-
const bundle = css ? injectCssRuntime(css) + '\n' +
|
|
119
|
+
const bundle = css ? injectCssRuntime(css) + '\n' + entry.code : entry.code;
|
|
120
|
+
const chunks = collectRuntimeChunks(output);
|
|
100
121
|
const sourceMap = fitSourceMapForDeploy(collectSourceMap(output));
|
|
101
122
|
return {
|
|
102
123
|
manifest: source.manifest,
|
|
103
124
|
files: source.files,
|
|
104
125
|
sourceHash: source.sourceHash,
|
|
105
126
|
bundle,
|
|
127
|
+
chunks,
|
|
128
|
+
bundleFormat: 'esm',
|
|
106
129
|
sourceMap,
|
|
107
|
-
bundleHash:
|
|
130
|
+
bundleHash: hashBundleAndChunks({ bundle, chunks }),
|
|
131
|
+
peerVersions: resolveArtifactStudioPeerVersions(),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* `.artifactignore` drops paths from sourceHash / deploy payloads, but Vite
|
|
136
|
+
* still sees the full tree. Reject any resolved import under an ignored prefix
|
|
137
|
+
* so `deploy --skip-unchanged` cannot silently keep a stale bundle when an
|
|
138
|
+
* ignored-but-imported file changes.
|
|
139
|
+
*/
|
|
140
|
+
function rejectIgnoredSourcePlugin(root, patterns) {
|
|
141
|
+
if (patterns.length === 0) {
|
|
142
|
+
return { name: 'reject-artifact-ignored-noop' };
|
|
143
|
+
}
|
|
144
|
+
const rootResolved = resolve(root);
|
|
145
|
+
return {
|
|
146
|
+
name: 'reject-artifact-ignored',
|
|
147
|
+
enforce: 'pre',
|
|
148
|
+
async resolveId(source, importer, options) {
|
|
149
|
+
const resolved = await this.resolve(source, importer, { ...options, skipSelf: true });
|
|
150
|
+
if (!resolved || resolved.external)
|
|
151
|
+
return resolved;
|
|
152
|
+
// Virtual modules (`\0…`) and query suffixes (`?worker`) are not source paths.
|
|
153
|
+
const filePath = resolved.id.split('\0').pop().split('?')[0];
|
|
154
|
+
if (!filePath.startsWith(rootResolved))
|
|
155
|
+
return resolved;
|
|
156
|
+
let rel;
|
|
157
|
+
try {
|
|
158
|
+
rel = normalizeArtifactPath(relative(rootResolved, filePath));
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
return resolved;
|
|
162
|
+
}
|
|
163
|
+
if (!isArtifactIgnoredPath(rel, patterns))
|
|
164
|
+
return resolved;
|
|
165
|
+
const from = importer
|
|
166
|
+
? ` (imported from ${relative(rootResolved, importer.split('?')[0])})`
|
|
167
|
+
: '';
|
|
168
|
+
throw new Error(`Cannot import "${rel}"${from}: path is listed in .artifactignore. ` +
|
|
169
|
+
'Ignored trees are excluded from sourceHash / deploy --skip-unchanged, ' +
|
|
170
|
+
'so build dependencies must not live under them.');
|
|
171
|
+
},
|
|
108
172
|
};
|
|
109
173
|
}
|
|
110
174
|
function fitSourceMapForDeploy(sourceMap) {
|
|
@@ -164,25 +228,30 @@ function nextStubPlugin() {
|
|
|
164
228
|
},
|
|
165
229
|
};
|
|
166
230
|
}
|
|
167
|
-
function resolveTwAnimateCssPath() {
|
|
168
|
-
const candidates = [
|
|
169
|
-
// Workspace layout: shared/services/artifact-studio/node_modules/...
|
|
170
|
-
resolve(cliDir, '..', 'node_modules', 'tw-animate-css', 'dist', 'tw-animate.css'),
|
|
171
|
-
// pnpm file-dependency layout: .../node_modules/@sequenceholdings/artifact-studio/dist
|
|
172
|
-
// with dependencies hoisted beside the scope directory.
|
|
173
|
-
resolve(cliDir, '..', '..', '..', 'tw-animate-css', 'dist', 'tw-animate.css'),
|
|
174
|
-
];
|
|
175
|
-
const resolved = candidates.find((candidate) => existsSync(candidate));
|
|
176
|
-
if (!resolved) {
|
|
177
|
-
throw new Error(`Unable to resolve tw-animate-css dist file. Tried: ${candidates.join(', ')}`);
|
|
178
|
-
}
|
|
179
|
-
return resolved;
|
|
180
|
-
}
|
|
181
231
|
function collectEntryJavaScript(output) {
|
|
182
232
|
const entryChunks = output.filter((chunk) => chunk.type === 'chunk' && chunk.isEntry);
|
|
183
233
|
if (entryChunks.length === 0)
|
|
184
234
|
return null;
|
|
185
|
-
|
|
235
|
+
// HTML multi-page inputs can emit multiple entries; Artifact Studio has one.
|
|
236
|
+
const entry = entryChunks[0];
|
|
237
|
+
return { code: entry.code, fileName: entry.fileName };
|
|
238
|
+
}
|
|
239
|
+
function collectRuntimeChunks(output) {
|
|
240
|
+
return output
|
|
241
|
+
.filter((chunk) => chunk.type === 'chunk' && !chunk.isEntry)
|
|
242
|
+
.map((chunk) => ({
|
|
243
|
+
fileName: assertSafeRuntimeChunkFileName(chunk.fileName),
|
|
244
|
+
code: chunk.code,
|
|
245
|
+
}))
|
|
246
|
+
.sort((a, b) => a.fileName.localeCompare(b.fileName));
|
|
247
|
+
}
|
|
248
|
+
export function hashBundleAndChunks({ bundle, chunks, }) {
|
|
249
|
+
const h = sha256Hex([
|
|
250
|
+
'artifact-studio-bundle-v2',
|
|
251
|
+
bundle,
|
|
252
|
+
...chunks.flatMap((chunk) => [chunk.fileName, chunk.code]),
|
|
253
|
+
].join('\0'));
|
|
254
|
+
return h;
|
|
186
255
|
}
|
|
187
256
|
function collectCss(output) {
|
|
188
257
|
const cssAssets = output.filter((chunk) => isAssetOutput(chunk) && chunk.fileName.endsWith('.css'));
|
|
@@ -203,25 +272,3 @@ function collectSourceMap(output) {
|
|
|
203
272
|
.map((chunk) => ({ fileName: chunk.fileName, map: chunk.map }));
|
|
204
273
|
return maps.length > 0 ? JSON.stringify(maps) : null;
|
|
205
274
|
}
|
|
206
|
-
function atlasUiCssResolverPlugin() {
|
|
207
|
-
return {
|
|
208
|
-
name: 'atlas-ui-css-resolver',
|
|
209
|
-
enforce: 'pre',
|
|
210
|
-
transform(code, id) {
|
|
211
|
-
if (!id.endsWith('.css'))
|
|
212
|
-
return undefined;
|
|
213
|
-
let result = code;
|
|
214
|
-
if (result.includes('@import "tailwindcss"')) {
|
|
215
|
-
result = result.replace('@import "tailwindcss"', `@import ${JSON.stringify(tailwindCssPath)}`);
|
|
216
|
-
// Prebuilt dists whose class names Tailwind must scan: atlas-ui plus
|
|
217
|
-
// the form renderer (field-scope.tsx emits Tailwind utility classes
|
|
218
|
-
// that only appear in the renderer's dist, not the artifact source).
|
|
219
|
-
result = `@source ${JSON.stringify(atlasUiDist)};\n@source ${JSON.stringify(formRendererDist)};\n${result}`;
|
|
220
|
-
}
|
|
221
|
-
if (result.includes('@import "tw-animate-css"')) {
|
|
222
|
-
result = result.replace('@import "tw-animate-css"', `@import ${JSON.stringify(twAnimateCssPath)}`);
|
|
223
|
-
}
|
|
224
|
-
return result !== code ? result : undefined;
|
|
225
|
-
},
|
|
226
|
-
};
|
|
227
|
-
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
// This prevents ambient credential inheritance and conventional HOME/config
|
|
3
|
+
// discovery. It is not an OS sandbox: the child still has the caller's uid and
|
|
4
|
+
// can read explicitly named filesystem paths and, where the OS permits it,
|
|
5
|
+
// inspect other same-uid processes (for example through Linux /proc).
|
|
6
|
+
const SAFE_CHILD_ENV_NAMES = new Set([
|
|
7
|
+
'PATH',
|
|
8
|
+
'PATHEXT',
|
|
9
|
+
'SYSTEMROOT',
|
|
10
|
+
'WINDIR',
|
|
11
|
+
'COMSPEC',
|
|
12
|
+
'TMPDIR',
|
|
13
|
+
'TMP',
|
|
14
|
+
'TEMP',
|
|
15
|
+
'LANG',
|
|
16
|
+
'LANGUAGE',
|
|
17
|
+
'LC_ALL',
|
|
18
|
+
'TERM',
|
|
19
|
+
'COLORTERM',
|
|
20
|
+
'NO_COLOR',
|
|
21
|
+
'FORCE_COLOR',
|
|
22
|
+
'CI',
|
|
23
|
+
'TZ',
|
|
24
|
+
'SOURCE_DATE_EPOCH',
|
|
25
|
+
'SSL_CERT_FILE',
|
|
26
|
+
'SSL_CERT_DIR',
|
|
27
|
+
'NODE_EXTRA_CA_CERTS',
|
|
28
|
+
]);
|
|
29
|
+
const PROXY_ENV_NAMES = new Set(['HTTP_PROXY', 'HTTPS_PROXY', 'ALL_PROXY', 'NO_PROXY']);
|
|
30
|
+
export function createScrubbedChildEnv({ homeDir, source = process.env, additionalEnv = {}, }) {
|
|
31
|
+
const env = {};
|
|
32
|
+
for (const [name, value] of Object.entries(source)) {
|
|
33
|
+
if (value === undefined)
|
|
34
|
+
continue;
|
|
35
|
+
const normalized = name.toUpperCase();
|
|
36
|
+
if (PROXY_ENV_NAMES.has(normalized)) {
|
|
37
|
+
env[name] = value;
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (SAFE_CHILD_ENV_NAMES.has(normalized) || normalized.startsWith('LC_')) {
|
|
41
|
+
env[name] = value;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
Object.assign(env, additionalEnv);
|
|
45
|
+
for (const [name, value] of Object.entries(env)) {
|
|
46
|
+
if (value !== undefined && PROXY_ENV_NAMES.has(name.toUpperCase())) {
|
|
47
|
+
assertProxySettingIsSafe({ name, value });
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
...env,
|
|
52
|
+
HOME: homeDir,
|
|
53
|
+
USERPROFILE: homeDir,
|
|
54
|
+
XDG_CONFIG_HOME: join(homeDir, '.config'),
|
|
55
|
+
XDG_CACHE_HOME: join(homeDir, '.cache'),
|
|
56
|
+
XDG_DATA_HOME: join(homeDir, '.local', 'share'),
|
|
57
|
+
APPDATA: join(homeDir, 'AppData', 'Roaming'),
|
|
58
|
+
LOCALAPPDATA: join(homeDir, 'AppData', 'Local'),
|
|
59
|
+
USER: 'sequence-build',
|
|
60
|
+
USERNAME: 'sequence-build',
|
|
61
|
+
LOGNAME: 'sequence-build',
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function assertProxySettingIsSafe({ name, value, }) {
|
|
65
|
+
if (name.toUpperCase() === 'NO_PROXY')
|
|
66
|
+
return;
|
|
67
|
+
let proxyUrl;
|
|
68
|
+
try {
|
|
69
|
+
// git/npm accept the legacy credential-free `host:port` form. Prefix a
|
|
70
|
+
// scheme for validation only; preserve the caller's exact value below.
|
|
71
|
+
proxyUrl = new URL(value.includes('://') ? value : `http://${value}`);
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
throw new Error(`${name} must be a valid proxy endpoint before it can be forwarded to a build worker`);
|
|
75
|
+
}
|
|
76
|
+
if (proxyUrl.username ||
|
|
77
|
+
proxyUrl.password ||
|
|
78
|
+
proxyUrl.search ||
|
|
79
|
+
proxyUrl.hash ||
|
|
80
|
+
(proxyUrl.pathname !== '' && proxyUrl.pathname !== '/')) {
|
|
81
|
+
throw new Error(`${name} contains credential-bearing URL components and cannot be forwarded to source-controlled build tooling`);
|
|
82
|
+
}
|
|
83
|
+
}
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,2 +1,41 @@
|
|
|
1
|
+
import { type ArtifactStudioPeerVersions } from './peer-versions.js';
|
|
2
|
+
import { type SourceAuthMode } from './source-resolver.js';
|
|
1
3
|
export declare function runCli(argv?: string[]): Promise<number>;
|
|
2
|
-
|
|
4
|
+
interface RemoteProject {
|
|
5
|
+
id: string;
|
|
6
|
+
slug: string;
|
|
7
|
+
title: string;
|
|
8
|
+
visibility?: string;
|
|
9
|
+
activeDeployment?: {
|
|
10
|
+
version: string;
|
|
11
|
+
sourceHash: string;
|
|
12
|
+
cliVersion?: string | null;
|
|
13
|
+
atlasUiVersion?: string | null;
|
|
14
|
+
} | null;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Whether `--skip-unchanged` may no-op: same source *and* same CLI/atlas-ui
|
|
18
|
+
* pin. Missing peer fields on older rows force a rebuild so the pin becomes
|
|
19
|
+
* observable (DES-254).
|
|
20
|
+
*/
|
|
21
|
+
export declare function activeDeploymentMatchesSkipPin({ active, sourceHash, peerVersions, }: {
|
|
22
|
+
active: RemoteProject['activeDeployment'];
|
|
23
|
+
sourceHash: string;
|
|
24
|
+
peerVersions: ArtifactStudioPeerVersions;
|
|
25
|
+
}): boolean;
|
|
26
|
+
export declare function getConfiguredDefaultEnv(): Promise<string | undefined>;
|
|
27
|
+
/**
|
|
28
|
+
* Optional refreshing token provider, injected by an embedder (e.g. seq-studio)
|
|
29
|
+
* that owns the shared seqapi session and can resolve an access token on
|
|
30
|
+
* demand. Authentication is owned by the embedding `seq-studio` CLI; this
|
|
31
|
+
* package deliberately has no bearer-token argv or environment escape hatch.
|
|
32
|
+
*/
|
|
33
|
+
export interface TokenProviderOptions {
|
|
34
|
+
allowInteractiveLogin: boolean;
|
|
35
|
+
}
|
|
36
|
+
export interface ProvidedToken {
|
|
37
|
+
authMode: SourceAuthMode;
|
|
38
|
+
token: string;
|
|
39
|
+
}
|
|
40
|
+
export declare function setTokenProvider(provider: ((options: TokenProviderOptions) => Promise<ProvidedToken | null>) | null): void;
|
|
41
|
+
export {};
|