From 68955e16b3b9f03bc2913fa859a8e7207154a805 Mon Sep 17 00:00:00 2001 From: Jonathan Remy Date: Tue, 18 Nov 2025 07:30:56 +0100 Subject: [PATCH] feat: update setupNewProducts script --- scripts/setupNewProducts.ts | 54 ++++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/scripts/setupNewProducts.ts b/scripts/setupNewProducts.ts index e14eec9db..e70f9214b 100644 --- a/scripts/setupNewProducts.ts +++ b/scripts/setupNewProducts.ts @@ -20,7 +20,6 @@ import { cwd } from 'node:process' import type { ParseArgsConfig } from 'node:util' import { parseArgs } from 'node:util' import { snakeToSlug } from './helpers' -import type { PackageJSON } from './types.js' type Scope = '@scaleway' | '@scaleway-internal' @@ -48,6 +47,21 @@ interface Product { hasPackageJson: boolean } +const REQUIRED_PRODUCT_FILES = [ + 'package.json', + 'tsconfig.json', + 'tsconfig.build.json', + 'vite.config.ts', + 'README.md', +] as const + +const OPTIONAL_PRODUCT_FILES: Record< + string, + Set<(typeof REQUIRED_PRODUCT_FILES)[number]> +> = { + std: new Set(['README.md']), +} + const log = (...args: unknown[]) => { if (VERBOSE) console.log(...args) } @@ -64,7 +78,7 @@ function safeReadJson(path: string): unknown { } function writeJsonIfChanged(path: string, data: unknown) { - const newContent = `${JSON.stringify(data, null, 2)}\n` + const newContent = JSON.stringify(data, null, 2) + '\n' const oldContent = existsSync(path) ? readFileSync(path, 'utf8') : '' if (oldContent !== newContent) { if (DRY_RUN) { @@ -82,8 +96,7 @@ function walkHasGenFiles(root: string): boolean { if (!existsSync(root)) return false const stack = [root] while (stack.length) { - const p = stack.pop() - if (!p) break + const p = stack.pop()! const st = statSync(p) if (st.isDirectory()) { for (const name of readdirSync(p)) stack.push(join(p, name)) @@ -113,6 +126,33 @@ function detectNewProducts(products: Product[]): Product[] { return products.filter(p => p.hasGenFiles && !p.hasPackageJson) } +function ensureProductFiles(products: Product[]) { + const missingFilesByProduct: string[] = [] + + for (const product of products) { + const optionalFiles = OPTIONAL_PRODUCT_FILES[product.name] ?? new Set() + + for (const fileName of REQUIRED_PRODUCT_FILES) { + if (optionalFiles.has(fileName)) continue + + const filePath = join(product.path, fileName) + if (!existsSync(filePath)) { + missingFilesByProduct.push(`${product.name}/${fileName}`) + } + } + } + + if (missingFilesByProduct.length > 0) { + throw new Error( + [ + 'Missing required configuration files for new products:', + ...missingFilesByProduct.map(f => ` • ${f}`), + 'Please re-run `pnpm run generatePackages` and `pnpm run generateAlias` locally to regenerate the missing files before committing.', + ].join('\n'), + ) + } +} + function detectPackageScope(sdkPackageJsonPath: string): Scope { if (values.scope) { const s = String(values.scope) as Scope @@ -122,7 +162,7 @@ function detectPackageScope(sdkPackageJsonPath: string): Scope { warn('⚠️ SDK package.json not found, using @scaleway scope') return '@scaleway' } - const sdkPackage = safeReadJson(sdkPackageJsonPath) as PackageJSON + const sdkPackage = safeReadJson(sdkPackageJsonPath) as any const deps: Record = sdkPackage?.dependencies ?? {} const hasInternal = Object.keys(deps).some(k => k.startsWith('@scaleway-internal/sdk-'), @@ -140,7 +180,7 @@ function updateSdkPackageJson( return { added: [] } } - const sdkPackage = safeReadJson(sdkPackageJsonPath) as PackageJSON + const sdkPackage = safeReadJson(sdkPackageJsonPath) as any sdkPackage.dependencies = sdkPackage.dependencies ?? {} sdkPackage.devDependencies = sdkPackage.devDependencies ?? {} @@ -226,6 +266,8 @@ async function main(): Promise { updateSdkPackageJson(SDK_PACKAGE_JSON, newProducts, scope) info('') + ensureProductFiles(newProducts) + // 4) alias info('📝 Step 4: Generating SDK exports…') runCommand('pnpm run generateAlias', 'Generate SDK exports')