workos 0.15.2 → 0.17.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/README.md +44 -14
- package/dist/bin.js +1449 -1261
- package/dist/bin.js.map +1 -1
- package/dist/cli.config.d.ts +1 -0
- package/dist/cli.config.js +1 -0
- package/dist/cli.config.js.map +1 -1
- package/dist/commands/api/index.js +7 -2
- package/dist/commands/api/index.js.map +1 -1
- package/dist/commands/api/interactive.js +9 -3
- package/dist/commands/api/interactive.js.map +1 -1
- package/dist/commands/debug.d.ts +2 -1
- package/dist/commands/debug.js +43 -3
- package/dist/commands/debug.js.map +1 -1
- package/dist/commands/dev.js +5 -4
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/doctor.js +13 -4
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/emulate.js +2 -2
- package/dist/commands/emulate.js.map +1 -1
- package/dist/commands/env.js +5 -4
- package/dist/commands/env.js.map +1 -1
- package/dist/commands/install-skill.js +4 -3
- package/dist/commands/install-skill.js.map +1 -1
- package/dist/commands/install.js +2 -2
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/login.js +3 -3
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/migrations.d.ts +1 -1
- package/dist/commands/migrations.js +4 -1
- package/dist/commands/migrations.js.map +1 -1
- package/dist/commands/telemetry.d.ts +3 -0
- package/dist/commands/telemetry.js +88 -0
- package/dist/commands/telemetry.js.map +1 -0
- package/dist/commands/uninstall-skill.js +3 -2
- package/dist/commands/uninstall-skill.js.map +1 -1
- package/dist/commands/vault-run.d.ts +13 -0
- package/dist/commands/vault-run.js +194 -0
- package/dist/commands/vault-run.js.map +1 -0
- package/dist/commands/vault.d.ts +3 -2
- package/dist/commands/vault.js +41 -8
- package/dist/commands/vault.js.map +1 -1
- package/dist/lib/adapters/cli-adapter.d.ts +7 -0
- package/dist/lib/adapters/cli-adapter.js +49 -0
- package/dist/lib/adapters/cli-adapter.js.map +1 -1
- package/dist/lib/adapters/dashboard-adapter.d.ts +4 -0
- package/dist/lib/adapters/dashboard-adapter.js +24 -0
- package/dist/lib/adapters/dashboard-adapter.js.map +1 -1
- package/dist/lib/adapters/headless-adapter.d.ts +6 -0
- package/dist/lib/adapters/headless-adapter.js +26 -1
- package/dist/lib/adapters/headless-adapter.js.map +1 -1
- package/dist/lib/api-error-handler.d.ts +15 -3
- package/dist/lib/api-error-handler.js +52 -34
- package/dist/lib/api-error-handler.js.map +1 -1
- package/dist/lib/command-aliases.d.ts +8 -0
- package/dist/lib/command-aliases.js +12 -0
- package/dist/lib/command-aliases.js.map +1 -0
- package/dist/lib/constants.d.ts +0 -1
- package/dist/lib/constants.js +0 -1
- package/dist/lib/constants.js.map +1 -1
- package/dist/lib/device-id.d.ts +25 -0
- package/dist/lib/device-id.js +102 -0
- package/dist/lib/device-id.js.map +1 -0
- package/dist/lib/events.d.ts +15 -0
- package/dist/lib/events.js.map +1 -1
- package/dist/lib/installer-core.d.ts +61 -1
- package/dist/lib/installer-core.js +132 -6
- package/dist/lib/installer-core.js.map +1 -1
- package/dist/lib/installer-core.types.d.ts +24 -0
- package/dist/lib/installer-core.types.js.map +1 -1
- package/dist/lib/preferences.d.ts +101 -0
- package/dist/lib/preferences.js +198 -0
- package/dist/lib/preferences.js.map +1 -0
- package/dist/lib/run-with-core.js +40 -15
- package/dist/lib/run-with-core.js.map +1 -1
- package/dist/lib/scaffold/index.d.ts +1 -0
- package/dist/lib/scaffold/index.js +2 -0
- package/dist/lib/scaffold/index.js.map +1 -0
- package/dist/lib/scaffold/scaffold.d.ts +66 -0
- package/dist/lib/scaffold/scaffold.js +156 -0
- package/dist/lib/scaffold/scaffold.js.map +1 -0
- package/dist/lib/settings.d.ts +6 -0
- package/dist/lib/settings.js +7 -0
- package/dist/lib/settings.js.map +1 -1
- package/dist/lib/telemetry-notice.d.ts +25 -0
- package/dist/lib/telemetry-notice.js +56 -0
- package/dist/lib/telemetry-notice.js.map +1 -0
- package/dist/run.d.ts +2 -2
- package/dist/run.js +2 -1
- package/dist/run.js.map +1 -1
- package/dist/test/force-insecure-storage.d.ts +1 -0
- package/dist/test/force-insecure-storage.js +9 -0
- package/dist/test/force-insecure-storage.js.map +1 -0
- package/dist/test/setup.d.ts +1 -0
- package/dist/test/setup.js +38 -0
- package/dist/test/setup.js.map +1 -0
- package/dist/utils/analytics.d.ts +41 -0
- package/dist/utils/analytics.js +199 -12
- package/dist/utils/analytics.js.map +1 -1
- package/dist/utils/box.d.ts +29 -1
- package/dist/utils/box.js +92 -4
- package/dist/utils/box.js.map +1 -1
- package/dist/utils/cli-exit.d.ts +15 -0
- package/dist/utils/cli-exit.js +11 -0
- package/dist/utils/cli-exit.js.map +1 -0
- package/dist/utils/cli-symbols.d.ts +1 -1
- package/dist/utils/command-telemetry.d.ts +17 -0
- package/dist/utils/command-telemetry.js +67 -0
- package/dist/utils/command-telemetry.js.map +1 -0
- package/dist/utils/crash-reporter.d.ts +13 -0
- package/dist/utils/crash-reporter.js +91 -0
- package/dist/utils/crash-reporter.js.map +1 -0
- package/dist/utils/debug.d.ts +1 -0
- package/dist/utils/debug.js +4 -1
- package/dist/utils/debug.js.map +1 -1
- package/dist/utils/exit-codes.d.ts +5 -0
- package/dist/utils/exit-codes.js +30 -1
- package/dist/utils/exit-codes.js.map +1 -1
- package/dist/utils/help-json.d.ts +6 -0
- package/dist/utils/help-json.js +87 -10
- package/dist/utils/help-json.js.map +1 -1
- package/dist/utils/output.d.ts +7 -2
- package/dist/utils/output.js +9 -2
- package/dist/utils/output.js.map +1 -1
- package/dist/utils/telemetry-client.d.ts +30 -2
- package/dist/utils/telemetry-client.js +122 -12
- package/dist/utils/telemetry-client.js.map +1 -1
- package/dist/utils/telemetry-store-forward.d.ts +11 -0
- package/dist/utils/telemetry-store-forward.js +94 -0
- package/dist/utils/telemetry-store-forward.js.map +1 -0
- package/dist/utils/telemetry-types.d.ts +58 -9
- package/dist/utils/telemetry-types.js.map +1 -1
- package/dist/utils/types.d.ts +10 -4
- package/dist/utils/types.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/scaffold/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,GAEjB,MAAM,eAAe,CAAC","sourcesContent":["export {\n CREATE_NEXT_APP_VERSION,\n SAFE_EMPTY_FILES,\n buildCreateNextAppArgs,\n isScaffoldableEmptyDir,\n resolvePackageManager,\n runCreateNextApp,\n type PackageManager,\n} from './scaffold.js';\n"]}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { InstallerEventEmitter } from '../events.js';
|
|
2
|
+
export type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun';
|
|
3
|
+
/**
|
|
4
|
+
* The `create-next-app` major we pin to. Matches `authkit-nextjs/examples/next`
|
|
5
|
+
* (Next 16). A major float (`@16`) keeps the pinned flag set stable while still
|
|
6
|
+
* receiving patch/minor updates. Re-pin when AuthKit bumps its supported Next major.
|
|
7
|
+
* `@latest` is intentionally avoided — it would reintroduce the flag-drift
|
|
8
|
+
* non-determinism this deterministic step exists to prevent.
|
|
9
|
+
*/
|
|
10
|
+
export declare const CREATE_NEXT_APP_VERSION = "16";
|
|
11
|
+
/**
|
|
12
|
+
* Files that may be present in a directory we still consider "scaffoldable empty".
|
|
13
|
+
*
|
|
14
|
+
* INVARIANT: this MUST stay a subset of create-next-app's own `validFiles`
|
|
15
|
+
* (verified against the v{@link CREATE_NEXT_APP_VERSION} tag). If ours is
|
|
16
|
+
* stricter, we simply scaffold less often (safe). If ours were looser,
|
|
17
|
+
* create-next-app would accept our offer and then refuse mid-run.
|
|
18
|
+
*
|
|
19
|
+
* We omit `docs` and `mkdocs.yml` from the upstream list on purpose — their
|
|
20
|
+
* presence usually signals real project content, so we err toward NOT scaffolding.
|
|
21
|
+
* We also omit `README.md`/`.vscode`: they are NOT in create-next-app's list, so a
|
|
22
|
+
* directory containing them is left to the normal (non-scaffold) install path.
|
|
23
|
+
*/
|
|
24
|
+
export declare const SAFE_EMPTY_FILES: ReadonlySet<string>;
|
|
25
|
+
/**
|
|
26
|
+
* True iff `dir` is empty or contains only {@link SAFE_EMPTY_FILES} entries.
|
|
27
|
+
*
|
|
28
|
+
* Because no project manifest (`package.json`, `go.mod`, `Gemfile`, etc.) appears
|
|
29
|
+
* in {@link SAFE_EMPTY_FILES}, the presence of any manifest makes this return
|
|
30
|
+
* false — i.e. an existing project always takes the normal install path.
|
|
31
|
+
*/
|
|
32
|
+
export declare function isScaffoldableEmptyDir(dir: string): Promise<boolean>;
|
|
33
|
+
/**
|
|
34
|
+
* Resolve the package manager for the scaffolded app.
|
|
35
|
+
*
|
|
36
|
+
* Precedence: validated `--pm` override > `npm_config_user_agent` parse > `npm`.
|
|
37
|
+
* An empty directory has no lockfile, so lockfile-based detection does not apply;
|
|
38
|
+
* we read the runner from the user agent instead (e.g. `pnpm dlx` → `pnpm`).
|
|
39
|
+
*/
|
|
40
|
+
export declare function resolvePackageManager(opts: {
|
|
41
|
+
pm?: string;
|
|
42
|
+
userAgent?: string;
|
|
43
|
+
}): PackageManager;
|
|
44
|
+
/**
|
|
45
|
+
* The pinned `create-next-app` flag set. Kept pure so a unit test can assert the
|
|
46
|
+
* exact array — flag drift across a pinned major is the primary failure mode.
|
|
47
|
+
*
|
|
48
|
+
* v1 scaffolds Next.js only. Multi-framework scaffolding (e.g. a Vite React app
|
|
49
|
+
* via its own `create-*` tool) is a tracked follow-up, not implemented.
|
|
50
|
+
*
|
|
51
|
+
* App Router + TypeScript + ESLint + Tailwind + `src/` + `@/*` alias, installed
|
|
52
|
+
* with the resolved package manager. `--yes` accepts all remaining defaults
|
|
53
|
+
* (including the major's Turbopack default) and prevents interactive hangs.
|
|
54
|
+
*/
|
|
55
|
+
export declare function buildCreateNextAppArgs(pm: PackageManager): string[];
|
|
56
|
+
/**
|
|
57
|
+
* Spawn `create-next-app@<pinned> .` in `installDir` via the resolved package
|
|
58
|
+
* manager's runner, streaming output as `scaffold:progress` events. Resolves on
|
|
59
|
+
* exit 0; rejects on non-zero exit or spawn error so the state machine can route
|
|
60
|
+
* to its error state.
|
|
61
|
+
*/
|
|
62
|
+
export declare function runCreateNextApp(opts: {
|
|
63
|
+
installDir: string;
|
|
64
|
+
packageManager: PackageManager;
|
|
65
|
+
emitter: InstallerEventEmitter;
|
|
66
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { readdir } from 'node:fs/promises';
|
|
3
|
+
import { SPAWN_OPTS } from '../../utils/platform.js';
|
|
4
|
+
/**
|
|
5
|
+
* The `create-next-app` major we pin to. Matches `authkit-nextjs/examples/next`
|
|
6
|
+
* (Next 16). A major float (`@16`) keeps the pinned flag set stable while still
|
|
7
|
+
* receiving patch/minor updates. Re-pin when AuthKit bumps its supported Next major.
|
|
8
|
+
* `@latest` is intentionally avoided — it would reintroduce the flag-drift
|
|
9
|
+
* non-determinism this deterministic step exists to prevent.
|
|
10
|
+
*/
|
|
11
|
+
export const CREATE_NEXT_APP_VERSION = '16';
|
|
12
|
+
const VALID_PACKAGE_MANAGERS = new Set(['npm', 'pnpm', 'yarn', 'bun']);
|
|
13
|
+
/**
|
|
14
|
+
* Files that may be present in a directory we still consider "scaffoldable empty".
|
|
15
|
+
*
|
|
16
|
+
* INVARIANT: this MUST stay a subset of create-next-app's own `validFiles`
|
|
17
|
+
* (verified against the v{@link CREATE_NEXT_APP_VERSION} tag). If ours is
|
|
18
|
+
* stricter, we simply scaffold less often (safe). If ours were looser,
|
|
19
|
+
* create-next-app would accept our offer and then refuse mid-run.
|
|
20
|
+
*
|
|
21
|
+
* We omit `docs` and `mkdocs.yml` from the upstream list on purpose — their
|
|
22
|
+
* presence usually signals real project content, so we err toward NOT scaffolding.
|
|
23
|
+
* We also omit `README.md`/`.vscode`: they are NOT in create-next-app's list, so a
|
|
24
|
+
* directory containing them is left to the normal (non-scaffold) install path.
|
|
25
|
+
*/
|
|
26
|
+
export const SAFE_EMPTY_FILES = new Set([
|
|
27
|
+
'.DS_Store',
|
|
28
|
+
'.git',
|
|
29
|
+
'.gitattributes',
|
|
30
|
+
'.gitignore',
|
|
31
|
+
'.gitlab-ci.yml',
|
|
32
|
+
'.hg',
|
|
33
|
+
'.hgcheck',
|
|
34
|
+
'.hgignore',
|
|
35
|
+
'.idea',
|
|
36
|
+
'.npmignore',
|
|
37
|
+
'.travis.yml',
|
|
38
|
+
'LICENSE',
|
|
39
|
+
'Thumbs.db',
|
|
40
|
+
'npm-debug.log',
|
|
41
|
+
'yarn-debug.log',
|
|
42
|
+
'yarn-error.log',
|
|
43
|
+
'yarnrc.yml',
|
|
44
|
+
'.yarn',
|
|
45
|
+
]);
|
|
46
|
+
/**
|
|
47
|
+
* True iff `dir` is empty or contains only {@link SAFE_EMPTY_FILES} entries.
|
|
48
|
+
*
|
|
49
|
+
* Because no project manifest (`package.json`, `go.mod`, `Gemfile`, etc.) appears
|
|
50
|
+
* in {@link SAFE_EMPTY_FILES}, the presence of any manifest makes this return
|
|
51
|
+
* false — i.e. an existing project always takes the normal install path.
|
|
52
|
+
*/
|
|
53
|
+
export async function isScaffoldableEmptyDir(dir) {
|
|
54
|
+
const entries = await readdir(dir);
|
|
55
|
+
return entries.every((entry) => SAFE_EMPTY_FILES.has(entry));
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Resolve the package manager for the scaffolded app.
|
|
59
|
+
*
|
|
60
|
+
* Precedence: validated `--pm` override > `npm_config_user_agent` parse > `npm`.
|
|
61
|
+
* An empty directory has no lockfile, so lockfile-based detection does not apply;
|
|
62
|
+
* we read the runner from the user agent instead (e.g. `pnpm dlx` → `pnpm`).
|
|
63
|
+
*/
|
|
64
|
+
export function resolvePackageManager(opts) {
|
|
65
|
+
const { pm, userAgent } = opts;
|
|
66
|
+
// `--pm` is validated by yargs `choices` upstream; guard again defensively and
|
|
67
|
+
// fall through on anything unexpected rather than throwing here.
|
|
68
|
+
if (pm && VALID_PACKAGE_MANAGERS.has(pm)) {
|
|
69
|
+
return pm;
|
|
70
|
+
}
|
|
71
|
+
if (userAgent) {
|
|
72
|
+
// e.g. "pnpm/8.6.0 npm/? node/v20.0.0 darwin arm64" → "pnpm"
|
|
73
|
+
const name = userAgent.split(/\s+/)[0]?.split('/')[0];
|
|
74
|
+
if (name && VALID_PACKAGE_MANAGERS.has(name)) {
|
|
75
|
+
return name;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return 'npm';
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The pinned `create-next-app` flag set. Kept pure so a unit test can assert the
|
|
82
|
+
* exact array — flag drift across a pinned major is the primary failure mode.
|
|
83
|
+
*
|
|
84
|
+
* v1 scaffolds Next.js only. Multi-framework scaffolding (e.g. a Vite React app
|
|
85
|
+
* via its own `create-*` tool) is a tracked follow-up, not implemented.
|
|
86
|
+
*
|
|
87
|
+
* App Router + TypeScript + ESLint + Tailwind + `src/` + `@/*` alias, installed
|
|
88
|
+
* with the resolved package manager. `--yes` accepts all remaining defaults
|
|
89
|
+
* (including the major's Turbopack default) and prevents interactive hangs.
|
|
90
|
+
*/
|
|
91
|
+
export function buildCreateNextAppArgs(pm) {
|
|
92
|
+
return ['.', '--ts', '--app', '--eslint', '--tailwind', '--src-dir', '--import-alias', '@/*', `--use-${pm}`, '--yes'];
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Each package manager's own package runner. Running create-next-app through the
|
|
96
|
+
* resolved PM's runner (instead of always `npx`) means we don't require npm/npx
|
|
97
|
+
* to be on PATH — e.g. a bun-only machine has no `npx`. `yarn dlx` assumes
|
|
98
|
+
* Yarn >= 2 (Berry); a Yarn 1 user would need `--pm npm`.
|
|
99
|
+
*/
|
|
100
|
+
const PM_RUNNER = {
|
|
101
|
+
npm: { bin: 'npx', args: ['--yes'] },
|
|
102
|
+
pnpm: { bin: 'pnpm', args: ['dlx'] },
|
|
103
|
+
yarn: { bin: 'yarn', args: ['dlx'] },
|
|
104
|
+
bun: { bin: 'bunx', args: [] },
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* Spawn `create-next-app@<pinned> .` in `installDir` via the resolved package
|
|
108
|
+
* manager's runner, streaming output as `scaffold:progress` events. Resolves on
|
|
109
|
+
* exit 0; rejects on non-zero exit or spawn error so the state machine can route
|
|
110
|
+
* to its error state.
|
|
111
|
+
*/
|
|
112
|
+
export function runCreateNextApp(opts) {
|
|
113
|
+
const { installDir, packageManager, emitter } = opts;
|
|
114
|
+
const runner = PM_RUNNER[packageManager];
|
|
115
|
+
const args = [
|
|
116
|
+
...runner.args,
|
|
117
|
+
`create-next-app@${CREATE_NEXT_APP_VERSION}`,
|
|
118
|
+
...buildCreateNextAppArgs(packageManager),
|
|
119
|
+
];
|
|
120
|
+
return new Promise((resolve, reject) => {
|
|
121
|
+
const child = spawn(runner.bin, args, {
|
|
122
|
+
cwd: installDir,
|
|
123
|
+
env: process.env,
|
|
124
|
+
...SPAWN_OPTS,
|
|
125
|
+
});
|
|
126
|
+
let stderr = '';
|
|
127
|
+
const stream = (data) => {
|
|
128
|
+
emitter.emit('scaffold:progress', { text: data.toString() });
|
|
129
|
+
};
|
|
130
|
+
child.stdout?.on('data', stream);
|
|
131
|
+
child.stderr?.on('data', (data) => {
|
|
132
|
+
// Bound the buffer at collection time so a pathological failure (e.g. a full
|
|
133
|
+
// npm resolution trace) can't accumulate hundreds of KB. Progress still streams.
|
|
134
|
+
if (stderr.length < 2000) {
|
|
135
|
+
stderr += data.toString();
|
|
136
|
+
}
|
|
137
|
+
stream(data);
|
|
138
|
+
});
|
|
139
|
+
child.on('close', (code, signal) => {
|
|
140
|
+
if (code === 0) {
|
|
141
|
+
resolve();
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
const detail = stderr ? `: ${stderr.trim().slice(0, 2000)}` : '';
|
|
145
|
+
// code is null when the process was killed by a signal (e.g. SIGTERM from a
|
|
146
|
+
// timeout layer); surface that instead of masking it as "exited with code 1".
|
|
147
|
+
const exitInfo = code !== null ? `exited with code ${code}` : `was killed by signal ${signal ?? 'unknown'}`;
|
|
148
|
+
reject(new Error(`create-next-app ${exitInfo}${detail}`));
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
child.on('error', (err) => {
|
|
152
|
+
reject(err);
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=scaffold.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../../src/lib/scaffold/scaffold.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from 'node:child_process';\nimport { readdir } from 'node:fs/promises';\nimport { SPAWN_OPTS } from '../../utils/platform.js';\nimport type { InstallerEventEmitter } from '../events.js';\n\nexport type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun';\n\n/**\n * The `create-next-app` major we pin to. Matches `authkit-nextjs/examples/next`\n * (Next 16). A major float (`@16`) keeps the pinned flag set stable while still\n * receiving patch/minor updates. Re-pin when AuthKit bumps its supported Next major.\n * `@latest` is intentionally avoided — it would reintroduce the flag-drift\n * non-determinism this deterministic step exists to prevent.\n */\nexport const CREATE_NEXT_APP_VERSION = '16';\n\nconst VALID_PACKAGE_MANAGERS: ReadonlySet<string> = new Set<PackageManager>(['npm', 'pnpm', 'yarn', 'bun']);\n\n/**\n * Files that may be present in a directory we still consider \"scaffoldable empty\".\n *\n * INVARIANT: this MUST stay a subset of create-next-app's own `validFiles`\n * (verified against the v{@link CREATE_NEXT_APP_VERSION} tag). If ours is\n * stricter, we simply scaffold less often (safe). If ours were looser,\n * create-next-app would accept our offer and then refuse mid-run.\n *\n * We omit `docs` and `mkdocs.yml` from the upstream list on purpose — their\n * presence usually signals real project content, so we err toward NOT scaffolding.\n * We also omit `README.md`/`.vscode`: they are NOT in create-next-app's list, so a\n * directory containing them is left to the normal (non-scaffold) install path.\n */\nexport const SAFE_EMPTY_FILES: ReadonlySet<string> = new Set([\n '.DS_Store',\n '.git',\n '.gitattributes',\n '.gitignore',\n '.gitlab-ci.yml',\n '.hg',\n '.hgcheck',\n '.hgignore',\n '.idea',\n '.npmignore',\n '.travis.yml',\n 'LICENSE',\n 'Thumbs.db',\n 'npm-debug.log',\n 'yarn-debug.log',\n 'yarn-error.log',\n 'yarnrc.yml',\n '.yarn',\n]);\n\n/**\n * True iff `dir` is empty or contains only {@link SAFE_EMPTY_FILES} entries.\n *\n * Because no project manifest (`package.json`, `go.mod`, `Gemfile`, etc.) appears\n * in {@link SAFE_EMPTY_FILES}, the presence of any manifest makes this return\n * false — i.e. an existing project always takes the normal install path.\n */\nexport async function isScaffoldableEmptyDir(dir: string): Promise<boolean> {\n const entries = await readdir(dir);\n return entries.every((entry) => SAFE_EMPTY_FILES.has(entry));\n}\n\n/**\n * Resolve the package manager for the scaffolded app.\n *\n * Precedence: validated `--pm` override > `npm_config_user_agent` parse > `npm`.\n * An empty directory has no lockfile, so lockfile-based detection does not apply;\n * we read the runner from the user agent instead (e.g. `pnpm dlx` → `pnpm`).\n */\nexport function resolvePackageManager(opts: { pm?: string; userAgent?: string }): PackageManager {\n const { pm, userAgent } = opts;\n\n // `--pm` is validated by yargs `choices` upstream; guard again defensively and\n // fall through on anything unexpected rather than throwing here.\n if (pm && VALID_PACKAGE_MANAGERS.has(pm)) {\n return pm as PackageManager;\n }\n\n if (userAgent) {\n // e.g. \"pnpm/8.6.0 npm/? node/v20.0.0 darwin arm64\" → \"pnpm\"\n const name = userAgent.split(/\\s+/)[0]?.split('/')[0];\n if (name && VALID_PACKAGE_MANAGERS.has(name)) {\n return name as PackageManager;\n }\n }\n\n return 'npm';\n}\n\n/**\n * The pinned `create-next-app` flag set. Kept pure so a unit test can assert the\n * exact array — flag drift across a pinned major is the primary failure mode.\n *\n * v1 scaffolds Next.js only. Multi-framework scaffolding (e.g. a Vite React app\n * via its own `create-*` tool) is a tracked follow-up, not implemented.\n *\n * App Router + TypeScript + ESLint + Tailwind + `src/` + `@/*` alias, installed\n * with the resolved package manager. `--yes` accepts all remaining defaults\n * (including the major's Turbopack default) and prevents interactive hangs.\n */\nexport function buildCreateNextAppArgs(pm: PackageManager): string[] {\n return ['.', '--ts', '--app', '--eslint', '--tailwind', '--src-dir', '--import-alias', '@/*', `--use-${pm}`, '--yes'];\n}\n\n/**\n * Each package manager's own package runner. Running create-next-app through the\n * resolved PM's runner (instead of always `npx`) means we don't require npm/npx\n * to be on PATH — e.g. a bun-only machine has no `npx`. `yarn dlx` assumes\n * Yarn >= 2 (Berry); a Yarn 1 user would need `--pm npm`.\n */\nconst PM_RUNNER: Record<PackageManager, { bin: string; args: string[] }> = {\n npm: { bin: 'npx', args: ['--yes'] },\n pnpm: { bin: 'pnpm', args: ['dlx'] },\n yarn: { bin: 'yarn', args: ['dlx'] },\n bun: { bin: 'bunx', args: [] },\n};\n\n/**\n * Spawn `create-next-app@<pinned> .` in `installDir` via the resolved package\n * manager's runner, streaming output as `scaffold:progress` events. Resolves on\n * exit 0; rejects on non-zero exit or spawn error so the state machine can route\n * to its error state.\n */\nexport function runCreateNextApp(opts: {\n installDir: string;\n packageManager: PackageManager;\n emitter: InstallerEventEmitter;\n}): Promise<void> {\n const { installDir, packageManager, emitter } = opts;\n const runner = PM_RUNNER[packageManager];\n const args = [\n ...runner.args,\n `create-next-app@${CREATE_NEXT_APP_VERSION}`,\n ...buildCreateNextAppArgs(packageManager),\n ];\n\n return new Promise<void>((resolve, reject) => {\n const child = spawn(runner.bin, args, {\n cwd: installDir,\n env: process.env,\n ...SPAWN_OPTS,\n });\n\n let stderr = '';\n\n const stream = (data: Buffer): void => {\n emitter.emit('scaffold:progress', { text: data.toString() });\n };\n\n child.stdout?.on('data', stream);\n child.stderr?.on('data', (data: Buffer) => {\n // Bound the buffer at collection time so a pathological failure (e.g. a full\n // npm resolution trace) can't accumulate hundreds of KB. Progress still streams.\n if (stderr.length < 2000) {\n stderr += data.toString();\n }\n stream(data);\n });\n\n child.on('close', (code, signal) => {\n if (code === 0) {\n resolve();\n } else {\n const detail = stderr ? `: ${stderr.trim().slice(0, 2000)}` : '';\n // code is null when the process was killed by a signal (e.g. SIGTERM from a\n // timeout layer); surface that instead of masking it as \"exited with code 1\".\n const exitInfo = code !== null ? `exited with code ${code}` : `was killed by signal ${signal ?? 'unknown'}`;\n reject(new Error(`create-next-app ${exitInfo}${detail}`));\n }\n });\n\n child.on('error', (err) => {\n reject(err);\n });\n });\n}\n"]}
|
package/dist/lib/settings.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export interface InstallerConfig {
|
|
|
9
9
|
clientId: string;
|
|
10
10
|
authkitDomain: string;
|
|
11
11
|
llmGatewayUrl: string;
|
|
12
|
+
telemetryUrl: string;
|
|
12
13
|
};
|
|
13
14
|
telemetry: {
|
|
14
15
|
enabled: boolean;
|
|
@@ -61,3 +62,8 @@ export declare function getAuthkitDomain(): string;
|
|
|
61
62
|
* Env var overrides config default.
|
|
62
63
|
*/
|
|
63
64
|
export declare function getLlmGatewayUrl(): string;
|
|
65
|
+
/**
|
|
66
|
+
* Get the CLI telemetry URL.
|
|
67
|
+
* Env var overrides config default.
|
|
68
|
+
*/
|
|
69
|
+
export declare function getTelemetryUrl(): string;
|
package/dist/lib/settings.js
CHANGED
|
@@ -32,4 +32,11 @@ export function getAuthkitDomain() {
|
|
|
32
32
|
export function getLlmGatewayUrl() {
|
|
33
33
|
return process.env.WORKOS_LLM_GATEWAY_URL || config.workos.llmGatewayUrl;
|
|
34
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Get the CLI telemetry URL.
|
|
37
|
+
* Env var overrides config default.
|
|
38
|
+
*/
|
|
39
|
+
export function getTelemetryUrl() {
|
|
40
|
+
return process.env.WORKOS_TELEMETRY_URL || config.workos.telemetryUrl;
|
|
41
|
+
}
|
|
35
42
|
//# sourceMappingURL=settings.js.map
|
package/dist/lib/settings.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../src/lib/settings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAEnD;;GAEG;AACH,MAAM,UAAU,UAAU;IACxB,OAAO,OAAO,CAAC;AACjB,CAAC;
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../src/lib/settings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAEnD;;GAEG;AACH,MAAM,UAAU,UAAU;IACxB,OAAO,OAAO,CAAC;AACjB,CAAC;AA4CD;;GAEG;AACH,MAAM,UAAU,SAAS;IACvB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB;IAChC,OAAO,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC;AAChC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC;AAC1E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC;AAC3E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;AACxE,CAAC","sourcesContent":["import { config, version } from '../cli.config.js';\n\n/**\n * Get version from package.json\n */\nexport function getVersion(): string {\n return version;\n}\n\nexport interface InstallerConfig {\n model: string;\n doctorModel: string;\n workos: {\n clientId: string;\n authkitDomain: string;\n llmGatewayUrl: string;\n telemetryUrl: string;\n };\n telemetry: {\n enabled: boolean;\n eventName: string;\n };\n proxy: {\n refreshThresholdMs: number;\n };\n nodeVersion: string;\n logging: {\n debugMode: boolean;\n };\n documentation: {\n workosDocsUrl: string;\n dashboardUrl: string;\n issuesUrl: string;\n };\n frameworks: {\n [key: string]: {\n port: number;\n callbackPath: string;\n };\n };\n legacy: {\n oauthPort: number;\n };\n branding: {\n showAsciiArt: boolean;\n asciiArt: string;\n compactAsciiArt: string;\n useCompact: boolean;\n };\n}\n\n/**\n * Get config\n */\nexport function getConfig(): InstallerConfig {\n return config;\n}\n\n/**\n * Get the CLI auth client ID.\n * Env var overrides config default.\n */\nexport function getCliAuthClientId(): string {\n return config.workos.clientId;\n}\n\n/**\n * Get the AuthKit domain.\n * Env var overrides config default.\n */\nexport function getAuthkitDomain(): string {\n return process.env.WORKOS_AUTHKIT_DOMAIN || config.workos.authkitDomain;\n}\n\n/**\n * Get the LLM gateway URL.\n * Env var overrides config default.\n */\nexport function getLlmGatewayUrl(): string {\n return process.env.WORKOS_LLM_GATEWAY_URL || config.workos.llmGatewayUrl;\n}\n\n/**\n * Get the CLI telemetry URL.\n * Env var overrides config default.\n */\nexport function getTelemetryUrl(): string {\n return process.env.WORKOS_TELEMETRY_URL || config.workos.telemetryUrl;\n}\n"]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* First-run telemetry notice.
|
|
3
|
+
*
|
|
4
|
+
* Prints a one-time, stderr-only box telling the user that anonymous CLI usage
|
|
5
|
+
* telemetry is being collected and how to turn it off. Shown at most once ever
|
|
6
|
+
* (backed by the persisted `noticeShownAt` timestamp in preferences.json), only
|
|
7
|
+
* in interactive human mode, and never on the machine-readable path.
|
|
8
|
+
*
|
|
9
|
+
* Mirrors the structural pattern of unclaimed-warning.ts: a per-session guard,
|
|
10
|
+
* a `!isJsonMode()` gate, the shared renderStderrBox helper, and a never-throws
|
|
11
|
+
* contract so it can never block command execution. The one structural
|
|
12
|
+
* difference is persistence — this notice writes `noticeShownAt` the first time
|
|
13
|
+
* it actually displays so it never re-shows across runs.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Show the first-run telemetry notice if it has never been displayed.
|
|
17
|
+
*
|
|
18
|
+
* Gate order is load-bearing: every suppression check runs BEFORE
|
|
19
|
+
* markNoticeShown(), so a non-human first run (--json / piped / CI) never
|
|
20
|
+
* consumes the one-time display. The flag is set only when the box is actually
|
|
21
|
+
* rendered, so a real human eventually sees it. Never throws.
|
|
22
|
+
*/
|
|
23
|
+
export declare function maybeShowTelemetryNotice(): void;
|
|
24
|
+
/** Reset session state (for testing). */
|
|
25
|
+
export declare function resetTelemetryNoticeState(): void;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* First-run telemetry notice.
|
|
3
|
+
*
|
|
4
|
+
* Prints a one-time, stderr-only box telling the user that anonymous CLI usage
|
|
5
|
+
* telemetry is being collected and how to turn it off. Shown at most once ever
|
|
6
|
+
* (backed by the persisted `noticeShownAt` timestamp in preferences.json), only
|
|
7
|
+
* in interactive human mode, and never on the machine-readable path.
|
|
8
|
+
*
|
|
9
|
+
* Mirrors the structural pattern of unclaimed-warning.ts: a per-session guard,
|
|
10
|
+
* a `!isJsonMode()` gate, the shared renderStderrBox helper, and a never-throws
|
|
11
|
+
* contract so it can never block command execution. The one structural
|
|
12
|
+
* difference is persistence — this notice writes `noticeShownAt` the first time
|
|
13
|
+
* it actually displays so it never re-shows across runs.
|
|
14
|
+
*/
|
|
15
|
+
import chalk from 'chalk';
|
|
16
|
+
import { isJsonMode } from '../utils/output.js';
|
|
17
|
+
import { renderStderrBox } from '../utils/box.js';
|
|
18
|
+
import { formatWorkOSCommand } from '../utils/command-invocation.js';
|
|
19
|
+
import { isNoticeShown, markNoticeShown, isTelemetryOptedOut } from './preferences.js';
|
|
20
|
+
let shownThisSession = false;
|
|
21
|
+
/**
|
|
22
|
+
* Show the first-run telemetry notice if it has never been displayed.
|
|
23
|
+
*
|
|
24
|
+
* Gate order is load-bearing: every suppression check runs BEFORE
|
|
25
|
+
* markNoticeShown(), so a non-human first run (--json / piped / CI) never
|
|
26
|
+
* consumes the one-time display. The flag is set only when the box is actually
|
|
27
|
+
* rendered, so a real human eventually sees it. Never throws.
|
|
28
|
+
*/
|
|
29
|
+
export function maybeShowTelemetryNotice() {
|
|
30
|
+
try {
|
|
31
|
+
if (shownThisSession)
|
|
32
|
+
return;
|
|
33
|
+
if (isJsonMode())
|
|
34
|
+
return; // suppress in --json / non-TTY / CI (output auto-switches to json)
|
|
35
|
+
if (isTelemetryOptedOut())
|
|
36
|
+
return; // already opted out — nothing to inform
|
|
37
|
+
if (isNoticeShown())
|
|
38
|
+
return; // already shown once, ever
|
|
39
|
+
const optOut = chalk.cyan(formatWorkOSCommand('telemetry opt-out'));
|
|
40
|
+
const inner = ` ${chalk.cyan('ℹ')} WorkOS collects anonymous CLI usage telemetry. Run ${optOut} to disable it. `;
|
|
41
|
+
renderStderrBox(inner, chalk.cyan);
|
|
42
|
+
// Set the per-session guard and persist ONLY after a successful render, so a
|
|
43
|
+
// render failure (caught below) lets a later command in this process retry
|
|
44
|
+
// rather than silently suppressing the notice for the rest of the session.
|
|
45
|
+
shownThisSession = true;
|
|
46
|
+
markNoticeShown();
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// Never block command execution.
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/** Reset session state (for testing). */
|
|
53
|
+
export function resetTelemetryNoticeState() {
|
|
54
|
+
shownThisSession = false;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=telemetry-notice.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry-notice.js","sourceRoot":"","sources":["../../src/lib/telemetry-notice.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEvF,IAAI,gBAAgB,GAAG,KAAK,CAAC;AAE7B;;;;;;;GAOG;AACH,MAAM,UAAU,wBAAwB;IACtC,IAAI,CAAC;QACH,IAAI,gBAAgB;YAAE,OAAO;QAC7B,IAAI,UAAU,EAAE;YAAE,OAAO,CAAC,mEAAmE;QAC7F,IAAI,mBAAmB,EAAE;YAAE,OAAO,CAAC,wCAAwC;QAC3E,IAAI,aAAa,EAAE;YAAE,OAAO,CAAC,2BAA2B;QAExD,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,mBAAmB,CAAC,CAAC,CAAC;QACpE,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,uDAAuD,MAAM,kBAAkB,CAAC;QACjH,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACnC,6EAA6E;QAC7E,2EAA2E;QAC3E,2EAA2E;QAC3E,gBAAgB,GAAG,IAAI,CAAC;QACxB,eAAe,EAAE,CAAC;IACpB,CAAC;IAAC,MAAM,CAAC;QACP,iCAAiC;IACnC,CAAC;AACH,CAAC;AAED,yCAAyC;AACzC,MAAM,UAAU,yBAAyB;IACvC,gBAAgB,GAAG,KAAK,CAAC;AAC3B,CAAC","sourcesContent":["/**\n * First-run telemetry notice.\n *\n * Prints a one-time, stderr-only box telling the user that anonymous CLI usage\n * telemetry is being collected and how to turn it off. Shown at most once ever\n * (backed by the persisted `noticeShownAt` timestamp in preferences.json), only\n * in interactive human mode, and never on the machine-readable path.\n *\n * Mirrors the structural pattern of unclaimed-warning.ts: a per-session guard,\n * a `!isJsonMode()` gate, the shared renderStderrBox helper, and a never-throws\n * contract so it can never block command execution. The one structural\n * difference is persistence — this notice writes `noticeShownAt` the first time\n * it actually displays so it never re-shows across runs.\n */\n\nimport chalk from 'chalk';\nimport { isJsonMode } from '../utils/output.js';\nimport { renderStderrBox } from '../utils/box.js';\nimport { formatWorkOSCommand } from '../utils/command-invocation.js';\nimport { isNoticeShown, markNoticeShown, isTelemetryOptedOut } from './preferences.js';\n\nlet shownThisSession = false;\n\n/**\n * Show the first-run telemetry notice if it has never been displayed.\n *\n * Gate order is load-bearing: every suppression check runs BEFORE\n * markNoticeShown(), so a non-human first run (--json / piped / CI) never\n * consumes the one-time display. The flag is set only when the box is actually\n * rendered, so a real human eventually sees it. Never throws.\n */\nexport function maybeShowTelemetryNotice(): void {\n try {\n if (shownThisSession) return;\n if (isJsonMode()) return; // suppress in --json / non-TTY / CI (output auto-switches to json)\n if (isTelemetryOptedOut()) return; // already opted out — nothing to inform\n if (isNoticeShown()) return; // already shown once, ever\n\n const optOut = chalk.cyan(formatWorkOSCommand('telemetry opt-out'));\n const inner = ` ${chalk.cyan('ℹ')} WorkOS collects anonymous CLI usage telemetry. Run ${optOut} to disable it. `;\n renderStderrBox(inner, chalk.cyan);\n // Set the per-session guard and persist ONLY after a successful render, so a\n // render failure (caught below) lets a later command in this process retry\n // rather than silently suppressing the notice for the rest of the session.\n shownThisSession = true;\n markNoticeShown();\n } catch {\n // Never block command execution.\n }\n}\n\n/** Reset session state (for testing). */\nexport function resetTelemetryNoticeState(): void {\n shownThisSession = false;\n}\n"]}
|
package/dist/run.d.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import type { Integration } from './lib/constants.js';
|
|
2
1
|
export type InstallerArgs = {
|
|
3
|
-
integration?: Integration;
|
|
4
2
|
debug?: boolean;
|
|
5
3
|
forceInstall?: boolean;
|
|
6
4
|
installDir?: string;
|
|
@@ -24,6 +22,8 @@ export type InstallerArgs = {
|
|
|
24
22
|
noGitCheck?: boolean;
|
|
25
23
|
gitCheck?: boolean;
|
|
26
24
|
direct?: boolean;
|
|
25
|
+
scaffold?: boolean;
|
|
26
|
+
pm?: string;
|
|
27
27
|
};
|
|
28
28
|
/**
|
|
29
29
|
* Main entry point for the wizard CLI.
|
package/dist/run.js
CHANGED
|
@@ -31,7 +31,6 @@ function buildOptions(argv) {
|
|
|
31
31
|
homepageUrl: merged.homepageUrl,
|
|
32
32
|
redirectUri: merged.redirectUri,
|
|
33
33
|
dashboard: merged.dashboard ?? false,
|
|
34
|
-
integration: merged.integration,
|
|
35
34
|
inspect: merged.inspect ?? false,
|
|
36
35
|
noValidate: merged.noValidate ?? merged.validate === false,
|
|
37
36
|
noCommit: merged.noCommit ?? merged.commit === false,
|
|
@@ -39,6 +38,8 @@ function buildOptions(argv) {
|
|
|
39
38
|
createPr: merged.createPr ?? false,
|
|
40
39
|
noGitCheck: merged.noGitCheck ?? merged.gitCheck === false,
|
|
41
40
|
direct: merged.direct ?? false,
|
|
41
|
+
scaffold: merged.scaffold ?? false,
|
|
42
|
+
pm: merged.pm,
|
|
42
43
|
emitter: createInstallerEventEmitter(), // Will be replaced in runWithCore
|
|
43
44
|
};
|
|
44
45
|
}
|
package/dist/run.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAErD,OAAO,EAAE,2BAA2B,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,YAAY,CAAC,mBAAmB,GAAG,EAAE,CAAC;AA8BtC;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAmB;IACpD,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,WAAW,CAAC,OAAO,CAAC,CAAC;AAC7B,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,IAAmB;IACvC,MAAM,OAAO,GAAG,eAAe,EAAE,CAAC;IAClC,MAAM,MAAM,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC;IAEvC,MAAM,UAAU,GAAG,iBAAiB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAExD,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,KAAK;QAC5B,YAAY,EAAE,MAAM,CAAC,YAAY,IAAI,KAAK;QAC1C,UAAU;QACV,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,KAAK;QAC5B,EAAE,EAAE,MAAM,CAAC,EAAE,IAAI,KAAK;QACtB,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,KAAK;QAClC,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,KAAK;QACpC,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,KAAK;QAChC,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,QAAQ,KAAK,KAAK;QAC1D,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,MAAM,KAAK,KAAK;QACpD,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,MAAM,KAAK,KAAK;QACpD,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,KAAK;QAClC,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,QAAQ,KAAK,KAAK;QAC1D,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,KAAK;QAC9B,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,KAAK;QAClC,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,OAAO,EAAE,2BAA2B,EAAE,EAAE,kCAAkC;KAC3E,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,iBAAiB,CAAC,GAAY;IACrC,IAAI,CAAC,GAAG;QAAE,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC;IAC/B,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC;AACpE,CAAC","sourcesContent":["import { readEnvironment } from './utils/environment.js';\nimport { runWithCore } from './lib/run-with-core.js';\nimport type { InstallerOptions } from './utils/types.js';\nimport { createInstallerEventEmitter } from './lib/events.js';\nimport path from 'path';\nimport { EventEmitter } from 'events';\n\nEventEmitter.defaultMaxListeners = 50;\n\nexport type InstallerArgs = {\n debug?: boolean;\n forceInstall?: boolean;\n installDir?: string;\n default?: boolean;\n local?: boolean;\n ci?: boolean;\n skipAuth?: boolean;\n apiKey?: string;\n clientId?: string;\n homepageUrl?: string;\n redirectUri?: string;\n dashboard?: boolean;\n inspect?: boolean;\n noValidate?: boolean;\n validate?: boolean;\n noCommit?: boolean;\n commit?: boolean;\n noBranch?: boolean;\n branch?: boolean;\n createPr?: boolean;\n noGitCheck?: boolean;\n gitCheck?: boolean;\n direct?: boolean;\n scaffold?: boolean;\n pm?: string;\n};\n\n/**\n * Main entry point for the wizard CLI.\n * Builds options from args and delegates to the core.\n */\nexport async function runInstaller(argv: InstallerArgs): Promise<void> {\n const options = buildOptions(argv);\n await runWithCore(options);\n}\n\n/**\n * Build InstallerOptions from CLI args and environment.\n */\nfunction buildOptions(argv: InstallerArgs): InstallerOptions {\n const envArgs = readEnvironment();\n const merged = { ...argv, ...envArgs };\n\n const installDir = resolveInstallDir(merged.installDir);\n\n return {\n debug: merged.debug ?? false,\n forceInstall: merged.forceInstall ?? false,\n installDir,\n local: merged.local ?? false,\n ci: merged.ci ?? false,\n skipAuth: merged.skipAuth ?? false,\n apiKey: merged.apiKey,\n clientId: merged.clientId,\n homepageUrl: merged.homepageUrl,\n redirectUri: merged.redirectUri,\n dashboard: merged.dashboard ?? false,\n inspect: merged.inspect ?? false,\n noValidate: merged.noValidate ?? merged.validate === false,\n noCommit: merged.noCommit ?? merged.commit === false,\n noBranch: merged.noBranch ?? merged.branch === false,\n createPr: merged.createPr ?? false,\n noGitCheck: merged.noGitCheck ?? merged.gitCheck === false,\n direct: merged.direct ?? false,\n scaffold: merged.scaffold ?? false,\n pm: merged.pm,\n emitter: createInstallerEventEmitter(), // Will be replaced in runWithCore\n };\n}\n\n/**\n * Resolve install directory to absolute path.\n */\nfunction resolveInstallDir(dir?: string): string {\n if (!dir) return process.cwd();\n return path.isAbsolute(dir) ? dir : path.join(process.cwd(), dir);\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { setInsecureStorage } from '../lib/credentials.js';
|
|
2
|
+
import { setInsecureConfigStorage } from '../lib/config-store.js';
|
|
3
|
+
// Subprocess integration tests import bin.ts directly, which initializes
|
|
4
|
+
// telemetry before command options are parsed. Flip the existing storage seams
|
|
5
|
+
// first so startup auth lookup stays inside the test's temporary HOME instead
|
|
6
|
+
// of touching the host keychain.
|
|
7
|
+
setInsecureStorage(true);
|
|
8
|
+
setInsecureConfigStorage(true);
|
|
9
|
+
//# sourceMappingURL=force-insecure-storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"force-insecure-storage.js","sourceRoot":"","sources":["../../src/test/force-insecure-storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAElE,yEAAyE;AACzE,+EAA+E;AAC/E,8EAA8E;AAC9E,iCAAiC;AACjC,kBAAkB,CAAC,IAAI,CAAC,CAAC;AACzB,wBAAwB,CAAC,IAAI,CAAC,CAAC","sourcesContent":["import { setInsecureStorage } from '../lib/credentials.js';\nimport { setInsecureConfigStorage } from '../lib/config-store.js';\n\n// Subprocess integration tests import bin.ts directly, which initializes\n// telemetry before command options are parsed. Flip the existing storage seams\n// first so startup auth lookup stays inside the test's temporary HOME instead\n// of touching the host keychain.\nsetInsecureStorage(true);\nsetInsecureConfigStorage(true);\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { vi } from 'vitest';
|
|
2
|
+
/**
|
|
3
|
+
* Global test setup — runs before every spec file.
|
|
4
|
+
*
|
|
5
|
+
* Replaces @napi-rs/keyring with an in-memory implementation so the test
|
|
6
|
+
* suite can NEVER touch the real OS keychain. clearCredentials() and
|
|
7
|
+
* saveCredentials() operate on the live `workos-cli` keychain entry even when
|
|
8
|
+
* file-fallback storage is forced, so an un-mocked spec would wipe a
|
|
9
|
+
* developer's real CLI login (this happened — that's why this exists).
|
|
10
|
+
*
|
|
11
|
+
* Specs that need richer keyring behaviour (e.g. simulating an unavailable
|
|
12
|
+
* keychain) still declare their own vi.mock('@napi-rs/keyring', ...); a
|
|
13
|
+
* per-file mock overrides this global default. The __IS_TEST_MOCK__ sentinel
|
|
14
|
+
* is asserted by src/test/keyring-isolation.spec.ts so removing this setup
|
|
15
|
+
* fails CI instead of silently re-arming the footgun.
|
|
16
|
+
*/
|
|
17
|
+
vi.mock('@napi-rs/keyring', () => {
|
|
18
|
+
const store = new Map();
|
|
19
|
+
return {
|
|
20
|
+
__IS_TEST_MOCK__: true,
|
|
21
|
+
Entry: class MockEntry {
|
|
22
|
+
key;
|
|
23
|
+
constructor(service, account) {
|
|
24
|
+
this.key = `${service}:${account}`;
|
|
25
|
+
}
|
|
26
|
+
getPassword() {
|
|
27
|
+
return store.get(this.key) ?? null;
|
|
28
|
+
}
|
|
29
|
+
setPassword(password) {
|
|
30
|
+
store.set(this.key, password);
|
|
31
|
+
}
|
|
32
|
+
deletePassword() {
|
|
33
|
+
store.delete(this.key);
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
//# sourceMappingURL=setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/test/setup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE5B;;;;;;;;;;;;;;GAcG;AACH,EAAE,CAAC,IAAI,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAC/B,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;IACxC,OAAO;QACL,gBAAgB,EAAE,IAAI;QACtB,KAAK,EAAE,MAAM,SAAS;YACZ,GAAG,CAAS;YAEpB,YAAY,OAAe,EAAE,OAAe;gBAC1C,IAAI,CAAC,GAAG,GAAG,GAAG,OAAO,IAAI,OAAO,EAAE,CAAC;YACrC,CAAC;YAED,WAAW;gBACT,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;YACrC,CAAC;YAED,WAAW,CAAC,QAAgB;gBAC1B,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;YAChC,CAAC;YAED,cAAc;gBACZ,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACzB,CAAC;SACF;KACF,CAAC;AACJ,CAAC,CAAC,CAAC","sourcesContent":["import { vi } from 'vitest';\n\n/**\n * Global test setup — runs before every spec file.\n *\n * Replaces @napi-rs/keyring with an in-memory implementation so the test\n * suite can NEVER touch the real OS keychain. clearCredentials() and\n * saveCredentials() operate on the live `workos-cli` keychain entry even when\n * file-fallback storage is forced, so an un-mocked spec would wipe a\n * developer's real CLI login (this happened — that's why this exists).\n *\n * Specs that need richer keyring behaviour (e.g. simulating an unavailable\n * keychain) still declare their own vi.mock('@napi-rs/keyring', ...); a\n * per-file mock overrides this global default. The __IS_TEST_MOCK__ sentinel\n * is asserted by src/test/keyring-isolation.spec.ts so removing this setup\n * fails CI instead of silently re-arming the footgun.\n */\nvi.mock('@napi-rs/keyring', () => {\n const store = new Map<string, string>();\n return {\n __IS_TEST_MOCK__: true,\n Entry: class MockEntry {\n private key: string;\n\n constructor(service: string, account: string) {\n this.key = `${service}:${account}`;\n }\n\n getPassword(): string | null {\n return store.get(this.key) ?? null;\n }\n\n setPassword(password: string): void {\n store.set(this.key, password);\n }\n\n deletePassword(): void {\n store.delete(this.key);\n }\n },\n };\n});\n"]}
|
|
@@ -1,24 +1,65 @@
|
|
|
1
|
+
import type { AuthMode, TerminationReason } from './telemetry-types.js';
|
|
1
2
|
export declare class Analytics {
|
|
2
3
|
private tags;
|
|
3
4
|
private sessionId;
|
|
4
5
|
private sessionStartTime;
|
|
5
6
|
private distinctId?;
|
|
7
|
+
private mode?;
|
|
8
|
+
private authMode;
|
|
6
9
|
private totalInputTokens;
|
|
7
10
|
private totalOutputTokens;
|
|
8
11
|
private agentIterations;
|
|
9
12
|
constructor();
|
|
10
13
|
setDistinctId(distinctId: string): void;
|
|
11
14
|
setAccessToken(token: string): void;
|
|
15
|
+
setApiKeyAuth(apiKey: string): void;
|
|
16
|
+
setClaimTokenAuth(clientId: string, claimToken: string): void;
|
|
17
|
+
/**
|
|
18
|
+
* Set the auth mode explicitly for special cases. Normal CLI flows should use
|
|
19
|
+
* `configureAuthFromAvailableSources()` so transport and auth.mode stay aligned.
|
|
20
|
+
*/
|
|
21
|
+
setAuthMode(mode: AuthMode): void;
|
|
12
22
|
setGatewayUrl(url: string): void;
|
|
23
|
+
private isEnabled;
|
|
24
|
+
/**
|
|
25
|
+
* Configure telemetry transport and auth.mode from all available CLI auth
|
|
26
|
+
* sources. Priority: stored JWT, unclaimed-environment claim token, active
|
|
27
|
+
* environment API key, then WORKOS_API_KEY.
|
|
28
|
+
*/
|
|
29
|
+
configureAuthFromAvailableSources(): AuthMode;
|
|
30
|
+
/**
|
|
31
|
+
* Initialize telemetry for non-installer commands.
|
|
32
|
+
* Sets telemetry URL from default config and loads auth credentials.
|
|
33
|
+
*/
|
|
34
|
+
initForNonInstaller(): void;
|
|
13
35
|
setTag(key: string, value: string | boolean | number | null | undefined): void;
|
|
14
36
|
capture(eventName: string, properties?: Record<string, unknown>): void;
|
|
15
37
|
captureException(error: Error, properties?: Record<string, unknown>): void;
|
|
16
38
|
getFeatureFlag(_flagKey: string): Promise<string | boolean | undefined>;
|
|
39
|
+
/** All capture methods that record error details MUST go through this. */
|
|
40
|
+
private extractErrorFields;
|
|
41
|
+
private detectCiProvider;
|
|
42
|
+
private getEnvFingerprint;
|
|
17
43
|
sessionStart(mode: 'cli' | 'tui' | 'headless', version: string): void;
|
|
18
44
|
stepCompleted(name: string, durationMs: number, success: boolean, error?: Error): void;
|
|
19
45
|
toolCalled(toolName: string, durationMs: number, success: boolean): void;
|
|
20
46
|
llmRequest(model: string, inputTokens: number, outputTokens: number): void;
|
|
21
47
|
incrementAgentIterations(): void;
|
|
48
|
+
emitCommandEvent(name: string, durationMs: number, success: boolean, options?: {
|
|
49
|
+
error?: Error;
|
|
50
|
+
flags?: string[];
|
|
51
|
+
reason?: TerminationReason;
|
|
52
|
+
errorCode?: string;
|
|
53
|
+
apiContext?: {
|
|
54
|
+
status?: number;
|
|
55
|
+
code?: string;
|
|
56
|
+
resource?: string;
|
|
57
|
+
};
|
|
58
|
+
}): void;
|
|
59
|
+
captureUnhandledCrash(error: Error, options?: {
|
|
60
|
+
command?: string;
|
|
61
|
+
version?: string;
|
|
62
|
+
}): void;
|
|
22
63
|
shutdown(status: 'success' | 'error' | 'cancelled'): Promise<void>;
|
|
23
64
|
}
|
|
24
65
|
export declare const analytics: Analytics;
|