diff --git a/.npmrc b/.npmrc index 801200cc7a..bd371de4a5 100644 --- a/.npmrc +++ b/.npmrc @@ -130,7 +130,6 @@ link-workspace-packages=false # deep ## script to handle this. ## sync-injected-deps-after-scripts[]=build:pkg -sync-injected-deps-after-scripts[]=build:infra sync-injected-deps-after-scripts[]=build:glint sync-injected-deps-after-scripts[]=sync diff --git a/contributing/setting-up-the-project.md b/contributing/setting-up-the-project.md index ee51a47c9d..906b4afbbd 100644 --- a/contributing/setting-up-the-project.md +++ b/contributing/setting-up-the-project.md @@ -73,7 +73,30 @@ pnpm dlx @warp-drive/holodeck ensure-cert ## Building the project -The project's packages will build whenever `pnpm install` is run. +The project's packages will build whenever `pnpm install` is run. They can be rebuilt by running `pnpm prepare`. + +Both `install` and `prepare` will ensure turbo cache is ignored so that pnpm will automatically update "hardlinks" for +the build output files in the node_modules directory of the various other packages and test apps that depend upon the package. + +However, this is pretty slow for development, so a fast albeit slightly manual approach is available for development +by running the below commands in order: + +From the project root: + +- install: `pnpm install` - installs all dependencies and sets up initial hardlinks +- start: `pnpm start` - starts the build for every public package in watch mode + +Then, from an individual test app: + +- `pnpm start` - starts the build for test assets in watch mode +- `pnpm test:start` - launches a test server (and by opens a browser window for debugging them) + +Because the project uses hardlinks, even though the packages are rebuilding, the test apps won't be able +to see the results of the change in many scenarios unless the hardlinks are regenerated. + +At anypoint, run `pnpm sync` from the root to regenerate the hardlinks. The test app server may +pick up this change automatically, but if it does not saving any file (even without changing it) +in the test app will trigger a rebuild. ## Run some commands diff --git a/internal-tooling/README.md b/internal-tooling/README.md index 3b44d78ea8..91f164de94 100644 --- a/internal-tooling/README.md +++ b/internal-tooling/README.md @@ -5,18 +5,38 @@ for use with the monorepo. These scripts can be run as bin-scripts from root. -## bun sync-logos +### sync-all + +```sh +bun sync-all +``` + +Will run all of the other available scripts. + +### sync-logos + +```sh +bun sync-logos +``` Will sync the logo directory from root to each public package and ensure that the logos directory is included in published files. -## bun sync-license +### sync-license + +```sh +bun sync-license +``` Will sync the LICENSE.md file from root to each public package and ensure that the license is both set to `MIT` in the package.json and included in the published files for each package. -## bun sync-references +### sync-references + +```sh +bun sync-references +``` Will ensure that `paths` and `references` are both correctly specified in tsconfig.json for any other workspace package specified by package.json @@ -26,3 +46,12 @@ Will also ensure the proper settings for composite etc. are in use. For packages that should emit types (any non-test app package) it will ensure that the declarationDir is added to the files array in package.json. + +### sync-scripts + +```sh +bun sync-scripts +``` + +Will ensure that scripts enumerated in package.json which should be the same +throughout the monorepo match expected configuration. diff --git a/internal-tooling/package.json b/internal-tooling/package.json index e4e0d85ab7..541f86926d 100644 --- a/internal-tooling/package.json +++ b/internal-tooling/package.json @@ -10,7 +10,9 @@ "bin": { "sync-logos": "src/sync-logos.ts", "sync-license": "src/sync-license.ts", - "sync-references": "src/sync-references.ts" + "sync-references": "src/sync-references.ts", + "sync-scripts": "src/sync-scripts.ts", + "sync-all": "src/sync-all.ts" }, "dependencies": { "@types/bun": "^1.2.4", diff --git a/internal-tooling/src/sync-all.ts b/internal-tooling/src/sync-all.ts new file mode 100755 index 0000000000..5190db964e --- /dev/null +++ b/internal-tooling/src/sync-all.ts @@ -0,0 +1,4 @@ +#! /usr/bin/env bun +import { main } from './tasks/sync-all'; + +main(); diff --git a/internal-tooling/src/sync-licence.ts b/internal-tooling/src/sync-licence.ts new file mode 100644 index 0000000000..bab8d0906e --- /dev/null +++ b/internal-tooling/src/sync-licence.ts @@ -0,0 +1,4 @@ +#! /usr/bin/env bun +import { main } from './tasks/sync-license'; + +main(); diff --git a/internal-tooling/src/sync-logos.ts b/internal-tooling/src/sync-logos.ts index 390b600648..558864d193 100755 --- a/internal-tooling/src/sync-logos.ts +++ b/internal-tooling/src/sync-logos.ts @@ -1,87 +1,4 @@ #! /usr/bin/env bun - -import path from 'path'; -import fs from 'fs'; -import debug from 'debug'; -import chalk from 'chalk'; -import type { BunFile } from 'bun'; -import { getMonorepoRoot, getPackageJson } from './-utils'; - -const log = debug('wd:sync-logos'); - -async function copyFiles({ - packageDir, - packageLogosDir, - logosDir, - isCopied, -}: { - packageDir: string; - packageLogosDir: string; - logosDir: string; - isCopied: boolean; -}) { - // if we are in copy mode, remove any existing symlink and copy the files - if (isCopied) { - fs.rmSync(packageLogosDir, { recursive: true, force: true }); - log(`\t\t\t🗑️ Deleted existing copy of ${packageDir}/logos`); - } - fs.mkdirSync(packageLogosDir, { recursive: true }); - log(`\t\t\t📁 Created ${packageDir}/logos`); - - for (const logo of fs.readdirSync(logosDir, { recursive: true, encoding: 'utf-8' })) { - const logoPath = path.join(logosDir, logo); - const destPath = path.join(packageLogosDir, logo); - fs.copyFileSync(logoPath, destPath); - log(`\t\t\t📁 Copied ${logo} to ${packageDir}/logos`); - } -} - -async function updatePackageJson({ pkg, file, nicePath }: { pkg: any; file: BunFile; path: string; nicePath: string }) { - // ensure "files" field in package.json includes "logos" - if (!pkg.files) { - pkg.files = ['logos']; - await file.write(JSON.stringify(pkg, null, 2)); - log(`\t\t📝 Added "logos" to "files" in ${nicePath}`); - } else if (!pkg.files.includes('logos')) { - pkg.files.push('logos'); - await file.write(JSON.stringify(pkg, null, 2)); - log(`\t\t📝 Added "logos" to "files" in ${nicePath}`); - } -} - -async function main() { - log( - `\n\t${chalk.gray('=').repeat(60)}\n\t\t${chalk.magentaBright('@warp-drive/')}${chalk.greenBright('internal-tooling')} Sync Logos\n\t${chalk.gray('=').repeat(60)}\n\n\t\t${chalk.gray(`Syncing logo files from monorepo root to each public package`)}\n\n` - ); - const monorepoRoot = await getMonorepoRoot(); - - // sync the logos from the monorepo root to each - // package directory that has a logos directory - - const logosDir = path.join(monorepoRoot, 'logos'); - const packagesDir = path.join(monorepoRoot, 'packages'); - - for (const packageDir of fs.readdirSync(packagesDir)) { - const packageLogosDir = path.join(packagesDir, packageDir, 'logos'); - const isCopied = fs.existsSync(packageLogosDir); - const details = await getPackageJson({ packageDir, packagesDir }); - - if (details.pkg.private) { - log(`\t\t🔒 Skipping private package ${details.nicePath}`); - continue; - } - - log(`\t\t🔁 Syncing logos to ${packageDir}`); - - await copyFiles({ - packageDir, - packageLogosDir, - logosDir, - isCopied, - }); - - await updatePackageJson(details); - } -} +import { main } from './tasks/sync-logos'; main(); diff --git a/internal-tooling/src/sync-references.ts b/internal-tooling/src/sync-references.ts index 53a01ac205..662bba5945 100755 --- a/internal-tooling/src/sync-references.ts +++ b/internal-tooling/src/sync-references.ts @@ -1,292 +1,4 @@ #! /usr/bin/env bun - -import debug from 'debug'; -import path from 'path'; -import chalk from 'chalk'; -import { - runPrettier, - walkPackages, - type ProjectPackage, - type ProjectPackageWithTsConfig, - type TsConfigFile, -} from './-utils'; - -const log = debug('wd:sync-references'); - -function isCleanRange(range: string) { - return !range.includes(' ') && !range.includes('||') && !range.includes('>') && !range.includes('<'); -} - -function cleanupAndGetReferencedPackages(project: ProjectPackage) { - const packages = new Set(); - const { pkg } = project; - let edited = false; - - for (const packageName of Object.keys(pkg.dependencies ?? {})) { - if (project.packages.has(packageName)) { - packages.add(packageName); - } - } - - for (const packageName of Object.keys(pkg.peerDependencies ?? {})) { - if (project.packages.has(packageName)) { - packages.add(packageName); - } - if (pkg.dependencies?.[packageName]) { - log(`\t\t🚨 ${project.pkg.name} has ${packageName} in both dependencies and peerDependencies`); - delete pkg.dependencies[packageName]; - log(`\t\t🔧 Removed ${packageName} from dependencies`); - edited = true; - } - if (!pkg.devDependencies?.[packageName]) { - log(`\t\t🚨 ${project.pkg.name} has ${packageName} in peerDependencies but not in devDependencies`); - if (!project.packages.has(packageName) && !isCleanRange(pkg.peerDependencies![packageName])) { - throw new Error( - `Unable to fix missing devDependency on PeerDependency ${packageName} as it is not a workspace package and specifies a range.` - ); - } - pkg.devDependencies ??= {}; - pkg.devDependencies[packageName] = project.packages.has(packageName) - ? `workspace:${packageName}` - : pkg.peerDependencies![packageName]; - log(`\t\t🔧 Added "${packageName}": "${pkg.devDependencies![packageName]}" to devDependencies`); - edited = true; - } - } - - for (const packageName of Object.keys(project.pkg.devDependencies ?? {})) { - if (project.packages.has(packageName)) { - packages.add(packageName); - } - } - - return { referenced: packages, edited }; -} - -function getRelativePath(pkgA: ProjectPackage, pkgB: ProjectPackage) { - return path.relative(pkgA.project.dir, pkgB.project.dir); -} - -function hasReference(srcPkg: ProjectPackageWithTsConfig, relPkg: ProjectPackageWithTsConfig) { - const referencePath = getRelativePath(srcPkg, relPkg); - if (!srcPkg.tsconfig.references) { - return false; - } - return srcPkg.tsconfig.references.some((ref) => ref.path === referencePath); -} - -function hasPaths(srcPkg: ProjectPackageWithTsConfig, relPkg: ProjectPackageWithTsConfig) { - if (!srcPkg.tsconfig.compilerOptions?.paths) { - return false; - } - const dep = relPkg.pkg.name; - const hasPrimary = !!srcPkg.tsconfig.compilerOptions.paths[dep]; - const hasWildcard = !!srcPkg.tsconfig.compilerOptions.paths[`${dep}/*`]; - - return hasPrimary && hasWildcard; -} - -function addPaths(srcPkg: ProjectPackageWithTsConfig, relPkg: ProjectPackageWithTsConfig) { - const typesDir = relPkg.tsconfig.compilerOptions?.declarationDir; - - if (!typesDir) { - throw new Error(`Missing compilerOptions.declarationDir in ${relPkg.tsconfigPath}`); - } - - const relativePath = getRelativePath(srcPkg, relPkg); - - srcPkg.tsconfig.compilerOptions!.paths![relPkg.pkg.name] = [`${relativePath}/${typesDir}`]; - srcPkg.tsconfig.compilerOptions!.paths![`${relPkg.pkg.name}/*`] = [`${relativePath}/${typesDir}/*`]; -} - -function validateDesiredTsConfigSettings(project: ProjectPackageWithTsConfig) { - // ensure that the tsconfig.json has the correct settings for our monorepo - const { tsconfig } = project; - let { compilerOptions } = tsconfig; - let edited = false; - - //////////////////////////// - // All Projects - //////////////////////////// - const BaseDefaults: Exclude = { - allowImportingTsExtensions: true, - // we use isolatedDeclarations in some projects, but not all - // once we use in all set this to false - // and set isolatedDeclarations to true in the projects - // allowJs: false, - // isolatedDeclarations: true, - // verbatimModuleSyntax: true, - checkJs: false, - baseUrl: '.', - composite: true, - declaration: true, - declarationDir: 'unstable-preview-types', - declarationMap: true, - emitDeclarationOnly: true, - erasableSyntaxOnly: true, - experimentalDecorators: true, - incremental: true, - inlineSourceMap: true, - inlineSources: true, - lib: ['ESNext'], - module: 'ESNext', - moduleDetection: 'force', - moduleResolution: 'bundler', - noEmit: undefined, - pretty: true, - rootDir: 'src', - skipLibCheck: true, - strict: true, - target: 'ESNext', - } as const; - - if (!compilerOptions) { - compilerOptions = tsconfig.compilerOptions = {}; - edited = true; - log(`\t\t🔧 Added compilerOptions hash to tsconfig.json`); - } - - const defaultKeys = Object.keys(BaseDefaults) as (keyof typeof BaseDefaults)[]; - for (const key of defaultKeys) { - const defaultValue = BaseDefaults[key]!; - if (!(key in compilerOptions)) { - // @ts-expect-error - compilerOptions[key] = defaultValue; - edited = true; - log(`\t\t🔧 Added "${key}": ${JSON.stringify(defaultValue)} in compilerOptions in tsconfig.json`); - continue; - } - - if (typeof defaultValue === 'boolean') { - if (compilerOptions[key] !== defaultValue) { - // @ts-expect-error - compilerOptions[key] = defaultValue; - edited = true; - log(`\t\t🔧 Updated "${key}" to ${defaultValue ? 'true' : 'false'} in compilerOptions in tsconfig.json`); - } - } - - if (typeof defaultValue === 'undefined') { - if (compilerOptions[key] !== defaultValue) { - delete compilerOptions[key]; - edited = true; - log(`\t\t🔧 Deleted "${key}" from compilerOptions in tsconfig.json`); - } - } - - if (typeof defaultValue === 'string') { - if (compilerOptions[key] !== defaultValue) { - log( - `\t\t⚠️ Non-default value "${compilerOptions[key]}" for "${key}" in compilerOptions in tsconfig.json, default is "${defaultValue}"` - ); - } - } - - if (Array.isArray(defaultValue)) { - // TODO probably nothing, but maybe a deep comparison here - // if (compilerOptions[key] !== defaultValue) { - // log( - // `\t\t⚠️ Non-default value "${JSON.stringify(compilerOptions[key])}" for "${key}" in compilerOptions in tsconfig.json, default is "${JSON.stringify( - // defaultValue - // )}"` - // ); - // } - } - } - - return edited; -} - -async function main() { - log( - `\n\t${chalk.gray('=').repeat(60)}\n\t\t${chalk.magentaBright('@warp-drive/')}${chalk.greenBright('internal-tooling')} Sync TypeScript References\n\t${chalk.gray('=').repeat(60)}\n\n\t\t${chalk.gray(`Syncing Project References`)}\n\n` - ); - let anyFileEdited = false; - - await walkPackages(async (project: ProjectPackage, projects: Map) => { - log(`\t📦 Syncing ${project.pkg.name}`); - let pkgEdited = false; - let tsconfigEdited = false; - - const { referenced, edited } = cleanupAndGetReferencedPackages(project); - pkgEdited = edited; - - ///////////////////////////////////////////////////////////////////// - // ensure that the tsconfig.json has the correct paths and references - ///////////////////////////////////////////////////////////////////// - - if (project.hasTsConfig) { - const { tsconfig } = project; - - tsconfigEdited = validateDesiredTsConfigSettings(project); - - if (!tsconfig.references) { - tsconfig.references = []; - tsconfigEdited = true; - log(`\t\t🔧 Added references array to tsconfig.json`); - } - - if (!tsconfig.compilerOptions) { - tsconfig.compilerOptions = {}; - tsconfigEdited = true; - log(`\t\t🔧 Added compilerOptions hash to tsconfig.json`); - } - - if (!tsconfig.compilerOptions.paths) { - tsconfig.compilerOptions.paths = {}; - tsconfigEdited = true; - log(`\t\t🔧 Added paths hash to tsconfig.json`); - } - - if (!project.isTest) { - if (!project.pkg.files?.includes(tsconfig.compilerOptions!.declarationDir!)) { - project.pkg.files ??= []; - project.pkg.files.push(tsconfig.compilerOptions!.declarationDir!); - pkgEdited = true; - log( - `\t\t🔧 Added types output directory "${tsconfig.compilerOptions.declarationDir}" to files in package.json` - ); - } - } - - for (const name of referenced) { - const relProject = projects.get(name); - if (!relProject) { - throw new Error(`Unable to find project ${name} in the workspace`); - } - - // we can only reference projects that emit types - if (!relProject.hasTsConfig) { - continue; - } - - if (relProject.tsconfig.compilerOptions?.noEmit === true) { - log(`\t\t🚨 ${project.pkg.name} cannot reference ${name} as it does not emit types`); - continue; - } - - if (!hasReference(project, relProject)) { - const referencePath = getRelativePath(project, relProject); - tsconfig.references!.push({ path: referencePath }); - tsconfigEdited = true; - log(`\t\t🔧 Added reference to ${referencePath} in tsconfig.json`); - } - - if (!hasPaths(project, relProject)) { - addPaths(project, relProject); - tsconfigEdited = true; - log(`\t\t🔧 Added paths for ${relProject.pkg.name} in tsconfig.json`); - } - } - } - - if (pkgEdited || tsconfigEdited) { - anyFileEdited = true; - await project.save({ pkgEdited, configEdited: tsconfigEdited }); - } - }); - - if (anyFileEdited) await runPrettier(); -} +import { main } from './tasks/sync-references'; main(); diff --git a/internal-tooling/src/sync-scripts.ts b/internal-tooling/src/sync-scripts.ts new file mode 100755 index 0000000000..7e03fcf843 --- /dev/null +++ b/internal-tooling/src/sync-scripts.ts @@ -0,0 +1,4 @@ +#! /usr/bin/env bun +import { main } from './tasks/sync-scripts'; + +main(); diff --git a/internal-tooling/src/-utils.ts b/internal-tooling/src/tasks/-utils.ts similarity index 100% rename from internal-tooling/src/-utils.ts rename to internal-tooling/src/tasks/-utils.ts diff --git a/internal-tooling/src/tasks/sync-all.ts b/internal-tooling/src/tasks/sync-all.ts new file mode 100644 index 0000000000..ffc196e678 --- /dev/null +++ b/internal-tooling/src/tasks/sync-all.ts @@ -0,0 +1,31 @@ +import debug from 'debug'; +import chalk from 'chalk'; + +const log = debug('wd:sync-all'); + +import { main as syncLogos } from './sync-logos'; +import { main as syncLicense } from './sync-license'; +import { main as syncReferences } from './sync-references'; +import { main as syncScripts } from './sync-scripts'; + +function isError(error: unknown): error is Error { + return error instanceof Error; +} + +async function runTask(name: string, task: () => Promise) { + log(chalk.greenBright(`♻️ Sync ${name}`)); + try { + await task(); + } catch (error) { + log(chalk.red(`Error Syncing ${name}: ${chalk.yellow(isError(error) ? error.message : error)}`)); + } +} + +export async function main() { + log(`Running all sync tasks`); + + await runTask('Logos', syncLogos); + await runTask('License', syncLicense); + await runTask('References', syncReferences); + await runTask('Scripts', syncScripts); +} diff --git a/internal-tooling/src/sync-license.ts b/internal-tooling/src/tasks/sync-license.ts similarity index 97% rename from internal-tooling/src/sync-license.ts rename to internal-tooling/src/tasks/sync-license.ts index 1dc5ad0944..69eeae3665 100755 --- a/internal-tooling/src/sync-license.ts +++ b/internal-tooling/src/tasks/sync-license.ts @@ -1,5 +1,3 @@ -#! /usr/bin/env bun - import path from 'path'; import fs from 'fs'; import debug from 'debug'; @@ -33,7 +31,7 @@ async function updatePackageJson({ pkg, file, nicePath }: { pkg: any; file: BunF } } -async function main() { +export async function main() { log( `\n\t${chalk.gray('=').repeat(60)}\n\t\t${chalk.magentaBright('@warp-drive/')}${chalk.greenBright('internal-tooling')} Sync LICENSE.md\n\t${chalk.gray('=').repeat(60)}\n\n\t\t${chalk.gray(`Syncing LICENSE.md from monorepo root to each public package`)}\n\n` ); @@ -70,5 +68,3 @@ async function main() { log('\n'); } } - -main(); diff --git a/internal-tooling/src/tasks/sync-logos.ts b/internal-tooling/src/tasks/sync-logos.ts new file mode 100755 index 0000000000..b016e824c0 --- /dev/null +++ b/internal-tooling/src/tasks/sync-logos.ts @@ -0,0 +1,83 @@ +import path from 'path'; +import fs from 'fs'; +import debug from 'debug'; +import chalk from 'chalk'; +import type { BunFile } from 'bun'; +import { getMonorepoRoot, getPackageJson } from './-utils'; + +const log = debug('wd:sync-logos'); + +async function copyFiles({ + packageDir, + packageLogosDir, + logosDir, + isCopied, +}: { + packageDir: string; + packageLogosDir: string; + logosDir: string; + isCopied: boolean; +}) { + // if we are in copy mode, remove any existing symlink and copy the files + if (isCopied) { + fs.rmSync(packageLogosDir, { recursive: true, force: true }); + log(`\t\t\t🗑️ Deleted existing copy of ${packageDir}/logos`); + } + fs.mkdirSync(packageLogosDir, { recursive: true }); + log(`\t\t\t📁 Created ${packageDir}/logos`); + + for (const logo of fs.readdirSync(logosDir, { recursive: true, encoding: 'utf-8' })) { + const logoPath = path.join(logosDir, logo); + const destPath = path.join(packageLogosDir, logo); + fs.copyFileSync(logoPath, destPath); + log(`\t\t\t📁 Copied ${logo} to ${packageDir}/logos`); + } +} + +async function updatePackageJson({ pkg, file, nicePath }: { pkg: any; file: BunFile; path: string; nicePath: string }) { + // ensure "files" field in package.json includes "logos" + if (!pkg.files) { + pkg.files = ['logos']; + await file.write(JSON.stringify(pkg, null, 2)); + log(`\t\t📝 Added "logos" to "files" in ${nicePath}`); + } else if (!pkg.files.includes('logos')) { + pkg.files.push('logos'); + await file.write(JSON.stringify(pkg, null, 2)); + log(`\t\t📝 Added "logos" to "files" in ${nicePath}`); + } +} + +export async function main() { + log( + `\n\t${chalk.gray('=').repeat(60)}\n\t\t${chalk.magentaBright('@warp-drive/')}${chalk.greenBright('internal-tooling')} Sync Logos\n\t${chalk.gray('=').repeat(60)}\n\n\t\t${chalk.gray(`Syncing logo files from monorepo root to each public package`)}\n\n` + ); + const monorepoRoot = await getMonorepoRoot(); + + // sync the logos from the monorepo root to each + // package directory that has a logos directory + + const logosDir = path.join(monorepoRoot, 'logos'); + const packagesDir = path.join(monorepoRoot, 'packages'); + + for (const packageDir of fs.readdirSync(packagesDir)) { + const packageLogosDir = path.join(packagesDir, packageDir, 'logos'); + const isCopied = fs.existsSync(packageLogosDir); + const details = await getPackageJson({ packageDir, packagesDir }); + + if (details.pkg.private) { + log(`\t\t🔒 Skipping private package ${details.nicePath}`); + continue; + } + + log(`\t\t🔁 Syncing logos to ${packageDir}`); + + await copyFiles({ + packageDir, + packageLogosDir, + logosDir, + isCopied, + }); + + await updatePackageJson(details); + } +} diff --git a/internal-tooling/src/tasks/sync-references.ts b/internal-tooling/src/tasks/sync-references.ts new file mode 100755 index 0000000000..efedd0c7ef --- /dev/null +++ b/internal-tooling/src/tasks/sync-references.ts @@ -0,0 +1,288 @@ +import debug from 'debug'; +import path from 'path'; +import chalk from 'chalk'; +import { + runPrettier, + walkPackages, + type ProjectPackage, + type ProjectPackageWithTsConfig, + type TsConfigFile, +} from './-utils'; + +const log = debug('wd:sync-references'); + +function isCleanRange(range: string) { + return !range.includes(' ') && !range.includes('||') && !range.includes('>') && !range.includes('<'); +} + +function cleanupAndGetReferencedPackages(project: ProjectPackage) { + const packages = new Set(); + const { pkg } = project; + let edited = false; + + for (const packageName of Object.keys(pkg.dependencies ?? {})) { + if (project.packages.has(packageName)) { + packages.add(packageName); + } + } + + for (const packageName of Object.keys(pkg.peerDependencies ?? {})) { + if (project.packages.has(packageName)) { + packages.add(packageName); + } + if (pkg.dependencies?.[packageName]) { + log(`\t\t🚨 ${project.pkg.name} has ${packageName} in both dependencies and peerDependencies`); + delete pkg.dependencies[packageName]; + log(`\t\t🔧 Removed ${packageName} from dependencies`); + edited = true; + } + if (!pkg.devDependencies?.[packageName]) { + log(`\t\t🚨 ${project.pkg.name} has ${packageName} in peerDependencies but not in devDependencies`); + if (!project.packages.has(packageName) && !isCleanRange(pkg.peerDependencies![packageName])) { + throw new Error( + `Unable to fix missing devDependency on PeerDependency ${packageName} as it is not a workspace package and specifies a range.` + ); + } + pkg.devDependencies ??= {}; + pkg.devDependencies[packageName] = project.packages.has(packageName) + ? `workspace:${packageName}` + : pkg.peerDependencies![packageName]; + log(`\t\t🔧 Added "${packageName}": "${pkg.devDependencies![packageName]}" to devDependencies`); + edited = true; + } + } + + for (const packageName of Object.keys(project.pkg.devDependencies ?? {})) { + if (project.packages.has(packageName)) { + packages.add(packageName); + } + } + + return { referenced: packages, edited }; +} + +function getRelativePath(pkgA: ProjectPackage, pkgB: ProjectPackage) { + return path.relative(pkgA.project.dir, pkgB.project.dir); +} + +function hasReference(srcPkg: ProjectPackageWithTsConfig, relPkg: ProjectPackageWithTsConfig) { + const referencePath = getRelativePath(srcPkg, relPkg); + if (!srcPkg.tsconfig.references) { + return false; + } + return srcPkg.tsconfig.references.some((ref) => ref.path === referencePath); +} + +function hasPaths(srcPkg: ProjectPackageWithTsConfig, relPkg: ProjectPackageWithTsConfig) { + if (!srcPkg.tsconfig.compilerOptions?.paths) { + return false; + } + const dep = relPkg.pkg.name; + const hasPrimary = !!srcPkg.tsconfig.compilerOptions.paths[dep]; + const hasWildcard = !!srcPkg.tsconfig.compilerOptions.paths[`${dep}/*`]; + + return hasPrimary && hasWildcard; +} + +function addPaths(srcPkg: ProjectPackageWithTsConfig, relPkg: ProjectPackageWithTsConfig) { + const typesDir = relPkg.tsconfig.compilerOptions?.declarationDir; + + if (!typesDir) { + throw new Error(`Missing compilerOptions.declarationDir in ${relPkg.tsconfigPath}`); + } + + const relativePath = getRelativePath(srcPkg, relPkg); + + srcPkg.tsconfig.compilerOptions!.paths![relPkg.pkg.name] = [`${relativePath}/${typesDir}`]; + srcPkg.tsconfig.compilerOptions!.paths![`${relPkg.pkg.name}/*`] = [`${relativePath}/${typesDir}/*`]; +} + +function validateDesiredTsConfigSettings(project: ProjectPackageWithTsConfig) { + // ensure that the tsconfig.json has the correct settings for our monorepo + const { tsconfig } = project; + let { compilerOptions } = tsconfig; + let edited = false; + + //////////////////////////// + // All Projects + //////////////////////////// + const BaseDefaults: Exclude = { + allowImportingTsExtensions: true, + // we use isolatedDeclarations in some projects, but not all + // once we use in all set this to false + // and set isolatedDeclarations to true in the projects + // allowJs: false, + // isolatedDeclarations: true, + // verbatimModuleSyntax: true, + checkJs: false, + baseUrl: '.', + composite: true, + declaration: true, + declarationDir: 'unstable-preview-types', + declarationMap: true, + emitDeclarationOnly: true, + erasableSyntaxOnly: true, + experimentalDecorators: true, + incremental: true, + inlineSourceMap: true, + inlineSources: true, + lib: ['ESNext'], + module: 'ESNext', + moduleDetection: 'force', + moduleResolution: 'bundler', + noEmit: undefined, + pretty: true, + rootDir: 'src', + skipLibCheck: true, + strict: true, + target: 'ESNext', + } as const; + + if (!compilerOptions) { + compilerOptions = tsconfig.compilerOptions = {}; + edited = true; + log(`\t\t🔧 Added compilerOptions hash to tsconfig.json`); + } + + const defaultKeys = Object.keys(BaseDefaults) as (keyof typeof BaseDefaults)[]; + for (const key of defaultKeys) { + const defaultValue = BaseDefaults[key]!; + if (!(key in compilerOptions)) { + // @ts-expect-error + compilerOptions[key] = defaultValue; + edited = true; + log(`\t\t🔧 Added "${key}": ${JSON.stringify(defaultValue)} in compilerOptions in tsconfig.json`); + continue; + } + + if (typeof defaultValue === 'boolean') { + if (compilerOptions[key] !== defaultValue) { + // @ts-expect-error + compilerOptions[key] = defaultValue; + edited = true; + log(`\t\t🔧 Updated "${key}" to ${defaultValue ? 'true' : 'false'} in compilerOptions in tsconfig.json`); + } + } + + if (typeof defaultValue === 'undefined') { + if (compilerOptions[key] !== defaultValue) { + delete compilerOptions[key]; + edited = true; + log(`\t\t🔧 Deleted "${key}" from compilerOptions in tsconfig.json`); + } + } + + if (typeof defaultValue === 'string') { + if (compilerOptions[key] !== defaultValue) { + log( + `\t\t⚠️ Non-default value "${compilerOptions[key]}" for "${key}" in compilerOptions in tsconfig.json, default is "${defaultValue}"` + ); + } + } + + if (Array.isArray(defaultValue)) { + // TODO probably nothing, but maybe a deep comparison here + // if (compilerOptions[key] !== defaultValue) { + // log( + // `\t\t⚠️ Non-default value "${JSON.stringify(compilerOptions[key])}" for "${key}" in compilerOptions in tsconfig.json, default is "${JSON.stringify( + // defaultValue + // )}"` + // ); + // } + } + } + + return edited; +} + +export async function main() { + log( + `\n\t${chalk.gray('=').repeat(60)}\n\t\t${chalk.magentaBright('@warp-drive/')}${chalk.greenBright('internal-tooling')} Sync TypeScript References\n\t${chalk.gray('=').repeat(60)}\n\n\t\t${chalk.gray(`Syncing Project References`)}\n\n` + ); + let anyFileEdited = false; + + await walkPackages(async (project: ProjectPackage, projects: Map) => { + log(`\t📦 Syncing ${project.pkg.name}`); + let pkgEdited = false; + let tsconfigEdited = false; + + const { referenced, edited } = cleanupAndGetReferencedPackages(project); + pkgEdited = edited; + + ///////////////////////////////////////////////////////////////////// + // ensure that the tsconfig.json has the correct paths and references + ///////////////////////////////////////////////////////////////////// + + if (project.hasTsConfig) { + const { tsconfig } = project; + + tsconfigEdited = validateDesiredTsConfigSettings(project); + + if (!tsconfig.references) { + tsconfig.references = []; + tsconfigEdited = true; + log(`\t\t🔧 Added references array to tsconfig.json`); + } + + if (!tsconfig.compilerOptions) { + tsconfig.compilerOptions = {}; + tsconfigEdited = true; + log(`\t\t🔧 Added compilerOptions hash to tsconfig.json`); + } + + if (!tsconfig.compilerOptions.paths) { + tsconfig.compilerOptions.paths = {}; + tsconfigEdited = true; + log(`\t\t🔧 Added paths hash to tsconfig.json`); + } + + if (!project.isTest) { + if (!project.pkg.files?.includes(tsconfig.compilerOptions!.declarationDir!)) { + project.pkg.files ??= []; + project.pkg.files.push(tsconfig.compilerOptions!.declarationDir!); + pkgEdited = true; + log( + `\t\t🔧 Added types output directory "${tsconfig.compilerOptions.declarationDir}" to files in package.json` + ); + } + } + + for (const name of referenced) { + const relProject = projects.get(name); + if (!relProject) { + throw new Error(`Unable to find project ${name} in the workspace`); + } + + // we can only reference projects that emit types + if (!relProject.hasTsConfig) { + continue; + } + + if (relProject.tsconfig.compilerOptions?.noEmit === true) { + log(`\t\t🚨 ${project.pkg.name} cannot reference ${name} as it does not emit types`); + continue; + } + + if (!hasReference(project, relProject)) { + const referencePath = getRelativePath(project, relProject); + tsconfig.references!.push({ path: referencePath }); + tsconfigEdited = true; + log(`\t\t🔧 Added reference to ${referencePath} in tsconfig.json`); + } + + if (!hasPaths(project, relProject)) { + addPaths(project, relProject); + tsconfigEdited = true; + log(`\t\t🔧 Added paths for ${relProject.pkg.name} in tsconfig.json`); + } + } + } + + if (pkgEdited || tsconfigEdited) { + anyFileEdited = true; + await project.save({ pkgEdited, configEdited: tsconfigEdited }); + } + }); + + if (anyFileEdited) await runPrettier(); +} diff --git a/internal-tooling/src/tasks/sync-scripts.ts b/internal-tooling/src/tasks/sync-scripts.ts new file mode 100644 index 0000000000..b329dbc3a2 --- /dev/null +++ b/internal-tooling/src/tasks/sync-scripts.ts @@ -0,0 +1,244 @@ +import debug from 'debug'; +import chalk from 'chalk'; +import { runPrettier, walkPackages, type ProjectPackage } from './-utils'; + +const log = debug('wd:sync-scripts'); + +const PUBLIC_PACKAGES = { + lint: 'eslint . --quiet --cache --cache-strategy=content', +}; + +// does not have vite +const CLASSIC_TEST_APP = { + 'build:tests': 'IS_TESTING=true EMBER_CLI_TEST_COMMAND=true ember build --output-path=dist-test --suppress-sizes', + 'build:production': 'bun run build:tests -e production', + start: 'bun run build:tests --watch', + 'check:types': 'tsc --noEmit', +}; + +const GLINT_TEST_APP = { + 'check:types': 'glint', +}; + +const EXAM_TEST_APP = { + examine: + 'export EXAM_PARALLEL_COUNT=$(./bin/calculate-test-jobs); ember exam --test-port=0 --path=dist-test --parallel=$EXAM_PARALLEL_COUNT --load-balance', + test: 'bun run examine', + 'test:production': 'bun run examine', + 'test:start': 'bun run ember test --test-port=0 --path=dist-test --serve --no-launch', +}; + +const TESTEM_TEST_APP = { + test: 'ember test --test-port=0 --path=dist-test', + 'test:production': 'ember test --test-port=0 --path=dist-test --environment=production', + 'test:start': 'bun run test --serve --no-launch', +}; + +const DIAGNOSTIC_TEST_APP = { + test: 'bun ./diagnostic.js', + 'test:production': 'bun ./diagnostic.js', + 'test:start': 'bun ./diagnostic.js --serve --no-launch', +}; + +const SPECIAL_CASED_TEST_APPS = new Set(['fastboot-test-app', 'embroider-basic-compat']); +const TOOLING_PACKAGES = new Set(['@ember-data/codemods', 'eslint-plugin-warp-drive']); + +const PUBLIC_PACKAGES_EXCEPT_TOOLING = { + prepack: 'pnpm run build:pkg', + sync: 'echo "syncing"', + start: 'vite', +}; + +const PUBLIC_PACKAGES_EXCEPT_BUILD_CONFIG_AND_TOOLING = { + 'build:pkg': 'vite build;', +}; + +function usesGlint(project: ProjectPackage) { + const availableDependencies = Object.assign({}, project.pkg.dependencies, project.pkg.devDependencies); + + if (availableDependencies['@glint/environment-ember-loose']) { + return true; + } + + return false; +} + +function usesDiagnostic(project: ProjectPackage) { + const availableDependencies = Object.assign({}, project.pkg.dependencies, project.pkg.devDependencies); + + if (availableDependencies['@warp-drive/diagnostic']) { + return true; + } + + return false; +} + +function usesTestem(project: ProjectPackage) { + const availableDependencies = Object.assign({}, project.pkg.dependencies, project.pkg.devDependencies); + + if (availableDependencies.testem) { + return true; + } + + return false; +} + +function usesExam(project: ProjectPackage) { + const availableDependencies = Object.assign({}, project.pkg.dependencies, project.pkg.devDependencies); + + if (availableDependencies['ember-exam']) { + return true; + } + + return false; +} + +function isTestApp(project: ProjectPackage) { + // test apps must always have one of testem or diagnostic as a devDependency or dependency + const availableDependencies = Object.assign({}, project.pkg.dependencies, project.pkg.devDependencies); + + if (availableDependencies.testem) { + return true; + } + + if (availableDependencies['@warp-drive/diagnostic']) { + return true; + } + + return false; +} + +function isViteApp(project: ProjectPackage) { + // test apps must always have one of testem or diagnostic as a devDependency or dependency + const availableDependencies = Object.assign({}, project.pkg.dependencies, project.pkg.devDependencies); + + if (availableDependencies.vite && availableDependencies['@embroider/core']) { + return true; + } + + return false; +} + +export async function main() { + log( + `\n\t${chalk.gray('=').repeat(60)}\n\t\t${chalk.magentaBright('@warp-drive/')}${chalk.greenBright('internal-tooling')} Sync Scripts\n\t${chalk.gray('=').repeat(60)}\n\n\t\t${chalk.gray(`Syncing default scripts for each package type`)}\n\n` + ); + + let anyFileEdited = false; + + await walkPackages(async (project: ProjectPackage, projects: Map) => { + log(`\t📦 Syncing ${project.pkg.name}`); + let pkgEdited = false; + let tsconfigEdited = false; + + ///////////////////////////////////////////////////////////////////// + // ensure that the package.json scripts are up to date with defaults + ///////////////////////////////////////////////////////////////////// + + if (!project.isPrivate) { + if (!project.pkg.scripts) { + project.pkg.scripts = {}; + pkgEdited = true; + log(`\t\t🔧 Added scripts hash to package.json`); + } + + for (const [script, command] of Object.entries(PUBLIC_PACKAGES)) { + if (!project.pkg.scripts[script]) { + project.pkg.scripts[script] = command; + pkgEdited = true; + log(`\t\t🔧 Added ${script} script to package.json`); + } else if (project.pkg.scripts[script] !== command) { + project.pkg.scripts[script] = command; + pkgEdited = true; + log(`\t\t🔧 Updated ${script} script in package.json`); + } + } + + if (project.pkg.name !== '@warp-drive/build-config' && !TOOLING_PACKAGES.has(project.pkg.name)) { + for (const [script, command] of Object.entries(PUBLIC_PACKAGES_EXCEPT_BUILD_CONFIG_AND_TOOLING)) { + if (!project.pkg.scripts[script]) { + project.pkg.scripts[script] = command; + pkgEdited = true; + log(`\t\t🔧 Added ${script} script to package.json`); + } else if (project.pkg.scripts[script] !== command) { + project.pkg.scripts[script] = command; + pkgEdited = true; + log(`\t\t🔧 Updated ${script} script in package.json`); + } + } + } + + if (!TOOLING_PACKAGES.has(project.pkg.name)) { + for (const [script, command] of Object.entries(PUBLIC_PACKAGES_EXCEPT_TOOLING)) { + if (!project.pkg.scripts[script]) { + project.pkg.scripts[script] = command; + pkgEdited = true; + log(`\t\t🔧 Added ${script} script to package.json`); + } else if (project.pkg.scripts[script] !== command) { + project.pkg.scripts[script] = command; + pkgEdited = true; + log(`\t\t🔧 Updated ${script} script in package.json`); + } + } + } + } else if (project.isTest && isTestApp(project) && !SPECIAL_CASED_TEST_APPS.has(project.pkg.name)) { + if (isViteApp(project)) { + throw new Error(`Update sync-scripts to handle vite test apps`); + } + + if (!project.pkg.scripts) { + project.pkg.scripts = {}; + pkgEdited = true; + log(`\t\t🔧 Added scripts hash to package.json`); + } + + const isGlint = usesGlint(project); + const isTestem = usesTestem(project); + const isExam = usesExam(project); + const isDiagnostic = usesDiagnostic(project); + + if (isGlint) { + log(`\t\t\t📡 Detected glint test app`); + } + if (isTestem) { + log(`\t\t\t📡 Detected testem test app`); + } + if (isExam) { + log(`\t\t\t📡 Detected exam test app`); + } + if (isDiagnostic) { + log(`\t\t\t📡 Detected diagnostic test app`); + } + + const expectedScripts = Object.assign( + {}, + CLASSIC_TEST_APP, + isGlint ? GLINT_TEST_APP : {}, + isTestem ? TESTEM_TEST_APP : {}, + isExam ? EXAM_TEST_APP : {}, + isDiagnostic ? DIAGNOSTIC_TEST_APP : {} + ) as Record; + + for (const [script, command] of Object.entries(expectedScripts)) { + if (!project.pkg.scripts[script]) { + project.pkg.scripts[script] = command; + pkgEdited = true; + log(`\t\t🔧 Added ${script} script to package.json`); + } else if (project.pkg.scripts[script] !== command) { + project.pkg.scripts[script] = command; + pkgEdited = true; + log(`\t\t🔧 Updated ${script} script in package.json`); + } + } + } else { + log(`\t\t🔒 Skipping private package ${project.pkg.name}`); + } + + if (pkgEdited || tsconfigEdited) { + anyFileEdited = true; + await project.save({ pkgEdited, configEdited: tsconfigEdited }); + } + }); + + if (anyFileEdited) await runPrettier(); +} diff --git a/package.json b/package.json index d59017c94e..eed4e04a8d 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "release": "./release/index.ts", "build": "turbo run build:pkg --log-order=stream --concurrency=10;", "sync": "pnpm --filter './packages/*' run --parallel --if-present sync", + "start": "turbo run start --filter=./packages/* --concurrency=23", "build:docs": "mkdir -p packages/-ember-data/dist && cd ./docs-generator && node ./compile-docs.js", "lint:tests": "turbo --log-order=stream lint --filter=./tests/* --continue --concurrency=10", "lint:pkg": "turbo --log-order=stream lint --filter=./packages/* --continue --concurrency=10", diff --git a/packages/-ember-data/package.json b/packages/-ember-data/package.json index d3d91beb3b..e0ac395573 100644 --- a/packages/-ember-data/package.json +++ b/packages/-ember-data/package.json @@ -17,7 +17,9 @@ "scripts": { "lint": "eslint . --quiet --cache --cache-strategy=content", "build:pkg": "vite build;", - "prepack": "pnpm run build:pkg" + "prepack": "pnpm run build:pkg", + "sync": "echo \"syncing\"", + "start": "vite" }, "ember-addon": { "main": "addon-main.cjs", diff --git a/packages/-warp-drive/package.json b/packages/-warp-drive/package.json index d5d8263c03..f77aa3b951 100644 --- a/packages/-warp-drive/package.json +++ b/packages/-warp-drive/package.json @@ -27,7 +27,9 @@ "scripts": { "build:pkg": "vite build;", "prepack": "pnpm run build:pkg", - "sync": "echo \"syncing\"" + "sync": "echo \"syncing\"", + "_temporarily_deactivated_lint": "eslint . --quiet --cache --cache-strategy=content", + "start": "vite" }, "bin": { "warp-drive": "./dist/warp-drive.js", diff --git a/packages/active-record/package.json b/packages/active-record/package.json index f3f867316a..d06509e9ca 100644 --- a/packages/active-record/package.json +++ b/packages/active-record/package.json @@ -36,7 +36,8 @@ "lint": "eslint . --quiet --cache --cache-strategy=content", "build:pkg": "vite build;", "prepack": "pnpm run build:pkg", - "sync": "echo \"syncing\"" + "sync": "echo \"syncing\"", + "start": "vite" }, "ember-addon": { "main": "addon-main.cjs", diff --git a/packages/adapter/package.json b/packages/adapter/package.json index d232b8c1af..4d54c56d7e 100644 --- a/packages/adapter/package.json +++ b/packages/adapter/package.json @@ -16,7 +16,9 @@ "scripts": { "lint": "eslint . --quiet --cache --cache-strategy=content", "build:pkg": "vite build;", - "prepack": "pnpm run build:pkg" + "prepack": "pnpm run build:pkg", + "sync": "echo \"syncing\"", + "start": "vite" }, "ember-addon": { "main": "addon-main.cjs", diff --git a/packages/build-config/package.json b/packages/build-config/package.json index 870ab5e45e..ea0bc774b8 100644 --- a/packages/build-config/package.json +++ b/packages/build-config/package.json @@ -14,9 +14,11 @@ "license": "MIT", "author": "Chris Thoburn ", "scripts": { - "build:infra": "vite build; vite build -c ./vite.config-cjs.mjs;", - "prepack": "pnpm run build:infra", - "sync": "echo \"syncing\"" + "build:pkg": "vite build; vite build -c ./vite.config-cjs.mjs;", + "prepack": "pnpm run build:pkg", + "sync": "echo \"syncing\"", + "_temporarily_deactivated_lint": "eslint . --quiet --cache --cache-strategy=content", + "start": "vite" }, "type": "module", "files": [ diff --git a/packages/codemods/package.json b/packages/codemods/package.json index 2f867c321e..f69bded46a 100644 --- a/packages/codemods/package.json +++ b/packages/codemods/package.json @@ -14,8 +14,7 @@ }, "scripts": { "build:cli": "bun build bin/codemods.ts --compile --target node --outfile codemods --sourcemap", - "lint": "eslint . --quiet --cache --cache-strategy=content", - "_syncPnpm": "bun run sync-dependencies-meta-injected" + "lint": "eslint . --quiet --cache --cache-strategy=content" }, "exports": { ".": { diff --git a/packages/core-types/package.json b/packages/core-types/package.json index 08888a551b..c37170e4e4 100644 --- a/packages/core-types/package.json +++ b/packages/core-types/package.json @@ -16,7 +16,8 @@ "lint": "eslint . --quiet --cache --cache-strategy=content", "build:pkg": "vite build;", "prepack": "pnpm run build:pkg", - "sync": "echo \"syncing\"" + "sync": "echo \"syncing\"", + "start": "vite" }, "files": [ "dist", diff --git a/packages/debug/package.json b/packages/debug/package.json index 2cfdbbbed8..efc1ba07f9 100644 --- a/packages/debug/package.json +++ b/packages/debug/package.json @@ -16,7 +16,9 @@ "scripts": { "lint": "eslint . --quiet --cache --cache-strategy=content", "build:pkg": "vite build;", - "prepack": "pnpm run build:pkg" + "prepack": "pnpm run build:pkg", + "sync": "echo \"syncing\"", + "start": "vite" }, "files": [ "unstable-preview-types", diff --git a/packages/diagnostic/package.json b/packages/diagnostic/package.json index 89776eda91..c46bf69e28 100644 --- a/packages/diagnostic/package.json +++ b/packages/diagnostic/package.json @@ -69,7 +69,8 @@ "build:tests": "rm -rf dist-test && cp -R test dist-test && mkdir -p dist-test/@warp-drive && cp -R dist dist-test/@warp-drive/diagnostic", "build:pkg": "vite build;", "prepack": "pnpm run build:pkg", - "sync": "echo \"syncing\"" + "sync": "echo \"syncing\"", + "start": "vite" }, "peerDependencies": { "ember-source": "3.28.12 || ^4.0.4 || ^5.0.0 || ^6.0.0", diff --git a/packages/ember/package.json b/packages/ember/package.json index 2e55bb6b86..53a674792e 100644 --- a/packages/ember/package.json +++ b/packages/ember/package.json @@ -15,11 +15,12 @@ "ember-addon" ], "scripts": { - "_lint": "eslint . --quiet --cache --cache-strategy=content", "build:glint": "glint && glint --build", "build:pkg": "vite build;", "prepack": "pnpm run build:pkg", - "sync": "echo \"syncing\"" + "sync": "echo \"syncing\"", + "_temporarily_deactivated_lint": "eslint . --quiet --cache --cache-strategy=content", + "start": "vite" }, "files": [ "unstable-preview-types", diff --git a/packages/eslint-plugin-warp-drive/package.json b/packages/eslint-plugin-warp-drive/package.json index b5f48aeec7..d6f3aacd7c 100644 --- a/packages/eslint-plugin-warp-drive/package.json +++ b/packages/eslint-plugin-warp-drive/package.json @@ -31,7 +31,8 @@ "LICENSE.md" ], "scripts": { - "test": "mocha tests" + "test": "mocha tests", + "lint": "eslint . --quiet --cache --cache-strategy=content" }, "license": "MIT" } diff --git a/packages/experiments/package.json b/packages/experiments/package.json index 57feb512b9..e87398178f 100644 --- a/packages/experiments/package.json +++ b/packages/experiments/package.json @@ -49,7 +49,8 @@ "lint": "eslint . --quiet --cache --cache-strategy=content", "build:pkg": "vite build;", "prepack": "pnpm run build:pkg", - "sync": "echo \"syncing\"" + "sync": "echo \"syncing\"", + "start": "vite" }, "peerDependencies": { "@sqlite.org/sqlite-wasm": "3.46.0-build2", diff --git a/packages/graph/package.json b/packages/graph/package.json index acae1b3a5c..c8eb0a4e63 100644 --- a/packages/graph/package.json +++ b/packages/graph/package.json @@ -16,7 +16,8 @@ "lint": "eslint . --quiet --cache --cache-strategy=content", "build:pkg": "vite build;", "prepack": "pnpm run build:pkg", - "sync": "echo \"syncing\"" + "sync": "echo \"syncing\"", + "start": "vite" }, "files": [ "unstable-preview-types", diff --git a/packages/holodeck/package.json b/packages/holodeck/package.json index 4396ea0258..058d47fe88 100644 --- a/packages/holodeck/package.json +++ b/packages/holodeck/package.json @@ -42,7 +42,9 @@ "check:pkg-types": "tsc --noEmit", "build:pkg": "vite build;", "prepack": "pnpm run build:pkg", - "sync": "echo \"syncing\"" + "sync": "echo \"syncing\"", + "_temporarily_deactivated_lint": "eslint . --quiet --cache --cache-strategy=content", + "start": "vite" }, "peerDependencies": { "@ember-data/request": "workspace:*", diff --git a/packages/json-api/package.json b/packages/json-api/package.json index 5f36b6d6f4..4bf7cc1cc3 100644 --- a/packages/json-api/package.json +++ b/packages/json-api/package.json @@ -16,7 +16,8 @@ "lint": "eslint . --quiet --cache --cache-strategy=content", "build:pkg": "vite build;", "prepack": "pnpm run build:pkg", - "sync": "echo \"syncing\"" + "sync": "echo \"syncing\"", + "start": "vite" }, "ember-addon": { "main": "addon-main.cjs", diff --git a/packages/legacy-compat/package.json b/packages/legacy-compat/package.json index 0f97c3e6cf..dc0261479d 100644 --- a/packages/legacy-compat/package.json +++ b/packages/legacy-compat/package.json @@ -42,7 +42,8 @@ "lint": "eslint . --quiet --cache --cache-strategy=content", "build:pkg": "vite build;", "prepack": "pnpm run build:pkg", - "sync": "echo \"syncing\"" + "sync": "echo \"syncing\"", + "start": "vite" }, "ember-addon": { "main": "addon-main.cjs", diff --git a/packages/model/package.json b/packages/model/package.json index 9114a6ea1b..d7838fc881 100644 --- a/packages/model/package.json +++ b/packages/model/package.json @@ -17,7 +17,8 @@ "lint": "eslint . --quiet --cache --cache-strategy=content", "build:pkg": "vite build;", "prepack": "pnpm run build:pkg", - "sync": "echo \"syncing\"" + "sync": "echo \"syncing\"", + "start": "vite" }, "ember-addon": { "main": "addon-main.cjs", diff --git a/packages/request-utils/package.json b/packages/request-utils/package.json index 7cbca6373e..58df80a2a8 100644 --- a/packages/request-utils/package.json +++ b/packages/request-utils/package.json @@ -43,7 +43,8 @@ "lint": "eslint . --quiet --cache --cache-strategy=content", "build:pkg": "vite build;", "prepack": "pnpm run build:pkg", - "sync": "echo \"syncing\"" + "sync": "echo \"syncing\"", + "start": "vite" }, "ember-addon": { "main": "addon-main.cjs", diff --git a/packages/request/package.json b/packages/request/package.json index e197f8853c..b5901558a7 100644 --- a/packages/request/package.json +++ b/packages/request/package.json @@ -18,7 +18,8 @@ "lint": "eslint . --quiet --cache --cache-strategy=content", "build:pkg": "vite build;", "prepack": "pnpm run build:pkg", - "sync": "echo \"syncing\"" + "sync": "echo \"syncing\"", + "start": "vite" }, "files": [ "unstable-preview-types", diff --git a/packages/rest/package.json b/packages/rest/package.json index 51ffc9b782..54934b68a9 100644 --- a/packages/rest/package.json +++ b/packages/rest/package.json @@ -48,7 +48,8 @@ "lint": "eslint . --quiet --cache --cache-strategy=content", "build:pkg": "vite build;", "prepack": "pnpm run build:pkg", - "sync": "echo \"syncing\"" + "sync": "echo \"syncing\"", + "start": "vite" }, "ember-addon": { "main": "addon-main.cjs", diff --git a/packages/schema-record/package.json b/packages/schema-record/package.json index 4246899e6f..ff9f7a81bf 100644 --- a/packages/schema-record/package.json +++ b/packages/schema-record/package.json @@ -16,7 +16,8 @@ "lint": "eslint . --quiet --cache --cache-strategy=content", "build:pkg": "vite build;", "prepack": "pnpm run build:pkg", - "sync": "echo \"syncing\"" + "sync": "echo \"syncing\"", + "start": "vite" }, "ember-addon": { "main": "addon-main.cjs", diff --git a/packages/serializer/package.json b/packages/serializer/package.json index 02d0e0c3a9..b0e6980c1f 100644 --- a/packages/serializer/package.json +++ b/packages/serializer/package.json @@ -17,7 +17,8 @@ "lint": "eslint . --quiet --cache --cache-strategy=content", "build:pkg": "vite build;", "prepack": "pnpm run build:pkg", - "sync": "echo \"syncing\"" + "sync": "echo \"syncing\"", + "start": "vite" }, "ember-addon": { "main": "addon-main.cjs", diff --git a/packages/store/package.json b/packages/store/package.json index 65e78deea0..453b00d94c 100644 --- a/packages/store/package.json +++ b/packages/store/package.json @@ -34,7 +34,8 @@ "lint": "eslint . --quiet --cache --cache-strategy=content", "build:pkg": "vite build;", "prepack": "pnpm run build:pkg", - "sync": "echo \"syncing\"" + "sync": "echo \"syncing\"", + "start": "vite" }, "dependencies": { "@embroider/macros": "^1.16.11", diff --git a/packages/tracking/package.json b/packages/tracking/package.json index ba0e2e7add..2b695f5583 100644 --- a/packages/tracking/package.json +++ b/packages/tracking/package.json @@ -51,7 +51,8 @@ "lint": "eslint . --quiet --cache --cache-strategy=content", "build:pkg": "vite build;", "prepack": "pnpm run build:pkg", - "sync": "echo \"syncing\"" + "sync": "echo \"syncing\"", + "start": "vite" }, "ember-addon": { "main": "addon-main.cjs", diff --git a/tests/builders/package.json b/tests/builders/package.json index 98d0047b45..3817ee9669 100644 --- a/tests/builders/package.json +++ b/tests/builders/package.json @@ -16,11 +16,13 @@ }, "scripts": { "build:tests": "IS_TESTING=true EMBER_CLI_TEST_COMMAND=true ember build --output-path=dist-test --suppress-sizes", - "build:production": "pnpm build:tests -e production", + "build:production": "bun run build:tests -e production", "lint": "eslint . --quiet --cache --cache-strategy=content", "check:types": "tsc --noEmit", "test": "bun ./diagnostic.js", - "test:production": "bun ./diagnostic.js" + "test:production": "bun ./diagnostic.js", + "start": "bun run build:tests --watch", + "test:start": "bun ./diagnostic.js --serve --no-launch" }, "devDependencies": { "@babel/core": "^7.26.9", diff --git a/tests/ember-data__adapter/package.json b/tests/ember-data__adapter/package.json index ee943921ff..5e74174bc7 100644 --- a/tests/ember-data__adapter/package.json +++ b/tests/ember-data__adapter/package.json @@ -16,11 +16,13 @@ }, "scripts": { "build:tests": "IS_TESTING=true EMBER_CLI_TEST_COMMAND=true ember build --output-path=dist-test --suppress-sizes", - "_build:production": "pnpm build:tests -e production", + "build:production": "bun run build:tests -e production", "lint": "eslint . --quiet --cache --cache-strategy=content", "check:types": "tsc --noEmit", "test": "bun ./diagnostic.js", - "_test:production": "bun ./diagnostic.js" + "test:production": "bun ./diagnostic.js", + "start": "bun run build:tests --watch", + "test:start": "bun ./diagnostic.js --serve --no-launch" }, "dependencies": { "@babel/core": "^7.26.9", diff --git a/tests/ember-data__graph/package.json b/tests/ember-data__graph/package.json index f60ea16475..0e9071efa7 100644 --- a/tests/ember-data__graph/package.json +++ b/tests/ember-data__graph/package.json @@ -16,11 +16,13 @@ }, "scripts": { "build:tests": "IS_TESTING=true EMBER_CLI_TEST_COMMAND=true ember build --output-path=dist-test --suppress-sizes", - "build:production": "pnpm build:tests -e production", + "build:production": "bun run build:tests -e production", "lint": "eslint . --quiet --cache --cache-strategy=content", "check:types": "tsc --noEmit", "test": "bun ./diagnostic.js", - "test:production": "bun ./diagnostic.js" + "test:production": "bun ./diagnostic.js", + "start": "bun run build:tests --watch", + "test:start": "bun ./diagnostic.js --serve --no-launch" }, "devDependencies": { "@babel/core": "^7.26.9", diff --git a/tests/ember-data__json-api/package.json b/tests/ember-data__json-api/package.json index 8e43699e08..399e4105aa 100644 --- a/tests/ember-data__json-api/package.json +++ b/tests/ember-data__json-api/package.json @@ -17,11 +17,12 @@ "scripts": { "build:tests": "IS_TESTING=true EMBER_CLI_TEST_COMMAND=true ember build --output-path=dist-test --suppress-sizes", "start": "bun run build:tests --watch", - "build:production": "pnpm build:tests -e production", + "build:production": "bun run build:tests -e production", "lint": "eslint . --quiet --cache --cache-strategy=content", "check:types": "tsc --noEmit", "test": "bun ./diagnostic.js", - "test:production": "bun ./diagnostic.js" + "test:production": "bun ./diagnostic.js", + "test:start": "bun ./diagnostic.js --serve --no-launch" }, "devDependencies": { "@babel/core": "^7.26.9", diff --git a/tests/ember-data__model/package.json b/tests/ember-data__model/package.json index 0504ebc130..7f736cad90 100644 --- a/tests/ember-data__model/package.json +++ b/tests/ember-data__model/package.json @@ -18,7 +18,11 @@ "build:tests": "IS_TESTING=true EMBER_CLI_TEST_COMMAND=true ember build --output-path=dist-test --suppress-sizes", "check:types": "tsc --noEmit", "lint": "eslint . --quiet --cache --cache-strategy=content", - "test": "bun ./diagnostic.js" + "test": "bun ./diagnostic.js", + "_temporarily_deactivated_build:production": "bun run build:tests -e production", + "start": "bun run build:tests --watch", + "_temporarily_deactivated_test:production": "bun ./diagnostic.js", + "test:start": "bun ./diagnostic.js --serve --no-launch" }, "devDependencies": { "@babel/core": "^7.26.9", diff --git a/tests/ember-data__request/package.json b/tests/ember-data__request/package.json index 3801b95465..b50329eff2 100644 --- a/tests/ember-data__request/package.json +++ b/tests/ember-data__request/package.json @@ -17,11 +17,12 @@ "scripts": { "build:tests": "IS_TESTING=true EMBER_CLI_TEST_COMMAND=true ember build --output-path=dist-test --suppress-sizes", "start": "bun run build:tests --watch", - "_build:production": "pnpm build:tests -e production", + "_temporarily_deactivated_build:production": "bun run build:tests -e production", "lint": "eslint . --quiet --cache --cache-strategy=content", "check:types": "tsc --noEmit", "test": "bun ./diagnostic.js", - "_test:production": "bun ./diagnostic.js" + "_temporarily_deactivated_test:production": "bun ./diagnostic.js", + "test:start": "bun ./diagnostic.js --serve --no-launch" }, "devDependencies": { "@babel/core": "^7.26.9", diff --git a/tests/main/package.json b/tests/main/package.json index 70a240f96e..8068f6bfef 100644 --- a/tests/main/package.json +++ b/tests/main/package.json @@ -14,14 +14,15 @@ }, "scripts": { "build:tests": "IS_TESTING=true EMBER_CLI_TEST_COMMAND=true ember build --output-path=dist-test --suppress-sizes", - "build:production": "pnpm build:tests -e production", + "build:production": "bun run build:tests -e production", "lint": "eslint . --quiet --cache --cache-strategy=content", "check:types": "glint", "examine": "export EXAM_PARALLEL_COUNT=$(./bin/calculate-test-jobs); ember exam --test-port=0 --path=dist-test --parallel=$EXAM_PARALLEL_COUNT --load-balance", "launch:tests": "ember test --test-port=0 --serve --no-launch", "start": "bun run build:tests --watch", "test": "bun run examine", - "test:production": "bun run examine" + "test:production": "bun run examine", + "test:start": "bun run ember test --test-port=0 --path=dist-test --serve --no-launch" }, "author": "", "license": "MIT", diff --git a/tests/warp-drive__ember/package.json b/tests/warp-drive__ember/package.json index 0b18bf2fb7..d93608cde2 100644 --- a/tests/warp-drive__ember/package.json +++ b/tests/warp-drive__ember/package.json @@ -16,12 +16,13 @@ }, "scripts": { "build:tests": "IS_TESTING=true EMBER_CLI_TEST_COMMAND=true ember build --output-path=dist-test --suppress-sizes", - "_build:production": "bun run build:tests -e production", + "_temporarily_deactivated_build:production": "bun run build:tests -e production", "lint": "eslint . --quiet --cache --cache-strategy=content", "check:types": "glint", "start": "bun run build:tests --watch", "test": "bun ./diagnostic.js", - "_test:production": "bun ./diagnostic.js" + "_temporarily_deactivated_test:production": "bun ./diagnostic.js", + "test:start": "bun ./diagnostic.js --serve --no-launch" }, "devDependencies": { "@babel/core": "^7.26.9", diff --git a/tests/warp-drive__experiments/package.json b/tests/warp-drive__experiments/package.json index 275281e63c..f27818aca6 100644 --- a/tests/warp-drive__experiments/package.json +++ b/tests/warp-drive__experiments/package.json @@ -16,12 +16,13 @@ }, "scripts": { "build:tests": "IS_TESTING=true EMBER_CLI_TEST_COMMAND=true ember build --output-path=dist-test --suppress-sizes", - "_build:production": "bun run build:tests -e production", + "build:production": "bun run build:tests -e production", "lint": "eslint . --quiet", "check:types": "tsc --noEmit", "start": "bun run build:tests --watch", "test": "bun ./diagnostic.js", - "_test:production": "bun ./diagnostic.js" + "test:production": "bun ./diagnostic.js", + "test:start": "bun ./diagnostic.js --serve --no-launch" }, "devDependencies": { "@babel/core": "^7.26.9", diff --git a/turbo.json b/turbo.json index 01a70ed230..1227a6341e 100644 --- a/turbo.json +++ b/turbo.json @@ -12,44 +12,21 @@ // ///////////////////////////////////////////////// ///////////////////////////////////////////////// - "build:infra": { - "inputs": [ - // + V2-Addon convention - "src/**", - "cjs-src/**", - "addon-main.*", - "package.json", - "tsconfig.json", - "babel.*", - "vite.config-cjs.*", - "vite.config.*", - "../../config/**" - ], - "outputs": [ - // V1-Addon convention - "addon-test-support/**", - // V2-Addon convention - "dist/**", - "unstable-preview-types/**", - "tsconfig.tsbuildinfo" - ], - "dependsOn": [], - // https://turbo.build/repo/docs/reference/configuration#outputmode - "outputMode": "new-only" - }, // run build in all library packages // these do not require any associated packages // to have been built to build other than - // the build:infra packages + // the build-config package "build:pkg": { "inputs": [ // + V2-Addon convention "src/**", + "cjs-src/**", // build-config package "addon-main.*", "tsconfig.json", "package.json", "babel.*", + "vite.config-cjs.*", // build-config package "vite.config.*", "../../config/**" ], @@ -61,7 +38,7 @@ "unstable-preview-types/**", "tsconfig.tsbuildinfo" ], - "dependsOn": ["^build:infra", "^build:pkg"], + "dependsOn": ["^build:pkg"], // https://turbo.build/repo/docs/reference/configuration#outputmode "outputMode": "new-only" }, @@ -70,7 +47,7 @@ // that ship gts files // these do not require any associated packages // to have been built to build other than - // the build:infra packages + // the build-config package "build:glint": { "inputs": [ // + V2-Addon convention @@ -106,10 +83,10 @@ ///////////////////////////////////////////////// ///////////////////////////////////////////////// "start": { - // "dependsOn": ["^_build"], + "dependsOn": ["^build:pkg"], // "outputs": [], - // "cache": false, - // "persistent": true + "cache": false, + "persistent": true }, /////////////////////////////////////////////////