Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 48 additions & 6 deletions scripts/setupNewProducts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'

Expand Down Expand Up @@ -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)
}
Expand All @@ -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) {
Expand All @@ -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))
Expand Down Expand Up @@ -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
Expand All @@ -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<string, string> = sdkPackage?.dependencies ?? {}
const hasInternal = Object.keys(deps).some(k =>
k.startsWith('@scaleway-internal/sdk-'),
Expand All @@ -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 ?? {}

Expand Down Expand Up @@ -226,6 +266,8 @@ async function main(): Promise<number> {
updateSdkPackageJson(SDK_PACKAGE_JSON, newProducts, scope)
info('')

ensureProductFiles(newProducts)

// 4) alias
info('📝 Step 4: Generating SDK exports…')
runCommand('pnpm run generateAlias', 'Generate SDK exports')
Expand Down