Merge branch 'main' into upstream/fix-register-claude-md
This commit is contained in:
@@ -9,6 +9,7 @@ const STEPS: Record<
|
||||
string,
|
||||
() => Promise<{ run: (args: string[]) => Promise<void> }>
|
||||
> = {
|
||||
timezone: () => import('./timezone.js'),
|
||||
environment: () => import('./environment.js'),
|
||||
container: () => import('./container.js'),
|
||||
groups: () => import('./groups.js'),
|
||||
|
||||
67
setup/timezone.ts
Normal file
67
setup/timezone.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* Step: timezone — Detect, validate, and persist the user's timezone.
|
||||
* Writes TZ to .env if a valid IANA timezone is resolved.
|
||||
* Emits NEEDS_USER_INPUT=true when autodetection fails.
|
||||
*/
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
import { isValidTimezone } from '../src/timezone.js';
|
||||
import { logger } from '../src/logger.js';
|
||||
import { emitStatus } from './status.js';
|
||||
|
||||
export async function run(args: string[]): Promise<void> {
|
||||
const projectRoot = process.cwd();
|
||||
const envFile = path.join(projectRoot, '.env');
|
||||
|
||||
// Check what's already in .env
|
||||
let envFileTz: string | undefined;
|
||||
if (fs.existsSync(envFile)) {
|
||||
const content = fs.readFileSync(envFile, 'utf-8');
|
||||
const match = content.match(/^TZ=(.+)$/m);
|
||||
if (match) envFileTz = match[1].trim().replace(/^["']|["']$/g, '');
|
||||
}
|
||||
|
||||
const systemTz = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||
const envTz = process.env.TZ;
|
||||
|
||||
// Accept --tz flag from CLI (used when setup skill collects from user)
|
||||
const tzFlagIdx = args.indexOf('--tz');
|
||||
const userTz = tzFlagIdx !== -1 ? args[tzFlagIdx + 1] : undefined;
|
||||
|
||||
// Resolve: user-provided > .env > process.env > system autodetect
|
||||
let resolvedTz: string | undefined;
|
||||
for (const candidate of [userTz, envFileTz, envTz, systemTz]) {
|
||||
if (candidate && isValidTimezone(candidate)) {
|
||||
resolvedTz = candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const needsUserInput = !resolvedTz;
|
||||
|
||||
if (resolvedTz && resolvedTz !== envFileTz) {
|
||||
// Write/update TZ in .env
|
||||
if (fs.existsSync(envFile)) {
|
||||
let content = fs.readFileSync(envFile, 'utf-8');
|
||||
if (/^TZ=/m.test(content)) {
|
||||
content = content.replace(/^TZ=.*$/m, `TZ=${resolvedTz}`);
|
||||
} else {
|
||||
content = content.trimEnd() + `\nTZ=${resolvedTz}\n`;
|
||||
}
|
||||
fs.writeFileSync(envFile, content);
|
||||
} else {
|
||||
fs.writeFileSync(envFile, `TZ=${resolvedTz}\n`);
|
||||
}
|
||||
logger.info({ timezone: resolvedTz }, 'Set TZ in .env');
|
||||
}
|
||||
|
||||
emitStatus('TIMEZONE', {
|
||||
SYSTEM_TZ: systemTz || 'unknown',
|
||||
ENV_TZ: envTz || 'unset',
|
||||
ENV_FILE_TZ: envFileTz || 'unset',
|
||||
RESOLVED_TZ: resolvedTz || 'none',
|
||||
NEEDS_USER_INPUT: needsUserInput,
|
||||
STATUS: needsUserInput ? 'needs_input' : 'success',
|
||||
});
|
||||
}
|
||||
@@ -101,7 +101,7 @@ export async function run(_args: string[]): Promise<void> {
|
||||
const envFile = path.join(projectRoot, '.env');
|
||||
if (fs.existsSync(envFile)) {
|
||||
const envContent = fs.readFileSync(envFile, 'utf-8');
|
||||
if (/^(CLAUDE_CODE_OAUTH_TOKEN|ANTHROPIC_API_KEY)=/m.test(envContent)) {
|
||||
if (/^(CLAUDE_CODE_OAUTH_TOKEN|ANTHROPIC_API_KEY|ONECLI_URL)=/m.test(envContent)) {
|
||||
credentials = 'configured';
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user