From 26f1096fa385623157f010ff88dcfb727ae6ceae Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Tue, 9 Jun 2026 15:53:01 -0400 Subject: [PATCH 01/38] build: pin Node >=24 across engines, .nvmrc, and CI Native Node 24 type-stripping is the target runtime for the ts-node migration. Set engines.node to ">=24" at the root and align packages that still declared older floors (boxel-cli was ">= 18"; host and eslint-plugin-boxel were ">= 20"). Add a root .nvmrc matching the existing .mise.toml pin (24.13.1), and bump the one stray CI setup-node from 20 to 24. Co-Authored-By: Claude Opus 4.8 (1M context) --- packages/eslint-plugin-boxel/package.json | 2 +- packages/host/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/eslint-plugin-boxel/package.json b/packages/eslint-plugin-boxel/package.json index d45b48889f..298c002048 100644 --- a/packages/eslint-plugin-boxel/package.json +++ b/packages/eslint-plugin-boxel/package.json @@ -63,6 +63,6 @@ "vitest": "catalog:" }, "engines": { - "node": ">= 20" + "node": ">=24" } } diff --git a/packages/host/package.json b/packages/host/package.json index da9a5d294f..051d9ff0d3 100644 --- a/packages/host/package.json +++ b/packages/host/package.json @@ -198,7 +198,7 @@ "unique-names-generator": "^4.7.1" }, "engines": { - "node": ">= 20" + "node": ">=24" }, "ember": { "edition": "octane" From 07a5b56c04539a2d781bee2a5698f7ac58bee674 Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Tue, 9 Jun 2026 15:53:18 -0400 Subject: [PATCH 02/38] refactor: make runtime-common resolvable by native Node (ESM exports) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Native Node ignores ts-node's resolver: it reads package.json exports and will neither fall back to index.js nor extension-resolve bare specifiers. Add an exports map pointing at the .ts sources so both native Node and the host's Vite/Embroider build resolve the package and its subpaths (bare entry, explicit directory-index subpaths, and a "./*" -> "./*.ts" wildcard); keep the existing #fetch/#lint-task imports. Do not set "type":"module" — the package ships CJS .js eslint configs that would break, so Node's per-file syntax detection handles the mix. Replace the runtime constructs native Node rejects under ESM: the lazy require() in fetch-node.ts (now createRequire) and url-signature.ts (now a bare crypto import, which the host already aliases to crypto-browserify), and __dirname -> import.meta.dirname. Flip the bench:amd scripts and their dynamic requires to native node, drop the ts-node devDependency, and drop the now-redundant .ts extension on the marked-sync shim import in the host so it resolves through the exports map. Co-Authored-By: Claude Opus 4.8 (1M context) --- packages/host/app/lib/externals.ts | 2 +- packages/runtime-common/fetch-node.ts | 6 +++++ .../runtime-common/lint/submission-lint.ts | 2 +- packages/runtime-common/package.json | 23 +++++++++++++------ .../runtime-common/scripts/bench-amd/bench.ts | 6 ++--- .../runtime-common/scripts/bench-amd/paths.ts | 6 ++--- .../scripts/bench-amd/prepare-fixtures.ts | 8 +++---- packages/runtime-common/url-signature.ts | 12 +++++----- pnpm-lock.yaml | 3 --- 9 files changed, 39 insertions(+), 29 deletions(-) diff --git a/packages/host/app/lib/externals.ts b/packages/host/app/lib/externals.ts index dbbd2e274c..52317de3b8 100644 --- a/packages/host/app/lib/externals.ts +++ b/packages/host/app/lib/externals.ts @@ -199,7 +199,7 @@ export function shimExternals(virtualNetwork: VirtualNetwork) { }); virtualNetwork.shimAsyncModule({ id: '@cardstack/runtime-common/marked-sync', - resolve: () => import('@cardstack/runtime-common/marked-sync.ts'), + resolve: () => import('@cardstack/runtime-common/marked-sync'), }); shimModulesForLiveTests(virtualNetwork); diff --git a/packages/runtime-common/fetch-node.ts b/packages/runtime-common/fetch-node.ts index 9872b7114c..59568e41b9 100644 --- a/packages/runtime-common/fetch-node.ts +++ b/packages/runtime-common/fetch-node.ts @@ -1,3 +1,9 @@ +import { createRequire } from 'node:module'; + +// Node-only module; resolved via the package `#fetch` condition. Browsers get +// fetch-browser.ts instead, so this CJS bridge never reaches a bundle. +const require = createRequire(import.meta.url); + /** * Creates a fetch implementation that's appropriate for the current environment. * In Node.js, it enhances localhost subdomain resolution using Undici agent. diff --git a/packages/runtime-common/lint/submission-lint.ts b/packages/runtime-common/lint/submission-lint.ts index c1b66de3d3..52d19ddcca 100644 --- a/packages/runtime-common/lint/submission-lint.ts +++ b/packages/runtime-common/lint/submission-lint.ts @@ -12,7 +12,7 @@ if (typeof (globalThis as any).document !== 'undefined') { const log = logger('submission-lint'); -const REPO_ROOT = path.resolve(__dirname, '..', '..', '..'); +const REPO_ROOT = path.resolve(import.meta.dirname, '..', '..', '..'); const CATALOG_DIR = path.join(REPO_ROOT, 'packages', 'catalog'); const HOST_DIR = path.join(REPO_ROOT, 'packages', 'host'); export const SUBMISSIONS_TEMP_ROOT = path.join( diff --git a/packages/runtime-common/package.json b/packages/runtime-common/package.json index c0cb2b6f23..7ef4ec26c3 100644 --- a/packages/runtime-common/package.json +++ b/packages/runtime-common/package.json @@ -12,6 +12,16 @@ "browser": "./fetch-browser.ts" } }, + "exports": { + ".": "./index.ts", + "./package.json": "./package.json", + "./ai": "./ai/index.ts", + "./amd-transpile": "./amd-transpile/index.ts", + "./helpers": "./helpers/index.ts", + "./serializers": "./serializers/index.ts", + "./tasks": "./tasks/index.ts", + "./*": "./*.ts" + }, "dependencies": { "@aws-crypto/sha256-js": "catalog:", "@babel/generator": "catalog:", @@ -96,8 +106,7 @@ "monaco-editor": "catalog:", "statuses": "catalog:", "@glint/ember-tsc": "catalog:", - "es-module-lexer": "^1.7.0", - "ts-node": "^10.9.1" + "es-module-lexer": "^1.7.0" }, "peerDependencies": { "@babel/core": "catalog:", @@ -108,10 +117,10 @@ "lint:js": "eslint . ", "lint:js:fix": "eslint . --report-unused-disable-directives --fix", "lint:types": "ember-tsc --noEmit", - "bench:amd:prep": "NODE_NO_WARNINGS=1 ts-node --transpileOnly scripts/bench-amd/prepare-fixtures.ts", - "bench:amd": "NODE_NO_WARNINGS=1 ts-node --transpileOnly scripts/bench-amd/bench.ts", - "bench:amd:check": "NODE_NO_WARNINGS=1 ts-node --transpileOnly scripts/bench-amd/check.ts", - "bench:amd:check:trip-test": "NODE_NO_WARNINGS=1 ts-node --transpileOnly scripts/bench-amd/trip-test.ts", - "bench:amd:trip-drill": "NODE_NO_WARNINGS=1 ts-node --transpileOnly scripts/bench-amd/trip-drill.ts" + "bench:amd:prep": "NODE_NO_WARNINGS=1 node scripts/bench-amd/prepare-fixtures.ts", + "bench:amd": "NODE_NO_WARNINGS=1 node scripts/bench-amd/bench.ts", + "bench:amd:check": "NODE_NO_WARNINGS=1 node scripts/bench-amd/check.ts", + "bench:amd:check:trip-test": "NODE_NO_WARNINGS=1 node scripts/bench-amd/trip-test.ts", + "bench:amd:trip-drill": "NODE_NO_WARNINGS=1 node scripts/bench-amd/trip-drill.ts" } } diff --git a/packages/runtime-common/scripts/bench-amd/bench.ts b/packages/runtime-common/scripts/bench-amd/bench.ts index 1e9c7dc2e9..8946f73b58 100644 --- a/packages/runtime-common/scripts/bench-amd/bench.ts +++ b/packages/runtime-common/scripts/bench-amd/bench.ts @@ -12,6 +12,7 @@ import { readdirSync, readFileSync } from 'node:fs'; import path from 'node:path'; import { performance } from 'node:perf_hooks'; +import { pathToFileURL } from 'node:url'; import { candidatesDir, fixturesDir } from './paths.ts'; @@ -69,9 +70,8 @@ export async function loadCandidates(): Promise { .sort(); const candidates: Candidate[] = []; for (const f of candidateFiles) { - // ts-node intercepts `.ts` so `require()` returns the compiled module. - // eslint-disable-next-line @typescript-eslint/no-var-requires - const mod = require(path.join(candidatesDir, f)); + // Native Node strips types from the `.ts` candidate on import. + const mod = await import(pathToFileURL(path.join(candidatesDir, f)).href); if (typeof mod.transform === 'function') { candidates.push({ name: mod.name ?? f.replace(/\.ts$/, ''), diff --git a/packages/runtime-common/scripts/bench-amd/paths.ts b/packages/runtime-common/scripts/bench-amd/paths.ts index 5acc8aa4ed..d39de9198b 100644 --- a/packages/runtime-common/scripts/bench-amd/paths.ts +++ b/packages/runtime-common/scripts/bench-amd/paths.ts @@ -3,7 +3,7 @@ // stay in lockstep when the layout changes. import path from 'node:path'; -export const repoRoot = path.resolve(__dirname, '../../../..'); +export const repoRoot = path.resolve(import.meta.dirname, '../../../..'); // Committed, hermetic fixtures. Generated by `pnpm bench:amd:prep`. The // bench gate reads only from this path so that edits to card sources @@ -13,7 +13,7 @@ export const fixturesDir = path.join( 'bench-fixtures/runtime-common/amd-transpile', ); -export const candidatesDir = path.join(__dirname, 'candidates'); +export const candidatesDir = path.join(import.meta.dirname, 'candidates'); // `BENCH_AMD_BASELINE_OVERRIDE` redirects the gate to read a synthetic // baseline from somewhere else on disk. Used by the trip-test to prove @@ -21,4 +21,4 @@ export const candidatesDir = path.join(__dirname, 'candidates'); // `baseline.json`. Default unchanged. export const baselinePath = process.env.BENCH_AMD_BASELINE_OVERRIDE ?? - path.join(__dirname, 'baseline.json'); + path.join(import.meta.dirname, 'baseline.json'); diff --git a/packages/runtime-common/scripts/bench-amd/prepare-fixtures.ts b/packages/runtime-common/scripts/bench-amd/prepare-fixtures.ts index 7d07b2db91..791ad206bf 100644 --- a/packages/runtime-common/scripts/bench-amd/prepare-fixtures.ts +++ b/packages/runtime-common/scripts/bench-amd/prepare-fixtures.ts @@ -35,11 +35,9 @@ const fixtures: { name: string; file: string }[] = [ const ContentTag = await import('content-tag'); (globalThis as any).ContentTagGlobal = ContentTag; - // transpile.ts is in the runtime-common package; ts-node intercepts the - // `.ts` extension via require. - const { transpileJS } = - // eslint-disable-next-line @typescript-eslint/no-var-requires - require('../../transpile') as typeof import('../../transpile.ts'); + // transpile.ts is in the runtime-common package; native Node strips its + // types on import. + const { transpileJS } = await import('../../transpile.ts'); mkdirSync(fixturesDir, { recursive: true }); diff --git a/packages/runtime-common/url-signature.ts b/packages/runtime-common/url-signature.ts index f0d9e839d8..a8a81d0ba6 100644 --- a/packages/runtime-common/url-signature.ts +++ b/packages/runtime-common/url-signature.ts @@ -7,6 +7,11 @@ * - urlPath is the pathname + search params (without the sig param) */ +// HMAC for the Node-only signing path below. Bare `crypto` resolves to the +// Node builtin under native Node, and to crypto-browserify in the host build +// via its Vite alias (host browsers only reach the Web Crypto path above). +import { createHmac } from 'crypto'; + // Browser implementation using Web Crypto API export async function createURLSignature( token: string, @@ -39,16 +44,11 @@ export async function createURLSignature( // Node.js implementation export function createURLSignatureSync(token: string, url: URL): string { - // Dynamic import to avoid issues in browser - // eslint-disable-next-line @typescript-eslint/no-var-requires - let crypto = require('crypto'); - let urlForSigning = new URL(url.href); urlForSigning.searchParams.delete('sig'); let message = urlForSigning.pathname + urlForSigning.search; - let signature = crypto - .createHmac('sha256', token) + let signature = createHmac('sha256', token) .update(message) .digest('base64url'); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index be35c65538..5f203844dc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3156,9 +3156,6 @@ importers: statuses: specifier: 'catalog:' version: 2.0.2 - ts-node: - specifier: ^10.9.1 - version: 10.9.2(@types/node@25.7.0)(typescript@5.9.3) packages/skills-realm: {} From 3b1dbc87e6a2d80fa611809d528c5813b4ca455c Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Tue, 9 Jun 2026 16:09:45 -0400 Subject: [PATCH 03/38] refactor: resolve runtime-common third-party imports under native Node ESM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The host's Vite/Embroider build adds extensions and index-resolves, so it hid import forms that native Node's ESM resolver rejects. Make every import in runtime-common resolvable by native Node (verified by importing the package and all subpaths under `node`, no bundler): - Add `.js` to extensionless CJS-package subpath imports that have no exports map (lodash/, matrix-js-sdk/lib/utils — the latter has both a utils.js file and a utils/ directory, and ESM picks the dir). - Replace the named import from lodash's CJS root in catalog.ts with per-method default imports (Node can't statically detect lodash's CJS named exports). - Point the three bare-directory barrel imports (`from '.'`) at `./index.ts` (native ESM does not index-resolve directories). Co-Authored-By: Claude Opus 4.8 (1M context) --- packages/runtime-common/ai/matrix-utils.ts | 2 +- packages/runtime-common/cached-fetch.ts | 2 +- packages/runtime-common/catalog.ts | 4 +++- packages/runtime-common/expression.ts | 4 ++-- packages/runtime-common/index-query-engine.ts | 2 +- packages/runtime-common/index-runner/card-indexer.ts | 2 +- packages/runtime-common/index-writer.ts | 4 ++-- packages/runtime-common/instance-filter-matcher.ts | 2 +- packages/runtime-common/jobs/indexing.ts | 2 +- packages/runtime-common/loader.ts | 2 +- packages/runtime-common/merge-relationships.ts | 2 +- packages/runtime-common/module-syntax.ts | 2 +- packages/runtime-common/query.ts | 2 +- packages/runtime-common/realm-index-query-engine.ts | 4 ++-- packages/runtime-common/realm-index-updater.ts | 2 +- packages/runtime-common/realm.ts | 10 +++++----- packages/runtime-common/worker.ts | 2 +- 17 files changed, 26 insertions(+), 24 deletions(-) diff --git a/packages/runtime-common/ai/matrix-utils.ts b/packages/runtime-common/ai/matrix-utils.ts index 68f52829da..0d5e0f3d46 100644 --- a/packages/runtime-common/ai/matrix-utils.ts +++ b/packages/runtime-common/ai/matrix-utils.ts @@ -21,7 +21,7 @@ import { import type { MatrixEvent as DiscreteMatrixEvent } from 'https://cardstack.com/base/matrix-event'; import type { MatrixEvent } from 'matrix-js-sdk'; import type { PromptParts } from './types.ts'; -import { encodeUri } from 'matrix-js-sdk/lib/utils'; +import { encodeUri } from 'matrix-js-sdk/lib/utils.js'; import type { SerializedFileDef } from 'https://cardstack.com/base/file-api'; import { isTextBasedContentType } from './modality.ts'; diff --git a/packages/runtime-common/cached-fetch.ts b/packages/runtime-common/cached-fetch.ts index ae622fa5f1..1c1ff5f226 100644 --- a/packages/runtime-common/cached-fetch.ts +++ b/packages/runtime-common/cached-fetch.ts @@ -1,4 +1,4 @@ -import merge from 'lodash/merge'; +import merge from 'lodash/merge.js'; import { isNode } from './index.ts'; diff --git a/packages/runtime-common/catalog.ts b/packages/runtime-common/catalog.ts index da78af0b9e..74ba448fdb 100644 --- a/packages/runtime-common/catalog.ts +++ b/packages/runtime-common/catalog.ts @@ -1,4 +1,6 @@ -import { isEqual, uniqWith, kebabCase } from 'lodash'; +import isEqual from 'lodash/isEqual.js'; +import uniqWith from 'lodash/uniqWith.js'; +import kebabCase from 'lodash/kebabCase.js'; import { v4 as uuidv4 } from 'uuid'; import type { Spec } from 'https://cardstack.com/base/spec'; import type { CardDef } from 'https://cardstack.com/base/card-api'; diff --git a/packages/runtime-common/expression.ts b/packages/runtime-common/expression.ts index f24bb363eb..a4bbe23dad 100644 --- a/packages/runtime-common/expression.ts +++ b/packages/runtime-common/expression.ts @@ -1,7 +1,7 @@ import type * as JSONTypes from 'json-typescript'; -import isPlainObject from 'lodash/isPlainObject'; +import isPlainObject from 'lodash/isPlainObject.js'; import stringify from 'safe-stable-stringify'; -import flattenDeep from 'lodash/flattenDeep'; +import flattenDeep from 'lodash/flattenDeep.js'; import type { CodeRef, DBAdapter, TypeCoercion } from './index.ts'; diff --git a/packages/runtime-common/index-query-engine.ts b/packages/runtime-common/index-query-engine.ts index ff5bb4a7ed..b1c8405ede 100644 --- a/packages/runtime-common/index-query-engine.ts +++ b/packages/runtime-common/index-query-engine.ts @@ -1,5 +1,5 @@ import type * as JSONTypes from 'json-typescript'; -import flatten from 'lodash/flatten'; +import flatten from 'lodash/flatten.js'; import stringify from 'safe-stable-stringify'; import type { ResolvedCodeRef } from './index.ts'; import type { RealmResourceIdentifier } from './realm-identifiers.ts'; diff --git a/packages/runtime-common/index-runner/card-indexer.ts b/packages/runtime-common/index-runner/card-indexer.ts index 509cd2cae3..488701f073 100644 --- a/packages/runtime-common/index-runner/card-indexer.ts +++ b/packages/runtime-common/index-runner/card-indexer.ts @@ -1,4 +1,4 @@ -import merge from 'lodash/merge'; +import merge from 'lodash/merge.js'; import { jobIdentity, diff --git a/packages/runtime-common/index-writer.ts b/packages/runtime-common/index-writer.ts index 0476b683b5..689a7c5782 100644 --- a/packages/runtime-common/index-writer.ts +++ b/packages/runtime-common/index-writer.ts @@ -1,5 +1,5 @@ -import flatten from 'lodash/flatten'; -import flattenDeep from 'lodash/flattenDeep'; +import flatten from 'lodash/flatten.js'; +import flattenDeep from 'lodash/flattenDeep.js'; import { type CardResource, type JobInfo, diff --git a/packages/runtime-common/instance-filter-matcher.ts b/packages/runtime-common/instance-filter-matcher.ts index 419f4f1744..7fcec99cad 100644 --- a/packages/runtime-common/instance-filter-matcher.ts +++ b/packages/runtime-common/instance-filter-matcher.ts @@ -1,4 +1,4 @@ -import isEqual from 'lodash/isEqual'; +import isEqual from 'lodash/isEqual.js'; import { getField, identifyCard } from './code-ref.ts'; import { diff --git a/packages/runtime-common/jobs/indexing.ts b/packages/runtime-common/jobs/indexing.ts index 6b2634c236..6cd7a11d19 100644 --- a/packages/runtime-common/jobs/indexing.ts +++ b/packages/runtime-common/jobs/indexing.ts @@ -7,7 +7,7 @@ import type { } from '../tasks/indexer.ts'; import type { PgPrimitive } from '../expression.ts'; import { v4 as uuidv4 } from '@lukeed/uuid'; -import isObjectLike from 'lodash/isObjectLike'; +import isObjectLike from 'lodash/isObjectLike.js'; export const INCREMENTAL_INDEX_JOB_TIMEOUT_SEC = 10 * 60; diff --git a/packages/runtime-common/loader.ts b/packages/runtime-common/loader.ts index 8282d0b23b..3528c9d92b 100644 --- a/packages/runtime-common/loader.ts +++ b/packages/runtime-common/loader.ts @@ -4,7 +4,7 @@ import { cachedFetch, type MaybeCachedResponse } from './cached-fetch.ts'; import { executableExtensions, logger } from './index.ts'; import { CardError, iconNotFoundMessage } from './error.ts'; -import flatMap from 'lodash/flatMap'; +import flatMap from 'lodash/flatMap.js'; import { shouldTrackRuntimeModuleGraph, trackRuntimeModuleDependency, diff --git a/packages/runtime-common/merge-relationships.ts b/packages/runtime-common/merge-relationships.ts index 31207b2745..e1f6af8a0d 100644 --- a/packages/runtime-common/merge-relationships.ts +++ b/packages/runtime-common/merge-relationships.ts @@ -1,6 +1,6 @@ import type { LooseCardResource, Relationship } from './index.ts'; import { relationshipEntries } from './relationship-utils.ts'; -import mergeWith from 'lodash/mergeWith'; +import mergeWith from 'lodash/mergeWith.js'; export function mergeRelationships( relData: LooseCardResource['relationships'], diff --git a/packages/runtime-common/module-syntax.ts b/packages/runtime-common/module-syntax.ts index 42d6f273d9..43b547187a 100644 --- a/packages/runtime-common/module-syntax.ts +++ b/packages/runtime-common/module-syntax.ts @@ -17,7 +17,7 @@ import type { Options as RemoveOptions } from './remove-field-plugin.ts'; import { removeFieldPlugin } from './remove-field-plugin.ts'; import { ImportUtil } from 'babel-import-util'; import camelCase from 'camelcase'; -import isEqual from 'lodash/isEqual'; +import isEqual from 'lodash/isEqual.js'; import * as ContentTag from 'content-tag'; import { diff --git a/packages/runtime-common/query.ts b/packages/runtime-common/query.ts index d6cecadb62..a479f7ac1f 100644 --- a/packages/runtime-common/query.ts +++ b/packages/runtime-common/query.ts @@ -1,4 +1,4 @@ -import isEqual from 'lodash/isEqual'; +import isEqual from 'lodash/isEqual.js'; import { assertJSONValue, assertJSONPrimitive } from './json-validation.ts'; import qs from 'qs'; diff --git a/packages/runtime-common/realm-index-query-engine.ts b/packages/runtime-common/realm-index-query-engine.ts index 9609957402..8d1ffc6610 100644 --- a/packages/runtime-common/realm-index-query-engine.ts +++ b/packages/runtime-common/realm-index-query-engine.ts @@ -1,5 +1,5 @@ import { isScopedCSSRequest } from './scoped-css.ts'; -import cloneDeep from 'lodash/cloneDeep'; +import cloneDeep from 'lodash/cloneDeep.js'; import { SupportedMimeType, isJsonContentType, @@ -25,7 +25,7 @@ import { visitInstanceURLs, maybeRelativeReference, codeRefFromInternalKey, -} from '.'; +} from './index.ts'; import type { Realm } from './realm.ts'; import type { VirtualNetwork } from './virtual-network.ts'; import { FILE_META_RESERVED_KEYS } from './realm.ts'; diff --git a/packages/runtime-common/realm-index-updater.ts b/packages/runtime-common/realm-index-updater.ts index 4f01509d32..aac0b7cd97 100644 --- a/packages/runtime-common/realm-index-updater.ts +++ b/packages/runtime-common/realm-index-updater.ts @@ -10,7 +10,7 @@ import { type QueuePublisher, type CopyArgs, type CopyResult, -} from '.'; +} from './index.ts'; import { INCREMENTAL_INDEX_JOB_TIMEOUT_SEC, makeIncrementalArgsWithCallerMetadata, diff --git a/packages/runtime-common/realm.ts b/packages/runtime-common/realm.ts index 9d8d40e287..ee45d94e98 100644 --- a/packages/runtime-common/realm.ts +++ b/packages/runtime-common/realm.ts @@ -107,11 +107,11 @@ import { } from './index.ts'; import type { FromScratchResult } from './tasks/indexer.ts'; import { isCodeRef, visitModuleDeps } from './code-ref.ts'; -import merge from 'lodash/merge'; -import mergeWith from 'lodash/mergeWith'; -import cloneDeep from 'lodash/cloneDeep'; -import isEqual from 'lodash/isEqual'; -import isPlainObject from 'lodash/isPlainObject'; +import merge from 'lodash/merge.js'; +import mergeWith from 'lodash/mergeWith.js'; +import cloneDeep from 'lodash/cloneDeep.js'; +import isEqual from 'lodash/isEqual.js'; +import isPlainObject from 'lodash/isPlainObject.js'; import { z } from 'zod'; import { inferContentType } from './infer-content-type.ts'; import { diff --git a/packages/runtime-common/worker.ts b/packages/runtime-common/worker.ts index 36067465e1..54c4891baf 100644 --- a/packages/runtime-common/worker.ts +++ b/packages/runtime-common/worker.ts @@ -24,7 +24,7 @@ import { type DBAdapter, type RealmPermissions, CachingDefinitionLookup, -} from '.'; +} from './index.ts'; import { MatrixClient } from './matrix-client.ts'; import * as Tasks from './tasks/index.ts'; import type { WorkerArgs, TaskArgs } from './tasks/index.ts'; From f3d772a0c594ac6d22c55318c75b7c7464545018 Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Tue, 9 Jun 2026 16:09:59 -0400 Subject: [PATCH 04/38] refactor: migrate postgres to native-Node ESM resolution postgres is the first leaf consumer of runtime-common to run on native Node. Add an exports map pointing at its .ts sources (".", "./*", and "./package.json") so consumers resolve the package and its subpaths without ts-node; replace __dirname with import.meta.dirname in pg-adapter.ts and convert-to-sqlite.ts; flip the migrate and make-schema scripts from ts-node to native node; and drop the ts-node dependency. Leave "type" unset so Node's syntax detection keeps the package's CJS .js migration helpers working alongside the ESM .ts sources. Verified by importing @cardstack/postgres (and its runtime-common dependency chain) under native node. Co-Authored-By: Claude Opus 4.8 (1M context) --- packages/postgres/package.json | 10 ++++++--- packages/postgres/pg-adapter.ts | 2 +- .../postgres/scripts/convert-to-sqlite.ts | 4 ++-- packages/postgres/scripts/schema-dump.sh | 2 +- pnpm-lock.yaml | 21 ------------------- 5 files changed, 11 insertions(+), 28 deletions(-) diff --git a/packages/postgres/package.json b/packages/postgres/package.json index 4e55d8c97d..a1314a4371 100644 --- a/packages/postgres/package.json +++ b/packages/postgres/package.json @@ -2,6 +2,11 @@ "name": "@cardstack/postgres", "version": "0.0.0", "license": "MIT", + "exports": { + ".": "./index.ts", + "./package.json": "./package.json", + "./*": "./*.ts" + }, "dependencies": { "@cardstack/runtime-common": "workspace:*", "@sentry/node": "catalog:", @@ -9,8 +14,7 @@ "@types/pg": "catalog:", "fs-extra": "catalog:", "node-pg-migrate": "catalog:", - "pg": "catalog:", - "ts-node": "^10.9.1" + "pg": "catalog:" }, "devDependencies": { "@cardstack/local-types": "workspace:*", @@ -21,7 +25,7 @@ "scripts": { "start:pg": "./scripts/start-pg.sh", "stop:pg": "./scripts/stop-pg.sh", - "migrate": "PGDATABASE=boxel ./scripts/ensure-db-exists.sh && PGPORT=5435 PGDATABASE=boxel PGUSER=postgres ts-node --transpileOnly ./scripts/fix-migration-names.ts && PGPORT=5435 PGDATABASE=boxel PGUSER=postgres node-pg-migrate --migrations-table migrations --no-check-order --verbose=false", + "migrate": "PGDATABASE=boxel ./scripts/ensure-db-exists.sh && PGPORT=5435 PGDATABASE=boxel PGUSER=postgres node ./scripts/fix-migration-names.ts && PGPORT=5435 PGDATABASE=boxel PGUSER=postgres node-pg-migrate --migrations-table migrations --no-check-order --verbose=false", "make-schema": "./scripts/schema-dump.sh", "drop-db": "docker exec boxel-pg dropdb --if-exists -U postgres -w", "lint": "concurrently \"pnpm:lint:*(!fix)\" --names \"lint:\"", diff --git a/packages/postgres/pg-adapter.ts b/packages/postgres/pg-adapter.ts index 07ca49b40f..3d6b1b9d56 100644 --- a/packages/postgres/pg-adapter.ts +++ b/packages/postgres/pg-adapter.ts @@ -658,7 +658,7 @@ export class PgAdapter implements DBAdapter { port: config.port, }, count: Infinity, - dir: join(__dirname, 'migrations'), + dir: join(import.meta.dirname, 'migrations'), ignorePattern: '.*\\.eslintrc\\.js', log: enableLogging ? (...args) => log.info(...args) : () => undefined, }); diff --git a/packages/postgres/scripts/convert-to-sqlite.ts b/packages/postgres/scripts/convert-to-sqlite.ts index b6016c8c34..ffbd68087b 100755 --- a/packages/postgres/scripts/convert-to-sqlite.ts +++ b/packages/postgres/scripts/convert-to-sqlite.ts @@ -16,9 +16,9 @@ import { // much more simplistic than postgres. const args = process.argv; -const migrationsDir = resolve(join(__dirname, '..', 'migrations')); +const migrationsDir = resolve(join(import.meta.dirname, '..', 'migrations')); const sqliteSchemaDir = resolve( - join(__dirname, '..', '..', 'host', 'config', 'schema'), + join(import.meta.dirname, '..', '..', 'host', 'config', 'schema'), ); const INDENT = ' '; const SQLITE_PK_COLUMN_MAPPING: Record> = { diff --git a/packages/postgres/scripts/schema-dump.sh b/packages/postgres/scripts/schema-dump.sh index 75d5d4d648..e947ea3e59 100755 --- a/packages/postgres/scripts/schema-dump.sh +++ b/packages/postgres/scripts/schema-dump.sh @@ -38,5 +38,5 @@ docker exec boxel-pg pg_dump \ --no-acl \ boxel >$tmpFile -ts-node --transpileOnly ./scripts/convert-to-sqlite.ts $tmpFile +node ./scripts/convert-to-sqlite.ts $tmpFile rm $tmpFile diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5f203844dc..4c1aa64c65 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2559,9 +2559,6 @@ importers: pg: specifier: 'catalog:' version: 8.20.0 - ts-node: - specifier: ^10.9.1 - version: 10.9.2(@types/node@25.7.0)(typescript@5.9.3) devDependencies: '@cardstack/local-types': specifier: workspace:* @@ -30487,24 +30484,6 @@ snapshots: v8-compile-cache-lib: 3.0.1 yn: 3.1.1 - ts-node@10.9.2(@types/node@25.7.0)(typescript@5.9.3): - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.12 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.4 - '@types/node': 25.7.0 - acorn: 8.16.0 - acorn-walk: 8.3.5 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.4 - make-error: 1.3.6 - typescript: 5.9.3 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - tsconfig-paths@3.15.0: dependencies: '@types/json5': 0.0.29 From 1914a63a543b3efcab312058046304490c4b36fd Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Tue, 9 Jun 2026 17:32:53 -0400 Subject: [PATCH 05/38] wip: type:module foundation for ESM big-bang (parked) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Foundation toward the full node-run ESM migration: type:module on runtime-common + postgres, nested package.json {type:commonjs} for their CJS dirs (etc/eslint, migrations), .cjs renames for stray CJS files, and revert of the collateral host/eslint-plugin engines bumps. Resolves TS1470 but TS2307 (base path aliases) and TS2349 (CJS interop) remain, plus all consumers still need migrating. Parked — not green. --- packages/eslint-plugin-boxel/package.json | 2 +- packages/host/package.json | 2 +- packages/postgres/{.eslintrc.js => .eslintrc.cjs} | 0 packages/postgres/migrations/package.json | 3 +++ packages/postgres/package.json | 3 ++- packages/postgres/scripts/fix-migration-names.ts | 2 +- .../scripts/{lint-migrations.js => lint-migrations.cjs} | 0 .../{migration-name-fixes.js => migration-name-fixes.cjs} | 0 packages/runtime-common/etc/eslint/package.json | 3 +++ packages/runtime-common/package.json | 1 + 10 files changed, 12 insertions(+), 4 deletions(-) rename packages/postgres/{.eslintrc.js => .eslintrc.cjs} (100%) create mode 100644 packages/postgres/migrations/package.json rename packages/postgres/scripts/{lint-migrations.js => lint-migrations.cjs} (100%) rename packages/postgres/scripts/{migration-name-fixes.js => migration-name-fixes.cjs} (100%) create mode 100644 packages/runtime-common/etc/eslint/package.json diff --git a/packages/eslint-plugin-boxel/package.json b/packages/eslint-plugin-boxel/package.json index 298c002048..d45b48889f 100644 --- a/packages/eslint-plugin-boxel/package.json +++ b/packages/eslint-plugin-boxel/package.json @@ -63,6 +63,6 @@ "vitest": "catalog:" }, "engines": { - "node": ">=24" + "node": ">= 20" } } diff --git a/packages/host/package.json b/packages/host/package.json index 051d9ff0d3..da9a5d294f 100644 --- a/packages/host/package.json +++ b/packages/host/package.json @@ -198,7 +198,7 @@ "unique-names-generator": "^4.7.1" }, "engines": { - "node": ">=24" + "node": ">= 20" }, "ember": { "edition": "octane" diff --git a/packages/postgres/.eslintrc.js b/packages/postgres/.eslintrc.cjs similarity index 100% rename from packages/postgres/.eslintrc.js rename to packages/postgres/.eslintrc.cjs diff --git a/packages/postgres/migrations/package.json b/packages/postgres/migrations/package.json new file mode 100644 index 0000000000..5bbefffbab --- /dev/null +++ b/packages/postgres/migrations/package.json @@ -0,0 +1,3 @@ +{ + "type": "commonjs" +} diff --git a/packages/postgres/package.json b/packages/postgres/package.json index a1314a4371..a43832a3ed 100644 --- a/packages/postgres/package.json +++ b/packages/postgres/package.json @@ -2,6 +2,7 @@ "name": "@cardstack/postgres", "version": "0.0.0", "license": "MIT", + "type": "module", "exports": { ".": "./index.ts", "./package.json": "./package.json", @@ -32,7 +33,7 @@ "lint:fix": "concurrently \"pnpm:lint:*:fix\" --names \"fix:\"", "lint:js": "eslint . --report-unused-disable-directives --cache", "lint:js:fix": "eslint . --report-unused-disable-directives --fix", - "lint:migrations": "node ./scripts/lint-migrations.js", + "lint:migrations": "node ./scripts/lint-migrations.cjs", "lint:types": "ember-tsc --noEmit" } } diff --git a/packages/postgres/scripts/fix-migration-names.ts b/packages/postgres/scripts/fix-migration-names.ts index 0ee566d446..efc7fc82f2 100755 --- a/packages/postgres/scripts/fix-migration-names.ts +++ b/packages/postgres/scripts/fix-migration-names.ts @@ -1,7 +1,7 @@ /* eslint-env node */ import { Client } from 'pg'; -import migrationNameFixes from './migration-name-fixes.js'; +import migrationNameFixes from './migration-name-fixes.cjs'; type MigrationNameFixes = { migrationRenames: Array<[string, string]>; diff --git a/packages/postgres/scripts/lint-migrations.js b/packages/postgres/scripts/lint-migrations.cjs similarity index 100% rename from packages/postgres/scripts/lint-migrations.js rename to packages/postgres/scripts/lint-migrations.cjs diff --git a/packages/postgres/scripts/migration-name-fixes.js b/packages/postgres/scripts/migration-name-fixes.cjs similarity index 100% rename from packages/postgres/scripts/migration-name-fixes.js rename to packages/postgres/scripts/migration-name-fixes.cjs diff --git a/packages/runtime-common/etc/eslint/package.json b/packages/runtime-common/etc/eslint/package.json new file mode 100644 index 0000000000..5bbefffbab --- /dev/null +++ b/packages/runtime-common/etc/eslint/package.json @@ -0,0 +1,3 @@ +{ + "type": "commonjs" +} diff --git a/packages/runtime-common/package.json b/packages/runtime-common/package.json index 7ef4ec26c3..46f939d706 100644 --- a/packages/runtime-common/package.json +++ b/packages/runtime-common/package.json @@ -2,6 +2,7 @@ "name": "@cardstack/runtime-common", "version": "1.0.0", "license": "MIT", + "type": "module", "imports": { "#lint-task": { "node": "./tasks/lint.ts", From 70137aa7b31c9e2d278f888c078cf041eeb32a97 Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Wed, 17 Jun 2026 13:57:10 -0400 Subject: [PATCH 06/38] refactor: migrate node-run cluster from ts-node to native Node ESM Swap ts-node for native Node (>=24) TypeScript execution across the node-run package cluster: runtime-common, postgres, billing, realm-server, realm-test-harness, ai-bot, bot-runner, matrix, and software-factory. All five service entries plus ai-bot and bot-runner now link their full module graph under native node. Native Node ESM is stricter than ts-node/Vite about resolution; the recurring breakages and their fixes are captured as a reusable, idempotent codemod under scripts/esm-codemod/ (run.mjs orchestrator, per-rule modules, and README.md documenting the full error taxonomy): - add explicit extensions to relative imports (no extension search) - switch lodash -> lodash-es named imports repo-wide - CJS named imports (fs-extra, debug) -> default + destructure - __dirname/__filename -> import.meta.dirname/filename - ts-node --transpileOnly -> node .ts in package.json / *.sh / mise-tasks Manual fixes not suited to a blind codemod: exports maps + type:module on billing and realm-test-harness; in-source spawn('ts-node', ...) -> spawn('node', ['x.ts', ...]); postgres .js->.cjs import; matrix-js-sdk deep-import .js suffixes; and an import.meta.url-as-path bug in lint.ts. Still remaining: the qunit test-runner bootstrap (qunit --require ts-node/register -> node tests/index.ts) and removing the ts-node devDependency afterward. Co-Authored-By: Claude Opus 4.8 --- mise-tasks/claude-prerender-token | 2 +- mise-tasks/infra/clear-modules-cache | 2 +- mise-tasks/infra/start-admin | 2 +- mise-tasks/infra/stop-synapse | 2 +- mise-tasks/services/ai-bot | 2 +- mise-tasks/services/bot-runner | 2 +- mise-tasks/services/prerender | 6 +- mise-tasks/services/prerender-mgr | 4 +- mise-tasks/services/realm-server | 5 +- mise-tasks/services/realm-server-base | 5 +- mise-tasks/services/test-realms | 5 +- mise-tasks/services/worker | 3 +- mise-tasks/services/worker-base | 3 +- mise-tasks/services/worker-test | 3 +- packages/ai-bot/lib/responder.ts | 4 +- packages/ai-bot/main.ts | 10 +- packages/ai-bot/package.json | 8 +- packages/ai-bot/scripts/start-development.sh | 2 +- .../ai-bot/tests/prompt-construction-test.ts | 108 ++++++++++++------ packages/base/card-api.gts | 2 +- packages/base/card-serialization.ts | 2 +- .../components/color-picker-field.gts | 2 +- packages/base/default-templates/card-info.gts | 2 +- .../base/default-templates/field-edit.gts | 2 +- .../default-templates/isolated-and-edit.gts | 2 +- packages/base/enum.gts | 2 +- packages/base/field-component.gts | 2 +- packages/base/field-support.ts | 2 +- packages/base/package.json | 2 +- packages/base/realm-config.gts | 2 +- packages/billing/package.json | 7 ++ .../checkout-session-completed.ts | 2 +- .../payment-succeeded.ts | 2 +- .../subscription-deleted.ts | 2 +- packages/bot-runner/package.json | 2 +- packages/boxel-cli/package.json | 14 +-- .../src/components/drag-and-drop/usage.gts | 2 +- .../src/components/multi-select/usage.gts | 2 +- packages/boxel-ui/addon/src/helpers/pick.ts | 2 +- packages/catalog/package.json | 4 +- .../components/search-input.gts | 2 +- .../experiments_fields_preview.gts | 2 +- .../llm-model-environment/environment.gts | 2 +- packages/experiments-realm/package.json | 2 +- .../components/ai-assistant/message/index.gts | 2 +- packages/host/app/components/matrix/room.gts | 2 +- .../components/operator-mode/code-editor.gts | 2 +- .../components/operator-mode/code-submode.gts | 2 +- .../components/operator-mode/detail-panel.gts | 2 +- .../operator-mode/interact-submode.gts | 2 +- .../app/components/operator-mode/overlays.gts | 2 +- .../host/app/helpers/subscribe-to-realms.ts | 2 +- packages/host/app/lib/browser-queue.ts | 2 +- packages/host/app/lib/externals.ts | 2 +- packages/host/app/lib/matrix-utils.ts | 2 +- packages/host/app/lib/utils.ts | 2 +- .../host/app/resources/card-collection.ts | 2 +- .../app/resources/file-tree-from-index.ts | 2 +- .../host/app/resources/prerendered-search.ts | 2 +- packages/host/app/resources/room.ts | 2 +- packages/host/app/resources/search-entries.ts | 2 +- packages/host/app/resources/search.ts | 4 +- packages/host/app/routes/module.ts | 2 +- packages/host/app/routes/render/meta.ts | 2 +- packages/host/app/services/matrix-service.ts | 2 +- packages/host/app/services/monaco-service.ts | 2 +- packages/host/app/services/store.ts | 6 +- .../utils/file-def-attributes-extractor.ts | 2 +- packages/host/package.json | 4 +- packages/host/tests/helpers/indexer.ts | 2 +- packages/matrix/package.json | 36 +++--- .../matrix/scripts/assert-synapse-running.sh | 2 +- packages/matrix/scripts/migrate-realm-user.sh | 2 +- .../matrix/scripts/migrate-realm-users.sh | 18 +-- packages/matrix/scripts/start-synapse.sh | 2 +- packages/matrix/support/environment-config.ts | 9 +- .../matrix/support/isolated-realm-server.ts | 33 +++--- packages/matrix/support/synapse/index.ts | 6 +- packages/postgres/pg-adapter.ts | 2 +- .../postgres/scripts/convert-to-sqlite.ts | 2 +- .../realm-server/handlers/create-realm.ts | 3 +- .../handlers/handle-download-realm.ts | 3 +- .../handlers/handle-publish-realm.ts | 10 +- .../handlers/realm-destruction-utils.ts | 3 +- packages/realm-server/handlers/serve-index.ts | 2 +- .../realm-server/lib/dev-service-registry.ts | 2 +- .../lib/realm-registry-backfill.ts | 2 +- packages/realm-server/lib/realm-routing.ts | 3 +- packages/realm-server/node-realm.ts | 12 +- packages/realm-server/package.json | 22 ++-- packages/realm-server/routes.ts | 2 +- .../realm-server/scripts/bench-realm/bench.ts | 4 +- .../realm-server/scripts/bench-realm/paths.ts | 2 +- .../scripts/codemod/context-search/run.ts | 2 +- .../scripts/start-prerender-manager.sh | 3 +- .../scripts/start-prerender-production.sh | 3 +- .../scripts/start-prerender-staging.sh | 3 +- .../realm-server/scripts/start-production.sh | 3 +- .../realm-server/scripts/start-staging.sh | 3 +- .../scripts/start-worker-production.sh | 3 +- .../scripts/start-worker-staging.sh | 3 +- packages/realm-server/server.ts | 3 +- packages/realm-server/synapse.ts | 7 +- .../tests/async-semaphore-test.ts | 2 +- .../tests/atomic-endpoints-test.ts | 2 +- .../realm-server/tests/auth-client-test.ts | 2 +- .../tests/bfm-card-references-test.ts | 2 +- packages/realm-server/tests/billing-test.ts | 2 +- .../tests/boxel-domain-availability-test.ts | 5 +- .../tests/card-dependencies-endpoint-test.ts | 2 +- .../realm-server/tests/card-endpoints-test.ts | 5 +- .../tests/card-source-endpoints-test.ts | 7 +- .../tests/claim-boxel-domain-test.ts | 5 +- .../tests/clamp-serialized-error-test.ts | 2 +- .../tests/codemod-context-search-test.ts | 4 +- .../tests/coerce-error-message-test.ts | 2 +- .../tests/command-parsing-utils-test.ts | 2 +- .../tests/consuming-realm-header-test.ts | 2 +- .../tests/data-plane-write-lock-test.ts | 2 +- .../tests/definition-lookup-test.ts | 2 +- .../tests/delete-boxel-claimed-domain-test.ts | 5 +- .../tests/eq-containment-integration-test.ts | 2 +- .../tests/fallback-models-test.ts | 2 +- .../tests/file-watcher-events-test.ts | 5 +- .../finalize-child-fatal-failure-test.ts | 2 +- .../finalize-orphan-reservations-test.ts | 2 +- .../tests/full-index-on-startup-test.ts | 2 +- .../realm-server/tests/full-reindex-test.ts | 2 +- .../tests/get-boxel-claimed-domain-test.ts | 5 +- packages/realm-server/tests/helpers/index.ts | 12 +- .../tests/host-routing-validation-test.ts | 2 +- .../tests/http2-keepalive-test.ts | 4 +- .../tests/indexing-event-sink-test.ts | 2 +- packages/realm-server/tests/indexing-test.ts | 2 +- .../tests/is-json-content-type-test.ts | 2 +- .../tests/job-scoped-search-cache-test.ts | 2 +- .../tests/jobs-finished-listener-test.ts | 2 +- .../realm-server/tests/lazy-mount-test.ts | 2 +- .../tests/listener-dispatcher-test.ts | 2 +- .../tests/load-links-batching-test.ts | 2 +- ...markdown-fallback-server-isolation-test.ts | 4 +- .../tests/matches-filter-integration-test.ts | 2 +- .../tests/module-cache-coordination-test.ts | 2 +- ...module-cache-invalidation-listener-test.ts | 2 +- .../tests/module-cache-race-test.ts | 5 +- .../realm-server/tests/module-syntax-test.ts | 2 +- .../realm-server/tests/node-realm-test.ts | 2 +- .../tests/normalize-realm-meta-value-test.ts | 2 +- .../tests/openrouter-passthrough-test.ts | 5 +- .../tests/package-shim-handler-test.ts | 2 +- .../page-pool-cert-verifier-retry-test.ts | 2 +- .../tests/page-pool-eviction-recovery-test.ts | 2 +- .../tests/page-pool-expansion-test.ts | 2 +- .../tests/page-pool-priority-test.ts | 2 +- .../tests/page-pool-standby-refill-test.ts | 2 +- .../permissions/permission-checker-test.ts | 2 +- .../tests/pg-adapter-subscribe-test.ts | 2 +- .../tests/prerender-affinity-activity-test.ts | 2 +- .../tests/prerender-batch-ownership-test.ts | 2 +- .../tests/prerender-cancellation-test.ts | 2 +- .../tests/prerender-deadlock-test.ts | 2 +- .../prerender-diagnostics-persistence-test.ts | 2 +- .../tests/prerender-manager-test.ts | 2 +- .../tests/prerender-proxy-test.ts | 2 +- .../tests/prerender-server-test.ts | 2 +- .../realm-server/tests/prerendering-test.ts | 2 +- .../tests/publish-unpublish-realm-test.ts | 13 +-- packages/realm-server/tests/queries-test.ts | 2 +- .../tests/query-matches-filter-test.ts | 2 +- packages/realm-server/tests/queue-test.ts | 2 +- .../tests/realm-advisory-locks-test.ts | 2 +- .../realm-server/tests/realm-auth-test.ts | 2 +- .../tests/realm-cleanup-transaction-test.ts | 2 +- .../tests/realm-endpoints-test.ts | 15 +-- .../cancel-indexing-job-test.ts | 2 +- .../realm-endpoints/dependencies-test.ts | 2 +- .../tests/realm-endpoints/directory-test.ts | 2 +- .../realm-endpoints/indexing-errors-test.ts | 2 +- .../tests/realm-endpoints/info-test.ts | 2 +- .../realm-endpoints/invalidate-urls-test.ts | 2 +- .../tests/realm-endpoints/lint-test.ts | 2 +- .../tests/realm-endpoints/markdown-test.ts | 2 +- .../tests/realm-endpoints/mtimes-test.ts | 2 +- .../tests/realm-endpoints/permissions-test.ts | 2 +- .../realm-endpoints/publishability-test.ts | 2 +- .../tests/realm-endpoints/reindex-test.ts | 2 +- .../tests/realm-endpoints/search-test.ts | 2 +- .../tests/realm-endpoints/search-v2-test.ts | 2 +- .../tests/realm-endpoints/user-test.ts | 2 +- .../tests/realm-file-changes-listener-test.ts | 2 +- .../tests/realm-identifiers-test.ts | 2 +- .../realm-index-updated-listener-test.ts | 2 +- .../tests/realm-operations-test.ts | 2 +- .../tests/realm-registry-backfill-test.ts | 5 +- .../tests/realm-registry-reconciler-test.ts | 2 +- .../tests/realm-registry-writes-test.ts | 2 +- .../realm-server/tests/realm-routing-test.ts | 2 +- .../tests/remote-prerenderer-test.ts | 4 +- .../tests/render-type-resolution-test.ts | 2 +- .../tests/request-forward-test.ts | 5 +- .../tests/resolve-published-realm-url-test.ts | 2 +- .../tests/run-command-task-test.ts | 2 +- .../tests/runtime-dependency-tracker-test.ts | 2 +- .../tests/runtime-exception-capture-test.ts | 2 +- .../tests/sanitize-for-jsonb-test.ts | 2 +- .../tests/sanitize-head-html-test.ts | 2 +- .../tests/screenshot-card-test.ts | 2 +- .../realm-server/tests/search-compat-test.ts | 2 +- .../tests/search-entries-engine-test.ts | 2 +- .../realm-server/tests/search-entry-test.ts | 2 +- .../tests/search-in-flight-key-test.ts | 2 +- .../tests/search-prerendered-test.ts | 2 +- .../realm-server/tests/serve-index-test.ts | 2 +- .../realm-server/tests/server-config-test.ts | 2 +- .../server-endpoints/authentication-test.ts | 2 +- .../server-endpoints/bot-commands-test.ts | 2 +- .../server-endpoints/bot-registration-test.ts | 2 +- .../server-endpoints/delete-realm-test.ts | 5 +- .../server-endpoints/download-realm-test.ts | 2 +- .../server-endpoints/federated-types-test.ts | 2 +- .../server-endpoints/incoming-webhook-test.ts | 2 +- .../server-endpoints/index-responses-test.ts | 5 +- .../tests/server-endpoints/info-test.ts | 2 +- .../maintenance-endpoints-test.ts | 2 +- .../server-endpoints/queue-status-test.ts | 2 +- .../server-endpoints/realm-lifecycle-test.ts | 5 +- .../run-command-endpoint-test.ts | 2 +- .../screenshot-card-endpoint-test.ts | 2 +- .../search-prerendered-test.ts | 2 +- .../tests/server-endpoints/search-test.ts | 2 +- .../tests/server-endpoints/search-v2-test.ts | 2 +- .../server-endpoints/stripe-session-test.ts | 2 +- .../server-endpoints/stripe-webhook-test.ts | 2 +- .../server-endpoints/user-and-catalog-test.ts | 2 +- .../server-endpoints/webhook-commands-test.ts | 2 +- .../server-endpoints/webhook-receiver-test.ts | 2 +- .../tests/session-room-queries-test.ts | 2 +- .../tests/skip-query-backed-expansion-test.ts | 2 +- packages/realm-server/tests/transpile-test.ts | 2 +- .../realm-server/tests/types-endpoint-test.ts | 5 +- .../tests/unified-search-contracts-test.ts | 2 +- .../tests/virtual-network-test.ts | 2 +- packages/realm-server/utils/jwt.ts | 8 +- packages/realm-server/worker-manager.ts | 7 +- packages/realm-test-harness/package.json | 6 + .../src/isolated-realm-stack.ts | 10 +- .../src/support-services.ts | 4 +- packages/runtime-common/cached-fetch.ts | 2 +- packages/runtime-common/catalog.ts | 6 +- packages/runtime-common/commands.ts | 2 +- packages/runtime-common/expression.ts | 4 +- packages/runtime-common/index-query-engine.ts | 2 +- .../index-runner/card-indexer.ts | 2 +- packages/runtime-common/index-writer.ts | 4 +- .../runtime-common/instance-filter-matcher.ts | 2 +- packages/runtime-common/jobs/indexing.ts | 2 +- packages/runtime-common/loader.ts | 2 +- .../runtime-common/merge-relationships.ts | 2 +- packages/runtime-common/module-syntax.ts | 2 +- packages/runtime-common/package.json | 4 +- packages/runtime-common/query.ts | 2 +- .../realm-index-query-engine.ts | 2 +- packages/runtime-common/realm.ts | 10 +- packages/runtime-common/tasks/lint.ts | 4 +- packages/runtime-common/unified-search.ts | 8 +- packages/software-factory/package.json | 32 +++--- .../playwright.global-setup.ts | 26 ++--- .../smoke-test-factory-scenarios.ts | 2 +- packages/software-factory/scripts/test.ts | 2 +- .../software-factory/src/cli/serve-realm.ts | 2 +- .../src/factory-issue-loop-wiring.ts | 2 +- .../src/factory-prompt-loader.ts | 2 +- .../src/factory-skill-loader.ts | 2 +- .../software-factory/src/parse-execution.ts | 4 +- .../tests/factory-brief.test.ts | 7 +- .../factory-entrypoint.integration.test.ts | 4 +- packages/software-factory/tests/fixtures.ts | 5 +- pnpm-lock.yaml | 51 ++++++--- pnpm-workspace.yaml | 2 + scripts/esm-codemod/README.md | 89 +++++++++++++++ .../esm-codemod/add-relative-extensions.mjs | 82 +++++++++++++ scripts/esm-codemod/cjs-named-to-default.mjs | 62 ++++++++++ .../esm-codemod/dirname-to-import-meta.mjs | 41 +++++++ scripts/esm-codemod/lodash-to-lodash-es.mjs | 47 ++++++++ scripts/esm-codemod/run.mjs | 106 +++++++++++++++++ scripts/esm-codemod/ts-node-to-node.mjs | 63 ++++++++++ 286 files changed, 1072 insertions(+), 547 deletions(-) create mode 100644 scripts/esm-codemod/README.md create mode 100644 scripts/esm-codemod/add-relative-extensions.mjs create mode 100644 scripts/esm-codemod/cjs-named-to-default.mjs create mode 100644 scripts/esm-codemod/dirname-to-import-meta.mjs create mode 100644 scripts/esm-codemod/lodash-to-lodash-es.mjs create mode 100644 scripts/esm-codemod/run.mjs create mode 100644 scripts/esm-codemod/ts-node-to-node.mjs diff --git a/mise-tasks/claude-prerender-token b/mise-tasks/claude-prerender-token index 9f4c8f51d0..4c3675fd53 100755 --- a/mise-tasks/claude-prerender-token +++ b/mise-tasks/claude-prerender-token @@ -2,4 +2,4 @@ #MISE description="Mint a realm-scoped boxel-session JWT (the indexer's auth shape) and write to /tmp/claude-prerender.json for Claude to drive a live browser render" #MISE dir="packages/realm-server" -exec ts-node --transpileOnly ./scripts/claude-prerender-token.ts "$@" +exec node ./scripts/claude-prerender-token.ts "$@" diff --git a/mise-tasks/infra/clear-modules-cache b/mise-tasks/infra/clear-modules-cache index b963a1e3f0..adcdce7006 100755 --- a/mise-tasks/infra/clear-modules-cache +++ b/mise-tasks/infra/clear-modules-cache @@ -6,4 +6,4 @@ echo "Clearing modules cache..." PGPORT="${PGPORT:-5435}" PGDATABASE="${PGDATABASE:-boxel}" \ NODE_NO_WARNINGS=1 \ - ts-node --transpileOnly scripts/clear-modules-cache.ts + node scripts/clear-modules-cache.ts diff --git a/mise-tasks/infra/start-admin b/mise-tasks/infra/start-admin index 09ed70ce8c..82927f2761 100755 --- a/mise-tasks/infra/start-admin +++ b/mise-tasks/infra/start-admin @@ -2,4 +2,4 @@ #MISE description="Start the Matrix admin console (port 8080)" #MISE dir="packages/matrix" -exec ts-node --transpileOnly ./scripts/admin-console +exec node ./scripts/admin-console.ts diff --git a/mise-tasks/infra/stop-synapse b/mise-tasks/infra/stop-synapse index d8cf9a5b54..bc5b392066 100755 --- a/mise-tasks/infra/stop-synapse +++ b/mise-tasks/infra/stop-synapse @@ -2,4 +2,4 @@ #MISE description="Stop the Matrix Synapse server" #MISE dir="packages/matrix" -exec ts-node --transpileOnly ./scripts/synapse.ts stop +exec node ./scripts/synapse.ts stop diff --git a/mise-tasks/services/ai-bot b/mise-tasks/services/ai-bot index 545a116787..5eb9402abb 100755 --- a/mise-tasks/services/ai-bot +++ b/mise-tasks/services/ai-bot @@ -6,4 +6,4 @@ MATRIX_URL="${MATRIX_URL_VAL}" \ NODE_NO_WARNINGS=1 \ PGPORT="${PGPORT}" \ PGDATABASE="${PGDATABASE}" \ - exec ts-node --transpileOnly main + exec node main.ts diff --git a/mise-tasks/services/bot-runner b/mise-tasks/services/bot-runner index 8a715f0122..4b312a4378 100755 --- a/mise-tasks/services/bot-runner +++ b/mise-tasks/services/bot-runner @@ -6,4 +6,4 @@ MATRIX_URL="${MATRIX_URL_VAL}" \ NODE_NO_WARNINGS=1 \ PGPORT="${PGPORT}" \ PGDATABASE="${PGDATABASE}" \ - exec ts-node --transpileOnly main + exec node main.ts diff --git a/mise-tasks/services/prerender b/mise-tasks/services/prerender index 9909fed477..88de792f19 100755 --- a/mise-tasks/services/prerender +++ b/mise-tasks/services/prerender @@ -44,7 +44,7 @@ fi # host is actually browser-ready. if [ -z "$ENV_MODE" ]; then HOST_URL="${BOXEL_HOST_URL:-$DEFAULT_HOST_URL}" \ - ts-node --transpileOnly ./scripts/wait-for-host-standby.ts || exit $? + node ./scripts/wait-for-host-standby.ts || exit $? fi # In local HTTPS dev (vite on https://localhost:4200 with HTTP/2), @@ -61,8 +61,8 @@ NODE_ENV=development \ NODE_NO_WARNINGS=1 \ BOXEL_HOST_URL="${BOXEL_HOST_URL:-$DEFAULT_HOST_URL}" \ PRERENDER_STANDBY_TIMEOUT_MS="${PRERENDER_STANDBY_TIMEOUT_MS:-}" \ - ts-node \ - --transpileOnly prerender/prerender-server \ + node \ + prerender/prerender-server.ts \ --port="${PRERENDER_PORT}" \ --count="${PRERENDER_COUNT:-1}" \ 2>&1 | "$LOG_TEE" prerender diff --git a/mise-tasks/services/prerender-mgr b/mise-tasks/services/prerender-mgr index a3de4293ca..364a59c988 100755 --- a/mise-tasks/services/prerender-mgr +++ b/mise-tasks/services/prerender-mgr @@ -23,8 +23,8 @@ NODE_ENV=development \ NODE_NO_WARNINGS=1 \ PRERENDER_MANAGER_VERBOSE_LOGS=false \ PRERENDER_MULTIPLEX="${PRERENDER_MULTIPLEX:-1}" \ - ts-node \ - --transpileOnly prerender/manager-server \ + node \ + prerender/manager-server.ts \ --port=${PRERENDER_MANAGER_PORT:-$PRERENDER_MGR_PORT} \ --exit-on-signal \ 2>&1 | "$LOG_TEE" prerender-manager diff --git a/mise-tasks/services/realm-server b/mise-tasks/services/realm-server index eeb7567433..f499ddab53 100755 --- a/mise-tasks/services/realm-server +++ b/mise-tasks/services/realm-server @@ -44,7 +44,7 @@ if [ "${SKIP_CATALOG:-}" != "true" ]; then fi if [ -z "$MATRIX_REGISTRATION_SHARED_SECRET" ]; then - MATRIX_REGISTRATION_SHARED_SECRET=$(ts-node --transpileOnly "$SCRIPTS_DIR/matrix-registration-secret.ts") + MATRIX_REGISTRATION_SHARED_SECRET=$(node "$SCRIPTS_DIR/matrix-registration-secret.ts").ts export MATRIX_REGISTRATION_SHARED_SECRET fi @@ -93,8 +93,7 @@ LOW_CREDIT_THRESHOLD="${LOW_CREDIT_THRESHOLD:-2000}" \ MATRIX_URL="${MATRIX_URL_VAL}" \ REALM_SERVER_MATRIX_USERNAME=realm_server \ ENABLE_FILE_WATCHER=true \ - ts-node \ - --transpileOnly main \ + node main.ts \ --port="${REALM_PORT}" \ --matrixURL="${MATRIX_URL_VAL}" \ --realmsRootPath="${REALMS_ROOT}" \ diff --git a/mise-tasks/services/realm-server-base b/mise-tasks/services/realm-server-base index b35ac208fa..a8b7887584 100755 --- a/mise-tasks/services/realm-server-base +++ b/mise-tasks/services/realm-server-base @@ -9,7 +9,7 @@ trap 'exit 0' INT TERM if [ -z "$MATRIX_REGISTRATION_SHARED_SECRET" ]; then - MATRIX_REGISTRATION_SHARED_SECRET=$(ts-node --transpileOnly ./scripts/matrix-registration-secret.ts) + MATRIX_REGISTRATION_SHARED_SECRET=$(node ./scripts/matrix-registration-secret.ts).ts export MATRIX_REGISTRATION_SHARED_SECRET fi @@ -22,8 +22,7 @@ NODE_ENV=development \ GRAFANA_SECRET="shhh! it's a secret" \ MATRIX_URL="${MATRIX_URL_VAL}" \ REALM_SERVER_MATRIX_USERNAME=realm_server \ - ts-node \ - --transpileOnly main \ + node main.ts \ --port=4201 \ --matrixURL="${MATRIX_URL_VAL}" \ --realmsRootPath='./realms/localhost_4201_base' \ diff --git a/mise-tasks/services/test-realms b/mise-tasks/services/test-realms index 830edb6c62..7c40151823 100755 --- a/mise-tasks/services/test-realms +++ b/mise-tasks/services/test-realms @@ -55,7 +55,7 @@ fi pnpm --dir=../skills-realm skills:setup if [ -z "$MATRIX_REGISTRATION_SHARED_SECRET" ]; then - MATRIX_REGISTRATION_SHARED_SECRET=$(ts-node --transpileOnly "$SCRIPTS_DIR/matrix-registration-secret.ts") + MATRIX_REGISTRATION_SHARED_SECRET=$(node "$SCRIPTS_DIR/matrix-registration-secret.ts").ts export MATRIX_REGISTRATION_SHARED_SECRET fi @@ -68,8 +68,7 @@ NODE_ENV=test \ GRAFANA_SECRET="shhh! it's a secret" \ MATRIX_URL="${MATRIX_URL_VAL}" \ REALM_SERVER_MATRIX_USERNAME=realm_server \ - ts-node \ - --transpileOnly main \ + node main.ts \ --port="${TEST_PORT}" \ --matrixURL="${MATRIX_URL_VAL}" \ --realmsRootPath="${REALMS_TEST_ROOT}" \ diff --git a/mise-tasks/services/worker b/mise-tasks/services/worker index 25ec3c7936..ee1fab8a25 100755 --- a/mise-tasks/services/worker +++ b/mise-tasks/services/worker @@ -40,8 +40,7 @@ NODE_ENV=development \ REALM_SERVER_MATRIX_USERNAME=realm_server \ LOW_CREDIT_THRESHOLD=2000 \ OPENROUTER_REALM_URL="${REALM_BASE_URL}/openrouter/" \ - ts-node \ - --transpileOnly worker-manager \ + node worker-manager.ts \ --allPriorityCount="${WORKER_ALL_PRIORITY_COUNT:-1}" \ --highPriorityCount="${WORKER_HIGH_PRIORITY_COUNT:-0}" \ --port="${WORKER_PORT}" \ diff --git a/mise-tasks/services/worker-base b/mise-tasks/services/worker-base index 5bdb2ed5a5..47961a9667 100755 --- a/mise-tasks/services/worker-base +++ b/mise-tasks/services/worker-base @@ -16,8 +16,7 @@ NODE_ENV=development \ REALM_SECRET_SEED="shhh! it's a secret" \ REALM_SERVER_MATRIX_USERNAME=realm_server \ LOW_CREDIT_THRESHOLD=2000 \ - ts-node \ - --transpileOnly worker-manager \ + node worker-manager.ts \ --port=4213 \ --matrixURL="${MATRIX_URL_VAL}" \ --prerendererUrl="${PRERENDER_MGR_URL}" \ diff --git a/mise-tasks/services/worker-test b/mise-tasks/services/worker-test index d54de08330..9443d4a81b 100755 --- a/mise-tasks/services/worker-test +++ b/mise-tasks/services/worker-test @@ -28,8 +28,7 @@ NODE_ENV=test \ REALM_SECRET_SEED="shhh! it's a secret" \ REALM_SERVER_MATRIX_USERNAME=realm_server \ LOW_CREDIT_THRESHOLD=2000 \ - ts-node \ - --transpileOnly worker-manager \ + node worker-manager.ts \ --port="${WORKER_TEST_PORT}" \ --matrixURL="${MATRIX_URL_VAL}" \ --prerendererUrl="${PRERENDER_MGR_URL}" \ diff --git a/packages/ai-bot/lib/responder.ts b/packages/ai-bot/lib/responder.ts index cfa0c0366f..773657108b 100644 --- a/packages/ai-bot/lib/responder.ts +++ b/packages/ai-bot/lib/responder.ts @@ -4,8 +4,8 @@ import { isCommandOrCodePatchResult } from '@cardstack/runtime-common/ai'; import * as Sentry from '@sentry/node'; import type { OpenAIError } from 'openai/error'; -import throttle from 'lodash/throttle'; -import type { ISendEventResponse } from 'matrix-js-sdk/lib/matrix'; +import { throttle } from 'lodash-es'; +import type { ISendEventResponse } from 'matrix-js-sdk/lib/matrix.js'; import type { ChatCompletionMessageFunctionToolCall } from 'openai/resources/chat/completions'; import type { FunctionToolCall } from '@cardstack/runtime-common/helpers/ai'; import type OpenAI from 'openai'; diff --git a/packages/ai-bot/main.ts b/packages/ai-bot/main.ts index 353cf05cbb..7cbddf4a63 100644 --- a/packages/ai-bot/main.ts +++ b/packages/ai-bot/main.ts @@ -2,7 +2,10 @@ import './instrument.ts'; import './setup-logger.ts'; // This should be first import type { MatrixEvent } from 'matrix-js-sdk'; import { RoomMemberEvent, RoomEvent, createClient } from 'matrix-js-sdk'; -import { SlidingSync, type MSC3575List } from 'matrix-js-sdk/lib/sliding-sync'; +import { + SlidingSync, + type MSC3575List, +} from 'matrix-js-sdk/lib/sliding-sync.js'; import OpenAI from 'openai'; import { logger, @@ -47,11 +50,12 @@ import { APIUserAbortError } from 'openai/error'; import type { OpenAIError } from 'openai/error'; import type { ChatCompletionStream } from 'openai/lib/ChatCompletionStream'; import { acquireRoomLock, releaseRoomLock } from './lib/queries.ts'; -import { DebugLogger } from 'matrix-js-sdk/lib/logger'; +import { DebugLogger } from 'matrix-js-sdk/lib/logger.js'; import { setupSignalHandlers } from './lib/signal-handlers.ts'; import { isShuttingDown, setActiveGenerations } from './lib/shutdown.ts'; import type { MatrixClient } from 'matrix-js-sdk'; -import { debug } from 'debug'; +import createDebug from 'debug'; +const { debug } = createDebug; import { profEnabled, profTime, profNote } from './lib/profiler.ts'; import { publishCodePatchCorrectnessMessage } from './lib/code-patch-correctness.ts'; import { diff --git a/packages/ai-bot/package.json b/packages/ai-bot/package.json index 7f85659e6f..d9d70ce4b5 100644 --- a/packages/ai-bot/package.json +++ b/packages/ai-bot/package.json @@ -5,12 +5,12 @@ "@cardstack/postgres": "workspace:*", "@cardstack/runtime-common": "workspace:*", "@sentry/node": "catalog:", - "@types/lodash": "catalog:", + "@types/lodash-es": "catalog:", "@types/node": "catalog:", "@types/stream-chain": "catalog:", "@types/stream-json": "catalog:", "debug": "^4.4.3", - "lodash": "catalog:", + "lodash-es": "catalog:", "matrix-js-sdk": "catalog:", "openai": "catalog:", "qunit": "catalog:", @@ -39,8 +39,8 @@ "lint:js": "eslint . --report-unused-disable-directives --cache", "lint:js:fix": "eslint . --report-unused-disable-directives --fix", "lint:types": "ember-tsc --noEmit", - "start": "NODE_NO_WARNINGS=1 ts-node --transpileOnly main", + "start": "NODE_NO_WARNINGS=1 node main.ts", "test": "NODE_NO_WARNINGS=1 qunit --require ts-node/register/transpile-only tests/index.ts", - "get-chat": "NODE_NO_WARNINGS=1 ts-node --transpileOnly scripts/get_chat.ts" + "get-chat": "NODE_NO_WARNINGS=1 node scripts/get_chat.ts" } } diff --git a/packages/ai-bot/scripts/start-development.sh b/packages/ai-bot/scripts/start-development.sh index ac1e8ad8da..eafd368c9f 100644 --- a/packages/ai-bot/scripts/start-development.sh +++ b/packages/ai-bot/scripts/start-development.sh @@ -32,4 +32,4 @@ else export PGDATABASE="${PGDATABASE:-boxel}" fi -exec ts-node --transpileOnly main +exec node main.ts diff --git a/packages/ai-bot/tests/prompt-construction-test.ts b/packages/ai-bot/tests/prompt-construction-test.ts index 59b084a922..db1c36b441 100644 --- a/packages/ai-bot/tests/prompt-construction-test.ts +++ b/packages/ai-bot/tests/prompt-construction-test.ts @@ -25,7 +25,8 @@ import type { } from 'https://cardstack.com/base/matrix-event'; import { EventStatus } from 'matrix-js-sdk'; import type { CardDef } from 'https://cardstack.com/base/card-api'; -import { readFileSync } from 'fs-extra'; +import fsExtra from 'fs-extra'; +const { readFileSync } = fsExtra; import * as path from 'path'; import { FakeMatrixClient } from './helpers/fake-matrix-client.ts'; import { @@ -1932,7 +1933,7 @@ Attached Files (files with newer versions don't show their content): test('should include instructions in system prompt for skill cards', async () => { const rawEvents = readFileSync( - path.join(__dirname, 'resources/chats/added-skill.json'), + path.join(import.meta.dirname, 'resources/chats/added-skill.json'), 'utf-8', ); const eventList: DiscreteMatrixEvent[] = JSON.parse( @@ -2011,7 +2012,7 @@ Attached Files (files with newer versions don't show their content): const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( path.join( - __dirname, + import.meta.dirname, 'resources/chats/added-skill-and-attached-card.json', ), 'utf-8', @@ -2129,7 +2130,7 @@ Attached Files (files with newer versions don't show their content): const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( path.join( - __dirname, + import.meta.dirname, 'resources/chats/added-two-skills-removed-one-skill.json', ), 'utf-8', @@ -2205,7 +2206,7 @@ Attached Files (files with newer versions don't show their content): const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( path.join( - __dirname, + import.meta.dirname, 'resources/chats/added-two-skills-removed-two-skills.json', ), 'utf-8', @@ -2232,7 +2233,7 @@ Attached Files (files with newer versions don't show their content): // handle that. const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( - path.join(__dirname, 'resources/chats/skill-card-no-id.json'), + path.join(import.meta.dirname, 'resources/chats/skill-card-no-id.json'), 'utf-8', ), ); @@ -2293,7 +2294,7 @@ Attached Files (files with newer versions don't show their content): const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( path.join( - __dirname, + import.meta.dirname, 'resources/chats/two-messages-with-same-skill-card.json', ), 'utf-8', @@ -2341,7 +2342,10 @@ Attached Files (files with newer versions don't show their content): test('if tool calls are required, ensure they are set', async () => { const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( - path.join(__dirname, 'resources/chats/forced-function-call.json'), + path.join( + import.meta.dirname, + 'resources/chats/forced-function-call.json', + ), 'utf-8', ), ); @@ -2717,7 +2721,7 @@ Attached Files (files with newer versions don't show their content): const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( path.join( - __dirname, + import.meta.dirname, 'resources/chats/required-tools-multiple-messages.json', ), 'utf-8', @@ -2743,7 +2747,7 @@ Attached Files (files with newer versions don't show their content): const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( path.join( - __dirname, + import.meta.dirname, 'resources/chats/required-tools-multiple-messages.json', ), 'utf-8', @@ -2762,7 +2766,7 @@ Attached Files (files with newer versions don't show their content): const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( path.join( - __dirname, + import.meta.dirname, 'resources/chats/required-tool-call-in-last-message.json', ), 'utf-8', @@ -2786,7 +2790,7 @@ Attached Files (files with newer versions don't show their content): const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( path.join( - __dirname, + import.meta.dirname, 'resources/chats/connect-tool-calls-to-results.json', ), 'utf-8', @@ -2836,7 +2840,7 @@ Attached Files (files with newer versions don't show their content): const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( path.join( - __dirname, + import.meta.dirname, 'resources/chats/invoke-submode-swith-command.json', ), 'utf-8', @@ -2960,7 +2964,10 @@ Attached Files (files with newer versions don't show their content): test('Does not respond to first tool call result when two tool calls were made', async function () { const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( - path.join(__dirname, 'resources/chats/two-tool-calls-one-result.json'), + path.join( + import.meta.dirname, + 'resources/chats/two-tool-calls-one-result.json', + ), 'utf-8', ), ); @@ -3002,7 +3009,10 @@ Attached Files (files with newer versions don't show their content): test('Responds to second tool call result when two tool calls were made', async function () { const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( - path.join(__dirname, 'resources/chats/two-tool-calls-two-results.json'), + path.join( + import.meta.dirname, + 'resources/chats/two-tool-calls-two-results.json', + ), 'utf-8', ), ); @@ -3080,7 +3090,7 @@ Attached Files (files with newer versions don't show their content): const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( path.join( - __dirname, + import.meta.dirname, 'resources/chats/enabled-skill-with-commands.json', ), 'utf-8', @@ -3224,7 +3234,7 @@ Attached Files (files with newer versions don't show their content): const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( path.join( - __dirname, + import.meta.dirname, 'resources/chats/disabled-skill-with-commands.json', ), 'utf-8', @@ -3256,7 +3266,7 @@ Current date and time: 2025-06-11T11:43:00.533Z const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( path.join( - __dirname, + import.meta.dirname, 'resources/chats/updated-skill-command-definitions.json', ), 'utf-8', @@ -3394,7 +3404,7 @@ Current date and time: 2025-06-11T11:43:00.533Z const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( path.join( - __dirname, + import.meta.dirname, 'resources/chats/two-code-blocks-two-results.json', ), 'utf-8', @@ -3428,7 +3438,10 @@ Current date and time: 2025-06-11T11:43:00.533Z // m.replace messages, relying on server side aggregation const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( - path.join(__dirname, 'resources/chats/server-side-aggregations.json'), + path.join( + import.meta.dirname, + 'resources/chats/server-side-aggregations.json', + ), 'utf-8', ), ); @@ -3533,7 +3546,10 @@ Current date and time: 2025-06-11T11:43:00.533Z test('Responds to successful completion of lone code patch', async function () { const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( - path.join(__dirname, 'resources/chats/one-code-block-one-success.json'), + path.join( + import.meta.dirname, + 'resources/chats/one-code-block-one-success.json', + ), 'utf-8', ), ); @@ -3558,7 +3574,10 @@ Current date and time: 2025-06-11T11:43:00.533Z test('Does not respond to first code patch result when two patches were proposed', async function () { const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( - path.join(__dirname, 'resources/chats/two-code-blocks-one-result.json'), + path.join( + import.meta.dirname, + 'resources/chats/two-code-blocks-one-result.json', + ), 'utf-8', ), ); @@ -3578,7 +3597,7 @@ Current date and time: 2025-06-11T11:43:00.533Z const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( path.join( - __dirname, + import.meta.dirname, 'resources/chats/two-code-blocks-two-results.json', ), 'utf-8', @@ -3605,7 +3624,7 @@ Current date and time: 2025-06-11T11:43:00.533Z const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( path.join( - __dirname, + import.meta.dirname, 'resources/chats/code-block-and-command-one-result.json', ), 'utf-8', @@ -3627,7 +3646,7 @@ Current date and time: 2025-06-11T11:43:00.533Z const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( path.join( - __dirname, + import.meta.dirname, 'resources/chats/code-block-and-command-two-results-a.json', ), 'utf-8', @@ -3694,7 +3713,7 @@ Current date and time: 2025-06-11T11:43:00.533Z const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( path.join( - __dirname, + import.meta.dirname, 'resources/chats/code-block-and-command-two-results-b.json', ), 'utf-8', @@ -3760,7 +3779,10 @@ Current date and time: 2025-06-11T11:43:00.533Z test('Responds to failure of lone code patch', async function () { const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( - path.join(__dirname, 'resources/chats/one-code-block-one-failure.json'), + path.join( + import.meta.dirname, + 'resources/chats/one-code-block-one-failure.json', + ), 'utf-8', ), ); @@ -3785,7 +3807,10 @@ Current date and time: 2025-06-11T11:43:00.533Z test('context message is placed before last user message when just one user message', async () => { const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( - path.join(__dirname, 'resources/chats/user-message-last-single.json'), + path.join( + import.meta.dirname, + 'resources/chats/user-message-last-single.json', + ), 'utf-8', ), ); @@ -3803,7 +3828,10 @@ Current date and time: 2025-06-11T11:43:00.533Z test('context message is placed before last user message when multiple user messages', async () => { const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( - path.join(__dirname, 'resources/chats/user-message-last-multiple.json'), + path.join( + import.meta.dirname, + 'resources/chats/user-message-last-multiple.json', + ), 'utf-8', ), ); @@ -3823,7 +3851,7 @@ Current date and time: 2025-06-11T11:43:00.533Z test('context message is placed after the last tool call if the last message is a tool call', async () => { const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( - path.join(__dirname, 'resources/chats/tool-call-last.json'), + path.join(import.meta.dirname, 'resources/chats/tool-call-last.json'), 'utf-8', ), ); @@ -3847,7 +3875,10 @@ Current date and time: 2025-06-11T11:43:00.533Z test('context message is placed after the last user message if the last message is an assistant message', async () => { const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( - path.join(__dirname, 'resources/chats/assistant-message-last.json'), + path.join( + import.meta.dirname, + 'resources/chats/assistant-message-last.json', + ), 'utf-8', ), ); @@ -3866,7 +3897,10 @@ Current date and time: 2025-06-11T11:43:00.533Z test('context message contains the current date and time', async () => { const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( - path.join(__dirname, 'resources/chats/user-message-last-multiple.json'), + path.join( + import.meta.dirname, + 'resources/chats/user-message-last-multiple.json', + ), 'utf-8', ), ); @@ -3889,7 +3923,7 @@ Current date and time: 2025-06-11T11:43:00.533Z test('tool call messages include attached files when command result does', async () => { const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( - path.join(__dirname, 'resources/chats/read-gts-file.json'), + path.join(import.meta.dirname, 'resources/chats/read-gts-file.json'), 'utf-8', ), ); @@ -3928,7 +3962,7 @@ Attached Files (files with newer versions don't show their content): test('tool call messages include attached cards when command result does', async () => { const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( - path.join(__dirname, 'resources/chats/read-card.json'), + path.join(import.meta.dirname, 'resources/chats/read-card.json'), 'utf-8', ), ); @@ -3973,7 +4007,7 @@ Attached Cards (cards with newer versions don't show their content): test('getPromptParts collects patched files from code patch result attachments', async () => { const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( - path.join(__dirname, 'resources/chats/patched-gts.json'), + path.join(import.meta.dirname, 'resources/chats/patched-gts.json'), 'utf-8', ), ); @@ -6540,7 +6574,7 @@ module('set model in prompt', (hooks) => { const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( path.join( - __dirname, + import.meta.dirname, 'resources/chats/required-tool-call-in-last-message.json', ), 'utf-8', @@ -6558,7 +6592,7 @@ module('set model in prompt', (hooks) => { test('use latest active llm', async () => { const eventList: DiscreteMatrixEvent[] = JSON.parse( readFileSync( - path.join(__dirname, 'resources/chats/set-active-llm.json'), + path.join(import.meta.dirname, 'resources/chats/set-active-llm.json'), 'utf-8', ), ); diff --git a/packages/base/card-api.gts b/packages/base/card-api.gts index e9f6eae177..48f07c8ca7 100644 --- a/packages/base/card-api.gts +++ b/packages/base/card-api.gts @@ -1,6 +1,6 @@ import Modifier from 'ember-modifier'; import GlimmerComponent from '@glimmer/component'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { WatchedArray, rawArrayValues } from './watched-array'; import { BoxelInput, CopyButton } from '@cardstack/boxel-ui/components'; import { diff --git a/packages/base/card-serialization.ts b/packages/base/card-serialization.ts index 529f7bb6cd..9af323e45d 100644 --- a/packages/base/card-serialization.ts +++ b/packages/base/card-serialization.ts @@ -21,7 +21,7 @@ import type { ResourceID, VirtualNetwork } from '@cardstack/runtime-common'; // --- Runtime Imports --- -import { isEqual, merge } from 'lodash'; +import { isEqual, merge } from 'lodash-es'; import { assertIsSerializerName, CardResourceType, diff --git a/packages/base/color-field/components/color-picker-field.gts b/packages/base/color-field/components/color-picker-field.gts index 6f4a980d2d..2ed67371cc 100644 --- a/packages/base/color-field/components/color-picker-field.gts +++ b/packages/base/color-field/components/color-picker-field.gts @@ -2,7 +2,7 @@ import Component from '@glimmer/component'; import type Owner from '@ember/owner'; import { tracked } from '@glimmer/tracking'; import { action } from '@ember/object'; -import { debounce } from 'lodash'; +import { debounce } from 'lodash-es'; import { eq, or, not } from '@cardstack/boxel-ui/helpers'; import { ColorPicker } from '@cardstack/boxel-ui/components'; diff --git a/packages/base/default-templates/card-info.gts b/packages/base/default-templates/card-info.gts index f44597f65d..2fedb47cdb 100644 --- a/packages/base/default-templates/card-info.gts +++ b/packages/base/default-templates/card-info.gts @@ -22,7 +22,7 @@ import { import { and, cn, eq } from '@cardstack/boxel-ui/helpers'; import { ChevronRight } from '@cardstack/boxel-ui/icons'; -import { startCase } from 'lodash'; +import { startCase } from 'lodash-es'; import { chooseFile, diff --git a/packages/base/default-templates/field-edit.gts b/packages/base/default-templates/field-edit.gts index 2887881321..0bdbaec7ce 100644 --- a/packages/base/default-templates/field-edit.gts +++ b/packages/base/default-templates/field-edit.gts @@ -2,7 +2,7 @@ import GlimmerComponent from '@glimmer/component'; import type { FieldDef } from '../card-api'; import { FieldContainer } from '@cardstack/boxel-ui/components'; import { eq } from '@cardstack/boxel-ui/helpers'; -import { startCase } from 'lodash'; +import { startCase } from 'lodash-es'; import { getField } from '@cardstack/runtime-common'; export default class FieldDefEditTemplate extends GlimmerComponent<{ diff --git a/packages/base/default-templates/isolated-and-edit.gts b/packages/base/default-templates/isolated-and-edit.gts index ab4d3761fb..e2c1bba486 100644 --- a/packages/base/default-templates/isolated-and-edit.gts +++ b/packages/base/default-templates/isolated-and-edit.gts @@ -2,7 +2,7 @@ import GlimmerComponent from '@glimmer/component'; import type { CardDef, FieldsTypeFor, Format } from '../card-api'; import { FieldContainer, Header } from '@cardstack/boxel-ui/components'; import { cn, eq } from '@cardstack/boxel-ui/helpers'; -import { startCase } from 'lodash'; +import { startCase } from 'lodash-es'; import { getFieldIcon, getField, diff --git a/packages/base/enum.gts b/packages/base/enum.gts index 0dcbbfe8ee..4230d47cd0 100644 --- a/packages/base/enum.gts +++ b/packages/base/enum.gts @@ -1,5 +1,5 @@ import GlimmerComponent from '@glimmer/component'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { BoxelSelect } from '@cardstack/boxel-ui/components'; import { getField } from '@cardstack/runtime-common'; import { resolveFieldConfiguration } from './field-support'; diff --git a/packages/base/field-component.gts b/packages/base/field-component.gts index 8282b6da07..32b5cdd1cd 100644 --- a/packages/base/field-component.gts +++ b/packages/base/field-component.gts @@ -34,7 +34,7 @@ import { sanitizeHtmlSafe, } from '@cardstack/boxel-ui/helpers'; import Modifier from 'ember-modifier'; -import { isEqual, flatMap } from 'lodash'; +import { isEqual, flatMap } from 'lodash-es'; import { initSharedState } from './shared-state'; import { and, cn, eq, not } from '@cardstack/boxel-ui/helpers'; import { consume, provide } from 'ember-provide-consume-context'; diff --git a/packages/base/field-support.ts b/packages/base/field-support.ts index 8c8ef2d165..e719fac11b 100644 --- a/packages/base/field-support.ts +++ b/packages/base/field-support.ts @@ -23,7 +23,7 @@ import { } from './card-serialization'; import { initSharedState } from './shared-state'; import { rawArrayValues } from './watched-array'; -import { flatMap } from 'lodash'; +import { flatMap } from 'lodash-es'; import { TrackedMap, TrackedWeakMap } from 'tracked-built-ins'; import type { ConfigurationInput, FieldConfiguration } from './card-api'; diff --git a/packages/base/package.json b/packages/base/package.json index 875e69e23a..9f442ab93f 100644 --- a/packages/base/package.json +++ b/packages/base/package.json @@ -12,7 +12,7 @@ "@glimmer/tracking": "^1.0.4", "@glint/template": "catalog:", "@types/flat": "catalog:", - "@types/lodash": "catalog:", + "@types/lodash-es": "catalog:", "awesome-phonenumber": "catalog:", "concurrently": "catalog:", "ember-cli-htmlbars": "^6.3.0", diff --git a/packages/base/realm-config.gts b/packages/base/realm-config.gts index 7fd32d3575..7fa1b99313 100644 --- a/packages/base/realm-config.gts +++ b/packages/base/realm-config.gts @@ -29,7 +29,7 @@ import FileSettingsIcon from '@cardstack/boxel-icons/file-settings'; import LinkIcon from '@cardstack/boxel-icons/link'; import { action } from '@ember/object'; import type Owner from '@ember/owner'; -import { startCase } from 'lodash'; +import { startCase } from 'lodash-es'; import type { FieldsTypeFor } from './card-api'; class RoutingRuleAtom extends Component { diff --git a/packages/billing/package.json b/packages/billing/package.json index 972b16d6a8..5151136150 100644 --- a/packages/billing/package.json +++ b/packages/billing/package.json @@ -2,6 +2,13 @@ "name": "@cardstack/billing", "version": "0.0.0", "license": "MIT", + "type": "module", + "exports": { + "./package.json": "./package.json", + "./stripe-webhook-handlers": "./stripe-webhook-handlers/index.ts", + "./stripe-webhook-handlers/*": "./stripe-webhook-handlers/*.ts", + "./*": "./*.ts" + }, "dependencies": { "@cardstack/postgres": "workspace:*", "@cardstack/runtime-common": "workspace:*", diff --git a/packages/billing/stripe-webhook-handlers/checkout-session-completed.ts b/packages/billing/stripe-webhook-handlers/checkout-session-completed.ts index 58e7b535ea..bb04a34986 100644 --- a/packages/billing/stripe-webhook-handlers/checkout-session-completed.ts +++ b/packages/billing/stripe-webhook-handlers/checkout-session-completed.ts @@ -8,7 +8,7 @@ import { markStripeEventAsProcessed, updateUserStripeCustomerEmail, } from '../billing-queries.ts'; -import type { StripeCheckoutSessionCompletedWebhookEvent } from '.'; +import type { StripeCheckoutSessionCompletedWebhookEvent } from './index.ts'; import type { PgAdapter } from '@cardstack/postgres'; import { TransactionManager } from '@cardstack/postgres'; diff --git a/packages/billing/stripe-webhook-handlers/payment-succeeded.ts b/packages/billing/stripe-webhook-handlers/payment-succeeded.ts index 726d596f57..ed4ec579c0 100644 --- a/packages/billing/stripe-webhook-handlers/payment-succeeded.ts +++ b/packages/billing/stripe-webhook-handlers/payment-succeeded.ts @@ -21,7 +21,7 @@ import { sumUpCreditsLedger, updateSubscription as updateSubscriptionQuery, } from '../billing-queries.ts'; -import type { StripeInvoicePaymentSucceededWebhookEvent } from '.'; +import type { StripeInvoicePaymentSucceededWebhookEvent } from './index.ts'; import type { PgAdapter } from '@cardstack/postgres'; import { TransactionManager } from '@cardstack/postgres'; import { ProrationCalculator } from '../proration-calculator.ts'; diff --git a/packages/billing/stripe-webhook-handlers/subscription-deleted.ts b/packages/billing/stripe-webhook-handlers/subscription-deleted.ts index 11f540a89d..f8fd209626 100644 --- a/packages/billing/stripe-webhook-handlers/subscription-deleted.ts +++ b/packages/billing/stripe-webhook-handlers/subscription-deleted.ts @@ -1,6 +1,6 @@ import type { DBAdapter } from '@cardstack/runtime-common'; import { reportError } from '@cardstack/runtime-common'; -import type { StripeSubscriptionDeletedWebhookEvent } from '.'; +import type { StripeSubscriptionDeletedWebhookEvent } from './index.ts'; import { insertStripeEvent, updateSubscription, diff --git a/packages/bot-runner/package.json b/packages/bot-runner/package.json index 4de1394192..334fabaf60 100644 --- a/packages/bot-runner/package.json +++ b/packages/bot-runner/package.json @@ -16,7 +16,7 @@ "qunit": "catalog:" }, "scripts": { - "start": "NODE_NO_WARNINGS=1 ts-node --transpileOnly main", + "start": "NODE_NO_WARNINGS=1 node main.ts", "test": "NODE_NO_WARNINGS=1 qunit --require ts-node/register/transpile-only tests/index.ts", "lint": "ember-tsc --noEmit" } diff --git a/packages/boxel-cli/package.json b/packages/boxel-cli/package.json index 74d5523f9f..b49b77890e 100644 --- a/packages/boxel-cli/package.json +++ b/packages/boxel-cli/package.json @@ -69,14 +69,14 @@ "vitest": "catalog:" }, "scripts": { - "build": "pnpm clean && pnpm build:types && pnpm build:test-harness && pnpm build:realms && NODE_NO_WARNINGS=1 ts-node --transpileOnly scripts/build.ts", - "build:plugin": "NODE_NO_WARNINGS=1 ts-node --transpileOnly scripts/build-plugin.ts", - "build:realms": "NODE_NO_WARNINGS=1 ts-node --transpileOnly scripts/build-realms.ts", - "build:skills": "NODE_NO_WARNINGS=1 ts-node --transpileOnly scripts/build-skills.ts", - "build:test-harness": "NODE_NO_WARNINGS=1 ts-node --transpileOnly scripts/build-test-harness.ts", - "build:types": "NODE_NO_WARNINGS=1 ts-node --transpileOnly scripts/build-types.ts", + "build": "pnpm clean && pnpm build:types && pnpm build:test-harness && pnpm build:realms && NODE_NO_WARNINGS=1 node scripts/build.ts", + "build:plugin": "NODE_NO_WARNINGS=1 node scripts/build-plugin.ts", + "build:realms": "NODE_NO_WARNINGS=1 node scripts/build-realms.ts", + "build:skills": "NODE_NO_WARNINGS=1 node scripts/build-skills.ts", + "build:test-harness": "NODE_NO_WARNINGS=1 node scripts/build-test-harness.ts", + "build:types": "NODE_NO_WARNINGS=1 node scripts/build-types.ts", "clean": "rm -rf dist/* bundled-types bundled-test-harness bundled-realms", - "start": "NODE_NO_WARNINGS=1 ts-node --transpileOnly src/index.ts", + "start": "NODE_NO_WARNINGS=1 node src/index.ts", "lint": "concurrently \"pnpm:lint:*(!fix)\" --names \"lint:\"", "lint:fix": "concurrently \"pnpm:lint:*:fix\" --names \"fix:\"", "lint:js": "eslint . --report-unused-disable-directives --cache", diff --git a/packages/boxel-ui/addon/src/components/drag-and-drop/usage.gts b/packages/boxel-ui/addon/src/components/drag-and-drop/usage.gts index a7f9297fee..228cefec8e 100644 --- a/packages/boxel-ui/addon/src/components/drag-and-drop/usage.gts +++ b/packages/boxel-ui/addon/src/components/drag-and-drop/usage.gts @@ -7,7 +7,7 @@ import { type CSSVariableInfo, cssVariable, } from 'ember-freestyle/decorators/css-variable'; -import { get } from 'lodash'; +import { get } from 'lodash-es'; import Pill from '../pill/index.gts'; import DndKanbanBoard, { DndColumn } from './index.gts'; diff --git a/packages/boxel-ui/addon/src/components/multi-select/usage.gts b/packages/boxel-ui/addon/src/components/multi-select/usage.gts index e00479eec1..9125d964d1 100644 --- a/packages/boxel-ui/addon/src/components/multi-select/usage.gts +++ b/packages/boxel-ui/addon/src/components/multi-select/usage.gts @@ -8,7 +8,7 @@ import { cssVariable, } from 'ember-freestyle/decorators/css-variable'; import type { Select } from 'ember-power-select/components/power-select'; -import { includes } from 'lodash'; +import { includes } from 'lodash-es'; import pluralize from 'pluralize'; import cn from '../../helpers/cn.ts'; diff --git a/packages/boxel-ui/addon/src/helpers/pick.ts b/packages/boxel-ui/addon/src/helpers/pick.ts index 06bc4ba575..67d81fe814 100644 --- a/packages/boxel-ui/addon/src/helpers/pick.ts +++ b/packages/boxel-ui/addon/src/helpers/pick.ts @@ -1,4 +1,4 @@ -import { get } from 'lodash'; +import { get } from 'lodash-es'; export default function pick( path: string, diff --git a/packages/catalog/package.json b/packages/catalog/package.json index b41c6d0553..ad6413952d 100644 --- a/packages/catalog/package.json +++ b/packages/catalog/package.json @@ -13,7 +13,7 @@ "@glint/ember-tsc": "catalog:", "@typescript-eslint/eslint-plugin": "catalog:", "@typescript-eslint/parser": "catalog:", - "@types/lodash": "catalog:", + "@types/lodash-es": "catalog:", "@types/qunit": "catalog:", "@universal-ember/test-support": "catalog:", "concurrently": "catalog:", @@ -28,7 +28,7 @@ "eslint-plugin-import": "catalog:", "eslint-plugin-n": "catalog:", "eslint-plugin-prettier": "catalog:", - "lodash": "catalog:", + "lodash-es": "catalog:", "prettier": "catalog:", "prettier-plugin-ember-template-tag": "catalog:", "qunit": "catalog:", diff --git a/packages/experiments-realm/components/search-input.gts b/packages/experiments-realm/components/search-input.gts index b9396ac669..a63c74a681 100644 --- a/packages/experiments-realm/components/search-input.gts +++ b/packages/experiments-realm/components/search-input.gts @@ -1,5 +1,5 @@ import Component from '@glimmer/component'; -import { debounce } from 'lodash'; +import { debounce } from 'lodash-es'; import { action } from '@ember/object'; import { on } from '@ember/modifier'; diff --git a/packages/experiments-realm/experiments_fields_preview.gts b/packages/experiments-realm/experiments_fields_preview.gts index 4a74842275..ad31704728 100644 --- a/packages/experiments-realm/experiments_fields_preview.gts +++ b/packages/experiments-realm/experiments_fields_preview.gts @@ -22,7 +22,7 @@ import { Component } from 'https://cardstack.com/base/card-api'; import { FieldContainer } from '@cardstack/boxel-ui/components'; import { eq } from '@cardstack/boxel-ui/helpers'; import { getField } from '@cardstack/runtime-common'; -import { startCase } from 'lodash'; +import { startCase } from 'lodash-es'; export class ExperimentsFieldsPreview extends CardDef { @field url = contains(UrlField); diff --git a/packages/experiments-realm/llm-model-environment/environment.gts b/packages/experiments-realm/llm-model-environment/environment.gts index d6ab13bf6c..c637408647 100644 --- a/packages/experiments-realm/llm-model-environment/environment.gts +++ b/packages/experiments-realm/llm-model-environment/environment.gts @@ -23,7 +23,7 @@ import { import { Component } from 'https://cardstack.com/base/card-api'; import StringField from 'https://cardstack.com/base/string'; import { Skill } from 'https://cardstack.com/base/skill'; -import { includes, uniqBy } from 'lodash'; +import { includes, uniqBy } from 'lodash-es'; import SettingsIcon from '@cardstack/boxel-icons/settings'; import ZapIcon from '@cardstack/boxel-icons/zap'; diff --git a/packages/experiments-realm/package.json b/packages/experiments-realm/package.json index 48903a065b..253417cb5e 100644 --- a/packages/experiments-realm/package.json +++ b/packages/experiments-realm/package.json @@ -12,7 +12,7 @@ "@types/qunit": "catalog:", "@universal-ember/test-support": "catalog:", "@cardstack/view-transitions": "catalog:", - "@types/lodash": "catalog:", + "@types/lodash-es": "catalog:", "ember-animated": "catalog:", "chess.js": "catalog:", "concurrently": "catalog:", diff --git a/packages/host/app/components/ai-assistant/message/index.gts b/packages/host/app/components/ai-assistant/message/index.gts index 532f14df15..21aad7c2cb 100644 --- a/packages/host/app/components/ai-assistant/message/index.gts +++ b/packages/host/app/components/ai-assistant/message/index.gts @@ -10,7 +10,7 @@ import Component from '@glimmer/component'; import { task } from 'ember-concurrency'; import perform from 'ember-concurrency/helpers/perform'; import Modifier from 'ember-modifier'; -import throttle from 'lodash/throttle'; +import { throttle } from 'lodash-es'; import { Alert } from '@cardstack/boxel-ui/components'; import { cn } from '@cardstack/boxel-ui/helpers'; diff --git a/packages/host/app/components/matrix/room.gts b/packages/host/app/components/matrix/room.gts index 9658112b29..0fd8b5b494 100644 --- a/packages/host/app/components/matrix/room.gts +++ b/packages/host/app/components/matrix/room.gts @@ -21,7 +21,7 @@ import { import perform from 'ember-concurrency/helpers/perform'; import { consume } from 'ember-provide-consume-context'; import { resource, use } from 'ember-resources'; -import max from 'lodash/max'; +import { max } from 'lodash-es'; import pluralize from 'pluralize'; diff --git a/packages/host/app/components/operator-mode/code-editor.gts b/packages/host/app/components/operator-mode/code-editor.gts index 7f39d05234..aff1f4b2fd 100644 --- a/packages/host/app/components/operator-mode/code-editor.gts +++ b/packages/host/app/components/operator-mode/code-editor.gts @@ -16,7 +16,7 @@ import { import perform from 'ember-concurrency/helpers/perform'; -import isEqual from 'lodash/isEqual'; +import { isEqual } from 'lodash-es'; import { Position } from 'monaco-editor'; diff --git a/packages/host/app/components/operator-mode/code-submode.gts b/packages/host/app/components/operator-mode/code-submode.gts index 7f09d01bac..07a3270d5f 100644 --- a/packages/host/app/components/operator-mode/code-submode.gts +++ b/packages/host/app/components/operator-mode/code-submode.gts @@ -19,7 +19,7 @@ import { consume, provide } from 'ember-provide-consume-context'; import { use, resource } from 'ember-resources'; import window from 'ember-window-mock'; -import startCase from 'lodash/startCase'; +import { startCase } from 'lodash-es'; import { TrackedObject } from 'tracked-built-ins'; import { diff --git a/packages/host/app/components/operator-mode/detail-panel.gts b/packages/host/app/components/operator-mode/detail-panel.gts index 319d2f8c96..7991123bbc 100644 --- a/packages/host/app/components/operator-mode/detail-panel.gts +++ b/packages/host/app/components/operator-mode/detail-panel.gts @@ -9,7 +9,7 @@ import Component from '@glimmer/component'; import Package from '@cardstack/boxel-icons/package'; import { use, resource } from 'ember-resources'; -import startCase from 'lodash/startCase'; +import { startCase } from 'lodash-es'; import { TrackedObject } from 'tracked-built-ins'; diff --git a/packages/host/app/components/operator-mode/interact-submode.gts b/packages/host/app/components/operator-mode/interact-submode.gts index b317baea5c..670017bc44 100644 --- a/packages/host/app/components/operator-mode/interact-submode.gts +++ b/packages/host/app/components/operator-mode/interact-submode.gts @@ -13,7 +13,7 @@ import perform from 'ember-concurrency/helpers/perform'; import onKeyMod from 'ember-keyboard/modifiers/on-key'; import { consume } from 'ember-provide-consume-context'; -import get from 'lodash/get'; +import { get } from 'lodash-es'; import { TrackedWeakMap, TrackedSet } from 'tracked-built-ins'; import { cn, gt, MenuItem, MenuDivider } from '@cardstack/boxel-ui/helpers'; diff --git a/packages/host/app/components/operator-mode/overlays.gts b/packages/host/app/components/operator-mode/overlays.gts index 1143d89fc0..ce110f4303 100644 --- a/packages/host/app/components/operator-mode/overlays.gts +++ b/packages/host/app/components/operator-mode/overlays.gts @@ -10,7 +10,7 @@ import { tracked } from '@glimmer/tracking'; import { dropTask } from 'ember-concurrency'; import { velcro } from 'ember-velcro'; -import { isEqual, omit } from 'lodash'; +import { isEqual, omit } from 'lodash-es'; import { localId as localIdSymbol, rri } from '@cardstack/runtime-common'; diff --git a/packages/host/app/helpers/subscribe-to-realms.ts b/packages/host/app/helpers/subscribe-to-realms.ts index 5401ae1712..70c517ee31 100644 --- a/packages/host/app/helpers/subscribe-to-realms.ts +++ b/packages/host/app/helpers/subscribe-to-realms.ts @@ -1,6 +1,6 @@ import Helper from '@ember/component/helper'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { subscribeToRealm } from '@cardstack/runtime-common'; diff --git a/packages/host/app/lib/browser-queue.ts b/packages/host/app/lib/browser-queue.ts index 4a55c734ab..56c17919e7 100644 --- a/packages/host/app/lib/browser-queue.ts +++ b/packages/host/app/lib/browser-queue.ts @@ -1,4 +1,4 @@ -import debounce from 'lodash/debounce'; +import { debounce } from 'lodash-es'; import { type QueueRunner, diff --git a/packages/host/app/lib/externals.ts b/packages/host/app/lib/externals.ts index 52317de3b8..cf0a56a432 100644 --- a/packages/host/app/lib/externals.ts +++ b/packages/host/app/lib/externals.ts @@ -43,7 +43,7 @@ import * as emberProvideConsumeContextContextConsumer from 'ember-provide-consum import * as emberProvideConsumeContextContextProvider from 'ember-provide-consume-context/components/context-provider'; import * as emberResources from 'ember-resources'; import * as flat from 'flat'; -import * as lodash from 'lodash'; +import * as lodash from 'lodash-es'; import * as matrixJsSDK from 'matrix-js-sdk'; import * as rsvp from 'rsvp'; import * as superFastMD5 from 'super-fast-md5'; diff --git a/packages/host/app/lib/matrix-utils.ts b/packages/host/app/lib/matrix-utils.ts index 939510a2d9..4c9d45f588 100644 --- a/packages/host/app/lib/matrix-utils.ts +++ b/packages/host/app/lib/matrix-utils.ts @@ -1,4 +1,4 @@ -import difference from 'lodash/difference'; +import { difference } from 'lodash-es'; export interface MatrixError { data: { diff --git a/packages/host/app/lib/utils.ts b/packages/host/app/lib/utils.ts index 10684fb0fc..7faee7a011 100644 --- a/packages/host/app/lib/utils.ts +++ b/packages/host/app/lib/utils.ts @@ -1,4 +1,4 @@ -import deburr from 'lodash/deburr'; +import { deburr } from 'lodash-es'; import { realmURL, diff --git a/packages/host/app/resources/card-collection.ts b/packages/host/app/resources/card-collection.ts index 0dc3ef5bbe..85785f8da7 100644 --- a/packages/host/app/resources/card-collection.ts +++ b/packages/host/app/resources/card-collection.ts @@ -8,7 +8,7 @@ import { restartableTask } from 'ember-concurrency'; import { Resource } from 'ember-modify-based-class-resource'; -import isEqual from 'lodash/isEqual'; +import { isEqual } from 'lodash-es'; import { TrackedArray } from 'tracked-built-ins'; diff --git a/packages/host/app/resources/file-tree-from-index.ts b/packages/host/app/resources/file-tree-from-index.ts index c8b111bdba..6022d4638a 100644 --- a/packages/host/app/resources/file-tree-from-index.ts +++ b/packages/host/app/resources/file-tree-from-index.ts @@ -6,7 +6,7 @@ import { cached } from '@glimmer/tracking'; import { restartableTask } from 'ember-concurrency'; import { Resource } from 'ember-modify-based-class-resource'; -import isEqual from 'lodash/isEqual'; +import { isEqual } from 'lodash-es'; import { TrackedArray } from 'tracked-built-ins'; import { diff --git a/packages/host/app/resources/prerendered-search.ts b/packages/host/app/resources/prerendered-search.ts index 6756c036db..f71f43f5c4 100644 --- a/packages/host/app/resources/prerendered-search.ts +++ b/packages/host/app/resources/prerendered-search.ts @@ -8,7 +8,7 @@ import { tracked } from '@glimmer/tracking'; import { restartableTask } from 'ember-concurrency'; import { Resource } from 'ember-modify-based-class-resource'; -import isEqual from 'lodash/isEqual'; +import { isEqual } from 'lodash-es'; import { TrackedArray } from 'tracked-built-ins'; import { diff --git a/packages/host/app/resources/room.ts b/packages/host/app/resources/room.ts index 891d5964bd..a199eb1920 100644 --- a/packages/host/app/resources/room.ts +++ b/packages/host/app/resources/room.ts @@ -6,7 +6,7 @@ import { tracked, cached } from '@glimmer/tracking'; import { restartableTask, timeout } from 'ember-concurrency'; import { Resource } from 'ember-modify-based-class-resource'; -import difference from 'lodash/difference'; +import { difference } from 'lodash-es'; import { TrackedMap } from 'tracked-built-ins'; diff --git a/packages/host/app/resources/search-entries.ts b/packages/host/app/resources/search-entries.ts index ae1a8b1fb7..f4d9d958b6 100644 --- a/packages/host/app/resources/search-entries.ts +++ b/packages/host/app/resources/search-entries.ts @@ -7,7 +7,7 @@ import { tracked } from '@glimmer/tracking'; import { didCancel, restartableTask } from 'ember-concurrency'; import { Resource } from 'ember-modify-based-class-resource'; -import isEqual from 'lodash/isEqual'; +import { isEqual } from 'lodash-es'; import { TrackedArray } from 'tracked-built-ins'; import { diff --git a/packages/host/app/resources/search.ts b/packages/host/app/resources/search.ts index 58240dff09..e2b75a721c 100644 --- a/packages/host/app/resources/search.ts +++ b/packages/host/app/resources/search.ts @@ -8,8 +8,8 @@ import { tracked, cached } from '@glimmer/tracking'; import { didCancel, restartableTask, task } from 'ember-concurrency'; import { Resource } from 'ember-modify-based-class-resource'; -import difference from 'lodash/difference'; -import isEqual from 'lodash/isEqual'; +import { difference } from 'lodash-es'; +import { isEqual } from 'lodash-es'; import { TrackedArray } from 'tracked-built-ins'; import type { diff --git a/packages/host/app/routes/module.ts b/packages/host/app/routes/module.ts index efec42d123..1e17996ddc 100644 --- a/packages/host/app/routes/module.ts +++ b/packages/host/app/routes/module.ts @@ -8,7 +8,7 @@ import { isTesting } from '@embroider/macros'; import { parse } from 'date-fns'; -import isEqual from 'lodash/isEqual'; +import { isEqual } from 'lodash-es'; import { type Definition, diff --git a/packages/host/app/routes/render/meta.ts b/packages/host/app/routes/render/meta.ts index 27be2364f2..35b68dc6f1 100644 --- a/packages/host/app/routes/render/meta.ts +++ b/packages/host/app/routes/render/meta.ts @@ -3,7 +3,7 @@ import type Transition from '@ember/routing/transition'; import { service } from '@ember/service'; -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import type { CodeRef } from '@cardstack/runtime-common'; import { diff --git a/packages/host/app/services/matrix-service.ts b/packages/host/app/services/matrix-service.ts index 1a59b35410..3d34b8c62d 100644 --- a/packages/host/app/services/matrix-service.ts +++ b/packages/host/app/services/matrix-service.ts @@ -9,7 +9,7 @@ import { cached, tracked } from '@glimmer/tracking'; import { dropTask, task, timeout } from 'ember-concurrency'; import window from 'ember-window-mock'; -import { cloneDeep } from 'lodash'; +import { cloneDeep } from 'lodash-es'; import { Filter } from 'matrix-js-sdk'; import { diff --git a/packages/host/app/services/monaco-service.ts b/packages/host/app/services/monaco-service.ts index 7cb287d17a..22684e891d 100644 --- a/packages/host/app/services/monaco-service.ts +++ b/packages/host/app/services/monaco-service.ts @@ -8,7 +8,7 @@ import { tracked } from '@glimmer/tracking'; import { task } from 'ember-concurrency'; -import merge from 'lodash/merge'; +import { merge } from 'lodash-es'; // The `?worker&url` suffix is a vite feature that builds each worker into a // standalone script outside the main bundle and gives us back its URL. We diff --git a/packages/host/app/services/store.ts b/packages/host/app/services/store.ts index 28780745d1..6a649e8f23 100644 --- a/packages/host/app/services/store.ts +++ b/packages/host/app/services/store.ts @@ -13,9 +13,9 @@ import { isTesting } from '@embroider/macros'; import { formatDistanceToNow } from 'date-fns'; import { task } from 'ember-concurrency'; -import cloneDeep from 'lodash/cloneDeep'; -import isEqual from 'lodash/isEqual'; -import merge from 'lodash/merge'; +import { cloneDeep } from 'lodash-es'; +import { isEqual } from 'lodash-es'; +import { merge } from 'lodash-es'; import { TrackedObject, TrackedMap } from 'tracked-built-ins'; diff --git a/packages/host/app/utils/file-def-attributes-extractor.ts b/packages/host/app/utils/file-def-attributes-extractor.ts index ef2daf7571..1557be43d3 100644 --- a/packages/host/app/utils/file-def-attributes-extractor.ts +++ b/packages/host/app/utils/file-def-attributes-extractor.ts @@ -1,4 +1,4 @@ -import { isEqual } from 'lodash'; +import { isEqual } from 'lodash-es'; import { baseRef, diff --git a/packages/host/package.json b/packages/host/package.json index da9a5d294f..4934773f86 100644 --- a/packages/host/package.json +++ b/packages/host/package.json @@ -81,7 +81,7 @@ "@types/flat": "catalog:", "@types/htmlbars-inline-precompile": "catalog:", "@types/indefinite": "catalog:", - "@types/lodash": "catalog:", + "@types/lodash-es": "catalog:", "@types/matrix-js-sdk": "catalog:", "@types/ms": "catalog:", "@types/pluralize": "catalog:", @@ -159,7 +159,7 @@ "ignore": "catalog:", "indefinite": "catalog:", "katex": "catalog:", - "lodash": "catalog:", + "lodash-es": "catalog:", "loglevel": "catalog:", "matrix-js-sdk": "catalog:", "mermaid": "catalog:", diff --git a/packages/host/tests/helpers/indexer.ts b/packages/host/tests/helpers/indexer.ts index 2358922723..880f272347 100644 --- a/packages/host/tests/helpers/indexer.ts +++ b/packages/host/tests/helpers/indexer.ts @@ -1,4 +1,4 @@ -import isEqual from 'lodash/isEqual'; +import { isEqual } from 'lodash-es'; import type { LooseCardResource, DBAdapter } from '@cardstack/runtime-common'; import { diff --git a/packages/matrix/package.json b/packages/matrix/package.json index 2e51a4151a..f975e6112a 100644 --- a/packages/matrix/package.json +++ b/packages/matrix/package.json @@ -24,28 +24,28 @@ }, "scripts": { "start:synapse": "./scripts/start-synapse.sh", - "stop:synapse": "ts-node --transpileOnly ./scripts/synapse.ts stop", + "stop:synapse": "node ./scripts/synapse.ts stop", "assert-synapse-running": "./scripts/assert-synapse-running.sh", - "start:smtp": "ts-node --transpileOnly ./scripts/smtp.ts start", - "stop:smtp": "ts-node --transpileOnly ./scripts/smtp.ts stop", + "start:smtp": "node ./scripts/smtp.ts start", + "stop:smtp": "node ./scripts/smtp.ts stop", "assert-smtp-running": "if [ \"`docker ps -f name='boxel-smtp' --format '{{.Names}}'`\" = 'boxel-smtp' ]; then echo 'SMTP is already running'; else pnpm run start:smtp; fi", "start:host-pre-built": "cd ../host && pnpm start --path ./dist", - "start:admin": "ts-node --transpileOnly ./scripts/admin-console", + "start:admin": "node ./scripts/admin-console.ts", "stop:admin": "docker stop synapse-admin && docker rm synapse-admin", - "register-bot-user": "MATRIX_USERNAME=aibot MATRIX_PASSWORD=pass ts-node --transpileOnly ./scripts/register-test-user.ts", - "register-submission-bot": "MATRIX_IS_ADMIN=TRUE MATRIX_USERNAME=submissionbot MATRIX_PASSWORD=password ts-node --transpileOnly ./scripts/register-test-user.ts", - "register-realm-user-using-api": "MATRIX_USERNAME=submissionbot MATRIX_PASSWORD=password ts-node --transpileOnly ./scripts/register-realm-user-using-api.ts", - "realm-user-password": "ts-node --transpileOnly ./scripts/reveal-realm-user-password.ts", - "setup-submission-bot": "MATRIX_USERNAME=submissionbot MATRIX_PASSWORD=password ts-node --transpileOnly ./scripts/setup-submission-bot.ts", - "register-test-user": "MATRIX_USERNAME=user MATRIX_PASSWORD=password ts-node --transpileOnly ./scripts/register-test-user.ts", - "register-skills-writer": "MATRIX_USERNAME=skills_writer MATRIX_PASSWORD=password ts-node --transpileOnly ./scripts/register-test-user.ts", - "register-homepage-writer": "MATRIX_USERNAME=homepage_writer MATRIX_PASSWORD=password ts-node --transpileOnly ./scripts/register-test-user.ts", - "register-realm-users": "ts-node --transpileOnly ./scripts/register-matrix-users.ts realms-only", - "migrate-account-data-http-to-https": "ts-node --transpileOnly ./scripts/migrate-account-data-http-to-https.ts", - "migrate-account-data-https-to-http": "ts-node --transpileOnly ./scripts/migrate-account-data-http-to-https.ts --reverse", - "register-test-admin": "MATRIX_IS_ADMIN=TRUE MATRIX_USERNAME=admin MATRIX_PASSWORD=password ts-node --transpileOnly ./scripts/register-test-user.ts", - "register-test-admin-and-token": "pnpm register-test-admin && ts-node --transpileOnly ./scripts/register-test-token.ts", - "register-all": "ts-node --transpileOnly ./scripts/register-matrix-users.ts all", + "register-bot-user": "MATRIX_USERNAME=aibot MATRIX_PASSWORD=pass node ./scripts/register-test-user.ts", + "register-submission-bot": "MATRIX_IS_ADMIN=TRUE MATRIX_USERNAME=submissionbot MATRIX_PASSWORD=password node ./scripts/register-test-user.ts", + "register-realm-user-using-api": "MATRIX_USERNAME=submissionbot MATRIX_PASSWORD=password node ./scripts/register-realm-user-using-api.ts", + "realm-user-password": "node ./scripts/reveal-realm-user-password.ts", + "setup-submission-bot": "MATRIX_USERNAME=submissionbot MATRIX_PASSWORD=password node ./scripts/setup-submission-bot.ts", + "register-test-user": "MATRIX_USERNAME=user MATRIX_PASSWORD=password node ./scripts/register-test-user.ts", + "register-skills-writer": "MATRIX_USERNAME=skills_writer MATRIX_PASSWORD=password node ./scripts/register-test-user.ts", + "register-homepage-writer": "MATRIX_USERNAME=homepage_writer MATRIX_PASSWORD=password node ./scripts/register-test-user.ts", + "register-realm-users": "node ./scripts/register-matrix-users.ts realms-only", + "migrate-account-data-http-to-https": "node ./scripts/migrate-account-data-http-to-https.ts", + "migrate-account-data-https-to-http": "node ./scripts/migrate-account-data-http-to-https.ts --reverse", + "register-test-admin": "MATRIX_IS_ADMIN=TRUE MATRIX_USERNAME=admin MATRIX_PASSWORD=password node ./scripts/register-test-user.ts", + "register-test-admin-and-token": "pnpm register-test-admin && node ./scripts/register-test-token.ts", + "register-all": "node ./scripts/register-matrix-users.ts all", "test": "./scripts/test.sh", "test:cleanup": "./scripts/remove-test-dbs.sh", "test:group": "./scripts/test.sh", diff --git a/packages/matrix/scripts/assert-synapse-running.sh b/packages/matrix/scripts/assert-synapse-running.sh index 06750b0f7f..9d6a3ced9d 100755 --- a/packages/matrix/scripts/assert-synapse-running.sh +++ b/packages/matrix/scripts/assert-synapse-running.sh @@ -25,7 +25,7 @@ if [ "$RUNNING" = "$CONTAINER_NAME" ]; then if [ -n "$BOXEL_ENVIRONMENT" ]; then HOST_PORT=$(docker port "$CONTAINER_NAME" 8008/tcp 2>/dev/null | head -1 | awk -F: '{print $NF}') if [ -n "$HOST_PORT" ]; then - pnpm exec ts-node --transpileOnly -e "import { registerSynapseWithTraefik } from './support/environment-config'; registerSynapseWithTraefik($HOST_PORT);" + node --input-type=module -e "import { registerSynapseWithTraefik } from './support/environment-config.ts'; registerSynapseWithTraefik($HOST_PORT);" fi fi else diff --git a/packages/matrix/scripts/migrate-realm-user.sh b/packages/matrix/scripts/migrate-realm-user.sh index d460e2a000..646670d5d5 100755 --- a/packages/matrix/scripts/migrate-realm-user.sh +++ b/packages/matrix/scripts/migrate-realm-user.sh @@ -10,4 +10,4 @@ if [ -z "$1" ]; then exit -1 fi -ts-node --transpileOnly ./scripts/migrate-realm-user $1 +node ./scripts/migrate-realm-user.ts $1 diff --git a/packages/matrix/scripts/migrate-realm-users.sh b/packages/matrix/scripts/migrate-realm-users.sh index 02f2efbea3..47d919a050 100755 --- a/packages/matrix/scripts/migrate-realm-users.sh +++ b/packages/matrix/scripts/migrate-realm-users.sh @@ -3,12 +3,12 @@ : ${REALM_SECRET_SEED:="shhh! it's a secret"} export REALM_SECRET_SEED -ts-node --transpileOnly ./scripts/migrate-realm-user @realm-server:localhost -ts-node --transpileOnly ./scripts/migrate-realm-user @node-test_realm-server:localhost -ts-node --transpileOnly ./scripts/migrate-realm-user @base_realm:localhost -ts-node --transpileOnly ./scripts/migrate-realm-user @boxel_homepage_realm:localhost -ts-node --transpileOnly ./scripts/migrate-realm-user @submission_realm:localhost -ts-node --transpileOnly ./scripts/migrate-realm-user @experiments_realm:localhost -ts-node --transpileOnly ./scripts/migrate-realm-user @software_factory_realm:localhost -ts-node --transpileOnly ./scripts/migrate-realm-user @node-test_realm:localhost -ts-node --transpileOnly ./scripts/migrate-realm-user @test_realm:localhost +node ./scripts/migrate-realm-user.ts @realm-server:localhost +node ./scripts/migrate-realm-user.ts @node-test_realm-server:localhost +node ./scripts/migrate-realm-user.ts @base_realm:localhost +node ./scripts/migrate-realm-user.ts @boxel_homepage_realm:localhost +node ./scripts/migrate-realm-user.ts @submission_realm:localhost +node ./scripts/migrate-realm-user.ts @experiments_realm:localhost +node ./scripts/migrate-realm-user.ts @software_factory_realm:localhost +node ./scripts/migrate-realm-user.ts @node-test_realm:localhost +node ./scripts/migrate-realm-user.ts @test_realm:localhost diff --git a/packages/matrix/scripts/start-synapse.sh b/packages/matrix/scripts/start-synapse.sh index aeadba1367..9e7b02748f 100755 --- a/packages/matrix/scripts/start-synapse.sh +++ b/packages/matrix/scripts/start-synapse.sh @@ -13,4 +13,4 @@ fi mkdir -p "${SYNAPSE_DATA_DIR}/db" export SYNAPSE_DATA_DIR -exec ts-node --transpileOnly ./scripts/synapse.ts start +exec node ./scripts/synapse.ts start diff --git a/packages/matrix/support/environment-config.ts b/packages/matrix/support/environment-config.ts index 760f808474..5ebdc60712 100644 --- a/packages/matrix/support/environment-config.ts +++ b/packages/matrix/support/environment-config.ts @@ -24,7 +24,14 @@ function traefikDynamicDir(): string { } catch { // Traefik not running — fall back to repo-relative path } - _traefikDir = resolve(__dirname, '..', '..', '..', 'traefik', 'dynamic'); + _traefikDir = resolve( + import.meta.dirname, + '..', + '..', + '..', + 'traefik', + 'dynamic', + ); return _traefikDir; } diff --git a/packages/matrix/support/isolated-realm-server.ts b/packages/matrix/support/isolated-realm-server.ts index 571fb95766..c82a84e5ac 100644 --- a/packages/matrix/support/isolated-realm-server.ts +++ b/packages/matrix/support/isolated-realm-server.ts @@ -2,7 +2,8 @@ import { spawn, type ChildProcess } from 'child_process'; import { resolve, join } from 'path'; // @ts-expect-error no types import { dirSync, setGracefulCleanup } from 'tmp'; -import { ensureDirSync, copySync, readFileSync } from 'fs-extra'; +import fsExtra from 'fs-extra'; +const { ensureDirSync, copySync, readFileSync } = fsExtra; import { Pool } from 'pg'; import { createServer as createNetServer, type AddressInfo } from 'net'; import type { SynapseInstance } from './synapse/index.ts'; @@ -22,14 +23,16 @@ setGracefulCleanup(); // `writable` patch, and the hand-rolled `proxyAsset` forwarder). const testRealmCards = resolve( - join(__dirname, '..', '..', 'test-realm-cards', 'contents'), + join(import.meta.dirname, '..', '..', 'test-realm-cards', 'contents'), +); +const realmServerDir = resolve( + join(import.meta.dirname, '..', '..', 'realm-server'), ); -const realmServerDir = resolve(join(__dirname, '..', '..', 'realm-server')); const skillsRealmDir = resolve( - join(__dirname, '..', '..', 'skills-realm', 'contents'), + join(import.meta.dirname, '..', '..', 'skills-realm', 'contents'), ); -const baseRealmDir = resolve(join(__dirname, '..', '..', 'base')); -const matrixDir = resolve(join(__dirname, '..')); +const baseRealmDir = resolve(join(import.meta.dirname, '..', '..', 'base')); +const matrixDir = resolve(join(import.meta.dirname, '..')); export const appURL = 'https://localhost:4205/test'; const DEFAULT_PRERENDER_PORT = 4231; @@ -288,13 +291,9 @@ export async function startPrerenderServer( PRERENDER_PAGE_POOL_MIN: process.env.PRERENDER_PAGE_POOL_MIN ?? '4', PRERENDER_PAGE_POOL_MAX: process.env.PRERENDER_PAGE_POOL_MAX ?? '8', }; - let prerenderArgs = [ - '--transpileOnly', - 'prerender/prerender-server', - `--port=${port}`, - ]; + let prerenderArgs = ['prerender/prerender-server.ts', `--port=${port}`]; - let child = spawn('ts-node', prerenderArgs, { + let child = spawn('node', prerenderArgs, { cwd: realmServerDir, stdio: ['pipe', 'pipe', 'pipe'], env, @@ -405,8 +404,7 @@ export async function startServer({ process.env.LOW_CREDIT_THRESHOLD = '2000'; let workerArgs = [ - `--transpileOnly`, - 'worker-manager', + 'worker-manager.ts', `--port=${workerManagerPort}`, `--matrixURL='${matrixURL}'`, `--prerendererUrl='${prerenderURL}'`, @@ -424,7 +422,7 @@ export async function startServer({ `--toUrl='https://localhost:4205/base/'`, ]); - let workerManager = spawn('ts-node', workerArgs, { + let workerManager = spawn('node', workerArgs, { cwd: realmServerDir, stdio: ['pipe', 'pipe', 'pipe', 'ipc'], env: { @@ -515,8 +513,7 @@ export async function startServer({ } let serverArgs = [ - `--transpileOnly`, - 'main', + 'main.ts', `--port=4205`, `--matrixURL='${matrixURL}'`, `--realmsRootPath='${dir.name}'`, @@ -544,7 +541,7 @@ export async function startServer({ console.log(`realm server database: ${testDBName}`); - realmServer = spawn('ts-node', serverArgs, { + realmServer = spawn('node', serverArgs, { cwd: realmServerDir, stdio: ['pipe', 'pipe', 'pipe', 'ipc'], env: { diff --git a/packages/matrix/support/synapse/index.ts b/packages/matrix/support/synapse/index.ts index 2a2813852e..a770645318 100644 --- a/packages/matrix/support/synapse/index.ts +++ b/packages/matrix/support/synapse/index.ts @@ -24,7 +24,7 @@ export const SYNAPSE_IP_ADDRESS = '172.20.0.5'; export const SYNAPSE_PORT = 8008; const registrationSecretFile = path.resolve( - path.join(__dirname, '..', '..', 'registration_secret.txt'), + path.join(import.meta.dirname, '..', '..', 'registration_secret.txt'), ); interface SynapseConfig { @@ -94,7 +94,7 @@ export async function cfgDirFromTemplate( port?: number; }, ): Promise { - const templateDir = path.join(__dirname, template); + const templateDir = path.join(import.meta.dirname, template); const stats = await fse.stat(templateDir); if (!stats?.isDirectory) { @@ -215,7 +215,7 @@ export async function synapseStart( '-v', `${synCfg.configDir}:/data`, '-v', - `${path.join(__dirname, 'templates')}:/custom/templates/`, + `${path.join(import.meta.dirname, 'templates')}:/custom/templates/`, ]; if (useDynamicHostPort) { // In dynamic-host-port mode multiple harnesses may run concurrently, so diff --git a/packages/postgres/pg-adapter.ts b/packages/postgres/pg-adapter.ts index 3d6b1b9d56..8984d6d9ca 100644 --- a/packages/postgres/pg-adapter.ts +++ b/packages/postgres/pg-adapter.ts @@ -14,7 +14,7 @@ import { join } from 'path'; import { Pool, Client, type Notification } from 'pg'; import { postgresConfig } from './pg-config.ts'; -import migrationNameFixes from './scripts/migration-name-fixes.js'; +import migrationNameFixes from './scripts/migration-name-fixes.cjs'; // Hash a realm URL to a stable signed int64 (as a string, because JS numbers // can't represent the full int64 range). Used as a pg advisory lock key: diff --git a/packages/postgres/scripts/convert-to-sqlite.ts b/packages/postgres/scripts/convert-to-sqlite.ts index ffbd68087b..ea6f9a23f4 100755 --- a/packages/postgres/scripts/convert-to-sqlite.ts +++ b/packages/postgres/scripts/convert-to-sqlite.ts @@ -1,5 +1,5 @@ /* eslint-env node */ -import { readFileSync, readdirSync, writeFileSync } from 'fs-extra'; +import { readFileSync, readdirSync, writeFileSync } from 'fs'; import { resolve, join } from 'path'; import { parse, diff --git a/packages/realm-server/handlers/create-realm.ts b/packages/realm-server/handlers/create-realm.ts index ea3d7b3ee9..6809570b54 100644 --- a/packages/realm-server/handlers/create-realm.ts +++ b/packages/realm-server/handlers/create-realm.ts @@ -1,6 +1,7 @@ import type Koa from 'koa'; import { resolve, join } from 'path'; -import { ensureDirSync, writeJSONSync } from 'fs-extra'; +import fsExtra from 'fs-extra'; +const { ensureDirSync, writeJSONSync } = fsExtra; import * as Sentry from '@sentry/node'; import type { DBAdapter, diff --git a/packages/realm-server/handlers/handle-download-realm.ts b/packages/realm-server/handlers/handle-download-realm.ts index 47575bbaf7..8c598bd728 100644 --- a/packages/realm-server/handlers/handle-download-realm.ts +++ b/packages/realm-server/handlers/handle-download-realm.ts @@ -12,7 +12,8 @@ import { AuthenticationError } from '@cardstack/runtime-common/router'; import { parseRealmsParam } from '@cardstack/runtime-common/search-utils'; import { verifyURLSignature } from '@cardstack/runtime-common/url-signature'; import archiver from 'archiver'; -import { existsSync, statSync } from 'fs-extra'; +import fsExtra from 'fs-extra'; +const { existsSync, statSync } = fsExtra; import { join, relative, resolve, sep, isAbsolute } from 'path'; import type { CreateRoutesArgs } from '../routes.ts'; import { retrieveTokenClaim } from '../utils/jwt.ts'; diff --git a/packages/realm-server/handlers/handle-publish-realm.ts b/packages/realm-server/handlers/handle-publish-realm.ts index aa16dbfd93..352e4e56eb 100644 --- a/packages/realm-server/handlers/handle-publish-realm.ts +++ b/packages/realm-server/handlers/handle-publish-realm.ts @@ -18,14 +18,8 @@ import { import { getPublishedRealmDomainOverrides } from '@cardstack/runtime-common/constants'; import { join } from 'path'; -import { - copySync, - readJsonSync, - writeJsonSync, - removeSync, - existsSync, - moveSync, -} from 'fs-extra'; +import fsExtra from 'fs-extra'; +const { copySync, readJsonSync, writeJsonSync, removeSync, existsSync, moveSync } = fsExtra; import { fetchRequestFromContext, diff --git a/packages/realm-server/handlers/realm-destruction-utils.ts b/packages/realm-server/handlers/realm-destruction-utils.ts index 889c01f147..af7d38d0db 100644 --- a/packages/realm-server/handlers/realm-destruction-utils.ts +++ b/packages/realm-server/handlers/realm-destruction-utils.ts @@ -6,7 +6,8 @@ import { param, separatedByCommas, } from '@cardstack/runtime-common'; -import { pathExistsSync, readdirSync, removeSync } from 'fs-extra'; +import fsExtra from 'fs-extra'; +const { pathExistsSync, readdirSync, removeSync } = fsExtra; import { join, relative } from 'path'; // Walk a realm's on-disk directory and return every file's path relative diff --git a/packages/realm-server/handlers/serve-index.ts b/packages/realm-server/handlers/serve-index.ts index 719effaf05..a484baeb93 100644 --- a/packages/realm-server/handlers/serve-index.ts +++ b/packages/realm-server/handlers/serve-index.ts @@ -1,6 +1,6 @@ import type Koa from 'koa'; import { JSDOM } from 'jsdom'; -import merge from 'lodash/merge'; +import { merge } from 'lodash-es'; import type { DBAdapter, Realm } from '@cardstack/runtime-common'; import { hasExtension, diff --git a/packages/realm-server/lib/dev-service-registry.ts b/packages/realm-server/lib/dev-service-registry.ts index 0abd4d5e14..9bc6b78366 100644 --- a/packages/realm-server/lib/dev-service-registry.ts +++ b/packages/realm-server/lib/dev-service-registry.ts @@ -31,7 +31,7 @@ function traefikDynamicDir(): string { } catch { // Traefik not running — fall back to repo-relative path } - _traefikDir = resolve(__dirname, '..', '..', '..', 'traefik', 'dynamic'); + _traefikDir = resolve(import.meta.dirname, '..', '..', '..', 'traefik', 'dynamic'); return _traefikDir; } diff --git a/packages/realm-server/lib/realm-registry-backfill.ts b/packages/realm-server/lib/realm-registry-backfill.ts index e553b5eeaa..84f8abc8a0 100644 --- a/packages/realm-server/lib/realm-registry-backfill.ts +++ b/packages/realm-server/lib/realm-registry-backfill.ts @@ -11,7 +11,7 @@ import { type DBAdapter, } from '@cardstack/runtime-common'; import type { PgAdapter } from '@cardstack/postgres'; -import { isEnvironmentMode } from './dev-service-registry'; +import { isEnvironmentMode } from './dev-service-registry.ts'; const log = logger('realm-server:registry-backfill'); diff --git a/packages/realm-server/lib/realm-routing.ts b/packages/realm-server/lib/realm-routing.ts index ec2aaf657d..a9848654b4 100644 --- a/packages/realm-server/lib/realm-routing.ts +++ b/packages/realm-server/lib/realm-routing.ts @@ -1,5 +1,6 @@ import { join } from 'path'; -import { existsSync } from 'fs-extra'; +import fsExtra from 'fs-extra'; +const { existsSync } = fsExtra; import type { DBAdapter, Realm } from '@cardstack/runtime-common'; import { executableExtensions, diff --git a/packages/realm-server/node-realm.ts b/packages/realm-server/node-realm.ts index 11de9151b9..f43426743e 100644 --- a/packages/realm-server/node-realm.ts +++ b/packages/realm-server/node-realm.ts @@ -19,16 +19,8 @@ import type { ServerResponse } from 'http'; import sane, { type Watcher } from 'sane'; import type { ReadStream } from 'fs-extra'; -import { - readdirSync, - existsSync, - writeFileSync, - statSync, - ensureDirSync, - ensureFileSync, - createReadStream, - removeSync, -} from 'fs-extra'; +import fsExtra from 'fs-extra'; +const { readdirSync, existsSync, writeFileSync, statSync, ensureDirSync, ensureFileSync, createReadStream, removeSync } = fsExtra; import { join } from 'path'; import { Duplex } from 'node:stream'; import type { diff --git a/packages/realm-server/package.json b/packages/realm-server/package.json index a5486df756..95f24dbedb 100644 --- a/packages/realm-server/package.json +++ b/packages/realm-server/package.json @@ -2,7 +2,7 @@ "name": "@cardstack/realm-server", "version": "0.0.0", "license": "MIT", - "type": "commonjs", + "type": "module", "devDependencies": { "@aws-crypto/sha256-js": "catalog:", "@babel/parser": "catalog:", @@ -29,7 +29,7 @@ "@types/koa-compose": "catalog:", "@types/koa__cors": "catalog:", "@types/koa__router": "catalog:", - "@types/lodash": "catalog:", + "@types/lodash-es": "catalog:", "@types/mime-types": "catalog:", "@types/ms": "catalog:", "@types/node": "catalog:", @@ -65,7 +65,7 @@ "koa": "catalog:", "koa-compose": "catalog:", "koa-proxies": "catalog:", - "lodash": "catalog:", + "lodash-es": "catalog:", "loglevel": "catalog:", "mime-types": "catalog:", "npm-run-all": "catalog:", @@ -97,9 +97,9 @@ "scripts": { "test": "./tests/scripts/run-qunit-with-test-pg.sh", "test-module": "./tests/scripts/run-qunit-with-test-pg.sh --module ${TEST_MODULE}", - "bench:realm": "LOG_LEVELS='*=warn,prerenderer-chrome=none' TEST_HARNESS_REALM_LOG_LEVELS='*=warn,prerenderer-chrome=none' TEST_HARNESS_PRERENDER_LOG_LEVELS='*=warn,prerenderer-chrome=none' NODE_NO_WARNINGS=1 ts-node --transpileOnly scripts/bench-realm/bench.ts", - "bench:realm:check": "LOG_LEVELS='*=warn,prerenderer-chrome=none' TEST_HARNESS_REALM_LOG_LEVELS='*=warn,prerenderer-chrome=none' TEST_HARNESS_PRERENDER_LOG_LEVELS='*=warn,prerenderer-chrome=none' NODE_NO_WARNINGS=1 ts-node --transpileOnly scripts/bench-realm/check.ts", - "migrate": "NODE_NO_WARNINGS=1 ts-node --transpileOnly scripts/run-migrations.ts", + "bench:realm": "LOG_LEVELS='*=warn,prerenderer-chrome=none' TEST_HARNESS_REALM_LOG_LEVELS='*=warn,prerenderer-chrome=none' TEST_HARNESS_PRERENDER_LOG_LEVELS='*=warn,prerenderer-chrome=none' NODE_NO_WARNINGS=1 node scripts/bench-realm/bench.ts", + "bench:realm:check": "LOG_LEVELS='*=warn,prerenderer-chrome=none' TEST_HARNESS_REALM_LOG_LEVELS='*=warn,prerenderer-chrome=none' TEST_HARNESS_PRERENDER_LOG_LEVELS='*=warn,prerenderer-chrome=none' NODE_NO_WARNINGS=1 node scripts/bench-realm/check.ts", + "migrate": "NODE_NO_WARNINGS=1 node scripts/run-migrations.ts", "start:matrix": "./scripts/start-matrix.sh", "start:smtp": "cd ../matrix && pnpm assert-smtp-running", "start:icons": "mise run services:icons", @@ -114,7 +114,7 @@ "setup:software-factory-in-deployment": "mkdir -p /persistent/software-factory && rsync --dry-run --itemize-changes --checksum --recursive --delete ../software-factory/realm/. /persistent/software-factory/ && rsync --checksum --recursive --delete ../software-factory/realm/. /persistent/software-factory/", "setup:boxel-homepage-in-deployment": "mkdir -p /persistent/boxel-homepage", "setup:openrouter-in-deployment": "mkdir -p /persistent/openrouter /persistent/openrouter/OpenRouterModel && rsync --dry-run --itemize-changes --checksum --recursive --delete --exclude 'OpenRouterModel/' ../openrouter-realm/. /persistent/openrouter/ && rsync --checksum --recursive --delete --exclude 'OpenRouterModel/' ../openrouter-realm/. /persistent/openrouter/", - "start": "PGPORT=5435 NODE_NO_WARNINGS=1 ts-node --transpileOnly main", + "start": "PGPORT=5435 NODE_NO_WARNINGS=1 node main.ts", "start:base": "mise run services:realm-server-base -- --workerManagerPort=4213", "start:test-realms": "mise run services:test-realms -- --workerManagerPort=4211", "start:all": "mise run dev", @@ -140,11 +140,11 @@ "lint:types": "ember-tsc --noEmit", "full-reset": "./scripts/full-reset.sh", "full-reindex": "./scripts/full-reindex.sh", - "clear-modules-cache": "NODE_NO_WARNINGS=1 PGDATABASE=${PGDATABASE:-boxel} PGPORT=${PGPORT:-5435} ts-node --transpileOnly scripts/clear-modules-cache.ts", - "codemod:context-search": "NODE_NO_WARNINGS=1 ts-node --transpileOnly scripts/codemod/context-search/run.ts", + "clear-modules-cache": "NODE_NO_WARNINGS=1 PGDATABASE=${PGDATABASE:-boxel} PGPORT=${PGPORT:-5435} node scripts/clear-modules-cache.ts", + "codemod:context-search": "NODE_NO_WARNINGS=1 node scripts/codemod/context-search/run.ts", "check-user-pg-connections": "./scripts/check-user-pg-connections.sh", - "sync-stripe-products": "NODE_NO_WARNINGS=1 PGDATABASE=boxel PGPORT=5435 ts-node --transpileOnly scripts/sync-stripe-products.ts", - "sync-openrouter-models": "NODE_NO_WARNINGS=1 PGDATABASE=boxel PGPORT=5435 ts-node --transpileOnly scripts/sync-openrouter-models.ts", + "sync-stripe-products": "NODE_NO_WARNINGS=1 PGDATABASE=boxel PGPORT=5435 node scripts/sync-stripe-products.ts", + "sync-openrouter-models": "NODE_NO_WARNINGS=1 PGDATABASE=boxel PGPORT=5435 node scripts/sync-openrouter-models.ts", "stripe": "docker run --rm --add-host=host.docker.internal:host-gateway -it stripe/stripe-cli:latest" }, "dependencies": { diff --git a/packages/realm-server/routes.ts b/packages/realm-server/routes.ts index ab5567bb62..589e2d250b 100644 --- a/packages/realm-server/routes.ts +++ b/packages/realm-server/routes.ts @@ -408,7 +408,7 @@ function handleGitHubPRRequestLazy(args: CreateRoutesArgs) { return async function (ctxt: Koa.Context, next: Koa.Next) { if (!handler) { handler = ( - createRequire(__filename)( + createRequire(import.meta.filename)( './handlers/handle-github-pr', ) as typeof import('./handlers/handle-github-pr.ts') ).default(args); diff --git a/packages/realm-server/scripts/bench-realm/bench.ts b/packages/realm-server/scripts/bench-realm/bench.ts index abd9bdd86b..02c996f166 100644 --- a/packages/realm-server/scripts/bench-realm/bench.ts +++ b/packages/realm-server/scripts/bench-realm/bench.ts @@ -50,7 +50,7 @@ import { realmSnapshotDir } from './paths.ts'; // which is correct — a different host produced the cached rows. function hostDistFingerprint(): string { let indexPath = pathResolve( - __dirname, + import.meta.dirname, '..', '..', '..', @@ -82,7 +82,7 @@ export const DEFAULT_WARMUP = 5; // the bench's instance JSONs `adoptsFrom`. No runtime fileFilter — the // glob is materialized in the snapshot itself, so the bench mounts the // realm with the default copy-everything semantics. -const benchSourceRealmDir = pathResolve(__dirname, 'fixtures', 'source-realm'); +const benchSourceRealmDir = pathResolve(import.meta.dirname, 'fixtures', 'source-realm'); export interface Scenario { name: string; diff --git a/packages/realm-server/scripts/bench-realm/paths.ts b/packages/realm-server/scripts/bench-realm/paths.ts index 1d32a62663..712bb83bf8 100644 --- a/packages/realm-server/scripts/bench-realm/paths.ts +++ b/packages/realm-server/scripts/bench-realm/paths.ts @@ -1,6 +1,6 @@ import { resolve } from 'node:path'; -export const benchRoot = __dirname; +export const benchRoot = import.meta.dirname; export const fixturesDir = resolve(benchRoot, 'fixtures'); export const realmSnapshotDir = resolve(fixturesDir, 'realm-snapshot'); export const baselinePath = resolve(benchRoot, 'baseline.json'); diff --git a/packages/realm-server/scripts/codemod/context-search/run.ts b/packages/realm-server/scripts/codemod/context-search/run.ts index ac87e703ee..daa4aa01d0 100644 --- a/packages/realm-server/scripts/codemod/context-search/run.ts +++ b/packages/realm-server/scripts/codemod/context-search/run.ts @@ -10,7 +10,7 @@ import { join, resolve } from 'path'; import * as prettier from 'prettier'; -import { transformContextSearch } from './transform'; +import { transformContextSearch } from './transform.ts'; // Format the migrated source through the repo's prettier config (with // prettier-plugin-ember-template-tag for `.gts`) so the structural edits land as diff --git a/packages/realm-server/scripts/start-prerender-manager.sh b/packages/realm-server/scripts/start-prerender-manager.sh index 962bc14e06..bc09846a1d 100755 --- a/packages/realm-server/scripts/start-prerender-manager.sh +++ b/packages/realm-server/scripts/start-prerender-manager.sh @@ -15,6 +15,5 @@ echo "[start-prerender-manager] pid=$$ ppid=$PPID about to exec ts-node at $(dat NODE_ENV=production \ NODE_NO_WARNINGS=1 \ - exec ts-node \ - --transpileOnly prerender/manager-server \ + exec node prerender/manager-server.ts \ --port=${PRERENDER_MANAGER_PORT:-4222} diff --git a/packages/realm-server/scripts/start-prerender-production.sh b/packages/realm-server/scripts/start-prerender-production.sh index 48c0ffe200..b30db37464 100755 --- a/packages/realm-server/scripts/start-prerender-production.sh +++ b/packages/realm-server/scripts/start-prerender-production.sh @@ -17,6 +17,5 @@ echo "[start-prerender-production] pid=$$ ppid=$PPID about to exec ts-node at $( NODE_ENV=production \ NODE_NO_WARNINGS=1 \ BOXEL_HOST_URL=https://app.boxel.ai \ - exec ts-node \ - --transpileOnly prerender/prerender-server \ + exec node prerender/prerender-server.ts \ --port=${PRERENDER_PORT:-4221} diff --git a/packages/realm-server/scripts/start-prerender-staging.sh b/packages/realm-server/scripts/start-prerender-staging.sh index c93d724a62..4eeebe3512 100755 --- a/packages/realm-server/scripts/start-prerender-staging.sh +++ b/packages/realm-server/scripts/start-prerender-staging.sh @@ -17,6 +17,5 @@ echo "[start-prerender-staging] pid=$$ ppid=$PPID about to exec ts-node at $(dat NODE_ENV=production \ NODE_NO_WARNINGS=1 \ BOXEL_HOST_URL=https://realms-staging.stack.cards \ - exec ts-node \ - --transpileOnly prerender/prerender-server \ + exec node prerender/prerender-server.ts \ --port=${PRERENDER_PORT:-4221} diff --git a/packages/realm-server/scripts/start-production.sh b/packages/realm-server/scripts/start-production.sh index 4fb9296138..4778c6ef3b 100755 --- a/packages/realm-server/scripts/start-production.sh +++ b/packages/realm-server/scripts/start-production.sh @@ -38,8 +38,7 @@ NODE_NO_WARNINGS=1 \ REALM_SERVER_MATRIX_USERNAME=realm_server \ PUBLISHED_REALM_BOXEL_SPACE_DOMAIN='boxel.space' \ PUBLISHED_REALM_BOXEL_SITE_DOMAIN='boxel.site' \ - exec ts-node \ - --transpileOnly main \ + exec node main.ts \ --port=3000 \ --matrixURL='https://matrix.boxel.ai' \ --realmsRootPath='/persistent/realms' \ diff --git a/packages/realm-server/scripts/start-staging.sh b/packages/realm-server/scripts/start-staging.sh index e12eb23666..9aba3408b3 100755 --- a/packages/realm-server/scripts/start-staging.sh +++ b/packages/realm-server/scripts/start-staging.sh @@ -38,8 +38,7 @@ NODE_NO_WARNINGS=1 \ REALM_SERVER_MATRIX_USERNAME=realm_server \ PUBLISHED_REALM_BOXEL_SPACE_DOMAIN='staging.boxel.dev' \ PUBLISHED_REALM_BOXEL_SITE_DOMAIN='staging.boxel.build' \ - exec ts-node \ - --transpileOnly main \ + exec node main.ts \ --port=3000 \ --matrixURL='https://matrix-staging.stack.cards' \ --realmsRootPath='/persistent/realms' \ diff --git a/packages/realm-server/scripts/start-worker-production.sh b/packages/realm-server/scripts/start-worker-production.sh index 0e1503f011..3af23aed58 100755 --- a/packages/realm-server/scripts/start-worker-production.sh +++ b/packages/realm-server/scripts/start-worker-production.sh @@ -21,8 +21,7 @@ NODE_NO_WARNINGS=1 \ REALM_SERVER_MATRIX_USERNAME=realm_server \ LOW_CREDIT_THRESHOLD=2000 \ OPENROUTER_REALM_URL='https://app.boxel.ai/openrouter/' \ - exec ts-node \ - --transpileOnly worker-manager \ + exec node worker-manager.ts \ --allPriorityCount="${WORKER_ALL_PRIORITY_COUNT:-1}" \ --highPriorityCount="${WORKER_HIGH_PRIORITY_COUNT:-0}" \ --prerendererUrl='http://boxel-prerender-manager.boxel-production-internal:4222' \ diff --git a/packages/realm-server/scripts/start-worker-staging.sh b/packages/realm-server/scripts/start-worker-staging.sh index 74754dc1f2..ee605f8256 100755 --- a/packages/realm-server/scripts/start-worker-staging.sh +++ b/packages/realm-server/scripts/start-worker-staging.sh @@ -21,8 +21,7 @@ NODE_NO_WARNINGS=1 \ REALM_SERVER_MATRIX_USERNAME=realm_server \ LOW_CREDIT_THRESHOLD=2000 \ OPENROUTER_REALM_URL='https://realms-staging.stack.cards/openrouter/' \ - exec ts-node \ - --transpileOnly worker-manager \ + exec node worker-manager.ts \ --allPriorityCount="${WORKER_ALL_PRIORITY_COUNT:-1}" \ --highPriorityCount="${WORKER_HIGH_PRIORITY_COUNT:-0}" \ --prerendererUrl='http://boxel-prerender-manager.boxel-staging-internal:4222' \ diff --git a/packages/realm-server/server.ts b/packages/realm-server/server.ts index 8357fc9835..3d5b881487 100644 --- a/packages/realm-server/server.ts +++ b/packages/realm-server/server.ts @@ -14,7 +14,8 @@ import { DEFAULT_CARD_SIZE_LIMIT_BYTES, DEFAULT_FILE_SIZE_LIMIT_BYTES, } from '@cardstack/runtime-common'; -import { ensureDirSync } from 'fs-extra'; +import fsExtra from 'fs-extra'; +const { ensureDirSync } = fsExtra; import { httpLogging, ecsMetadata, diff --git a/packages/realm-server/synapse.ts b/packages/realm-server/synapse.ts index aef86026e4..73aac8cc34 100644 --- a/packages/realm-server/synapse.ts +++ b/packages/realm-server/synapse.ts @@ -1,5 +1,6 @@ /* eslint-env node */ -import { readFileSync } from 'fs-extra'; +import fsExtra from 'fs-extra'; +const { readFileSync } = fsExtra; import { resolve, join } from 'path'; import { createHmac } from 'crypto'; import yaml from 'yaml'; @@ -15,7 +16,7 @@ function homeserverFile(): string { .replace(/^-|-$/g, ''); let branchFile = resolve( join( - __dirname, + import.meta.dirname, '..', 'matrix', `synapse-data-${slug}`, @@ -27,7 +28,7 @@ function homeserverFile(): string { } } return resolve( - join(__dirname, '..', 'matrix', 'synapse-data', 'homeserver.yaml'), + join(import.meta.dirname, '..', 'matrix', 'synapse-data', 'homeserver.yaml'), ); } diff --git a/packages/realm-server/tests/async-semaphore-test.ts b/packages/realm-server/tests/async-semaphore-test.ts index 3080dba364..5329043bcb 100644 --- a/packages/realm-server/tests/async-semaphore-test.ts +++ b/packages/realm-server/tests/async-semaphore-test.ts @@ -20,7 +20,7 @@ import { isPrerenderCancellation } from '../prerender/prerender-cancel.ts'; // 4. Edge cases: clamping to 1, no-op resize, resize while empty, // cancelled waiters mixed with grow. -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('AsyncSemaphore basic state', function () { test('reports correct counts at construction', function (assert) { let sem = new AsyncSemaphore(3); diff --git a/packages/realm-server/tests/atomic-endpoints-test.ts b/packages/realm-server/tests/atomic-endpoints-test.ts index 80c8a2fe79..3578311a9a 100644 --- a/packages/realm-server/tests/atomic-endpoints-test.ts +++ b/packages/realm-server/tests/atomic-endpoints-test.ts @@ -95,7 +95,7 @@ async function readIndexSnapshot( }; } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module( 'Realm-specific Endpoints: can make request to post /_atomic', function () { diff --git a/packages/realm-server/tests/auth-client-test.ts b/packages/realm-server/tests/auth-client-test.ts index 01d78e9de3..d010270d8d 100644 --- a/packages/realm-server/tests/auth-client-test.ts +++ b/packages/realm-server/tests/auth-client-test.ts @@ -17,7 +17,7 @@ function createJWT( return jwt.sign(payload, 'secret', { expiresIn }); } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('realm-auth-client', function (assert) { let client: RealmAuthClient; let sessionHandler: (request: Request) => Promise; diff --git a/packages/realm-server/tests/bfm-card-references-test.ts b/packages/realm-server/tests/bfm-card-references-test.ts index 0557049ee5..9be2a7a6be 100644 --- a/packages/realm-server/tests/bfm-card-references-test.ts +++ b/packages/realm-server/tests/bfm-card-references-test.ts @@ -3,7 +3,7 @@ import { basename } from 'path'; import { runSharedTest } from '@cardstack/runtime-common/helpers'; import bfmCardReferencesTests from '@cardstack/runtime-common/tests/bfm-card-references-test'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('cardTypeName', function () { test('cardTypeName extracts type from absolute URL', async function (assert) { await runSharedTest(bfmCardReferencesTests, assert, {}); diff --git a/packages/realm-server/tests/billing-test.ts b/packages/realm-server/tests/billing-test.ts index 2fa53d567e..829984d7f2 100644 --- a/packages/realm-server/tests/billing-test.ts +++ b/packages/realm-server/tests/billing-test.ts @@ -101,7 +101,7 @@ function buildDailyCreditGrantTaskArgs(dbAdapter: PgAdapter): TaskArgs { }; } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('billing', function (hooks) { let dbAdapter: PgAdapter; diff --git a/packages/realm-server/tests/boxel-domain-availability-test.ts b/packages/realm-server/tests/boxel-domain-availability-test.ts index 43313cf298..7810d8d5a1 100644 --- a/packages/realm-server/tests/boxel-domain-availability-test.ts +++ b/packages/realm-server/tests/boxel-domain-availability-test.ts @@ -19,11 +19,12 @@ import type { SuperTest, Test } from 'supertest'; import supertest from 'supertest'; import type { RealmHttpServer as Server } from '../server.ts'; import { dirSync, type DirResult } from 'tmp'; -import { copySync, ensureDirSync } from 'fs-extra'; +import fsExtra from 'fs-extra'; +const { copySync, ensureDirSync } = fsExtra; const testRealmURL = new URL('http://127.0.0.1:0/test/'); -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('boxel domain availability endpoint', function (hooks) { let testRealmServer: Server; let request: SuperTest; diff --git a/packages/realm-server/tests/card-dependencies-endpoint-test.ts b/packages/realm-server/tests/card-dependencies-endpoint-test.ts index f5f3bf439e..3ceda40820 100644 --- a/packages/realm-server/tests/card-dependencies-endpoint-test.ts +++ b/packages/realm-server/tests/card-dependencies-endpoint-test.ts @@ -12,7 +12,7 @@ import { } from './helpers/index.ts'; import '@cardstack/runtime-common/helpers/code-equality-assertion'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('Realm-specific Endpoints | card dependencies requests', function () { let testRealm: Realm; let request: SuperTest; diff --git a/packages/realm-server/tests/card-endpoints-test.ts b/packages/realm-server/tests/card-endpoints-test.ts index 066b4e41b1..6fc45c4856 100644 --- a/packages/realm-server/tests/card-endpoints-test.ts +++ b/packages/realm-server/tests/card-endpoints-test.ts @@ -4,7 +4,8 @@ import supertest from 'supertest'; import { join, basename } from 'path'; import type { RealmHttpServer as Server } from '../server.ts'; import type { DirResult } from 'tmp'; -import { existsSync, readJSONSync, statSync, writeFileSync } from 'fs-extra'; +import fsExtra from 'fs-extra'; +const { existsSync, readJSONSync, statSync, writeFileSync } = fsExtra; import type { Realm, Relationship, @@ -94,7 +95,7 @@ function buildPngChunk(type: string, data: Uint8Array): Uint8Array { return chunk; } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('Realm-specific Endpoints | card URLs', function (hooks) { let realmURL = new URL('http://127.0.0.1:4444/test/'); let testRealmHref = realmURL.href; diff --git a/packages/realm-server/tests/card-source-endpoints-test.ts b/packages/realm-server/tests/card-source-endpoints-test.ts index b5076d0a84..58d65817e8 100644 --- a/packages/realm-server/tests/card-source-endpoints-test.ts +++ b/packages/realm-server/tests/card-source-endpoints-test.ts @@ -3,7 +3,8 @@ import type { Test, SuperTest } from 'supertest'; import { join, basename } from 'path'; import type { RealmHttpServer as Server } from '../server.ts'; import type { DirResult } from 'tmp'; -import { existsSync, readFileSync } from 'fs-extra'; +import fsExtra from 'fs-extra'; +const { existsSync, readFileSync } = fsExtra; import { cardSrc, compiledCard, @@ -30,9 +31,9 @@ import '@cardstack/runtime-common/helpers/code-equality-assertion'; import stripScopedCSSGlimmerAttributes from '@cardstack/runtime-common/helpers/strip-scoped-css-glimmer-attributes'; import { APP_BOXEL_REALM_EVENT_TYPE } from '@cardstack/runtime-common/matrix-constants'; import type { MatrixEvent } from 'https://cardstack.com/base/matrix-event'; -import isEqual from 'lodash/isEqual'; +import { isEqual } from 'lodash-es'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('Realm-specific Endpoints | card source requests', function () { let realmURL = new URL('http://127.0.0.1:4444/test/'); let testRealmHref = realmURL.href; diff --git a/packages/realm-server/tests/claim-boxel-domain-test.ts b/packages/realm-server/tests/claim-boxel-domain-test.ts index 039c21f8ba..f4aa574a61 100644 --- a/packages/realm-server/tests/claim-boxel-domain-test.ts +++ b/packages/realm-server/tests/claim-boxel-domain-test.ts @@ -19,11 +19,12 @@ import type { SuperTest, Test } from 'supertest'; import supertest from 'supertest'; import type { RealmHttpServer as Server } from '../server.ts'; import { dirSync, type DirResult } from 'tmp'; -import { copySync, ensureDirSync } from 'fs-extra'; +import fsExtra from 'fs-extra'; +const { copySync, ensureDirSync } = fsExtra; const testRealmURL = new URL('http://127.0.0.1:0/test/'); -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('claim boxel claimed domain endpoint', function (hooks) { let testRealmServer: Server; let request: SuperTest; diff --git a/packages/realm-server/tests/clamp-serialized-error-test.ts b/packages/realm-server/tests/clamp-serialized-error-test.ts index 3e198696b2..9b923e9342 100644 --- a/packages/realm-server/tests/clamp-serialized-error-test.ts +++ b/packages/realm-server/tests/clamp-serialized-error-test.ts @@ -39,7 +39,7 @@ function isOmittedSentinel(entry: any): boolean { ); } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { test('returns the input unchanged when the doc fits the budget', function (assert) { let input: SerializedError = { message: 'boom', diff --git a/packages/realm-server/tests/codemod-context-search-test.ts b/packages/realm-server/tests/codemod-context-search-test.ts index f770a1e63c..520dc5801e 100644 --- a/packages/realm-server/tests/codemod-context-search-test.ts +++ b/packages/realm-server/tests/codemod-context-search-test.ts @@ -1,7 +1,7 @@ import { module, test } from 'qunit'; import { basename } from 'path'; -import { transformContextSearch } from '../scripts/codemod/context-search/transform'; +import { transformContextSearch } from '../scripts/codemod/context-search/transform.ts'; // A clean, mechanically-transformable usage: the `:response` body is a direct // `{{#each}}` over the result array that renders ``, the query @@ -184,7 +184,7 @@ export class Plain extends GlimmerComponent { } `; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { test('transforms a representative card: renames the component, reshapes the blocks, adds the query getter + import', function (assert) { let { status, output, reasons } = transformContextSearch(TRANSFORMABLE, { filename: 'grid.gts', diff --git a/packages/realm-server/tests/coerce-error-message-test.ts b/packages/realm-server/tests/coerce-error-message-test.ts index 3b7ca26957..80b3e26ea2 100644 --- a/packages/realm-server/tests/coerce-error-message-test.ts +++ b/packages/realm-server/tests/coerce-error-message-test.ts @@ -3,7 +3,7 @@ import { basename } from 'path'; import { runSharedTest } from '@cardstack/runtime-common/helpers'; import coerceErrorMessageTests from '@cardstack/runtime-common/tests/coerce-error-message-test'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('coerceErrorMessage', function () { test('returns the existing non-empty message', async function (assert) { await runSharedTest(coerceErrorMessageTests, assert, {}); diff --git a/packages/realm-server/tests/command-parsing-utils-test.ts b/packages/realm-server/tests/command-parsing-utils-test.ts index 918028be21..74dfb85307 100644 --- a/packages/realm-server/tests/command-parsing-utils-test.ts +++ b/packages/realm-server/tests/command-parsing-utils-test.ts @@ -3,7 +3,7 @@ import { basename } from 'path'; import { runSharedTest } from '@cardstack/runtime-common/helpers'; import commandParsingTests from '@cardstack/runtime-common/tests/command-parsing-utils-test'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('command parsing utils', function () { test('parseBoxelHostCommandSpecifier parses scoped command specifier', async function (assert) { await runSharedTest(commandParsingTests, assert, {}); diff --git a/packages/realm-server/tests/consuming-realm-header-test.ts b/packages/realm-server/tests/consuming-realm-header-test.ts index 250fd3bd8b..728a9fabfa 100644 --- a/packages/realm-server/tests/consuming-realm-header-test.ts +++ b/packages/realm-server/tests/consuming-realm-header-test.ts @@ -3,7 +3,7 @@ import { basename } from 'path'; import { runSharedTest } from '@cardstack/runtime-common/helpers'; import consumingRealmHeaderTests from '@cardstack/runtime-common/tests/consuming-realm-header-test'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('sanitizeConsumingRealmHeader', function () { test('accepts a plain http realm URL', async function (assert) { await runSharedTest(consumingRealmHeaderTests, assert, {}); diff --git a/packages/realm-server/tests/data-plane-write-lock-test.ts b/packages/realm-server/tests/data-plane-write-lock-test.ts index 6c714ce8c0..eb0c3d5d57 100644 --- a/packages/realm-server/tests/data-plane-write-lock-test.ts +++ b/packages/realm-server/tests/data-plane-write-lock-test.ts @@ -22,7 +22,7 @@ import '@cardstack/runtime-common/helpers/code-equality-assertion'; // Postgres advisory lock to serialize critical sections that pre-CS-11125 // raced. Without the lock applied to PATCH and /_atomic, the assertions // below detect the lost update / TOCTOU directly. -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('CS-11125: data-plane write serialization', function () { let realmURL = new URL('http://127.0.0.1:4444/test/'); let testRealm: Realm; diff --git a/packages/realm-server/tests/definition-lookup-test.ts b/packages/realm-server/tests/definition-lookup-test.ts index eae3f1f0d5..23be1d05a6 100644 --- a/packages/realm-server/tests/definition-lookup-test.ts +++ b/packages/realm-server/tests/definition-lookup-test.ts @@ -93,7 +93,7 @@ function buildModuleResponse( }; } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('DefinitionLookup', function (hooks) { let definitionLookup: CachingDefinitionLookup; let realmURL = 'http://127.0.0.1:4450/'; diff --git a/packages/realm-server/tests/delete-boxel-claimed-domain-test.ts b/packages/realm-server/tests/delete-boxel-claimed-domain-test.ts index a870638ab8..4ebb70ed05 100644 --- a/packages/realm-server/tests/delete-boxel-claimed-domain-test.ts +++ b/packages/realm-server/tests/delete-boxel-claimed-domain-test.ts @@ -24,11 +24,12 @@ import type { SuperTest, Test } from 'supertest'; import supertest from 'supertest'; import type { RealmHttpServer as Server } from '../server.ts'; import { dirSync, type DirResult } from 'tmp'; -import { copySync, ensureDirSync } from 'fs-extra'; +import fsExtra from 'fs-extra'; +const { copySync, ensureDirSync } = fsExtra; const testRealmURL = new URL('http://127.0.0.1:0/test/'); -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('delete boxel claimed domain endpoint', function (hooks) { let testRealmServer: Server; let request: SuperTest; diff --git a/packages/realm-server/tests/eq-containment-integration-test.ts b/packages/realm-server/tests/eq-containment-integration-test.ts index 02b7767b61..38eb22b254 100644 --- a/packages/realm-server/tests/eq-containment-integration-test.ts +++ b/packages/realm-server/tests/eq-containment-integration-test.ts @@ -294,7 +294,7 @@ async function seedPolicy( ]); } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('eq containment (Postgres integration)', function (hooks) { let dbAdapter: PgAdapter; let engine: IndexQueryEngine; diff --git a/packages/realm-server/tests/fallback-models-test.ts b/packages/realm-server/tests/fallback-models-test.ts index 7e2158dce7..36d37282e3 100644 --- a/packages/realm-server/tests/fallback-models-test.ts +++ b/packages/realm-server/tests/fallback-models-test.ts @@ -3,7 +3,7 @@ import { basename } from 'path'; import { runSharedTest } from '@cardstack/runtime-common/helpers'; import fallbackModelsTests from '@cardstack/runtime-common/tests/fallback-models-test'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('DEFAULT_FALLBACK_MODELS', function () { test('ships at least one curated model', async function (assert) { await runSharedTest(fallbackModelsTests, assert, {}); diff --git a/packages/realm-server/tests/file-watcher-events-test.ts b/packages/realm-server/tests/file-watcher-events-test.ts index 59dc4687ab..bf6ffc94fb 100644 --- a/packages/realm-server/tests/file-watcher-events-test.ts +++ b/packages/realm-server/tests/file-watcher-events-test.ts @@ -3,7 +3,8 @@ import type { Test, SuperTest } from 'supertest'; import { join, basename } from 'path'; import type { RealmHttpServer as Server } from '../server.ts'; import type { DirResult } from 'tmp'; -import { removeSync, writeJSONSync, writeFileSync } from 'fs-extra'; +import fsExtra from 'fs-extra'; +const { removeSync, writeJSONSync, writeFileSync } = fsExtra; import type { Realm } from '@cardstack/runtime-common'; import { rri } from '@cardstack/runtime-common'; import { @@ -20,7 +21,7 @@ import type { UpdateRealmEventContent, } from 'https://cardstack.com/base/matrix-event'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('file watcher realm events', function (hooks) { let realmURL = new URL('http://127.0.0.1:4444/test/'); let testRealm: Realm; diff --git a/packages/realm-server/tests/finalize-child-fatal-failure-test.ts b/packages/realm-server/tests/finalize-child-fatal-failure-test.ts index ee1d892916..7f562c02be 100644 --- a/packages/realm-server/tests/finalize-child-fatal-failure-test.ts +++ b/packages/realm-server/tests/finalize-child-fatal-failure-test.ts @@ -47,7 +47,7 @@ async function fetchReservation( return rows[0]; } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('finalizeChildReservationAsFailure', function (hooks) { let adapter: PgAdapter; diff --git a/packages/realm-server/tests/finalize-orphan-reservations-test.ts b/packages/realm-server/tests/finalize-orphan-reservations-test.ts index 7b70a0c937..e189173506 100644 --- a/packages/realm-server/tests/finalize-orphan-reservations-test.ts +++ b/packages/realm-server/tests/finalize-orphan-reservations-test.ts @@ -57,7 +57,7 @@ async function fetchReservation( return rows[0]; } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('finalizeOrphanedReservations', function (hooks) { let adapter: PgAdapter; diff --git a/packages/realm-server/tests/full-index-on-startup-test.ts b/packages/realm-server/tests/full-index-on-startup-test.ts index 70c958a26d..278144d061 100644 --- a/packages/realm-server/tests/full-index-on-startup-test.ts +++ b/packages/realm-server/tests/full-index-on-startup-test.ts @@ -2,7 +2,7 @@ import { module, test } from 'qunit'; import { basename } from 'path'; import { resolveFullIndexOnStartup } from '../lib/full-index-on-startup.ts'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('default behavior (env var unset)', function () { test('bootstrap realms full-index on startup', function (assert) { assert.true(resolveFullIndexOnStartup('bootstrap', undefined)); diff --git a/packages/realm-server/tests/full-reindex-test.ts b/packages/realm-server/tests/full-reindex-test.ts index 09b1d7b62f..2c62eba13e 100644 --- a/packages/realm-server/tests/full-reindex-test.ts +++ b/packages/realm-server/tests/full-reindex-test.ts @@ -18,7 +18,7 @@ import { import { upsertPublishedRealmInRegistry } from '../lib/realm-registry-writes.ts'; import { setupDB } from './helpers/index.ts'; -module(basename(__filename), function (hooks) { +module(basename(import.meta.filename), function (hooks) { let dbAdapter: PgAdapter; let queuePublisher: QueuePublisher; diff --git a/packages/realm-server/tests/get-boxel-claimed-domain-test.ts b/packages/realm-server/tests/get-boxel-claimed-domain-test.ts index 7b9128767c..87b0c88b43 100644 --- a/packages/realm-server/tests/get-boxel-claimed-domain-test.ts +++ b/packages/realm-server/tests/get-boxel-claimed-domain-test.ts @@ -19,11 +19,12 @@ import type { SuperTest, Test } from 'supertest'; import supertest from 'supertest'; import type { RealmHttpServer as Server } from '../server.ts'; import { dirSync, type DirResult } from 'tmp'; -import { copySync, ensureDirSync } from 'fs-extra'; +import fsExtra from 'fs-extra'; +const { copySync, ensureDirSync } = fsExtra; const testRealmURL = new URL('http://127.0.0.1:0/test/'); -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('get boxel claimed domain endpoint', function (hooks) { let testRealmServer: Server; let request: SuperTest; diff --git a/packages/realm-server/tests/helpers/index.ts b/packages/realm-server/tests/helpers/index.ts index 27bdfca4d2..ce394a9727 100644 --- a/packages/realm-server/tests/helpers/index.ts +++ b/packages/realm-server/tests/helpers/index.ts @@ -1,11 +1,5 @@ -import { - writeFileSync, - writeJSONSync, - readdirSync, - statSync, - ensureDirSync, - copySync, -} from 'fs-extra'; +import fsExtra from 'fs-extra'; +const { writeFileSync, writeJSONSync, readdirSync, statSync, ensureDirSync, copySync } = fsExtra; import { NodeAdapter } from '../../node-realm.ts'; import { dirname, join } from 'path'; import { createHash } from 'crypto'; @@ -1935,7 +1929,7 @@ function realmEventIsIndex( export type RealmFixtureName = 'blank' | 'simple' | 'realistic'; export function fixtureDir(name: RealmFixtureName): string { - return join(__dirname, '..', 'fixtures', name); + return join(import.meta.dirname, '..', 'fixtures', name); } type InternalPermissionedRealmSetupOptions = { diff --git a/packages/realm-server/tests/host-routing-validation-test.ts b/packages/realm-server/tests/host-routing-validation-test.ts index 7564beaba3..d29aac4ed4 100644 --- a/packages/realm-server/tests/host-routing-validation-test.ts +++ b/packages/realm-server/tests/host-routing-validation-test.ts @@ -3,7 +3,7 @@ import { basename } from 'path'; import { runSharedTest } from '@cardstack/runtime-common/helpers'; import hostRoutingValidationTests from '@cardstack/runtime-common/tests/host-routing-validation-test'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('validateRoutingPath', function () { test('validateRoutingPath: no warning for empty or whitespace paths', async function (assert) { await runSharedTest(hostRoutingValidationTests, assert, {}); diff --git a/packages/realm-server/tests/http2-keepalive-test.ts b/packages/realm-server/tests/http2-keepalive-test.ts index 96833f4062..ec027fcc00 100644 --- a/packages/realm-server/tests/http2-keepalive-test.ts +++ b/packages/realm-server/tests/http2-keepalive-test.ts @@ -4,7 +4,7 @@ import { EventEmitter } from 'events'; import type http2 from 'http2'; import { logger } from '@cardstack/runtime-common'; -import { startSessionKeepalive } from '../server'; +import { startSessionKeepalive } from '../server.ts'; // Unit coverage for the HTTP/2 PING keepalive that tears down wedged sessions // so a hung browser fetch rejects (and retries) instead of hanging until a @@ -103,7 +103,7 @@ function wait(ms: number) { return new Promise((resolve) => setTimeout(resolve, ms)); } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { test('a responsive session is pinged and never torn down', async function (assert) { let fake = new FakeSession(); let stopKeepalive = startSessionKeepalive(asSession(fake), log, FAST); diff --git a/packages/realm-server/tests/indexing-event-sink-test.ts b/packages/realm-server/tests/indexing-event-sink-test.ts index 3727b007df..0879533e10 100644 --- a/packages/realm-server/tests/indexing-event-sink-test.ts +++ b/packages/realm-server/tests/indexing-event-sink-test.ts @@ -44,7 +44,7 @@ function sleep(ms: number): Promise { return new Promise((r) => setTimeout(r, ms)); } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { test('tracks active indexing from start through file visits to finish', function (assert) { let sink = new IndexingEventSink(); diff --git a/packages/realm-server/tests/indexing-test.ts b/packages/realm-server/tests/indexing-test.ts index fee2300802..297f3fe4a5 100644 --- a/packages/realm-server/tests/indexing-test.ts +++ b/packages/realm-server/tests/indexing-test.ts @@ -459,7 +459,7 @@ function makeTestRealmFileSystem(): Record< }; } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('indexing (read only)', function (hooks) { let realm: Realm; diff --git a/packages/realm-server/tests/is-json-content-type-test.ts b/packages/realm-server/tests/is-json-content-type-test.ts index b6d696325c..33212fa566 100644 --- a/packages/realm-server/tests/is-json-content-type-test.ts +++ b/packages/realm-server/tests/is-json-content-type-test.ts @@ -2,7 +2,7 @@ import { module, test } from 'qunit'; import { basename } from 'path'; import { isJsonContentType } from '@cardstack/runtime-common'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { test('accepts application/json and JSON-suffix media types', function (assert) { assert.true(isJsonContentType('application/json')); assert.true(isJsonContentType('text/json')); diff --git a/packages/realm-server/tests/job-scoped-search-cache-test.ts b/packages/realm-server/tests/job-scoped-search-cache-test.ts index 693350c950..9636d96561 100644 --- a/packages/realm-server/tests/job-scoped-search-cache-test.ts +++ b/packages/realm-server/tests/job-scoped-search-cache-test.ts @@ -30,7 +30,7 @@ function makeDoc(label: string): string { ); } -module(basename(__filename), function (hooks) { +module(basename(import.meta.filename), function (hooks) { let dbAdapter: PgAdapter; setupDB(hooks, { diff --git a/packages/realm-server/tests/jobs-finished-listener-test.ts b/packages/realm-server/tests/jobs-finished-listener-test.ts index dc0a6f2778..c1cd0bd4c1 100644 --- a/packages/realm-server/tests/jobs-finished-listener-test.ts +++ b/packages/realm-server/tests/jobs-finished-listener-test.ts @@ -50,7 +50,7 @@ function waitFor( }); } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('JobsFinishedListener (sweep dispatch)', function () { test('clears every cached key whose job has finalized', async function (assert) { let cache = new FakeSearchCache(['5.1', '9.1']); diff --git a/packages/realm-server/tests/lazy-mount-test.ts b/packages/realm-server/tests/lazy-mount-test.ts index c160dfc149..ca378e0a78 100644 --- a/packages/realm-server/tests/lazy-mount-test.ts +++ b/packages/realm-server/tests/lazy-mount-test.ts @@ -91,7 +91,7 @@ function buildServer(opts: { }); } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('Phase 3 lazy mount', function (hooks) { let dbAdapter: PgAdapter; let mountCalls: string[]; diff --git a/packages/realm-server/tests/listener-dispatcher-test.ts b/packages/realm-server/tests/listener-dispatcher-test.ts index 2f0a70472e..ec6886a389 100644 --- a/packages/realm-server/tests/listener-dispatcher-test.ts +++ b/packages/realm-server/tests/listener-dispatcher-test.ts @@ -258,7 +258,7 @@ function withEnv( } } -module(basename(__filename), function (hooks) { +module(basename(import.meta.filename), function (hooks) { hooks.before(function () { tmpCertDir = mkdtempSync(join(tmpdir(), 'realm-listener-test-')); let pair = makeCert(tmpCertDir); diff --git a/packages/realm-server/tests/load-links-batching-test.ts b/packages/realm-server/tests/load-links-batching-test.ts index f7b5e8d7f2..860cce9fbf 100644 --- a/packages/realm-server/tests/load-links-batching-test.ts +++ b/packages/realm-server/tests/load-links-batching-test.ts @@ -82,7 +82,7 @@ function buildFileSystem(): Record { // cards each linking to 5 targets, the original implementation would have // fired 250 sequential `WHERE i.url = $1` lookups. The new BFS path issues // one batched `WHERE i.url IN (...)` per recursion depth. -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('loadLinks batching', function (hooks) { let realm: Realm; diff --git a/packages/realm-server/tests/markdown-fallback-server-isolation-test.ts b/packages/realm-server/tests/markdown-fallback-server-isolation-test.ts index e3e0cb21fd..0f01f8de27 100644 --- a/packages/realm-server/tests/markdown-fallback-server-isolation-test.ts +++ b/packages/realm-server/tests/markdown-fallback-server-isolation-test.ts @@ -16,7 +16,7 @@ import * as path from 'path'; // If a future change accidentally pulls turndown into the server graph, this // test fails — even before any networked behavior is exercised. -const REPO_ROOT = path.resolve(__dirname, '..', '..', '..'); +const REPO_ROOT = path.resolve(import.meta.dirname, '..', '..', '..'); // Packages whose source code runs in the realm-server Node.js process. If a // new server-side workspace is added that runs in Node, list it here too. @@ -86,7 +86,7 @@ function findForbiddenImports(file: string): string | null { return null; } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { test('realm-server package.json does not declare turndown deps', function (assert) { let pkg = JSON.parse( fs.readFileSync( diff --git a/packages/realm-server/tests/matches-filter-integration-test.ts b/packages/realm-server/tests/matches-filter-integration-test.ts index da17ef685a..6429e58f57 100644 --- a/packages/realm-server/tests/matches-filter-integration-test.ts +++ b/packages/realm-server/tests/matches-filter-integration-test.ts @@ -86,7 +86,7 @@ async function countBoxelIndexRows(dbAdapter: PgAdapter): Promise { return rows[0].total; } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('MatchesFilter (Postgres integration)', function (hooks) { let dbAdapter: PgAdapter; let engine: IndexQueryEngine; diff --git a/packages/realm-server/tests/module-cache-coordination-test.ts b/packages/realm-server/tests/module-cache-coordination-test.ts index d6783536aa..de80ec23d5 100644 --- a/packages/realm-server/tests/module-cache-coordination-test.ts +++ b/packages/realm-server/tests/module-cache-coordination-test.ts @@ -152,7 +152,7 @@ function makeLookup( return lookup; } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('ModuleCacheCoordinator unit', function (hooks) { let dbAdapter: PgAdapter; setupDB(hooks, { diff --git a/packages/realm-server/tests/module-cache-invalidation-listener-test.ts b/packages/realm-server/tests/module-cache-invalidation-listener-test.ts index 64bd536fc0..6360f82749 100644 --- a/packages/realm-server/tests/module-cache-invalidation-listener-test.ts +++ b/packages/realm-server/tests/module-cache-invalidation-listener-test.ts @@ -118,7 +118,7 @@ function waitFor( }); } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('parseModuleCacheInvalidationPayload', function () { test('parses a module payload carrying a single URL', function (assert) { assert.deepEqual( diff --git a/packages/realm-server/tests/module-cache-race-test.ts b/packages/realm-server/tests/module-cache-race-test.ts index 2f07a17105..ec020e1b06 100644 --- a/packages/realm-server/tests/module-cache-race-test.ts +++ b/packages/realm-server/tests/module-cache-race-test.ts @@ -1,6 +1,7 @@ import { module, test } from 'qunit'; import { basename, join } from 'path'; -import { ensureDirSync, writeFileSync, writeJSONSync } from 'fs-extra'; +import fsExtra from 'fs-extra'; +const { ensureDirSync, writeFileSync, writeJSONSync } = fsExtra; import sinon from 'sinon'; import { dirSync } from 'tmp'; import type { SuperTest, Test } from 'supertest'; @@ -49,7 +50,7 @@ import { // transforms + scoped-css), so the invalidate lands inside the race // window. The observable assertion is on the subsequent request's // `x-boxel-cache` header — a miss proves A's cache write was discarded. -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module( 'Realm.#transpiledModuleCache invalidate-during-transpile race', function (hooks) { diff --git a/packages/realm-server/tests/module-syntax-test.ts b/packages/realm-server/tests/module-syntax-test.ts index 3bed967552..b584646921 100644 --- a/packages/realm-server/tests/module-syntax-test.ts +++ b/packages/realm-server/tests/module-syntax-test.ts @@ -22,7 +22,7 @@ const virtualNetwork = new VirtualNetwork(); import { basename } from 'path'; import '@cardstack/runtime-common/helpers/code-equality-assertion'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('module-syntax', function () { function addField(src: string, addFieldAtIndex?: number) { let mod = new ModuleSyntax( diff --git a/packages/realm-server/tests/node-realm-test.ts b/packages/realm-server/tests/node-realm-test.ts index 98cbb6e41f..e4b569769f 100644 --- a/packages/realm-server/tests/node-realm-test.ts +++ b/packages/realm-server/tests/node-realm-test.ts @@ -11,7 +11,7 @@ import type { RealmEventContent } from 'https://cardstack.com/base/matrix-event' import { NodeAdapter } from '../node-realm.ts'; import { insertUser, setupDB } from './helpers/index.ts'; -module(basename(__filename), function (hooks) { +module(basename(import.meta.filename), function (hooks) { let dbAdapter: PgAdapter; const realmURL = new URL('http://127.0.0.1:4444/test/'); const staleRoomId = '!room-alice:localhost'; diff --git a/packages/realm-server/tests/normalize-realm-meta-value-test.ts b/packages/realm-server/tests/normalize-realm-meta-value-test.ts index d68baa8d7e..4d8471598f 100644 --- a/packages/realm-server/tests/normalize-realm-meta-value-test.ts +++ b/packages/realm-server/tests/normalize-realm-meta-value-test.ts @@ -3,7 +3,7 @@ import { basename } from 'path'; import { runSharedTest } from '@cardstack/runtime-common/helpers'; import normalizeRealmMetaValueTests from '@cardstack/runtime-common/tests/normalize-realm-meta-value-test'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('normalizeRealmMetaValue', function () { test('undefined value normalizes to empty groups', async function (assert) { await runSharedTest(normalizeRealmMetaValueTests, assert, {}); diff --git a/packages/realm-server/tests/openrouter-passthrough-test.ts b/packages/realm-server/tests/openrouter-passthrough-test.ts index e63de0a51e..0ac02d8bbe 100644 --- a/packages/realm-server/tests/openrouter-passthrough-test.ts +++ b/packages/realm-server/tests/openrouter-passthrough-test.ts @@ -5,7 +5,8 @@ import supertest from 'supertest'; import { basename, join } from 'path'; import type { RealmHttpServer as Server } from '../server.ts'; import { dirSync, type DirResult } from 'tmp'; -import { copySync, ensureDirSync } from 'fs-extra'; +import fsExtra from 'fs-extra'; +const { copySync, ensureDirSync } = fsExtra; import { setupDB, runTestRealmServer, @@ -25,7 +26,7 @@ import { } from '@cardstack/billing/billing-queries'; import { AllowedProxyDestinations } from '../lib/allowed-proxy-destinations.ts'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module( 'Realm-specific Endpoints | _openrouter/chat/completions', function (hooks) { diff --git a/packages/realm-server/tests/package-shim-handler-test.ts b/packages/realm-server/tests/package-shim-handler-test.ts index 03c145f3e4..5697443f6e 100644 --- a/packages/realm-server/tests/package-shim-handler-test.ts +++ b/packages/realm-server/tests/package-shim-handler-test.ts @@ -3,7 +3,7 @@ import { basename } from 'path'; import { runSharedTest } from '@cardstack/runtime-common/helpers'; import packageShimHandlerTests from '@cardstack/runtime-common/tests/package-shim-handler-test'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('Strict named-export check (CS-10860 follow-up)', function () { test('wrapWithStrictNamespace returns existing exports unchanged', async function (assert) { await runSharedTest(packageShimHandlerTests, assert, {}); diff --git a/packages/realm-server/tests/page-pool-cert-verifier-retry-test.ts b/packages/realm-server/tests/page-pool-cert-verifier-retry-test.ts index 8c84510f3c..1b8b20aef6 100644 --- a/packages/realm-server/tests/page-pool-cert-verifier-retry-test.ts +++ b/packages/realm-server/tests/page-pool-cert-verifier-retry-test.ts @@ -117,7 +117,7 @@ function makeBrowserStub(opts: BrowserStubOptions) { return browserManager; } -module(basename(__filename), function (hooks) { +module(basename(import.meta.filename), function (hooks) { let pools: PagePool[] = []; hooks.afterEach(async () => { diff --git a/packages/realm-server/tests/page-pool-eviction-recovery-test.ts b/packages/realm-server/tests/page-pool-eviction-recovery-test.ts index bf103c0230..7cdc86c87f 100644 --- a/packages/realm-server/tests/page-pool-eviction-recovery-test.ts +++ b/packages/realm-server/tests/page-pool-eviction-recovery-test.ts @@ -80,7 +80,7 @@ function makeBrowserStub(control: CloseControl) { }; } -module(basename(__filename), function (hooks) { +module(basename(import.meta.filename), function (hooks) { let pools: PagePool[] = []; hooks.afterEach(async () => { diff --git a/packages/realm-server/tests/page-pool-expansion-test.ts b/packages/realm-server/tests/page-pool-expansion-test.ts index 159ddce2b5..d32786e3f1 100644 --- a/packages/realm-server/tests/page-pool-expansion-test.ts +++ b/packages/realm-server/tests/page-pool-expansion-test.ts @@ -105,7 +105,7 @@ async function withEnv( } } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('PagePool dynamic-pool configuration', function (hooks) { let teardown: Array<() => Promise> = []; diff --git a/packages/realm-server/tests/page-pool-priority-test.ts b/packages/realm-server/tests/page-pool-priority-test.ts index 0921dedc0c..0532d6f5cb 100644 --- a/packages/realm-server/tests/page-pool-priority-test.ts +++ b/packages/realm-server/tests/page-pool-priority-test.ts @@ -16,7 +16,7 @@ import { TabQueue } from '../prerender/page-pool.ts'; // arriving while a system-priority full reindex has saturated the // queue should NOT wait behind every queued background entry. -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('AsyncSemaphore priority dequeue', function () { test('higher priority jumps the queue ahead of lower-priority pending work', async function (assert) { let sem = new AsyncSemaphore(1); diff --git a/packages/realm-server/tests/page-pool-standby-refill-test.ts b/packages/realm-server/tests/page-pool-standby-refill-test.ts index 2a6bbf066e..01d4aae8eb 100644 --- a/packages/realm-server/tests/page-pool-standby-refill-test.ts +++ b/packages/realm-server/tests/page-pool-standby-refill-test.ts @@ -90,7 +90,7 @@ function makeManualGate() { }; } -module(basename(__filename), function (hooks) { +module(basename(import.meta.filename), function (hooks) { let pools: PagePool[] = []; hooks.afterEach(async () => { diff --git a/packages/realm-server/tests/permissions/permission-checker-test.ts b/packages/realm-server/tests/permissions/permission-checker-test.ts index 5b2c6cba20..b926759ab3 100644 --- a/packages/realm-server/tests/permissions/permission-checker-test.ts +++ b/packages/realm-server/tests/permissions/permission-checker-test.ts @@ -10,7 +10,7 @@ let mockMatrixClient = { }, } as MatrixClient; -module(`permissions/${basename(__filename)}`, function () { +module(`permissions/${basename(import.meta.filename)}`, function () { module('world-readable realm', function () { let permissionsChecker = new RealmPermissionChecker( { diff --git a/packages/realm-server/tests/pg-adapter-subscribe-test.ts b/packages/realm-server/tests/pg-adapter-subscribe-test.ts index 555ea858f8..2cca73278e 100644 --- a/packages/realm-server/tests/pg-adapter-subscribe-test.ts +++ b/packages/realm-server/tests/pg-adapter-subscribe-test.ts @@ -48,7 +48,7 @@ async function notify( ]); } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('PgAdapter.subscribe', function (hooks) { let dbAdapter: PgAdapter; diff --git a/packages/realm-server/tests/prerender-affinity-activity-test.ts b/packages/realm-server/tests/prerender-affinity-activity-test.ts index 275c643e49..7b644963a7 100644 --- a/packages/realm-server/tests/prerender-affinity-activity-test.ts +++ b/packages/realm-server/tests/prerender-affinity-activity-test.ts @@ -11,7 +11,7 @@ import { AffinityActivityTracker } from '../prerender/affinity-activity.ts'; // `computeBatchClearCacheGate` for CS-10758 — we test the extracted // helper directly rather than spinning up a full Prerenderer. -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { const REALM_A = 'realm:http://localhost:4201/user/alpha/'; const REALM_B = 'realm:http://localhost:4201/user/beta/'; diff --git a/packages/realm-server/tests/prerender-batch-ownership-test.ts b/packages/realm-server/tests/prerender-batch-ownership-test.ts index 35a4bcf224..2166da1699 100644 --- a/packages/realm-server/tests/prerender-batch-ownership-test.ts +++ b/packages/realm-server/tests/prerender-batch-ownership-test.ts @@ -29,7 +29,7 @@ function args( }; } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module( 'computeBatchClearCacheGate — clearCache batch ownership (CS-10758 step 3)', function () { diff --git a/packages/realm-server/tests/prerender-cancellation-test.ts b/packages/realm-server/tests/prerender-cancellation-test.ts index a6e5bf7dea..6a009efde1 100644 --- a/packages/realm-server/tests/prerender-cancellation-test.ts +++ b/packages/realm-server/tests/prerender-cancellation-test.ts @@ -24,7 +24,7 @@ import { AsyncSemaphore } from '../prerender/async-semaphore.ts'; // Holding these invariants down means the manager-level client-abort // tests don't have to re-verify them end to end. -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('PrerenderCancelledError shape', function () { test('defaults to queued state with no reason', function (assert) { let err = new PrerenderCancelledError(); diff --git a/packages/realm-server/tests/prerender-deadlock-test.ts b/packages/realm-server/tests/prerender-deadlock-test.ts index ad73ea0956..1f433e9377 100644 --- a/packages/realm-server/tests/prerender-deadlock-test.ts +++ b/packages/realm-server/tests/prerender-deadlock-test.ts @@ -140,7 +140,7 @@ function makeStubPagePool(opts: { return { pool, stub }; } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('CS-10976: deadlock-safety reservation', function (hooks) { let prevTabMax: string | undefined; diff --git a/packages/realm-server/tests/prerender-diagnostics-persistence-test.ts b/packages/realm-server/tests/prerender-diagnostics-persistence-test.ts index dacd3ac681..fcf32e5b95 100644 --- a/packages/realm-server/tests/prerender-diagnostics-persistence-test.ts +++ b/packages/realm-server/tests/prerender-diagnostics-persistence-test.ts @@ -80,7 +80,7 @@ function buildFakeSuccessVisitResponse(): FakeVisitResponse { }; } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('render diagnostics persistence — consolidated channel', function () { test('Prerenderer.decorateRenderErrorsWithTimings lifts outer RenderError.diagnostics onto response.meta and leaves the inner SerializedError clean', function (assert) { let response = buildFakeVisitResponseWithTimeoutError(); diff --git a/packages/realm-server/tests/prerender-manager-test.ts b/packages/realm-server/tests/prerender-manager-test.ts index 02a20af85f..ac10b64ed0 100644 --- a/packages/realm-server/tests/prerender-manager-test.ts +++ b/packages/realm-server/tests/prerender-manager-test.ts @@ -17,7 +17,7 @@ import { toAffinityKey } from '../prerender/affinity.ts'; import { Deferred } from '@cardstack/runtime-common'; import { testCreatePrerenderAuth } from './helpers/index.ts'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('Prerender manager', function (hooks) { let previousMultiplex: string | undefined; let previousHeartbeatTimeout: string | undefined; diff --git a/packages/realm-server/tests/prerender-proxy-test.ts b/packages/realm-server/tests/prerender-proxy-test.ts index 7c8671603e..a94ba62865 100644 --- a/packages/realm-server/tests/prerender-proxy-test.ts +++ b/packages/realm-server/tests/prerender-proxy-test.ts @@ -13,7 +13,7 @@ import { realmSecretSeed } from './helpers/index.ts'; import { buildCreatePrerenderAuth } from '../prerender/auth.ts'; import { verifyJWT } from '../jwt.ts'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('prerender proxy', function () { let createPrerenderAuth = buildCreatePrerenderAuth(realmSecretSeed); diff --git a/packages/realm-server/tests/prerender-server-test.ts b/packages/realm-server/tests/prerender-server-test.ts index 6f6e628692..c9c3a75627 100644 --- a/packages/realm-server/tests/prerender-server-test.ts +++ b/packages/realm-server/tests/prerender-server-test.ts @@ -23,7 +23,7 @@ import { import { toAffinityKey } from '../prerender/affinity.ts'; import { Deferred } from '@cardstack/runtime-common'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('Prerender server', function (hooks) { let request: SuperTest; let prerenderer: Prerenderer; diff --git a/packages/realm-server/tests/prerendering-test.ts b/packages/realm-server/tests/prerendering-test.ts index 5485e775c1..281a59e60f 100644 --- a/packages/realm-server/tests/prerendering-test.ts +++ b/packages/realm-server/tests/prerendering-test.ts @@ -226,7 +226,7 @@ function makeStubPagePool(opts: StubPagePoolOptions) { return { pool, contextsCreated, contextsClosed }; } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('prerender - mutating tests', function (hooks) { let realmURL = 'http://127.0.0.1:4450/test/'; let prerenderServerURL = new URL(realmURL).origin; diff --git a/packages/realm-server/tests/publish-unpublish-realm-test.ts b/packages/realm-server/tests/publish-unpublish-realm-test.ts index 4a058a1d23..454da5e6ee 100644 --- a/packages/realm-server/tests/publish-unpublish-realm-test.ts +++ b/packages/realm-server/tests/publish-unpublish-realm-test.ts @@ -2,15 +2,8 @@ import { module, test } from 'qunit'; import type { SuperTest, Test } from 'supertest'; import supertest from 'supertest'; import { v4 as uuidv4 } from 'uuid'; -import { - existsSync, - ensureDirSync, - copySync, - pathExistsSync, - readJsonSync, - writeJsonSync, - removeSync, -} from 'fs-extra'; +import fsExtra from 'fs-extra'; +const { existsSync, ensureDirSync, copySync, pathExistsSync, readJsonSync, writeJsonSync, removeSync } = fsExtra; import { basename, join } from 'path'; import type { RealmHttpServer as Server } from '../server.ts'; import { dirSync, type DirResult } from 'tmp'; @@ -37,7 +30,7 @@ import { createJWT as createRealmServerJWT } from '../utils/jwt.ts'; const testRealm2URL = 'http://127.0.0.1:4445/test/'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('publish and unpublish realm tests', function (hooks) { let testRealmHttpServer: Server; let testRealm: Realm; diff --git a/packages/realm-server/tests/queries-test.ts b/packages/realm-server/tests/queries-test.ts index d9f2777f59..0b40da1935 100644 --- a/packages/realm-server/tests/queries-test.ts +++ b/packages/realm-server/tests/queries-test.ts @@ -12,7 +12,7 @@ import { import { upsertPublishedRealmInRegistry } from '../lib/realm-registry-writes.ts'; import { setupDB } from './helpers/index.ts'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('fetchUserPermissions', function (hooks) { let dbAdapter: PgAdapter; diff --git a/packages/realm-server/tests/query-matches-filter-test.ts b/packages/realm-server/tests/query-matches-filter-test.ts index 4cdff7912f..8cf0edbef7 100644 --- a/packages/realm-server/tests/query-matches-filter-test.ts +++ b/packages/realm-server/tests/query-matches-filter-test.ts @@ -3,7 +3,7 @@ import { basename } from 'path'; import { runSharedTest } from '@cardstack/runtime-common/helpers'; import queryMatchesFilterTests from '@cardstack/runtime-common/tests/query-matches-filter-test'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('MatchesFilter', function () { test('isMatchesFilter returns true for a MatchesFilter', async function (assert) { await runSharedTest(queryMatchesFilterTests, assert, {}); diff --git a/packages/realm-server/tests/queue-test.ts b/packages/realm-server/tests/queue-test.ts index a0e66f6056..0c8293a482 100644 --- a/packages/realm-server/tests/queue-test.ts +++ b/packages/realm-server/tests/queue-test.ts @@ -33,7 +33,7 @@ import { import queueTests from '@cardstack/runtime-common/tests/queue-test'; import { basename } from 'path'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('queue', function (hooks) { let publisher: QueuePublisher; let runner: QueueRunner; diff --git a/packages/realm-server/tests/realm-advisory-locks-test.ts b/packages/realm-server/tests/realm-advisory-locks-test.ts index 9b7dd207d7..202a2f7c03 100644 --- a/packages/realm-server/tests/realm-advisory-locks-test.ts +++ b/packages/realm-server/tests/realm-advisory-locks-test.ts @@ -19,7 +19,7 @@ function timeline(events: string[], startedAt: number, eventTimes: number[]) { .join(','); } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('hashRealmUrlForAdvisoryLock', function () { test('is deterministic', function (assert) { const url = 'http://localhost:4201/luke/my-realm/'; diff --git a/packages/realm-server/tests/realm-auth-test.ts b/packages/realm-server/tests/realm-auth-test.ts index cd0a3073b6..7b12c1657e 100644 --- a/packages/realm-server/tests/realm-auth-test.ts +++ b/packages/realm-server/tests/realm-auth-test.ts @@ -16,7 +16,7 @@ import { createJWT as createRealmServerJWT } from '../utils/jwt.ts'; import { insertSourceRealmInRegistry } from '../lib/realm-registry-writes.ts'; import type { RealmServer } from '../server.ts'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('realm auth handler', function (hooks) { let dbAdapter: PgAdapter; let request: SuperTest; diff --git a/packages/realm-server/tests/realm-cleanup-transaction-test.ts b/packages/realm-server/tests/realm-cleanup-transaction-test.ts index 6bbca75e90..c6e22c66d2 100644 --- a/packages/realm-server/tests/realm-cleanup-transaction-test.ts +++ b/packages/realm-server/tests/realm-cleanup-transaction-test.ts @@ -19,7 +19,7 @@ import { // registry-row delete AND the permissions delete. Pre-CS-10898 the handler // ran each helper through the shared dbAdapter, so each DELETE committed in // its own auto-tx and a mid-cleanup throw left the realm half-deleted. -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('CS-10898: realm cleanup transactionality', function (hooks) { let dbAdapter: PgAdapter; setupDB(hooks, { diff --git a/packages/realm-server/tests/realm-endpoints-test.ts b/packages/realm-server/tests/realm-endpoints-test.ts index 47e208e351..a7336df01a 100644 --- a/packages/realm-server/tests/realm-endpoints-test.ts +++ b/packages/realm-server/tests/realm-endpoints-test.ts @@ -4,15 +4,8 @@ import supertest from 'supertest'; import { join, resolve, basename } from 'path'; import type { RealmHttpServer as Server } from '../server.ts'; import { dirSync, type DirResult } from 'tmp'; -import { - copySync, - ensureDirSync, - existsSync, - readFileSync, - readJSONSync, - removeSync, - writeFileSync, -} from 'fs-extra'; +import fsExtra from 'fs-extra'; +const { copySync, ensureDirSync, existsSync, readFileSync, readJSONSync, removeSync, writeFileSync } = fsExtra; import { utimesSync } from 'fs'; import type { Realm } from '@cardstack/runtime-common'; import { @@ -72,7 +65,7 @@ import type { const testRealm2URL = new URL('http://127.0.0.1:4445/test/'); -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('Realm-specific Endpoints', function (hooks) { let realmURL = new URL('http://127.0.0.1:4444/test/'); let testRealmHref = realmURL.href; @@ -2008,7 +2001,7 @@ module(basename(__filename), function () { let testRealm: Realm; let virtualNetwork = createVirtualNetwork(); - const basePath = resolve(join(__dirname, '..', '..', 'base')); + const basePath = resolve(join(import.meta.dirname, '..', '..', 'base')); const demoFileSystem: Record = { 'realm.json': readJSONSync(join(fixtureDir('realistic'), 'realm.json')), 'person.gts': readFileSync( diff --git a/packages/realm-server/tests/realm-endpoints/cancel-indexing-job-test.ts b/packages/realm-server/tests/realm-endpoints/cancel-indexing-job-test.ts index d79ecf0513..e08edee8ca 100644 --- a/packages/realm-server/tests/realm-endpoints/cancel-indexing-job-test.ts +++ b/packages/realm-server/tests/realm-endpoints/cancel-indexing-job-test.ts @@ -15,7 +15,7 @@ import { } from '../helpers/index.ts'; import type { PgAdapter as TestPgAdapter } from '@cardstack/postgres'; -module(`realm-endpoints/${basename(__filename)}`, function () { +module(`realm-endpoints/${basename(import.meta.filename)}`, function () { module( 'Realm-specific Endpoints | POST _cancel-indexing-job', function (hooks) { diff --git a/packages/realm-server/tests/realm-endpoints/dependencies-test.ts b/packages/realm-server/tests/realm-endpoints/dependencies-test.ts index 5f2b199cf6..4678219e7d 100644 --- a/packages/realm-server/tests/realm-endpoints/dependencies-test.ts +++ b/packages/realm-server/tests/realm-endpoints/dependencies-test.ts @@ -6,7 +6,7 @@ import { SupportedMimeType } from '@cardstack/runtime-common'; import type { RealmHttpServer as Server } from '../../server.ts'; import { closeServer, setupPermissionedRealmCached } from '../helpers/index.ts'; -module(`realm-endpoints/${basename(__filename)}`, function (hooks) { +module(`realm-endpoints/${basename(import.meta.filename)}`, function (hooks) { let testRealm: Realm; let testRealmHttpServer: Server; let request: SuperTest; diff --git a/packages/realm-server/tests/realm-endpoints/directory-test.ts b/packages/realm-server/tests/realm-endpoints/directory-test.ts index a12cdf4909..5b9e6359ff 100644 --- a/packages/realm-server/tests/realm-endpoints/directory-test.ts +++ b/packages/realm-server/tests/realm-endpoints/directory-test.ts @@ -9,7 +9,7 @@ import { } from '../helpers/index.ts'; import '@cardstack/runtime-common/helpers/code-equality-assertion'; -module(`realm-endpoints/${basename(__filename)}`, function () { +module(`realm-endpoints/${basename(import.meta.filename)}`, function () { module('Realm-specific Endpoints | GET directory path', function () { let testRealm: Realm; let request: SuperTest; diff --git a/packages/realm-server/tests/realm-endpoints/indexing-errors-test.ts b/packages/realm-server/tests/realm-endpoints/indexing-errors-test.ts index 961bcd67e4..cc98d408d2 100644 --- a/packages/realm-server/tests/realm-endpoints/indexing-errors-test.ts +++ b/packages/realm-server/tests/realm-endpoints/indexing-errors-test.ts @@ -20,7 +20,7 @@ import { const ownerUserId = '@mango:localhost'; -module(`realm-endpoints/${basename(__filename)}`, function () { +module(`realm-endpoints/${basename(import.meta.filename)}`, function () { module('with a clean realm', function (hooks) { let realmURL = testRealmURLFor('test/'); let request: RealmRequest; diff --git a/packages/realm-server/tests/realm-endpoints/info-test.ts b/packages/realm-server/tests/realm-endpoints/info-test.ts index e2ac6dc5fc..6b62c582dd 100644 --- a/packages/realm-server/tests/realm-endpoints/info-test.ts +++ b/packages/realm-server/tests/realm-endpoints/info-test.ts @@ -13,7 +13,7 @@ import { import '@cardstack/runtime-common/helpers/code-equality-assertion'; import { resetCatalogRealms } from '../../handlers/handle-fetch-catalog-realms.ts'; -module(`realm-endpoints/${basename(__filename)}`, function () { +module(`realm-endpoints/${basename(import.meta.filename)}`, function () { module('Realm-specific Endpoints | QUERY _info', function (hooks) { let realmURL = testRealmURLFor('test/'); let testRealm: Realm; diff --git a/packages/realm-server/tests/realm-endpoints/invalidate-urls-test.ts b/packages/realm-server/tests/realm-endpoints/invalidate-urls-test.ts index 2bcbeb4076..963d6be83d 100644 --- a/packages/realm-server/tests/realm-endpoints/invalidate-urls-test.ts +++ b/packages/realm-server/tests/realm-endpoints/invalidate-urls-test.ts @@ -6,7 +6,7 @@ import { SupportedMimeType } from '@cardstack/runtime-common'; import { createJWT, setupPermissionedRealmCached } from '../helpers/index.ts'; import type { PgAdapter as TestPgAdapter } from '@cardstack/postgres'; -module(`realm-endpoints/${basename(__filename)}`, function () { +module(`realm-endpoints/${basename(import.meta.filename)}`, function () { module('Realm-specific Endpoints | POST _invalidate', function (hooks) { let testRealm: Realm; let request: SuperTest; diff --git a/packages/realm-server/tests/realm-endpoints/lint-test.ts b/packages/realm-server/tests/realm-endpoints/lint-test.ts index 3a2129db87..63ef41f873 100644 --- a/packages/realm-server/tests/realm-endpoints/lint-test.ts +++ b/packages/realm-server/tests/realm-endpoints/lint-test.ts @@ -12,7 +12,7 @@ import { } from '../helpers/prettier-test-utils.ts'; import '@cardstack/runtime-common/helpers/code-equality-assertion'; -module(`realm-endpoints/${basename(__filename)}`, function () { +module(`realm-endpoints/${basename(import.meta.filename)}`, function () { module('Realm-specific Endpoints | POST _lint', function (hooks) { let testRealm: Realm; let request: SuperTest; diff --git a/packages/realm-server/tests/realm-endpoints/markdown-test.ts b/packages/realm-server/tests/realm-endpoints/markdown-test.ts index 09548a4457..2cb7dbbc25 100644 --- a/packages/realm-server/tests/realm-endpoints/markdown-test.ts +++ b/packages/realm-server/tests/realm-endpoints/markdown-test.ts @@ -280,7 +280,7 @@ const CACHE_CARD_UPDATED_GTS = ` } `; -module(`realm-endpoints/${basename(__filename)}`, function (hooks) { +module(`realm-endpoints/${basename(import.meta.filename)}`, function (hooks) { let testRealm: Realm; let testRealmHttpServer: Server; let request: SuperTest; diff --git a/packages/realm-server/tests/realm-endpoints/mtimes-test.ts b/packages/realm-server/tests/realm-endpoints/mtimes-test.ts index e6e5605176..270aef12a5 100644 --- a/packages/realm-server/tests/realm-endpoints/mtimes-test.ts +++ b/packages/realm-server/tests/realm-endpoints/mtimes-test.ts @@ -11,7 +11,7 @@ import { } from '../helpers/index.ts'; import '@cardstack/runtime-common/helpers/code-equality-assertion'; -module(`realm-endpoints/${basename(__filename)}`, function () { +module(`realm-endpoints/${basename(import.meta.filename)}`, function () { module('Realm-specific Endpoints | GET _mtimes', function (hooks) { let testRealm: Realm; let testRealmPath: string; diff --git a/packages/realm-server/tests/realm-endpoints/permissions-test.ts b/packages/realm-server/tests/realm-endpoints/permissions-test.ts index 11e19ab992..63fc7df534 100644 --- a/packages/realm-server/tests/realm-endpoints/permissions-test.ts +++ b/packages/realm-server/tests/realm-endpoints/permissions-test.ts @@ -17,7 +17,7 @@ import { import '@cardstack/runtime-common/helpers/code-equality-assertion'; import type { PgAdapter } from '@cardstack/postgres'; -module(`realm-endpoints/${basename(__filename)}`, function () { +module(`realm-endpoints/${basename(import.meta.filename)}`, function () { module('Realm-specific Endpoints | _permissions', function () { let testRealm: Realm; let request: SuperTest; diff --git a/packages/realm-server/tests/realm-endpoints/publishability-test.ts b/packages/realm-server/tests/realm-endpoints/publishability-test.ts index 1f820781a7..1f09e7a1e6 100644 --- a/packages/realm-server/tests/realm-endpoints/publishability-test.ts +++ b/packages/realm-server/tests/realm-endpoints/publishability-test.ts @@ -20,7 +20,7 @@ import { const ownerUserId = '@mango:localhost'; -module(`realm-endpoints/${basename(__filename)}`, function () { +module(`realm-endpoints/${basename(import.meta.filename)}`, function () { module('with a publishable realm', function (hooks) { let realmURL = testRealmURLFor('test/'); let request: RealmRequest; diff --git a/packages/realm-server/tests/realm-endpoints/reindex-test.ts b/packages/realm-server/tests/realm-endpoints/reindex-test.ts index dc3136ff4b..862e72b14b 100644 --- a/packages/realm-server/tests/realm-endpoints/reindex-test.ts +++ b/packages/realm-server/tests/realm-endpoints/reindex-test.ts @@ -95,7 +95,7 @@ const ARTICLE_INSTANCE = JSON.stringify({ }, }); -module(`realm-endpoints/${basename(__filename)}`, function () { +module(`realm-endpoints/${basename(import.meta.filename)}`, function () { module( 'Realm-specific Endpoints | POST _reindex and _full-reindex', function (hooks) { diff --git a/packages/realm-server/tests/realm-endpoints/search-test.ts b/packages/realm-server/tests/realm-endpoints/search-test.ts index f4b9c198c0..dc7d8d2355 100644 --- a/packages/realm-server/tests/realm-endpoints/search-test.ts +++ b/packages/realm-server/tests/realm-endpoints/search-test.ts @@ -10,7 +10,7 @@ import { } from '../helpers/index.ts'; import '@cardstack/runtime-common/helpers/code-equality-assertion'; -module(`realm-endpoints/${basename(__filename)}`, function () { +module(`realm-endpoints/${basename(import.meta.filename)}`, function () { module('Realm-specific Endpoints | _search', function () { let testRealm: Realm; let request: SuperTest; diff --git a/packages/realm-server/tests/realm-endpoints/search-v2-test.ts b/packages/realm-server/tests/realm-endpoints/search-v2-test.ts index b763c94f3d..dcf27052ad 100644 --- a/packages/realm-server/tests/realm-endpoints/search-v2-test.ts +++ b/packages/realm-server/tests/realm-endpoints/search-v2-test.ts @@ -9,7 +9,7 @@ import { } from '../helpers/index.ts'; import '@cardstack/runtime-common/helpers/code-equality-assertion'; -module(`realm-endpoints/${basename(__filename)}`, function () { +module(`realm-endpoints/${basename(import.meta.filename)}`, function () { module('Realm-specific Endpoints | _search-v2', function (hooks) { let testRealm: Realm; let dbAdapter: PgAdapter; diff --git a/packages/realm-server/tests/realm-endpoints/user-test.ts b/packages/realm-server/tests/realm-endpoints/user-test.ts index a302257ab3..0b6dea97a1 100644 --- a/packages/realm-server/tests/realm-endpoints/user-test.ts +++ b/packages/realm-server/tests/realm-endpoints/user-test.ts @@ -21,7 +21,7 @@ import { } from '@cardstack/billing/billing-queries'; import { resetCatalogRealms } from '../../handlers/handle-fetch-catalog-realms.ts'; -module(`realm-endpoints/${basename(__filename)}`, function () { +module(`realm-endpoints/${basename(import.meta.filename)}`, function () { module('Realm-specific Endpoints | GET _user', function (hooks) { let testRealm: Realm; let testRealmHttpServer: Server; diff --git a/packages/realm-server/tests/realm-file-changes-listener-test.ts b/packages/realm-server/tests/realm-file-changes-listener-test.ts index b616f4941d..85bed03e68 100644 --- a/packages/realm-server/tests/realm-file-changes-listener-test.ts +++ b/packages/realm-server/tests/realm-file-changes-listener-test.ts @@ -53,7 +53,7 @@ function waitFor( }); } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('parsePayload', function () { test('parses url:path with a port in the url', function (assert) { assert.deepEqual( diff --git a/packages/realm-server/tests/realm-identifiers-test.ts b/packages/realm-server/tests/realm-identifiers-test.ts index 9a95552624..d18bfaa413 100644 --- a/packages/realm-server/tests/realm-identifiers-test.ts +++ b/packages/realm-server/tests/realm-identifiers-test.ts @@ -5,7 +5,7 @@ import { ri, rri } from '@cardstack/runtime-common'; import type { SingleCardDocument } from '@cardstack/runtime-common'; import { relativizeDocument } from '@cardstack/runtime-common/realm-index-query-engine'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { // Regression test for CS-10498: cards in prefix-mapped realms (like the // openrouter realm) threw TypeError: Invalid URL when served. // diff --git a/packages/realm-server/tests/realm-index-updated-listener-test.ts b/packages/realm-server/tests/realm-index-updated-listener-test.ts index 37ed38a205..b7ee54ad4b 100644 --- a/packages/realm-server/tests/realm-index-updated-listener-test.ts +++ b/packages/realm-server/tests/realm-index-updated-listener-test.ts @@ -39,7 +39,7 @@ function waitFor( }); } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('RealmIndexUpdatedListener (dispatch)', function () { test('handleNotification forwards to the mounted realm', function (assert) { let cleared = 0; diff --git a/packages/realm-server/tests/realm-operations-test.ts b/packages/realm-server/tests/realm-operations-test.ts index d2631ab67d..d2dcea20ad 100644 --- a/packages/realm-server/tests/realm-operations-test.ts +++ b/packages/realm-server/tests/realm-operations-test.ts @@ -53,7 +53,7 @@ function jsonResponse(status: number, body: unknown): Response { }); } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('realm-operations', function () { test('publishRealm POSTs normalized URLs and maps the 202 response', async function (assert) { let { client, calls } = makeClient(() => diff --git a/packages/realm-server/tests/realm-registry-backfill-test.ts b/packages/realm-server/tests/realm-registry-backfill-test.ts index 3f5b1f468b..9fe9942245 100644 --- a/packages/realm-server/tests/realm-registry-backfill-test.ts +++ b/packages/realm-server/tests/realm-registry-backfill-test.ts @@ -1,7 +1,8 @@ import { module, test } from 'qunit'; import { basename, join } from 'path'; import { dirSync, type DirResult } from 'tmp'; -import { ensureDirSync, writeFileSync } from 'fs-extra'; +import fsExtra from 'fs-extra'; +const { ensureDirSync, writeFileSync } = fsExtra; import type { PgAdapter } from '@cardstack/postgres'; import { asExpressions, @@ -103,7 +104,7 @@ function seedRealmJson(realmDir: string, payload: Record) { writeFileSync(join(realmDir, 'realm.json'), JSON.stringify(card, null, 2)); } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('runRegistryBackfill', function (hooks) { let dbAdapter: PgAdapter; let dir: DirResult; diff --git a/packages/realm-server/tests/realm-registry-reconciler-test.ts b/packages/realm-server/tests/realm-registry-reconciler-test.ts index 8df5348fb6..b62614403d 100644 --- a/packages/realm-server/tests/realm-registry-reconciler-test.ts +++ b/packages/realm-server/tests/realm-registry-reconciler-test.ts @@ -51,7 +51,7 @@ async function deleteRow(dbAdapter: PgAdapter, url: string) { ]); } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('RealmRegistryReconciler', function (hooks) { let dbAdapter: PgAdapter; let mountCalls: string[]; diff --git a/packages/realm-server/tests/realm-registry-writes-test.ts b/packages/realm-server/tests/realm-registry-writes-test.ts index d81473c609..8c9e25635b 100644 --- a/packages/realm-server/tests/realm-registry-writes-test.ts +++ b/packages/realm-server/tests/realm-registry-writes-test.ts @@ -71,7 +71,7 @@ async function seedBootstrapRow(dbAdapter: PgAdapter, url: string) { ); } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('upsertPublishedRealmInRegistry', function (hooks) { let dbAdapter: PgAdapter; setupDB(hooks, { diff --git a/packages/realm-server/tests/realm-routing-test.ts b/packages/realm-server/tests/realm-routing-test.ts index 293197312b..769cef60a8 100644 --- a/packages/realm-server/tests/realm-routing-test.ts +++ b/packages/realm-server/tests/realm-routing-test.ts @@ -73,7 +73,7 @@ function makeRoutingFixture(): Record< }; } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('Realm.getHostRoutingMap', function (hooks) { let realmURL = new URL('http://127.0.0.1:4444/routing-unit/'); let testRealm: Realm; diff --git a/packages/realm-server/tests/remote-prerenderer-test.ts b/packages/realm-server/tests/remote-prerenderer-test.ts index 555440e331..cbe36f5186 100644 --- a/packages/realm-server/tests/remote-prerenderer-test.ts +++ b/packages/realm-server/tests/remote-prerenderer-test.ts @@ -8,7 +8,7 @@ import { PRERENDER_SERVER_STATUS_HEADER, } from '../prerender/prerender-constants.ts'; -module(basename(__filename), function (hooks) { +module(basename(import.meta.filename), function (hooks) { hooks.afterEach(function () { delete process.env.PRERENDER_MANAGER_RETRY_ATTEMPTS; delete process.env.PRERENDER_MANAGER_RETRY_DELAY_MS; @@ -449,7 +449,7 @@ module(basename(__filename), function (hooks) { }); }); -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('remote prerenderer timeouts', function () { test('does not retry when the client aborts from request timeout', async function (assert) { process.env.PRERENDER_MANAGER_RETRY_ATTEMPTS = '3'; diff --git a/packages/realm-server/tests/render-type-resolution-test.ts b/packages/realm-server/tests/render-type-resolution-test.ts index a3d30d0c89..8cfeb64bf7 100644 --- a/packages/realm-server/tests/render-type-resolution-test.ts +++ b/packages/realm-server/tests/render-type-resolution-test.ts @@ -22,7 +22,7 @@ const explicitRef: ResolvedCodeRef = { name: 'Contact', }; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('render-type resolution', function () { test('an explicit renderType CodeRef wins', function (assert) { assert.deepEqual( diff --git a/packages/realm-server/tests/request-forward-test.ts b/packages/realm-server/tests/request-forward-test.ts index 4c7fa1b1a3..fd15beb13a 100644 --- a/packages/realm-server/tests/request-forward-test.ts +++ b/packages/realm-server/tests/request-forward-test.ts @@ -5,7 +5,8 @@ import supertest from 'supertest'; import { basename, join } from 'path'; import type { RealmHttpServer as Server } from '../server.ts'; import { dirSync, type DirResult } from 'tmp'; -import { copySync, ensureDirSync } from 'fs-extra'; +import fsExtra from 'fs-extra'; +const { copySync, ensureDirSync } = fsExtra; import { setupDB, runTestRealmServer, @@ -26,7 +27,7 @@ import { } from '@cardstack/billing/billing-queries'; import { AllowedProxyDestinations } from '../lib/allowed-proxy-destinations.ts'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('Realm-specific Endpoints | _request-forward', function (hooks) { let testRealmHttpServer: Server; let testRealm: any; diff --git a/packages/realm-server/tests/resolve-published-realm-url-test.ts b/packages/realm-server/tests/resolve-published-realm-url-test.ts index bf641bf5cf..a07849e460 100644 --- a/packages/realm-server/tests/resolve-published-realm-url-test.ts +++ b/packages/realm-server/tests/resolve-published-realm-url-test.ts @@ -5,7 +5,7 @@ import { resolvePublishedRealmUrl, } from '@cardstack/runtime-common'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('resolve-published-realm-url', function () { // deriveRealmName test('deriveRealmName returns the last path segment, lowercased', async function (assert) { diff --git a/packages/realm-server/tests/run-command-task-test.ts b/packages/realm-server/tests/run-command-task-test.ts index d4de108c4a..2d4e8b2004 100644 --- a/packages/realm-server/tests/run-command-task-test.ts +++ b/packages/realm-server/tests/run-command-task-test.ts @@ -3,7 +3,7 @@ import { basename } from 'path'; import { runSharedTest } from '@cardstack/runtime-common/helpers'; import runCommandTaskTests from '@cardstack/runtime-common/tests/run-command-task-shared-tests'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('run-command task', function () { test('returns error when runAs has no realm permissions', async function (assert) { await runSharedTest(runCommandTaskTests, assert, {}); diff --git a/packages/realm-server/tests/runtime-dependency-tracker-test.ts b/packages/realm-server/tests/runtime-dependency-tracker-test.ts index facbff8ccb..f0f69baf13 100644 --- a/packages/realm-server/tests/runtime-dependency-tracker-test.ts +++ b/packages/realm-server/tests/runtime-dependency-tracker-test.ts @@ -14,7 +14,7 @@ import { withRuntimeDependencyTrackingContext, } from '@cardstack/runtime-common'; -module(basename(__filename), function (hooks) { +module(basename(import.meta.filename), function (hooks) { hooks.afterEach(() => { endRuntimeDependencyTrackingSession(); resetRuntimeDependencyTracker(); diff --git a/packages/realm-server/tests/runtime-exception-capture-test.ts b/packages/realm-server/tests/runtime-exception-capture-test.ts index 53fd79f31d..bdc125d95e 100644 --- a/packages/realm-server/tests/runtime-exception-capture-test.ts +++ b/packages/realm-server/tests/runtime-exception-capture-test.ts @@ -124,7 +124,7 @@ function buildExceptionThrownEvent(opts: { }; } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { test('records Runtime.exceptionThrown into the recorder', async function (assert) { let client = new FakeCDPClient(); let page = new FakePage(client); diff --git a/packages/realm-server/tests/sanitize-for-jsonb-test.ts b/packages/realm-server/tests/sanitize-for-jsonb-test.ts index cc79b4a07e..7ac2adfba7 100644 --- a/packages/realm-server/tests/sanitize-for-jsonb-test.ts +++ b/packages/realm-server/tests/sanitize-for-jsonb-test.ts @@ -18,7 +18,7 @@ function hasIllegalCodePoint(value: string): boolean { ); } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { test('returns clean values unchanged', function (assert) { assert.strictEqual(sanitizeForJsonb('plain text'), 'plain text'); assert.strictEqual(sanitizeForJsonb(42 as unknown), 42); diff --git a/packages/realm-server/tests/sanitize-head-html-test.ts b/packages/realm-server/tests/sanitize-head-html-test.ts index 1270b8578c..942319b17e 100644 --- a/packages/realm-server/tests/sanitize-head-html-test.ts +++ b/packages/realm-server/tests/sanitize-head-html-test.ts @@ -11,7 +11,7 @@ function makeDoc() { return new JSDOM().window.document; } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('sanitizeHeadHTML', function () { test('allows title, meta, and link tags', function (assert) { let doc = makeDoc(); diff --git a/packages/realm-server/tests/screenshot-card-test.ts b/packages/realm-server/tests/screenshot-card-test.ts index b64d10805a..9f39b57851 100644 --- a/packages/realm-server/tests/screenshot-card-test.ts +++ b/packages/realm-server/tests/screenshot-card-test.ts @@ -19,7 +19,7 @@ import { jwtMiddleware } from '../middleware/index.ts'; import { createJWT } from '../utils/jwt.ts'; import { realmSecretSeed } from './helpers/index.ts'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('/_screenshot-card endpoint', function () { function makeDbAdapter(): DBAdapter { return { diff --git a/packages/realm-server/tests/search-compat-test.ts b/packages/realm-server/tests/search-compat-test.ts index a5818620cb..1bbeb15bc7 100644 --- a/packages/realm-server/tests/search-compat-test.ts +++ b/packages/realm-server/tests/search-compat-test.ts @@ -64,7 +64,7 @@ function chainDoc(memberRefs: { module: string; name: string }[]) { return doc; } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('prerendered coalescing: renderType pick', function () { test('picks the requested ancestor when its rendering exists', function (assert) { let doc = searchEntryDocToPrerenderedDoc( diff --git a/packages/realm-server/tests/search-entries-engine-test.ts b/packages/realm-server/tests/search-entries-engine-test.ts index c8c0c9d80f..1cc7fd4971 100644 --- a/packages/realm-server/tests/search-entries-engine-test.ts +++ b/packages/realm-server/tests/search-entries-engine-test.ts @@ -70,7 +70,7 @@ function htmlIdsOf(entry: SearchEntryResource): string[] | undefined { return entry.relationships.html?.data.map((member) => member.id); } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('searchEntries projection engine', function (hooks) { let testRealm: Realm; let dbAdapter: PgAdapter; diff --git a/packages/realm-server/tests/search-entry-test.ts b/packages/realm-server/tests/search-entry-test.ts index 94752ebcef..d18960b651 100644 --- a/packages/realm-server/tests/search-entry-test.ts +++ b/packages/realm-server/tests/search-entry-test.ts @@ -79,7 +79,7 @@ const universe: RenderingCandidate[] = [ { format: 'head' }, ]; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('search-entry query parser', function () { test('translates the canonical search-entry query', function (assert) { let htmlQuery: HtmlQuery = { diff --git a/packages/realm-server/tests/search-in-flight-key-test.ts b/packages/realm-server/tests/search-in-flight-key-test.ts index 47b33be840..1d4f3bb159 100644 --- a/packages/realm-server/tests/search-in-flight-key-test.ts +++ b/packages/realm-server/tests/search-in-flight-key-test.ts @@ -3,7 +3,7 @@ import { basename } from 'path'; import { runSharedTest } from '@cardstack/runtime-common/helpers'; import searchInFlightKeyTests from '@cardstack/runtime-common/tests/search-in-flight-key-test'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('searchInFlightKey', function () { test('same query + opts produce the same key', async function (assert) { await runSharedTest(searchInFlightKeyTests, assert, {}); diff --git a/packages/realm-server/tests/search-prerendered-test.ts b/packages/realm-server/tests/search-prerendered-test.ts index 360ccfaa4b..5e43f16343 100644 --- a/packages/realm-server/tests/search-prerendered-test.ts +++ b/packages/realm-server/tests/search-prerendered-test.ts @@ -10,7 +10,7 @@ import '@cardstack/runtime-common/helpers/code-equality-assertion'; const missingPrerenderedHtmlFormatMessage = `Must include a 'prerenderedHtmlFormat' parameter with a value of ${PRERENDERED_HTML_FORMATS.join()} to use this endpoint`; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('Realm-specific Endpoints | _search-prerendered', function () { let testRealm: Realm; let request: SuperTest; diff --git a/packages/realm-server/tests/serve-index-test.ts b/packages/realm-server/tests/serve-index-test.ts index 2dfecb6235..2fc9f1aa4d 100644 --- a/packages/realm-server/tests/serve-index-test.ts +++ b/packages/realm-server/tests/serve-index-test.ts @@ -32,7 +32,7 @@ function validIndexHTML(): string { )}">`; } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { test('a thrown error in retrieveIndexHTML clears the cache so the next call retries', async function (assert) { let calls = 0; let { retrieveIndexHTML } = createServeIndex( diff --git a/packages/realm-server/tests/server-config-test.ts b/packages/realm-server/tests/server-config-test.ts index 2107762bbc..2e3d122557 100644 --- a/packages/realm-server/tests/server-config-test.ts +++ b/packages/realm-server/tests/server-config-test.ts @@ -3,7 +3,7 @@ import { basename } from 'path'; import { createServeIndex } from '../handlers/serve-index.ts'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { test('prefers MATRIX_SERVER_NAME over matrix URL hostname in host config', async function (assert) { let originalMatrixServerName = process.env.MATRIX_SERVER_NAME; diff --git a/packages/realm-server/tests/server-endpoints/authentication-test.ts b/packages/realm-server/tests/server-endpoints/authentication-test.ts index a2d457e86f..87df3fd608 100644 --- a/packages/realm-server/tests/server-endpoints/authentication-test.ts +++ b/packages/realm-server/tests/server-endpoints/authentication-test.ts @@ -16,7 +16,7 @@ import { getUserByMatrixUserId } from '@cardstack/billing/billing-queries'; import type { PgAdapter } from '@cardstack/postgres'; import '@cardstack/runtime-common/helpers/code-equality-assertion'; -module(`server-endpoints/${basename(__filename)}`, function () { +module(`server-endpoints/${basename(import.meta.filename)}`, function () { module('Realm server authentication', function (hooks) { let request: SuperTest; let dbAdapter: PgAdapter; diff --git a/packages/realm-server/tests/server-endpoints/bot-commands-test.ts b/packages/realm-server/tests/server-endpoints/bot-commands-test.ts index 4f207eae47..403e2b1357 100644 --- a/packages/realm-server/tests/server-endpoints/bot-commands-test.ts +++ b/packages/realm-server/tests/server-endpoints/bot-commands-test.ts @@ -5,7 +5,7 @@ import { realmSecretSeed, insertUser } from '../helpers/index.ts'; import { param, query, uuidv4 } from '@cardstack/runtime-common'; import { setupServerEndpointsTest } from './helpers.ts'; -module(`server-endpoints/${basename(__filename)}`, function () { +module(`server-endpoints/${basename(import.meta.filename)}`, function () { module('Realm Server Endpoints', function (hooks) { let context = setupServerEndpointsTest(hooks); diff --git a/packages/realm-server/tests/server-endpoints/bot-registration-test.ts b/packages/realm-server/tests/server-endpoints/bot-registration-test.ts index 4344a2cee2..5b4a5a527f 100644 --- a/packages/realm-server/tests/server-endpoints/bot-registration-test.ts +++ b/packages/realm-server/tests/server-endpoints/bot-registration-test.ts @@ -5,7 +5,7 @@ import { realmSecretSeed, insertUser } from '../helpers/index.ts'; import { param, query, uuidv4 } from '@cardstack/runtime-common'; import { setupServerEndpointsTest } from './helpers.ts'; -module(`server-endpoints/${basename(__filename)}`, function () { +module(`server-endpoints/${basename(import.meta.filename)}`, function () { module( 'Realm Server Endpoints (not specific to one realm)', function (hooks) { diff --git a/packages/realm-server/tests/server-endpoints/delete-realm-test.ts b/packages/realm-server/tests/server-endpoints/delete-realm-test.ts index 52067e97bb..e4d6d44e36 100644 --- a/packages/realm-server/tests/server-endpoints/delete-realm-test.ts +++ b/packages/realm-server/tests/server-endpoints/delete-realm-test.ts @@ -1,6 +1,7 @@ import { module, test } from 'qunit'; import { basename, join } from 'path'; -import { existsSync } from 'fs-extra'; +import fsExtra from 'fs-extra'; +const { existsSync } = fsExtra; import { v4 as uuidv4 } from 'uuid'; import { @@ -15,7 +16,7 @@ import { insertJob, insertUser, realmSecretSeed } from '../helpers/index.ts'; import { createJWT as createRealmServerJWT } from '../../utils/jwt.ts'; import { setupServerEndpointsTest } from './helpers.ts'; -module(`server-endpoints/${basename(__filename)}`, function (hooks) { +module(`server-endpoints/${basename(import.meta.filename)}`, function (hooks) { let context = setupServerEndpointsTest(hooks); async function createRealmFor(ownerUserId: string) { diff --git a/packages/realm-server/tests/server-endpoints/download-realm-test.ts b/packages/realm-server/tests/server-endpoints/download-realm-test.ts index f8519696ce..f2545684c4 100644 --- a/packages/realm-server/tests/server-endpoints/download-realm-test.ts +++ b/packages/realm-server/tests/server-endpoints/download-realm-test.ts @@ -25,7 +25,7 @@ function binaryParser( }); } -module(`server-endpoints/${basename(__filename)}`, function (hooks) { +module(`server-endpoints/${basename(import.meta.filename)}`, function (hooks) { // Use the `simple` fixture so the realm has real card files to assert // the archive contains; the `blank` fixture has no card content. let context = setupServerEndpointsTest(hooks, { fixture: 'simple' }); diff --git a/packages/realm-server/tests/server-endpoints/federated-types-test.ts b/packages/realm-server/tests/server-endpoints/federated-types-test.ts index e3a6956061..2092fc2d47 100644 --- a/packages/realm-server/tests/server-endpoints/federated-types-test.ts +++ b/packages/realm-server/tests/server-endpoints/federated-types-test.ts @@ -32,7 +32,7 @@ interface FederatedTypesResponse { }; } -module(`server-endpoints/${basename(__filename)}`, function (_hooks) { +module(`server-endpoints/${basename(import.meta.filename)}`, function (_hooks) { module('Realm Server Endpoints | /_federated-types', function (hooks) { let testRealm: Realm; let secondaryRealm: Realm; diff --git a/packages/realm-server/tests/server-endpoints/incoming-webhook-test.ts b/packages/realm-server/tests/server-endpoints/incoming-webhook-test.ts index 3b21b10e54..13a8d40902 100644 --- a/packages/realm-server/tests/server-endpoints/incoming-webhook-test.ts +++ b/packages/realm-server/tests/server-endpoints/incoming-webhook-test.ts @@ -5,7 +5,7 @@ import { realmSecretSeed, insertUser } from '../helpers/index.ts'; import { param, query, uuidv4 } from '@cardstack/runtime-common'; import { setupServerEndpointsTest } from './helpers.ts'; -module(`server-endpoints/${basename(__filename)}`, function () { +module(`server-endpoints/${basename(import.meta.filename)}`, function () { module('Incoming Webhook Endpoints', function (hooks) { let context = setupServerEndpointsTest(hooks); diff --git a/packages/realm-server/tests/server-endpoints/index-responses-test.ts b/packages/realm-server/tests/server-endpoints/index-responses-test.ts index ef5c74cd44..7658ee268f 100644 --- a/packages/realm-server/tests/server-endpoints/index-responses-test.ts +++ b/packages/realm-server/tests/server-endpoints/index-responses-test.ts @@ -24,10 +24,11 @@ import { waitUntil, } from '../helpers/index.ts'; import { createJWT as createRealmServerJWT } from '../../utils/jwt.ts'; -import { ensureDirSync } from 'fs-extra'; +import fsExtra from 'fs-extra'; +const { ensureDirSync } = fsExtra; import '@cardstack/runtime-common/helpers/code-equality-assertion'; -module(`server-endpoints/${basename(__filename)}`, function () { +module(`server-endpoints/${basename(import.meta.filename)}`, function () { module( 'Realm Server Endpoints (not specific to one realm)', function (hooks) { diff --git a/packages/realm-server/tests/server-endpoints/info-test.ts b/packages/realm-server/tests/server-endpoints/info-test.ts index a734726c7b..303ba3e03d 100644 --- a/packages/realm-server/tests/server-endpoints/info-test.ts +++ b/packages/realm-server/tests/server-endpoints/info-test.ts @@ -22,7 +22,7 @@ import { import { createJWT as createRealmServerJWT } from '../../utils/jwt.ts'; import type { RealmHttpServer as Server } from '../../server.ts'; -module(`server-endpoints/${basename(__filename)}`, function (_hooks) { +module(`server-endpoints/${basename(import.meta.filename)}`, function (_hooks) { module('Realm Server Endpoints | /_federated-info', function (hooks) { let testRealm: Realm; let secondaryRealm: Realm; diff --git a/packages/realm-server/tests/server-endpoints/maintenance-endpoints-test.ts b/packages/realm-server/tests/server-endpoints/maintenance-endpoints-test.ts index 70e2037ecd..af1755708b 100644 --- a/packages/realm-server/tests/server-endpoints/maintenance-endpoints-test.ts +++ b/packages/realm-server/tests/server-endpoints/maintenance-endpoints-test.ts @@ -54,7 +54,7 @@ async function ensureMatrixAdminUser(): Promise { }); } -module(`server-endpoints/${basename(__filename)}`, function () { +module(`server-endpoints/${basename(import.meta.filename)}`, function () { module( 'Realm Server Endpoints (not specific to one realm)', function (hooks) { diff --git a/packages/realm-server/tests/server-endpoints/queue-status-test.ts b/packages/realm-server/tests/server-endpoints/queue-status-test.ts index d76d1ac276..effb92289e 100644 --- a/packages/realm-server/tests/server-endpoints/queue-status-test.ts +++ b/packages/realm-server/tests/server-endpoints/queue-status-test.ts @@ -6,7 +6,7 @@ import { insertJob, setupPermissionedRealmCached } from '../helpers/index.ts'; import { monitoringAuthToken } from '../../utils/monitoring.ts'; import '@cardstack/runtime-common/helpers/code-equality-assertion'; -module(`server-endpoints/${basename(__filename)}`, function () { +module(`server-endpoints/${basename(import.meta.filename)}`, function () { module('Realm Server Endpoints (not specific to one realm)', function () { module('_queue-status', function (hooks) { let request: SuperTest; diff --git a/packages/realm-server/tests/server-endpoints/realm-lifecycle-test.ts b/packages/realm-server/tests/server-endpoints/realm-lifecycle-test.ts index 21c901a3fa..c631fa3be2 100644 --- a/packages/realm-server/tests/server-endpoints/realm-lifecycle-test.ts +++ b/packages/realm-server/tests/server-endpoints/realm-lifecycle-test.ts @@ -1,6 +1,7 @@ import { module, test } from 'qunit'; import { basename, join } from 'path'; -import { existsSync, readJSONSync } from 'fs-extra'; +import fsExtra from 'fs-extra'; +const { existsSync, readJSONSync } = fsExtra; import type { Test, SuperTest } from 'supertest'; import { v4 as uuidv4 } from 'uuid'; import type { Query } from '@cardstack/runtime-common/query'; @@ -26,7 +27,7 @@ import { createJWT as createRealmServerJWT } from '../../utils/jwt.ts'; import { setupServerEndpointsTest, testRealmURL } from './helpers.ts'; import '@cardstack/runtime-common/helpers/code-equality-assertion'; -module(`server-endpoints/${basename(__filename)}`, function () { +module(`server-endpoints/${basename(import.meta.filename)}`, function () { module( 'Realm Server Endpoints (not specific to one realm)', function (hooks) { diff --git a/packages/realm-server/tests/server-endpoints/run-command-endpoint-test.ts b/packages/realm-server/tests/server-endpoints/run-command-endpoint-test.ts index 244abb06f5..2ba8c4af5b 100644 --- a/packages/realm-server/tests/server-endpoints/run-command-endpoint-test.ts +++ b/packages/realm-server/tests/server-endpoints/run-command-endpoint-test.ts @@ -4,7 +4,7 @@ import { createJWT as createRealmServerJWT } from '../../utils/jwt.ts'; import { realmSecretSeed, insertUser } from '../helpers/index.ts'; import { setupServerEndpointsTest, testRealmURL } from './helpers.ts'; -module(`server-endpoints/${basename(__filename)}`, function () { +module(`server-endpoints/${basename(import.meta.filename)}`, function () { module('/_run-command endpoint', function (hooks) { let context = setupServerEndpointsTest(hooks); diff --git a/packages/realm-server/tests/server-endpoints/screenshot-card-endpoint-test.ts b/packages/realm-server/tests/server-endpoints/screenshot-card-endpoint-test.ts index c01969ac5e..97a36625fe 100644 --- a/packages/realm-server/tests/server-endpoints/screenshot-card-endpoint-test.ts +++ b/packages/realm-server/tests/server-endpoints/screenshot-card-endpoint-test.ts @@ -4,7 +4,7 @@ import { createJWT as createRealmServerJWT } from '../../utils/jwt.ts'; import { realmSecretSeed, insertUser } from '../helpers/index.ts'; import { setupServerEndpointsTest, testRealmURL } from './helpers.ts'; -module(`server-endpoints/${basename(__filename)}`, function () { +module(`server-endpoints/${basename(import.meta.filename)}`, function () { module('/_screenshot-card endpoint', function (hooks) { // Auth / body-validation only — the cardId never has to resolve, so use `blank`. let context = setupServerEndpointsTest(hooks, { fixture: 'blank' }); diff --git a/packages/realm-server/tests/server-endpoints/search-prerendered-test.ts b/packages/realm-server/tests/server-endpoints/search-prerendered-test.ts index 75e94f9ed7..ff480dba0c 100644 --- a/packages/realm-server/tests/server-endpoints/search-prerendered-test.ts +++ b/packages/realm-server/tests/server-endpoints/search-prerendered-test.ts @@ -28,7 +28,7 @@ import { import { createJWT as createRealmServerJWT } from '../../utils/jwt.ts'; import type { RealmHttpServer as Server } from '../../server.ts'; -module(`server-endpoints/${basename(__filename)}`, function (_hooks) { +module(`server-endpoints/${basename(import.meta.filename)}`, function (_hooks) { module( 'Realm Server Endpoints | /_federated-search-prerendered', function (hooks) { diff --git a/packages/realm-server/tests/server-endpoints/search-test.ts b/packages/realm-server/tests/server-endpoints/search-test.ts index 8ea600b5d4..4932a01f00 100644 --- a/packages/realm-server/tests/server-endpoints/search-test.ts +++ b/packages/realm-server/tests/server-endpoints/search-test.ts @@ -32,7 +32,7 @@ import { import { createJWT as createRealmServerJWT } from '../../utils/jwt.ts'; import type { RealmHttpServer as Server } from '../../server.ts'; -module(`server-endpoints/${basename(__filename)}`, function (_hooks) { +module(`server-endpoints/${basename(import.meta.filename)}`, function (_hooks) { module('Realm Server Endpoints | /_federated-search', function (hooks) { let testRealm: Realm; let secondaryRealm: Realm; diff --git a/packages/realm-server/tests/server-endpoints/search-v2-test.ts b/packages/realm-server/tests/server-endpoints/search-v2-test.ts index 2dcd00299e..a3086a46ad 100644 --- a/packages/realm-server/tests/server-endpoints/search-v2-test.ts +++ b/packages/realm-server/tests/server-endpoints/search-v2-test.ts @@ -23,7 +23,7 @@ import { import { createJWT as createRealmServerJWT } from '../../utils/jwt.ts'; import type { RealmHttpServer as Server } from '../../server.ts'; -module(`server-endpoints/${basename(__filename)}`, function (_hooks) { +module(`server-endpoints/${basename(import.meta.filename)}`, function (_hooks) { module('Realm Server Endpoints | /_federated-search-v2', function (hooks) { let testRealm: Realm; let secondaryRealm: Realm; diff --git a/packages/realm-server/tests/server-endpoints/stripe-session-test.ts b/packages/realm-server/tests/server-endpoints/stripe-session-test.ts index ee1ae83ca4..2a8f81513a 100644 --- a/packages/realm-server/tests/server-endpoints/stripe-session-test.ts +++ b/packages/realm-server/tests/server-endpoints/stripe-session-test.ts @@ -14,7 +14,7 @@ import { import '@cardstack/runtime-common/helpers/code-equality-assertion'; import type { Realm } from '@cardstack/runtime-common'; -module(`server-endpoints/${basename(__filename)}`, function () { +module(`server-endpoints/${basename(import.meta.filename)}`, function () { module('Realm Server Endpoints (not specific to one realm)', function () { module('stripe session handler', function (hooks) { let createCustomerStub: sinon.SinonStub; diff --git a/packages/realm-server/tests/server-endpoints/stripe-webhook-test.ts b/packages/realm-server/tests/server-endpoints/stripe-webhook-test.ts index 71103cb70d..04bb799ee5 100644 --- a/packages/realm-server/tests/server-endpoints/stripe-webhook-test.ts +++ b/packages/realm-server/tests/server-endpoints/stripe-webhook-test.ts @@ -25,7 +25,7 @@ import type { } from 'https://cardstack.com/base/matrix-event'; import '@cardstack/runtime-common/helpers/code-equality-assertion'; -module(`server-endpoints/${basename(__filename)}`, function () { +module(`server-endpoints/${basename(import.meta.filename)}`, function () { module('Realm Server Endpoints (not specific to one realm)', function () { module('stripe webhook handler', function (hooks) { let testRealm: Realm; diff --git a/packages/realm-server/tests/server-endpoints/user-and-catalog-test.ts b/packages/realm-server/tests/server-endpoints/user-and-catalog-test.ts index 504744a305..cb61d8fe89 100644 --- a/packages/realm-server/tests/server-endpoints/user-and-catalog-test.ts +++ b/packages/realm-server/tests/server-endpoints/user-and-catalog-test.ts @@ -8,7 +8,7 @@ import { resetCatalogRealms } from '../../handlers/handle-fetch-catalog-realms.t import { setupServerEndpointsTest, testRealmURL } from './helpers.ts'; import '@cardstack/runtime-common/helpers/code-equality-assertion'; -module(`server-endpoints/${basename(__filename)}`, function () { +module(`server-endpoints/${basename(import.meta.filename)}`, function () { module( 'Realm Server Endpoints (not specific to one realm)', function (hooks) { diff --git a/packages/realm-server/tests/server-endpoints/webhook-commands-test.ts b/packages/realm-server/tests/server-endpoints/webhook-commands-test.ts index ab61668fd5..7ffc117a37 100644 --- a/packages/realm-server/tests/server-endpoints/webhook-commands-test.ts +++ b/packages/realm-server/tests/server-endpoints/webhook-commands-test.ts @@ -5,7 +5,7 @@ import { realmSecretSeed, insertUser } from '../helpers/index.ts'; import { param, query, uuidv4 } from '@cardstack/runtime-common'; import { setupServerEndpointsTest } from './helpers.ts'; -module(`server-endpoints/${basename(__filename)}`, function () { +module(`server-endpoints/${basename(import.meta.filename)}`, function () { module('Webhook Command Endpoints', function (hooks) { let context = setupServerEndpointsTest(hooks); diff --git a/packages/realm-server/tests/server-endpoints/webhook-receiver-test.ts b/packages/realm-server/tests/server-endpoints/webhook-receiver-test.ts index 9ce42993dd..5b1aae9b2e 100644 --- a/packages/realm-server/tests/server-endpoints/webhook-receiver-test.ts +++ b/packages/realm-server/tests/server-endpoints/webhook-receiver-test.ts @@ -10,7 +10,7 @@ import { extractBranchNameFromPayload, } from '../../handlers/webhook-filter-handlers.ts'; -module(`server-endpoints/${basename(__filename)}`, function () { +module(`server-endpoints/${basename(import.meta.filename)}`, function () { module('Webhook Receiver Endpoint', function (hooks) { let context = setupServerEndpointsTest(hooks); diff --git a/packages/realm-server/tests/session-room-queries-test.ts b/packages/realm-server/tests/session-room-queries-test.ts index be5fdff3b5..ef6137f05e 100644 --- a/packages/realm-server/tests/session-room-queries-test.ts +++ b/packages/realm-server/tests/session-room-queries-test.ts @@ -10,7 +10,7 @@ import { } from '@cardstack/runtime-common/db-queries/session-room-queries'; import { setupDB, insertUser } from './helpers/index.ts'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('fetchRealmSessionRooms', function (hooks) { let dbAdapter: PgAdapter; const realmURL = new URL('http://127.0.0.1:4444/test/'); diff --git a/packages/realm-server/tests/skip-query-backed-expansion-test.ts b/packages/realm-server/tests/skip-query-backed-expansion-test.ts index f92c9a0d41..a74be57f40 100644 --- a/packages/realm-server/tests/skip-query-backed-expansion-test.ts +++ b/packages/realm-server/tests/skip-query-backed-expansion-test.ts @@ -79,7 +79,7 @@ function buildFileSystem(): Record { return fs; } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('skipQueryBackedExpansion', function (hooks) { let realm: Realm; diff --git a/packages/realm-server/tests/transpile-test.ts b/packages/realm-server/tests/transpile-test.ts index 757aecdf6a..5b5f2b2d8c 100644 --- a/packages/realm-server/tests/transpile-test.ts +++ b/packages/realm-server/tests/transpile-test.ts @@ -3,7 +3,7 @@ import { basename } from 'path'; import { transpileJS } from '@cardstack/runtime-common/transpile'; import '@cardstack/runtime-common/helpers/code-equality-assertion'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('Transpile', function () { test('can rewrite fetch()', async function (assert) { let transpiled = await transpileJS( diff --git a/packages/realm-server/tests/types-endpoint-test.ts b/packages/realm-server/tests/types-endpoint-test.ts index 014777b2fa..1a75525a05 100644 --- a/packages/realm-server/tests/types-endpoint-test.ts +++ b/packages/realm-server/tests/types-endpoint-test.ts @@ -3,7 +3,8 @@ import type { Test, SuperTest } from 'supertest'; import { join, basename } from 'path'; import type { RealmHttpServer as Server } from '../server.ts'; import type { DirResult } from 'tmp'; -import { copySync, ensureDirSync } from 'fs-extra'; +import fsExtra from 'fs-extra'; +const { copySync, ensureDirSync } = fsExtra; import type { Realm } from '@cardstack/runtime-common'; import type { QueuePublisher, QueueRunner } from '@cardstack/runtime-common'; import { @@ -24,7 +25,7 @@ import type { PgAdapter } from '@cardstack/postgres'; const testRealm2URL = new URL('http://127.0.0.1:4445/test/'); -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('Realm-specific Endpoints | GET _types', function (hooks) { let realmURL = new URL('http://127.0.0.1:4444/test/'); let testRealm: Realm; diff --git a/packages/realm-server/tests/unified-search-contracts-test.ts b/packages/realm-server/tests/unified-search-contracts-test.ts index 79a983207c..2449d116d2 100644 --- a/packages/realm-server/tests/unified-search-contracts-test.ts +++ b/packages/realm-server/tests/unified-search-contracts-test.ts @@ -105,7 +105,7 @@ function css( }; } -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('unified search contracts', function () { // --- predicates --------------------------------------------------------- diff --git a/packages/realm-server/tests/virtual-network-test.ts b/packages/realm-server/tests/virtual-network-test.ts index cd4a1fd402..6372125900 100644 --- a/packages/realm-server/tests/virtual-network-test.ts +++ b/packages/realm-server/tests/virtual-network-test.ts @@ -4,7 +4,7 @@ import { module, test } from 'qunit'; import { basename } from 'path'; import '../setup-logger.ts'; -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('virtual-network', function () { test('will respond with real (not virtual) url when handler makes a redirect', async function (assert) { let virtualNetwork = new VirtualNetwork(); diff --git a/packages/realm-server/utils/jwt.ts b/packages/realm-server/utils/jwt.ts index 4cb6ee6050..64716c094a 100644 --- a/packages/realm-server/utils/jwt.ts +++ b/packages/realm-server/utils/jwt.ts @@ -2,12 +2,8 @@ import { AuthenticationError, AuthenticationErrorMessages, } from '@cardstack/runtime-common/router'; -import { - JsonWebTokenError, - sign, - TokenExpiredError, - verify, -} from 'jsonwebtoken'; +import * as jsonwebtoken from 'jsonwebtoken'; +const { JsonWebTokenError, sign, TokenExpiredError, verify } = jsonwebtoken; export interface RealmServerTokenClaim { user: string; diff --git a/packages/realm-server/worker-manager.ts b/packages/realm-server/worker-manager.ts index 41b0c05ce1..20ab7ff93d 100644 --- a/packages/realm-server/worker-manager.ts +++ b/packages/realm-server/worker-manager.ts @@ -55,7 +55,7 @@ import { } from '@cardstack/runtime-common'; import yargs from 'yargs'; import * as Sentry from '@sentry/node'; -import flattenDeep from 'lodash/flattenDeep'; +import { flattenDeep } from 'lodash-es'; import { spawn, type ChildProcess } from 'child_process'; import pluralize from 'pluralize'; import Koa from 'koa'; @@ -822,10 +822,9 @@ async function startWorker( urlMappings: [URL | string, URL][], ) { let worker = spawn( - 'ts-node', + 'node', [ - '--transpileOnly', - 'worker', + 'worker.ts', `--matrixURL='${matrixURL}'`, `--prerendererUrl=${prerendererUrl}`, `--priority=${priority}`, diff --git a/packages/realm-test-harness/package.json b/packages/realm-test-harness/package.json index e90bec7432..5edb9d3e76 100644 --- a/packages/realm-test-harness/package.json +++ b/packages/realm-test-harness/package.json @@ -4,8 +4,14 @@ "version": "1.0.0", "license": "MIT", "description": "Spin up an isolated boxel realm-server stack (postgres + prerender + worker + realm-server) against a fixture realm directory. Used by integration tests, benchmarks, and CLI dev tools that need a hermetic realm.", + "type": "module", "main": "src/index.ts", "types": "src/index.ts", + "exports": { + ".": "./src/index.ts", + "./package.json": "./package.json", + "./*": "./src/*.ts" + }, "scripts": { "lint": "concurrently \"pnpm:lint:*(!fix)\" --names \"lint:\"", "lint:fix": "concurrently \"pnpm:lint:*:fix\" --names \"fix:\"", diff --git a/packages/realm-test-harness/src/isolated-realm-stack.ts b/packages/realm-test-harness/src/isolated-realm-stack.ts index 94a1e15114..a756ca88ec 100644 --- a/packages/realm-test-harness/src/isolated-realm-stack.ts +++ b/packages/realm-test-harness/src/isolated-realm-stack.ts @@ -840,8 +840,7 @@ export async function startIsolatedRealmStack({ }; let workerArgs = [ - '--transpileOnly', - 'worker-manager', + 'worker-manager.ts', `--port=${actualWorkerManagerPort}`, `--matrixURL=${context.matrixURL}`, `--prerendererUrl=${prerenderURL}`, @@ -893,7 +892,7 @@ export async function startIsolatedRealmStack({ attempt++; // Release the worker-manager port holder right before the child binds. await workerManagerPortInfo.releaseHolder(); - workerManager = spawn('ts-node', workerArgs, { + workerManager = spawn('node', workerArgs, { cwd: realmServerDir, env, stdio: managedProcessStdio, @@ -962,8 +961,7 @@ export async function startIsolatedRealmStack({ } let serverArgs = [ - '--transpileOnly', - 'main', + 'main.ts', `--port=${actualRealmServerPort}`, `--serverURL=${realmServerURL.href}`, `--matrixURL=${context.matrixURL}`, @@ -1013,7 +1011,7 @@ export async function startIsolatedRealmStack({ // Release the realm-server port holder right before the child binds. await realmServerPortInfo.releaseHolder(); let realmServerSpawnedAt = Date.now(); - let realmServer = spawn('ts-node', serverArgs, { + let realmServer = spawn('node', serverArgs, { cwd: realmServerDir, env, stdio: managedProcessStdio, diff --git a/packages/realm-test-harness/src/support-services.ts b/packages/realm-test-harness/src/support-services.ts index b3362fc1df..2a6d926e4f 100644 --- a/packages/realm-test-harness/src/support-services.ts +++ b/packages/realm-test-harness/src/support-services.ts @@ -644,8 +644,8 @@ async function attemptStartHarnessPrerenderServer(options: { await portReservation.release(); } let child = spawn( - 'ts-node', - ['--transpileOnly', 'prerender/prerender-server', `--port=${port}`], + 'node', + ['prerender/prerender-server.ts', `--port=${port}`], { cwd: realmServerDir, stdio: ['pipe', 'pipe', 'pipe'], diff --git a/packages/runtime-common/cached-fetch.ts b/packages/runtime-common/cached-fetch.ts index 1c1ff5f226..774e524749 100644 --- a/packages/runtime-common/cached-fetch.ts +++ b/packages/runtime-common/cached-fetch.ts @@ -1,4 +1,4 @@ -import merge from 'lodash/merge.js'; +import { merge } from 'lodash-es'; import { isNode } from './index.ts'; diff --git a/packages/runtime-common/catalog.ts b/packages/runtime-common/catalog.ts index 74ba448fdb..3263b0338b 100644 --- a/packages/runtime-common/catalog.ts +++ b/packages/runtime-common/catalog.ts @@ -1,6 +1,6 @@ -import isEqual from 'lodash/isEqual.js'; -import uniqWith from 'lodash/uniqWith.js'; -import kebabCase from 'lodash/kebabCase.js'; +import { isEqual } from 'lodash-es'; +import { uniqWith } from 'lodash-es'; +import { kebabCase } from 'lodash-es'; import { v4 as uuidv4 } from 'uuid'; import type { Spec } from 'https://cardstack.com/base/spec'; import type { CardDef } from 'https://cardstack.com/base/card-api'; diff --git a/packages/runtime-common/commands.ts b/packages/runtime-common/commands.ts index de79ce96c4..e5b86fa0e9 100644 --- a/packages/runtime-common/commands.ts +++ b/packages/runtime-common/commands.ts @@ -10,7 +10,7 @@ import type { CardDefConstructor } from 'https://cardstack.com/base/card-api'; import type { AttributesSchema, CardSchema } from './helpers/ai.ts'; import { generateJsonSchemaForCardType } from './helpers/ai.ts'; import { simpleHash } from './utils.ts'; -import type { EncodedCommandRequest } from '../base/matrix-event'; +import type { EncodedCommandRequest } from '../base/matrix-event.gts'; export interface CommandRequest { id: string; diff --git a/packages/runtime-common/expression.ts b/packages/runtime-common/expression.ts index a4bbe23dad..c2f0a56d56 100644 --- a/packages/runtime-common/expression.ts +++ b/packages/runtime-common/expression.ts @@ -1,7 +1,7 @@ import type * as JSONTypes from 'json-typescript'; -import isPlainObject from 'lodash/isPlainObject.js'; +import { isPlainObject } from 'lodash-es'; import stringify from 'safe-stable-stringify'; -import flattenDeep from 'lodash/flattenDeep.js'; +import { flattenDeep } from 'lodash-es'; import type { CodeRef, DBAdapter, TypeCoercion } from './index.ts'; diff --git a/packages/runtime-common/index-query-engine.ts b/packages/runtime-common/index-query-engine.ts index b1c8405ede..c505104fc3 100644 --- a/packages/runtime-common/index-query-engine.ts +++ b/packages/runtime-common/index-query-engine.ts @@ -1,5 +1,5 @@ import type * as JSONTypes from 'json-typescript'; -import flatten from 'lodash/flatten.js'; +import { flatten } from 'lodash-es'; import stringify from 'safe-stable-stringify'; import type { ResolvedCodeRef } from './index.ts'; import type { RealmResourceIdentifier } from './realm-identifiers.ts'; diff --git a/packages/runtime-common/index-runner/card-indexer.ts b/packages/runtime-common/index-runner/card-indexer.ts index 488701f073..4e4ff483d6 100644 --- a/packages/runtime-common/index-runner/card-indexer.ts +++ b/packages/runtime-common/index-runner/card-indexer.ts @@ -1,4 +1,4 @@ -import merge from 'lodash/merge.js'; +import { merge } from 'lodash-es'; import { jobIdentity, diff --git a/packages/runtime-common/index-writer.ts b/packages/runtime-common/index-writer.ts index 689a7c5782..04694ed667 100644 --- a/packages/runtime-common/index-writer.ts +++ b/packages/runtime-common/index-writer.ts @@ -1,5 +1,5 @@ -import flatten from 'lodash/flatten.js'; -import flattenDeep from 'lodash/flattenDeep.js'; +import { flatten } from 'lodash-es'; +import { flattenDeep } from 'lodash-es'; import { type CardResource, type JobInfo, diff --git a/packages/runtime-common/instance-filter-matcher.ts b/packages/runtime-common/instance-filter-matcher.ts index 7fcec99cad..9b707d0de8 100644 --- a/packages/runtime-common/instance-filter-matcher.ts +++ b/packages/runtime-common/instance-filter-matcher.ts @@ -1,4 +1,4 @@ -import isEqual from 'lodash/isEqual.js'; +import { isEqual } from 'lodash-es'; import { getField, identifyCard } from './code-ref.ts'; import { diff --git a/packages/runtime-common/jobs/indexing.ts b/packages/runtime-common/jobs/indexing.ts index 6cd7a11d19..abe0b73dc9 100644 --- a/packages/runtime-common/jobs/indexing.ts +++ b/packages/runtime-common/jobs/indexing.ts @@ -7,7 +7,7 @@ import type { } from '../tasks/indexer.ts'; import type { PgPrimitive } from '../expression.ts'; import { v4 as uuidv4 } from '@lukeed/uuid'; -import isObjectLike from 'lodash/isObjectLike.js'; +import { isObjectLike } from 'lodash-es'; export const INCREMENTAL_INDEX_JOB_TIMEOUT_SEC = 10 * 60; diff --git a/packages/runtime-common/loader.ts b/packages/runtime-common/loader.ts index 3528c9d92b..c1642f7df5 100644 --- a/packages/runtime-common/loader.ts +++ b/packages/runtime-common/loader.ts @@ -4,7 +4,7 @@ import { cachedFetch, type MaybeCachedResponse } from './cached-fetch.ts'; import { executableExtensions, logger } from './index.ts'; import { CardError, iconNotFoundMessage } from './error.ts'; -import flatMap from 'lodash/flatMap.js'; +import { flatMap } from 'lodash-es'; import { shouldTrackRuntimeModuleGraph, trackRuntimeModuleDependency, diff --git a/packages/runtime-common/merge-relationships.ts b/packages/runtime-common/merge-relationships.ts index e1f6af8a0d..2136af212a 100644 --- a/packages/runtime-common/merge-relationships.ts +++ b/packages/runtime-common/merge-relationships.ts @@ -1,6 +1,6 @@ import type { LooseCardResource, Relationship } from './index.ts'; import { relationshipEntries } from './relationship-utils.ts'; -import mergeWith from 'lodash/mergeWith.js'; +import { mergeWith } from 'lodash-es'; export function mergeRelationships( relData: LooseCardResource['relationships'], diff --git a/packages/runtime-common/module-syntax.ts b/packages/runtime-common/module-syntax.ts index 43b547187a..ff7ee2b29d 100644 --- a/packages/runtime-common/module-syntax.ts +++ b/packages/runtime-common/module-syntax.ts @@ -17,7 +17,7 @@ import type { Options as RemoveOptions } from './remove-field-plugin.ts'; import { removeFieldPlugin } from './remove-field-plugin.ts'; import { ImportUtil } from 'babel-import-util'; import camelCase from 'camelcase'; -import isEqual from 'lodash/isEqual.js'; +import { isEqual } from 'lodash-es'; import * as ContentTag from 'content-tag'; import { diff --git a/packages/runtime-common/package.json b/packages/runtime-common/package.json index 46f939d706..f1f8e47891 100644 --- a/packages/runtime-common/package.json +++ b/packages/runtime-common/package.json @@ -46,7 +46,7 @@ "@types/diff": "catalog:", "@types/eslint": "catalog:", "@types/flat": "catalog:", - "@types/lodash": "catalog:", + "@types/lodash-es": "catalog:", "@types/pluralize": "catalog:", "@types/qs": "catalog:", "@types/uuid": "catalog:", @@ -70,7 +70,7 @@ "ignore": "catalog:", "js-string-escape": "catalog:", "json-typescript": "catalog:", - "lodash": "catalog:", + "lodash-es": "catalog:", "loglevel": "catalog:", "magic-string": "catalog:", "marked": "catalog:", diff --git a/packages/runtime-common/query.ts b/packages/runtime-common/query.ts index a479f7ac1f..613a5691f7 100644 --- a/packages/runtime-common/query.ts +++ b/packages/runtime-common/query.ts @@ -1,4 +1,4 @@ -import isEqual from 'lodash/isEqual.js'; +import { isEqual } from 'lodash-es'; import { assertJSONValue, assertJSONPrimitive } from './json-validation.ts'; import qs from 'qs'; diff --git a/packages/runtime-common/realm-index-query-engine.ts b/packages/runtime-common/realm-index-query-engine.ts index 8d1ffc6610..7f4f2e3a0a 100644 --- a/packages/runtime-common/realm-index-query-engine.ts +++ b/packages/runtime-common/realm-index-query-engine.ts @@ -1,5 +1,5 @@ import { isScopedCSSRequest } from './scoped-css.ts'; -import cloneDeep from 'lodash/cloneDeep.js'; +import { cloneDeep } from 'lodash-es'; import { SupportedMimeType, isJsonContentType, diff --git a/packages/runtime-common/realm.ts b/packages/runtime-common/realm.ts index ee45d94e98..663444083e 100644 --- a/packages/runtime-common/realm.ts +++ b/packages/runtime-common/realm.ts @@ -107,11 +107,11 @@ import { } from './index.ts'; import type { FromScratchResult } from './tasks/indexer.ts'; import { isCodeRef, visitModuleDeps } from './code-ref.ts'; -import merge from 'lodash/merge.js'; -import mergeWith from 'lodash/mergeWith.js'; -import cloneDeep from 'lodash/cloneDeep.js'; -import isEqual from 'lodash/isEqual.js'; -import isPlainObject from 'lodash/isPlainObject.js'; +import { merge } from 'lodash-es'; +import { mergeWith } from 'lodash-es'; +import { cloneDeep } from 'lodash-es'; +import { isEqual } from 'lodash-es'; +import { isPlainObject } from 'lodash-es'; import { z } from 'zod'; import { inferContentType } from './infer-content-type.ts'; import { diff --git a/packages/runtime-common/tasks/lint.ts b/packages/runtime-common/tasks/lint.ts index fb20f0ea9d..91eff2f1b6 100644 --- a/packages/runtime-common/tasks/lint.ts +++ b/packages/runtime-common/tasks/lint.ts @@ -58,9 +58,9 @@ const MAX_FILE_SIZE_BYTES = 5 * 1024 * 1024; // --------------------------------------------------------------------------- // runtime-common lives at /packages/runtime-common; host is its sibling. -const HOST_PKG = resolve(__dirname, '..', '..', 'host'); +const HOST_PKG = resolve(import.meta.dirname, '..', '..', 'host'); const HOST_ESLINTRC = resolve(HOST_PKG, '.eslintrc.js'); -const REPO_ROOT = resolve(__dirname, '..', '..', '..'); +const REPO_ROOT = resolve(import.meta.dirname, '..', '..', '..'); const LINT_ANCHOR = resolve(HOST_PKG, '__realm__'); // pnpm doesn't hoist transitive deps, so parsers/plugins host references by diff --git a/packages/runtime-common/unified-search.ts b/packages/runtime-common/unified-search.ts index cdba6fc4ea..e12e3648a9 100644 --- a/packages/runtime-common/unified-search.ts +++ b/packages/runtime-common/unified-search.ts @@ -1,4 +1,4 @@ -import { isScopedCSSRequest } from './scoped-css'; +import { isScopedCSSRequest } from './scoped-css.ts'; import { cssResourceId, type CardResource, @@ -6,9 +6,9 @@ import { type FileMetaResource, type RenderedHtmlResource, type Saved, -} from './resource-types'; -import type { CodeRef } from './code-ref'; -import type { RealmResourceIdentifier } from './realm-identifiers'; +} from './resource-types.ts'; +import type { CodeRef } from './code-ref.ts'; +import type { RealmResourceIdentifier } from './realm-identifiers.ts'; // Builders for the unified-search resources. The realm-server's result mapper // runs these per row when applying the prefer-HTML resolution policy; keeping diff --git a/packages/software-factory/package.json b/packages/software-factory/package.json index f8aa4b4f2a..de7bae1574 100644 --- a/packages/software-factory/package.json +++ b/packages/software-factory/package.json @@ -5,14 +5,14 @@ "license": "MIT", "description": "Software Factory workspace package", "scripts": { - "boxel:search": "NODE_NO_WARNINGS=1 ts-node --transpileOnly scripts/boxel-search.ts", - "cache:prepare": "NODE_NO_WARNINGS=1 ts-node --transpileOnly src/cli/cache-realm.ts", - "factory:go": "NODE_NO_WARNINGS=1 ts-node --transpileOnly src/cli/factory-entrypoint.ts", - "smoke:context": "NODE_NO_WARNINGS=1 ts-node --transpileOnly scripts/smoke-tests/factory-context-smoke.ts", - "smoke:prompt": "NODE_NO_WARNINGS=1 ts-node --transpileOnly scripts/smoke-tests/factory-prompt-smoke.ts", - "smoke:skill": "NODE_NO_WARNINGS=1 ts-node --transpileOnly scripts/smoke-tests/factory-skill-smoke.ts", - "smoke:issue-loop": "NODE_NO_WARNINGS=1 ts-node --transpileOnly scripts/smoke-tests/issue-loop-smoke.ts", - "smoke:tools": "NODE_NO_WARNINGS=1 ts-node --transpileOnly scripts/smoke-tests/factory-tools-smoke.ts", + "boxel:search": "NODE_NO_WARNINGS=1 node scripts/boxel-search.ts", + "cache:prepare": "NODE_NO_WARNINGS=1 node src/cli/cache-realm.ts", + "factory:go": "NODE_NO_WARNINGS=1 node src/cli/factory-entrypoint.ts", + "smoke:context": "NODE_NO_WARNINGS=1 node scripts/smoke-tests/factory-context-smoke.ts", + "smoke:prompt": "NODE_NO_WARNINGS=1 node scripts/smoke-tests/factory-prompt-smoke.ts", + "smoke:skill": "NODE_NO_WARNINGS=1 node scripts/smoke-tests/factory-skill-smoke.ts", + "smoke:issue-loop": "NODE_NO_WARNINGS=1 node scripts/smoke-tests/issue-loop-smoke.ts", + "smoke:tools": "NODE_NO_WARNINGS=1 node scripts/smoke-tests/factory-tools-smoke.ts", "lint": "concurrently \"pnpm:lint:*(!fix)\" --names \"lint:\"", "lint:fix": "concurrently \"pnpm:lint:*:fix\" --names \"fix:\"", "lint:js": "eslint . --report-unused-disable-directives --cache", @@ -20,17 +20,17 @@ "lint:format": "prettier --check .", "lint:format:fix": "prettier --write .", "lint:types": "ember-tsc --noEmit", - "serve:realm": "NODE_NO_WARNINGS=1 ts-node --transpileOnly src/cli/serve-realm.ts", - "serve:support": "NODE_NO_WARNINGS=1 ts-node --transpileOnly src/cli/serve-support.ts", - "smoke:factory-scenarios": "NODE_NO_WARNINGS=1 ts-node --transpileOnly scripts/smoke-tests/smoke-test-factory-scenarios.ts", - "smoke:test-realm": "NODE_NO_WARNINGS=1 ts-node --transpileOnly scripts/smoke-tests/smoke-test-realm.ts", - "test": "NODE_NO_WARNINGS=1 ts-node --transpileOnly scripts/test.ts", - "test:all": "NODE_NO_WARNINGS=1 ts-node --transpileOnly scripts/test.ts", - "test:node": "NODE_NO_WARNINGS=1 ts-node --transpileOnly scripts/test.ts --node-only", + "serve:realm": "NODE_NO_WARNINGS=1 node src/cli/serve-realm.ts", + "serve:support": "NODE_NO_WARNINGS=1 node src/cli/serve-support.ts", + "smoke:factory-scenarios": "NODE_NO_WARNINGS=1 node scripts/smoke-tests/smoke-test-factory-scenarios.ts", + "smoke:test-realm": "NODE_NO_WARNINGS=1 node scripts/smoke-tests/smoke-test-realm.ts", + "test": "NODE_NO_WARNINGS=1 node scripts/test.ts", + "test:all": "NODE_NO_WARNINGS=1 node scripts/test.ts", + "test:node": "NODE_NO_WARNINGS=1 node scripts/test.ts --node-only", "test:playwright": "playwright test", "test:playwright:headed": "playwright test --headed", "test:playwright:shard": "playwright test --shard", - "test:realm": "NODE_NO_WARNINGS=1 ts-node --transpileOnly scripts/run-realm-tests.ts" + "test:realm": "NODE_NO_WARNINGS=1 node scripts/run-realm-tests.ts" }, "devDependencies": { "@anthropic-ai/claude-agent-sdk": "^0.2.114", diff --git a/packages/software-factory/playwright.global-setup.ts b/packages/software-factory/playwright.global-setup.ts index 3f9f88298c..786c442b38 100644 --- a/packages/software-factory/playwright.global-setup.ts +++ b/packages/software-factory/playwright.global-setup.ts @@ -10,8 +10,8 @@ import { type PreparedTemplateMetadata, } from '@cardstack/realm-test-harness'; -const packageRoot = resolve(__dirname); -const tsNodeBin = resolve(packageRoot, 'node_modules', '.bin', 'ts-node'); +const packageRoot = resolve(import.meta.dirname); +const nodeBin = process.execPath; const configuredRealmDir = resolve( packageRoot, process.env.TEST_HARNESS_REALM_DIR ?? 'test-fixtures/darkfactory-adopter', @@ -258,20 +258,16 @@ export default async function globalSetup() { supportLog.debug(`starting serve:support for realm ${realmDir}`); let logs = ''; - let child = spawn( - tsNodeBin, - ['--transpileOnly', 'src/cli/serve-support.ts', realmDir], - { - cwd: packageRoot, - detached: true, - stdio: ['ignore', 'pipe', 'pipe'], - env: { - ...process.env, - NODE_NO_WARNINGS: '1', - TEST_HARNESS_SUPPORT_METADATA_FILE: metadataFile, - }, + let child = spawn(nodeBin, ['src/cli/serve-support.ts', realmDir], { + cwd: packageRoot, + detached: true, + stdio: ['ignore', 'pipe', 'pipe'], + env: { + ...process.env, + NODE_NO_WARNINGS: '1', + TEST_HARNESS_SUPPORT_METADATA_FILE: metadataFile, }, - ); + }); mirrorChildOutput( child, diff --git a/packages/software-factory/scripts/smoke-tests/smoke-test-factory-scenarios.ts b/packages/software-factory/scripts/smoke-tests/smoke-test-factory-scenarios.ts index b15b1aa375..21eba62c55 100644 --- a/packages/software-factory/scripts/smoke-tests/smoke-test-factory-scenarios.ts +++ b/packages/software-factory/scripts/smoke-tests/smoke-test-factory-scenarios.ts @@ -39,7 +39,7 @@ import { logger } from '../../src/logger.ts'; // --------------------------------------------------------------------------- let log = logger('smoke-factory-scenarios'); -let packageRoot = resolve(__dirname, '../..'); +let packageRoot = resolve(import.meta.dirname, '../..'); const DEFAULT_BRIEF_URL = 'http://localhost:4201/software-factory/Wiki/sticky-note'; diff --git a/packages/software-factory/scripts/test.ts b/packages/software-factory/scripts/test.ts index 39d5b10f34..a14154374c 100644 --- a/packages/software-factory/scripts/test.ts +++ b/packages/software-factory/scripts/test.ts @@ -6,7 +6,7 @@ configureLogger(process.env.LOG_LEVELS || '*=error'); let log = logger('test'); -const packageRoot = resolve(__dirname, '..'); +const packageRoot = resolve(import.meta.dirname, '..'); type TestRunnerOptions = { nodeOnly: boolean; diff --git a/packages/software-factory/src/cli/serve-realm.ts b/packages/software-factory/src/cli/serve-realm.ts index 1cd5f87502..3190b66b57 100644 --- a/packages/software-factory/src/cli/serve-realm.ts +++ b/packages/software-factory/src/cli/serve-realm.ts @@ -39,7 +39,7 @@ function cardDefinitionsOnly(relativePath: string): boolean { return included; } -const sfSourceRealmDir = resolve(__dirname, '..', '..', 'realm'); +const sfSourceRealmDir = resolve(import.meta.dirname, '..', '..', 'realm'); function parseCliArg(name: string): string | undefined { let prefix = `--${name}=`; diff --git a/packages/software-factory/src/factory-issue-loop-wiring.ts b/packages/software-factory/src/factory-issue-loop-wiring.ts index b5cecd92fa..8eb3eb9b00 100644 --- a/packages/software-factory/src/factory-issue-loop-wiring.ts +++ b/packages/software-factory/src/factory-issue-loop-wiring.ts @@ -52,7 +52,7 @@ import { withStdoutRedirected } from './redirect-stdout.ts'; let log = logger('factory-issue-loop-wiring'); -const PACKAGE_ROOT = resolve(__dirname, '..'); +const PACKAGE_ROOT = resolve(import.meta.dirname, '..'); // --------------------------------------------------------------------------- // Types diff --git a/packages/software-factory/src/factory-prompt-loader.ts b/packages/software-factory/src/factory-prompt-loader.ts index fc0afe5a08..cc3d0b7ea3 100644 --- a/packages/software-factory/src/factory-prompt-loader.ts +++ b/packages/software-factory/src/factory-prompt-loader.ts @@ -14,7 +14,7 @@ import type { // Constants // --------------------------------------------------------------------------- -const PROMPTS_DIR = resolve(__dirname, '../prompts'); +const PROMPTS_DIR = resolve(import.meta.dirname, '../prompts'); // --------------------------------------------------------------------------- // PromptLoader diff --git a/packages/software-factory/src/factory-skill-loader.ts b/packages/software-factory/src/factory-skill-loader.ts index fc524267f3..73b996c19c 100644 --- a/packages/software-factory/src/factory-skill-loader.ts +++ b/packages/software-factory/src/factory-skill-loader.ts @@ -14,7 +14,7 @@ const log = logger('factory-skill-loader'); // Constants // --------------------------------------------------------------------------- -const PACKAGE_ROOT = resolve(__dirname, '..'); +const PACKAGE_ROOT = resolve(import.meta.dirname, '..'); const MONOREPO_ROOT = resolve(PACKAGE_ROOT, '../..'); /** * The SDK orchestrator and the new interactive Claude Code path each get diff --git a/packages/software-factory/src/parse-execution.ts b/packages/software-factory/src/parse-execution.ts index e92130a494..1c4688df22 100644 --- a/packages/software-factory/src/parse-execution.ts +++ b/packages/software-factory/src/parse-execution.ts @@ -61,7 +61,7 @@ export const PARSEABLE_JSON_EXTENSION = '.json'; * `packages/software-factory`, alongside `packages/base`, * `packages/host`, and `packages/boxel-ui`. */ -const PACKAGES_PATH = resolve(__dirname, '..', '..'); +const PACKAGES_PATH = resolve(import.meta.dirname, '..', '..'); const BASE_PKG_PATH = join(PACKAGES_PATH, 'base'); const HOST_PKG_PATH = join(PACKAGES_PATH, 'host'); @@ -650,7 +650,7 @@ export async function runGlintCheck( symlinkSync(NODE_MODULES_PATH, join(tempDir, 'node_modules')); let emberTscBin = resolve( - __dirname, + import.meta.dirname, '..', 'node_modules', '.bin', diff --git a/packages/software-factory/tests/factory-brief.test.ts b/packages/software-factory/tests/factory-brief.test.ts index 20f1c82cd7..fd0df0e7b7 100644 --- a/packages/software-factory/tests/factory-brief.test.ts +++ b/packages/software-factory/tests/factory-brief.test.ts @@ -12,12 +12,15 @@ import { } from '../src/factory-brief.ts'; const stickyNoteFixture = JSON.parse( - readFileSync(resolve(__dirname, '../realm/Wiki/sticky-note.json'), 'utf8'), + readFileSync( + resolve(import.meta.dirname, '../realm/Wiki/sticky-note.json'), + 'utf8', + ), ) as unknown; const darkfactoryIssueFixture = JSON.parse( readFileSync( resolve( - __dirname, + import.meta.dirname, '../test-fixtures/darkfactory-adopter/Issues/issue-001.json', ), 'utf8', diff --git a/packages/software-factory/tests/factory-entrypoint.integration.test.ts b/packages/software-factory/tests/factory-entrypoint.integration.test.ts index 69243c347b..5fbf91ab9e 100644 --- a/packages/software-factory/tests/factory-entrypoint.integration.test.ts +++ b/packages/software-factory/tests/factory-entrypoint.integration.test.ts @@ -13,9 +13,9 @@ import { module, test } from 'qunit'; import { SupportedMimeType } from '@cardstack/runtime-common/supported-mime-type'; -const packageRoot = resolve(__dirname, '..'); +const packageRoot = resolve(import.meta.dirname, '..'); const stickyNoteFixture = readFileSync( - resolve(__dirname, '../realm/Wiki/sticky-note.json'), + resolve(import.meta.dirname, '../realm/Wiki/sticky-note.json'), 'utf8', ); diff --git a/packages/software-factory/tests/fixtures.ts b/packages/software-factory/tests/fixtures.ts index 37c31ace6f..0bed0bac99 100644 --- a/packages/software-factory/tests/fixtures.ts +++ b/packages/software-factory/tests/fixtures.ts @@ -90,7 +90,7 @@ type SharedRealmHandle = { }; const packageRoot = resolve(process.cwd()); -const tsNodeBin = resolve(packageRoot, 'node_modules', '.bin', 'ts-node'); +const nodeBin = process.execPath; const defaultRealmDir = resolve( packageRoot, process.env.TEST_HARNESS_REALM_DIR ?? 'test-fixtures/darkfactory-adopter', @@ -278,9 +278,8 @@ async function startRealmProcess( }; try { child = spawn( - tsNodeBin, + nodeBin, [ - '--transpileOnly', 'src/cli/serve-realm.ts', realmDir, `--compatRealmServerPort=${testWorkerPortSet.compatRealmServerPort}`, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4c1aa64c65..f21f709e3a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -216,6 +216,9 @@ catalogs: '@types/lodash': specifier: ^4.17.15 version: 4.17.24 + '@types/lodash-es': + specifier: ^4.17.12 + version: 4.17.12 '@types/matrix-js-sdk': specifier: ^11.0.1 version: 11.1.0 @@ -513,6 +516,9 @@ catalogs: lodash: specifier: ^4.17.21 version: 4.18.1 + lodash-es: + specifier: ^4.17.21 + version: 4.18.1 loglevel: specifier: ^1.8.1 version: 1.9.2 @@ -808,9 +814,9 @@ importers: '@sentry/node': specifier: 'catalog:' version: 8.55.2 - '@types/lodash': + '@types/lodash-es': specifier: 'catalog:' - version: 4.17.24 + version: 4.17.12 '@types/node': specifier: 'catalog:' version: 24.12.4 @@ -823,7 +829,7 @@ importers: debug: specifier: ^4.4.3 version: 4.4.3(supports-color@8.1.1) - lodash: + lodash-es: specifier: 'catalog:' version: 4.18.1 matrix-js-sdk: @@ -918,9 +924,9 @@ importers: '@types/flat': specifier: 'catalog:' version: 5.0.5 - '@types/lodash': + '@types/lodash-es': specifier: 'catalog:' - version: 4.17.24 + version: 4.17.12 awesome-phonenumber: specifier: 'catalog:' version: 7.8.0 @@ -1737,9 +1743,9 @@ importers: '@glint/template': specifier: 'catalog:' version: 1.7.7 - '@types/lodash': + '@types/lodash-es': specifier: 'catalog:' - version: 4.17.24 + version: 4.17.12 '@types/qunit': specifier: 'catalog:' version: 2.19.14 @@ -1788,7 +1794,7 @@ importers: eslint-plugin-prettier: specifier: 'catalog:' version: 5.5.5(@types/eslint@8.56.5)(eslint-config-prettier@9.1.2(eslint@8.57.1))(eslint@8.57.1)(prettier@3.8.3) - lodash: + lodash-es: specifier: 'catalog:' version: 4.18.1 prettier: @@ -1920,9 +1926,9 @@ importers: '@ember/test-helpers': specifier: 'catalog:' version: 5.4.2(@babel/core@7.29.0)(@glint/template@1.7.7) - '@types/lodash': + '@types/lodash-es': specifier: 'catalog:' - version: 4.17.24 + version: 4.17.12 '@types/qunit': specifier: 'catalog:' version: 2.19.14 @@ -2110,9 +2116,9 @@ importers: '@types/indefinite': specifier: 'catalog:' version: 2.3.4 - '@types/lodash': + '@types/lodash-es': specifier: 'catalog:' - version: 4.17.24 + version: 4.17.12 '@types/matrix-js-sdk': specifier: 'catalog:' version: 11.1.0 @@ -2344,7 +2350,7 @@ importers: katex: specifier: 'catalog:' version: 0.16.45 - lodash: + lodash-es: specifier: 'catalog:' version: 4.18.1 loglevel: @@ -2663,9 +2669,9 @@ importers: '@types/koa__router': specifier: 'catalog:' version: 12.0.5 - '@types/lodash': + '@types/lodash-es': specifier: 'catalog:' - version: 4.17.24 + version: 4.17.12 '@types/mime-types': specifier: 'catalog:' version: 2.1.4 @@ -2771,7 +2777,7 @@ importers: koa-proxies: specifier: 'catalog:' version: 0.12.4(koa@2.16.4) - lodash: + lodash-es: specifier: 'catalog:' version: 4.18.1 loglevel: @@ -2972,9 +2978,9 @@ importers: '@types/flat': specifier: 'catalog:' version: 5.0.5 - '@types/lodash': + '@types/lodash-es': specifier: 'catalog:' - version: 4.17.24 + version: 4.17.12 '@types/pluralize': specifier: 'catalog:' version: 0.0.30 @@ -3044,7 +3050,7 @@ importers: json-typescript: specifier: 'catalog:' version: 1.1.2 - lodash: + lodash-es: specifier: 'catalog:' version: 4.18.1 loglevel: @@ -6915,6 +6921,9 @@ packages: '@types/koa__router@12.0.5': resolution: {integrity: sha512-1HeLxuDn4n5it1yZYCSyOYXo++73zT0ffoviXnPxbwbxLbvDFEvWD9ZzpRiIpK4oKR0pi+K+Mk/ZjyROjW3HSw==} + '@types/lodash-es@4.17.12': + resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==} + '@types/lodash@4.17.24': resolution: {integrity: sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==} @@ -20147,6 +20156,10 @@ snapshots: dependencies: '@types/koa': 2.15.0 + '@types/lodash-es@4.17.12': + dependencies: + '@types/lodash': 4.17.24 + '@types/lodash@4.17.24': {} '@types/luxon@3.4.2': {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index fef2c83dfc..6a844d47d3 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -80,6 +80,7 @@ catalog: "@types/koa__router": ^12.0.0 "@types/line-column": ^1.0.0 "@types/lodash": ^4.17.15 + "@types/lodash-es": ^4.17.12 "@types/matrix-js-sdk": ^11.0.1 "@types/mime-types": ^2.1.1 "@types/ms": ^2.1.0 @@ -183,6 +184,7 @@ catalog: line-column: ^1.0.2 loader.js: ^4.7.0 lodash: ^4.17.21 + lodash-es: ^4.17.21 loglevel: ^1.8.1 lucide-static: ^0.447.0 macro-decorators: ^0.1.2 diff --git a/scripts/esm-codemod/README.md b/scripts/esm-codemod/README.md new file mode 100644 index 0000000000..fbc05b77c4 --- /dev/null +++ b/scripts/esm-codemod/README.md @@ -0,0 +1,89 @@ +# CS-11449 — ts-node → native-Node ESM codemod + +Tooling for migrating the **node-run package cluster** off `ts-node` and onto +native Node (≥24) TypeScript execution (type-stripping). Native Node ESM is far +stricter than ts-node / Vite about module resolution, so the swap surfaces a +predictable set of breakages. This directory automates the mechanical ones. + +The host (Vite/Embroider) build **masks** every error below — a green host build +does not mean a package is node-loadable. Verify by actually `import()`-ing the +entry under native node. + +## Usage + +```sh +# Apply all automated rules across the cluster (idempotent): +node scripts/esm-codemod/run.mjs + +# Preview without writing: +node scripts/esm-codemod/run.mjs --dry +``` + +Individual rules can be run on specific files, e.g. +`node scripts/esm-codemod/lodash-to-lodash-es.mjs ...`. + +## The node-run cluster + +Packages Node executes directly (NOT bundled by Vite): +`runtime-common`, `postgres`, `billing`, `realm-server`, `realm-test-harness`, +`ai-bot`, `bot-runner`, `matrix`, `software-factory`. + +## Error taxonomy + +Each error was found by `import()`-ing a service entry under native node and +reading the first failure, then fixing and repeating. Classes marked +**automated** are handled by `run.mjs`; **manual** ones are listed in the next +section. + +| # | Symptom | Cause | Fix | | +| --- | ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | +| 1 | `ERR_MODULE_NOT_FOUND` resolving a relative import `./foo` | Node does no extension search or directory-index resolution | append `./foo.ts` / `./foo.gts` / `./foo/index.ts`; bare `'.'` → `'./index.ts'` | automated (`add-relative-extensions`) | +| 2 | `ERR_MODULE_NOT_FOUND` resolving a workspace pkg subpath (`@cardstack/billing/x`) | workspace package has no `exports` map → Node looks for `index.js` | add an `exports` map pointing at `.ts` + `"type":"module"` | **manual** | +| 3 | `Cannot find module '.../lodash/merge'` (`Did you mean lodash/merge.js?`) | `lodash` is CJS-only with no exports map | repo-wide switch to `lodash-es` named imports | automated (`lodash-to-lodash-es`) | +| 4 | `does not provide an export named 'X'` from a CJS pkg (`fs-extra`, `debug`) | Node can't statically read named exports from these CJS modules | default-import + destructure | automated (`cjs-named-to-default`) — extend `CJS_PACKAGES` as new ones surface | +| 5 | `ERR_MODULE_NOT_FOUND` on a CJS pkg deep import (`matrix-js-sdk/lib/x`) | no exports map; ESM won't add `.js` or pick a file over a same-named dir | append `.js` | **manual** (small, package-specific) | +| 6 | `Cannot find module '.../scripts/x.js'` | a stray CJS file was renamed `.cjs` (because the pkg is now `type:module`) but the import still says `.js` | update the import to `.cjs` | **manual** | +| 7 | `ReferenceError: __dirname is not defined` | CJS globals don't exist under ESM | `import.meta.dirname` / `import.meta.filename` | automated (`dirname-to-import-meta`) | +| 8 | wrong path built from `import.meta.url` | `import.meta.url` is a `file://` URL string, not a path | use `import.meta.dirname` | **manual** (rare — was a WIP bug) | +| 9 | `ReferenceError: exports is not defined` when a consumer runs the dep via `ts-node` | once a dep ships an `exports` map Node handles its `.ts` natively, colliding with a still-`ts-node` consumer | the dep + all its node-run consumers must drop ts-node in the same change (big-bang) | **manual** (coordination) | +| 10 | in-source `spawn('ts-node', ['--transpileOnly', 'entry', …])` | child processes also need native node | `spawn('node', ['entry.ts', …])` (or `process.execPath`) | **manual** (few sites, varied shapes) | + +### Invocation sites (automated — `ts-node-to-node`) + +`ts-node --transpileOnly ` → `node .ts` in `package.json` scripts, +`*.sh`, and `mise-tasks`. The extensionless entry must gain `.ts` because Node +does no extension search for the CLI entry point. Handles shell line-continuation +(`exec ts-node \`↵`--transpileOnly main`). Skips (and reports) two forms it can't +safely rewrite: `qunit --require ts-node/register/transpile-only …` and inline +`ts-node … -e/--eval …`. + +## Not automated — do by hand + +These are too package-specific or too coupled for a blind codemod: + +1. **`exports` maps + `"type":"module"`** per workspace package (class #2). Each + map mirrors that package's directory layout. A wildcard + `"./*":["./*.ts","./*/index.ts"]` does **not** work — Node exports won't fall + through on file-not-found, so add an explicit entry per directory-index + subpath. Never set `--preserve-symlinks` (it breaks type-stripping for + pnpm-symlinked workspace deps, which only works because Node resolves to + realpath outside `node_modules` first). +2. **The qunit test-runner bootstrap.** `qunit --require ts-node/register` has no + node equivalent; each test package needs a `node tests/index.ts`-style + bootstrap that installs the `QUnit` global, a TAP reporter, `QUnit.start()`, + and a failure-based exit code. Affects `ai-bot`, `bot-runner`, `realm-server` + (via `run-qunit-with-test-pg.sh` / `measure-test-file.sh`), `software-factory`. +3. **Remove the `ts-node` devDependency** from each package once its test runner + is converted. +4. **CJS deep imports** needing `.js` (class #5) and **`.cjs` import path fixes** + (class #6) — verify against the actual file on disk. + +## Verifying a package loads + +```sh +cd packages/realm-server +node --eval 'import("./main.ts").then(()=>process.exit(0)).catch(e=>{console.error(e);process.exit(1)})' +``` + +Reaching a runtime error (e.g. "REALM_SERVER_SECRET_SEED not set") means the full +module graph linked — the migration succeeded for that entry. diff --git a/scripts/esm-codemod/add-relative-extensions.mjs b/scripts/esm-codemod/add-relative-extensions.mjs new file mode 100644 index 0000000000..0c778049aa --- /dev/null +++ b/scripts/esm-codemod/add-relative-extensions.mjs @@ -0,0 +1,82 @@ +#!/usr/bin/env node +// Adds explicit extensions to relative imports/exports so native Node ESM can +// resolve them (Node does NOT do extension search or directory-index resolution). +// +// import x from './foo' -> './foo.ts' (foo.ts exists) +// import x from './foo' -> './foo.gts' (foo.gts exists) +// import x from './foo' -> './foo/index.ts' (foo/ is a dir with index) +// import x from '.' -> './index.ts' +// export * from './bar' -> './bar.ts' +// +// Leaves alone: specifiers that already have a known extension, bare/package +// specifiers, and relative specifiers that resolve to nothing (reported). +// +// Usage: node add-relative-extensions.mjs ... (edits in place) +import { readFileSync, writeFileSync, existsSync, statSync } from 'node:fs'; +import { dirname, resolve } from 'node:path'; + +const KNOWN_EXT = + /\.(ts|tsx|mts|cts|gts|js|mjs|cjs|gjs|json|css|wasm|node|d\.ts)$/; +// Resolution order matters: prefer source over compiled, ts over gts. +const FILE_EXTS = ['.ts', '.gts', '.tsx', '.js', '.mjs', '.cjs', '.gjs']; +const INDEX_EXTS = FILE_EXTS; + +// Matches the specifier in import/export ... from '...' and bare import '...'. +const FROM = + /(\bfrom\s*|\bimport\s*|\bexport\s*\*\s*from\s*)(['"])(\.[^'"]*)\2/g; + +function resolveSpecifier(fromFile, spec) { + const base = resolve(dirname(fromFile), spec); + // Already a file with an extension we trust. + if (KNOWN_EXT.test(spec)) return null; + // Direct file match by appending an extension. + for (const ext of FILE_EXTS) { + if (existsSync(base + ext)) return spec + ext; + } + // Directory index. + if (existsSync(base) && statSync(base).isDirectory()) { + for (const ext of INDEX_EXTS) { + if (existsSync(resolve(base, 'index' + ext))) { + return (spec.endsWith('/') ? spec.slice(0, -1) : spec) + '/index' + ext; + } + } + } + return undefined; // unresolved +} + +export function transform(fromFile, src) { + const unresolved = []; + let changed = false; + const code = src.replace(FROM, (full, kw, q, spec) => { + const out = resolveSpecifier(fromFile, spec); + if (out === null) return full; // already extensioned + if (out === undefined) { + unresolved.push(spec); + return full; + } + changed = true; + return `${kw}${q}${out}${q}`; + }); + return { code, changed, unresolved }; +} + +if (import.meta.url === `file://${process.argv[1]}`) { + let count = 0; + const allUnresolved = []; + for (const file of process.argv.slice(2)) { + const { code, changed, unresolved } = transform( + file, + readFileSync(file, 'utf8'), + ); + if (changed) { + writeFileSync(file, code); + count++; + } + for (const u of unresolved) allUnresolved.push(`${file}: ${u}`); + } + console.log(`relative-extensions: ${count} file(s) changed`); + if (allUnresolved.length) { + console.log(`\nUNRESOLVED (${allUnresolved.length}):`); + for (const u of allUnresolved) console.log(' ' + u); + } +} diff --git a/scripts/esm-codemod/cjs-named-to-default.mjs b/scripts/esm-codemod/cjs-named-to-default.mjs new file mode 100644 index 0000000000..fa5dc958de --- /dev/null +++ b/scripts/esm-codemod/cjs-named-to-default.mjs @@ -0,0 +1,62 @@ +#!/usr/bin/env node +// Converts named imports from CommonJS packages that Node's static analyzer +// can't read named exports from, into default-import + destructure. +// +// import { ensureDir, copy as cp } from 'fs-extra'; +// becomes +// import fsExtra from 'fs-extra'; +// const { ensureDir, copy: cp } = fsExtra; +// +// Works under both native Node ESM (default export is module.exports) and Vite. +// +// Usage: node cjs-named-to-default.mjs ... (edits in place) +import { readFileSync, writeFileSync } from 'node:fs'; + +// Packages whose named exports Node cannot statically detect. +export const CJS_PACKAGES = { + 'fs-extra': 'fsExtra', + debug: 'createDebug', +}; + +function varName(pkg) { + if (CJS_PACKAGES[pkg]) return CJS_PACKAGES[pkg]; + return pkg.replace(/[^a-zA-Z0-9]+(.)/g, (_, c) => c.toUpperCase()); +} + +export function transform(src) { + let changed = false; + let code = src; + for (const pkg of Object.keys(CJS_PACKAGES)) { + const re = new RegExp( + `import\\s*\\{([^}]*)\\}\\s*from\\s*(['"])${pkg.replace(/[/\\^$*+?.()|[\]{}]/g, '\\$&')}\\2;?`, + 'g', + ); + code = code.replace(re, (_full, names) => { + const local = varName(pkg); + const destructure = names + .split(',') + .map((s) => s.trim()) + .filter(Boolean) + .map((s) => { + const m = s.match(/^(\w+)\s+as\s+(\w+)$/); + return m ? `${m[1]}: ${m[2]}` : s; + }) + .join(', '); + changed = true; + return `import ${local} from '${pkg}';\nconst { ${destructure} } = ${local};`; + }); + } + return { code, changed }; +} + +if (import.meta.url === `file://${process.argv[1]}`) { + let count = 0; + for (const file of process.argv.slice(2)) { + const { code, changed } = transform(readFileSync(file, 'utf8')); + if (changed) { + writeFileSync(file, code); + count++; + } + } + console.log(`cjs-named-to-default: ${count} file(s) changed`); +} diff --git a/scripts/esm-codemod/dirname-to-import-meta.mjs b/scripts/esm-codemod/dirname-to-import-meta.mjs new file mode 100644 index 0000000000..eb8545a6ab --- /dev/null +++ b/scripts/esm-codemod/dirname-to-import-meta.mjs @@ -0,0 +1,41 @@ +#!/usr/bin/env node +// Replaces CommonJS `__dirname` / `__filename` with their ESM equivalents. +// Node >=20.11 exposes `import.meta.dirname` and `import.meta.filename`; under +// ESM the bare `__dirname` / `__filename` globals are undefined (ReferenceError). +// +// path.resolve(__dirname, '..') -> path.resolve(import.meta.dirname, '..') +// basename(__filename) -> basename(import.meta.filename) +// createRequire(__filename) -> createRequire(import.meta.filename) +// +// Apply ONLY to ESM source (.ts/.mts/.gts). Never run it on .cjs/.js CommonJS +// files, where these globals are legitimately defined. +// +// Usage: node dirname-to-import-meta.mjs ... (edits in place) +import { readFileSync, writeFileSync } from 'node:fs'; + +export function transform(src) { + let changed = false; + let code = src + .replace(/\b__dirname\b/g, () => { + changed = true; + return 'import.meta.dirname'; + }) + .replace(/\b__filename\b/g, () => { + changed = true; + return 'import.meta.filename'; + }); + return { code, changed }; +} + +if (import.meta.url === `file://${process.argv[1]}`) { + let count = 0; + for (const file of process.argv.slice(2)) { + if (/\.(cjs|js)$/.test(file)) continue; // never touch CommonJS files + const { code, changed } = transform(readFileSync(file, 'utf8')); + if (changed) { + writeFileSync(file, code); + count++; + } + } + console.log(`dirname-to-import-meta: ${count} file(s) changed`); +} diff --git a/scripts/esm-codemod/lodash-to-lodash-es.mjs b/scripts/esm-codemod/lodash-to-lodash-es.mjs new file mode 100644 index 0000000000..ec5613c12b --- /dev/null +++ b/scripts/esm-codemod/lodash-to-lodash-es.mjs @@ -0,0 +1,47 @@ +#!/usr/bin/env node +// Rewrites lodash imports to lodash-es (native ESM, named exports). +// +// import merge from 'lodash/merge' -> import { merge } from 'lodash-es' +// import merge from 'lodash/merge.js' -> import { merge } from 'lodash-es' +// import foo from 'lodash/merge' -> import { merge as foo } from 'lodash-es' +// import { a, b } from 'lodash' -> import { a, b } from 'lodash-es' +// import * as _ from 'lodash' -> import * as _ from 'lodash-es' +// +// Usage: node lodash-to-lodash-es.mjs ... (edits in place) +import { readFileSync, writeFileSync } from 'node:fs'; + +const SUBPATH = + /^(\s*)import\s+(\w+)\s+from\s+['"]lodash\/([\w]+)(?:\.js)?['"];?\s*$/; +const BARE = /from\s+(['"])lodash\1/g; + +export function transform(src) { + let changed = false; + const lines = src.split('\n').map((line) => { + const m = line.match(SUBPATH); + if (m) { + const [, indent, binding, method] = m; + const spec = binding === method ? method : `${method} as ${binding}`; + changed = true; + return `${indent}import { ${spec} } from 'lodash-es';`; + } + if (BARE.test(line)) { + changed = true; + return line.replace(BARE, 'from $1lodash-es$1'); + } + return line; + }); + return { code: lines.join('\n'), changed }; +} + +if (import.meta.url === `file://${process.argv[1]}`) { + let count = 0; + for (const file of process.argv.slice(2)) { + const { code, changed } = transform(readFileSync(file, 'utf8')); + if (changed) { + writeFileSync(file, code); + count++; + console.log(`rewrote ${file}`); + } + } + console.log(`lodash-es: ${count} file(s) changed`); +} diff --git a/scripts/esm-codemod/run.mjs b/scripts/esm-codemod/run.mjs new file mode 100644 index 0000000000..65660f988f --- /dev/null +++ b/scripts/esm-codemod/run.mjs @@ -0,0 +1,106 @@ +#!/usr/bin/env node +// Orchestrates the CS-11449 ts-node -> native-Node ESM codemod across the +// node-run package cluster. Idempotent: safe to re-run. Pass --dry to preview. +// +// node scripts/esm-codemod/run.mjs [--dry] +// +// What it does (see ./README.md for the full error taxonomy): +// 1. Source rewrites over cluster .ts files: +// - add explicit extensions to relative imports (add-relative-extensions) +// - lodash/X -> named import from lodash-es (lodash-to-lodash-es) +// - named CJS imports -> default + destructure (cjs-named-to-default) +// - __dirname/__filename-> import.meta.dirname/filename (dirname-to-import-meta) +// 2. Invocation rewrites over package.json / *.sh / mise-tasks: +// - ts-node --transpileOnly -> node .ts (ts-node-to-node) +// +// NOT automated (do by hand — see README): per-package `exports` maps + `type`, +// `import.meta.url`-as-path bugs, the qunit test-runner bootstrap, removing the +// `ts-node` devDependency, and in-source `spawn('ts-node', ...)` sites. +import { readFileSync, writeFileSync, readdirSync, statSync } from 'node:fs'; +import { join } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { transform as addExt } from './add-relative-extensions.mjs'; +import { transform as lodashEs } from './lodash-to-lodash-es.mjs'; +import { transform as cjsNamed } from './cjs-named-to-default.mjs'; +import { transform as dirname } from './dirname-to-import-meta.mjs'; +import { transform as tsNode } from './ts-node-to-node.mjs'; + +const REPO = fileURLToPath(new URL('../..', import.meta.url)); +const DRY = process.argv.includes('--dry'); + +// The node-run cluster: packages Node executes directly (not bundled by Vite). +const CLUSTER = [ + 'packages/runtime-common', + 'packages/postgres', + 'packages/billing', + 'packages/realm-server', + 'packages/realm-test-harness', + 'packages/ai-bot', + 'packages/bot-runner', + 'packages/matrix', + 'packages/software-factory', +]; + +function walk(dir, test, out = []) { + let entries; + try { + entries = readdirSync(dir, { withFileTypes: true }); + } catch { + return out; + } + for (const e of entries) { + if (e.name === 'node_modules' || e.name === 'dist' || e.name === '.git') + continue; + const p = join(dir, e.name); + if (e.isDirectory()) walk(p, test, out); + else if (test(p)) out.push(p); + } + return out; +} + +function applySource(file, fns) { + let src = readFileSync(file, 'utf8'); + let changed = false; + for (const fn of fns) { + const r = fn === addExt ? fn(file, src) : fn(src); + if (r.changed) { + src = r.code; + changed = true; + } + } + if (changed && !DRY) writeFileSync(file, src); + return changed; +} + +let srcChanged = 0; +for (const pkg of CLUSTER) { + const files = walk(join(REPO, pkg), (p) => /\.(ts|mts)$/.test(p)); + for (const f of files) { + if (applySource(f, [addExt, lodashEs, cjsNamed, dirname])) srcChanged++; + } +} +console.log(`source rewrites: ${srcChanged} file(s)${DRY ? ' (dry)' : ''}`); + +let invChanged = 0; +const invFiles = [ + ...CLUSTER.map((p) => join(REPO, p, 'package.json')), + ...walk(join(REPO, 'mise-tasks'), () => true), + ...CLUSTER.flatMap((p) => walk(join(REPO, p), (f) => f.endsWith('.sh'))), +]; +for (const f of invFiles) { + let src; + try { + src = readFileSync(f, 'utf8'); + } catch { + continue; + } + const r = tsNode(src); + if (r.changed) { + if (!DRY) writeFileSync(f, r.code); + invChanged++; + } + if (r.skipped?.length) { + for (const s of r.skipped) console.log(` SKIP ${f}: ${s}`); + } +} +console.log(`invocation rewrites: ${invChanged} file(s)${DRY ? ' (dry)' : ''}`); diff --git a/scripts/esm-codemod/ts-node-to-node.mjs b/scripts/esm-codemod/ts-node-to-node.mjs new file mode 100644 index 0000000000..31b51269d1 --- /dev/null +++ b/scripts/esm-codemod/ts-node-to-node.mjs @@ -0,0 +1,63 @@ +#!/usr/bin/env node +// Rewrites `ts-node --transpileOnly ` invocations to `node .ts` +// in package.json scripts, shell scripts, and mise-tasks. Native Node runs the +// TypeScript entry directly (type-stripping is stable in Node >=23.6); the +// extensionless entry must gain a `.ts` suffix because Node does no extension +// search for the CLI entry point. +// +// ts-node --transpileOnly main -> node main.ts +// ts-node --transpileOnly prerender/server -> node prerender/server.ts +// ts-node --transpileOnly scripts/foo.ts -> node scripts/foo.ts +// NODE_NO_WARNINGS=1 ts-node --transpileOnly x -> NODE_NO_WARNINGS=1 node x.ts +// +// Leaves alone (reported, fix by hand): +// - qunit --require ts-node/register/transpile-only ... (needs a node bootstrap) +// - ts-node ... -e / --eval ... (inline code, no type-strip) +// +// Usage: node ts-node-to-node.mjs ... (edits in place) +import { readFileSync, writeFileSync } from 'node:fs'; + +const KNOWN_EXT = /\.(ts|mts|cts|js|mjs|cjs)$/; + +// `ts-node --transpileOnly ` (entry = next non-flag token). The +// separator class allows shell line-continuations (`\` + newline + indent), +// so multi-line `exec ts-node \\\n --transpileOnly main \\` forms convert too. +const INVOCATION = /\bts-node[\s\\]+--transpileOnly[\s\\]+([^\s"'\\]+)/g; + +export function transform(src) { + const skipped = []; + let changed = false; + let code = src.replace(INVOCATION, (full, entry) => { + if (entry.startsWith('-')) { + skipped.push(full.trim()); + return full; // inline -e / --eval etc. + } + changed = true; + const withExt = KNOWN_EXT.test(entry) ? entry : `${entry}.ts`; + return `node ${withExt}`; + }); + // `qunit --require ts-node/register/transpile-only` needs a hand-written + // bootstrap; flag it rather than silently breaking it. + if (/ts-node\/register\/transpile-only/.test(code)) { + skipped.push('qunit --require ts-node/register/transpile-only'); + } + return { code, changed, skipped }; +} + +if (import.meta.url === `file://${process.argv[1]}`) { + let count = 0; + const allSkipped = []; + for (const file of process.argv.slice(2)) { + const { code, changed, skipped } = transform(readFileSync(file, 'utf8')); + if (changed) { + writeFileSync(file, code); + count++; + } + for (const s of skipped) allSkipped.push(`${file}: ${s}`); + } + console.log(`ts-node-to-node: ${count} file(s) changed`); + if (allSkipped.length) { + console.log(`\nSKIPPED — fix by hand (${allSkipped.length}):`); + for (const s of allSkipped) console.log(' ' + s); + } +} From 06913fdf64e743287e49b8528a474e62312b3f03 Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Wed, 17 Jun 2026 14:16:12 -0400 Subject: [PATCH 07/38] test: run node-cluster qunit suites under native Node Replace `qunit --require ts-node/register/transpile-only tests/index.ts` with `node tests/index.ts` for ai-bot, bot-runner, software-factory, and realm-server. The qunit CLI used to supply the QUnit global, TAP reporter, autostart, and a failure-based exit code; each package now has a tests/qunit-bootstrap.ts that wires those up (autostart off, TAP reporter, runEnd exit code) and its tests/index.ts ends with QUnit.start(). Test files imported `{ module, test }` from qunit, which Node's ESM loader can't read as named exports from the CJS package; the cjs-named-to-default codemod (now line-anchored so it skips qunit imports embedded in test-fixture strings) rewrites them to a default import + destructure. Also adds jsonwebtoken to that codemod's CJS list. realm-server's tests/index.ts additionally needed a createRequire shim so its synchronous, order-preserving test-file loader keeps working, with an explicit `.ts` on each require (native require does no extension search); its CI JUnit reporter is renamed .cjs (realm-server is now type:module). Removes the now-unused ts-node devDependency from every package and fixes two `#!/usr/bin/env ts-node` shebangs and a `ps | grep ts-node` process-matcher that no longer matches the node-run children. Known remaining: ai-bot has 5 tests that reassign sealed ES-module namespace bindings for mocking (needs DI); software-factory's full node suite needs boxel-cli and its own src migrated off bare require(). Co-Authored-By: Claude Opus 4.8 --- packages/ai-bot/package.json | 3 +- packages/ai-bot/tests/chat-titling-test.ts | 3 +- .../tests/code-patch-correctness-test.ts | 3 +- packages/ai-bot/tests/credit-tracking-test.ts | 3 +- .../ai-bot/tests/history-construction-test.ts | 3 +- packages/ai-bot/tests/index.ts | 4 ++ packages/ai-bot/tests/interrupt-test.ts | 3 +- packages/ai-bot/tests/locking-test.ts | 3 +- packages/ai-bot/tests/matrix-util-test.ts | 3 +- packages/ai-bot/tests/modality-test.ts | 3 +- .../ai-bot/tests/prompt-construction-test.ts | 3 +- packages/ai-bot/tests/qunit-bootstrap.ts | 13 +++++ packages/ai-bot/tests/responding-test.ts | 3 +- .../ai-bot/tests/response-parsing-test.ts | 3 +- packages/bot-runner/package.json | 3 +- packages/bot-runner/tests/bot-runner-test.ts | 3 +- .../bot-runner/tests/command-runner-test.ts | 3 +- .../tests/create-listing-pr-handler-test.ts | 3 +- packages/bot-runner/tests/index.ts | 4 ++ packages/bot-runner/tests/lint-runner-test.ts | 13 ++--- packages/bot-runner/tests/qunit-bootstrap.ts | 13 +++++ packages/boxel-cli/package.json | 6 +- packages/matrix/package.json | 1 - ...ter-github-webhook-for-submission-realm.ts | 2 +- packages/matrix/scripts/remove-test-dbs.sh | 4 +- .../scripts/reveal-realm-user-password.ts | 2 +- packages/realm-server/package.json | 1 - .../{junit-reporter.js => junit-reporter.cjs} | 0 .../realm-server/scripts/measure-test-file.sh | 2 +- .../tests/async-semaphore-test.ts | 3 +- .../tests/atomic-endpoints-test.ts | 3 +- .../realm-server/tests/auth-client-test.ts | 3 +- .../tests/bfm-card-references-test.ts | 3 +- packages/realm-server/tests/billing-test.ts | 3 +- .../tests/boxel-domain-availability-test.ts | 3 +- .../tests/card-dependencies-endpoint-test.ts | 3 +- .../realm-server/tests/card-endpoints-test.ts | 3 +- .../tests/card-source-endpoints-test.ts | 3 +- .../tests/claim-boxel-domain-test.ts | 3 +- .../tests/clamp-serialized-error-test.ts | 3 +- .../tests/codemod-context-search-test.ts | 3 +- .../tests/coerce-error-message-test.ts | 3 +- .../tests/command-parsing-utils-test.ts | 3 +- .../tests/consuming-realm-header-test.ts | 3 +- .../tests/cpu-profiler-affinity-gate-test.ts | 3 +- .../tests/data-plane-write-lock-test.ts | 3 +- .../tests/definition-lookup-test.ts | 3 +- .../tests/delete-boxel-claimed-domain-test.ts | 3 +- .../tests/eq-containment-integration-test.ts | 3 +- .../tests/fallback-models-test.ts | 3 +- .../tests/file-watcher-events-test.ts | 3 +- .../finalize-child-fatal-failure-test.ts | 3 +- .../finalize-orphan-reservations-test.ts | 3 +- .../tests/full-index-on-startup-test.ts | 3 +- .../realm-server/tests/full-reindex-test.ts | 3 +- .../tests/get-boxel-claimed-domain-test.ts | 3 +- packages/realm-server/tests/helpers/index.ts | 3 +- .../tests/host-routing-validation-test.ts | 3 +- .../tests/http2-keepalive-test.ts | 3 +- packages/realm-server/tests/index.ts | 24 +++++++- .../tests/indexing-event-sink-test.ts | 3 +- packages/realm-server/tests/indexing-test.ts | 3 +- .../tests/is-json-content-type-test.ts | 3 +- .../tests/job-scoped-search-cache-test.ts | 3 +- .../tests/jobs-finished-listener-test.ts | 3 +- .../realm-server/tests/lazy-mount-test.ts | 3 +- .../tests/listener-dispatcher-test.ts | 3 +- .../tests/load-links-batching-test.ts | 3 +- ...markdown-fallback-server-isolation-test.ts | 3 +- .../tests/matches-filter-integration-test.ts | 3 +- .../tests/module-cache-coordination-test.ts | 3 +- ...module-cache-invalidation-listener-test.ts | 3 +- .../tests/module-cache-race-test.ts | 3 +- .../realm-server/tests/module-syntax-test.ts | 3 +- .../tests/network-inflight-tracker-test.ts | 3 +- .../realm-server/tests/node-realm-test.ts | 3 +- .../tests/normalize-realm-meta-value-test.ts | 3 +- .../tests/openrouter-passthrough-test.ts | 3 +- .../tests/package-shim-handler-test.ts | 3 +- .../page-pool-cert-verifier-retry-test.ts | 3 +- .../tests/page-pool-eviction-recovery-test.ts | 3 +- .../tests/page-pool-expansion-test.ts | 3 +- .../tests/page-pool-priority-test.ts | 3 +- .../tests/page-pool-standby-refill-test.ts | 3 +- .../permissions/permission-checker-test.ts | 3 +- .../tests/pg-adapter-subscribe-test.ts | 3 +- .../tests/prerender-affinity-activity-test.ts | 3 +- .../tests/prerender-artifact-sink-test.ts | 3 +- .../tests/prerender-batch-ownership-test.ts | 3 +- .../tests/prerender-cancellation-test.ts | 3 +- .../tests/prerender-deadlock-test.ts | 3 +- .../prerender-diagnostics-persistence-test.ts | 3 +- .../tests/prerender-manager-test.ts | 3 +- .../tests/prerender-proxy-test.ts | 3 +- .../tests/prerender-server-test.ts | 3 +- .../tests/prerender-v8-prof-test.ts | 3 +- .../realm-server/tests/prerendering-test.ts | 3 +- .../tests/publish-unpublish-realm-test.ts | 3 +- packages/realm-server/tests/queries-test.ts | 3 +- .../tests/query-matches-filter-test.ts | 3 +- packages/realm-server/tests/queue-test.ts | 3 +- .../tests/realm-advisory-locks-test.ts | 3 +- .../realm-server/tests/realm-auth-test.ts | 3 +- .../tests/realm-cleanup-transaction-test.ts | 3 +- .../cancel-indexing-job-test.ts | 3 +- .../realm-endpoints/dependencies-test.ts | 3 +- .../tests/realm-endpoints/directory-test.ts | 3 +- .../realm-endpoints/indexing-errors-test.ts | 3 +- .../tests/realm-endpoints/info-test.ts | 3 +- .../realm-endpoints/invalidate-urls-test.ts | 3 +- .../tests/realm-endpoints/lint-test.ts | 3 +- .../tests/realm-endpoints/markdown-test.ts | 3 +- .../tests/realm-endpoints/mtimes-test.ts | 3 +- .../tests/realm-endpoints/permissions-test.ts | 3 +- .../realm-endpoints/publishability-test.ts | 3 +- .../tests/realm-endpoints/reindex-test.ts | 3 +- .../tests/realm-endpoints/search-test.ts | 3 +- .../tests/realm-endpoints/search-v2-test.ts | 3 +- .../tests/realm-endpoints/user-test.ts | 3 +- .../tests/realm-file-changes-listener-test.ts | 3 +- .../tests/realm-identifiers-test.ts | 3 +- .../realm-index-updated-listener-test.ts | 3 +- .../tests/realm-operations-test.ts | 3 +- .../tests/realm-registry-backfill-test.ts | 3 +- .../tests/realm-registry-reconciler-test.ts | 3 +- .../tests/realm-registry-writes-test.ts | 3 +- .../realm-server/tests/realm-routing-test.ts | 3 +- .../tests/remote-prerenderer-test.ts | 3 +- .../tests/render-type-resolution-test.ts | 3 +- .../tests/request-forward-test.ts | 3 +- .../tests/resolve-published-realm-url-test.ts | 3 +- .../tests/run-command-task-test.ts | 3 +- .../tests/runtime-dependency-tracker-test.ts | 3 +- .../tests/runtime-exception-capture-test.ts | 3 +- .../tests/sanitize-for-jsonb-test.ts | 3 +- .../tests/sanitize-head-html-test.ts | 3 +- .../tests/screenshot-card-test.ts | 3 +- .../tests/scripts/run-qunit-with-test-pg.sh | 4 +- .../realm-server/tests/search-compat-test.ts | 3 +- .../tests/search-entries-engine-test.ts | 3 +- .../realm-server/tests/search-entry-test.ts | 3 +- .../tests/search-in-flight-key-test.ts | 3 +- .../tests/search-prerendered-test.ts | 3 +- .../realm-server/tests/serve-index-test.ts | 3 +- .../realm-server/tests/server-config-test.ts | 3 +- .../server-endpoints/authentication-test.ts | 3 +- .../server-endpoints/bot-commands-test.ts | 3 +- .../server-endpoints/bot-registration-test.ts | 3 +- .../server-endpoints/delete-realm-test.ts | 3 +- .../server-endpoints/download-realm-test.ts | 3 +- .../server-endpoints/federated-types-test.ts | 3 +- .../server-endpoints/incoming-webhook-test.ts | 3 +- .../server-endpoints/index-responses-test.ts | 3 +- .../tests/server-endpoints/info-test.ts | 3 +- .../maintenance-endpoints-test.ts | 3 +- .../server-endpoints/queue-status-test.ts | 3 +- .../server-endpoints/realm-lifecycle-test.ts | 3 +- .../run-command-endpoint-test.ts | 3 +- .../screenshot-card-endpoint-test.ts | 3 +- .../search-prerendered-test.ts | 3 +- .../tests/server-endpoints/search-test.ts | 3 +- .../tests/server-endpoints/search-v2-test.ts | 3 +- .../server-endpoints/stripe-session-test.ts | 3 +- .../server-endpoints/stripe-webhook-test.ts | 3 +- .../server-endpoints/user-and-catalog-test.ts | 3 +- .../server-endpoints/webhook-commands-test.ts | 3 +- .../server-endpoints/webhook-receiver-test.ts | 3 +- .../tests/session-room-queries-test.ts | 3 +- .../tests/skip-query-backed-expansion-test.ts | 3 +- packages/realm-server/tests/transpile-test.ts | 3 +- .../realm-server/tests/types-endpoint-test.ts | 3 +- .../tests/unified-search-contracts-test.ts | 3 +- .../tests/virtual-network-test.ts | 3 +- packages/realm-test-harness/package.json | 1 - packages/software-factory/package.json | 1 - .../smoke-test-factory-scenarios.ts | 3 +- .../scripts/smoke-tests/smoke-test-realm.ts | 6 +- packages/software-factory/scripts/test.ts | 2 +- .../tests/eval-execution.test.ts | 3 +- .../software-factory/tests/eval-step.test.ts | 3 +- .../tests/factory-agent-claude-code.test.ts | 3 +- .../tests/factory-brief.test.ts | 3 +- .../tests/factory-context-builder.test.ts | 3 +- .../factory-entrypoint.integration.test.ts | 3 +- .../tests/factory-entrypoint.test.ts | 3 +- .../tests/factory-prompt-loader.test.ts | 3 +- .../tests/factory-skill-loader.test.ts | 3 +- .../tests/factory-target-realm.spec.ts | 2 - .../tests/factory-target-realm.test.ts | 3 +- .../tests/factory-test-realm.test.ts | 3 +- .../tests/factory-tool-builder.test.ts | 3 +- .../factory-tool-executor.integration.test.ts | 3 +- .../tests/factory-tool-executor.test.ts | 3 +- .../tests/factory-tool-registry.test.ts | 3 +- .../tests/factory-tool-schema-adapter.test.ts | 3 +- .../find-and-hold-available-port.test.ts | 3 +- .../tests/hold-specific-port.test.ts | 3 +- packages/software-factory/tests/index.ts | 4 ++ .../tests/instantiate-discovery.test.ts | 3 +- .../tests/instantiate-step.test.ts | 3 +- .../software-factory/tests/issue-loop.test.ts | 3 +- .../tests/issue-scheduler.test.ts | 3 +- .../software-factory/tests/lint-step.test.ts | 3 +- .../software-factory/tests/parse-step.test.ts | 3 +- .../tests/port-allocator.test.ts | 3 +- .../software-factory/tests/qunit-bootstrap.ts | 13 +++++ .../tests/retry-blocked-issues.test.ts | 3 +- .../software-factory/tests/test-step.test.ts | 3 +- .../tests/validation-pipeline.test.ts | 3 +- .../tests/validation-run-cache.test.ts | 3 +- scripts/esm-codemod/README.md | 55 ++++++++++++------- scripts/esm-codemod/cjs-named-to-default.mjs | 9 ++- 212 files changed, 510 insertions(+), 240 deletions(-) create mode 100644 packages/ai-bot/tests/qunit-bootstrap.ts create mode 100644 packages/bot-runner/tests/qunit-bootstrap.ts rename packages/realm-server/scripts/{junit-reporter.js => junit-reporter.cjs} (100%) create mode 100644 packages/software-factory/tests/qunit-bootstrap.ts diff --git a/packages/ai-bot/package.json b/packages/ai-bot/package.json index d9d70ce4b5..42c39d331a 100644 --- a/packages/ai-bot/package.json +++ b/packages/ai-bot/package.json @@ -16,7 +16,6 @@ "qunit": "catalog:", "stream-chain": "catalog:", "stream-json": "catalog:", - "ts-node": "^10.9.2", "typescript": "catalog:" }, "devDependencies": { @@ -40,7 +39,7 @@ "lint:js:fix": "eslint . --report-unused-disable-directives --fix", "lint:types": "ember-tsc --noEmit", "start": "NODE_NO_WARNINGS=1 node main.ts", - "test": "NODE_NO_WARNINGS=1 qunit --require ts-node/register/transpile-only tests/index.ts", + "test": "NODE_NO_WARNINGS=1 node tests/index.ts", "get-chat": "NODE_NO_WARNINGS=1 node scripts/get_chat.ts" } } diff --git a/packages/ai-bot/tests/chat-titling-test.ts b/packages/ai-bot/tests/chat-titling-test.ts index 4b76b97986..6385fec665 100644 --- a/packages/ai-bot/tests/chat-titling-test.ts +++ b/packages/ai-bot/tests/chat-titling-test.ts @@ -1,4 +1,5 @@ -import { module, test, assert } from 'qunit'; +import QUnit from 'qunit'; +const { module, test, assert } = QUnit; import { getLatestResultMessage, setTitle, diff --git a/packages/ai-bot/tests/code-patch-correctness-test.ts b/packages/ai-bot/tests/code-patch-correctness-test.ts index fbea6e8306..3cc5d90be5 100644 --- a/packages/ai-bot/tests/code-patch-correctness-test.ts +++ b/packages/ai-bot/tests/code-patch-correctness-test.ts @@ -1,4 +1,5 @@ -import { module, test, assert } from 'qunit'; +import QUnit from 'qunit'; +const { module, test, assert } = QUnit; import { publishCodePatchCorrectnessMessage } from '../lib/code-patch-correctness.ts'; import { FakeMatrixClient } from './helpers/fake-matrix-client.ts'; diff --git a/packages/ai-bot/tests/credit-tracking-test.ts b/packages/ai-bot/tests/credit-tracking-test.ts index d463728da7..2ed2385272 100644 --- a/packages/ai-bot/tests/credit-tracking-test.ts +++ b/packages/ai-bot/tests/credit-tracking-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import FakeTimers from '@sinonjs/fake-timers'; import type { DBAdapter } from '@cardstack/runtime-common'; import { diff --git a/packages/ai-bot/tests/history-construction-test.ts b/packages/ai-bot/tests/history-construction-test.ts index 75409b7e4c..a439145475 100644 --- a/packages/ai-bot/tests/history-construction-test.ts +++ b/packages/ai-bot/tests/history-construction-test.ts @@ -1,4 +1,5 @@ -import { module, test, assert } from 'qunit'; +import QUnit from 'qunit'; +const { module, test, assert } = QUnit; import { APP_BOXEL_COMMAND_RESULT_EVENT_TYPE, APP_BOXEL_COMMAND_RESULT_REL_TYPE, diff --git a/packages/ai-bot/tests/index.ts b/packages/ai-bot/tests/index.ts index 698197141d..e31d569d96 100644 --- a/packages/ai-bot/tests/index.ts +++ b/packages/ai-bot/tests/index.ts @@ -1,3 +1,5 @@ +import './qunit-bootstrap.ts'; // configures QUnit before any test registers +import QUnit from 'qunit'; import '../setup-logger.ts'; // This should be first import './response-parsing-test.ts'; import './history-construction-test.ts'; @@ -10,3 +12,5 @@ import './modality-test.ts'; import './locking-test.ts'; import './interrupt-test.ts'; import './credit-tracking-test.ts'; + +QUnit.start(); diff --git a/packages/ai-bot/tests/interrupt-test.ts b/packages/ai-bot/tests/interrupt-test.ts index d14c67322c..af31deb4b3 100644 --- a/packages/ai-bot/tests/interrupt-test.ts +++ b/packages/ai-bot/tests/interrupt-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { Responder } from '../lib/responder.ts'; import { FakeMatrixClient } from './helpers/fake-matrix-client.ts'; import FakeTimers from '@sinonjs/fake-timers'; diff --git a/packages/ai-bot/tests/locking-test.ts b/packages/ai-bot/tests/locking-test.ts index 8ba9d25d50..ae1ec87013 100644 --- a/packages/ai-bot/tests/locking-test.ts +++ b/packages/ai-bot/tests/locking-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { PgAdapter } from '@cardstack/postgres'; import { acquireRoomLock, releaseRoomLock } from '../lib/queries.ts'; import { Client } from 'pg'; diff --git a/packages/ai-bot/tests/matrix-util-test.ts b/packages/ai-bot/tests/matrix-util-test.ts index a0d5a8a432..218fbb911d 100644 --- a/packages/ai-bot/tests/matrix-util-test.ts +++ b/packages/ai-bot/tests/matrix-util-test.ts @@ -1,4 +1,5 @@ -import { test } from 'qunit'; +import QUnit from 'qunit'; +const { test } = QUnit; import { FakeMatrixClient } from './helpers/fake-matrix-client.ts'; import type { Method } from 'matrix-js-sdk'; import type { diff --git a/packages/ai-bot/tests/modality-test.ts b/packages/ai-bot/tests/modality-test.ts index db21bae182..04bb4e335d 100644 --- a/packages/ai-bot/tests/modality-test.ts +++ b/packages/ai-bot/tests/modality-test.ts @@ -1,4 +1,5 @@ -import { module, test, assert } from 'qunit'; +import QUnit from 'qunit'; +const { module, test, assert } = QUnit; import { requiredModality, modalityLabel, diff --git a/packages/ai-bot/tests/prompt-construction-test.ts b/packages/ai-bot/tests/prompt-construction-test.ts index db1c36b441..ce24a81599 100644 --- a/packages/ai-bot/tests/prompt-construction-test.ts +++ b/packages/ai-bot/tests/prompt-construction-test.ts @@ -1,4 +1,5 @@ -import { module, test, assert } from 'qunit'; +import QUnit from 'qunit'; +const { module, test, assert } = QUnit; import { getPatchTool } from '@cardstack/runtime-common/helpers/ai'; import type { ChatCompletionMessageFunctionToolCall } from 'openai/resources/chat/completions'; import { diff --git a/packages/ai-bot/tests/qunit-bootstrap.ts b/packages/ai-bot/tests/qunit-bootstrap.ts new file mode 100644 index 0000000000..1867954065 --- /dev/null +++ b/packages/ai-bot/tests/qunit-bootstrap.ts @@ -0,0 +1,13 @@ +// Configures QUnit to run under native Node (`node tests/index.ts`). The qunit +// CLI used to provide these three things; running the suite directly under node +// means wiring them up ourselves: +// - autostart off, so `index.ts` can register every test before starting +// - the TAP reporter the CLI emitted by default +// - a failure-based process exit code +import QUnit from 'qunit'; + +QUnit.config.autostart = false; +QUnit.reporters.tap.init(QUnit); +QUnit.on('runEnd', (data) => { + process.exitCode = data.testCounts.failed > 0 ? 1 : 0; +}); diff --git a/packages/ai-bot/tests/responding-test.ts b/packages/ai-bot/tests/responding-test.ts index 984b6a3506..fd3c8086f7 100644 --- a/packages/ai-bot/tests/responding-test.ts +++ b/packages/ai-bot/tests/responding-test.ts @@ -1,4 +1,5 @@ -import { module, test, assert } from 'qunit'; +import QUnit from 'qunit'; +const { module, test, assert } = QUnit; import { Responder } from '../lib/responder.ts'; import { DEFAULT_EVENT_SIZE_MAX } from '../lib/matrix/response-publisher.ts'; import FakeTimers from '@sinonjs/fake-timers'; diff --git a/packages/ai-bot/tests/response-parsing-test.ts b/packages/ai-bot/tests/response-parsing-test.ts index 82b74ab94f..8c9fc872ea 100644 --- a/packages/ai-bot/tests/response-parsing-test.ts +++ b/packages/ai-bot/tests/response-parsing-test.ts @@ -1,4 +1,5 @@ -import { module, test, assert } from 'qunit'; +import QUnit from 'qunit'; +const { module, test, assert } = QUnit; import { cleanContent } from '@cardstack/runtime-common/ai'; module('cleanContent', () => { diff --git a/packages/bot-runner/package.json b/packages/bot-runner/package.json index 334fabaf60..78b9e2bfd4 100644 --- a/packages/bot-runner/package.json +++ b/packages/bot-runner/package.json @@ -5,7 +5,6 @@ "@cardstack/runtime-common": "workspace:*", "@sentry/node": "catalog:", "matrix-js-sdk": "catalog:", - "ts-node": "^10.9.2", "typescript": "catalog:" }, "devDependencies": { @@ -17,7 +16,7 @@ }, "scripts": { "start": "NODE_NO_WARNINGS=1 node main.ts", - "test": "NODE_NO_WARNINGS=1 qunit --require ts-node/register/transpile-only tests/index.ts", + "test": "NODE_NO_WARNINGS=1 node tests/index.ts", "lint": "ember-tsc --noEmit" } } diff --git a/packages/bot-runner/tests/bot-runner-test.ts b/packages/bot-runner/tests/bot-runner-test.ts index 1f25c911a2..164c327a5c 100644 --- a/packages/bot-runner/tests/bot-runner-test.ts +++ b/packages/bot-runner/tests/bot-runner-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { DBAdapter, ExecuteOptions, diff --git a/packages/bot-runner/tests/command-runner-test.ts b/packages/bot-runner/tests/command-runner-test.ts index 249fbe820e..cd7f55a310 100644 --- a/packages/bot-runner/tests/command-runner-test.ts +++ b/packages/bot-runner/tests/command-runner-test.ts @@ -1,4 +1,5 @@ -import { module, test, skip } from 'qunit'; +import QUnit from 'qunit'; +const { module, test, skip } = QUnit; import type { DBAdapter, ExecuteOptions, diff --git a/packages/bot-runner/tests/create-listing-pr-handler-test.ts b/packages/bot-runner/tests/create-listing-pr-handler-test.ts index d75543ef33..a4d9a0ccba 100644 --- a/packages/bot-runner/tests/create-listing-pr-handler-test.ts +++ b/packages/bot-runner/tests/create-listing-pr-handler-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { GitHubClient } from '../lib/github.ts'; import { CreateListingPRHandler, diff --git a/packages/bot-runner/tests/index.ts b/packages/bot-runner/tests/index.ts index cc9767aba1..187ec6d4ed 100644 --- a/packages/bot-runner/tests/index.ts +++ b/packages/bot-runner/tests/index.ts @@ -1,5 +1,9 @@ +import './qunit-bootstrap.ts'; // configures QUnit before any test registers +import QUnit from 'qunit'; import '../setup-logger.ts'; import './bot-runner-test.ts'; import './command-runner-test.ts'; import './create-listing-pr-handler-test.ts'; import './lint-runner-test.ts'; + +QUnit.start(); diff --git a/packages/bot-runner/tests/lint-runner-test.ts b/packages/bot-runner/tests/lint-runner-test.ts index 70ca2553cb..753108460e 100644 --- a/packages/bot-runner/tests/lint-runner-test.ts +++ b/packages/bot-runner/tests/lint-runner-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import * as os from 'node:os'; import * as path from 'node:path'; import { @@ -86,10 +87,7 @@ module('lint-runner | parseTscOutput', () => { test('also works when prefix is passed with a trailing slash', (assert) => { let output = '../catalog/__submissions-temp__/x/foo.gts(1,1): error TS1: msg'; - let errors = parseTscOutput( - output, - '../catalog/__submissions-temp__/x/', - ); + let errors = parseTscOutput(output, '../catalog/__submissions-temp__/x/'); assert.strictEqual(errors.length, 1); assert.ok(errors[0].startsWith('foo.gts '), errors[0]); }); @@ -171,10 +169,7 @@ module('lint-runner | parseTemplateLintOutput', () => { test('handles empty messages array', (assert) => { let json = JSON.stringify({ '__submissions-temp__/abc/foo.hbs': [] }); - assert.deepEqual( - parseTemplateLintOutput(json, tempDir, catalogDir), - [], - ); + assert.deepEqual(parseTemplateLintOutput(json, tempDir, catalogDir), []); }); test('handles multiple files', (assert) => { diff --git a/packages/bot-runner/tests/qunit-bootstrap.ts b/packages/bot-runner/tests/qunit-bootstrap.ts new file mode 100644 index 0000000000..1867954065 --- /dev/null +++ b/packages/bot-runner/tests/qunit-bootstrap.ts @@ -0,0 +1,13 @@ +// Configures QUnit to run under native Node (`node tests/index.ts`). The qunit +// CLI used to provide these three things; running the suite directly under node +// means wiring them up ourselves: +// - autostart off, so `index.ts` can register every test before starting +// - the TAP reporter the CLI emitted by default +// - a failure-based process exit code +import QUnit from 'qunit'; + +QUnit.config.autostart = false; +QUnit.reporters.tap.init(QUnit); +QUnit.on('runEnd', (data) => { + process.exitCode = data.testCounts.failed > 0 ? 1 : 0; +}); diff --git a/packages/boxel-cli/package.json b/packages/boxel-cli/package.json index b49b77890e..f7142394a0 100644 --- a/packages/boxel-cli/package.json +++ b/packages/boxel-cli/package.json @@ -4,6 +4,11 @@ "license": "MIT", "description": "CLI tools for Boxel workspace management", "main": "./dist/index.js", + "exports": { + ".": "./dist/index.js", + "./api": "./api.ts", + "./package.json": "./package.json" + }, "bin": { "boxel": "./bin/boxel.js" }, @@ -64,7 +69,6 @@ "eslint-plugin-prettier": "catalog:", "prettier": "catalog:", "semver": "^7.7.0", - "ts-node": "^10.9.1", "vite": "catalog:", "vitest": "catalog:" }, diff --git a/packages/matrix/package.json b/packages/matrix/package.json index f975e6112a..a8f4c73464 100644 --- a/packages/matrix/package.json +++ b/packages/matrix/package.json @@ -17,7 +17,6 @@ "pg": "catalog:", "start-server-and-test": "catalog:", "tmp": "catalog:", - "ts-node": "^10.9.1", "typescript": "catalog:", "uuid": "catalog:", "yaml": "catalog:" diff --git a/packages/matrix/scripts/register-github-webhook-for-submission-realm.ts b/packages/matrix/scripts/register-github-webhook-for-submission-realm.ts index 3c63f14197..736e64a981 100755 --- a/packages/matrix/scripts/register-github-webhook-for-submission-realm.ts +++ b/packages/matrix/scripts/register-github-webhook-for-submission-realm.ts @@ -1,4 +1,4 @@ -#!/usr/bin/env ts-node +#!/usr/bin/env -S node import { registerRealmUser } from './register-realm-user-using-api.ts'; import { realmPassword } from '../helpers/realm-credentials.ts'; diff --git a/packages/matrix/scripts/remove-test-dbs.sh b/packages/matrix/scripts/remove-test-dbs.sh index 43028801ab..128ca019c3 100755 --- a/packages/matrix/scripts/remove-test-dbs.sh +++ b/packages/matrix/scripts/remove-test-dbs.sh @@ -1,11 +1,11 @@ #!/bin/sh # forcibly stop any isolated realm processes -isolated_realm_processes=$(ps -ef | grep ts-node | grep '\-\-port=4205' | awk '{print $2}') +isolated_realm_processes=$(ps -ef | grep node | grep '\-\-port=4205' | awk '{print $2}') for pid in $isolated_realm_processes; do kill -9 $pid done -isolated_realm_processes=$(ps -ef | grep ts-node | grep '\-\-port=4212' | awk '{print $2}') +isolated_realm_processes=$(ps -ef | grep node | grep '\-\-port=4212' | awk '{print $2}') for pid in $isolated_realm_processes; do kill -9 $pid done diff --git a/packages/matrix/scripts/reveal-realm-user-password.ts b/packages/matrix/scripts/reveal-realm-user-password.ts index b092b655ff..2662a60e34 100755 --- a/packages/matrix/scripts/reveal-realm-user-password.ts +++ b/packages/matrix/scripts/reveal-realm-user-password.ts @@ -1,4 +1,4 @@ -#!/usr/bin/env ts-node +#!/usr/bin/env -S node import { realmPassword } from '../helpers/realm-credentials.ts'; diff --git a/packages/realm-server/package.json b/packages/realm-server/package.json index 95f24dbedb..4ccc2d57a3 100644 --- a/packages/realm-server/package.json +++ b/packages/realm-server/package.json @@ -84,7 +84,6 @@ "supertest": "catalog:", "testem": "catalog:", "tmp": "catalog:", - "ts-node": "^10.9.1", "typescript": "catalog:", "undici": "catalog:", "uuid": "catalog:", diff --git a/packages/realm-server/scripts/junit-reporter.js b/packages/realm-server/scripts/junit-reporter.cjs similarity index 100% rename from packages/realm-server/scripts/junit-reporter.js rename to packages/realm-server/scripts/junit-reporter.cjs diff --git a/packages/realm-server/scripts/measure-test-file.sh b/packages/realm-server/scripts/measure-test-file.sh index bfaa1253a9..c4aba253ba 100755 --- a/packages/realm-server/scripts/measure-test-file.sh +++ b/packages/realm-server/scripts/measure-test-file.sh @@ -74,7 +74,7 @@ for i in $(seq 1 "$RUNS"); do STRIPE_API_KEY=stripe-api-key \ MATRIX_REGISTRATION_SHARED_SECRET="${MATRIX_REGISTRATION_SHARED_SECRET:-fake}" \ TEST_FILES="$TEST_FILES_ARG" \ - "$QUNIT" --require ts-node/register/transpile-only tests/index.ts \ + node tests/index.ts \ >/dev/null 2>"$timing" qunit_status=$? set -e diff --git a/packages/realm-server/tests/async-semaphore-test.ts b/packages/realm-server/tests/async-semaphore-test.ts index 5329043bcb..82f622b662 100644 --- a/packages/realm-server/tests/async-semaphore-test.ts +++ b/packages/realm-server/tests/async-semaphore-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { AsyncSemaphore } from '../prerender/async-semaphore.ts'; import { isPrerenderCancellation } from '../prerender/prerender-cancel.ts'; diff --git a/packages/realm-server/tests/atomic-endpoints-test.ts b/packages/realm-server/tests/atomic-endpoints-test.ts index 3578311a9a..39061184da 100644 --- a/packages/realm-server/tests/atomic-endpoints-test.ts +++ b/packages/realm-server/tests/atomic-endpoints-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { Test, SuperTest } from 'supertest'; import { basename } from 'path'; import type { RealmHttpServer as Server } from '../server.ts'; diff --git a/packages/realm-server/tests/auth-client-test.ts b/packages/realm-server/tests/auth-client-test.ts index d010270d8d..48b08b4037 100644 --- a/packages/realm-server/tests/auth-client-test.ts +++ b/packages/realm-server/tests/auth-client-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import '@cardstack/runtime-common/helpers/code-equality-assertion'; import { diff --git a/packages/realm-server/tests/bfm-card-references-test.ts b/packages/realm-server/tests/bfm-card-references-test.ts index 9be2a7a6be..f3e83b9967 100644 --- a/packages/realm-server/tests/bfm-card-references-test.ts +++ b/packages/realm-server/tests/bfm-card-references-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { runSharedTest } from '@cardstack/runtime-common/helpers'; import bfmCardReferencesTests from '@cardstack/runtime-common/tests/bfm-card-references-test'; diff --git a/packages/realm-server/tests/billing-test.ts b/packages/realm-server/tests/billing-test.ts index 829984d7f2..b0958769ec 100644 --- a/packages/realm-server/tests/billing-test.ts +++ b/packages/realm-server/tests/billing-test.ts @@ -6,7 +6,8 @@ import type { User, } from '@cardstack/runtime-common'; import { logger, param, query } from '@cardstack/runtime-common'; -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { createTestPgAdapter, fetchSubscriptionsByUserId, diff --git a/packages/realm-server/tests/boxel-domain-availability-test.ts b/packages/realm-server/tests/boxel-domain-availability-test.ts index 7810d8d5a1..0f693bca12 100644 --- a/packages/realm-server/tests/boxel-domain-availability-test.ts +++ b/packages/realm-server/tests/boxel-domain-availability-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename, join } from 'path'; import type { PgAdapter } from '@cardstack/postgres'; import type { User } from '@cardstack/runtime-common'; diff --git a/packages/realm-server/tests/card-dependencies-endpoint-test.ts b/packages/realm-server/tests/card-dependencies-endpoint-test.ts index 3ceda40820..f9af9cc00b 100644 --- a/packages/realm-server/tests/card-dependencies-endpoint-test.ts +++ b/packages/realm-server/tests/card-dependencies-endpoint-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { Test, SuperTest } from 'supertest'; import { basename } from 'path'; import type { RealmHttpServer as Server } from '../server.ts'; diff --git a/packages/realm-server/tests/card-endpoints-test.ts b/packages/realm-server/tests/card-endpoints-test.ts index 6fc45c4856..a9b55ae8c8 100644 --- a/packages/realm-server/tests/card-endpoints-test.ts +++ b/packages/realm-server/tests/card-endpoints-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { Test, SuperTest } from 'supertest'; import supertest from 'supertest'; import { join, basename } from 'path'; diff --git a/packages/realm-server/tests/card-source-endpoints-test.ts b/packages/realm-server/tests/card-source-endpoints-test.ts index 58d65817e8..f2e1ea5ea2 100644 --- a/packages/realm-server/tests/card-source-endpoints-test.ts +++ b/packages/realm-server/tests/card-source-endpoints-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { Test, SuperTest } from 'supertest'; import { join, basename } from 'path'; import type { RealmHttpServer as Server } from '../server.ts'; diff --git a/packages/realm-server/tests/claim-boxel-domain-test.ts b/packages/realm-server/tests/claim-boxel-domain-test.ts index f4aa574a61..a9b0cf1d15 100644 --- a/packages/realm-server/tests/claim-boxel-domain-test.ts +++ b/packages/realm-server/tests/claim-boxel-domain-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename, join } from 'path'; import type { PgAdapter } from '@cardstack/postgres'; import type { User } from '@cardstack/runtime-common'; diff --git a/packages/realm-server/tests/clamp-serialized-error-test.ts b/packages/realm-server/tests/clamp-serialized-error-test.ts index 9b923e9342..541da77228 100644 --- a/packages/realm-server/tests/clamp-serialized-error-test.ts +++ b/packages/realm-server/tests/clamp-serialized-error-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { clampSerializedError, diff --git a/packages/realm-server/tests/codemod-context-search-test.ts b/packages/realm-server/tests/codemod-context-search-test.ts index 520dc5801e..72fee09cf0 100644 --- a/packages/realm-server/tests/codemod-context-search-test.ts +++ b/packages/realm-server/tests/codemod-context-search-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { transformContextSearch } from '../scripts/codemod/context-search/transform.ts'; diff --git a/packages/realm-server/tests/coerce-error-message-test.ts b/packages/realm-server/tests/coerce-error-message-test.ts index 80b3e26ea2..aed2210f7f 100644 --- a/packages/realm-server/tests/coerce-error-message-test.ts +++ b/packages/realm-server/tests/coerce-error-message-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { runSharedTest } from '@cardstack/runtime-common/helpers'; import coerceErrorMessageTests from '@cardstack/runtime-common/tests/coerce-error-message-test'; diff --git a/packages/realm-server/tests/command-parsing-utils-test.ts b/packages/realm-server/tests/command-parsing-utils-test.ts index 74dfb85307..c82545f4b8 100644 --- a/packages/realm-server/tests/command-parsing-utils-test.ts +++ b/packages/realm-server/tests/command-parsing-utils-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { runSharedTest } from '@cardstack/runtime-common/helpers'; import commandParsingTests from '@cardstack/runtime-common/tests/command-parsing-utils-test'; diff --git a/packages/realm-server/tests/consuming-realm-header-test.ts b/packages/realm-server/tests/consuming-realm-header-test.ts index 728a9fabfa..1b3f449727 100644 --- a/packages/realm-server/tests/consuming-realm-header-test.ts +++ b/packages/realm-server/tests/consuming-realm-header-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { runSharedTest } from '@cardstack/runtime-common/helpers'; import consumingRealmHeaderTests from '@cardstack/runtime-common/tests/consuming-realm-header-test'; diff --git a/packages/realm-server/tests/cpu-profiler-affinity-gate-test.ts b/packages/realm-server/tests/cpu-profiler-affinity-gate-test.ts index ee37318369..54e44e28c5 100644 --- a/packages/realm-server/tests/cpu-profiler-affinity-gate-test.ts +++ b/packages/realm-server/tests/cpu-profiler-affinity-gate-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { shouldProfileAffinity, getAffinityProfileTargets, diff --git a/packages/realm-server/tests/data-plane-write-lock-test.ts b/packages/realm-server/tests/data-plane-write-lock-test.ts index eb0c3d5d57..719e85e56f 100644 --- a/packages/realm-server/tests/data-plane-write-lock-test.ts +++ b/packages/realm-server/tests/data-plane-write-lock-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { Test, SuperTest } from 'supertest'; import { basename } from 'path'; import type { RealmHttpServer as Server } from '../server.ts'; diff --git a/packages/realm-server/tests/definition-lookup-test.ts b/packages/realm-server/tests/definition-lookup-test.ts index 23be1d05a6..133e909a1f 100644 --- a/packages/realm-server/tests/definition-lookup-test.ts +++ b/packages/realm-server/tests/definition-lookup-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { CachingDefinitionLookup, diff --git a/packages/realm-server/tests/delete-boxel-claimed-domain-test.ts b/packages/realm-server/tests/delete-boxel-claimed-domain-test.ts index 4ebb70ed05..caefef5149 100644 --- a/packages/realm-server/tests/delete-boxel-claimed-domain-test.ts +++ b/packages/realm-server/tests/delete-boxel-claimed-domain-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename, join } from 'path'; import type { PgAdapter } from '@cardstack/postgres'; import type { User } from '@cardstack/runtime-common'; diff --git a/packages/realm-server/tests/eq-containment-integration-test.ts b/packages/realm-server/tests/eq-containment-integration-test.ts index 38eb22b254..d61238f21e 100644 --- a/packages/realm-server/tests/eq-containment-integration-test.ts +++ b/packages/realm-server/tests/eq-containment-integration-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import type { PgAdapter } from '@cardstack/postgres'; diff --git a/packages/realm-server/tests/fallback-models-test.ts b/packages/realm-server/tests/fallback-models-test.ts index 36d37282e3..1a90dd048d 100644 --- a/packages/realm-server/tests/fallback-models-test.ts +++ b/packages/realm-server/tests/fallback-models-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { runSharedTest } from '@cardstack/runtime-common/helpers'; import fallbackModelsTests from '@cardstack/runtime-common/tests/fallback-models-test'; diff --git a/packages/realm-server/tests/file-watcher-events-test.ts b/packages/realm-server/tests/file-watcher-events-test.ts index bf6ffc94fb..2bf249ffe6 100644 --- a/packages/realm-server/tests/file-watcher-events-test.ts +++ b/packages/realm-server/tests/file-watcher-events-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { Test, SuperTest } from 'supertest'; import { join, basename } from 'path'; import type { RealmHttpServer as Server } from '../server.ts'; diff --git a/packages/realm-server/tests/finalize-child-fatal-failure-test.ts b/packages/realm-server/tests/finalize-child-fatal-failure-test.ts index 7f562c02be..82865e0171 100644 --- a/packages/realm-server/tests/finalize-child-fatal-failure-test.ts +++ b/packages/realm-server/tests/finalize-child-fatal-failure-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import type { diff --git a/packages/realm-server/tests/finalize-orphan-reservations-test.ts b/packages/realm-server/tests/finalize-orphan-reservations-test.ts index e189173506..ced0a797a2 100644 --- a/packages/realm-server/tests/finalize-orphan-reservations-test.ts +++ b/packages/realm-server/tests/finalize-orphan-reservations-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import type { diff --git a/packages/realm-server/tests/full-index-on-startup-test.ts b/packages/realm-server/tests/full-index-on-startup-test.ts index 278144d061..02ab6c943f 100644 --- a/packages/realm-server/tests/full-index-on-startup-test.ts +++ b/packages/realm-server/tests/full-index-on-startup-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { resolveFullIndexOnStartup } from '../lib/full-index-on-startup.ts'; diff --git a/packages/realm-server/tests/full-reindex-test.ts b/packages/realm-server/tests/full-reindex-test.ts index 2c62eba13e..7fb7db6cb1 100644 --- a/packages/realm-server/tests/full-reindex-test.ts +++ b/packages/realm-server/tests/full-reindex-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import type { PgAdapter } from '@cardstack/postgres'; import type { diff --git a/packages/realm-server/tests/get-boxel-claimed-domain-test.ts b/packages/realm-server/tests/get-boxel-claimed-domain-test.ts index 87b0c88b43..8cb9a3575c 100644 --- a/packages/realm-server/tests/get-boxel-claimed-domain-test.ts +++ b/packages/realm-server/tests/get-boxel-claimed-domain-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename, join } from 'path'; import type { PgAdapter } from '@cardstack/postgres'; import type { User } from '@cardstack/runtime-common'; diff --git a/packages/realm-server/tests/helpers/index.ts b/packages/realm-server/tests/helpers/index.ts index ce394a9727..74dc7f5ac5 100644 --- a/packages/realm-server/tests/helpers/index.ts +++ b/packages/realm-server/tests/helpers/index.ts @@ -40,7 +40,8 @@ import { resetCatalogRealms } from '../../handlers/handle-fetch-catalog-realms.t import { dirSync, setGracefulCleanup, type DirResult } from 'tmp'; import { getLocalConfig as getSynapseConfig } from '../../synapse.ts'; import { RealmServer } from '../../server.ts'; -import { sign as jwtSign } from 'jsonwebtoken'; +import jsonwebtoken from 'jsonwebtoken'; +const { sign: jwtSign } = jsonwebtoken; import { RealmRegistryReconciler, type RealmRegistryRow, diff --git a/packages/realm-server/tests/host-routing-validation-test.ts b/packages/realm-server/tests/host-routing-validation-test.ts index d29aac4ed4..941e3290a3 100644 --- a/packages/realm-server/tests/host-routing-validation-test.ts +++ b/packages/realm-server/tests/host-routing-validation-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { runSharedTest } from '@cardstack/runtime-common/helpers'; import hostRoutingValidationTests from '@cardstack/runtime-common/tests/host-routing-validation-test'; diff --git a/packages/realm-server/tests/http2-keepalive-test.ts b/packages/realm-server/tests/http2-keepalive-test.ts index ec027fcc00..e486c97c0e 100644 --- a/packages/realm-server/tests/http2-keepalive-test.ts +++ b/packages/realm-server/tests/http2-keepalive-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { EventEmitter } from 'events'; import type http2 from 'http2'; diff --git a/packages/realm-server/tests/index.ts b/packages/realm-server/tests/index.ts index 40d7c9366d..a0eedf609c 100644 --- a/packages/realm-server/tests/index.ts +++ b/packages/realm-server/tests/index.ts @@ -36,6 +36,21 @@ delete process.env.REALM_SERVER_TLS_KEY_FILE; } import QUnit from 'qunit'; +import { createRequire } from 'module'; + +// `require` doesn't exist in ESM scope; recreate it so the synchronous, +// order-preserving test-file loader and the lazy cleanup requires below keep +// working under native node. +const require = createRequire(import.meta.url); + +// The qunit CLI used to provide the TAP reporter, autostart, and a +// failure-based exit code. Running under `node tests/index.ts` we wire them up +// here; autostart is disabled so every test file registers before we start. +QUnit.config.autostart = false; +QUnit.reporters.tap.init(QUnit); +QUnit.on('runEnd', (data) => { + process.exitCode = data.testCounts.failed > 0 ? 1 : 0; +}); QUnit.config.testTimeout = 60000; const testModules = process.env.TEST_MODULES?.trim(); @@ -60,7 +75,7 @@ if (testModules) { // Ctrl+C or an abnormal exit (but not SIGKILL, which bypasses handlers). async function runTrackedCleanup(): Promise { // eslint-disable-next-line @typescript-eslint/no-var-requires - const helpers = require('./helpers') as { + const helpers = require('./helpers/index.ts') as { closeTrackedServers?: () => Promise; stopTrackedPrerenderers?: () => Promise; destroyTrackedQueueRunners?: () => Promise; @@ -88,7 +103,7 @@ for (let signal of ['SIGINT', 'SIGTERM', 'SIGHUP'] as const) { QUnit.done(() => { // eslint-disable-next-line @typescript-eslint/no-var-requires - const helpers = require('./helpers') as { + const helpers = require('./helpers/index.ts') as { closeTrackedServers?: () => Promise; stopTrackedPrerenderers?: () => Promise; destroyTrackedQueueRunners?: () => Promise; @@ -330,9 +345,12 @@ if (testFilesEnv) { } for (const file of filesToLoad) { - require(file); + // Explicit `.ts` — native `require` does no extension search for TypeScript. + require(`${file}.ts`); } +QUnit.start(); + function parseTestFiles(value: string): string[] { return value .split(',') diff --git a/packages/realm-server/tests/indexing-event-sink-test.ts b/packages/realm-server/tests/indexing-event-sink-test.ts index 0879533e10..07cf39d43b 100644 --- a/packages/realm-server/tests/indexing-event-sink-test.ts +++ b/packages/realm-server/tests/indexing-event-sink-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import type { DBAdapter, PgPrimitive } from '@cardstack/runtime-common'; import { IndexingEventSink } from '../indexing-event-sink.ts'; diff --git a/packages/realm-server/tests/indexing-test.ts b/packages/realm-server/tests/indexing-test.ts index 297f3fe4a5..696a9895f5 100644 --- a/packages/realm-server/tests/indexing-test.ts +++ b/packages/realm-server/tests/indexing-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { internalKeyFor, rri, diff --git a/packages/realm-server/tests/is-json-content-type-test.ts b/packages/realm-server/tests/is-json-content-type-test.ts index 33212fa566..77ec242d95 100644 --- a/packages/realm-server/tests/is-json-content-type-test.ts +++ b/packages/realm-server/tests/is-json-content-type-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { isJsonContentType } from '@cardstack/runtime-common'; diff --git a/packages/realm-server/tests/job-scoped-search-cache-test.ts b/packages/realm-server/tests/job-scoped-search-cache-test.ts index 9636d96561..08607cd1be 100644 --- a/packages/realm-server/tests/job-scoped-search-cache-test.ts +++ b/packages/realm-server/tests/job-scoped-search-cache-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import type { PgAdapter } from '@cardstack/postgres'; import { query, type Query, type Expression } from '@cardstack/runtime-common'; diff --git a/packages/realm-server/tests/jobs-finished-listener-test.ts b/packages/realm-server/tests/jobs-finished-listener-test.ts index c1cd0bd4c1..72992eac86 100644 --- a/packages/realm-server/tests/jobs-finished-listener-test.ts +++ b/packages/realm-server/tests/jobs-finished-listener-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import type { PgAdapter } from '@cardstack/postgres'; import { query, param } from '@cardstack/runtime-common'; diff --git a/packages/realm-server/tests/lazy-mount-test.ts b/packages/realm-server/tests/lazy-mount-test.ts index ca378e0a78..cb52855a21 100644 --- a/packages/realm-server/tests/lazy-mount-test.ts +++ b/packages/realm-server/tests/lazy-mount-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { dirSync } from 'tmp'; import type { PgAdapter } from '@cardstack/postgres'; diff --git a/packages/realm-server/tests/listener-dispatcher-test.ts b/packages/realm-server/tests/listener-dispatcher-test.ts index ec6886a389..70d9042b9c 100644 --- a/packages/realm-server/tests/listener-dispatcher-test.ts +++ b/packages/realm-server/tests/listener-dispatcher-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { execFileSync } from 'child_process'; import { mkdtempSync, rmSync, writeFileSync } from 'fs'; diff --git a/packages/realm-server/tests/load-links-batching-test.ts b/packages/realm-server/tests/load-links-batching-test.ts index 860cce9fbf..688d6b0e87 100644 --- a/packages/realm-server/tests/load-links-batching-test.ts +++ b/packages/realm-server/tests/load-links-batching-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { rri } from '@cardstack/runtime-common'; import type { diff --git a/packages/realm-server/tests/markdown-fallback-server-isolation-test.ts b/packages/realm-server/tests/markdown-fallback-server-isolation-test.ts index 0f01f8de27..3419625e15 100644 --- a/packages/realm-server/tests/markdown-fallback-server-isolation-test.ts +++ b/packages/realm-server/tests/markdown-fallback-server-isolation-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import * as fs from 'fs'; import * as path from 'path'; diff --git a/packages/realm-server/tests/matches-filter-integration-test.ts b/packages/realm-server/tests/matches-filter-integration-test.ts index 6429e58f57..6bdc7016c0 100644 --- a/packages/realm-server/tests/matches-filter-integration-test.ts +++ b/packages/realm-server/tests/matches-filter-integration-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import type { PgAdapter } from '@cardstack/postgres'; diff --git a/packages/realm-server/tests/module-cache-coordination-test.ts b/packages/realm-server/tests/module-cache-coordination-test.ts index de80ec23d5..347c3bf779 100644 --- a/packages/realm-server/tests/module-cache-coordination-test.ts +++ b/packages/realm-server/tests/module-cache-coordination-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import type { PgAdapter } from '@cardstack/postgres'; import { diff --git a/packages/realm-server/tests/module-cache-invalidation-listener-test.ts b/packages/realm-server/tests/module-cache-invalidation-listener-test.ts index 6360f82749..e09b2dfdca 100644 --- a/packages/realm-server/tests/module-cache-invalidation-listener-test.ts +++ b/packages/realm-server/tests/module-cache-invalidation-listener-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import type { PgAdapter } from '@cardstack/postgres'; import { diff --git a/packages/realm-server/tests/module-cache-race-test.ts b/packages/realm-server/tests/module-cache-race-test.ts index ec020e1b06..2bb72cbd81 100644 --- a/packages/realm-server/tests/module-cache-race-test.ts +++ b/packages/realm-server/tests/module-cache-race-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename, join } from 'path'; import fsExtra from 'fs-extra'; const { ensureDirSync, writeFileSync, writeJSONSync } = fsExtra; diff --git a/packages/realm-server/tests/module-syntax-test.ts b/packages/realm-server/tests/module-syntax-test.ts index b584646921..cdca609f09 100644 --- a/packages/realm-server/tests/module-syntax-test.ts +++ b/packages/realm-server/tests/module-syntax-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { ModuleSyntax, gjsToPlaceholderJS, diff --git a/packages/realm-server/tests/network-inflight-tracker-test.ts b/packages/realm-server/tests/network-inflight-tracker-test.ts index f5a17db8fc..b8aa70116a 100644 --- a/packages/realm-server/tests/network-inflight-tracker-test.ts +++ b/packages/realm-server/tests/network-inflight-tracker-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { NetworkInflightTracker } from '../prerender/network-inflight-tracker.ts'; // The tracker is the one render-hang signal that survives a wedged page diff --git a/packages/realm-server/tests/node-realm-test.ts b/packages/realm-server/tests/node-realm-test.ts index e4b569769f..252bf5c0b4 100644 --- a/packages/realm-server/tests/node-realm-test.ts +++ b/packages/realm-server/tests/node-realm-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import type { PgAdapter } from '@cardstack/postgres'; import { diff --git a/packages/realm-server/tests/normalize-realm-meta-value-test.ts b/packages/realm-server/tests/normalize-realm-meta-value-test.ts index 4d8471598f..ff2a1d3972 100644 --- a/packages/realm-server/tests/normalize-realm-meta-value-test.ts +++ b/packages/realm-server/tests/normalize-realm-meta-value-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { runSharedTest } from '@cardstack/runtime-common/helpers'; import normalizeRealmMetaValueTests from '@cardstack/runtime-common/tests/normalize-realm-meta-value-test'; diff --git a/packages/realm-server/tests/openrouter-passthrough-test.ts b/packages/realm-server/tests/openrouter-passthrough-test.ts index 0ac02d8bbe..5142e8fce1 100644 --- a/packages/realm-server/tests/openrouter-passthrough-test.ts +++ b/packages/realm-server/tests/openrouter-passthrough-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import sinon from 'sinon'; import type { Test, SuperTest } from 'supertest'; import supertest from 'supertest'; diff --git a/packages/realm-server/tests/package-shim-handler-test.ts b/packages/realm-server/tests/package-shim-handler-test.ts index 5697443f6e..23a8186b49 100644 --- a/packages/realm-server/tests/package-shim-handler-test.ts +++ b/packages/realm-server/tests/package-shim-handler-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { runSharedTest } from '@cardstack/runtime-common/helpers'; import packageShimHandlerTests from '@cardstack/runtime-common/tests/package-shim-handler-test'; diff --git a/packages/realm-server/tests/page-pool-cert-verifier-retry-test.ts b/packages/realm-server/tests/page-pool-cert-verifier-retry-test.ts index 1b8b20aef6..9137a27672 100644 --- a/packages/realm-server/tests/page-pool-cert-verifier-retry-test.ts +++ b/packages/realm-server/tests/page-pool-cert-verifier-retry-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { PagePool } from '../prerender/page-pool.ts'; diff --git a/packages/realm-server/tests/page-pool-eviction-recovery-test.ts b/packages/realm-server/tests/page-pool-eviction-recovery-test.ts index 7cdc86c87f..20422372fe 100644 --- a/packages/realm-server/tests/page-pool-eviction-recovery-test.ts +++ b/packages/realm-server/tests/page-pool-eviction-recovery-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { PagePool } from '../prerender/page-pool.ts'; diff --git a/packages/realm-server/tests/page-pool-expansion-test.ts b/packages/realm-server/tests/page-pool-expansion-test.ts index d32786e3f1..86e9174db8 100644 --- a/packages/realm-server/tests/page-pool-expansion-test.ts +++ b/packages/realm-server/tests/page-pool-expansion-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { PagePool } from '../prerender/page-pool.ts'; import { AsyncSemaphore } from '../prerender/async-semaphore.ts'; diff --git a/packages/realm-server/tests/page-pool-priority-test.ts b/packages/realm-server/tests/page-pool-priority-test.ts index 0532d6f5cb..3ba87038a3 100644 --- a/packages/realm-server/tests/page-pool-priority-test.ts +++ b/packages/realm-server/tests/page-pool-priority-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { AsyncSemaphore } from '../prerender/async-semaphore.ts'; import { TabQueue } from '../prerender/page-pool.ts'; diff --git a/packages/realm-server/tests/page-pool-standby-refill-test.ts b/packages/realm-server/tests/page-pool-standby-refill-test.ts index 01d4aae8eb..42da12180f 100644 --- a/packages/realm-server/tests/page-pool-standby-refill-test.ts +++ b/packages/realm-server/tests/page-pool-standby-refill-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { PagePool } from '../prerender/page-pool.ts'; diff --git a/packages/realm-server/tests/permissions/permission-checker-test.ts b/packages/realm-server/tests/permissions/permission-checker-test.ts index b926759ab3..89dc2de61d 100644 --- a/packages/realm-server/tests/permissions/permission-checker-test.ts +++ b/packages/realm-server/tests/permissions/permission-checker-test.ts @@ -1,7 +1,8 @@ import type { MatrixClient } from '@cardstack/runtime-common/matrix-client'; import RealmPermissionChecker from '@cardstack/runtime-common/realm-permission-checker'; import { basename } from 'path'; -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; let matrixUserProfile: { displayname: string } | undefined = undefined; let mockMatrixClient = { diff --git a/packages/realm-server/tests/pg-adapter-subscribe-test.ts b/packages/realm-server/tests/pg-adapter-subscribe-test.ts index 2cca73278e..f75773dd49 100644 --- a/packages/realm-server/tests/pg-adapter-subscribe-test.ts +++ b/packages/realm-server/tests/pg-adapter-subscribe-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import type { PgAdapter } from '@cardstack/postgres'; import { query, param } from '@cardstack/runtime-common'; diff --git a/packages/realm-server/tests/prerender-affinity-activity-test.ts b/packages/realm-server/tests/prerender-affinity-activity-test.ts index 7b644963a7..9eabe2c803 100644 --- a/packages/realm-server/tests/prerender-affinity-activity-test.ts +++ b/packages/realm-server/tests/prerender-affinity-activity-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { AffinityActivityTracker } from '../prerender/affinity-activity.ts'; diff --git a/packages/realm-server/tests/prerender-artifact-sink-test.ts b/packages/realm-server/tests/prerender-artifact-sink-test.ts index 587a83b5ee..6f5676be11 100644 --- a/packages/realm-server/tests/prerender-artifact-sink-test.ts +++ b/packages/realm-server/tests/prerender-artifact-sink-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { buildArtifactKey, getMaxSessionBytes, diff --git a/packages/realm-server/tests/prerender-batch-ownership-test.ts b/packages/realm-server/tests/prerender-batch-ownership-test.ts index 2166da1699..d701a018d4 100644 --- a/packages/realm-server/tests/prerender-batch-ownership-test.ts +++ b/packages/realm-server/tests/prerender-batch-ownership-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { computeBatchClearCacheGate, diff --git a/packages/realm-server/tests/prerender-cancellation-test.ts b/packages/realm-server/tests/prerender-cancellation-test.ts index 6a009efde1..8ca6e3ff57 100644 --- a/packages/realm-server/tests/prerender-cancellation-test.ts +++ b/packages/realm-server/tests/prerender-cancellation-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { PrerenderCancelledError, diff --git a/packages/realm-server/tests/prerender-deadlock-test.ts b/packages/realm-server/tests/prerender-deadlock-test.ts index 1f433e9377..2cdffc7f84 100644 --- a/packages/realm-server/tests/prerender-deadlock-test.ts +++ b/packages/realm-server/tests/prerender-deadlock-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { PagePool } from '../prerender/page-pool.ts'; import { AsyncSemaphore } from '../prerender/async-semaphore.ts'; diff --git a/packages/realm-server/tests/prerender-diagnostics-persistence-test.ts b/packages/realm-server/tests/prerender-diagnostics-persistence-test.ts index fcf32e5b95..1f75adbbb6 100644 --- a/packages/realm-server/tests/prerender-diagnostics-persistence-test.ts +++ b/packages/realm-server/tests/prerender-diagnostics-persistence-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { Prerenderer } from '../prerender/prerenderer.ts'; import { decorateRenderErrorDiagnostics } from '../prerender/prerender-app.ts'; diff --git a/packages/realm-server/tests/prerender-manager-test.ts b/packages/realm-server/tests/prerender-manager-test.ts index ac10b64ed0..25f65b2631 100644 --- a/packages/realm-server/tests/prerender-manager-test.ts +++ b/packages/realm-server/tests/prerender-manager-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { SuperTest, Test } from 'supertest'; import supertest from 'supertest'; import { basename } from 'path'; diff --git a/packages/realm-server/tests/prerender-proxy-test.ts b/packages/realm-server/tests/prerender-proxy-test.ts index a94ba62865..af851a79fd 100644 --- a/packages/realm-server/tests/prerender-proxy-test.ts +++ b/packages/realm-server/tests/prerender-proxy-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import Koa from 'koa'; import Router from '@koa/router'; import supertest from 'supertest'; diff --git a/packages/realm-server/tests/prerender-server-test.ts b/packages/realm-server/tests/prerender-server-test.ts index c9c3a75627..5cd427b379 100644 --- a/packages/realm-server/tests/prerender-server-test.ts +++ b/packages/realm-server/tests/prerender-server-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { SuperTest, Test } from 'supertest'; import supertest from 'supertest'; import { basename } from 'path'; diff --git a/packages/realm-server/tests/prerender-v8-prof-test.ts b/packages/realm-server/tests/prerender-v8-prof-test.ts index 5291825608..2a05e128fe 100644 --- a/packages/realm-server/tests/prerender-v8-prof-test.ts +++ b/packages/realm-server/tests/prerender-v8-prof-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { promises as fs } from 'fs'; import path from 'path'; import { diff --git a/packages/realm-server/tests/prerendering-test.ts b/packages/realm-server/tests/prerendering-test.ts index 281a59e60f..ec775d5bdd 100644 --- a/packages/realm-server/tests/prerendering-test.ts +++ b/packages/realm-server/tests/prerendering-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import type { RealmPermissions, diff --git a/packages/realm-server/tests/publish-unpublish-realm-test.ts b/packages/realm-server/tests/publish-unpublish-realm-test.ts index 454da5e6ee..c49e6d9b84 100644 --- a/packages/realm-server/tests/publish-unpublish-realm-test.ts +++ b/packages/realm-server/tests/publish-unpublish-realm-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { SuperTest, Test } from 'supertest'; import supertest from 'supertest'; import { v4 as uuidv4 } from 'uuid'; diff --git a/packages/realm-server/tests/queries-test.ts b/packages/realm-server/tests/queries-test.ts index 0b40da1935..39b2bf5a0f 100644 --- a/packages/realm-server/tests/queries-test.ts +++ b/packages/realm-server/tests/queries-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { v4 as uuidv4 } from 'uuid'; diff --git a/packages/realm-server/tests/query-matches-filter-test.ts b/packages/realm-server/tests/query-matches-filter-test.ts index 8cf0edbef7..61e56a5485 100644 --- a/packages/realm-server/tests/query-matches-filter-test.ts +++ b/packages/realm-server/tests/query-matches-filter-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { runSharedTest } from '@cardstack/runtime-common/helpers'; import queryMatchesFilterTests from '@cardstack/runtime-common/tests/query-matches-filter-test'; diff --git a/packages/realm-server/tests/queue-test.ts b/packages/realm-server/tests/queue-test.ts index 0c8293a482..22d941f776 100644 --- a/packages/realm-server/tests/queue-test.ts +++ b/packages/realm-server/tests/queue-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { createTestPgAdapter, prepareTestDB } from './helpers/index.ts'; import { diff --git a/packages/realm-server/tests/realm-advisory-locks-test.ts b/packages/realm-server/tests/realm-advisory-locks-test.ts index 202a2f7c03..096be55899 100644 --- a/packages/realm-server/tests/realm-advisory-locks-test.ts +++ b/packages/realm-server/tests/realm-advisory-locks-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { hashRealmUrlForAdvisoryLock, diff --git a/packages/realm-server/tests/realm-auth-test.ts b/packages/realm-server/tests/realm-auth-test.ts index 7b12c1657e..e063050dab 100644 --- a/packages/realm-server/tests/realm-auth-test.ts +++ b/packages/realm-server/tests/realm-auth-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { SuperTest, Test as SupertestTest } from 'supertest'; import sinon from 'sinon'; import { basename } from 'path'; diff --git a/packages/realm-server/tests/realm-cleanup-transaction-test.ts b/packages/realm-server/tests/realm-cleanup-transaction-test.ts index c6e22c66d2..3ad660bf2c 100644 --- a/packages/realm-server/tests/realm-cleanup-transaction-test.ts +++ b/packages/realm-server/tests/realm-cleanup-transaction-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import type { PgAdapter } from '@cardstack/postgres'; import { diff --git a/packages/realm-server/tests/realm-endpoints/cancel-indexing-job-test.ts b/packages/realm-server/tests/realm-endpoints/cancel-indexing-job-test.ts index e08edee8ca..9e59a58243 100644 --- a/packages/realm-server/tests/realm-endpoints/cancel-indexing-job-test.ts +++ b/packages/realm-server/tests/realm-endpoints/cancel-indexing-job-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import type { SuperTest, Test } from 'supertest'; import type { diff --git a/packages/realm-server/tests/realm-endpoints/dependencies-test.ts b/packages/realm-server/tests/realm-endpoints/dependencies-test.ts index 4678219e7d..7724bb1712 100644 --- a/packages/realm-server/tests/realm-endpoints/dependencies-test.ts +++ b/packages/realm-server/tests/realm-endpoints/dependencies-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { SuperTest, Test } from 'supertest'; import { basename } from 'path'; import type { Realm } from '@cardstack/runtime-common'; diff --git a/packages/realm-server/tests/realm-endpoints/directory-test.ts b/packages/realm-server/tests/realm-endpoints/directory-test.ts index 5b9e6359ff..ed00f210de 100644 --- a/packages/realm-server/tests/realm-endpoints/directory-test.ts +++ b/packages/realm-server/tests/realm-endpoints/directory-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { Test, SuperTest } from 'supertest'; import { basename } from 'path'; import type { Realm } from '@cardstack/runtime-common'; diff --git a/packages/realm-server/tests/realm-endpoints/indexing-errors-test.ts b/packages/realm-server/tests/realm-endpoints/indexing-errors-test.ts index cc98d408d2..99fb462757 100644 --- a/packages/realm-server/tests/realm-endpoints/indexing-errors-test.ts +++ b/packages/realm-server/tests/realm-endpoints/indexing-errors-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import supertest from 'supertest'; import type { SuperTest, Test } from 'supertest'; diff --git a/packages/realm-server/tests/realm-endpoints/info-test.ts b/packages/realm-server/tests/realm-endpoints/info-test.ts index 6b62c582dd..bbbfcc0395 100644 --- a/packages/realm-server/tests/realm-endpoints/info-test.ts +++ b/packages/realm-server/tests/realm-endpoints/info-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { Test, SuperTest } from 'supertest'; import { basename } from 'path'; import type { RealmHttpServer as Server } from '../../server.ts'; diff --git a/packages/realm-server/tests/realm-endpoints/invalidate-urls-test.ts b/packages/realm-server/tests/realm-endpoints/invalidate-urls-test.ts index 963d6be83d..bdb7822096 100644 --- a/packages/realm-server/tests/realm-endpoints/invalidate-urls-test.ts +++ b/packages/realm-server/tests/realm-endpoints/invalidate-urls-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import type { SuperTest, Test } from 'supertest'; import type { Realm } from '@cardstack/runtime-common'; diff --git a/packages/realm-server/tests/realm-endpoints/lint-test.ts b/packages/realm-server/tests/realm-endpoints/lint-test.ts index 63ef41f873..984003c47d 100644 --- a/packages/realm-server/tests/realm-endpoints/lint-test.ts +++ b/packages/realm-server/tests/realm-endpoints/lint-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { Test, SuperTest } from 'supertest'; import { basename } from 'path'; import type { Realm } from '@cardstack/runtime-common'; diff --git a/packages/realm-server/tests/realm-endpoints/markdown-test.ts b/packages/realm-server/tests/realm-endpoints/markdown-test.ts index 2cb7dbbc25..8090f7cf5c 100644 --- a/packages/realm-server/tests/realm-endpoints/markdown-test.ts +++ b/packages/realm-server/tests/realm-endpoints/markdown-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { SuperTest, Test } from 'supertest'; import { basename } from 'path'; import type { Realm } from '@cardstack/runtime-common'; diff --git a/packages/realm-server/tests/realm-endpoints/mtimes-test.ts b/packages/realm-server/tests/realm-endpoints/mtimes-test.ts index 270aef12a5..b3c83aa05b 100644 --- a/packages/realm-server/tests/realm-endpoints/mtimes-test.ts +++ b/packages/realm-server/tests/realm-endpoints/mtimes-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { Test, SuperTest } from 'supertest'; import { basename } from 'path'; import type { Realm } from '@cardstack/runtime-common'; diff --git a/packages/realm-server/tests/realm-endpoints/permissions-test.ts b/packages/realm-server/tests/realm-endpoints/permissions-test.ts index 63fc7df534..181bdb67f7 100644 --- a/packages/realm-server/tests/realm-endpoints/permissions-test.ts +++ b/packages/realm-server/tests/realm-endpoints/permissions-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { Test, SuperTest } from 'supertest'; import { basename } from 'path'; import type { Realm } from '@cardstack/runtime-common'; diff --git a/packages/realm-server/tests/realm-endpoints/publishability-test.ts b/packages/realm-server/tests/realm-endpoints/publishability-test.ts index 1f09e7a1e6..e28ec6c421 100644 --- a/packages/realm-server/tests/realm-endpoints/publishability-test.ts +++ b/packages/realm-server/tests/realm-endpoints/publishability-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import supertest from 'supertest'; import type { SuperTest, Test } from 'supertest'; diff --git a/packages/realm-server/tests/realm-endpoints/reindex-test.ts b/packages/realm-server/tests/realm-endpoints/reindex-test.ts index 862e72b14b..1bee35981d 100644 --- a/packages/realm-server/tests/realm-endpoints/reindex-test.ts +++ b/packages/realm-server/tests/realm-endpoints/reindex-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename, join } from 'path'; import { readFileSync, utimesSync, writeFileSync } from 'fs'; import type { SuperTest, Test } from 'supertest'; diff --git a/packages/realm-server/tests/realm-endpoints/search-test.ts b/packages/realm-server/tests/realm-endpoints/search-test.ts index dc7d8d2355..8a09526c97 100644 --- a/packages/realm-server/tests/realm-endpoints/search-test.ts +++ b/packages/realm-server/tests/realm-endpoints/search-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { Test, SuperTest } from 'supertest'; import { basename } from 'path'; import { baseRealm, baseRRI, type Realm, rri } from '@cardstack/runtime-common'; diff --git a/packages/realm-server/tests/realm-endpoints/search-v2-test.ts b/packages/realm-server/tests/realm-endpoints/search-v2-test.ts index dcf27052ad..21b42b030d 100644 --- a/packages/realm-server/tests/realm-endpoints/search-v2-test.ts +++ b/packages/realm-server/tests/realm-endpoints/search-v2-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { Test, SuperTest } from 'supertest'; import { basename } from 'path'; import { rri, type Realm } from '@cardstack/runtime-common'; diff --git a/packages/realm-server/tests/realm-endpoints/user-test.ts b/packages/realm-server/tests/realm-endpoints/user-test.ts index 0b6dea97a1..f1d66ed573 100644 --- a/packages/realm-server/tests/realm-endpoints/user-test.ts +++ b/packages/realm-server/tests/realm-endpoints/user-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { Test, SuperTest } from 'supertest'; import { basename } from 'path'; import type { RealmHttpServer as Server } from '../../server.ts'; diff --git a/packages/realm-server/tests/realm-file-changes-listener-test.ts b/packages/realm-server/tests/realm-file-changes-listener-test.ts index 85bed03e68..e97f417fa5 100644 --- a/packages/realm-server/tests/realm-file-changes-listener-test.ts +++ b/packages/realm-server/tests/realm-file-changes-listener-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import type { PgAdapter } from '@cardstack/postgres'; import { notifyAllFileChanges, type Realm } from '@cardstack/runtime-common'; diff --git a/packages/realm-server/tests/realm-identifiers-test.ts b/packages/realm-server/tests/realm-identifiers-test.ts index d18bfaa413..de2eb6717f 100644 --- a/packages/realm-server/tests/realm-identifiers-test.ts +++ b/packages/realm-server/tests/realm-identifiers-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { RealmPaths, VirtualNetwork } from '@cardstack/runtime-common'; import { ri, rri } from '@cardstack/runtime-common'; diff --git a/packages/realm-server/tests/realm-index-updated-listener-test.ts b/packages/realm-server/tests/realm-index-updated-listener-test.ts index b7ee54ad4b..0466f6886a 100644 --- a/packages/realm-server/tests/realm-index-updated-listener-test.ts +++ b/packages/realm-server/tests/realm-index-updated-listener-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import type { PgAdapter } from '@cardstack/postgres'; import type { Realm } from '@cardstack/runtime-common'; diff --git a/packages/realm-server/tests/realm-operations-test.ts b/packages/realm-server/tests/realm-operations-test.ts index d2dcea20ad..a65ab67397 100644 --- a/packages/realm-server/tests/realm-operations-test.ts +++ b/packages/realm-server/tests/realm-operations-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { checkDomainAvailability, diff --git a/packages/realm-server/tests/realm-registry-backfill-test.ts b/packages/realm-server/tests/realm-registry-backfill-test.ts index 9fe9942245..ea70fcc1ae 100644 --- a/packages/realm-server/tests/realm-registry-backfill-test.ts +++ b/packages/realm-server/tests/realm-registry-backfill-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename, join } from 'path'; import { dirSync, type DirResult } from 'tmp'; import fsExtra from 'fs-extra'; diff --git a/packages/realm-server/tests/realm-registry-reconciler-test.ts b/packages/realm-server/tests/realm-registry-reconciler-test.ts index b62614403d..28b8f4e369 100644 --- a/packages/realm-server/tests/realm-registry-reconciler-test.ts +++ b/packages/realm-server/tests/realm-registry-reconciler-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import type { PgAdapter } from '@cardstack/postgres'; import type { Realm } from '@cardstack/runtime-common'; diff --git a/packages/realm-server/tests/realm-registry-writes-test.ts b/packages/realm-server/tests/realm-registry-writes-test.ts index 8c9e25635b..082551016a 100644 --- a/packages/realm-server/tests/realm-registry-writes-test.ts +++ b/packages/realm-server/tests/realm-registry-writes-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import type { PgAdapter } from '@cardstack/postgres'; import { asExpressions, insert, query } from '@cardstack/runtime-common'; diff --git a/packages/realm-server/tests/realm-routing-test.ts b/packages/realm-server/tests/realm-routing-test.ts index 769cef60a8..cfe32570a3 100644 --- a/packages/realm-server/tests/realm-routing-test.ts +++ b/packages/realm-server/tests/realm-routing-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { rri } from '@cardstack/runtime-common'; import type { LooseSingleCardDocument, Realm } from '@cardstack/runtime-common'; diff --git a/packages/realm-server/tests/remote-prerenderer-test.ts b/packages/realm-server/tests/remote-prerenderer-test.ts index cbe36f5186..afaff3f4b5 100644 --- a/packages/realm-server/tests/remote-prerenderer-test.ts +++ b/packages/realm-server/tests/remote-prerenderer-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { createServer } from 'http'; import { createRemotePrerenderer } from '../prerender/remote-prerenderer.ts'; diff --git a/packages/realm-server/tests/render-type-resolution-test.ts b/packages/realm-server/tests/render-type-resolution-test.ts index 8cfeb64bf7..5202cf1fa2 100644 --- a/packages/realm-server/tests/render-type-resolution-test.ts +++ b/packages/realm-server/tests/render-type-resolution-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { parseUnifiedSearchRequestFromPayload, diff --git a/packages/realm-server/tests/request-forward-test.ts b/packages/realm-server/tests/request-forward-test.ts index fd15beb13a..532724acf3 100644 --- a/packages/realm-server/tests/request-forward-test.ts +++ b/packages/realm-server/tests/request-forward-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import sinon from 'sinon'; import type { Test, SuperTest } from 'supertest'; import supertest from 'supertest'; diff --git a/packages/realm-server/tests/resolve-published-realm-url-test.ts b/packages/realm-server/tests/resolve-published-realm-url-test.ts index a07849e460..0cf2a73351 100644 --- a/packages/realm-server/tests/resolve-published-realm-url-test.ts +++ b/packages/realm-server/tests/resolve-published-realm-url-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { deriveRealmName, diff --git a/packages/realm-server/tests/run-command-task-test.ts b/packages/realm-server/tests/run-command-task-test.ts index 2d4e8b2004..16c1117eb6 100644 --- a/packages/realm-server/tests/run-command-task-test.ts +++ b/packages/realm-server/tests/run-command-task-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { runSharedTest } from '@cardstack/runtime-common/helpers'; import runCommandTaskTests from '@cardstack/runtime-common/tests/run-command-task-shared-tests'; diff --git a/packages/realm-server/tests/runtime-dependency-tracker-test.ts b/packages/realm-server/tests/runtime-dependency-tracker-test.ts index f0f69baf13..8975ed0712 100644 --- a/packages/realm-server/tests/runtime-dependency-tracker-test.ts +++ b/packages/realm-server/tests/runtime-dependency-tracker-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { Loader, diff --git a/packages/realm-server/tests/runtime-exception-capture-test.ts b/packages/realm-server/tests/runtime-exception-capture-test.ts index bdc125d95e..1b29f479f5 100644 --- a/packages/realm-server/tests/runtime-exception-capture-test.ts +++ b/packages/realm-server/tests/runtime-exception-capture-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { EventEmitter } from 'events'; import { attachRuntimeExceptionCapture } from '../prerender/runtime-exception-capture.ts'; diff --git a/packages/realm-server/tests/sanitize-for-jsonb-test.ts b/packages/realm-server/tests/sanitize-for-jsonb-test.ts index 7ac2adfba7..ced91212bf 100644 --- a/packages/realm-server/tests/sanitize-for-jsonb-test.ts +++ b/packages/realm-server/tests/sanitize-for-jsonb-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { sanitizeForJsonb } from '@cardstack/runtime-common'; diff --git a/packages/realm-server/tests/sanitize-head-html-test.ts b/packages/realm-server/tests/sanitize-head-html-test.ts index 942319b17e..c31f510b84 100644 --- a/packages/realm-server/tests/sanitize-head-html-test.ts +++ b/packages/realm-server/tests/sanitize-head-html-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { JSDOM } from 'jsdom'; import { diff --git a/packages/realm-server/tests/screenshot-card-test.ts b/packages/realm-server/tests/screenshot-card-test.ts index 9f39b57851..a5a079f206 100644 --- a/packages/realm-server/tests/screenshot-card-test.ts +++ b/packages/realm-server/tests/screenshot-card-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import Koa from 'koa'; import Router from '@koa/router'; import supertest from 'supertest'; diff --git a/packages/realm-server/tests/scripts/run-qunit-with-test-pg.sh b/packages/realm-server/tests/scripts/run-qunit-with-test-pg.sh index 3796ca8455..8a236da66c 100755 --- a/packages/realm-server/tests/scripts/run-qunit-with-test-pg.sh +++ b/packages/realm-server/tests/scripts/run-qunit-with-test-pg.sh @@ -16,7 +16,7 @@ fi JUNIT_REPORTER_ARGS=() if [ -n "${JUNIT_OUTPUT_FILE-}" ]; then - JUNIT_REPORTER_ARGS=(--require "${SCRIPT_DIR}/../../scripts/junit-reporter.js") + JUNIT_REPORTER_ARGS=(--require "${SCRIPT_DIR}/../../scripts/junit-reporter.cjs") fi # Trust mkcert's local CA so test fetches to the dev stack on HTTPS @@ -45,4 +45,4 @@ NODE_DISABLE_COMPILE_CACHE=1 \ PGPORT=55436 \ STRIPE_WEBHOOK_SECRET=stripe-webhook-secret \ STRIPE_API_KEY=stripe-api-key \ -qunit --require ts-node/register/transpile-only ${JUNIT_REPORTER_ARGS[@]+"${JUNIT_REPORTER_ARGS[@]}"} "$@" tests/index.ts +node ${JUNIT_REPORTER_ARGS[@]+"${JUNIT_REPORTER_ARGS[@]}"} tests/index.ts "$@" diff --git a/packages/realm-server/tests/search-compat-test.ts b/packages/realm-server/tests/search-compat-test.ts index 1bbeb15bc7..d76cb84ce1 100644 --- a/packages/realm-server/tests/search-compat-test.ts +++ b/packages/realm-server/tests/search-compat-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { searchEntryDocToPrerenderedDoc, diff --git a/packages/realm-server/tests/search-entries-engine-test.ts b/packages/realm-server/tests/search-entries-engine-test.ts index 1cc7fd4971..2ffaf9f649 100644 --- a/packages/realm-server/tests/search-entries-engine-test.ts +++ b/packages/realm-server/tests/search-entries-engine-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { baseRRI, diff --git a/packages/realm-server/tests/search-entry-test.ts b/packages/realm-server/tests/search-entry-test.ts index d18960b651..d8b5170d61 100644 --- a/packages/realm-server/tests/search-entry-test.ts +++ b/packages/realm-server/tests/search-entry-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { buildHtmlResource, diff --git a/packages/realm-server/tests/search-in-flight-key-test.ts b/packages/realm-server/tests/search-in-flight-key-test.ts index 1d4f3bb159..d58f74d1a8 100644 --- a/packages/realm-server/tests/search-in-flight-key-test.ts +++ b/packages/realm-server/tests/search-in-flight-key-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { runSharedTest } from '@cardstack/runtime-common/helpers'; import searchInFlightKeyTests from '@cardstack/runtime-common/tests/search-in-flight-key-test'; diff --git a/packages/realm-server/tests/search-prerendered-test.ts b/packages/realm-server/tests/search-prerendered-test.ts index 5e43f16343..00c8fc50b0 100644 --- a/packages/realm-server/tests/search-prerendered-test.ts +++ b/packages/realm-server/tests/search-prerendered-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { Test, SuperTest } from 'supertest'; import { basename } from 'path'; import type { Realm } from '@cardstack/runtime-common'; diff --git a/packages/realm-server/tests/serve-index-test.ts b/packages/realm-server/tests/serve-index-test.ts index 2fc9f1aa4d..d880780032 100644 --- a/packages/realm-server/tests/serve-index-test.ts +++ b/packages/realm-server/tests/serve-index-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { createServeIndex } from '../handlers/serve-index.ts'; diff --git a/packages/realm-server/tests/server-config-test.ts b/packages/realm-server/tests/server-config-test.ts index 2e3d122557..b248da5a5e 100644 --- a/packages/realm-server/tests/server-config-test.ts +++ b/packages/realm-server/tests/server-config-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { createServeIndex } from '../handlers/serve-index.ts'; diff --git a/packages/realm-server/tests/server-endpoints/authentication-test.ts b/packages/realm-server/tests/server-endpoints/authentication-test.ts index 87df3fd608..3556b4a820 100644 --- a/packages/realm-server/tests/server-endpoints/authentication-test.ts +++ b/packages/realm-server/tests/server-endpoints/authentication-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import type { Test, SuperTest } from 'supertest'; import type { RealmHttpServer as Server } from '../../server.ts'; diff --git a/packages/realm-server/tests/server-endpoints/bot-commands-test.ts b/packages/realm-server/tests/server-endpoints/bot-commands-test.ts index 403e2b1357..f2d97ba08d 100644 --- a/packages/realm-server/tests/server-endpoints/bot-commands-test.ts +++ b/packages/realm-server/tests/server-endpoints/bot-commands-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { createJWT as createRealmServerJWT } from '../../utils/jwt.ts'; import { realmSecretSeed, insertUser } from '../helpers/index.ts'; diff --git a/packages/realm-server/tests/server-endpoints/bot-registration-test.ts b/packages/realm-server/tests/server-endpoints/bot-registration-test.ts index 5b4a5a527f..8ad2af2f3b 100644 --- a/packages/realm-server/tests/server-endpoints/bot-registration-test.ts +++ b/packages/realm-server/tests/server-endpoints/bot-registration-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { createJWT as createRealmServerJWT } from '../../utils/jwt.ts'; import { realmSecretSeed, insertUser } from '../helpers/index.ts'; diff --git a/packages/realm-server/tests/server-endpoints/delete-realm-test.ts b/packages/realm-server/tests/server-endpoints/delete-realm-test.ts index e4d6d44e36..8bcae9ac43 100644 --- a/packages/realm-server/tests/server-endpoints/delete-realm-test.ts +++ b/packages/realm-server/tests/server-endpoints/delete-realm-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename, join } from 'path'; import fsExtra from 'fs-extra'; const { existsSync } = fsExtra; diff --git a/packages/realm-server/tests/server-endpoints/download-realm-test.ts b/packages/realm-server/tests/server-endpoints/download-realm-test.ts index f2545684c4..447b9978df 100644 --- a/packages/realm-server/tests/server-endpoints/download-realm-test.ts +++ b/packages/realm-server/tests/server-endpoints/download-realm-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename, join } from 'path'; import { mkdirSync, writeFileSync } from 'fs'; import { v4 as uuidv4 } from 'uuid'; diff --git a/packages/realm-server/tests/server-endpoints/federated-types-test.ts b/packages/realm-server/tests/server-endpoints/federated-types-test.ts index 2092fc2d47..00414ea12e 100644 --- a/packages/realm-server/tests/server-endpoints/federated-types-test.ts +++ b/packages/realm-server/tests/server-endpoints/federated-types-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import supertest from 'supertest'; import type { Test, SuperTest } from 'supertest'; import { basename, join } from 'path'; diff --git a/packages/realm-server/tests/server-endpoints/incoming-webhook-test.ts b/packages/realm-server/tests/server-endpoints/incoming-webhook-test.ts index 13a8d40902..5f45150486 100644 --- a/packages/realm-server/tests/server-endpoints/incoming-webhook-test.ts +++ b/packages/realm-server/tests/server-endpoints/incoming-webhook-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { createJWT as createRealmServerJWT } from '../../utils/jwt.ts'; import { realmSecretSeed, insertUser } from '../helpers/index.ts'; diff --git a/packages/realm-server/tests/server-endpoints/index-responses-test.ts b/packages/realm-server/tests/server-endpoints/index-responses-test.ts index 7658ee268f..130373fb03 100644 --- a/packages/realm-server/tests/server-endpoints/index-responses-test.ts +++ b/packages/realm-server/tests/server-endpoints/index-responses-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { join, basename } from 'path'; import supertest from 'supertest'; import type { Test, SuperTest } from 'supertest'; diff --git a/packages/realm-server/tests/server-endpoints/info-test.ts b/packages/realm-server/tests/server-endpoints/info-test.ts index 303ba3e03d..174deb272a 100644 --- a/packages/realm-server/tests/server-endpoints/info-test.ts +++ b/packages/realm-server/tests/server-endpoints/info-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import supertest from 'supertest'; import type { Test, SuperTest } from 'supertest'; import { basename, join } from 'path'; diff --git a/packages/realm-server/tests/server-endpoints/maintenance-endpoints-test.ts b/packages/realm-server/tests/server-endpoints/maintenance-endpoints-test.ts index af1755708b..956db024df 100644 --- a/packages/realm-server/tests/server-endpoints/maintenance-endpoints-test.ts +++ b/packages/realm-server/tests/server-endpoints/maintenance-endpoints-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { v4 as uuidv4 } from 'uuid'; import sinon from 'sinon'; diff --git a/packages/realm-server/tests/server-endpoints/queue-status-test.ts b/packages/realm-server/tests/server-endpoints/queue-status-test.ts index effb92289e..629d55ffe1 100644 --- a/packages/realm-server/tests/server-endpoints/queue-status-test.ts +++ b/packages/realm-server/tests/server-endpoints/queue-status-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import type { Test, SuperTest } from 'supertest'; import type { PgAdapter } from '@cardstack/postgres'; diff --git a/packages/realm-server/tests/server-endpoints/realm-lifecycle-test.ts b/packages/realm-server/tests/server-endpoints/realm-lifecycle-test.ts index c631fa3be2..b0f5604249 100644 --- a/packages/realm-server/tests/server-endpoints/realm-lifecycle-test.ts +++ b/packages/realm-server/tests/server-endpoints/realm-lifecycle-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename, join } from 'path'; import fsExtra from 'fs-extra'; const { existsSync, readJSONSync } = fsExtra; diff --git a/packages/realm-server/tests/server-endpoints/run-command-endpoint-test.ts b/packages/realm-server/tests/server-endpoints/run-command-endpoint-test.ts index 2ba8c4af5b..57360a8f0b 100644 --- a/packages/realm-server/tests/server-endpoints/run-command-endpoint-test.ts +++ b/packages/realm-server/tests/server-endpoints/run-command-endpoint-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { createJWT as createRealmServerJWT } from '../../utils/jwt.ts'; import { realmSecretSeed, insertUser } from '../helpers/index.ts'; diff --git a/packages/realm-server/tests/server-endpoints/screenshot-card-endpoint-test.ts b/packages/realm-server/tests/server-endpoints/screenshot-card-endpoint-test.ts index 97a36625fe..cfe28ac17b 100644 --- a/packages/realm-server/tests/server-endpoints/screenshot-card-endpoint-test.ts +++ b/packages/realm-server/tests/server-endpoints/screenshot-card-endpoint-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { createJWT as createRealmServerJWT } from '../../utils/jwt.ts'; import { realmSecretSeed, insertUser } from '../helpers/index.ts'; diff --git a/packages/realm-server/tests/server-endpoints/search-prerendered-test.ts b/packages/realm-server/tests/server-endpoints/search-prerendered-test.ts index ff480dba0c..1312eda453 100644 --- a/packages/realm-server/tests/server-endpoints/search-prerendered-test.ts +++ b/packages/realm-server/tests/server-endpoints/search-prerendered-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import supertest from 'supertest'; import type { Test, SuperTest } from 'supertest'; import { basename, join } from 'path'; diff --git a/packages/realm-server/tests/server-endpoints/search-test.ts b/packages/realm-server/tests/server-endpoints/search-test.ts index 4932a01f00..e11c9fb85e 100644 --- a/packages/realm-server/tests/server-endpoints/search-test.ts +++ b/packages/realm-server/tests/server-endpoints/search-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import supertest from 'supertest'; import type { Test, SuperTest } from 'supertest'; import { basename, join } from 'path'; diff --git a/packages/realm-server/tests/server-endpoints/search-v2-test.ts b/packages/realm-server/tests/server-endpoints/search-v2-test.ts index a3086a46ad..7fd5a09e98 100644 --- a/packages/realm-server/tests/server-endpoints/search-v2-test.ts +++ b/packages/realm-server/tests/server-endpoints/search-v2-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import supertest from 'supertest'; import type { Test, SuperTest } from 'supertest'; import { basename, join } from 'path'; diff --git a/packages/realm-server/tests/server-endpoints/stripe-session-test.ts b/packages/realm-server/tests/server-endpoints/stripe-session-test.ts index 2a8f81513a..97f5b23667 100644 --- a/packages/realm-server/tests/server-endpoints/stripe-session-test.ts +++ b/packages/realm-server/tests/server-endpoints/stripe-session-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import type { Test, SuperTest } from 'supertest'; import sinon from 'sinon'; diff --git a/packages/realm-server/tests/server-endpoints/stripe-webhook-test.ts b/packages/realm-server/tests/server-endpoints/stripe-webhook-test.ts index 04bb799ee5..cd938ee9e4 100644 --- a/packages/realm-server/tests/server-endpoints/stripe-webhook-test.ts +++ b/packages/realm-server/tests/server-endpoints/stripe-webhook-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import type { Test, SuperTest } from 'supertest'; import type { Realm, User } from '@cardstack/runtime-common'; diff --git a/packages/realm-server/tests/server-endpoints/user-and-catalog-test.ts b/packages/realm-server/tests/server-endpoints/user-and-catalog-test.ts index cb61d8fe89..666606717c 100644 --- a/packages/realm-server/tests/server-endpoints/user-and-catalog-test.ts +++ b/packages/realm-server/tests/server-endpoints/user-and-catalog-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { getUserByMatrixUserId } from '@cardstack/billing/billing-queries'; import { param, query } from '@cardstack/runtime-common'; diff --git a/packages/realm-server/tests/server-endpoints/webhook-commands-test.ts b/packages/realm-server/tests/server-endpoints/webhook-commands-test.ts index 7ffc117a37..1d37e44b91 100644 --- a/packages/realm-server/tests/server-endpoints/webhook-commands-test.ts +++ b/packages/realm-server/tests/server-endpoints/webhook-commands-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { createJWT as createRealmServerJWT } from '../../utils/jwt.ts'; import { realmSecretSeed, insertUser } from '../helpers/index.ts'; diff --git a/packages/realm-server/tests/server-endpoints/webhook-receiver-test.ts b/packages/realm-server/tests/server-endpoints/webhook-receiver-test.ts index 5b1aae9b2e..4af17c6b8e 100644 --- a/packages/realm-server/tests/server-endpoints/webhook-receiver-test.ts +++ b/packages/realm-server/tests/server-endpoints/webhook-receiver-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { createHmac } from 'crypto'; import { createJWT as createRealmServerJWT } from '../../utils/jwt.ts'; diff --git a/packages/realm-server/tests/session-room-queries-test.ts b/packages/realm-server/tests/session-room-queries-test.ts index ef6137f05e..9bc2d561ca 100644 --- a/packages/realm-server/tests/session-room-queries-test.ts +++ b/packages/realm-server/tests/session-room-queries-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import type { PgAdapter } from '@cardstack/postgres'; import { insertPermissions } from '@cardstack/runtime-common'; diff --git a/packages/realm-server/tests/skip-query-backed-expansion-test.ts b/packages/realm-server/tests/skip-query-backed-expansion-test.ts index a74be57f40..820f432420 100644 --- a/packages/realm-server/tests/skip-query-backed-expansion-test.ts +++ b/packages/realm-server/tests/skip-query-backed-expansion-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { rri } from '@cardstack/runtime-common'; import type { LooseSingleCardDocument, Realm } from '@cardstack/runtime-common'; diff --git a/packages/realm-server/tests/transpile-test.ts b/packages/realm-server/tests/transpile-test.ts index 5b5f2b2d8c..adfea33b8b 100644 --- a/packages/realm-server/tests/transpile-test.ts +++ b/packages/realm-server/tests/transpile-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { transpileJS } from '@cardstack/runtime-common/transpile'; import '@cardstack/runtime-common/helpers/code-equality-assertion'; diff --git a/packages/realm-server/tests/types-endpoint-test.ts b/packages/realm-server/tests/types-endpoint-test.ts index 1a75525a05..938d59f37b 100644 --- a/packages/realm-server/tests/types-endpoint-test.ts +++ b/packages/realm-server/tests/types-endpoint-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { Test, SuperTest } from 'supertest'; import { join, basename } from 'path'; import type { RealmHttpServer as Server } from '../server.ts'; diff --git a/packages/realm-server/tests/unified-search-contracts-test.ts b/packages/realm-server/tests/unified-search-contracts-test.ts index 2449d116d2..5203d65fcd 100644 --- a/packages/realm-server/tests/unified-search-contracts-test.ts +++ b/packages/realm-server/tests/unified-search-contracts-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { buildCssResource, diff --git a/packages/realm-server/tests/virtual-network-test.ts b/packages/realm-server/tests/virtual-network-test.ts index 6372125900..0b3528315b 100644 --- a/packages/realm-server/tests/virtual-network-test.ts +++ b/packages/realm-server/tests/virtual-network-test.ts @@ -1,6 +1,7 @@ import type { ResponseWithNodeStream } from '@cardstack/runtime-common'; import { VirtualNetwork } from '@cardstack/runtime-common'; -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import '../setup-logger.ts'; diff --git a/packages/realm-test-harness/package.json b/packages/realm-test-harness/package.json index 5edb9d3e76..0bf6501d1c 100644 --- a/packages/realm-test-harness/package.json +++ b/packages/realm-test-harness/package.json @@ -33,7 +33,6 @@ "jsonwebtoken": "catalog:", "pg": "catalog:", "puppeteer": "^25.0.2", - "ts-node": "^10.9.1", "typescript": "catalog:" }, "volta": { diff --git a/packages/software-factory/package.json b/packages/software-factory/package.json index de7bae1574..16b470951e 100644 --- a/packages/software-factory/package.json +++ b/packages/software-factory/package.json @@ -69,7 +69,6 @@ "qunit": "catalog:", "qunit-dom": "catalog:", "tmp": "catalog:", - "ts-node": "^10.9.1", "typescript": "catalog:", "zod": "^4.0.17", "zod-from-json-schema": "^0.5.2" diff --git a/packages/software-factory/scripts/smoke-tests/smoke-test-factory-scenarios.ts b/packages/software-factory/scripts/smoke-tests/smoke-test-factory-scenarios.ts index 21eba62c55..6b8d12d68b 100644 --- a/packages/software-factory/scripts/smoke-tests/smoke-test-factory-scenarios.ts +++ b/packages/software-factory/scripts/smoke-tests/smoke-test-factory-scenarios.ts @@ -237,7 +237,8 @@ export class HelloCard extends CardDef { `; // QUnit test for HelloCard -const HELLO_TEST_GTS = `import { module, test } from 'qunit'; +const HELLO_TEST_GTS = `import QUnit from 'qunit'; +const { module, test } = QUnit; import { setupCardTest } from '@cardstack/host/tests/helpers'; import { renderCard } from '@cardstack/host/tests/helpers/render-component'; import { getService } from '@universal-ember/test-support'; diff --git a/packages/software-factory/scripts/smoke-tests/smoke-test-realm.ts b/packages/software-factory/scripts/smoke-tests/smoke-test-realm.ts index a03c6158b6..805982ed9a 100644 --- a/packages/software-factory/scripts/smoke-tests/smoke-test-realm.ts +++ b/packages/software-factory/scripts/smoke-tests/smoke-test-realm.ts @@ -74,7 +74,8 @@ const HELLO_SPEC_CARD = { }, }; -const HELLO_TEST_GTS = `import { module, test } from 'qunit'; +const HELLO_TEST_GTS = `import QUnit from 'qunit'; +const { module, test } = QUnit; import { setupCardTest } from '@cardstack/host/tests/helpers'; import { renderCard } from '@cardstack/host/tests/helpers/render-component'; import { getService } from '@universal-ember/test-support'; @@ -96,7 +97,8 @@ export function runTests() { } `; -const HELLO_FAILING_TEST_GTS = `import { module, test } from 'qunit'; +const HELLO_FAILING_TEST_GTS = `import QUnit from 'qunit'; +const { module, test } = QUnit; import { setupCardTest } from '@cardstack/host/tests/helpers'; import { renderCard } from '@cardstack/host/tests/helpers/render-component'; import { getService } from '@universal-ember/test-support'; diff --git a/packages/software-factory/scripts/test.ts b/packages/software-factory/scripts/test.ts index a14154374c..2e9f0c6cf4 100644 --- a/packages/software-factory/scripts/test.ts +++ b/packages/software-factory/scripts/test.ts @@ -81,7 +81,7 @@ async function main(): Promise { await runCommand( `LOG_LEVELS=${JSON.stringify( logLevels, - )} NODE_NO_WARNINGS=1 qunit --require ts-node/register/transpile-only tests/index.ts`, + )} NODE_NO_WARNINGS=1 node tests/index.ts`, ); } diff --git a/packages/software-factory/tests/eval-execution.test.ts b/packages/software-factory/tests/eval-execution.test.ts index 0a8e84fd91..4057cbe153 100644 --- a/packages/software-factory/tests/eval-execution.test.ts +++ b/packages/software-factory/tests/eval-execution.test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { BoxelCLIClient } from '@cardstack/boxel-cli/api'; diff --git a/packages/software-factory/tests/eval-step.test.ts b/packages/software-factory/tests/eval-step.test.ts index 3c19384af4..428b876849 100644 --- a/packages/software-factory/tests/eval-step.test.ts +++ b/packages/software-factory/tests/eval-step.test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { ValidationStepResult } from '../src/factory-agent/index.ts'; diff --git a/packages/software-factory/tests/factory-agent-claude-code.test.ts b/packages/software-factory/tests/factory-agent-claude-code.test.ts index f97418589a..3ab7b6fecc 100644 --- a/packages/software-factory/tests/factory-agent-claude-code.test.ts +++ b/packages/software-factory/tests/factory-agent-claude-code.test.ts @@ -2,7 +2,8 @@ import { mkdtempSync, rmSync, symlinkSync, unlinkSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { z, type ZodType } from 'zod'; import type { Options } from '@anthropic-ai/claude-agent-sdk'; diff --git a/packages/software-factory/tests/factory-brief.test.ts b/packages/software-factory/tests/factory-brief.test.ts index fd0df0e7b7..523b76fca5 100644 --- a/packages/software-factory/tests/factory-brief.test.ts +++ b/packages/software-factory/tests/factory-brief.test.ts @@ -1,7 +1,8 @@ import { readFileSync } from 'node:fs'; import { createServer } from 'node:http'; import { resolve } from 'node:path'; -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { SupportedMimeType } from '@cardstack/runtime-common/supported-mime-type'; diff --git a/packages/software-factory/tests/factory-context-builder.test.ts b/packages/software-factory/tests/factory-context-builder.test.ts index 0fb80202b3..ea1810f233 100644 --- a/packages/software-factory/tests/factory-context-builder.test.ts +++ b/packages/software-factory/tests/factory-context-builder.test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { KnowledgeArticleData, diff --git a/packages/software-factory/tests/factory-entrypoint.integration.test.ts b/packages/software-factory/tests/factory-entrypoint.integration.test.ts index 5fbf91ab9e..eb365e5c77 100644 --- a/packages/software-factory/tests/factory-entrypoint.integration.test.ts +++ b/packages/software-factory/tests/factory-entrypoint.integration.test.ts @@ -9,7 +9,8 @@ import { spawn, spawnSync } from 'node:child_process'; import { createServer } from 'node:http'; import { tmpdir } from 'node:os'; import { join, resolve } from 'node:path'; -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { SupportedMimeType } from '@cardstack/runtime-common/supported-mime-type'; diff --git a/packages/software-factory/tests/factory-entrypoint.test.ts b/packages/software-factory/tests/factory-entrypoint.test.ts index 084b3e4140..edbd2edf6a 100644 --- a/packages/software-factory/tests/factory-entrypoint.test.ts +++ b/packages/software-factory/tests/factory-entrypoint.test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { SupportedMimeType } from '@cardstack/runtime-common/supported-mime-type'; diff --git a/packages/software-factory/tests/factory-prompt-loader.test.ts b/packages/software-factory/tests/factory-prompt-loader.test.ts index a4160564a2..97b12db597 100644 --- a/packages/software-factory/tests/factory-prompt-loader.test.ts +++ b/packages/software-factory/tests/factory-prompt-loader.test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { assembleImplementPrompt, diff --git a/packages/software-factory/tests/factory-skill-loader.test.ts b/packages/software-factory/tests/factory-skill-loader.test.ts index 22f54978fe..03c9a9c137 100644 --- a/packages/software-factory/tests/factory-skill-loader.test.ts +++ b/packages/software-factory/tests/factory-skill-loader.test.ts @@ -2,7 +2,8 @@ import { existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs'; import { join } from 'node:path'; import { tmpdir } from 'node:os'; -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { ProjectData, diff --git a/packages/software-factory/tests/factory-target-realm.spec.ts b/packages/software-factory/tests/factory-target-realm.spec.ts index 9421a4e567..0997e8505e 100644 --- a/packages/software-factory/tests/factory-target-realm.spec.ts +++ b/packages/software-factory/tests/factory-target-realm.spec.ts @@ -100,8 +100,6 @@ test('factory:go creates a target realm and bootstraps project artifacts end-to- 'node', [ '--no-warnings', - '--require', - require.resolve('ts-node/register/transpile-only'), resolve(packageRoot, 'src/cli/factory-entrypoint.ts'), '--brief-url', briefUrl, diff --git a/packages/software-factory/tests/factory-target-realm.test.ts b/packages/software-factory/tests/factory-target-realm.test.ts index 3ac0c5eda9..7fafbdddbd 100644 --- a/packages/software-factory/tests/factory-target-realm.test.ts +++ b/packages/software-factory/tests/factory-target-realm.test.ts @@ -1,7 +1,8 @@ import { mkdtempSync, rmSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { setProfileManager, diff --git a/packages/software-factory/tests/factory-test-realm.test.ts b/packages/software-factory/tests/factory-test-realm.test.ts index 6691e442d3..a514ee0274 100644 --- a/packages/software-factory/tests/factory-test-realm.test.ts +++ b/packages/software-factory/tests/factory-test-realm.test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { rri } from '@cardstack/runtime-common/realm-identifiers'; import { SupportedMimeType } from '@cardstack/runtime-common/supported-mime-type'; diff --git a/packages/software-factory/tests/factory-tool-builder.test.ts b/packages/software-factory/tests/factory-tool-builder.test.ts index 430afd8c1f..b6e9a8074d 100644 --- a/packages/software-factory/tests/factory-tool-builder.test.ts +++ b/packages/software-factory/tests/factory-tool-builder.test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { ToolResult } from '../src/factory-agent/index.ts'; import { diff --git a/packages/software-factory/tests/factory-tool-executor.integration.test.ts b/packages/software-factory/tests/factory-tool-executor.integration.test.ts index ad05cff057..5d11de189f 100644 --- a/packages/software-factory/tests/factory-tool-executor.integration.test.ts +++ b/packages/software-factory/tests/factory-tool-executor.integration.test.ts @@ -1,5 +1,6 @@ import { createServer, type IncomingMessage, type Server } from 'node:http'; -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { SupportedMimeType } from '@cardstack/runtime-common/supported-mime-type'; diff --git a/packages/software-factory/tests/factory-tool-executor.test.ts b/packages/software-factory/tests/factory-tool-executor.test.ts index 710102c7c4..ed38ee1938 100644 --- a/packages/software-factory/tests/factory-tool-executor.test.ts +++ b/packages/software-factory/tests/factory-tool-executor.test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { ToolExecutor, diff --git a/packages/software-factory/tests/factory-tool-registry.test.ts b/packages/software-factory/tests/factory-tool-registry.test.ts index 8910fc6c1c..0de60875fa 100644 --- a/packages/software-factory/tests/factory-tool-registry.test.ts +++ b/packages/software-factory/tests/factory-tool-registry.test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { getDefaultToolRegistry, diff --git a/packages/software-factory/tests/factory-tool-schema-adapter.test.ts b/packages/software-factory/tests/factory-tool-schema-adapter.test.ts index 5236bfdbf7..b00b680898 100644 --- a/packages/software-factory/tests/factory-tool-schema-adapter.test.ts +++ b/packages/software-factory/tests/factory-tool-schema-adapter.test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { z, type ZodObject } from 'zod'; import { diff --git a/packages/software-factory/tests/find-and-hold-available-port.test.ts b/packages/software-factory/tests/find-and-hold-available-port.test.ts index a1fb9e1654..746ebc46a5 100644 --- a/packages/software-factory/tests/find-and-hold-available-port.test.ts +++ b/packages/software-factory/tests/find-and-hold-available-port.test.ts @@ -1,5 +1,6 @@ import { createServer } from 'node:net'; -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { findAndHoldAvailablePort } from '@cardstack/realm-test-harness'; diff --git a/packages/software-factory/tests/hold-specific-port.test.ts b/packages/software-factory/tests/hold-specific-port.test.ts index 2fc7e49113..2dd2d003b2 100644 --- a/packages/software-factory/tests/hold-specific-port.test.ts +++ b/packages/software-factory/tests/hold-specific-port.test.ts @@ -1,5 +1,6 @@ import { createServer } from 'node:net'; -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { findAndHoldAvailablePort, diff --git a/packages/software-factory/tests/index.ts b/packages/software-factory/tests/index.ts index 8fba08587c..0024040813 100644 --- a/packages/software-factory/tests/index.ts +++ b/packages/software-factory/tests/index.ts @@ -1,3 +1,5 @@ +import './qunit-bootstrap.ts'; // configures QUnit before any test registers +import QUnit from 'qunit'; import './factory-brief.test.ts'; import './validation-run-cache.test.ts'; import './factory-prompt-loader.test.ts'; @@ -26,3 +28,5 @@ import './instantiate-step.test.ts'; import './parse-step.test.ts'; import './port-allocator.test.ts'; import './find-and-hold-available-port.test.ts'; + +QUnit.start(); diff --git a/packages/software-factory/tests/instantiate-discovery.test.ts b/packages/software-factory/tests/instantiate-discovery.test.ts index 9cb69e3081..af79e794e1 100644 --- a/packages/software-factory/tests/instantiate-discovery.test.ts +++ b/packages/software-factory/tests/instantiate-discovery.test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { BoxelCLIClient } from '@cardstack/boxel-cli/api'; diff --git a/packages/software-factory/tests/instantiate-step.test.ts b/packages/software-factory/tests/instantiate-step.test.ts index 0a501b6979..fedbe6e92f 100644 --- a/packages/software-factory/tests/instantiate-step.test.ts +++ b/packages/software-factory/tests/instantiate-step.test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { InstantiateValidationStep, diff --git a/packages/software-factory/tests/issue-loop.test.ts b/packages/software-factory/tests/issue-loop.test.ts index 7b448f4df8..a5968f7a54 100644 --- a/packages/software-factory/tests/issue-loop.test.ts +++ b/packages/software-factory/tests/issue-loop.test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { AgentContext, diff --git a/packages/software-factory/tests/issue-scheduler.test.ts b/packages/software-factory/tests/issue-scheduler.test.ts index 3edf8aed59..9eda91cb66 100644 --- a/packages/software-factory/tests/issue-scheduler.test.ts +++ b/packages/software-factory/tests/issue-scheduler.test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { BoxelCLIClient } from '@cardstack/boxel-cli/api'; diff --git a/packages/software-factory/tests/lint-step.test.ts b/packages/software-factory/tests/lint-step.test.ts index 40c6ba05cb..5c6eeee6ed 100644 --- a/packages/software-factory/tests/lint-step.test.ts +++ b/packages/software-factory/tests/lint-step.test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { ValidationStepResult } from '../src/factory-agent/index.ts'; diff --git a/packages/software-factory/tests/parse-step.test.ts b/packages/software-factory/tests/parse-step.test.ts index 478dfcecd3..6a32502027 100644 --- a/packages/software-factory/tests/parse-step.test.ts +++ b/packages/software-factory/tests/parse-step.test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { ValidationStepResult } from '../src/factory-agent/index.ts'; diff --git a/packages/software-factory/tests/port-allocator.test.ts b/packages/software-factory/tests/port-allocator.test.ts index 51cc10f799..6497db3e24 100644 --- a/packages/software-factory/tests/port-allocator.test.ts +++ b/packages/software-factory/tests/port-allocator.test.ts @@ -1,5 +1,6 @@ import { createServer } from 'node:net'; -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { TEST_WORKER_PORT_RANGE_END, diff --git a/packages/software-factory/tests/qunit-bootstrap.ts b/packages/software-factory/tests/qunit-bootstrap.ts new file mode 100644 index 0000000000..1867954065 --- /dev/null +++ b/packages/software-factory/tests/qunit-bootstrap.ts @@ -0,0 +1,13 @@ +// Configures QUnit to run under native Node (`node tests/index.ts`). The qunit +// CLI used to provide these three things; running the suite directly under node +// means wiring them up ourselves: +// - autostart off, so `index.ts` can register every test before starting +// - the TAP reporter the CLI emitted by default +// - a failure-based process exit code +import QUnit from 'qunit'; + +QUnit.config.autostart = false; +QUnit.reporters.tap.init(QUnit); +QUnit.on('runEnd', (data) => { + process.exitCode = data.testCounts.failed > 0 ? 1 : 0; +}); diff --git a/packages/software-factory/tests/retry-blocked-issues.test.ts b/packages/software-factory/tests/retry-blocked-issues.test.ts index ff73d4ad05..7e11d6178f 100644 --- a/packages/software-factory/tests/retry-blocked-issues.test.ts +++ b/packages/software-factory/tests/retry-blocked-issues.test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { SchedulableIssue } from '../src/factory-agent/index.ts'; import type { IssueStore } from '../src/issue-scheduler.ts'; diff --git a/packages/software-factory/tests/test-step.test.ts b/packages/software-factory/tests/test-step.test.ts index 2e7e619a43..1fb2177863 100644 --- a/packages/software-factory/tests/test-step.test.ts +++ b/packages/software-factory/tests/test-step.test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { LooseSingleCardDocument } from '@cardstack/runtime-common'; diff --git a/packages/software-factory/tests/validation-pipeline.test.ts b/packages/software-factory/tests/validation-pipeline.test.ts index ef357c3e95..8a4c67b8a6 100644 --- a/packages/software-factory/tests/validation-pipeline.test.ts +++ b/packages/software-factory/tests/validation-pipeline.test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { ValidationStep, diff --git a/packages/software-factory/tests/validation-run-cache.test.ts b/packages/software-factory/tests/validation-run-cache.test.ts index ef8fd1a7e5..0c9e6d5977 100644 --- a/packages/software-factory/tests/validation-run-cache.test.ts +++ b/packages/software-factory/tests/validation-run-cache.test.ts @@ -2,7 +2,8 @@ import { mkdtempSync, rmSync, writeFileSync, mkdirSync } from 'node:fs'; import { join } from 'node:path'; import { tmpdir } from 'node:os'; -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { BoxelCLIClient } from '@cardstack/boxel-cli/api'; diff --git a/scripts/esm-codemod/README.md b/scripts/esm-codemod/README.md index fbc05b77c4..463a6ac5c4 100644 --- a/scripts/esm-codemod/README.md +++ b/scripts/esm-codemod/README.md @@ -35,18 +35,20 @@ reading the first failure, then fixing and repeating. Classes marked **automated** are handled by `run.mjs`; **manual** ones are listed in the next section. -| # | Symptom | Cause | Fix | | -| --- | ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | -| 1 | `ERR_MODULE_NOT_FOUND` resolving a relative import `./foo` | Node does no extension search or directory-index resolution | append `./foo.ts` / `./foo.gts` / `./foo/index.ts`; bare `'.'` → `'./index.ts'` | automated (`add-relative-extensions`) | -| 2 | `ERR_MODULE_NOT_FOUND` resolving a workspace pkg subpath (`@cardstack/billing/x`) | workspace package has no `exports` map → Node looks for `index.js` | add an `exports` map pointing at `.ts` + `"type":"module"` | **manual** | -| 3 | `Cannot find module '.../lodash/merge'` (`Did you mean lodash/merge.js?`) | `lodash` is CJS-only with no exports map | repo-wide switch to `lodash-es` named imports | automated (`lodash-to-lodash-es`) | -| 4 | `does not provide an export named 'X'` from a CJS pkg (`fs-extra`, `debug`) | Node can't statically read named exports from these CJS modules | default-import + destructure | automated (`cjs-named-to-default`) — extend `CJS_PACKAGES` as new ones surface | -| 5 | `ERR_MODULE_NOT_FOUND` on a CJS pkg deep import (`matrix-js-sdk/lib/x`) | no exports map; ESM won't add `.js` or pick a file over a same-named dir | append `.js` | **manual** (small, package-specific) | -| 6 | `Cannot find module '.../scripts/x.js'` | a stray CJS file was renamed `.cjs` (because the pkg is now `type:module`) but the import still says `.js` | update the import to `.cjs` | **manual** | -| 7 | `ReferenceError: __dirname is not defined` | CJS globals don't exist under ESM | `import.meta.dirname` / `import.meta.filename` | automated (`dirname-to-import-meta`) | -| 8 | wrong path built from `import.meta.url` | `import.meta.url` is a `file://` URL string, not a path | use `import.meta.dirname` | **manual** (rare — was a WIP bug) | -| 9 | `ReferenceError: exports is not defined` when a consumer runs the dep via `ts-node` | once a dep ships an `exports` map Node handles its `.ts` natively, colliding with a still-`ts-node` consumer | the dep + all its node-run consumers must drop ts-node in the same change (big-bang) | **manual** (coordination) | -| 10 | in-source `spawn('ts-node', ['--transpileOnly', 'entry', …])` | child processes also need native node | `spawn('node', ['entry.ts', …])` (or `process.execPath`) | **manual** (few sites, varied shapes) | +| # | Symptom | Cause | Fix | | +| --- | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | +| 1 | `ERR_MODULE_NOT_FOUND` resolving a relative import `./foo` | Node does no extension search or directory-index resolution | append `./foo.ts` / `./foo.gts` / `./foo/index.ts`; bare `'.'` → `'./index.ts'` | automated (`add-relative-extensions`) | +| 2 | `ERR_MODULE_NOT_FOUND` resolving a workspace pkg subpath (`@cardstack/billing/x`) | workspace package has no `exports` map → Node looks for `index.js` | add an `exports` map pointing at `.ts` + `"type":"module"` | **manual** | +| 3 | `Cannot find module '.../lodash/merge'` (`Did you mean lodash/merge.js?`) | `lodash` is CJS-only with no exports map | repo-wide switch to `lodash-es` named imports | automated (`lodash-to-lodash-es`) | +| 4 | `does not provide an export named 'X'` from a CJS pkg (`fs-extra`, `debug`, `qunit`, `jsonwebtoken`) | Node can't statically read named exports from these CJS modules | default-import + destructure | automated (`cjs-named-to-default`, line-anchored so it skips imports embedded in test-fixture strings) — extend `CJS_PACKAGES` as new ones surface | +| 5 | `ERR_MODULE_NOT_FOUND` on a CJS pkg deep import (`matrix-js-sdk/lib/x`) | no exports map; ESM won't add `.js` or pick a file over a same-named dir | append `.js` | **manual** (small, package-specific) | +| 6 | `Cannot find module '.../scripts/x.js'` | a stray CJS file was renamed `.cjs` (because the pkg is now `type:module`) but the import still says `.js` | update the import to `.cjs` | **manual** | +| 7 | `ReferenceError: __dirname is not defined` | CJS globals don't exist under ESM | `import.meta.dirname` / `import.meta.filename` | automated (`dirname-to-import-meta`) | +| 8 | wrong path built from `import.meta.url` | `import.meta.url` is a `file://` URL string, not a path | use `import.meta.dirname` | **manual** (rare — was a WIP bug) | +| 9 | `ReferenceError: exports is not defined` when a consumer runs the dep via `ts-node` | once a dep ships an `exports` map Node handles its `.ts` natively, colliding with a still-`ts-node` consumer | the dep + all its node-run consumers must drop ts-node in the same change (big-bang) | **manual** (coordination) | +| 10 | in-source `spawn('ts-node', ['--transpileOnly', 'entry', …])` | child processes also need native node | `spawn('node', ['entry.ts', …])` (or `process.execPath`) | **manual** (few sites, varied shapes) | +| 11 | `ReferenceError: require is not defined in ES module scope` | `require()` / lazy `require()` don't exist in ESM | `const require = createRequire(import.meta.url)` shim, OR static/dynamic import. Native `require()` does NO extension search — `require('./x.ts')` works, `require('./x')` and `require('./dir')` do not | **manual** (small set) | +| 12 | a test's `sinon.stub(NS, 'fn')` / `(NS as any).fn = …` silently no-ops | ES-module namespace objects (`import * as NS`) are sealed; their bindings are read-only | inject the dependency, or stub through a mutable indirection — not the namespace | **manual** (per-test; e.g. ai-bot Sentry/locking tests) | ### Invocation sites (automated — `ts-node-to-node`) @@ -68,15 +70,30 @@ These are too package-specific or too coupled for a blind codemod: subpath. Never set `--preserve-symlinks` (it breaks type-stripping for pnpm-symlinked workspace deps, which only works because Node resolves to realpath outside `node_modules` first). -2. **The qunit test-runner bootstrap.** `qunit --require ts-node/register` has no - node equivalent; each test package needs a `node tests/index.ts`-style - bootstrap that installs the `QUnit` global, a TAP reporter, `QUnit.start()`, - and a failure-based exit code. Affects `ai-bot`, `bot-runner`, `realm-server` - (via `run-qunit-with-test-pg.sh` / `measure-test-file.sh`), `software-factory`. -3. **Remove the `ts-node` devDependency** from each package once its test runner - is converted. +2. **The qunit test-runner bootstrap** (DONE). `qunit --require ts-node/register` + has no node equivalent, so each test package now runs `node tests/index.ts` + with a `tests/qunit-bootstrap.ts` that turns autostart off, inits the TAP + reporter, and sets a failure-based exit code; `index.ts` ends with + `QUnit.start()`. Done for `ai-bot`, `bot-runner`, `software-factory`, and + `realm-server` (whose `index.ts` also needed the class-#11 `createRequire` + shim and `require(`${file}.ts`)` so its sync, order-preserving loader keeps + working; the CI JUnit reporter is `--require`d and was renamed `.cjs`). +3. **Remove the `ts-node` devDependency** (DONE) — dropped from every package now + that all invocations and test runners are converted. 4. **CJS deep imports** needing `.js` (class #5) and **`.cjs` import path fixes** (class #6) — verify against the actual file on disk. +5. **`require()` shims** (class #11) and **ESM-namespace mock breakage** (class + #12) — the latter is genuine per-test work (e.g. ai-bot's Sentry/locking + tests fail because they reassign a sealed namespace binding). + +## Remaining known gaps + +- **ai-bot**: 5 tests fail on class #12 (ESM namespace mocking) — needs DI/indirection. +- **software-factory**: full node suite needs `boxel-cli` + `software-factory`'s own + source migrated (their `src/logger.ts` etc. still use bare `require()`); the + bootstrap wiring is in place. +- **realm-server**: the full suite needs the dev services stack to run; the + bootstrap is validated on standalone unit tests. ## Verifying a package loads diff --git a/scripts/esm-codemod/cjs-named-to-default.mjs b/scripts/esm-codemod/cjs-named-to-default.mjs index fa5dc958de..2d41153b52 100644 --- a/scripts/esm-codemod/cjs-named-to-default.mjs +++ b/scripts/esm-codemod/cjs-named-to-default.mjs @@ -16,6 +16,8 @@ import { readFileSync, writeFileSync } from 'node:fs'; export const CJS_PACKAGES = { 'fs-extra': 'fsExtra', debug: 'createDebug', + qunit: 'QUnit', + jsonwebtoken: 'jsonwebtoken', }; function varName(pkg) { @@ -27,9 +29,12 @@ export function transform(src) { let changed = false; let code = src; for (const pkg of Object.keys(CJS_PACKAGES)) { + // Line-anchored so it only matches a real top-level import statement, never + // an import that appears as test-fixture text inside a string/template + // literal (those are preceded by a quote/backtick, so never start a line). const re = new RegExp( - `import\\s*\\{([^}]*)\\}\\s*from\\s*(['"])${pkg.replace(/[/\\^$*+?.()|[\]{}]/g, '\\$&')}\\2;?`, - 'g', + `^[ \\t]*import\\s*\\{([^}]*)\\}\\s*from\\s*(['"])${pkg.replace(/[/\\^$*+?.()|[\]{}]/g, '\\$&')}\\2;?[ \\t]*$`, + 'gm', ); code = code.replace(re, (_full, names) => { const local = varName(pkg); From 75816be023546c92eb8e8bc7e681038f84b0ff93 Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Wed, 17 Jun 2026 14:27:24 -0400 Subject: [PATCH 08/38] fix: make ai-bot suite pass under native Node ESM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two ESM-semantic issues surfaced once ai-bot ran under `node tests/index.ts`: 1. node-pg-migrate default-export interop (postgres). `import migrate from 'node-pg-migrate'` binds the whole CJS namespace under native ESM, so the runner (on `.default`) wasn't callable — "migrate is not a function". This broke DB migration everywhere, not just tests. Resolve `.default ?? ns`. Also add `package.json` to the migrate `ignorePattern` so the `type:commonjs` marker file in the migrations dir isn't loaded as a migration. 2. Sentry mocking against a sealed ES-module namespace. Tests reassigned `(Sentry as any).captureException`, a no-op because `import * as Sentry` bindings are read-only. Route the source through a mutable `lib/sentry.ts` `errorReporter` indirection that responder.ts/debug.ts call and the tests stub. ai-bot now passes 170/170 (locking tests need the usual PG env vars). Documents both as error classes #12 and #13 in the codemod README. Co-Authored-By: Claude Opus 4.8 --- packages/ai-bot/lib/debug.ts | 6 ++--- packages/ai-bot/lib/responder.ts | 4 +-- packages/ai-bot/lib/sentry.ts | 13 +++++++++ packages/ai-bot/tests/interrupt-test.ts | 8 +++--- packages/ai-bot/tests/responding-test.ts | 14 +++++----- packages/postgres/pg-adapter.ts | 13 +++++++-- scripts/esm-codemod/README.md | 34 +++++++++++++----------- 7 files changed, 59 insertions(+), 33 deletions(-) create mode 100644 packages/ai-bot/lib/sentry.ts diff --git a/packages/ai-bot/lib/debug.ts b/packages/ai-bot/lib/debug.ts index 3bd511dae0..f3e5ddd3ef 100644 --- a/packages/ai-bot/lib/debug.ts +++ b/packages/ai-bot/lib/debug.ts @@ -1,7 +1,7 @@ import { setTitle } from './set-title.ts'; import type OpenAI from 'openai'; -import * as Sentry from '@sentry/node'; +import { errorReporter } from './sentry.ts'; import type { MatrixEvent as DiscreteMatrixEvent } from 'https://cardstack.com/base/matrix-event'; import { getPromptParts, @@ -78,7 +78,7 @@ To patch a card:\n customMessage, ); } catch (error) { - Sentry.captureException(error, { + errorReporter.captureException(error, { extra: { roomId: roomId, userId: userId, @@ -133,7 +133,7 @@ To patch a card:\n ); } } catch (error) { - Sentry.captureException(error, { + errorReporter.captureException(error, { extra: { roomId: roomId, userId: userId, diff --git a/packages/ai-bot/lib/responder.ts b/packages/ai-bot/lib/responder.ts index 773657108b..111c59cea8 100644 --- a/packages/ai-bot/lib/responder.ts +++ b/packages/ai-bot/lib/responder.ts @@ -2,7 +2,7 @@ import { logger } from '@cardstack/runtime-common'; import { APP_BOXEL_CODE_PATCH_CORRECTNESS_MSGTYPE } from '@cardstack/runtime-common/matrix-constants'; import { isCommandOrCodePatchResult } from '@cardstack/runtime-common/ai'; -import * as Sentry from '@sentry/node'; +import { errorReporter } from './sentry.ts'; import type { OpenAIError } from 'openai/error'; import { throttle } from 'lodash-es'; import type { ISendEventResponse } from 'matrix-js-sdk/lib/matrix.js'; @@ -188,7 +188,7 @@ export class Responder { if (this.responseState.isStreamingFinished) { return; } - Sentry.captureException(error, { + errorReporter.captureException(error, { extra: { roomId: this.matrixResponsePublisher.roomId, agentId: this.matrixResponsePublisher.agentId, diff --git a/packages/ai-bot/lib/sentry.ts b/packages/ai-bot/lib/sentry.ts new file mode 100644 index 0000000000..3b9dc55a2b --- /dev/null +++ b/packages/ai-bot/lib/sentry.ts @@ -0,0 +1,13 @@ +import * as Sentry from '@sentry/node'; + +// Indirection over Sentry so tests can replace `captureException`. Under native +// ESM, `import * as Sentry` is a sealed module namespace whose bindings are +// read-only, so tests can't stub `Sentry.captureException` directly. Calling +// through this mutable object lets a test swap the method and restore it. +export const errorReporter = { + captureException( + ...args: Parameters + ): ReturnType { + return Sentry.captureException(...args); + }, +}; diff --git a/packages/ai-bot/tests/interrupt-test.ts b/packages/ai-bot/tests/interrupt-test.ts index af31deb4b3..73ee0d18ae 100644 --- a/packages/ai-bot/tests/interrupt-test.ts +++ b/packages/ai-bot/tests/interrupt-test.ts @@ -4,7 +4,7 @@ import { Responder } from '../lib/responder.ts'; import { FakeMatrixClient } from './helpers/fake-matrix-client.ts'; import FakeTimers from '@sinonjs/fake-timers'; import type { ChatCompletionSnapshot } from 'openai/lib/ChatCompletionStream'; -import * as Sentry from '@sentry/node'; +import { errorReporter } from '../lib/sentry.ts'; import { OpenAIError } from 'openai'; function snapshotWithContent(content: string): ChatCompletionSnapshot { @@ -218,8 +218,8 @@ module('Responder Cancellation', (hooks) => { test('onError does not report to Sentry after cancellation', async (assert) => { let sentryCalls: any[] = []; - let originalCaptureException = Sentry.captureException; - (Sentry as any).captureException = (...args: any[]) => { + let originalCaptureException = errorReporter.captureException; + errorReporter.captureException = (...args: any[]) => { sentryCalls.push(args); return ''; }; @@ -247,7 +247,7 @@ module('Responder Cancellation', (hooks) => { 'Sentry should NOT be called after finalize — prevents false alarms from cancellation', ); } finally { - (Sentry as any).captureException = originalCaptureException; + errorReporter.captureException = originalCaptureException; } }); diff --git a/packages/ai-bot/tests/responding-test.ts b/packages/ai-bot/tests/responding-test.ts index fd3c8086f7..0b9ac7e6e4 100644 --- a/packages/ai-bot/tests/responding-test.ts +++ b/packages/ai-bot/tests/responding-test.ts @@ -15,7 +15,7 @@ import { import type OpenAI from 'openai'; import { FakeMatrixClient } from './helpers/fake-matrix-client.ts'; import { OpenAIError } from 'openai'; -import * as Sentry from '@sentry/node'; +import { errorReporter } from '../lib/sentry.ts'; function snapshotWithContent(content: string): ChatCompletionSnapshot { return { @@ -1136,8 +1136,8 @@ module('Responding', (hooks) => { test('onError does not report to Sentry when streaming is already finished', async () => { let sentryCalls: any[] = []; - let originalCaptureException = Sentry.captureException; - (Sentry as any).captureException = (...args: any[]) => { + let originalCaptureException = errorReporter.captureException; + errorReporter.captureException = (...args: any[]) => { sentryCalls.push(args); return ''; }; @@ -1169,14 +1169,14 @@ module('Responding', (hooks) => { 'No error events should be sent to Matrix', ); } finally { - (Sentry as any).captureException = originalCaptureException; + errorReporter.captureException = originalCaptureException; } }); test('onError reports to Sentry when streaming is not finished', async () => { let sentryCalls: any[] = []; - let originalCaptureException = Sentry.captureException; - (Sentry as any).captureException = (...args: any[]) => { + let originalCaptureException = errorReporter.captureException; + errorReporter.captureException = (...args: any[]) => { sentryCalls.push(args); return ''; }; @@ -1193,7 +1193,7 @@ module('Responding', (hooks) => { 'Sentry should be called when streaming is not finished', ); } finally { - (Sentry as any).captureException = originalCaptureException; + errorReporter.captureException = originalCaptureException; } }); diff --git a/packages/postgres/pg-adapter.ts b/packages/postgres/pg-adapter.ts index 8984d6d9ca..ad97f7121f 100644 --- a/packages/postgres/pg-adapter.ts +++ b/packages/postgres/pg-adapter.ts @@ -9,13 +9,19 @@ import { param, } from '@cardstack/runtime-common'; import { createHash } from 'crypto'; -import migrate from 'node-pg-migrate'; +import nodePgMigrate from 'node-pg-migrate'; import { join } from 'path'; import { Pool, Client, type Notification } from 'pg'; import { postgresConfig } from './pg-config.ts'; import migrationNameFixes from './scripts/migration-name-fixes.cjs'; +// node-pg-migrate is CJS and exposes the runner on `.default`; native ESM +// doesn't unwrap it the way ts-node's esModuleInterop did. +const migrate = + (nodePgMigrate as unknown as { default?: typeof nodePgMigrate }).default ?? + nodePgMigrate; + // Hash a realm URL to a stable signed int64 (as a string, because JS numbers // can't represent the full int64 range). Used as a pg advisory lock key: // two writers for the same realm URL hash to the same key and serialize; @@ -659,7 +665,10 @@ export class PgAdapter implements DBAdapter { }, count: Infinity, dir: join(import.meta.dirname, 'migrations'), - ignorePattern: '.*\\.eslintrc\\.js', + // Ignore the eslint config and the `package.json` that pins this dir + // to `type:commonjs` (the CJS migration files use `exports.up`); both + // sit in the migrations dir but aren't migrations. + ignorePattern: '.*\\.eslintrc\\.js|package\\.json', log: enableLogging ? (...args) => log.info(...args) : () => undefined, }); await this.fixupEnvironmentModePermissions(config); diff --git a/scripts/esm-codemod/README.md b/scripts/esm-codemod/README.md index 463a6ac5c4..3437337b8a 100644 --- a/scripts/esm-codemod/README.md +++ b/scripts/esm-codemod/README.md @@ -35,20 +35,21 @@ reading the first failure, then fixing and repeating. Classes marked **automated** are handled by `run.mjs`; **manual** ones are listed in the next section. -| # | Symptom | Cause | Fix | | -| --- | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | -| 1 | `ERR_MODULE_NOT_FOUND` resolving a relative import `./foo` | Node does no extension search or directory-index resolution | append `./foo.ts` / `./foo.gts` / `./foo/index.ts`; bare `'.'` → `'./index.ts'` | automated (`add-relative-extensions`) | -| 2 | `ERR_MODULE_NOT_FOUND` resolving a workspace pkg subpath (`@cardstack/billing/x`) | workspace package has no `exports` map → Node looks for `index.js` | add an `exports` map pointing at `.ts` + `"type":"module"` | **manual** | -| 3 | `Cannot find module '.../lodash/merge'` (`Did you mean lodash/merge.js?`) | `lodash` is CJS-only with no exports map | repo-wide switch to `lodash-es` named imports | automated (`lodash-to-lodash-es`) | -| 4 | `does not provide an export named 'X'` from a CJS pkg (`fs-extra`, `debug`, `qunit`, `jsonwebtoken`) | Node can't statically read named exports from these CJS modules | default-import + destructure | automated (`cjs-named-to-default`, line-anchored so it skips imports embedded in test-fixture strings) — extend `CJS_PACKAGES` as new ones surface | -| 5 | `ERR_MODULE_NOT_FOUND` on a CJS pkg deep import (`matrix-js-sdk/lib/x`) | no exports map; ESM won't add `.js` or pick a file over a same-named dir | append `.js` | **manual** (small, package-specific) | -| 6 | `Cannot find module '.../scripts/x.js'` | a stray CJS file was renamed `.cjs` (because the pkg is now `type:module`) but the import still says `.js` | update the import to `.cjs` | **manual** | -| 7 | `ReferenceError: __dirname is not defined` | CJS globals don't exist under ESM | `import.meta.dirname` / `import.meta.filename` | automated (`dirname-to-import-meta`) | -| 8 | wrong path built from `import.meta.url` | `import.meta.url` is a `file://` URL string, not a path | use `import.meta.dirname` | **manual** (rare — was a WIP bug) | -| 9 | `ReferenceError: exports is not defined` when a consumer runs the dep via `ts-node` | once a dep ships an `exports` map Node handles its `.ts` natively, colliding with a still-`ts-node` consumer | the dep + all its node-run consumers must drop ts-node in the same change (big-bang) | **manual** (coordination) | -| 10 | in-source `spawn('ts-node', ['--transpileOnly', 'entry', …])` | child processes also need native node | `spawn('node', ['entry.ts', …])` (or `process.execPath`) | **manual** (few sites, varied shapes) | -| 11 | `ReferenceError: require is not defined in ES module scope` | `require()` / lazy `require()` don't exist in ESM | `const require = createRequire(import.meta.url)` shim, OR static/dynamic import. Native `require()` does NO extension search — `require('./x.ts')` works, `require('./x')` and `require('./dir')` do not | **manual** (small set) | -| 12 | a test's `sinon.stub(NS, 'fn')` / `(NS as any).fn = …` silently no-ops | ES-module namespace objects (`import * as NS`) are sealed; their bindings are read-only | inject the dependency, or stub through a mutable indirection — not the namespace | **manual** (per-test; e.g. ai-bot Sentry/locking tests) | +| # | Symptom | Cause | Fix | | +| --- | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | +| 1 | `ERR_MODULE_NOT_FOUND` resolving a relative import `./foo` | Node does no extension search or directory-index resolution | append `./foo.ts` / `./foo.gts` / `./foo/index.ts`; bare `'.'` → `'./index.ts'` | automated (`add-relative-extensions`) | +| 2 | `ERR_MODULE_NOT_FOUND` resolving a workspace pkg subpath (`@cardstack/billing/x`) | workspace package has no `exports` map → Node looks for `index.js` | add an `exports` map pointing at `.ts` + `"type":"module"` | **manual** | +| 3 | `Cannot find module '.../lodash/merge'` (`Did you mean lodash/merge.js?`) | `lodash` is CJS-only with no exports map | repo-wide switch to `lodash-es` named imports | automated (`lodash-to-lodash-es`) | +| 4 | `does not provide an export named 'X'` from a CJS pkg (`fs-extra`, `debug`, `qunit`, `jsonwebtoken`) | Node can't statically read named exports from these CJS modules | default-import + destructure | automated (`cjs-named-to-default`, line-anchored so it skips imports embedded in test-fixture strings) — extend `CJS_PACKAGES` as new ones surface | +| 5 | `ERR_MODULE_NOT_FOUND` on a CJS pkg deep import (`matrix-js-sdk/lib/x`) | no exports map; ESM won't add `.js` or pick a file over a same-named dir | append `.js` | **manual** (small, package-specific) | +| 6 | `Cannot find module '.../scripts/x.js'` | a stray CJS file was renamed `.cjs` (because the pkg is now `type:module`) but the import still says `.js` | update the import to `.cjs` | **manual** | +| 7 | `ReferenceError: __dirname is not defined` | CJS globals don't exist under ESM | `import.meta.dirname` / `import.meta.filename` | automated (`dirname-to-import-meta`) | +| 8 | wrong path built from `import.meta.url` | `import.meta.url` is a `file://` URL string, not a path | use `import.meta.dirname` | **manual** (rare — was a WIP bug) | +| 9 | `ReferenceError: exports is not defined` when a consumer runs the dep via `ts-node` | once a dep ships an `exports` map Node handles its `.ts` natively, colliding with a still-`ts-node` consumer | the dep + all its node-run consumers must drop ts-node in the same change (big-bang) | **manual** (coordination) | +| 10 | in-source `spawn('ts-node', ['--transpileOnly', 'entry', …])` | child processes also need native node | `spawn('node', ['entry.ts', …])` (or `process.execPath`) | **manual** (few sites, varied shapes) | +| 11 | `ReferenceError: require is not defined in ES module scope` | `require()` / lazy `require()` don't exist in ESM | `const require = createRequire(import.meta.url)` shim, OR static/dynamic import. Native `require()` does NO extension search — `require('./x.ts')` works, `require('./x')` and `require('./dir')` do not | **manual** (small set) | +| 12 | a test's `sinon.stub(NS, 'fn')` / `(NS as any).fn = …` silently no-ops | ES-module namespace objects (`import * as NS`) are sealed; their bindings are read-only | inject the dependency, or stub through a small mutable indirection module the source calls and the test imports — not the namespace | **manual** (per-test; ai-bot Sentry tests now stub `lib/sentry.ts`'s `errorReporter`) | +| 13 | `X is not a function` from `import X from 'some-cjs-pkg'` (e.g. `node-pg-migrate`) | CJS pkg authored with transpiled `exports.default = fn`: native ESM binds `X = module.exports` (the whole namespace) and the callable is on `X.default`; ts-node's `esModuleInterop` unwrapped it | `const fn = (X as any).default ?? X` | **manual** (surfaces at runtime, not load — verify the export shape) | ### Invocation sites (automated — `ts-node-to-node`) @@ -88,7 +89,10 @@ These are too package-specific or too coupled for a blind codemod: ## Remaining known gaps -- **ai-bot**: 5 tests fail on class #12 (ESM namespace mocking) — needs DI/indirection. +- **ai-bot**: full suite passes (170/170) — the 5 prior failures were class #12 + (Sentry namespace mocking, fixed via `lib/sentry.ts`) and class #13 + (`node-pg-migrate` default interop in `postgres`). The locking tests need PG + env (`PGHOST`/`PGPORT`/`PGUSER`/`PGPASSWORD`) like the rest of the DB suite. - **software-factory**: full node suite needs `boxel-cli` + `software-factory`'s own source migrated (their `src/logger.ts` etc. still use bare `require()`); the bootstrap wiring is in place. From cf5d64611aad1fc4fd588f75c1557a76a9d269f3 Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Wed, 17 Jun 2026 14:35:18 -0400 Subject: [PATCH 09/38] fix: load @cardstack/logger via createRequire under native ESM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit software-factory's node test suite crashed at boot on `require('@cardstack/logger')` in src/logger.ts — `require` doesn't exist in ESM scope. @cardstack/logger is a CJS package that ships no type declarations, so the existing code cast the `require()` result; keep that by defining `require` via createRequire rather than switching to a static import (which would trip TS7016). Same fix for the identical realm-test-harness/src/logger.ts. With this and the previously-added @cardstack/boxel-cli `exports` map, the software-factory node suite runs: 452/453 pass. The one failure (port-allocator dual-stack `::` bind) is a macOS-vs-Linux socket-semantics difference, not a migration regression — it asserts Linux behavior and fails the same way under ts-node on macOS. Co-Authored-By: Claude Opus 4.8 --- packages/realm-test-harness/src/logger.ts | 7 +++++-- packages/software-factory/src/logger.ts | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/realm-test-harness/src/logger.ts b/packages/realm-test-harness/src/logger.ts index ee703f936e..ab3cb3eb58 100644 --- a/packages/realm-test-harness/src/logger.ts +++ b/packages/realm-test-harness/src/logger.ts @@ -1,3 +1,5 @@ +import { createRequire } from 'module'; + export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'none'; type AcceptedLogLevel = LogLevel | 'silent'; @@ -21,8 +23,9 @@ type LoggerFactory = { }; // The published package does not ship TypeScript declarations, so we keep the -// typing local here instead of maintaining an ambient .d.ts shim. -// eslint-disable-next-line @typescript-eslint/no-var-requires +// typing local here instead of maintaining an ambient .d.ts shim. It's also +// CJS, so under native ESM we load it through createRequire. +const require = createRequire(import.meta.url); const createLogger = require('@cardstack/logger') as LoggerFactory; export function configureLogger(serializedLogLevels: string): void { diff --git a/packages/software-factory/src/logger.ts b/packages/software-factory/src/logger.ts index 5940be983e..df0296f964 100644 --- a/packages/software-factory/src/logger.ts +++ b/packages/software-factory/src/logger.ts @@ -1,3 +1,5 @@ +import { createRequire } from 'module'; + export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'none'; type AcceptedLogLevel = LogLevel | 'silent'; @@ -21,8 +23,9 @@ type LoggerFactory = { }; // The published package does not ship TypeScript declarations, so we keep the -// typing local here instead of maintaining an ambient .d.ts shim. -// eslint-disable-next-line @typescript-eslint/no-var-requires +// typing local here instead of maintaining an ambient .d.ts shim. It's also +// CJS, so under native ESM we load it through createRequire. +const require = createRequire(import.meta.url); const createLogger = require('@cardstack/logger') as LoggerFactory; export function configureLogger(serializedLogLevels: string): void { From 99a1a6c3abbbbfffa4ab967c0ed378578bb9e32b Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Wed, 17 Jun 2026 14:37:50 -0400 Subject: [PATCH 10/38] build: rename CJS .js configs/scripts to .cjs under type:module packages Packages flipped to "type":"module" (billing, realm-server, realm-test-harness) treat their `.eslintrc.js` as ESM, so ESLint fails to load them ("module is not defined in ES module scope"). Rename those configs to `.eslintrc.cjs`, which ESLint still auto-discovers. Same problem for realm-server's CJS helper scripts run via `node`: `shard-test-modules.js` (invoked in CI to compute test shards) and `run-test-modules.js` both use `require`. Rename to `.cjs` and update the CI workflow reference. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/ci.yaml | 2 +- packages/billing/{.eslintrc.js => .eslintrc.cjs} | 0 packages/realm-server/{.eslintrc.js => .eslintrc.cjs} | 0 .../scripts/{run-test-modules.js => run-test-modules.cjs} | 0 .../scripts/{shard-test-modules.js => shard-test-modules.cjs} | 4 ++-- packages/realm-test-harness/{.eslintrc.js => .eslintrc.cjs} | 0 6 files changed, 3 insertions(+), 3 deletions(-) rename packages/billing/{.eslintrc.js => .eslintrc.cjs} (100%) rename packages/realm-server/{.eslintrc.js => .eslintrc.cjs} (100%) rename packages/realm-server/scripts/{run-test-modules.js => run-test-modules.cjs} (100%) rename packages/realm-server/scripts/{shard-test-modules.js => shard-test-modules.cjs} (89%) rename packages/realm-test-harness/{.eslintrc.js => .eslintrc.cjs} (100%) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 70dd2a5a48..42235bf37f 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -595,7 +595,7 @@ jobs: cp -a .test-web-assets-artifact/. ./ - name: Compute shard test modules id: shard_modules - run: echo "modules=$(node scripts/shard-test-modules.js ${{ matrix.shardIndex }} ${{ matrix.shardTotal }})" >> "$GITHUB_OUTPUT" + run: echo "modules=$(node scripts/shard-test-modules.cjs ${{ matrix.shardIndex }} ${{ matrix.shardTotal }})" >> "$GITHUB_OUTPUT" working-directory: packages/realm-server # Warm the test images from the GHCR mirror so the services # below start from a local image instead of an unauthenticated Docker Hub diff --git a/packages/billing/.eslintrc.js b/packages/billing/.eslintrc.cjs similarity index 100% rename from packages/billing/.eslintrc.js rename to packages/billing/.eslintrc.cjs diff --git a/packages/realm-server/.eslintrc.js b/packages/realm-server/.eslintrc.cjs similarity index 100% rename from packages/realm-server/.eslintrc.js rename to packages/realm-server/.eslintrc.cjs diff --git a/packages/realm-server/scripts/run-test-modules.js b/packages/realm-server/scripts/run-test-modules.cjs similarity index 100% rename from packages/realm-server/scripts/run-test-modules.js rename to packages/realm-server/scripts/run-test-modules.cjs diff --git a/packages/realm-server/scripts/shard-test-modules.js b/packages/realm-server/scripts/shard-test-modules.cjs similarity index 89% rename from packages/realm-server/scripts/shard-test-modules.js rename to packages/realm-server/scripts/shard-test-modules.cjs index 7eaeb1124c..8950f4c1cf 100644 --- a/packages/realm-server/scripts/shard-test-modules.js +++ b/packages/realm-server/scripts/shard-test-modules.cjs @@ -6,7 +6,7 @@ // to the requested shard (1-based). Files are sorted alphabetically and // distributed round-robin so every shard gets a roughly equal share. // -// Usage: node shard-test-modules.js +// Usage: node shard-test-modules.cjs // Output: module names joined by "|", suitable for TEST_MODULES. const fs = require('node:fs'); // eslint-disable-line @typescript-eslint/no-var-requires @@ -17,7 +17,7 @@ const totalShards = parseInt(process.argv[3], 10); if (!shard || !totalShards || shard < 1 || shard > totalShards) { console.error( - `Usage: shard-test-modules.js (got shard=${process.argv[2]}, totalShards=${process.argv[3]})`, + `Usage: shard-test-modules.cjs (got shard=${process.argv[2]}, totalShards=${process.argv[3]})`, ); process.exit(1); } diff --git a/packages/realm-test-harness/.eslintrc.js b/packages/realm-test-harness/.eslintrc.cjs similarity index 100% rename from packages/realm-test-harness/.eslintrc.js rename to packages/realm-test-harness/.eslintrc.cjs From e0695207864691b438b3cf221f17fdbe7799eee7 Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Wed, 17 Jun 2026 14:38:52 -0400 Subject: [PATCH 11/38] docs: record software-factory completion + config-file ESM class in codemod README Co-Authored-By: Claude Opus 4.8 --- scripts/esm-codemod/README.md | 46 +++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/scripts/esm-codemod/README.md b/scripts/esm-codemod/README.md index 3437337b8a..1c934e86ac 100644 --- a/scripts/esm-codemod/README.md +++ b/scripts/esm-codemod/README.md @@ -35,21 +35,22 @@ reading the first failure, then fixing and repeating. Classes marked **automated** are handled by `run.mjs`; **manual** ones are listed in the next section. -| # | Symptom | Cause | Fix | | -| --- | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | -| 1 | `ERR_MODULE_NOT_FOUND` resolving a relative import `./foo` | Node does no extension search or directory-index resolution | append `./foo.ts` / `./foo.gts` / `./foo/index.ts`; bare `'.'` → `'./index.ts'` | automated (`add-relative-extensions`) | -| 2 | `ERR_MODULE_NOT_FOUND` resolving a workspace pkg subpath (`@cardstack/billing/x`) | workspace package has no `exports` map → Node looks for `index.js` | add an `exports` map pointing at `.ts` + `"type":"module"` | **manual** | -| 3 | `Cannot find module '.../lodash/merge'` (`Did you mean lodash/merge.js?`) | `lodash` is CJS-only with no exports map | repo-wide switch to `lodash-es` named imports | automated (`lodash-to-lodash-es`) | -| 4 | `does not provide an export named 'X'` from a CJS pkg (`fs-extra`, `debug`, `qunit`, `jsonwebtoken`) | Node can't statically read named exports from these CJS modules | default-import + destructure | automated (`cjs-named-to-default`, line-anchored so it skips imports embedded in test-fixture strings) — extend `CJS_PACKAGES` as new ones surface | -| 5 | `ERR_MODULE_NOT_FOUND` on a CJS pkg deep import (`matrix-js-sdk/lib/x`) | no exports map; ESM won't add `.js` or pick a file over a same-named dir | append `.js` | **manual** (small, package-specific) | -| 6 | `Cannot find module '.../scripts/x.js'` | a stray CJS file was renamed `.cjs` (because the pkg is now `type:module`) but the import still says `.js` | update the import to `.cjs` | **manual** | -| 7 | `ReferenceError: __dirname is not defined` | CJS globals don't exist under ESM | `import.meta.dirname` / `import.meta.filename` | automated (`dirname-to-import-meta`) | -| 8 | wrong path built from `import.meta.url` | `import.meta.url` is a `file://` URL string, not a path | use `import.meta.dirname` | **manual** (rare — was a WIP bug) | -| 9 | `ReferenceError: exports is not defined` when a consumer runs the dep via `ts-node` | once a dep ships an `exports` map Node handles its `.ts` natively, colliding with a still-`ts-node` consumer | the dep + all its node-run consumers must drop ts-node in the same change (big-bang) | **manual** (coordination) | -| 10 | in-source `spawn('ts-node', ['--transpileOnly', 'entry', …])` | child processes also need native node | `spawn('node', ['entry.ts', …])` (or `process.execPath`) | **manual** (few sites, varied shapes) | -| 11 | `ReferenceError: require is not defined in ES module scope` | `require()` / lazy `require()` don't exist in ESM | `const require = createRequire(import.meta.url)` shim, OR static/dynamic import. Native `require()` does NO extension search — `require('./x.ts')` works, `require('./x')` and `require('./dir')` do not | **manual** (small set) | -| 12 | a test's `sinon.stub(NS, 'fn')` / `(NS as any).fn = …` silently no-ops | ES-module namespace objects (`import * as NS`) are sealed; their bindings are read-only | inject the dependency, or stub through a small mutable indirection module the source calls and the test imports — not the namespace | **manual** (per-test; ai-bot Sentry tests now stub `lib/sentry.ts`'s `errorReporter`) | -| 13 | `X is not a function` from `import X from 'some-cjs-pkg'` (e.g. `node-pg-migrate`) | CJS pkg authored with transpiled `exports.default = fn`: native ESM binds `X = module.exports` (the whole namespace) and the callable is on `X.default`; ts-node's `esModuleInterop` unwrapped it | `const fn = (X as any).default ?? X` | **manual** (surfaces at runtime, not load — verify the export shape) | +| # | Symptom | Cause | Fix | | +| --- | ------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | +| 1 | `ERR_MODULE_NOT_FOUND` resolving a relative import `./foo` | Node does no extension search or directory-index resolution | append `./foo.ts` / `./foo.gts` / `./foo/index.ts`; bare `'.'` → `'./index.ts'` | automated (`add-relative-extensions`) | +| 2 | `ERR_MODULE_NOT_FOUND` resolving a workspace pkg subpath (`@cardstack/billing/x`) | workspace package has no `exports` map → Node looks for `index.js` | add an `exports` map pointing at `.ts` + `"type":"module"` | **manual** | +| 3 | `Cannot find module '.../lodash/merge'` (`Did you mean lodash/merge.js?`) | `lodash` is CJS-only with no exports map | repo-wide switch to `lodash-es` named imports | automated (`lodash-to-lodash-es`) | +| 4 | `does not provide an export named 'X'` from a CJS pkg (`fs-extra`, `debug`, `qunit`, `jsonwebtoken`) | Node can't statically read named exports from these CJS modules | default-import + destructure | automated (`cjs-named-to-default`, line-anchored so it skips imports embedded in test-fixture strings) — extend `CJS_PACKAGES` as new ones surface | +| 5 | `ERR_MODULE_NOT_FOUND` on a CJS pkg deep import (`matrix-js-sdk/lib/x`) | no exports map; ESM won't add `.js` or pick a file over a same-named dir | append `.js` | **manual** (small, package-specific) | +| 6 | `Cannot find module '.../scripts/x.js'` | a stray CJS file was renamed `.cjs` (because the pkg is now `type:module`) but the import still says `.js` | update the import to `.cjs` | **manual** | +| 7 | `ReferenceError: __dirname is not defined` | CJS globals don't exist under ESM | `import.meta.dirname` / `import.meta.filename` | automated (`dirname-to-import-meta`) | +| 8 | wrong path built from `import.meta.url` | `import.meta.url` is a `file://` URL string, not a path | use `import.meta.dirname` | **manual** (rare — was a WIP bug) | +| 9 | `ReferenceError: exports is not defined` when a consumer runs the dep via `ts-node` | once a dep ships an `exports` map Node handles its `.ts` natively, colliding with a still-`ts-node` consumer | the dep + all its node-run consumers must drop ts-node in the same change (big-bang) | **manual** (coordination) | +| 10 | in-source `spawn('ts-node', ['--transpileOnly', 'entry', …])` | child processes also need native node | `spawn('node', ['entry.ts', …])` (or `process.execPath`) | **manual** (few sites, varied shapes) | +| 11 | `ReferenceError: require is not defined in ES module scope` | `require()` / lazy `require()` don't exist in ESM | `const require = createRequire(import.meta.url)` shim, OR static/dynamic import. Native `require()` does NO extension search — `require('./x.ts')` works, `require('./x')` and `require('./dir')` do not | **manual** (small set) | +| 12 | a test's `sinon.stub(NS, 'fn')` / `(NS as any).fn = …` silently no-ops | ES-module namespace objects (`import * as NS`) are sealed; their bindings are read-only | inject the dependency, or stub through a small mutable indirection module the source calls and the test imports — not the namespace | **manual** (per-test; ai-bot Sentry tests now stub `lib/sentry.ts`'s `errorReporter`) | +| 13 | `X is not a function` from `import X from 'some-cjs-pkg'` (e.g. `node-pg-migrate`) | CJS pkg authored with transpiled `exports.default = fn`: native ESM binds `X = module.exports` (the whole namespace) and the callable is on `X.default`; ts-node's `esModuleInterop` unwrapped it | `const fn = (X as any).default ?? X` | **manual** (surfaces at runtime, not load — verify the export shape) | +| 14 | `module is not defined in ES module scope` loading a `.js` config/script (`.eslintrc.js`, helper scripts run via `node`) | the pkg is now `type:module`, so its CJS `.js` files (using `module.exports`/`require`) are parsed as ESM | rename to `.cjs` (ESLint still auto-discovers `.eslintrc.cjs`) and update any `node x.js` / path references | **manual** (find CJS `.js` in each `type:module` pkg) | ### Invocation sites (automated — `ts-node-to-node`) @@ -93,11 +94,20 @@ These are too package-specific or too coupled for a blind codemod: (Sentry namespace mocking, fixed via `lib/sentry.ts`) and class #13 (`node-pg-migrate` default interop in `postgres`). The locking tests need PG env (`PGHOST`/`PGPORT`/`PGUSER`/`PGPASSWORD`) like the rest of the DB suite. -- **software-factory**: full node suite needs `boxel-cli` + `software-factory`'s own - source migrated (their `src/logger.ts` etc. still use bare `require()`); the - bootstrap wiring is in place. +- **software-factory**: full node suite passes (452/453). The one failure + (port-allocator dual-stack `::` bind) is a macOS-vs-Linux socket-semantics + difference, not a migration regression. Unblocked by the `@cardstack/boxel-cli` + `exports` map, the `@cardstack/logger` createRequire fix (class #11, shared + with `realm-test-harness`), and the `.eslintrc.cjs` rename (class #14). - **realm-server**: the full suite needs the dev services stack to run; the bootstrap is validated on standalone unit tests. +- **realm-server / runtime-common lazy `require()`** (class #11): a few still + unfixed — `runtime-common/fetch-node.ts` (`require('undici')`/`require('dns')`), + `realm-server/setup-localhost-resolver.ts`, `realm-server/lib/wtfnode-on-signal.ts`. + They're lazy (inside functions), so they only throw when that code path runs; + fix with a `createRequire` shim when validating realm-server end-to-end. +- **realm-server `testem.js`** is CJS under `type:module` but only loaded by the + (now-unused) testem CLI, so it's dormant rather than broken. ## Verifying a package loads From 34a7b52ededeb2eb9ee0d86317db6d3b0a411d27 Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Wed, 17 Jun 2026 14:41:14 -0400 Subject: [PATCH 12/38] fix: shim require in realm-server's lazy env-gated loaders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit setup-localhost-resolver.ts (undici/dns, gated on BOXEL_ENVIRONMENT) and lib/wtfnode-on-signal.ts (wtfnode, gated on BOXEL_WTFNODE) call `require`, which doesn't exist in ESM scope — they'd throw the moment their gate is set. Recreate `require` via createRequire inside each guard, preserving the lazy, optional-dependency semantics (matching the existing fetch-node.ts pattern). Co-Authored-By: Claude Opus 4.8 --- packages/realm-server/lib/wtfnode-on-signal.ts | 5 ++++- packages/realm-server/setup-localhost-resolver.ts | 7 +++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/realm-server/lib/wtfnode-on-signal.ts b/packages/realm-server/lib/wtfnode-on-signal.ts index 865f8a772e..a1b88bb111 100644 --- a/packages/realm-server/lib/wtfnode-on-signal.ts +++ b/packages/realm-server/lib/wtfnode-on-signal.ts @@ -5,8 +5,11 @@ // // Import this for side effects at the top of each node entry point. +import { createRequire } from 'module'; + if (process.env.BOXEL_WTFNODE === '1') { - // eslint-disable-next-line @typescript-eslint/no-var-requires + // `require` doesn't exist in ESM scope; recreate it for this lazy, opt-in load. + const require = createRequire(import.meta.url); const wtfnode = require('wtfnode'); const tag = (process.argv[1] || 'node').split('/').pop() + `(pid=${process.pid})`; diff --git a/packages/realm-server/setup-localhost-resolver.ts b/packages/realm-server/setup-localhost-resolver.ts index 8b061e9021..e95cd592cf 100644 --- a/packages/realm-server/setup-localhost-resolver.ts +++ b/packages/realm-server/setup-localhost-resolver.ts @@ -7,11 +7,14 @@ // NOTE: This runs before logger setup, so we check the env var directly instead // of importing isEnvironmentMode() (which would trigger a logger import). +import { createRequire } from 'module'; + if (process.env.BOXEL_ENVIRONMENT) { try { - // eslint-disable-next-line @typescript-eslint/no-var-requires + // `require` doesn't exist in ESM scope; recreate it so undici stays a lazy, + // optional load (the catch below tolerates it being absent). + const require = createRequire(import.meta.url); const undici = require('undici') as typeof import('undici'); - // eslint-disable-next-line @typescript-eslint/no-var-requires const dns = require('dns'); const agent = new undici.Agent({ From b8a46b5a2fa83eef9468c333793537b4bf9c51e5 Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Wed, 17 Jun 2026 14:41:59 -0400 Subject: [PATCH 13/38] docs: mark cluster require() sites cleared in codemod README Co-Authored-By: Claude Opus 4.8 --- scripts/esm-codemod/README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/scripts/esm-codemod/README.md b/scripts/esm-codemod/README.md index 1c934e86ac..e53df8fcc1 100644 --- a/scripts/esm-codemod/README.md +++ b/scripts/esm-codemod/README.md @@ -100,12 +100,11 @@ These are too package-specific or too coupled for a blind codemod: `exports` map, the `@cardstack/logger` createRequire fix (class #11, shared with `realm-test-harness`), and the `.eslintrc.cjs` rename (class #14). - **realm-server**: the full suite needs the dev services stack to run; the - bootstrap is validated on standalone unit tests. -- **realm-server / runtime-common lazy `require()`** (class #11): a few still - unfixed — `runtime-common/fetch-node.ts` (`require('undici')`/`require('dns')`), - `realm-server/setup-localhost-resolver.ts`, `realm-server/lib/wtfnode-on-signal.ts`. - They're lazy (inside functions), so they only throw when that code path runs; - fix with a `createRequire` shim when validating realm-server end-to-end. + bootstrap is validated on standalone unit tests. All known bare/lazy + `require()` sites in the cluster are now shimmed (`createRequire`) or + dual-mode — every remaining `require()` either has a `const require = +createRequire(import.meta.url)` in its file or is guarded by + `typeof require === 'function'`. - **realm-server `testem.js`** is CJS under `type:module` but only loaded by the (now-unused) testem CLI, so it's dormant rather than broken. From 4173b5cb2b2b94b35ddec712d548e7f2071963fb Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Wed, 17 Jun 2026 15:26:23 -0400 Subject: [PATCH 14/38] fix: green lint:types across the native-ESM node cluster MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flipping the node cluster to "type":"module" switches ember-tsc's nodenext resolution from CJS-mode to ESM-mode, which surfaced the parked-WIP type errors. Root causes and fixes: - Base-realm path alias (the bulk): under ESM-mode nodenext the extensionless `"https://cardstack.com/base/*": ["../base/*"]` mapping no longer resolves (.gts/.ts need explicit extensions). Expand every tsconfig's mapping to try `*.gts`/`*.ts`/`*.d.ts`/`*`. This also clears the transitive TS2307 cascade in consumers (catalog, host, …) that type-check runtime-common's now-ESM sources. - CJS default-interop the nodenext type layer can't model even though it works at runtime: bump magic-string 0.25.9 -> ^0.30.21 (properly packaged exports+types; AMD transpiler output verified unchanged); re-export `ignore` once with its call signature (runtime-common/ignore.ts); type node-pg-migrate's runner via RunnerOption. - Make ai-bot/bot-runner/software-factory/matrix "type":"module" (they already run as ESM and use import.meta, which CJS-mode rejected with TS1470); switch matrix's tsconfig to nodenext + skipLibCheck; rename their CJS .eslintrc.js -> .cjs. - Misc: `import type` from a bare `utils/jwt` -> relative; matrix-js-sdk type deep-import gains .js; QUnit.reporters/on cast (missing from @types/qunit); drop a now-conflicting `declare const QUnit`; sweep 3 catalog cards to lodash-es. All nine node-cluster packages now type-check clean (0 errors): runtime-common, postgres, billing, realm-server, realm-test-harness, ai-bot, bot-runner, software-factory, matrix. Suites still pass (ai-bot 170, bot-runner 38) and the service entries still load. Co-Authored-By: Claude Opus 4.8 --- .../ai-bot/{.eslintrc.js => .eslintrc.cjs} | 0 packages/ai-bot/lib/code-patch-correctness.ts | 2 +- packages/ai-bot/package.json | 1 + packages/ai-bot/tests/qunit-bootstrap.ts | 4 +- packages/ai-bot/tsconfig.json | 7 +++- packages/billing/tsconfig.json | 7 +++- packages/bot-runner/package.json | 1 + packages/bot-runner/tests/qunit-bootstrap.ts | 4 +- packages/bot-runner/tsconfig.json | 7 +++- packages/catalog/tsconfig.json | 42 ++++++------------- packages/experiments-realm/tsconfig.json | 16 +++---- packages/host/tsconfig.json | 7 +++- packages/matrix/package.json | 1 + packages/matrix/tsconfig.json | 12 ++++-- packages/postgres/pg-adapter.ts | 13 +++--- packages/postgres/tsconfig.json | 7 +++- .../handlers/handle-realm-auth.ts | 2 +- packages/realm-server/tests/index.ts | 4 +- packages/realm-server/tsconfig.json | 7 +++- packages/runtime-common/ignore.ts | 8 ++++ packages/runtime-common/index-runner.ts | 2 +- .../index-runner/discover-invalidations.ts | 2 +- .../runtime-common/realm-index-updater.ts | 2 +- packages/runtime-common/tsconfig.json | 7 +++- .../{.eslintrc.js => .eslintrc.cjs} | 0 packages/software-factory/package.json | 1 + .../tests/factory-tool-builder.test.ts | 4 -- .../software-factory/tests/qunit-bootstrap.ts | 4 +- packages/software-factory/tsconfig.json | 7 +++- packages/test-realm-cards/tsconfig.json | 7 +++- packages/vscode-boxel-tools/tsconfig.json | 7 +++- pnpm-lock.yaml | 6 +-- pnpm-workspace.yaml | 2 +- 33 files changed, 123 insertions(+), 80 deletions(-) rename packages/ai-bot/{.eslintrc.js => .eslintrc.cjs} (100%) create mode 100644 packages/runtime-common/ignore.ts rename packages/software-factory/{.eslintrc.js => .eslintrc.cjs} (100%) diff --git a/packages/ai-bot/.eslintrc.js b/packages/ai-bot/.eslintrc.cjs similarity index 100% rename from packages/ai-bot/.eslintrc.js rename to packages/ai-bot/.eslintrc.cjs diff --git a/packages/ai-bot/lib/code-patch-correctness.ts b/packages/ai-bot/lib/code-patch-correctness.ts index 3daa1699cc..7693ad9c22 100644 --- a/packages/ai-bot/lib/code-patch-correctness.ts +++ b/packages/ai-bot/lib/code-patch-correctness.ts @@ -1,5 +1,5 @@ import type { MatrixClient } from 'matrix-js-sdk'; -import type { RoomMessageEventContent } from 'matrix-js-sdk/lib/@types/events'; +import type { RoomMessageEventContent } from 'matrix-js-sdk/lib/@types/events.js'; import { uuidv4 } from '@cardstack/runtime-common'; import type { PendingCodePatchCorrectnessCheck } from '@cardstack/runtime-common/ai/types'; diff --git a/packages/ai-bot/package.json b/packages/ai-bot/package.json index 42c39d331a..6e6a42b90b 100644 --- a/packages/ai-bot/package.json +++ b/packages/ai-bot/package.json @@ -1,5 +1,6 @@ { "name": "@cardstack/ai-bot", + "type": "module", "dependencies": { "@cardstack/billing": "workspace:*", "@cardstack/postgres": "workspace:*", diff --git a/packages/ai-bot/tests/qunit-bootstrap.ts b/packages/ai-bot/tests/qunit-bootstrap.ts index 1867954065..6f938d42c4 100644 --- a/packages/ai-bot/tests/qunit-bootstrap.ts +++ b/packages/ai-bot/tests/qunit-bootstrap.ts @@ -7,7 +7,7 @@ import QUnit from 'qunit'; QUnit.config.autostart = false; -QUnit.reporters.tap.init(QUnit); -QUnit.on('runEnd', (data) => { +(QUnit as any).reporters.tap.init(QUnit); // QUnit 2.x API missing from @types/qunit +(QUnit as any).on('runEnd', (data: { testCounts: { failed: number } }) => { process.exitCode = data.testCounts.failed > 0 ? 1 : 0; }); diff --git a/packages/ai-bot/tsconfig.json b/packages/ai-bot/tsconfig.json index 9d1b5b4ebf..27d530eb29 100644 --- a/packages/ai-bot/tsconfig.json +++ b/packages/ai-bot/tsconfig.json @@ -26,7 +26,12 @@ "skipLibCheck": true, "strict": true, "paths": { - "https://cardstack.com/base/*": ["../base/*"], + "https://cardstack.com/base/*": [ + "../base/*.gts", + "../base/*.ts", + "../base/*.d.ts", + "../base/*" + ], "@cardstack/boxel-ui": ["../boxel-ui/addon"], "@cardstack/boxel-ui/*": ["../boxel-ui/addon/*"] }, diff --git a/packages/billing/tsconfig.json b/packages/billing/tsconfig.json index 5516357016..ab079dac84 100644 --- a/packages/billing/tsconfig.json +++ b/packages/billing/tsconfig.json @@ -26,7 +26,12 @@ "skipLibCheck": true, "strict": true, "paths": { - "https://cardstack.com/base/*": ["../base/*"], + "https://cardstack.com/base/*": [ + "../base/*.gts", + "../base/*.ts", + "../base/*.d.ts", + "../base/*" + ], "@cardstack/boxel-ui": ["../boxel-ui/addon"], "@cardstack/boxel-ui/*": ["../boxel-ui/addon/*"], "*": ["types/*"] diff --git a/packages/bot-runner/package.json b/packages/bot-runner/package.json index 78b9e2bfd4..b087a05758 100644 --- a/packages/bot-runner/package.json +++ b/packages/bot-runner/package.json @@ -1,5 +1,6 @@ { "name": "@cardstack/bot-runner", + "type": "module", "dependencies": { "@cardstack/postgres": "workspace:*", "@cardstack/runtime-common": "workspace:*", diff --git a/packages/bot-runner/tests/qunit-bootstrap.ts b/packages/bot-runner/tests/qunit-bootstrap.ts index 1867954065..6f938d42c4 100644 --- a/packages/bot-runner/tests/qunit-bootstrap.ts +++ b/packages/bot-runner/tests/qunit-bootstrap.ts @@ -7,7 +7,7 @@ import QUnit from 'qunit'; QUnit.config.autostart = false; -QUnit.reporters.tap.init(QUnit); -QUnit.on('runEnd', (data) => { +(QUnit as any).reporters.tap.init(QUnit); // QUnit 2.x API missing from @types/qunit +(QUnit as any).on('runEnd', (data: { testCounts: { failed: number } }) => { process.exitCode = data.testCounts.failed > 0 ? 1 : 0; }); diff --git a/packages/bot-runner/tsconfig.json b/packages/bot-runner/tsconfig.json index eda8b5f44e..f33fc1dae9 100644 --- a/packages/bot-runner/tsconfig.json +++ b/packages/bot-runner/tsconfig.json @@ -26,7 +26,12 @@ "skipLibCheck": true, "strict": true, "paths": { - "https://cardstack.com/base/*": ["../base/*"], + "https://cardstack.com/base/*": [ + "../base/*.gts", + "../base/*.ts", + "../base/*.d.ts", + "../base/*" + ], "@cardstack/boxel-ui": ["../boxel-ui/addon"], "@cardstack/boxel-ui/*": ["../boxel-ui/addon/*"], "@cardstack/runtime-common": ["../runtime-common"], diff --git a/packages/catalog/tsconfig.json b/packages/catalog/tsconfig.json index 10ea6c1ddc..f24264165f 100644 --- a/packages/catalog/tsconfig.json +++ b/packages/catalog/tsconfig.json @@ -26,39 +26,21 @@ "skipLibCheck": true, "paths": { "https://cardstack.com/base/*": [ + "../base/*.gts", + "../base/*.ts", + "../base/*.d.ts", "../base/*" ], - "@cardstack/catalog/*": [ - "contents/*" - ], - "@cardstack/host/*": [ - "../host/app/*" - ], - "@cardstack/host/tests/*": [ - "../host/tests/*" - ], - "@cardstack/openrouter/*": [ - "../openrouter-realm/*" - ], - "@cardstack/boxel-host/commands/*": [ - "../host/app/commands/*" - ], - "@cardstack/boxel-ui": [ - "../boxel-ui/addon" - ], - "@cardstack/boxel-ui/*": [ - "../boxel-ui/addon/*" - ], - "*": [ - "../host/types/*" - ] + "@cardstack/catalog/*": ["contents/*"], + "@cardstack/host/*": ["../host/app/*"], + "@cardstack/host/tests/*": ["../host/tests/*"], + "@cardstack/openrouter/*": ["../openrouter-realm/*"], + "@cardstack/boxel-host/commands/*": ["../host/app/commands/*"], + "@cardstack/boxel-ui": ["../boxel-ui/addon"], + "@cardstack/boxel-ui/*": ["../boxel-ui/addon/*"], + "*": ["../host/types/*"] }, "types": ["@cardstack/local-types", "qunit", "qunit-dom"] }, - "include": [ - "../host/types/**/*", - "**/*.d.ts", - "**/*.ts", - "**/*.gts" - ] + "include": ["../host/types/**/*", "**/*.d.ts", "**/*.ts", "**/*.gts"] } diff --git a/packages/experiments-realm/tsconfig.json b/packages/experiments-realm/tsconfig.json index 48a215fb58..76d2fd3d87 100644 --- a/packages/experiments-realm/tsconfig.json +++ b/packages/experiments-realm/tsconfig.json @@ -23,18 +23,14 @@ "experimentalDecorators": true, "paths": { "https://cardstack.com/base/*": [ + "../base/*.gts", + "../base/*.ts", + "../base/*.d.ts", "../base/*" ], - "@cardstack/host/tests/*": [ - "../host/tests/*" - ] + "@cardstack/host/tests/*": ["../host/tests/*"] }, - "types": [ - "@cardstack/local-types" - ] + "types": ["@cardstack/local-types"] }, - "include": [ - "**/*.ts", - "**/*.gts" - ] + "include": ["**/*.ts", "**/*.gts"] } diff --git a/packages/host/tsconfig.json b/packages/host/tsconfig.json index 3dcfaa3492..4b23b4dbb6 100644 --- a/packages/host/tsconfig.json +++ b/packages/host/tsconfig.json @@ -28,7 +28,12 @@ "@cardstack/host/tests/*": ["tests/*"], "@cardstack/host/*": ["app/*"], "@cardstack/boxel-host/commands/*": ["app/commands/*"], - "https://cardstack.com/base/*": ["../base/*"], + "https://cardstack.com/base/*": [ + "../base/*.gts", + "../base/*.ts", + "../base/*.d.ts", + "../base/*" + ], "@cardstack/openrouter/*": ["../openrouter-realm/*"], "*": ["types/*"] }, diff --git a/packages/matrix/package.json b/packages/matrix/package.json index a8f4c73464..fda3e34e8b 100644 --- a/packages/matrix/package.json +++ b/packages/matrix/package.json @@ -2,6 +2,7 @@ "name": "@cardstack/matrix", "version": "1.0.0", "license": "MIT", + "type": "module", "devDependencies": { "@aws-crypto/sha256-js": "catalog:", "@cardstack/runtime-common": "workspace:*", diff --git a/packages/matrix/tsconfig.json b/packages/matrix/tsconfig.json index 3e9a6a4fde..9296f90469 100644 --- a/packages/matrix/tsconfig.json +++ b/packages/matrix/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "target": "es2020", "allowJs": true, - "moduleResolution": "node", + "moduleResolution": "nodenext", "allowImportingTsExtensions": true, "allowSyntheticDefaultImports": true, "noImplicitAny": true, @@ -19,12 +19,18 @@ "inlineSourceMap": true, "inlineSources": true, "baseUrl": ".", - "module": "CommonJS", + "module": "nodenext", "esModuleInterop": true, + "skipLibCheck": true, "experimentalDecorators": true, "strict": true, "paths": { - "https://cardstack.com/base/*": ["../base/*"], + "https://cardstack.com/base/*": [ + "../base/*.gts", + "../base/*.ts", + "../base/*.d.ts", + "../base/*" + ], "@cardstack/boxel-ui": ["../boxel-ui/addon"], "@cardstack/boxel-ui/*": ["../boxel-ui/addon/*"], "*": ["types/*"] diff --git a/packages/postgres/pg-adapter.ts b/packages/postgres/pg-adapter.ts index ad97f7121f..303012dcb6 100644 --- a/packages/postgres/pg-adapter.ts +++ b/packages/postgres/pg-adapter.ts @@ -9,18 +9,19 @@ import { param, } from '@cardstack/runtime-common'; import { createHash } from 'crypto'; -import nodePgMigrate from 'node-pg-migrate'; +import nodePgMigrate, { type RunnerOption } from 'node-pg-migrate'; import { join } from 'path'; import { Pool, Client, type Notification } from 'pg'; import { postgresConfig } from './pg-config.ts'; import migrationNameFixes from './scripts/migration-name-fixes.cjs'; -// node-pg-migrate is CJS and exposes the runner on `.default`; native ESM -// doesn't unwrap it the way ts-node's esModuleInterop did. -const migrate = - (nodePgMigrate as unknown as { default?: typeof nodePgMigrate }).default ?? - nodePgMigrate; +// node-pg-migrate is CJS and exposes the runner on `.default` at runtime; native +// ESM doesn't unwrap it the way ts-node's esModuleInterop did, and the package's +// types declare the default as the runner, so cast to its call signature. +const migrate = ((nodePgMigrate as any).default ?? nodePgMigrate) as ( + options: RunnerOption, +) => Promise; // Hash a realm URL to a stable signed int64 (as a string, because JS numbers // can't represent the full int64 range). Used as a pg advisory lock key: diff --git a/packages/postgres/tsconfig.json b/packages/postgres/tsconfig.json index 9bd38a1942..19868bcffc 100644 --- a/packages/postgres/tsconfig.json +++ b/packages/postgres/tsconfig.json @@ -25,7 +25,12 @@ "skipLibCheck": true, "strict": true, "paths": { - "https://cardstack.com/base/*": ["../base/*"], + "https://cardstack.com/base/*": [ + "../base/*.gts", + "../base/*.ts", + "../base/*.d.ts", + "../base/*" + ], "@cardstack/boxel-ui": ["../boxel-ui/addon"], "@cardstack/boxel-ui/*": ["../boxel-ui/addon/*"], "*": ["types/*"] diff --git a/packages/realm-server/handlers/handle-realm-auth.ts b/packages/realm-server/handlers/handle-realm-auth.ts index 2374e65cd1..885d771278 100644 --- a/packages/realm-server/handlers/handle-realm-auth.ts +++ b/packages/realm-server/handlers/handle-realm-auth.ts @@ -11,7 +11,7 @@ import { upsertSessionRoom, type Expression, } from '@cardstack/runtime-common'; -import type { RealmServerTokenClaim } from 'utils/jwt'; +import type { RealmServerTokenClaim } from '../utils/jwt.ts'; import { getUserByMatrixUserId } from '@cardstack/billing/billing-queries'; import { createJWT } from '../jwt.ts'; import { diff --git a/packages/realm-server/tests/index.ts b/packages/realm-server/tests/index.ts index a0eedf609c..0d3a9e7a63 100644 --- a/packages/realm-server/tests/index.ts +++ b/packages/realm-server/tests/index.ts @@ -47,8 +47,8 @@ const require = createRequire(import.meta.url); // failure-based exit code. Running under `node tests/index.ts` we wire them up // here; autostart is disabled so every test file registers before we start. QUnit.config.autostart = false; -QUnit.reporters.tap.init(QUnit); -QUnit.on('runEnd', (data) => { +(QUnit as any).reporters.tap.init(QUnit); // QUnit 2.x API missing from @types/qunit +(QUnit as any).on('runEnd', (data: { testCounts: { failed: number } }) => { process.exitCode = data.testCounts.failed > 0 ? 1 : 0; }); diff --git a/packages/realm-server/tsconfig.json b/packages/realm-server/tsconfig.json index 76b1cf7c17..b9bf5a2f9e 100644 --- a/packages/realm-server/tsconfig.json +++ b/packages/realm-server/tsconfig.json @@ -25,7 +25,12 @@ "skipLibCheck": true, "strict": true, "paths": { - "https://cardstack.com/base/*": ["../base/*"], + "https://cardstack.com/base/*": [ + "../base/*.gts", + "../base/*.ts", + "../base/*.d.ts", + "../base/*" + ], "@cardstack/boxel-ui": ["../boxel-ui/addon"], "@cardstack/boxel-ui/*": ["../boxel-ui/addon/*"] }, diff --git a/packages/runtime-common/ignore.ts b/packages/runtime-common/ignore.ts new file mode 100644 index 0000000000..5a3964c5b9 --- /dev/null +++ b/packages/runtime-common/ignore.ts @@ -0,0 +1,8 @@ +// `ignore` ships no `types`/`exports` fields, so under nodenext ESM-mode +// TypeScript types its default export as a non-callable namespace even though +// the runtime default IS the factory function (verified under native node). +// Re-export it once with the correct call signature so call sites stay clean. +import ignoreImport, { type Ignore } from 'ignore'; + +export const ignore = ignoreImport as unknown as (options?: object) => Ignore; +export type { Ignore }; diff --git a/packages/runtime-common/index-runner.ts b/packages/runtime-common/index-runner.ts index 91faa4ec3b..334c0239d5 100644 --- a/packages/runtime-common/index-runner.ts +++ b/packages/runtime-common/index-runner.ts @@ -1,4 +1,4 @@ -import ignore, { type Ignore } from 'ignore'; +import { ignore, type Ignore } from './ignore.ts'; // Isomorphic UUID — works in both Node and the browser (host tests // instantiate IndexRunner inside a Chrome tab, so Node's built-in // `crypto.randomUUID` is not available). diff --git a/packages/runtime-common/index-runner/discover-invalidations.ts b/packages/runtime-common/index-runner/discover-invalidations.ts index 42bac26343..4cc829e870 100644 --- a/packages/runtime-common/index-runner/discover-invalidations.ts +++ b/packages/runtime-common/index-runner/discover-invalidations.ts @@ -1,4 +1,4 @@ -import ignore, { type Ignore } from 'ignore'; +import { ignore, type Ignore } from '../ignore.ts'; import { jobIdentity, diff --git a/packages/runtime-common/realm-index-updater.ts b/packages/runtime-common/realm-index-updater.ts index aac0b7cd97..3dc4f83695 100644 --- a/packages/runtime-common/realm-index-updater.ts +++ b/packages/runtime-common/realm-index-updater.ts @@ -24,7 +24,7 @@ import type { } from './tasks/indexer.ts'; import type { Realm } from './realm.ts'; import { RealmPaths } from './paths.ts'; -import ignore, { type Ignore } from 'ignore'; +import { ignore, type Ignore } from './ignore.ts'; export class RealmIndexUpdater { #realm: Realm; diff --git a/packages/runtime-common/tsconfig.json b/packages/runtime-common/tsconfig.json index 31b1b583fd..e02d04c8e9 100644 --- a/packages/runtime-common/tsconfig.json +++ b/packages/runtime-common/tsconfig.json @@ -24,7 +24,12 @@ "experimentalDecorators": true, "skipLibCheck": true, "paths": { - "https://cardstack.com/base/*": ["../base/*"], + "https://cardstack.com/base/*": [ + "../base/*.gts", + "../base/*.ts", + "../base/*.d.ts", + "../base/*" + ], "@cardstack/boxel-ui": ["../boxel-ui/addon/declarations"], "@cardstack/boxel-ui/*": ["../boxel-ui/addon/declarations/*"] }, diff --git a/packages/software-factory/.eslintrc.js b/packages/software-factory/.eslintrc.cjs similarity index 100% rename from packages/software-factory/.eslintrc.js rename to packages/software-factory/.eslintrc.cjs diff --git a/packages/software-factory/package.json b/packages/software-factory/package.json index 16b470951e..29683f210f 100644 --- a/packages/software-factory/package.json +++ b/packages/software-factory/package.json @@ -1,5 +1,6 @@ { "name": "@cardstack/software-factory", + "type": "module", "private": true, "version": "1.0.0", "license": "MIT", diff --git a/packages/software-factory/tests/factory-tool-builder.test.ts b/packages/software-factory/tests/factory-tool-builder.test.ts index b6e9a8074d..ceab5eed6a 100644 --- a/packages/software-factory/tests/factory-tool-builder.test.ts +++ b/packages/software-factory/tests/factory-tool-builder.test.ts @@ -31,13 +31,9 @@ const TARGET_REALM = 'https://realms.example.test/user/target/'; // for anything that slips past, but cleaning per-test is cheaper and // keeps the OS tmpdir from growing during the run. let pendingWorkspaces: TestWorkspace[] = []; -declare const QUnit: { - testDone: (cb: () => void) => void; -}; let testDoneHookInstalled = false; function installTestDoneHook() { if (testDoneHookInstalled) return; - if (typeof QUnit === 'undefined') return; testDoneHookInstalled = true; QUnit.testDone(() => { let toClean = pendingWorkspaces; diff --git a/packages/software-factory/tests/qunit-bootstrap.ts b/packages/software-factory/tests/qunit-bootstrap.ts index 1867954065..6f938d42c4 100644 --- a/packages/software-factory/tests/qunit-bootstrap.ts +++ b/packages/software-factory/tests/qunit-bootstrap.ts @@ -7,7 +7,7 @@ import QUnit from 'qunit'; QUnit.config.autostart = false; -QUnit.reporters.tap.init(QUnit); -QUnit.on('runEnd', (data) => { +(QUnit as any).reporters.tap.init(QUnit); // QUnit 2.x API missing from @types/qunit +(QUnit as any).on('runEnd', (data: { testCounts: { failed: number } }) => { process.exitCode = data.testCounts.failed > 0 ? 1 : 0; }); diff --git a/packages/software-factory/tsconfig.json b/packages/software-factory/tsconfig.json index 43a346c3e6..9369a3dbcb 100644 --- a/packages/software-factory/tsconfig.json +++ b/packages/software-factory/tsconfig.json @@ -26,7 +26,12 @@ "skipLibCheck": true, "strict": true, "paths": { - "https://cardstack.com/base/*": ["../base/*"] + "https://cardstack.com/base/*": [ + "../base/*.gts", + "../base/*.ts", + "../base/*.d.ts", + "../base/*" + ] }, "types": ["@cardstack/local-types", "node"] }, diff --git a/packages/test-realm-cards/tsconfig.json b/packages/test-realm-cards/tsconfig.json index 917c3ece39..ba7706d102 100644 --- a/packages/test-realm-cards/tsconfig.json +++ b/packages/test-realm-cards/tsconfig.json @@ -22,7 +22,12 @@ "strict": true, "experimentalDecorators": true, "paths": { - "https://cardstack.com/base/*": ["../base/*"], + "https://cardstack.com/base/*": [ + "../base/*.gts", + "../base/*.ts", + "../base/*.d.ts", + "../base/*" + ], "@cardstack/boxel-host/commands/*": ["../host/app/commands/*"] }, "types": ["@cardstack/local-types"] diff --git a/packages/vscode-boxel-tools/tsconfig.json b/packages/vscode-boxel-tools/tsconfig.json index df42714344..053b2bf7f9 100644 --- a/packages/vscode-boxel-tools/tsconfig.json +++ b/packages/vscode-boxel-tools/tsconfig.json @@ -13,7 +13,12 @@ "experimentalDecorators": true, "skipLibCheck": true, "paths": { - "https://cardstack.com/base/*": ["../base/*"], + "https://cardstack.com/base/*": [ + "../base/*.gts", + "../base/*.ts", + "../base/*.d.ts", + "../base/*" + ], "@cardstack/runtime-common/*": ["../runtime-common/*"], "babel-plugin-ember-template-compilation": [ "node_modules/babel-plugin-ember-template-compilation/*" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f21f709e3a..49abc32a0c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -523,8 +523,8 @@ catalogs: specifier: ^1.8.1 version: 1.9.2 magic-string: - specifier: 0.25.9 - version: 0.25.9 + specifier: ^0.30.21 + version: 0.30.21 marked: specifier: ^12.0.1 version: 12.0.2 @@ -3058,7 +3058,7 @@ importers: version: 1.9.2 magic-string: specifier: 'catalog:' - version: 0.25.9(patch_hash=32dda55b40f0bc860d0a8e93bee54d8005c34ed7ac5faed23ce9f5e5f57eea39) + version: 0.30.21 marked: specifier: 'catalog:' version: 12.0.2 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 6a844d47d3..3513795397 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -188,7 +188,7 @@ catalog: loglevel: ^1.8.1 lucide-static: ^0.447.0 macro-decorators: ^0.1.2 - magic-string: 0.25.9 + magic-string: ^0.30.21 katex: ^0.16.44 marked: ^12.0.1 marked-alert: ^2.1.2 From 8f2c7f419f0bb5e8aa2320190e7aef99fc6cf170 Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Wed, 17 Jun 2026 15:27:30 -0400 Subject: [PATCH 15/38] docs: record lint:types layer completion + nodenext decision in codemod README Co-Authored-By: Claude Opus 4.8 --- scripts/esm-codemod/README.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/scripts/esm-codemod/README.md b/scripts/esm-codemod/README.md index e53df8fcc1..e8cf87bcde 100644 --- a/scripts/esm-codemod/README.md +++ b/scripts/esm-codemod/README.md @@ -88,6 +88,32 @@ These are too package-specific or too coupled for a blind codemod: #12) — the latter is genuine per-test work (e.g. ai-bot's Sentry/locking tests fail because they reassign a sealed namespace binding). +## Type-checking (`lint:types`) + +All nine node-cluster packages type-check clean under `ember-tsc` (nodenext). +`"type":"module"` flips nodenext from CJS-mode to ESM-mode resolution, which is +what surfaces the type errors. Decision: stay on **nodenext** (not `bundler`) so +the type layer models the native-node runtime; the friction was bounded. Classes +fixed (see also #11/#13): + +- **Base-realm alias** (class #15): under ESM-mode nodenext the extensionless + `"https://cardstack.com/base/*": ["../base/*"]` mapping stops resolving. Expand + every tsconfig's mapping to `["../base/*.gts","../base/*.ts","../base/*.d.ts","../base/*"]`. + Applies to consumers too (host, catalog, …) — they re-type-check runtime-common's + now-ESM sources, so the cascade lands there as well. +- **`import.meta` rejected (TS1470/TS1343)**: a `type:module` (or import.meta-using) + package must type-check in ESM-mode — set `module`/`moduleResolution` to + `nodenext` and add `skipLibCheck`. Flip ai-bot/bot-runner/software-factory/matrix + to `type:module` (they already run as ESM). +- **CJS interop the nodenext type layer can't model** (runtime is fine): bump the + mispackaged dep when a properly-packaged version exists (magic-string + 0.25→0.30), else re-export once with the right signature (`runtime-common/ignore.ts`) + or cast (`node-pg-migrate` via `RunnerOption`). +- **Types missing from a dep** (`@types/qunit` lacks `.reporters`/`.on`): cast the + call site (`(QUnit as any)`), typing any callback param to avoid noImplicitAny. + +`@types/lodash` was swapped to `@types/lodash-es` alongside the runtime dep. + ## Remaining known gaps - **ai-bot**: full suite passes (170/170) — the 5 prior failures were class #12 @@ -105,6 +131,12 @@ These are too package-specific or too coupled for a blind codemod: dual-mode — every remaining `require()` either has a `const require = createRequire(import.meta.url)` in its file or is guarded by `typeof require === 'function'`. +- **host**: configured for the migration (nodenext + skipLibCheck + the base-path + fix, same as catalog which type-checks clean); its full `lint:types` is slow, so + CI is the practical confirmation. +- **experiments-realm**: pre-existing `lint:types` debt unrelated to the migration + (`node16` tsconfig, no `skipLibCheck`, ~568 source errors); only its base-path + mapping was touched here. - **realm-server `testem.js`** is CJS under `type:module` but only loaded by the (now-unused) testem CLI, so it's dormant rather than broken. From b1b50b13bbc382d871af31d9a0435098bd6b55df Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Wed, 17 Jun 2026 15:56:27 -0400 Subject: [PATCH 16/38] fix: declare lodash-es deps and satisfy realm-server lint CI surfaced two gaps from the lodash-es switch and the require shims: - base, boxel-ui, and experiments-realm import lodash-es but never declared it (the dep swap only covered packages that previously declared `lodash`), so their builds/type-checks failed to resolve the module. Add `lodash-es` (boxel-ui also swaps `@types/lodash` -> `@types/lodash-es`). - realm-server lint:js: prettier-wrap the multi-line CJS destructures the interop codemod emitted, and drop the now-unused `eslint-disable @typescript-eslint/no-var-requires` directives left above the createRequire-shimmed `require()` calls. Co-Authored-By: Claude Opus 4.8 --- packages/base/package.json | 3 ++- packages/boxel-ui/addon/package.json | 4 ++-- packages/experiments-realm/package.json | 1 + .../handlers/handle-publish-realm.ts | 9 ++++++++- .../realm-server/lib/dev-service-registry.ts | 9 ++++++++- packages/realm-server/node-realm.ts | 11 ++++++++++- .../realm-server/scripts/bench-realm/bench.ts | 6 +++++- packages/realm-server/synapse.ts | 8 +++++++- packages/realm-server/tests/helpers/index.ts | 9 ++++++++- packages/realm-server/tests/index.ts | 3 --- .../tests/publish-unpublish-realm-test.ts | 10 +++++++++- .../realm-server/tests/realm-endpoints-test.ts | 10 +++++++++- pnpm-lock.yaml | 18 +++++++++--------- 13 files changed, 78 insertions(+), 23 deletions(-) diff --git a/packages/base/package.json b/packages/base/package.json index 9f442ab93f..0bf39c593a 100644 --- a/packages/base/package.json +++ b/packages/base/package.json @@ -29,7 +29,8 @@ }, "peerDependencies": { "ember-provide-consume-context": "^0.7.0", - "ember-source": "catalog:" + "ember-source": "catalog:", + "lodash-es": "catalog:" }, "scripts": { "lint": "concurrently \"pnpm:lint:*(!fix)\" --names \"lint:\"", diff --git a/packages/boxel-ui/addon/package.json b/packages/boxel-ui/addon/package.json index edacc1757d..87be581ca9 100644 --- a/packages/boxel-ui/addon/package.json +++ b/packages/boxel-ui/addon/package.json @@ -63,7 +63,7 @@ "ember-velcro": "^2.1.3", "file-loader": "catalog:", "focus-trap": "catalog:", - "lodash": "catalog:", + "lodash-es": "catalog:", "pluralize": "catalog:", "tracked-built-ins": "catalog:", "typescript": "catalog:" @@ -82,7 +82,7 @@ "@rollup/plugin-babel": "catalog:", "@tsconfig/ember": "3.0.1", "@types/dompurify": "catalog:", - "@types/lodash": "catalog:", + "@types/lodash-es": "catalog:", "@types/pluralize": "catalog:", "@typescript-eslint/eslint-plugin": "catalog:", "@typescript-eslint/parser": "catalog:", diff --git a/packages/experiments-realm/package.json b/packages/experiments-realm/package.json index 253417cb5e..45736a777d 100644 --- a/packages/experiments-realm/package.json +++ b/packages/experiments-realm/package.json @@ -13,6 +13,7 @@ "@universal-ember/test-support": "catalog:", "@cardstack/view-transitions": "catalog:", "@types/lodash-es": "catalog:", + "lodash-es": "catalog:", "ember-animated": "catalog:", "chess.js": "catalog:", "concurrently": "catalog:", diff --git a/packages/realm-server/handlers/handle-publish-realm.ts b/packages/realm-server/handlers/handle-publish-realm.ts index 352e4e56eb..549003c1ec 100644 --- a/packages/realm-server/handlers/handle-publish-realm.ts +++ b/packages/realm-server/handlers/handle-publish-realm.ts @@ -19,7 +19,14 @@ import { getPublishedRealmDomainOverrides } from '@cardstack/runtime-common/cons import { join } from 'path'; import fsExtra from 'fs-extra'; -const { copySync, readJsonSync, writeJsonSync, removeSync, existsSync, moveSync } = fsExtra; +const { + copySync, + readJsonSync, + writeJsonSync, + removeSync, + existsSync, + moveSync, +} = fsExtra; import { fetchRequestFromContext, diff --git a/packages/realm-server/lib/dev-service-registry.ts b/packages/realm-server/lib/dev-service-registry.ts index 9bc6b78366..f386a51164 100644 --- a/packages/realm-server/lib/dev-service-registry.ts +++ b/packages/realm-server/lib/dev-service-registry.ts @@ -31,7 +31,14 @@ function traefikDynamicDir(): string { } catch { // Traefik not running — fall back to repo-relative path } - _traefikDir = resolve(import.meta.dirname, '..', '..', '..', 'traefik', 'dynamic'); + _traefikDir = resolve( + import.meta.dirname, + '..', + '..', + '..', + 'traefik', + 'dynamic', + ); return _traefikDir; } diff --git a/packages/realm-server/node-realm.ts b/packages/realm-server/node-realm.ts index f43426743e..a3884601e8 100644 --- a/packages/realm-server/node-realm.ts +++ b/packages/realm-server/node-realm.ts @@ -20,7 +20,16 @@ import sane, { type Watcher } from 'sane'; import type { ReadStream } from 'fs-extra'; import fsExtra from 'fs-extra'; -const { readdirSync, existsSync, writeFileSync, statSync, ensureDirSync, ensureFileSync, createReadStream, removeSync } = fsExtra; +const { + readdirSync, + existsSync, + writeFileSync, + statSync, + ensureDirSync, + ensureFileSync, + createReadStream, + removeSync, +} = fsExtra; import { join } from 'path'; import { Duplex } from 'node:stream'; import type { diff --git a/packages/realm-server/scripts/bench-realm/bench.ts b/packages/realm-server/scripts/bench-realm/bench.ts index 02c996f166..9ddf9e83b6 100644 --- a/packages/realm-server/scripts/bench-realm/bench.ts +++ b/packages/realm-server/scripts/bench-realm/bench.ts @@ -82,7 +82,11 @@ export const DEFAULT_WARMUP = 5; // the bench's instance JSONs `adoptsFrom`. No runtime fileFilter — the // glob is materialized in the snapshot itself, so the bench mounts the // realm with the default copy-everything semantics. -const benchSourceRealmDir = pathResolve(import.meta.dirname, 'fixtures', 'source-realm'); +const benchSourceRealmDir = pathResolve( + import.meta.dirname, + 'fixtures', + 'source-realm', +); export interface Scenario { name: string; diff --git a/packages/realm-server/synapse.ts b/packages/realm-server/synapse.ts index 73aac8cc34..23f1fd766b 100644 --- a/packages/realm-server/synapse.ts +++ b/packages/realm-server/synapse.ts @@ -28,7 +28,13 @@ function homeserverFile(): string { } } return resolve( - join(import.meta.dirname, '..', 'matrix', 'synapse-data', 'homeserver.yaml'), + join( + import.meta.dirname, + '..', + 'matrix', + 'synapse-data', + 'homeserver.yaml', + ), ); } diff --git a/packages/realm-server/tests/helpers/index.ts b/packages/realm-server/tests/helpers/index.ts index 74dc7f5ac5..e931a80bf3 100644 --- a/packages/realm-server/tests/helpers/index.ts +++ b/packages/realm-server/tests/helpers/index.ts @@ -1,5 +1,12 @@ import fsExtra from 'fs-extra'; -const { writeFileSync, writeJSONSync, readdirSync, statSync, ensureDirSync, copySync } = fsExtra; +const { + writeFileSync, + writeJSONSync, + readdirSync, + statSync, + ensureDirSync, + copySync, +} = fsExtra; import { NodeAdapter } from '../../node-realm.ts'; import { dirname, join } from 'path'; import { createHash } from 'crypto'; diff --git a/packages/realm-server/tests/index.ts b/packages/realm-server/tests/index.ts index 0d3a9e7a63..5b8ac4a64a 100644 --- a/packages/realm-server/tests/index.ts +++ b/packages/realm-server/tests/index.ts @@ -74,7 +74,6 @@ if (testModules) { // hardcoded test ports (4444-4471, etc.) bound after a test is aborted by // Ctrl+C or an abnormal exit (but not SIGKILL, which bypasses handlers). async function runTrackedCleanup(): Promise { - // eslint-disable-next-line @typescript-eslint/no-var-requires const helpers = require('./helpers/index.ts') as { closeTrackedServers?: () => Promise; stopTrackedPrerenderers?: () => Promise; @@ -102,7 +101,6 @@ for (let signal of ['SIGINT', 'SIGTERM', 'SIGHUP'] as const) { } QUnit.done(() => { - // eslint-disable-next-line @typescript-eslint/no-var-requires const helpers = require('./helpers/index.ts') as { closeTrackedServers?: () => Promise; stopTrackedPrerenderers?: () => Promise; @@ -118,7 +116,6 @@ QUnit.done(() => { await helpers.destroyTrackedQueuePublishers?.(); await helpers.closeTrackedDbAdapters?.(); try { - // eslint-disable-next-line @typescript-eslint/no-var-requires const undici = require('undici') as { getGlobalDispatcher?: () => { close?: () => Promise }; }; diff --git a/packages/realm-server/tests/publish-unpublish-realm-test.ts b/packages/realm-server/tests/publish-unpublish-realm-test.ts index c49e6d9b84..a814ed2b75 100644 --- a/packages/realm-server/tests/publish-unpublish-realm-test.ts +++ b/packages/realm-server/tests/publish-unpublish-realm-test.ts @@ -4,7 +4,15 @@ import type { SuperTest, Test } from 'supertest'; import supertest from 'supertest'; import { v4 as uuidv4 } from 'uuid'; import fsExtra from 'fs-extra'; -const { existsSync, ensureDirSync, copySync, pathExistsSync, readJsonSync, writeJsonSync, removeSync } = fsExtra; +const { + existsSync, + ensureDirSync, + copySync, + pathExistsSync, + readJsonSync, + writeJsonSync, + removeSync, +} = fsExtra; import { basename, join } from 'path'; import type { RealmHttpServer as Server } from '../server.ts'; import { dirSync, type DirResult } from 'tmp'; diff --git a/packages/realm-server/tests/realm-endpoints-test.ts b/packages/realm-server/tests/realm-endpoints-test.ts index a7336df01a..1fb2618951 100644 --- a/packages/realm-server/tests/realm-endpoints-test.ts +++ b/packages/realm-server/tests/realm-endpoints-test.ts @@ -5,7 +5,15 @@ import { join, resolve, basename } from 'path'; import type { RealmHttpServer as Server } from '../server.ts'; import { dirSync, type DirResult } from 'tmp'; import fsExtra from 'fs-extra'; -const { copySync, ensureDirSync, existsSync, readFileSync, readJSONSync, removeSync, writeFileSync } = fsExtra; +const { + copySync, + ensureDirSync, + existsSync, + readFileSync, + readJSONSync, + removeSync, + writeFileSync, +} = fsExtra; import { utimesSync } from 'fs'; import type { Realm } from '@cardstack/runtime-common'; import { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 49abc32a0c..90e91ed087 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -213,9 +213,6 @@ catalogs: '@types/koa__router': specifier: ^12.0.0 version: 12.0.5 - '@types/lodash': - specifier: ^4.17.15 - version: 4.17.24 '@types/lodash-es': specifier: ^4.17.12 version: 4.17.12 @@ -513,9 +510,6 @@ catalogs: loader.js: specifier: ^4.7.0 version: 4.7.0 - lodash: - specifier: ^4.17.21 - version: 4.18.1 lodash-es: specifier: ^4.17.21 version: 4.18.1 @@ -896,6 +890,9 @@ importers: ember-source: specifier: 'catalog:' version: 6.10.1(patch_hash=ea945024993105fb6cc4ae5cb5e9ea8e0eff6cd5fe0b0033c43dd0cf9453eb0d)(@glimmer/component@2.1.1)(rsvp@4.8.5) + lodash-es: + specifier: 'catalog:' + version: 4.18.1 devDependencies: '@babel/core': specifier: 'catalog:' @@ -1350,7 +1347,7 @@ importers: focus-trap: specifier: 'catalog:' version: 7.8.0 - lodash: + lodash-es: specifier: 'catalog:' version: 4.18.1 pluralize: @@ -1405,9 +1402,9 @@ importers: '@types/dompurify': specifier: 'catalog:' version: 3.2.0 - '@types/lodash': + '@types/lodash-es': specifier: 'catalog:' - version: 4.17.24 + version: 4.17.12 '@types/pluralize': specifier: 'catalog:' version: 0.0.30 @@ -1953,6 +1950,9 @@ importers: ember-template-lint: specifier: 'catalog:' version: 7.9.3 + lodash-es: + specifier: 'catalog:' + version: 4.18.1 tracked-built-ins: specifier: ^4.1.2 version: 4.1.2(@babel/core@7.29.0) From a397d5793b726848869d8e64717d42d640227d0e Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Wed, 17 Jun 2026 16:10:38 -0400 Subject: [PATCH 17/38] fix: schema-freshness check and require.main guards under ESM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two more CI failures from the native-ESM move: - Build / Realm Performance Benchmark: the host build's getLatestSchemaFile() (config/environment.js) picked the lexically-last entry in the migrations and schema dirs. The migrations dir now contains `package.json` (pins it to type:commonjs), which sorts after the timestamped migrations and made the freshness check compare `package.json` against the schema timestamp → false "schema out of date". Filter both lists to timestamped files only. - AMD Transpile Bench: `if (require.main === module)` entry-point guards throw `require is not defined` under ESM. Replace with `import.meta.main` (Node 24) across the affected scripts in runtime-common, realm-server, matrix, and boxel-cli. AMD bench gate passes locally (also confirms magic-string 0.30 transpile output is within the perf tolerance). Co-Authored-By: Claude Opus 4.8 --- packages/boxel-cli/scripts/build-skills.ts | 2 +- packages/boxel-cli/scripts/compute-release.ts | 4 ++-- packages/boxel-cli/scripts/generate-release-notes.ts | 2 +- packages/host/config/environment.js | 9 +++++++-- .../register-github-webhook-for-submission-realm.ts | 2 +- packages/matrix/scripts/register-realm-user-using-api.ts | 2 +- packages/realm-server/scripts/bench-realm/bench.ts | 2 +- packages/realm-server/scripts/sync-openrouter-models.ts | 2 +- packages/runtime-common/scripts/bench-amd/bench.ts | 2 +- 9 files changed, 16 insertions(+), 11 deletions(-) diff --git a/packages/boxel-cli/scripts/build-skills.ts b/packages/boxel-cli/scripts/build-skills.ts index fd5aaafb88..60bdcfc52b 100644 --- a/packages/boxel-cli/scripts/build-skills.ts +++ b/packages/boxel-cli/scripts/build-skills.ts @@ -554,7 +554,7 @@ async function main(): Promise { } // Run main only when invoked directly, not when imported from tests. -if (require.main === module) { +if (import.meta.main) { main().catch((err) => { console.error(err); process.exit(1); diff --git a/packages/boxel-cli/scripts/compute-release.ts b/packages/boxel-cli/scripts/compute-release.ts index 10f4338bd0..7196354338 100644 --- a/packages/boxel-cli/scripts/compute-release.ts +++ b/packages/boxel-cli/scripts/compute-release.ts @@ -319,7 +319,7 @@ function main(): void { } // CJS guard: only run main() when invoked as a script, not when imported -// by the vitest test file. `require.main === module` is the standard idiom. -if (require.main === module) { +// by the vitest test file. `import.meta.main` is the standard idiom. +if (import.meta.main) { main(); } diff --git a/packages/boxel-cli/scripts/generate-release-notes.ts b/packages/boxel-cli/scripts/generate-release-notes.ts index 366f9d05af..dac7132c12 100644 --- a/packages/boxel-cli/scripts/generate-release-notes.ts +++ b/packages/boxel-cli/scripts/generate-release-notes.ts @@ -261,6 +261,6 @@ function main(): void { ); } -if (require.main === module) { +if (import.meta.main) { main(); } diff --git a/packages/host/config/environment.js b/packages/host/config/environment.js index f116695c89..654fdc14d6 100644 --- a/packages/host/config/environment.js +++ b/packages/host/config/environment.js @@ -241,13 +241,18 @@ function getLatestSchemaFile() { path.join(__dirname, '..', '..', 'postgres', 'migrations'), ); let migrations = fs.readdirSync(migrationsDir); + // Only timestamped migration files — ignores non-migration entries in the dir + // such as `package.json` (pins the dir to type:commonjs) and `.eslintrc.js`. let lastMigration = migrations - .filter((f) => f !== '.eslintrc.js') + .filter((f) => /^\d+_/.test(f)) .sort() .pop(); const schemaDir = path.join(__dirname, 'schema'); let files = fs.readdirSync(schemaDir); - let latestSchemaFile = files.sort().pop(); + let latestSchemaFile = files + .filter((f) => /^\d+_schema\.sql$/.test(f)) + .sort() + .pop(); if ( lastMigration.replace(/_.*/, '') !== latestSchemaFile.replace(/_.*/, '') && ['development', 'test'].includes(process.env.EMBER_ENV) diff --git a/packages/matrix/scripts/register-github-webhook-for-submission-realm.ts b/packages/matrix/scripts/register-github-webhook-for-submission-realm.ts index 736e64a981..036071f875 100755 --- a/packages/matrix/scripts/register-github-webhook-for-submission-realm.ts +++ b/packages/matrix/scripts/register-github-webhook-for-submission-realm.ts @@ -274,7 +274,7 @@ async function main() { console.log('='.repeat(70)); } -if (require.main === module) { +if (import.meta.main) { main() .then(() => { console.log('✓ GitHub webhook registration complete'); diff --git a/packages/matrix/scripts/register-realm-user-using-api.ts b/packages/matrix/scripts/register-realm-user-using-api.ts index ed5abc0090..d629842f4b 100644 --- a/packages/matrix/scripts/register-realm-user-using-api.ts +++ b/packages/matrix/scripts/register-realm-user-using-api.ts @@ -123,7 +123,7 @@ export async function registerRealmUser(): Promise<{ return { jwt, userId }; } -if (require.main === module) { +if (import.meta.main) { registerRealmUser() .then(({ userId }) => { console.log(`Registered realm user ${userId}`); diff --git a/packages/realm-server/scripts/bench-realm/bench.ts b/packages/realm-server/scripts/bench-realm/bench.ts index 9ddf9e83b6..072b2086da 100644 --- a/packages/realm-server/scripts/bench-realm/bench.ts +++ b/packages/realm-server/scripts/bench-realm/bench.ts @@ -362,7 +362,7 @@ async function main(): Promise { } } -if (require.main === module) { +if (import.meta.main) { main().catch((err) => { console.error(err); process.exit(1); diff --git a/packages/realm-server/scripts/sync-openrouter-models.ts b/packages/realm-server/scripts/sync-openrouter-models.ts index 506b916a31..5acb7a6f3e 100644 --- a/packages/realm-server/scripts/sync-openrouter-models.ts +++ b/packages/realm-server/scripts/sync-openrouter-models.ts @@ -30,7 +30,7 @@ async function main() { } // When run directly as a script -if (require.main === module) { +if (import.meta.main) { main().catch((err) => { console.error(err); process.exit(1); diff --git a/packages/runtime-common/scripts/bench-amd/bench.ts b/packages/runtime-common/scripts/bench-amd/bench.ts index 8946f73b58..0259392a8c 100644 --- a/packages/runtime-common/scripts/bench-amd/bench.ts +++ b/packages/runtime-common/scripts/bench-amd/bench.ts @@ -229,7 +229,7 @@ async function main() { } } -if (require.main === module) { +if (import.meta.main) { main().catch((err) => { console.error(err); process.exit(1); From bc695d6cb66109baaa82e07bd3808b765b0f81b0 Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Wed, 17 Jun 2026 16:51:38 -0400 Subject: [PATCH 18/38] fix: ESM-ify boxel-cli build scripts and fix ignore re-export for esbuild MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit boxel-cli is a published CJS package (esbuild emits format:cjs), but the ts-node->node conversion of its dev/build scripts made node run them as ESM (import syntax + type:unset), so their `__dirname`/`require.main` broke: - Convert the build scripts (build.ts, build-types.ts, build-test-harness.ts, build-realms.ts, build-skills.ts, build-plugin.ts) to import.meta.dirname / import.meta.main. Leave src/ on __dirname — esbuild bundles it to CJS, where __dirname is correct and import.meta would be empty. - tsconfig -> module:esnext + moduleResolution:bundler so the now-ESM scripts' import.meta type-checks (the package stays CJS-published; tsconfig only drives lint:types, esbuild owns the build). - `start` now runs the built dist (node dist/index.js) since src is no longer directly node-runnable as ESM. Also fix runtime-common/ignore.ts to import the `ignore` CJS package via a namespace (`.default ?? ns`) instead of a default import: esbuild bundling downstream consumers (vscode-boxel-tools) couldn't synthesize the default. Co-Authored-By: Claude Opus 4.8 --- packages/boxel-cli/package.json | 2 +- packages/boxel-cli/scripts/build-plugin.ts | 2 +- packages/boxel-cli/scripts/build-realms.ts | 2 +- packages/boxel-cli/scripts/build-skills.ts | 11 +++++++---- packages/boxel-cli/scripts/build-test-harness.ts | 2 +- packages/boxel-cli/scripts/build-types.ts | 2 +- packages/boxel-cli/scripts/build.ts | 6 +++--- packages/boxel-cli/tsconfig.json | 4 ++-- packages/runtime-common/ignore.ts | 15 +++++++++------ 9 files changed, 26 insertions(+), 20 deletions(-) diff --git a/packages/boxel-cli/package.json b/packages/boxel-cli/package.json index f7142394a0..dd32681161 100644 --- a/packages/boxel-cli/package.json +++ b/packages/boxel-cli/package.json @@ -80,7 +80,7 @@ "build:test-harness": "NODE_NO_WARNINGS=1 node scripts/build-test-harness.ts", "build:types": "NODE_NO_WARNINGS=1 node scripts/build-types.ts", "clean": "rm -rf dist/* bundled-types bundled-test-harness bundled-realms", - "start": "NODE_NO_WARNINGS=1 node src/index.ts", + "start": "NODE_NO_WARNINGS=1 node dist/index.js", "lint": "concurrently \"pnpm:lint:*(!fix)\" --names \"lint:\"", "lint:fix": "concurrently \"pnpm:lint:*:fix\" --names \"fix:\"", "lint:js": "eslint . --report-unused-disable-directives --cache", diff --git a/packages/boxel-cli/scripts/build-plugin.ts b/packages/boxel-cli/scripts/build-plugin.ts index e9f745f3cd..80637f113f 100644 --- a/packages/boxel-cli/scripts/build-plugin.ts +++ b/packages/boxel-cli/scripts/build-plugin.ts @@ -12,7 +12,7 @@ import { readFileSync, writeFileSync } from 'fs'; import { resolve } from 'path'; import { buildBoxelProgram } from '../src/build-program.ts'; -const PLUGIN_DIR = resolve(__dirname, '..', 'plugin'); +const PLUGIN_DIR = resolve(import.meta.dirname, '..', 'plugin'); interface SkillSpec { /** Skill folder name under plugin/skills/ */ diff --git a/packages/boxel-cli/scripts/build-realms.ts b/packages/boxel-cli/scripts/build-realms.ts index d4c1d158f6..0fcdbe6a8a 100644 --- a/packages/boxel-cli/scripts/build-realms.ts +++ b/packages/boxel-cli/scripts/build-realms.ts @@ -22,7 +22,7 @@ import { cpSync, mkdirSync, readdirSync, rmSync, statSync } from 'node:fs'; import { basename, join, resolve } from 'node:path'; -const PACKAGE_ROOT = resolve(__dirname, '..'); +const PACKAGE_ROOT = resolve(import.meta.dirname, '..'); const MONOREPO_PACKAGES = resolve(PACKAGE_ROOT, '..'); const OUT_DIR = join(PACKAGE_ROOT, 'bundled-realms'); diff --git a/packages/boxel-cli/scripts/build-skills.ts b/packages/boxel-cli/scripts/build-skills.ts index 60bdcfc52b..a8ac7d5fc1 100644 --- a/packages/boxel-cli/scripts/build-skills.ts +++ b/packages/boxel-cli/scripts/build-skills.ts @@ -38,10 +38,13 @@ import { format, resolveConfig } from 'prettier'; const BOXEL_SKILLS_VERSION = 'v0.0.22'; const BOXEL_SKILLS_REPO_URL = 'https://github.com/cardstack/boxel-skills.git'; -const PLUGIN_DIR = resolve(__dirname, '..', 'plugin'); +const PLUGIN_DIR = resolve(import.meta.dirname, '..', 'plugin'); const PLUGIN_README_PATH = resolve(PLUGIN_DIR, 'README.md'); -const CACHE_DIR = resolve(__dirname, '..', '.boxel-skills-cache'); -const MANIFEST_PATH = resolve(__dirname, '.boxel-skills-manifest.json'); +const CACHE_DIR = resolve(import.meta.dirname, '..', '.boxel-skills-cache'); +const MANIFEST_PATH = resolve( + import.meta.dirname, + '.boxel-skills-manifest.json', +); const README_BEGIN_MARKER = ''; @@ -459,7 +462,7 @@ function writeManifest(plan: EmissionPlan): void { }; writeFileSync(MANIFEST_PATH, JSON.stringify(manifest, null, 2) + '\n'); console.log( - `wrote ${relative(resolve(__dirname, '..'), MANIFEST_PATH)} (${manifest.skills.length} skills)`, + `wrote ${relative(resolve(import.meta.dirname, '..'), MANIFEST_PATH)} (${manifest.skills.length} skills)`, ); } diff --git a/packages/boxel-cli/scripts/build-test-harness.ts b/packages/boxel-cli/scripts/build-test-harness.ts index 3ffdb66bc8..e4b85af71e 100644 --- a/packages/boxel-cli/scripts/build-test-harness.ts +++ b/packages/boxel-cli/scripts/build-test-harness.ts @@ -21,7 +21,7 @@ import { cpSync, mkdirSync, readdirSync, rmSync, statSync } from 'node:fs'; import { basename, join, resolve } from 'node:path'; -const PACKAGE_ROOT = resolve(__dirname, '..'); +const PACKAGE_ROOT = resolve(import.meta.dirname, '..'); const MONOREPO_PACKAGES = resolve(PACKAGE_ROOT, '..'); const HOST_DIST = join(MONOREPO_PACKAGES, 'host', 'dist'); diff --git a/packages/boxel-cli/scripts/build-types.ts b/packages/boxel-cli/scripts/build-types.ts index 485ce86d1c..d08a36c243 100644 --- a/packages/boxel-cli/scripts/build-types.ts +++ b/packages/boxel-cli/scripts/build-types.ts @@ -66,7 +66,7 @@ import { dirname, isAbsolute, join, relative, resolve } from 'node:path'; import { Preprocessor } from 'content-tag'; import * as ts from 'typescript'; -const PACKAGE_ROOT = resolve(__dirname, '..'); +const PACKAGE_ROOT = resolve(import.meta.dirname, '..'); const MONOREPO_PACKAGES = resolve(PACKAGE_ROOT, '..'); // --------------------------------------------------------------------------- diff --git a/packages/boxel-cli/scripts/build.ts b/packages/boxel-cli/scripts/build.ts index 9f951dff2c..a7dc1d3bf3 100644 --- a/packages/boxel-cli/scripts/build.ts +++ b/packages/boxel-cli/scripts/build.ts @@ -58,13 +58,13 @@ async function buildCLI() { chmodSync('dist/index.js', 0o755); // content-tag (pulled in via runtime-common's transpile pipeline) - // loads its wasm with `readFileSync(`${__dirname}/content_tag_bg.wasm`)` + // loads its wasm with `readFileSync(`${import.meta.dirname}/content_tag_bg.wasm`)` // from `pkg/node/`. After esbuild bundles content-tag into - // `dist/index.js`, `__dirname` becomes the boxel-cli dist/ dir, + // `dist/index.js`, `import.meta.dirname` becomes the boxel-cli dist/ dir, // so the wasm has to live next to index.js — otherwise `boxel test` // hits ENOENT on the first transpile. let wasmSrc = join( - __dirname, + import.meta.dirname, '..', 'node_modules', 'content-tag', diff --git a/packages/boxel-cli/tsconfig.json b/packages/boxel-cli/tsconfig.json index 05d3f8476d..c7b3e458f7 100644 --- a/packages/boxel-cli/tsconfig.json +++ b/packages/boxel-cli/tsconfig.json @@ -1,8 +1,8 @@ { "compilerOptions": { "target": "es2022", - "module": "nodenext", - "moduleResolution": "nodenext", + "module": "esnext", + "moduleResolution": "bundler", "allowImportingTsExtensions": true, "strict": true, "noEmit": true, diff --git a/packages/runtime-common/ignore.ts b/packages/runtime-common/ignore.ts index 5a3964c5b9..34ea84df19 100644 --- a/packages/runtime-common/ignore.ts +++ b/packages/runtime-common/ignore.ts @@ -1,8 +1,11 @@ -// `ignore` ships no `types`/`exports` fields, so under nodenext ESM-mode -// TypeScript types its default export as a non-callable namespace even though -// the runtime default IS the factory function (verified under native node). -// Re-export it once with the correct call signature so call sites stay clean. -import ignoreImport, { type Ignore } from 'ignore'; +// `ignore` ships no `types`/`exports` fields, so its default export resolves +// inconsistently across toolchains: nodenext types it as a non-callable +// namespace, and esbuild (bundling downstream consumers) won't synthesize a +// default at all. Import the namespace and read the CJS default off it — that's +// the callable factory under native Node, esbuild, and Vite alike. +import type { Ignore } from 'ignore'; +import * as ignoreNamespace from 'ignore'; -export const ignore = ignoreImport as unknown as (options?: object) => Ignore; +export const ignore = ((ignoreNamespace as { default?: unknown }).default ?? + ignoreNamespace) as unknown as (options?: object) => Ignore; export type { Ignore }; From cfb4909a943da1bbbd085f3bdffe90a87b31e0d7 Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Wed, 17 Jun 2026 17:31:09 -0400 Subject: [PATCH 19/38] fix: stray .ts on MATRIX_REGISTRATION_SHARED_SECRET broke realm-server boot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ts-node->node codemod's entry capture grabbed the closing `)` of a `$(ts-node … secret)` command substitution and appended `.ts` after it: MATRIX_REGISTRATION_SHARED_SECRET=$(node "…/matrix-registration-secret.ts").ts so the secret value was suffixed with a literal `.ts`. The realm-server then failed to come up, never bound :4201, and every integration suite that needs the dev-services stack (Host / Realm-Server / Matrix / Live Tests and downstream) cascaded. Verified locally: with the secret restored, the realm-server starts under native node and serves :4201 (base/skills modules + indexing). Fix the three mise service tasks (realm-server, test-realms, realm-server-base) and harden the codemod's entry pattern to exclude shell metacharacters ( ) ; & | ) so a command substitution can't be mis-captured again. Co-Authored-By: Claude Opus 4.8 --- mise-tasks/services/realm-server | 2 +- mise-tasks/services/realm-server-base | 2 +- mise-tasks/services/test-realms | 2 +- scripts/esm-codemod/ts-node-to-node.mjs | 5 ++++- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/mise-tasks/services/realm-server b/mise-tasks/services/realm-server index f499ddab53..e56f3fd1e3 100755 --- a/mise-tasks/services/realm-server +++ b/mise-tasks/services/realm-server @@ -44,7 +44,7 @@ if [ "${SKIP_CATALOG:-}" != "true" ]; then fi if [ -z "$MATRIX_REGISTRATION_SHARED_SECRET" ]; then - MATRIX_REGISTRATION_SHARED_SECRET=$(node "$SCRIPTS_DIR/matrix-registration-secret.ts").ts + MATRIX_REGISTRATION_SHARED_SECRET=$(node "$SCRIPTS_DIR/matrix-registration-secret.ts") export MATRIX_REGISTRATION_SHARED_SECRET fi diff --git a/mise-tasks/services/realm-server-base b/mise-tasks/services/realm-server-base index a8b7887584..2b34b382cd 100755 --- a/mise-tasks/services/realm-server-base +++ b/mise-tasks/services/realm-server-base @@ -9,7 +9,7 @@ trap 'exit 0' INT TERM if [ -z "$MATRIX_REGISTRATION_SHARED_SECRET" ]; then - MATRIX_REGISTRATION_SHARED_SECRET=$(node ./scripts/matrix-registration-secret.ts).ts + MATRIX_REGISTRATION_SHARED_SECRET=$(node ./scripts/matrix-registration-secret.ts) export MATRIX_REGISTRATION_SHARED_SECRET fi diff --git a/mise-tasks/services/test-realms b/mise-tasks/services/test-realms index 7c40151823..2000a46f83 100755 --- a/mise-tasks/services/test-realms +++ b/mise-tasks/services/test-realms @@ -55,7 +55,7 @@ fi pnpm --dir=../skills-realm skills:setup if [ -z "$MATRIX_REGISTRATION_SHARED_SECRET" ]; then - MATRIX_REGISTRATION_SHARED_SECRET=$(node "$SCRIPTS_DIR/matrix-registration-secret.ts").ts + MATRIX_REGISTRATION_SHARED_SECRET=$(node "$SCRIPTS_DIR/matrix-registration-secret.ts") export MATRIX_REGISTRATION_SHARED_SECRET fi diff --git a/scripts/esm-codemod/ts-node-to-node.mjs b/scripts/esm-codemod/ts-node-to-node.mjs index 31b51269d1..eb88b15275 100644 --- a/scripts/esm-codemod/ts-node-to-node.mjs +++ b/scripts/esm-codemod/ts-node-to-node.mjs @@ -22,7 +22,10 @@ const KNOWN_EXT = /\.(ts|mts|cts|js|mjs|cjs)$/; // `ts-node --transpileOnly ` (entry = next non-flag token). The // separator class allows shell line-continuations (`\` + newline + indent), // so multi-line `exec ts-node \\\n --transpileOnly main \\` forms convert too. -const INVOCATION = /\bts-node[\s\\]+--transpileOnly[\s\\]+([^\s"'\\]+)/g; +// The entry class excludes shell metacharacters `)`, `;`, `&`, `|` as well as +// quotes so a `$(ts-node … entry)` command substitution doesn't capture the +// closing `)` and get a `.ts` appended after it. +const INVOCATION = /\bts-node[\s\\]+--transpileOnly[\s\\]+([^\s"'\\);&|]+)/g; export function transform(src) { const skipped = []; From 96bcd38cc438809fd1ff98d30c2321acae56ed51 Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Wed, 17 Jun 2026 18:02:37 -0400 Subject: [PATCH 20/38] fix: ESM interop breaking the worker, synapse, and JWT auth MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three native-ESM gaps the CI integration stack surfaced, each cascading widely: - handlers/handle-indexing-dashboard.ts used `require.resolve('morphdom/…')` at module load. `require.resolve` (no `require(` token, no `require.main`) slipped past the earlier sweeps; it threw `require is not defined` and crashed the worker-manager on import -> no indexing -> realm-server never reached :4201 readiness. Resolve via createRequire. - matrix synapse start (support/synapse/index.ts, support/docker.ts) and realm-server utils/jwt.ts imported CJS packages as `import * as fse/jsonwebtoken` and then read members off the namespace. Under native ESM those members live on the CJS default, so `fse.stat`/`sign`/`verify` were `undefined` — synapse failed to start (`fse.stat is not a function`) and JWT signing/verification would no-op. Switch to default imports. Verified each member resolves under native node; matrix and realm-server type-check clean. Co-Authored-By: Claude Opus 4.8 --- packages/matrix/support/docker.ts | 2 +- packages/matrix/support/synapse/index.ts | 2 +- packages/realm-server/handlers/handle-indexing-dashboard.ts | 5 +++++ packages/realm-server/utils/jwt.ts | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/matrix/support/docker.ts b/packages/matrix/support/docker.ts index c3b832a9c1..4691e1a538 100644 --- a/packages/matrix/support/docker.ts +++ b/packages/matrix/support/docker.ts @@ -1,6 +1,6 @@ import * as os from 'os'; import * as childProcess from 'child_process'; -import * as fse from 'fs-extra'; +import fse from 'fs-extra'; function imageExistsLocally(image: string): Promise { return new Promise((resolve) => { diff --git a/packages/matrix/support/synapse/index.ts b/packages/matrix/support/synapse/index.ts index a770645318..48755ebf20 100644 --- a/packages/matrix/support/synapse/index.ts +++ b/packages/matrix/support/synapse/index.ts @@ -2,7 +2,7 @@ import * as path from 'path'; import * as os from 'os'; import * as crypto from 'crypto'; import * as net from 'net'; -import * as fse from 'fs-extra'; +import fse from 'fs-extra'; import { request } from '@playwright/test'; import { dockerCreateNetwork, diff --git a/packages/realm-server/handlers/handle-indexing-dashboard.ts b/packages/realm-server/handlers/handle-indexing-dashboard.ts index 0391f8e93f..a4d7d9f2cb 100644 --- a/packages/realm-server/handlers/handle-indexing-dashboard.ts +++ b/packages/realm-server/handlers/handle-indexing-dashboard.ts @@ -1,7 +1,12 @@ import { readFileSync } from 'node:fs'; +import { createRequire } from 'node:module'; import type { RealmIndexingState } from '../indexing-event-sink.ts'; +// `require` doesn't exist in ESM scope; recreate it to resolve the bundled +// morphdom asset path. +const require = createRequire(import.meta.url); + // morphdom's UMD build, inlined into the dashboard so the auto-refresh can // patch the live DOM in place instead of reloading the page. Read once at // module load; the dashboard is a local-only debug surface. diff --git a/packages/realm-server/utils/jwt.ts b/packages/realm-server/utils/jwt.ts index 64716c094a..99c07b5036 100644 --- a/packages/realm-server/utils/jwt.ts +++ b/packages/realm-server/utils/jwt.ts @@ -2,7 +2,7 @@ import { AuthenticationError, AuthenticationErrorMessages, } from '@cardstack/runtime-common/router'; -import * as jsonwebtoken from 'jsonwebtoken'; +import jsonwebtoken from 'jsonwebtoken'; const { JsonWebTokenError, sign, TokenExpiredError, verify } = jsonwebtoken; export interface RealmServerTokenClaim { From 10b68b7e5963eee69665c1c8b7f7ecdc490637c0 Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Wed, 17 Jun 2026 22:54:36 -0400 Subject: [PATCH 21/38] fix: register lodash shim under lodash-es id after ESM migration The ESM migration switched realm-served code to import from lodash-es, but the VirtualNetwork shim was still registered under the old 'lodash' id. Card code importing lodash-es found no shim and fell through to a network fetch (https://packages/lodash-es), failing every prerender render and wedging the base realm readiness check. Update the shim id to lodash-es and the matching expected-dependency lists in the realm indexing test. Co-Authored-By: Claude Opus 4.8 --- packages/host/app/lib/externals.ts | 2 +- packages/host/tests/integration/realm-indexing-test.gts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/host/app/lib/externals.ts b/packages/host/app/lib/externals.ts index cf0a56a432..993d77e8f0 100644 --- a/packages/host/app/lib/externals.ts +++ b/packages/host/app/lib/externals.ts @@ -180,7 +180,7 @@ export function shimExternals(virtualNetwork: VirtualNetwork) { }); virtualNetwork.shimModule('flat', flat); virtualNetwork.shimModule('@floating-ui/dom', floatingUiDom); - virtualNetwork.shimModule('lodash', lodash); + virtualNetwork.shimModule('lodash-es', lodash); virtualNetwork.shimModule('matrix-js-sdk', matrixJsSDK); virtualNetwork.shimModule('rsvp', rsvp); virtualNetwork.shimModule('super-fast-md5', superFastMD5); diff --git a/packages/host/tests/integration/realm-indexing-test.gts b/packages/host/tests/integration/realm-indexing-test.gts index 7a5f7642df..2e1b861ebd 100644 --- a/packages/host/tests/integration/realm-indexing-test.gts +++ b/packages/host/tests/integration/realm-indexing-test.gts @@ -4795,7 +4795,7 @@ module(`Integration | realm indexing`, function (hooks) { 'https://packages/ember-css-url', 'https://packages/ember-modifier', 'https://packages/ember-provide-consume-context', - 'https://packages/lodash', + 'https://packages/lodash-es', 'https://packages/super-fast-md5', 'https://packages/tracked-built-ins', // Sort the expected list so the assertion is robust against @@ -4968,7 +4968,7 @@ module(`Integration | realm indexing`, function (hooks) { 'https://packages/ember-modifier', 'https://packages/ember-provide-consume-context', 'https://packages/ember-resources', - 'https://packages/lodash', + 'https://packages/lodash-es', 'https://packages/super-fast-md5', 'https://packages/tracked-built-ins', // See note on iconsBase ordering above. From 6dc5148f60fc0c65789feec2e6f5cfd2b9eefec1 Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Thu, 18 Jun 2026 09:57:55 -0400 Subject: [PATCH 22/38] fix: ignore package.json in migrate CLI script after ESM migration The migrations dir now carries a package.json pinning it to type:commonjs (so the CJS migration files keep working under the package's new type:module). node-pg-migrate's CLI default ignore pattern only skips dotfiles, so `pnpm migrate` loaded that package.json as a migration named "package" with no up/down function and threw "Unknown value for direction: up". Pass the same --ignore-pattern the programmatic runner in pg-adapter.ts already uses, so the CLI path (DB setup, CI migrate steps) skips package.json and .eslintrc.js too. Co-Authored-By: Claude Opus 4.8 --- packages/postgres/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/postgres/package.json b/packages/postgres/package.json index a43832a3ed..d27148be11 100644 --- a/packages/postgres/package.json +++ b/packages/postgres/package.json @@ -26,7 +26,7 @@ "scripts": { "start:pg": "./scripts/start-pg.sh", "stop:pg": "./scripts/stop-pg.sh", - "migrate": "PGDATABASE=boxel ./scripts/ensure-db-exists.sh && PGPORT=5435 PGDATABASE=boxel PGUSER=postgres node ./scripts/fix-migration-names.ts && PGPORT=5435 PGDATABASE=boxel PGUSER=postgres node-pg-migrate --migrations-table migrations --no-check-order --verbose=false", + "migrate": "PGDATABASE=boxel ./scripts/ensure-db-exists.sh && PGPORT=5435 PGDATABASE=boxel PGUSER=postgres node ./scripts/fix-migration-names.ts && PGPORT=5435 PGDATABASE=boxel PGUSER=postgres node-pg-migrate --migrations-table migrations --no-check-order --ignore-pattern '.*\\.eslintrc\\.js|package\\.json' --verbose=false", "make-schema": "./scripts/schema-dump.sh", "drop-db": "docker exec boxel-pg dropdb --if-exists -U postgres -w", "lint": "concurrently \"pnpm:lint:*(!fix)\" --names \"lint:\"", From 829dc562986b5f4fdb2698ef0788989e2c409b25 Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Thu, 18 Jun 2026 13:27:55 -0400 Subject: [PATCH 23/38] fix: ignore package.json in test-pg seed migrate after ESM migration The migrations dir carries a package.json pinning it to type:commonjs (so the CJS migration files keep working under the package's new type:module). node-pg-migrate's CLI default ignore pattern only skips dotfiles, so the test-pg seed builder loaded that package.json as a migration named "package" with no up/down function and threw "Unknown value for direction: up", failing realm-server DB setup in CI. 4ae93124 fixed the `pnpm migrate` package.json script the same way, but the create_seeded_db.sh seed builder has its own inlined node-pg-migrate invocation that was missed. Pass the same --ignore-pattern so the seed path skips package.json and .eslintrc.js too. Co-Authored-By: Claude Opus 4.8 --- packages/realm-server/tests/scripts/create_seeded_db.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/realm-server/tests/scripts/create_seeded_db.sh b/packages/realm-server/tests/scripts/create_seeded_db.sh index fa72e80580..fd1cf7d25e 100755 --- a/packages/realm-server/tests/scripts/create_seeded_db.sh +++ b/packages/realm-server/tests/scripts/create_seeded_db.sh @@ -38,6 +38,7 @@ docker exec "$TEST_PG_SEED_CONTAINER" psql -U postgres -d postgres -v ON_ERROR_S pnpm exec node-pg-migrate \ --migrations-table migrations \ --check-order false \ + --ignore-pattern '.*\.eslintrc\.js|package\.json' \ --no-verbose \ up ) From b1fdea5c6ba6f0f7b1d1220b7a4536639de2f587 Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Thu, 18 Jun 2026 13:36:20 -0400 Subject: [PATCH 24/38] fix: default-import qunit in codeEqual helper for native ESM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `import * as QUnit from 'qunit'` yields an ESM namespace whose `.assert` is undefined under native Node ESM (qunit is CJS; the real object is the default export). ts-node's esModuleInterop previously masked this. The helper's `QUnit.assert.codeEqual = codeEqual` then threw "Cannot set properties of undefined (setting 'codeEqual')" at import time, aborting the entire realm-server test suite. Switch to the default import (`import QUnit from 'qunit'`) — the form every realm-server test file already uses — so `.assert` resolves. Co-Authored-By: Claude Opus 4.8 --- packages/runtime-common/helpers/code-equality-assertion.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/runtime-common/helpers/code-equality-assertion.ts b/packages/runtime-common/helpers/code-equality-assertion.ts index c09cf99074..0d9df2acbc 100644 --- a/packages/runtime-common/helpers/code-equality-assertion.ts +++ b/packages/runtime-common/helpers/code-equality-assertion.ts @@ -10,7 +10,7 @@ import classPropertiesPlugin from '@babel/plugin-syntax-class-properties'; //@ts-ignore unsure where these types live import typescriptPlugin from '@babel/plugin-syntax-typescript'; -import * as QUnit from 'qunit'; +import QUnit from 'qunit'; import { gjsToPlaceholderJS } from '../module-syntax.ts'; declare global { From bead579c313f7f9bb457dd146c79f56b536217ac Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Thu, 18 Jun 2026 14:04:15 -0400 Subject: [PATCH 25/38] fix: avoid named qunit imports in realm-endpoints-test for native ESM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `import QUnit, { module, test } from 'qunit'` fails under native Node ESM with "The requested module 'qunit' does not provide an export named 'module'" — qunit is CJS and exposes module/test as properties of the default export, not as ESM named exports. Because tests/index.ts requires every test file at load time (TEST_MODULES only filters which run), this one file aborted all six realm-server shards. Destructure module/test from the default import, matching the 142 other realm-server test files that already use `import QUnit from 'qunit'`. Co-Authored-By: Claude Opus 4.8 --- packages/realm-server/tests/realm-endpoints-test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/realm-server/tests/realm-endpoints-test.ts b/packages/realm-server/tests/realm-endpoints-test.ts index 1fb2618951..225fa6245a 100644 --- a/packages/realm-server/tests/realm-endpoints-test.ts +++ b/packages/realm-server/tests/realm-endpoints-test.ts @@ -1,4 +1,5 @@ -import QUnit, { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import type { Test, SuperTest } from 'supertest'; import supertest from 'supertest'; import { join, resolve, basename } from 'path'; From 604aa7ae72777b86038a7b82ea030822207996f9 Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Thu, 18 Jun 2026 15:09:44 -0400 Subject: [PATCH 26/38] test: drop ts-node from fake-watcher fixture after ESM migration The realm-watch-stop integration fixture spawned a child that called `require('ts-node').register(...)` to load watch-process-registry.ts from source. ts-node was removed in the ESM migration, so the child threw "Cannot find module 'ts-node'", exited 1, and both realm-watch-stop tests failed with "fake watcher exited early". Node 24 strips TypeScript types natively, so the registry .ts loads via a plain require with no loader. Verified the fixture boots (FAKE_WATCHER_READY, registers, stays alive) and all three tests pass. Co-Authored-By: Claude Opus 4.8 --- .../boxel-cli/tests/fixtures/fake-watcher.cjs | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/packages/boxel-cli/tests/fixtures/fake-watcher.cjs b/packages/boxel-cli/tests/fixtures/fake-watcher.cjs index ae34d323c6..b5c03b14e4 100644 --- a/packages/boxel-cli/tests/fixtures/fake-watcher.cjs +++ b/packages/boxel-cli/tests/fixtures/fake-watcher.cjs @@ -4,16 +4,19 @@ // exiting cleanly — mimicking what a real `realm watch start` does on // shutdown. -require('ts-node').register({ transpileOnly: true }); +// Node (>=22.18 / 24) strips TypeScript types natively, so the registry .ts +// loads via a plain require — no ts-node needed after the ESM migration. const path = require('path'); -const registry = require(path.resolve( - __dirname, - '..', - '..', - 'src', - 'lib', - 'watch-process-registry.ts', -)); +const registry = require( + path.resolve( + __dirname, + '..', + '..', + 'src', + 'lib', + 'watch-process-registry.ts', + ), +); async function main() { const workspace = process.env.WATCHER_WORKSPACE || '/tmp/fake-watcher'; From 4259b6be2c3f482d69bf6051f8444d1ac672ebb7 Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Thu, 18 Jun 2026 15:24:12 -0400 Subject: [PATCH 27/38] chore: remove remaining ts-node usage after ESM migration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ts-node was dropped from every package's deps, but invocations, a broken process-kill pattern, and stale comments/docs lingered. Sweep them: Functional - boxel-cli `bin/boxel.js`: the dev fallback `require('ts-node')` is gone; the CLI ships as a built CJS bundle (source uses CommonJS-only globals like __dirname and isn't native-ESM-runnable), so error clearly when dist is missing instead of throwing "Cannot find module 'ts-node'". - `mise-tasks/lib/dev-common.sh`: the orphan-sweep matched `node_modules.*--transpileOnly (worker|main|prerender)`, which never matches the native `node main.ts` / `node worker-manager.ts` / `node prerender/*-server.ts` processes — so `mise run kill-all` and dev cleanup leaked the realm/worker/prerender ports. Match the native entries (by name + a distinctive flag) instead. - `packages/postgres/Dockerfile`: ts-node → node for fix-migration-names.ts. - `.github/workflows/boxel-cli-publish.yml`: ts-node → node (3 sites). - delete `packages/realm-server/scripts/run-test-modules.cjs` — an unused qunit runner that still bootstrapped ts-node (the suite runs via run-qunit-with-test-pg.sh / `node tests/index.ts`). Docs / comments / log strings - start-*.sh: "about to exec ts-node" log lines now say node; header comments drop the ts-node tsconfig/binary rationale. - mise service comments, worker-manager.ts, opencode.ts, find-package-root.ts, fixtures.ts, context-search + canusetool usage strings, boxel-cli + ai-bot READMEs, and the indexing-diagnostics skill: ts-node → node. Left intentionally: the esm-codemod tooling, accurate "without ts-node" notes, pg-adapter's historical esModuleInterop rationale, and the phase-1-plan historical design doc. Co-Authored-By: Claude Opus 4.8 --- .claude/skills/indexing-diagnostics/SKILL.md | 2 +- .github/workflows/boxel-cli-publish.yml | 6 +- mise-tasks/lib/dev-common.sh | 20 ++++--- mise-tasks/services/realm-server | 4 +- mise-tasks/services/worker | 2 +- packages/ai-bot/README.md | 4 +- packages/boxel-cli/README.md | 2 +- packages/boxel-cli/bin/boxel.js | 13 +++-- .../boxel-cli/src/lib/find-package-root.ts | 6 +- packages/postgres/Dockerfile | 2 +- .../scripts/codemod/context-search/run.ts | 4 +- .../realm-server/scripts/run-test-modules.cjs | 58 ------------------- .../scripts/start-prerender-manager.sh | 8 +-- .../scripts/start-prerender-production.sh | 8 +-- .../scripts/start-prerender-staging.sh | 8 +-- .../realm-server/scripts/start-production.sh | 8 +-- .../realm-server/scripts/start-staging.sh | 8 +-- .../scripts/start-worker-production.sh | 8 +-- .../scripts/start-worker-staging.sh | 8 +-- packages/realm-server/worker-manager.ts | 2 +- .../scripts/canusetool-fix-verify.ts | 2 +- .../scripts/canusetool-repro.ts | 2 +- .../src/factory-agent/opencode.ts | 6 +- packages/software-factory/tests/fixtures.ts | 2 +- 24 files changed, 72 insertions(+), 121 deletions(-) delete mode 100644 packages/realm-server/scripts/run-test-modules.cjs diff --git a/.claude/skills/indexing-diagnostics/SKILL.md b/.claude/skills/indexing-diagnostics/SKILL.md index fbc814da78..1a8b1bd92a 100644 --- a/.claude/skills/indexing-diagnostics/SKILL.md +++ b/.claude/skills/indexing-diagnostics/SKILL.md @@ -1288,7 +1288,7 @@ Path A is faster, doesn't require server config changes, and works against stagi ### Path A — direct token mint (the common case) -The user runs `mise run claude-prerender-token []`. The script (`packages/realm-server/scripts/claude-prerender-token.ts`, executed via `ts-node --transpileOnly` from inside `packages/realm-server`) mints a `boxel-session` JWT the same way the indexer does — same claims, same HS256/1d, same `JSON.stringify({ : })` map shape that lands in `localStorage['boxel-session']`. Faithful CLI port of `buildCreatePrerenderAuth` (`packages/realm-server/prerender/auth.ts`). +The user runs `mise run claude-prerender-token []`. The script (`packages/realm-server/scripts/claude-prerender-token.ts`, executed via `node` from inside `packages/realm-server`) mints a `boxel-session` JWT the same way the indexer does — same claims, same HS256/1d, same `JSON.stringify({ : })` map shape that lands in `localStorage['boxel-session']`. Faithful CLI port of `buildCreatePrerenderAuth` (`packages/realm-server/prerender/auth.ts`). **The CLI is intentionally minimal: just `` and an optional `` positional.** If `` is omitted the script reads from `process.stdin` — interactively that's a masked TTY paste prompt (each char echoes as `*`, paste-friendly, no shell history); piped/redirected stdin is read in full and trimmed. Optional flags: `--user ` (required only for system realms), `--permissions `, `--output `, `--no-output`. That's it. The token is realm-scoped, not card-scoped — Claude builds the `/render` URL itself for whichever card it's investigating. diff --git a/.github/workflows/boxel-cli-publish.yml b/.github/workflows/boxel-cli-publish.yml index 05c5603266..a7165b3982 100644 --- a/.github/workflows/boxel-cli-publish.yml +++ b/.github/workflows/boxel-cli-publish.yml @@ -125,7 +125,7 @@ jobs: PR_BODY: ${{ steps.pr.outputs.body }} run: | set -euo pipefail - RESULT=$(NODE_NO_WARNINGS=1 pnpm exec ts-node --transpileOnly scripts/compute-release.ts) + RESULT=$(NODE_NO_WARNINGS=1 pnpm exec node scripts/compute-release.ts) echo "Compute result: $RESULT" { echo "json<<__REL_EOF__" @@ -205,7 +205,7 @@ jobs: RELEASE_BODY_FILE="$BODY_FILE" \ CHANGELOG_FRAGMENT_FILE="$FRAGMENT_FILE" \ NODE_NO_WARNINGS=1 pnpm --filter @cardstack/boxel-cli exec \ - ts-node --transpileOnly scripts/generate-release-notes.ts + node scripts/generate-release-notes.ts echo "has=true" >> "$GITHUB_OUTPUT" echo "body_file=$BODY_FILE" >> "$GITHUB_OUTPUT" @@ -441,7 +441,7 @@ jobs: RELEASE_BODY_FILE="$BODY_FILE" \ CHANGELOG_FRAGMENT_FILE="$FRAGMENT_FILE" \ NODE_NO_WARNINGS=1 pnpm --filter @cardstack/boxel-cli exec \ - ts-node --transpileOnly scripts/generate-release-notes.ts + node scripts/generate-release-notes.ts FRAG_FILE="$FRAGMENT_FILE" node -e ' const fs = require("fs"); const path = "packages/boxel-cli/CHANGELOG.md"; diff --git a/mise-tasks/lib/dev-common.sh b/mise-tasks/lib/dev-common.sh index 2ebe8c7da9..25af829d90 100644 --- a/mise-tasks/lib/dev-common.sh +++ b/mise-tasks/lib/dev-common.sh @@ -230,7 +230,7 @@ _kill_tree_walk() { # Sweep orphaned dev-stack processes scoped to this checkout. mise's task # supervisor reparents long-running task scripts to init, and the wrapper -# layers above ts-node (pnpm, npm exec, run-p, vite, start-server-and-test) +# layers above the node entrypoints (pnpm, npm exec, run-p, vite, start-server-and-test) # routinely exit without relaying SIGTERM to their grandchildren — so a # tree-walk from a known pid can't reach all of them via PPID. SIGTERM first # for anything that listens, brief grace, then SIGKILL. @@ -245,11 +245,15 @@ _kill_tree_walk() { # # The patterns: # - mise-tasks/services/* — the bash service entrypoints -# - node_modules.*--transpileOnly (worker|main|prerender) — ts-node -# grandchildren that actually hold the realm/worker/prerender ports -# (4201/4202, 4210/4211, 4221/4222). Wrappers that just invoke ts-node -# don't `exec` it, so killing the wrapper alone leaves the ts-node -# grandchild reparented to init with its port still bound. +# - node .ts (main / worker-manager / prerender/*-server) — the +# native-Node grandchildren that actually hold the realm/worker/prerender +# ports (4201/4202, 4210/4211, 4221/4222). They run with +# cwd=packages/realm-server and relative argv, so $REPO_ROOT can't anchor +# the match; the entry names plus a distinctive flag keep it +# Boxel-specific, and the early-return guard above prevents +# sibling-checkout collisions. Wrappers that just invoke node don't +# `exec` it, so killing the wrapper alone leaves the node grandchild +# reparented to init with its port still bound. # - scripts/vite-serve.js — the host start wrapper that spawns the # actual vite child. Can't anchor to $REPO_ROOT because pnpm invokes # it as `node scripts/vite-serve.js` (relative argv, cwd-relative), @@ -287,7 +291,7 @@ sweep_orphaned_services() { return 0 fi REPO_ROOT_RE="$(printf '%s' "$REPO_ROOT" | sed -E 's/[][\\.*^$+?(){}|]/\\&/g')" - TSNODE_RE="${REPO_ROOT_RE}/packages/realm-server/node_modules.*--transpileOnly (worker|main|prerender)" + REALM_NODE_RE="(main\.ts .*--realmsRootPath|worker-manager\.ts .*--allPriorityCount|prerender/(prerender|manager)-server\.ts)" VITE_SERVE_RE="scripts/vite-serve\.js" VITE_BIN_RE="${REPO_ROOT_RE}/packages/host/.*vite/bin/vite\.js" SAT_RE="${REPO_ROOT_RE}/.*node_modules/.*start-server-and-test/src/bin/start\.js" @@ -296,7 +300,7 @@ sweep_orphaned_services() { for sig in TERM KILL; do pkill -"$sig" -f "${REPO_ROOT_RE}/mise-tasks/services/" 2>/dev/null || true - pkill -"$sig" -f "$TSNODE_RE" 2>/dev/null || true + pkill -"$sig" -f "$REALM_NODE_RE" 2>/dev/null || true pkill -"$sig" -f "$VITE_SERVE_RE" 2>/dev/null || true pkill -"$sig" -f "$VITE_BIN_RE" 2>/dev/null || true pkill -"$sig" -f "$SAT_RE" 2>/dev/null || true diff --git a/mise-tasks/services/realm-server b/mise-tasks/services/realm-server index e56f3fd1e3..61ca190697 100755 --- a/mise-tasks/services/realm-server +++ b/mise-tasks/services/realm-server @@ -23,9 +23,9 @@ cleanup_icons_server() { fi } # EXIT runs cleanup unconditionally. INT/TERM additionally exit 0 so that the -# 143-on-Ctrl-C from the ts-node pipeline below isn't reported by mise / +# 143-on-Ctrl-C from the node pipeline below isn't reported by mise / # run-p as "task failed" — see mise-tasks/services/worker for the broader -# rationale. Real crashes still propagate (ts-node faulting on its own +# rationale. Real crashes still propagate (node faulting on its own # leaves the trap unfired, so pipefail's 143-aware exit code wins). # The signal handler clears the EXIT trap before exiting so cleanup doesn't # run twice in succession. diff --git a/mise-tasks/services/worker b/mise-tasks/services/worker index ee1fab8a25..e364c4de11 100755 --- a/mise-tasks/services/worker +++ b/mise-tasks/services/worker @@ -13,7 +13,7 @@ set -o pipefail # SIGTERM this script during Ctrl-C; without this trap the pipefail-aware # pipe below exits 143, mise reports it as "task failed", and run-p prints # `ERROR: "start:worker-development" exited with 143` — pure shutdown -# noise. Real crashes (ts-node faulting on its own) still propagate, since +# noise. Real crashes (node faulting on its own) still propagate, since # the trap only fires when *we* receive the signal. trap 'exit 0' INT TERM diff --git a/packages/ai-bot/README.md b/packages/ai-bot/README.md index c4dda479b2..9d2b582596 100644 --- a/packages/ai-bot/README.md +++ b/packages/ai-bot/README.md @@ -37,8 +37,8 @@ Start the server with `pnpm start` or `pnpm start-dev` for live reload. ### Async graphs (Clinic Bubbleprof) -- Run Bubbleprof attached to ts-node: - - `AI_BOT_PROF=1 DISABLE_MATRIX_JS_LOGGING=1 LOG_LEVELS="ai-bot=debug" pnpm dlx clinic bubbleprof --dest .clinic/ai-bot-bp -- node --require ts-node/register/transpile-only main.ts` +- Run Bubbleprof attached to the node process: + - `AI_BOT_PROF=1 DISABLE_MATRIX_JS_LOGGING=1 LOG_LEVELS="ai-bot=debug" pnpm dlx clinic bubbleprof --dest .clinic/ai-bot-bp -- node main.ts` - Drive one interaction; stop with Ctrl+C twice (~200–500ms apart) or send `SIGTERM` from another terminal. - Open the report: - `pnpm dlx clinic open .clinic/ai-bot-bp` diff --git a/packages/boxel-cli/README.md b/packages/boxel-cli/README.md index b47ad3f81f..7438dcb8ab 100644 --- a/packages/boxel-cli/README.md +++ b/packages/boxel-cli/README.md @@ -101,7 +101,7 @@ boxel --help boxel sync . ``` -The linked command automatically uses `dist/index.js` if built, or falls back to running TypeScript source via `ts-node`. +The linked command runs `dist/index.js`, so build the CLI first (`pnpm --filter @cardstack/boxel-cli build`). The TypeScript source isn't run directly. To unlink: diff --git a/packages/boxel-cli/bin/boxel.js b/packages/boxel-cli/bin/boxel.js index 12ecddf070..30b46a2698 100755 --- a/packages/boxel-cli/bin/boxel.js +++ b/packages/boxel-cli/bin/boxel.js @@ -67,13 +67,18 @@ function mkcertRootCAPath() { maybeReExecWithMkcertCA(); -// Use the built dist version if available, otherwise fall back to ts-node +// Use the built dist version if available, otherwise run the TS source directly. const distEntry = path.resolve(__dirname, '..', 'dist', 'index.js'); if (fs.existsSync(distEntry)) { require(distEntry); } else { - // Development fallback: run from TypeScript source via ts-node - require('ts-node').register({ transpileOnly: true }); - require('../src/index.ts'); + // The CLI ships as a built CJS bundle (the TypeScript source uses + // CommonJS-only globals like __dirname and isn't runnable as native ESM). + // Build it first. + console.error( + 'boxel-cli: dist/index.js not found. Build the CLI first:\n' + + ' pnpm --filter @cardstack/boxel-cli build', + ); + process.exit(1); } diff --git a/packages/boxel-cli/src/lib/find-package-root.ts b/packages/boxel-cli/src/lib/find-package-root.ts index e8b1415a65..9c2d530eac 100644 --- a/packages/boxel-cli/src/lib/find-package-root.ts +++ b/packages/boxel-cli/src/lib/find-package-root.ts @@ -4,9 +4,9 @@ import { dirname, join } from 'node:path'; /** * Walk up from `__dirname` until we find the `@cardstack/boxel-cli` * package.json. The single-file esbuild bundle places `__dirname` at - * `boxel-cli/dist`; the ts-node fallback places it inside `src/...`. - * Anchoring to the package.json keeps every downstream path stable - * regardless of which entry mode is active. + * `boxel-cli/dist`; running from source (e.g. under vitest) places it + * inside `src/...`. Anchoring to the package.json keeps every downstream + * path stable regardless of which entry mode is active. */ export function findBoxelCliRoot(startDir: string): string { let dir = startDir; diff --git a/packages/postgres/Dockerfile b/packages/postgres/Dockerfile index 4b442434eb..d78f2e064c 100644 --- a/packages/postgres/Dockerfile +++ b/packages/postgres/Dockerfile @@ -20,4 +20,4 @@ RUN CI=1 pnpm install -r --offline WORKDIR /boxel/packages/postgres -CMD ./node_modules/.bin/ts-node --transpileOnly ./scripts/fix-migration-names.ts && ./node_modules/.bin/node-pg-migrate --check-order false --migrations-table migrations up && sleep infinity +CMD node ./scripts/fix-migration-names.ts && ./node_modules/.bin/node-pg-migrate --check-order false --migrations-table migrations up && sleep infinity diff --git a/packages/realm-server/scripts/codemod/context-search/run.ts b/packages/realm-server/scripts/codemod/context-search/run.ts index daa4aa01d0..2cf51b4e9c 100644 --- a/packages/realm-server/scripts/codemod/context-search/run.ts +++ b/packages/realm-server/scripts/codemod/context-search/run.ts @@ -3,7 +3,7 @@ // usages it can transform mechanically, and reports the ones it can't so they // can be migrated by hand. // -// ts-node --transpileOnly scripts/codemod/context-search/run.ts [--write] +// node scripts/codemod/context-search/run.ts [--write] import { readFileSync, writeFileSync, statSync, readdirSync } from 'fs'; import { join, resolve } from 'path'; @@ -54,7 +54,7 @@ async function main(): Promise { let paths = args.filter((a) => !a.startsWith('--')); if (paths.length === 0) { console.error( - 'usage: ts-node scripts/codemod/context-search/run.ts … [--write]', + 'usage: node scripts/codemod/context-search/run.ts … [--write]', ); process.exit(2); } diff --git a/packages/realm-server/scripts/run-test-modules.cjs b/packages/realm-server/scripts/run-test-modules.cjs deleted file mode 100644 index 9d3d224686..0000000000 --- a/packages/realm-server/scripts/run-test-modules.cjs +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env node -/* eslint-env node */ -'use strict'; - -const { spawnSync } = require('node:child_process'); // eslint-disable-line @typescript-eslint/no-var-requires - -function buildModuleFilter(modulesToMatch) { - const escaped = modulesToMatch - .map((moduleName) => escapeRegex(moduleName)) - .join('|'); - const pattern = `^(?:${escaped})(?:\\s>\\s|:)`; - return `/${pattern}/`; -} - -function escapeRegex(value) { - return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&').replace(/\//g, '\\/'); -} - -const rawModules = process.env.TEST_MODULES ?? ''; -const cleanedRaw = rawModules.trim(); - -if (!cleanedRaw) { - console.error('TEST_MODULES must be set.'); - process.exit(1); -} - -const modules = cleanedRaw - .split(/[|,]/) - .map((value) => value.trim()) - .filter(Boolean) - .map((value) => value.replace(/^['"]+|['"]+$/g, '')); - -if (modules.length === 0) { - console.error('No module names found in TEST_MODULES.'); - process.exit(1); -} - -const args = ['--require', 'ts-node/register/transpile-only']; - -args.push('--filter', buildModuleFilter(modules)); - -args.push('tests/index.ts'); - -const qunitBin = require.resolve('qunit/bin/qunit.js'); -const result = spawnSync(process.execPath, [qunitBin, ...args], { - stdio: 'inherit', - env: process.env, -}); - -if (typeof result.status === 'number') { - process.exit(result.status); -} - -if (result.error) { - console.error(result.error); -} - -process.exit(1); diff --git a/packages/realm-server/scripts/start-prerender-manager.sh b/packages/realm-server/scripts/start-prerender-manager.sh index bc09846a1d..bf53e344cf 100755 --- a/packages/realm-server/scripts/start-prerender-manager.sh +++ b/packages/realm-server/scripts/start-prerender-manager.sh @@ -2,16 +2,16 @@ # Start the prerender manager in staging -# Run from the realm-server package directory so ts-node finds the package's -# tsconfig. Previously the CMD wrapped pnpm --filter, which set CWD for us; +# Run from the realm-server package directory so node resolves the package's +# node_modules. Previously the CMD wrapped pnpm --filter, which set CWD for us; # now PID 1 execs into this script directly so we set it ourselves. The PATH -# prepend gives us the local ts-node binary that `pnpm --filter` used to put +# prepend gives us the package's local node_modules/.bin that `pnpm --filter` used to put # on PATH automatically. cd "$(cd "$(dirname "$0")" && pwd)/.." PATH="./node_modules/.bin:$PATH" export PATH -echo "[start-prerender-manager] pid=$$ ppid=$PPID about to exec ts-node at $(date -Iseconds)" >&2 +echo "[start-prerender-manager] pid=$$ ppid=$PPID about to exec node at $(date -Iseconds)" >&2 NODE_ENV=production \ NODE_NO_WARNINGS=1 \ diff --git a/packages/realm-server/scripts/start-prerender-production.sh b/packages/realm-server/scripts/start-prerender-production.sh index b30db37464..8ed09013f5 100755 --- a/packages/realm-server/scripts/start-prerender-production.sh +++ b/packages/realm-server/scripts/start-prerender-production.sh @@ -3,16 +3,16 @@ # Start the prerender server in production # Expects REALM_SECRET_SEED to be set in the environment -# Run from the realm-server package directory so ts-node finds the package's -# tsconfig. Previously the CMD wrapped pnpm --filter, which set CWD for us; +# Run from the realm-server package directory so node resolves the package's +# node_modules. Previously the CMD wrapped pnpm --filter, which set CWD for us; # now PID 1 execs into this script directly so we set it ourselves. The PATH -# prepend gives us the local ts-node binary that `pnpm --filter` used to put +# prepend gives us the package's local node_modules/.bin that `pnpm --filter` used to put # on PATH automatically. cd "$(cd "$(dirname "$0")" && pwd)/.." PATH="./node_modules/.bin:$PATH" export PATH -echo "[start-prerender-production] pid=$$ ppid=$PPID about to exec ts-node at $(date -Iseconds)" >&2 +echo "[start-prerender-production] pid=$$ ppid=$PPID about to exec node at $(date -Iseconds)" >&2 NODE_ENV=production \ NODE_NO_WARNINGS=1 \ diff --git a/packages/realm-server/scripts/start-prerender-staging.sh b/packages/realm-server/scripts/start-prerender-staging.sh index 4eeebe3512..5f17f3ef4e 100755 --- a/packages/realm-server/scripts/start-prerender-staging.sh +++ b/packages/realm-server/scripts/start-prerender-staging.sh @@ -3,16 +3,16 @@ # Start the prerender server in staging # Expects REALM_SECRET_SEED to be set in the environment -# Run from the realm-server package directory so ts-node finds the package's -# tsconfig. Previously the CMD wrapped pnpm --filter, which set CWD for us; +# Run from the realm-server package directory so node resolves the package's +# node_modules. Previously the CMD wrapped pnpm --filter, which set CWD for us; # now PID 1 execs into this script directly so we set it ourselves. The PATH -# prepend gives us the local ts-node binary that `pnpm --filter` used to put +# prepend gives us the package's local node_modules/.bin that `pnpm --filter` used to put # on PATH automatically. cd "$(cd "$(dirname "$0")" && pwd)/.." PATH="./node_modules/.bin:$PATH" export PATH -echo "[start-prerender-staging] pid=$$ ppid=$PPID about to exec ts-node at $(date -Iseconds)" >&2 +echo "[start-prerender-staging] pid=$$ ppid=$PPID about to exec node at $(date -Iseconds)" >&2 NODE_ENV=production \ NODE_NO_WARNINGS=1 \ diff --git a/packages/realm-server/scripts/start-production.sh b/packages/realm-server/scripts/start-production.sh index 4778c6ef3b..1d98efc1ae 100755 --- a/packages/realm-server/scripts/start-production.sh +++ b/packages/realm-server/scripts/start-production.sh @@ -2,10 +2,10 @@ SCRIPTS_DIR="$(cd "$(dirname "$0")" && pwd)" # Run from the realm-server package directory so `pnpm setup:*` resolves the # package's npm scripts (the relative `../base/` paths inside those scripts -# depend on this CWD) and ts-node can find the package's tsconfig. Previously +# depend on this CWD). Previously # the CMD wrapped pnpm --filter, which set CWD for us; now PID 1 execs into -# this script directly so we set it ourselves. The PATH prepend gives us the -# local ts-node binary that `pnpm --filter` used to put on PATH automatically. +# this script directly so we set it ourselves. The PATH prepend gives us the package's +# local node_modules/.bin that `pnpm --filter` used to put on PATH automatically. cd "$SCRIPTS_DIR/.." PATH="./node_modules/.bin:$PATH" export PATH @@ -28,7 +28,7 @@ SOFTWARE_FACTORY_REALM_URL="${RESOLVED_SOFTWARE_FACTORY_REALM_URL:-$DEFAULT_SOFT DEFAULT_BOXEL_HOMEPAGE_REALM_URL='https://app.boxel.ai/boxel-homepage/' BOXEL_HOMEPAGE_REALM_URL="${RESOLVED_BOXEL_HOMEPAGE_REALM_URL:-$DEFAULT_BOXEL_HOMEPAGE_REALM_URL}" -echo "[start-production] pid=$$ ppid=$PPID about to exec ts-node at $(date -Iseconds)" >&2 +echo "[start-production] pid=$$ ppid=$PPID about to exec node at $(date -Iseconds)" >&2 NODE_NO_WARNINGS=1 \ LOW_CREDIT_THRESHOLD=2000 \ diff --git a/packages/realm-server/scripts/start-staging.sh b/packages/realm-server/scripts/start-staging.sh index 9aba3408b3..e4ae93808a 100755 --- a/packages/realm-server/scripts/start-staging.sh +++ b/packages/realm-server/scripts/start-staging.sh @@ -2,10 +2,10 @@ SCRIPTS_DIR="$(cd "$(dirname "$0")" && pwd)" # Run from the realm-server package directory so `pnpm setup:*` resolves the # package's npm scripts (the relative `../base/` paths inside those scripts -# depend on this CWD) and ts-node can find the package's tsconfig. Previously +# depend on this CWD). Previously # the CMD wrapped pnpm --filter, which set CWD for us; now PID 1 execs into -# this script directly so we set it ourselves. The PATH prepend gives us the -# local ts-node binary that `pnpm --filter` used to put on PATH automatically. +# this script directly so we set it ourselves. The PATH prepend gives us the package's +# local node_modules/.bin that `pnpm --filter` used to put on PATH automatically. cd "$SCRIPTS_DIR/.." PATH="./node_modules/.bin:$PATH" export PATH @@ -28,7 +28,7 @@ SOFTWARE_FACTORY_REALM_URL="${RESOLVED_SOFTWARE_FACTORY_REALM_URL:-$DEFAULT_SOFT DEFAULT_BOXEL_HOMEPAGE_REALM_URL='https://realms-staging.stack.cards/boxel-homepage/' BOXEL_HOMEPAGE_REALM_URL="${RESOLVED_BOXEL_HOMEPAGE_REALM_URL:-$DEFAULT_BOXEL_HOMEPAGE_REALM_URL}" -echo "[start-staging] pid=$$ ppid=$PPID about to exec ts-node at $(date -Iseconds)" >&2 +echo "[start-staging] pid=$$ ppid=$PPID about to exec node at $(date -Iseconds)" >&2 NODE_NO_WARNINGS=1 \ LOW_CREDIT_THRESHOLD=2000 \ diff --git a/packages/realm-server/scripts/start-worker-production.sh b/packages/realm-server/scripts/start-worker-production.sh index 3af23aed58..d5e6d006f4 100755 --- a/packages/realm-server/scripts/start-worker-production.sh +++ b/packages/realm-server/scripts/start-worker-production.sh @@ -1,9 +1,9 @@ #! /bin/sh -# Run from the realm-server package directory so ts-node finds the package's -# tsconfig. Previously the CMD wrapped pnpm --filter, which set CWD for us; +# Run from the realm-server package directory so node resolves the package's +# node_modules. Previously the CMD wrapped pnpm --filter, which set CWD for us; # now PID 1 execs into this script directly so we set it ourselves. The PATH -# prepend gives us the local ts-node binary that `pnpm --filter` used to put +# prepend gives us the package's local node_modules/.bin that `pnpm --filter` used to put # on PATH automatically. cd "$(cd "$(dirname "$0")" && pwd)/.." PATH="./node_modules/.bin:$PATH" @@ -14,7 +14,7 @@ CATALOG_REALM_URL="${RESOLVED_CATALOG_REALM_URL:-$DEFAULT_CATALOG_REALM_URL}" DEFAULT_SOFTWARE_FACTORY_REALM_URL='https://app.boxel.ai/software-factory/' SOFTWARE_FACTORY_REALM_URL="${RESOLVED_SOFTWARE_FACTORY_REALM_URL:-$DEFAULT_SOFTWARE_FACTORY_REALM_URL}" -echo "[start-worker-production] pid=$$ ppid=$PPID about to exec ts-node at $(date -Iseconds)" >&2 +echo "[start-worker-production] pid=$$ ppid=$PPID about to exec node at $(date -Iseconds)" >&2 NODE_NO_WARNINGS=1 \ NODE_OPTIONS="${NODE_OPTIONS:---max-old-space-size=4096}" \ diff --git a/packages/realm-server/scripts/start-worker-staging.sh b/packages/realm-server/scripts/start-worker-staging.sh index ee605f8256..3861506d5d 100755 --- a/packages/realm-server/scripts/start-worker-staging.sh +++ b/packages/realm-server/scripts/start-worker-staging.sh @@ -1,9 +1,9 @@ #! /bin/sh -# Run from the realm-server package directory so ts-node finds the package's -# tsconfig. Previously the CMD wrapped pnpm --filter, which set CWD for us; +# Run from the realm-server package directory so node resolves the package's +# node_modules. Previously the CMD wrapped pnpm --filter, which set CWD for us; # now PID 1 execs into this script directly so we set it ourselves. The PATH -# prepend gives us the local ts-node binary that `pnpm --filter` used to put +# prepend gives us the package's local node_modules/.bin that `pnpm --filter` used to put # on PATH automatically. cd "$(cd "$(dirname "$0")" && pwd)/.." PATH="./node_modules/.bin:$PATH" @@ -14,7 +14,7 @@ CATALOG_REALM_URL="${RESOLVED_CATALOG_REALM_URL:-$DEFAULT_CATALOG_REALM_URL}" DEFAULT_SOFTWARE_FACTORY_REALM_URL='https://realms-staging.stack.cards/software-factory/' SOFTWARE_FACTORY_REALM_URL="${RESOLVED_SOFTWARE_FACTORY_REALM_URL:-$DEFAULT_SOFTWARE_FACTORY_REALM_URL}" -echo "[start-worker-staging] pid=$$ ppid=$PPID about to exec ts-node at $(date -Iseconds)" >&2 +echo "[start-worker-staging] pid=$$ ppid=$PPID about to exec node at $(date -Iseconds)" >&2 NODE_NO_WARNINGS=1 \ NODE_OPTIONS="${NODE_OPTIONS:---max-old-space-size=4096}" \ diff --git a/packages/realm-server/worker-manager.ts b/packages/realm-server/worker-manager.ts index 20ab7ff93d..f03db7eaf1 100644 --- a/packages/realm-server/worker-manager.ts +++ b/packages/realm-server/worker-manager.ts @@ -12,7 +12,7 @@ import { writeSync } from 'node:fs'; // and throws *again*. Node delivers the throw inside an uncaughtException // handler as the next pending exception, so V8 hot-loops re-reporting it // (uv__run_check → CheckImmediate → InspectorConsoleCall → Error.stack -// formatting via ts-node) at ~100% CPU until the process is SIGKILLed — +// formatting) at ~100% CPU until the process is SIGKILLed — // CS-11084. Swallowing EPIPE at the stream level breaks the loop and // lets normal SIGTERM-driven shutdown finish. const swallowEpipe = (err: NodeJS.ErrnoException) => { diff --git a/packages/software-factory/scripts/canusetool-fix-verify.ts b/packages/software-factory/scripts/canusetool-fix-verify.ts index 6984220499..750ce79fef 100644 --- a/packages/software-factory/scripts/canusetool-fix-verify.ts +++ b/packages/software-factory/scripts/canusetool-fix-verify.ts @@ -8,7 +8,7 @@ * Faster than the full matrix repro — two probes instead of sixteen. * * Usage: - * pnpm exec ts-node --transpileOnly scripts/canusetool-fix-verify.ts + * pnpm exec node scripts/canusetool-fix-verify.ts */ import { existsSync, mkdtempSync, realpathSync, rmSync } from 'node:fs'; diff --git a/packages/software-factory/scripts/canusetool-repro.ts b/packages/software-factory/scripts/canusetool-repro.ts index 8852950eed..6e78564919 100644 --- a/packages/software-factory/scripts/canusetool-repro.ts +++ b/packages/software-factory/scripts/canusetool-repro.ts @@ -26,7 +26,7 @@ * out-of-workspace Write is rejected. * * Usage: - * pnpm exec ts-node --transpileOnly scripts/canusetool-repro.ts + * pnpm exec node scripts/canusetool-repro.ts * * (Auth: works with whatever `claude login` already set up; no * ANTHROPIC_API_KEY needed.) diff --git a/packages/software-factory/src/factory-agent/opencode.ts b/packages/software-factory/src/factory-agent/opencode.ts index eb35e2b01c..48c0d4c147 100644 --- a/packages/software-factory/src/factory-agent/opencode.ts +++ b/packages/software-factory/src/factory-agent/opencode.ts @@ -32,9 +32,9 @@ import { } from '@modelcontextprotocol/sdk/types.js'; import type { Config as OpencodeConfig } from '@opencode-ai/sdk'; -// `@opencode-ai/sdk` is ESM-only and the test runner uses ts-node in -// CommonJS mode, so a top-level `import` would fail at module-load -// time on every test that touches this file. Lazy-load via dynamic +// `@opencode-ai/sdk` is ESM-only, so in a CommonJS load context a +// top-level `import` would fail at module-load time on every test that +// touches this file. Lazy-load via dynamic // import inside `run()` so the type imports stay available at compile // time and the runtime cost (one dynamic import per `factory:go`) is // negligible. diff --git a/packages/software-factory/tests/fixtures.ts b/packages/software-factory/tests/fixtures.ts index 0bed0bac99..303a64de2e 100644 --- a/packages/software-factory/tests/fixtures.ts +++ b/packages/software-factory/tests/fixtures.ts @@ -346,7 +346,7 @@ async function startRealmProcess( // Race the metadata-file poll against an early `'error'` from the // child. Without this, a spawn-level failure (e.g. ENOENT on the - // ts-node binary) leaves waitForMetadataFile polling until its + // node binary) leaves waitForMetadataFile polling until its // 300-second timeout before the startup error surfaces. let earlyError = new Promise((_, reject) => { child!.once('error', reject); From 538841bd2c6961905646cc54bad3037d99bce434 Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Thu, 18 Jun 2026 15:38:03 -0400 Subject: [PATCH 28/38] chore: drop remaining ts-node mentions from comments and docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-up to the ts-node cleanup: the last references were explanatory comments/docs, not usage. Reword them to describe the native-Node behavior directly instead of contrasting with ts-node. - .eslintrc.js / erasable-syntax-selectors.cjs: describe the "erasable TS for --experimental-strip-types" rule without naming ts-node. - pg-adapter.ts: the node-pg-migrate `.default` unwrap is still required (native ESM binds the CJS namespace object; the runner is on `.default`) — keep the cast, but explain it purely in native-ESM terms. - fake-watcher fixture + software-factory phase-1 plan: native `node` wording, no ts-node. Only scripts/esm-codemod/** still mentions ts-node, by design (it's the migration tooling). Co-Authored-By: Claude Opus 4.8 --- .eslintrc.js | 4 ++-- eslint/erasable-syntax-selectors.cjs | 2 +- packages/boxel-cli/tests/fixtures/fake-watcher.cjs | 2 +- packages/postgres/pg-adapter.ts | 7 ++++--- packages/software-factory/docs/phase-1-plan.md | 4 ++-- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 0d12a3c49b..1f871c456c 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -53,8 +53,8 @@ module.exports = { 'error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }, ], - // Keep new code "erasable" so it can run under Node's - // `--experimental-strip-types` without ts-node. + // Keep new code "erasable" so Node can run it via + // `--experimental-strip-types` (type-only syntax that vanishes when stripped). '@typescript-eslint/parameter-properties': [ 'error', { prefer: 'class-property' }, diff --git a/eslint/erasable-syntax-selectors.cjs b/eslint/erasable-syntax-selectors.cjs index 31150a86f9..eed739e0a6 100644 --- a/eslint/erasable-syntax-selectors.cjs +++ b/eslint/erasable-syntax-selectors.cjs @@ -3,7 +3,7 @@ // Selectors for TypeScript syntax that Node cannot run via // `--experimental-strip-types`, which only handles "erasable" TS — // syntax that vanishes once type annotations are stripped. New code -// must avoid these so it can run under Node natively, without ts-node. +// must avoid these so it can run under Node natively. // // Shared by the root `.eslintrc.js`, `packages/ai-bot/.eslintrc.js` // (which is `root: true`), and `packages/catalog/.eslintrc.cjs` (which diff --git a/packages/boxel-cli/tests/fixtures/fake-watcher.cjs b/packages/boxel-cli/tests/fixtures/fake-watcher.cjs index b5c03b14e4..497c028a21 100644 --- a/packages/boxel-cli/tests/fixtures/fake-watcher.cjs +++ b/packages/boxel-cli/tests/fixtures/fake-watcher.cjs @@ -5,7 +5,7 @@ // shutdown. // Node (>=22.18 / 24) strips TypeScript types natively, so the registry .ts -// loads via a plain require — no ts-node needed after the ESM migration. +// loads via a plain require with no extra loader. const path = require('path'); const registry = require( path.resolve( diff --git a/packages/postgres/pg-adapter.ts b/packages/postgres/pg-adapter.ts index 303012dcb6..c91704f95d 100644 --- a/packages/postgres/pg-adapter.ts +++ b/packages/postgres/pg-adapter.ts @@ -16,9 +16,10 @@ import { Pool, Client, type Notification } from 'pg'; import { postgresConfig } from './pg-config.ts'; import migrationNameFixes from './scripts/migration-name-fixes.cjs'; -// node-pg-migrate is CJS and exposes the runner on `.default` at runtime; native -// ESM doesn't unwrap it the way ts-node's esModuleInterop did, and the package's -// types declare the default as the runner, so cast to its call signature. +// node-pg-migrate is CJS and exposes the runner as its default export. Under +// native ESM the default import binds the module's namespace object, so the +// callable lives on `.default`; the package's types declare the default as the +// runner, so cast to its call signature. const migrate = ((nodePgMigrate as any).default ?? nodePgMigrate) as ( options: RunnerOption, ) => Promise; diff --git a/packages/software-factory/docs/phase-1-plan.md b/packages/software-factory/docs/phase-1-plan.md index babf239dfb..0544ba2ff2 100644 --- a/packages/software-factory/docs/phase-1-plan.md +++ b/packages/software-factory/docs/phase-1-plan.md @@ -443,10 +443,10 @@ The first version should support: Add a script: ```json -"factory:go": "ts-node --transpileOnly src/cli/factory-entrypoint.ts" +"factory:go": "node src/cli/factory-entrypoint.ts" ``` -For software-factory CLI entrypoints, favor `ts-node --transpileOnly` over `tsx`. +For software-factory CLI entrypoints, run the TypeScript directly with `node` (native type stripping) rather than a separate runner like `tsx`. - it matches the execution model already used by `realm-server` - it avoids the decorator/runtime incompatibilities we hit when `tsx` imports `runtime-common` auth code From df856f773a57e05c8d63ab0761b4fb3d4114c380 Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Thu, 18 Jun 2026 15:44:51 -0400 Subject: [PATCH 29/38] fix: make boxel-ui checker stubbable under native ESM (post-deployment tests) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The two `/_post-deployment` maintenance-endpoints tests stubbed `compareCurrentBoxelUIChecksum` / `writeCurrentBoxelUIChecksum` on the `import * as` namespace of boxel-ui-change-checker. Under native ESM that namespace is read-only, so sinon threw "ES Modules cannot be stubbed" and both tests failed (the only red in realm-server shard 4). Group the two functions on an exported mutable object `boxelUIChecker` and have the post-deployment handler call through it; the tests stub the object's methods. This matches the codebase's stubbing convention (stub methods on objects/instances — global.fetch, stripe.subscriptions — never module namespaces) and preserves the handler's behavior. Verified the stub intercepts calls through the object under native node. Co-Authored-By: Claude Opus 4.8 --- .../realm-server/handlers/handle-post-deployment.ts | 11 +++++------ packages/realm-server/lib/boxel-ui-change-checker.ts | 9 +++++++++ .../server-endpoints/maintenance-endpoints-test.ts | 10 +++++----- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/packages/realm-server/handlers/handle-post-deployment.ts b/packages/realm-server/handlers/handle-post-deployment.ts index a139307f69..03ef927ddf 100644 --- a/packages/realm-server/handlers/handle-post-deployment.ts +++ b/packages/realm-server/handlers/handle-post-deployment.ts @@ -8,10 +8,7 @@ import { setContextResponse, } from '../middleware/index.ts'; import type { CreateRoutesArgs } from '../routes.ts'; -import { - compareCurrentBoxelUIChecksum, - writeCurrentBoxelUIChecksum, -} from '../lib/boxel-ui-change-checker.ts'; +import { boxelUIChecker } from '../lib/boxel-ui-change-checker.ts'; import { getFullReindexRealmUrls } from '../lib/full-reindex-realm-urls.ts'; export default function handlePostDeployment({ @@ -39,7 +36,7 @@ export default function handlePostDeployment({ await definitionLookup.clearAllDefinitions(); let boxelUiChangeCheckerResult = - await compareCurrentBoxelUIChecksum(assetsURL); + await boxelUIChecker.compareCurrentBoxelUIChecksum(assetsURL); if ( boxelUiChangeCheckerResult.currentChecksum !== @@ -57,7 +54,9 @@ export default function handlePostDeployment({ }, }); - writeCurrentBoxelUIChecksum(boxelUiChangeCheckerResult.currentChecksum); + boxelUIChecker.writeCurrentBoxelUIChecksum( + boxelUiChangeCheckerResult.currentChecksum, + ); } await setContextResponse( diff --git a/packages/realm-server/lib/boxel-ui-change-checker.ts b/packages/realm-server/lib/boxel-ui-change-checker.ts index dbfeaf5a98..7479456445 100644 --- a/packages/realm-server/lib/boxel-ui-change-checker.ts +++ b/packages/realm-server/lib/boxel-ui-change-checker.ts @@ -53,3 +53,12 @@ export async function compareCurrentBoxelUIChecksum(distURL: URL) { export function writeCurrentBoxelUIChecksum(checksum: string) { fs.writeFileSync(fileChecksumPath, checksum); } + +// Grouped on a mutable object so tests can stub these under native ESM — +// named exports are read-only live bindings and can't be stubbed directly. +// Consumers (e.g. the post-deployment handler) call through `boxelUIChecker` +// so a `sinon.stub(boxelUIChecker, …)` takes effect. +export const boxelUIChecker = { + compareCurrentBoxelUIChecksum, + writeCurrentBoxelUIChecksum, +}; diff --git a/packages/realm-server/tests/server-endpoints/maintenance-endpoints-test.ts b/packages/realm-server/tests/server-endpoints/maintenance-endpoints-test.ts index 956db024df..bce26054ea 100644 --- a/packages/realm-server/tests/server-endpoints/maintenance-endpoints-test.ts +++ b/packages/realm-server/tests/server-endpoints/maintenance-endpoints-test.ts @@ -5,7 +5,7 @@ import { v4 as uuidv4 } from 'uuid'; import sinon from 'sinon'; import { PgAdapter, PgQueueRunner } from '@cardstack/postgres'; import { sumUpCreditsLedger } from '@cardstack/billing/billing-queries'; -import * as boxelUIChangeChecker from '../../lib/boxel-ui-change-checker.ts'; +import { boxelUIChecker } from '../../lib/boxel-ui-change-checker.ts'; import { fetchRealmPermissions } from '@cardstack/runtime-common'; import { grafanaSecret, @@ -901,13 +901,13 @@ module(`server-endpoints/${basename(import.meta.filename)}`, function () { test('post-deployment endpoint triggers full reindex when checksums differ', async function (assert: Assert) { let compareCurrentBoxelUIChecksumStub = sinon - .stub(boxelUIChangeChecker, 'compareCurrentBoxelUIChecksum') + .stub(boxelUIChecker, 'compareCurrentBoxelUIChecksum') .resolves({ previousChecksum: 'old-checksum-123', currentChecksum: 'new-checksum-456', }); let writeCurrentBoxelUIChecksumStub = sinon.stub( - boxelUIChangeChecker, + boxelUIChecker, 'writeCurrentBoxelUIChecksum', ); let registryOnlyRealmURL = `http://localhost:4201/registry-only-${uuidv4()}/`; @@ -1031,13 +1031,13 @@ module(`server-endpoints/${basename(import.meta.filename)}`, function () { test('post-deployment endpoint clears modules cache even when checksums match', async function (assert: Assert) { let compareCurrentBoxelUIChecksumStub = sinon - .stub(boxelUIChangeChecker, 'compareCurrentBoxelUIChecksum') + .stub(boxelUIChecker, 'compareCurrentBoxelUIChecksum') .resolves({ previousChecksum: 'same-checksum-789', currentChecksum: 'same-checksum-789', }); let writeCurrentBoxelUIChecksumStub = sinon.stub( - boxelUIChangeChecker, + boxelUIChecker, 'writeCurrentBoxelUIChecksum', ); From 30527404b7bb85a4a3321a268f6d16a9a844609e Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Thu, 18 Jun 2026 16:09:09 -0400 Subject: [PATCH 30/38] fix: ensure CI provisions browsers for prerender and Software Factory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Env-mode CI (host shards, Live Tests, Software Factory) drives the prerender through puppeteer, which in env-mode relies on puppeteer's bundled Chrome (env-vars.sh only points PUPPETEER_EXECUTABLE_PATH at a system Chrome in non-env-mode). actions/cache caches the pnpm store but not ~/.cache/puppeteer, and on a store cache hit puppeteer's postinstall skips the Chrome download — so the prerender threw "Could not find Chrome (148.0.7778.97)", the standby pool stayed empty, base indexing never finished, and /base/_readiness-check hung (host shards timed out at 000000). Main only passed because its warm cache still had Chrome. - init: explicitly `puppeteer browsers install chrome` after install (idempotent; no-op when already cached) so every job that runs the prerender has Chrome regardless of cache state. - Software Factory: `playwright install --with-deps` so the apt system libraries are present too ("Host system is missing dependencies to run browsers"). Co-Authored-By: Claude Opus 4.8 --- .github/actions/init/action.yml | 10 ++++++++++ .github/workflows/ci-software-factory.yaml | 5 ++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/.github/actions/init/action.yml b/.github/actions/init/action.yml index aaff14aea1..79c27d4ef0 100644 --- a/.github/actions/init/action.yml +++ b/.github/actions/init/action.yml @@ -27,6 +27,16 @@ runs: shell: bash run: pnpm install --frozen-lockfile + # Ensure puppeteer's Chrome is present. actions/cache caches the pnpm + # store but not ~/.cache/puppeteer, and on a store cache hit puppeteer's + # postinstall can skip the browser download — which leaves the prerender + # unable to launch Chrome in env-mode CI (where PUPPETEER_EXECUTABLE_PATH + # isn't pointed at a system Chrome). Installing explicitly is idempotent + # (a no-op when the cached version is already present). + - name: Ensure puppeteer Chrome is installed + shell: bash + run: pnpm --filter @cardstack/realm-server exec puppeteer browsers install chrome + - name: Prune pnpm store if: ${{ steps.cache.outputs.cache-hit != 'true' }} shell: bash diff --git a/.github/workflows/ci-software-factory.yaml b/.github/workflows/ci-software-factory.yaml index 6526207b5f..cf2a6bbab5 100644 --- a/.github/workflows/ci-software-factory.yaml +++ b/.github/workflows/ci-software-factory.yaml @@ -75,7 +75,10 @@ jobs: shopt -s dotglob cp -a .test-web-assets-artifact/. ./ - name: Install Playwright Browsers - run: pnpm exec playwright install + # --with-deps also apt-installs the system libraries Playwright needs; + # without it CI fails with "Host system is missing dependencies to run + # browsers". + run: pnpm exec playwright install --with-deps working-directory: packages/software-factory - name: Run Node tests if: ${{ matrix.shard.index == 1 }} From fae928efa6bf6f54d13940ac2ddd8c939cbdee5d Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Thu, 18 Jun 2026 16:58:30 -0400 Subject: [PATCH 31/38] fix: correct puppeteer Chrome install invocation in init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `pnpm --filter exec puppeteer browsers install chrome` went through pnpm's recursive-exec path and dropped the `chrome` arg in CI (puppeteer printed its usage and exited 1), which failed the init step for every workflow. Use a non-recursive `pnpm exec` from the package directory instead — the same form SF's `pnpm exec playwright install` uses, which forwards args correctly. Co-Authored-By: Claude Opus 4.8 --- .github/actions/init/action.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/actions/init/action.yml b/.github/actions/init/action.yml index 79c27d4ef0..a8beb2d643 100644 --- a/.github/actions/init/action.yml +++ b/.github/actions/init/action.yml @@ -35,7 +35,8 @@ runs: # (a no-op when the cached version is already present). - name: Ensure puppeteer Chrome is installed shell: bash - run: pnpm --filter @cardstack/realm-server exec puppeteer browsers install chrome + working-directory: packages/realm-server + run: pnpm exec puppeteer browsers install chrome - name: Prune pnpm store if: ${{ steps.cache.outputs.cache-hit != 'true' }} From 2b0a55842c288be2d59feeeeeec3b1f6f45059b8 Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Thu, 18 Jun 2026 17:27:40 -0400 Subject: [PATCH 32/38] fix: clear partial puppeteer Chrome install before downloading MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit puppeteer's postinstall leaves an empty browser folder (~/.cache/puppeteer/chrome/linux-) with the download skipped, so the prerender fails "Could not find Chrome" and a plain `browsers install` refuses with "folder exists but executable is missing — All providers failed". Remove any partial install first, then download cleanly (the CDN works — main's postinstall downloads the same version fine). Co-Authored-By: Claude Opus 4.8 --- .github/actions/init/action.yml | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/.github/actions/init/action.yml b/.github/actions/init/action.yml index a8beb2d643..19af1c966e 100644 --- a/.github/actions/init/action.yml +++ b/.github/actions/init/action.yml @@ -28,15 +28,18 @@ runs: run: pnpm install --frozen-lockfile # Ensure puppeteer's Chrome is present. actions/cache caches the pnpm - # store but not ~/.cache/puppeteer, and on a store cache hit puppeteer's - # postinstall can skip the browser download — which leaves the prerender - # unable to launch Chrome in env-mode CI (where PUPPETEER_EXECUTABLE_PATH - # isn't pointed at a system Chrome). Installing explicitly is idempotent - # (a no-op when the cached version is already present). + # store but not ~/.cache/puppeteer, and puppeteer's postinstall can leave + # an empty browser folder (download skipped) — which makes the prerender + # fail with "Could not find Chrome" in env-mode CI (where + # PUPPETEER_EXECUTABLE_PATH isn't pointed at a system Chrome) and makes a + # plain `browsers install` refuse with "folder exists but executable is + # missing". Clear any partial install, then download cleanly. - name: Ensure puppeteer Chrome is installed shell: bash working-directory: packages/realm-server - run: pnpm exec puppeteer browsers install chrome + run: | + rm -rf "${PUPPETEER_CACHE_DIR:-$HOME/.cache/puppeteer}/chrome" + pnpm exec puppeteer browsers install chrome - name: Prune pnpm store if: ${{ steps.cache.outputs.cache-hit != 'true' }} From ef500c510a8931320833b984900e8d2f7b483655 Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Thu, 18 Jun 2026 18:24:35 -0400 Subject: [PATCH 33/38] fix: point env-mode prerender at system Chrome MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Abandon the bundled-Chrome approach for env-mode CI — puppeteer's postinstall leaves an empty cache folder and an explicit `browsers install` wouldn't reliably land Chrome where the prerender looks, so the env-mode prerender kept failing "Could not find Chrome". env-vars.sh already points PUPPETEER_EXECUTABLE_PATH at the system Chrome in standard mode; the block was just inside the non-env-mode guard. Move it to the "regardless of env-mode" section so env-mode uses the runner's /usr/bin/google-chrome too (it exists — the non-env-mode jobs already use it). Gated on the binary existing and the path being unset, so it's a no-op-or-correct in env-mode prod (the prerender container installs google-chrome-stable, and an explicit override still wins). Revert the init browser-install step it replaces. Co-Authored-By: Claude Opus 4.8 --- .github/actions/init/action.yml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/.github/actions/init/action.yml b/.github/actions/init/action.yml index 19af1c966e..aaff14aea1 100644 --- a/.github/actions/init/action.yml +++ b/.github/actions/init/action.yml @@ -27,20 +27,6 @@ runs: shell: bash run: pnpm install --frozen-lockfile - # Ensure puppeteer's Chrome is present. actions/cache caches the pnpm - # store but not ~/.cache/puppeteer, and puppeteer's postinstall can leave - # an empty browser folder (download skipped) — which makes the prerender - # fail with "Could not find Chrome" in env-mode CI (where - # PUPPETEER_EXECUTABLE_PATH isn't pointed at a system Chrome) and makes a - # plain `browsers install` refuse with "folder exists but executable is - # missing". Clear any partial install, then download cleanly. - - name: Ensure puppeteer Chrome is installed - shell: bash - working-directory: packages/realm-server - run: | - rm -rf "${PUPPETEER_CACHE_DIR:-$HOME/.cache/puppeteer}/chrome" - pnpm exec puppeteer browsers install chrome - - name: Prune pnpm store if: ${{ steps.cache.outputs.cache-hit != 'true' }} shell: bash From 9a78caae9d2e376b03ce58d3e92f50ba6d782263 Mon Sep 17 00:00:00 2001 From: Luke Melia Date: Thu, 18 Jun 2026 21:56:01 -0400 Subject: [PATCH 34/38] fix: build boxel-cli /api to JS so cross-package consumers load a real module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @cardstack/boxel-cli/api mapped to raw api.ts source. That resolves under some loaders (vitest, plain node via the workspace symlink realpath) but not Playwright's ESM worker loader, which failed loading software-factory's .spec.ts files with "does not provide an export named 'BoxelCLIClient'", taking down every SF Playwright shard. Bundle api.ts to dist/api.js (esbuild CJS — named exports stay detectable by Node's cjs-module-lexer, so ESM consumers keep `import { BoxelCLIClient }`) and point exports["./api"] at it; the types condition still resolves to api.ts, so type resolution is unchanged and no .d.ts is needed. Add a `build:api` script and run it before software-factory's node + playwright tests so the built module is present (only SF consumes this subpath). Co-Authored-By: Claude Opus 4.8 --- packages/boxel-cli/package.json | 6 ++++- packages/boxel-cli/scripts/build.ts | 34 +++++++++++++++++++++++++- packages/software-factory/package.json | 8 +++--- 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/packages/boxel-cli/package.json b/packages/boxel-cli/package.json index dd32681161..170c8d77de 100644 --- a/packages/boxel-cli/package.json +++ b/packages/boxel-cli/package.json @@ -6,7 +6,10 @@ "main": "./dist/index.js", "exports": { ".": "./dist/index.js", - "./api": "./api.ts", + "./api": { + "types": "./api.ts", + "default": "./dist/api.js" + }, "./package.json": "./package.json" }, "bin": { @@ -74,6 +77,7 @@ }, "scripts": { "build": "pnpm clean && pnpm build:types && pnpm build:test-harness && pnpm build:realms && NODE_NO_WARNINGS=1 node scripts/build.ts", + "build:api": "NODE_NO_WARNINGS=1 node scripts/build.ts --api-only", "build:plugin": "NODE_NO_WARNINGS=1 node scripts/build-plugin.ts", "build:realms": "NODE_NO_WARNINGS=1 node scripts/build-realms.ts", "build:skills": "NODE_NO_WARNINGS=1 node scripts/build-skills.ts", diff --git a/packages/boxel-cli/scripts/build.ts b/packages/boxel-cli/scripts/build.ts index a7dc1d3bf3..2c4ae48a19 100644 --- a/packages/boxel-cli/scripts/build.ts +++ b/packages/boxel-cli/scripts/build.ts @@ -89,4 +89,36 @@ async function buildCLI() { } } -buildCLI(); +// The public `@cardstack/boxel-cli/api` surface, bundled to a single CJS file +// so cross-package consumers (software-factory) load a normal built module +// rather than raw `.ts` source — the latter resolves under some loaders +// (vitest, plain node) but not others (Playwright's worker loader), which +// failed with "does not provide an export named 'BoxelCLIClient'". esbuild's +// CJS output keeps named exports detectable by Node's cjs-module-lexer, so ESM +// consumers can still `import { BoxelCLIClient }`. +async function buildAPI() { + mkdirSync('dist', { recursive: true }); + console.log('Building api...'); + try { + await build({ + ...commonConfig, + entryPoints: ['api.ts'], + outfile: 'dist/api.js', + }); + console.log('Built dist/api.js'); + } catch (error) { + console.error('API build failed:', error); + process.exit(1); + } +} + +async function main() { + // `build:api` passes --api-only to rebuild just the API surface quickly + // (consumers' test pipelines do this); a full `build` produces both. + if (!process.argv.includes('--api-only')) { + await buildCLI(); + } + await buildAPI(); +} + +main(); diff --git a/packages/software-factory/package.json b/packages/software-factory/package.json index 29683f210f..c30d4cf1cf 100644 --- a/packages/software-factory/package.json +++ b/packages/software-factory/package.json @@ -27,10 +27,10 @@ "smoke:test-realm": "NODE_NO_WARNINGS=1 node scripts/smoke-tests/smoke-test-realm.ts", "test": "NODE_NO_WARNINGS=1 node scripts/test.ts", "test:all": "NODE_NO_WARNINGS=1 node scripts/test.ts", - "test:node": "NODE_NO_WARNINGS=1 node scripts/test.ts --node-only", - "test:playwright": "playwright test", - "test:playwright:headed": "playwright test --headed", - "test:playwright:shard": "playwright test --shard", + "test:node": "pnpm --filter @cardstack/boxel-cli build:api && NODE_NO_WARNINGS=1 node scripts/test.ts --node-only", + "test:playwright": "pnpm --filter @cardstack/boxel-cli build:api && playwright test", + "test:playwright:headed": "pnpm --filter @cardstack/boxel-cli build:api && playwright test --headed", + "test:playwright:shard": "pnpm --filter @cardstack/boxel-cli build:api && playwright test --shard", "test:realm": "NODE_NO_WARNINGS=1 node scripts/run-realm-tests.ts" }, "devDependencies": { From da4f8c6cffc5fe8af1541197ae678e3e77450414 Mon Sep 17 00:00:00 2001 From: ylm Date: Fri, 19 Jun 2026 11:50:42 -0400 Subject: [PATCH 35/38] fix: copy content_tag_bg.wasm in build:api too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `pnpm --filter @cardstack/boxel-cli build:api` runs only buildAPI() to rebuild the API surface quickly for cross-package test consumers (software-factory). But the bundled dist/api.js imports content-tag transitively, and content-tag reads its wasm with `${import.meta.dirname}/content_tag_bg.wasm` — i.e. from boxel-cli's dist/. The wasm copy lived inside buildCLI() and only ran on a full build, so software-factory's `test:node` / `test:playwright` saw ENOENT on dist/content_tag_bg.wasm. Hoist the copy into a standalone step that always runs. Co-Authored-By: Claude Opus 4.7 (1M context) --- packages/boxel-cli/scripts/build.ts | 39 ++++++++++++++++------------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/packages/boxel-cli/scripts/build.ts b/packages/boxel-cli/scripts/build.ts index 2c4ae48a19..caa15b5730 100644 --- a/packages/boxel-cli/scripts/build.ts +++ b/packages/boxel-cli/scripts/build.ts @@ -57,24 +57,6 @@ async function buildCLI() { console.log('Making CLI file executable...'); chmodSync('dist/index.js', 0o755); - // content-tag (pulled in via runtime-common's transpile pipeline) - // loads its wasm with `readFileSync(`${import.meta.dirname}/content_tag_bg.wasm`)` - // from `pkg/node/`. After esbuild bundles content-tag into - // `dist/index.js`, `import.meta.dirname` becomes the boxel-cli dist/ dir, - // so the wasm has to live next to index.js — otherwise `boxel test` - // hits ENOENT on the first transpile. - let wasmSrc = join( - import.meta.dirname, - '..', - 'node_modules', - 'content-tag', - 'pkg', - 'node', - 'content_tag_bg.wasm', - ); - copyFileSync(wasmSrc, 'dist/content_tag_bg.wasm'); - console.log('Copied content_tag_bg.wasm into dist/'); - console.log('Build complete!'); // Log bundle size @@ -112,6 +94,26 @@ async function buildAPI() { } } +// content-tag (pulled in via runtime-common's transpile pipeline) loads its +// wasm with `readFileSync(`${import.meta.dirname}/content_tag_bg.wasm`)` from +// `pkg/node/`. After esbuild bundles content-tag into `dist/index.js` or +// `dist/api.js`, `import.meta.dirname` becomes the boxel-cli `dist/` dir, so +// the wasm has to live next to whichever entry was built — otherwise the first +// transpile hits ENOENT. Both `build` and `build:api` consumers need it. +function copyContentTagWasm() { + let wasmSrc = join( + import.meta.dirname, + '..', + 'node_modules', + 'content-tag', + 'pkg', + 'node', + 'content_tag_bg.wasm', + ); + copyFileSync(wasmSrc, 'dist/content_tag_bg.wasm'); + console.log('Copied content_tag_bg.wasm into dist/'); +} + async function main() { // `build:api` passes --api-only to rebuild just the API surface quickly // (consumers' test pipelines do this); a full `build` produces both. @@ -119,6 +121,7 @@ async function main() { await buildCLI(); } await buildAPI(); + copyContentTagWasm(); } main(); From bbae331fdfccb90cc2706ba6649c64f78bfadb04 Mon Sep 17 00:00:00 2001 From: ylm Date: Fri, 19 Jun 2026 11:50:44 -0400 Subject: [PATCH 36/38] fix: avoid named qunit imports in prerender-host-shell-recycle-test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same root cause as eb42f8184d / 40ad5cf098 — qunit is CJS and exposes module/test as properties of the default export, not as ESM named exports. Under native Node ESM, `import { module, test } from 'qunit'` throws "does not provide an export named 'module'". Because tests/index.ts requires every test file at load time (TEST_MODULES filters which run), this one file aborted all six realm-server shards. Match the convention used by the other realm-server test files. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../realm-server/tests/prerender-host-shell-recycle-test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/realm-server/tests/prerender-host-shell-recycle-test.ts b/packages/realm-server/tests/prerender-host-shell-recycle-test.ts index 497fae4495..0d3d410af6 100644 --- a/packages/realm-server/tests/prerender-host-shell-recycle-test.ts +++ b/packages/realm-server/tests/prerender-host-shell-recycle-test.ts @@ -1,4 +1,5 @@ -import { module, test } from 'qunit'; +import QUnit from 'qunit'; +const { module, test } = QUnit; import { basename } from 'path'; import { decideHostShellRecycle } from '../prerender/prerender-app.ts'; From 43edffd862c2a11625ea192aac9c4fab728427f2 Mon Sep 17 00:00:00 2001 From: ylm Date: Fri, 19 Jun 2026 12:18:07 -0400 Subject: [PATCH 37/38] fix: use import.meta.filename in prerender-host-shell-recycle-test Native Node ESM doesn't expose `__filename`. The sibling realm-server tests use `basename(import.meta.filename)` for the same module label; match that convention. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../realm-server/tests/prerender-host-shell-recycle-test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/realm-server/tests/prerender-host-shell-recycle-test.ts b/packages/realm-server/tests/prerender-host-shell-recycle-test.ts index 0d3d410af6..a07c2572c5 100644 --- a/packages/realm-server/tests/prerender-host-shell-recycle-test.ts +++ b/packages/realm-server/tests/prerender-host-shell-recycle-test.ts @@ -7,7 +7,7 @@ import { decideHostShellRecycle } from '../prerender/prerender-app.ts'; // every heartbeat: the manager echoes the current host-shell token, and the // server recycles its browser when that token differs from the one it warmed // against (the host was redeployed). See PRERENDER_HOST_SHELL_HASH_HEADER. -module(basename(__filename), function () { +module(basename(import.meta.filename), function () { module('decideHostShellRecycle', function () { test('no token reported yet → no recycle, baseline unchanged', function (assert) { assert.deepEqual(decideHostShellRecycle(null, undefined), { From 9c55e1a6aeca45c75855378ebf24699d756701ee Mon Sep 17 00:00:00 2001 From: ylm Date: Fri, 19 Jun 2026 22:26:07 -0400 Subject: [PATCH 38/38] fix: prune stale ts-node lockfile entries after rebase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After rebasing onto main (which bumped puppeteer to 25.0.2 and removed ts-node from realm-test-harness), `pnpm install` strips the residual ts-node entries that lingered in pnpm-lock.yaml from the pre-rebase state. No package.json changes — just lockfile alignment. Co-Authored-By: Claude Opus 4.7 (1M context) --- pnpm-lock.yaml | 121 ------------------------------------------------- 1 file changed, 121 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 90e91ed087..0538daa092 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -841,9 +841,6 @@ importers: stream-json: specifier: 'catalog:' version: 1.9.1 - ts-node: - specifier: ^10.9.2 - version: 10.9.2(@types/node@24.12.4)(typescript@5.9.3) typescript: specifier: 'catalog:' version: 5.9.3 @@ -1000,9 +997,6 @@ importers: matrix-js-sdk: specifier: 'catalog:' version: 38.3.0(patch_hash=cee0baf579283943dc5a6b48977e8ed40a13fc111b5de9c91814893f9a4989fb) - ts-node: - specifier: ^10.9.2 - version: 10.9.2(@types/node@24.12.4)(typescript@5.9.3) typescript: specifier: 'catalog:' version: 5.9.3 @@ -1119,9 +1113,6 @@ importers: semver: specifier: ^7.7.0 version: 7.8.0 - ts-node: - specifier: ^10.9.1 - version: 10.9.2(@types/node@24.12.4)(typescript@5.9.3) vite: specifier: 'catalog:' version: 6.4.2(@types/node@24.12.4)(lightningcss@1.32.0)(terser@5.47.1)(yaml@2.9.0) @@ -2506,9 +2497,6 @@ importers: tmp: specifier: 'catalog:' version: 0.2.5 - ts-node: - specifier: ^10.9.1 - version: 10.9.2(@types/node@24.12.4)(typescript@5.9.3) typescript: specifier: 'catalog:' version: 5.9.3 @@ -2834,9 +2822,6 @@ importers: tmp: specifier: 'catalog:' version: 0.2.5 - ts-node: - specifier: ^10.9.1 - version: 10.9.2(@types/node@24.12.4)(typescript@5.9.3) typescript: specifier: 'catalog:' version: 5.9.3 @@ -2903,9 +2888,6 @@ importers: puppeteer: specifier: ^25.0.2 version: 25.1.0 - ts-node: - specifier: ^10.9.1 - version: 10.9.2(@types/node@24.12.4)(typescript@5.9.3) typescript: specifier: 'catalog:' version: 5.9.3 @@ -3272,9 +3254,6 @@ importers: tmp: specifier: 'catalog:' version: 0.2.5 - ts-node: - specifier: ^10.9.1 - version: 10.9.2(@types/node@24.12.4)(typescript@5.9.3) typescript: specifier: 'catalog:' version: 5.9.3 @@ -4303,10 +4282,6 @@ packages: resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} engines: {node: '>=0.1.90'} - '@cspotcode/source-map-support@0.8.1': - resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} - engines: {node: '>=12'} - '@csstools/color-helpers@5.1.0': resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==} engines: {node: '>=18'} @@ -5477,9 +5452,6 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - '@jridgewell/trace-mapping@0.3.9': - resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - '@koa/cors@4.0.0': resolution: {integrity: sha512-Y4RrbvGTlAaa04DBoPBWJqDR5gPj32OOz827ULXfgB1F7piD1MB/zwn8JR2LAnvdILhxUbXbkXGWuNVsFuVFCQ==} engines: {node: '>= 14.0.0'} @@ -6652,18 +6624,6 @@ packages: resolution: {integrity: sha512-IBoECN9o9StxTZSy12eNSPdqiH5VzngD5Qx9YQDfteiXk9XyJhnyRQuBoU/MQCVnqau9fJpgKoA8Sy/0qItFXw==} deprecated: Please use @ember/app-tsconfig or @ember/library-tsconfig instead. These live at https://github.com/ember-cli/tsconfigs - '@tsconfig/node10@1.0.12': - resolution: {integrity: sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==} - - '@tsconfig/node12@1.0.11': - resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} - - '@tsconfig/node14@1.0.3': - resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} - - '@tsconfig/node16@1.0.4': - resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} - '@tybys/wasm-util@0.10.2': resolution: {integrity: sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==} @@ -7589,9 +7549,6 @@ packages: engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} deprecated: This package is no longer supported. - arg@4.1.3: - resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} - arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} @@ -8912,9 +8869,6 @@ packages: create-hmac@1.1.7: resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} - create-require@1.1.1: - resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - crelt@1.0.6: resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==} @@ -9385,10 +9339,6 @@ packages: resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - diff@4.0.4: - resolution: {integrity: sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==} - engines: {node: '>=0.3.1'} - diff@5.2.2: resolution: {integrity: sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==} engines: {node: '>=0.3.1'} @@ -12260,9 +12210,6 @@ packages: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} - make-error@1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - makeerror@1.0.12: resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} @@ -14929,20 +14876,6 @@ packages: resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} engines: {node: '>=6.10'} - ts-node@10.9.2: - resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} - hasBin: true - peerDependencies: - '@swc/core': '>=1.2.50' - '@swc/wasm': '>=1.2.50' - '@types/node': '*' - typescript: '>=2.7' - peerDependenciesMeta: - '@swc/core': - optional: true - '@swc/wasm': - optional: true - tsconfig-paths@3.15.0: resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} @@ -15258,9 +15191,6 @@ packages: deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). hasBin: true - v8-compile-cache-lib@3.0.1: - resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} @@ -15829,10 +15759,6 @@ packages: resolution: {integrity: sha512-2OQsPNEmBCvXuFlIni/a+Rn+R2pHW9INm0BxXJ4hVDA8TirqMj+J/Rp9ItLatT/5pZqWwefVrTQcHpixsxnVlA==} engines: {node: '>= 4.0.0'} - yn@3.1.1: - resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} - engines: {node: '>=6'} - yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -17207,10 +17133,6 @@ snapshots: '@colors/colors@1.5.0': optional: true - '@cspotcode/source-map-support@0.8.1': - dependencies: - '@jridgewell/trace-mapping': 0.3.9 - '@csstools/color-helpers@5.1.0': {} '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': @@ -18494,11 +18416,6 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@jridgewell/trace-mapping@0.3.9': - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.5 - '@koa/cors@4.0.0': dependencies: vary: 1.1.2 @@ -19820,14 +19737,6 @@ snapshots: '@tsconfig/ember@3.0.1': {} - '@tsconfig/node10@1.0.12': {} - - '@tsconfig/node12@1.0.11': {} - - '@tsconfig/node14@1.0.3': {} - - '@tsconfig/node16@1.0.4': {} - '@tybys/wasm-util@0.10.2': dependencies: tslib: 2.8.1 @@ -20951,8 +20860,6 @@ snapshots: are-we-there-yet@4.0.2: {} - arg@4.1.3: {} - arg@5.0.2: {} argparse@2.0.1: {} @@ -22524,8 +22431,6 @@ snapshots: safe-buffer: 5.2.1 sha.js: 2.4.12 - create-require@1.1.1: {} - crelt@1.0.6: {} cron@3.5.0: @@ -23040,8 +22945,6 @@ snapshots: diff-sequences@29.6.3: {} - diff@4.0.4: {} - diff@5.2.2: {} diff@7.0.0: {} @@ -27352,8 +27255,6 @@ snapshots: dependencies: semver: 6.3.1 - make-error@1.3.6: {} - makeerror@1.0.12: dependencies: tmpl: 1.0.5 @@ -30479,24 +30380,6 @@ snapshots: ts-dedent@2.2.0: {} - ts-node@10.9.2(@types/node@24.12.4)(typescript@5.9.3): - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.12 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.4 - '@types/node': 24.12.4 - acorn: 8.16.0 - acorn-walk: 8.3.5 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.4 - make-error: 1.3.6 - typescript: 5.9.3 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - tsconfig-paths@3.15.0: dependencies: '@types/json5': 0.0.29 @@ -30770,8 +30653,6 @@ snapshots: uuid@9.0.1: {} - v8-compile-cache-lib@3.0.1: {} - validate-npm-package-license@3.0.4: dependencies: spdx-correct: 3.2.0 @@ -31440,8 +31321,6 @@ snapshots: ylru@1.4.0: {} - yn@3.1.1: {} - yocto-queue@0.1.0: {} yocto-queue@1.2.2: {}