From aa7f96aef6140f0399787be2b88ad6583c6881f0 Mon Sep 17 00:00:00 2001 From: Timothee Guerin Date: Thu, 3 Apr 2025 13:48:56 -0700 Subject: [PATCH 1/5] Scaffold init template package --- packages/compiler/package.json | 3 +- packages/init-templates/package.json | 56 +++++++ .../scripts/build.ts} | 4 +- .../scripts}/helpers.ts | 2 +- packages/init-templates/src/index.d.ts | 6 + packages/init-templates/src/index.js | 10 ++ .../__snapshots__/emitter-ts/.gitignore | 0 .../__snapshots__/emitter-ts/eslint.config.js | 0 .../__snapshots__/emitter-ts/package.json | 0 .../__snapshots__/emitter-ts/prettierrc.yaml | 0 .../__snapshots__/emitter-ts/src/emitter.ts | 0 .../__snapshots__/emitter-ts/src/index.ts | 0 .../__snapshots__/emitter-ts/src/lib.ts | 0 .../emitter-ts/src/testing/index.ts | 0 .../emitter-ts/test/hello.test.ts | 0 .../emitter-ts/test/test-host.ts | 0 .../__snapshots__/emitter-ts/tsconfig.json | 0 .../__snapshots__/library-ts/.gitignore | 0 .../__snapshots__/library-ts/eslint.config.js | 0 .../library-ts/lib/decorators.tsp | 0 .../__snapshots__/library-ts/lib/main.tsp | 0 .../__snapshots__/library-ts/package.json | 0 .../__snapshots__/library-ts/prettierrc.yaml | 0 .../library-ts/src/decorators.ts | 0 .../__snapshots__/library-ts/src/index.ts | 0 .../__snapshots__/library-ts/src/lib.ts | 0 .../__snapshots__/library-ts/src/linter.ts | 0 .../src/rules/no-interfaces.rule.ts | 0 .../library-ts/src/testing/index.ts | 0 .../library-ts/test/decorators.test.ts | 0 .../test/rules/no-interfaces.rule.test.ts | 0 .../library-ts/test/test-host.ts | 0 .../__snapshots__/library-ts/tsconfig.json | 0 .../templates/__snapshots__/rest/.gitignore | 0 .../templates/__snapshots__/rest/main.tsp | 0 .../templates/__snapshots__/rest/package.json | 0 .../__snapshots__/rest/tspconfig.yaml | 0 .../templates/emitter-ts/eslint.config.js | 0 .../templates/emitter-ts/package.json | 0 .../templates/emitter-ts/prettierrc.yaml | 0 .../templates/emitter-ts/src/emitter.ts | 0 .../templates/emitter-ts/src/index.ts | 0 .../templates/emitter-ts/src/lib.ts | 0 .../emitter-ts/src/testing/index.ts.mu | 0 .../templates/emitter-ts/test/hello.test.ts | 0 .../templates/emitter-ts/test/test-host.ts.mu | 0 .../templates/emitter-ts/tsconfig.json | 0 .../templates/library-ts/eslint.config.js | 0 .../library-ts/lib/decorators.tsp.mu | 0 .../templates/library-ts/lib/main.tsp | 0 .../templates/library-ts/package.json | 0 .../templates/library-ts/prettierrc.yaml | 0 .../templates/library-ts/src/decorators.ts | 0 .../templates/library-ts/src/index.ts | 0 .../templates/library-ts/src/lib.ts | 0 .../templates/library-ts/src/linter.ts | 0 .../src/rules/no-interfaces.rule.ts | 0 .../library-ts/src/testing/index.ts.mu | 0 .../library-ts/test/decorators.test.ts.mu | 0 .../test/rules/no-interfaces.rule.test.ts | 0 .../templates/library-ts/test/test-host.ts.mu | 0 .../templates/library-ts/tsconfig.json | 0 .../templates/rest/main.tsp | 0 .../templates/scaffolding.json | 0 .../init-templates/test/init-templates.e2e.ts | 147 ++++++++++++++++++ packages/init-templates/tsconfig.json | 14 ++ packages/init-templates/vitest.config.e2e.ts | 17 ++ pnpm-lock.yaml | 30 ++++ tsconfig.json | 2 +- 69 files changed, 285 insertions(+), 6 deletions(-) create mode 100644 packages/init-templates/package.json rename packages/{compiler/.scripts/build-init-templates.ts => init-templates/scripts/build.ts} (96%) rename packages/{compiler/.scripts => init-templates/scripts}/helpers.ts (96%) create mode 100644 packages/init-templates/src/index.d.ts create mode 100644 packages/init-templates/src/index.js rename packages/{compiler => init-templates}/templates/__snapshots__/emitter-ts/.gitignore (100%) rename packages/{compiler => init-templates}/templates/__snapshots__/emitter-ts/eslint.config.js (100%) rename packages/{compiler => init-templates}/templates/__snapshots__/emitter-ts/package.json (100%) rename packages/{compiler => init-templates}/templates/__snapshots__/emitter-ts/prettierrc.yaml (100%) rename packages/{compiler => init-templates}/templates/__snapshots__/emitter-ts/src/emitter.ts (100%) rename packages/{compiler => init-templates}/templates/__snapshots__/emitter-ts/src/index.ts (100%) rename packages/{compiler => init-templates}/templates/__snapshots__/emitter-ts/src/lib.ts (100%) rename packages/{compiler => init-templates}/templates/__snapshots__/emitter-ts/src/testing/index.ts (100%) rename packages/{compiler => init-templates}/templates/__snapshots__/emitter-ts/test/hello.test.ts (100%) rename packages/{compiler => init-templates}/templates/__snapshots__/emitter-ts/test/test-host.ts (100%) rename packages/{compiler => init-templates}/templates/__snapshots__/emitter-ts/tsconfig.json (100%) rename packages/{compiler => init-templates}/templates/__snapshots__/library-ts/.gitignore (100%) rename packages/{compiler => init-templates}/templates/__snapshots__/library-ts/eslint.config.js (100%) rename packages/{compiler => init-templates}/templates/__snapshots__/library-ts/lib/decorators.tsp (100%) rename packages/{compiler => init-templates}/templates/__snapshots__/library-ts/lib/main.tsp (100%) rename packages/{compiler => init-templates}/templates/__snapshots__/library-ts/package.json (100%) rename packages/{compiler => init-templates}/templates/__snapshots__/library-ts/prettierrc.yaml (100%) rename packages/{compiler => init-templates}/templates/__snapshots__/library-ts/src/decorators.ts (100%) rename packages/{compiler => init-templates}/templates/__snapshots__/library-ts/src/index.ts (100%) rename packages/{compiler => init-templates}/templates/__snapshots__/library-ts/src/lib.ts (100%) rename packages/{compiler => init-templates}/templates/__snapshots__/library-ts/src/linter.ts (100%) rename packages/{compiler => init-templates}/templates/__snapshots__/library-ts/src/rules/no-interfaces.rule.ts (100%) rename packages/{compiler => init-templates}/templates/__snapshots__/library-ts/src/testing/index.ts (100%) rename packages/{compiler => init-templates}/templates/__snapshots__/library-ts/test/decorators.test.ts (100%) rename packages/{compiler => init-templates}/templates/__snapshots__/library-ts/test/rules/no-interfaces.rule.test.ts (100%) rename packages/{compiler => init-templates}/templates/__snapshots__/library-ts/test/test-host.ts (100%) rename packages/{compiler => init-templates}/templates/__snapshots__/library-ts/tsconfig.json (100%) rename packages/{compiler => init-templates}/templates/__snapshots__/rest/.gitignore (100%) rename packages/{compiler => init-templates}/templates/__snapshots__/rest/main.tsp (100%) rename packages/{compiler => init-templates}/templates/__snapshots__/rest/package.json (100%) rename packages/{compiler => init-templates}/templates/__snapshots__/rest/tspconfig.yaml (100%) rename packages/{compiler => init-templates}/templates/emitter-ts/eslint.config.js (100%) rename packages/{compiler => init-templates}/templates/emitter-ts/package.json (100%) rename packages/{compiler => init-templates}/templates/emitter-ts/prettierrc.yaml (100%) rename packages/{compiler => init-templates}/templates/emitter-ts/src/emitter.ts (100%) rename packages/{compiler => init-templates}/templates/emitter-ts/src/index.ts (100%) rename packages/{compiler => init-templates}/templates/emitter-ts/src/lib.ts (100%) rename packages/{compiler => init-templates}/templates/emitter-ts/src/testing/index.ts.mu (100%) rename packages/{compiler => init-templates}/templates/emitter-ts/test/hello.test.ts (100%) rename packages/{compiler => init-templates}/templates/emitter-ts/test/test-host.ts.mu (100%) rename packages/{compiler => init-templates}/templates/emitter-ts/tsconfig.json (100%) rename packages/{compiler => init-templates}/templates/library-ts/eslint.config.js (100%) rename packages/{compiler => init-templates}/templates/library-ts/lib/decorators.tsp.mu (100%) rename packages/{compiler => init-templates}/templates/library-ts/lib/main.tsp (100%) rename packages/{compiler => init-templates}/templates/library-ts/package.json (100%) rename packages/{compiler => init-templates}/templates/library-ts/prettierrc.yaml (100%) rename packages/{compiler => init-templates}/templates/library-ts/src/decorators.ts (100%) rename packages/{compiler => init-templates}/templates/library-ts/src/index.ts (100%) rename packages/{compiler => init-templates}/templates/library-ts/src/lib.ts (100%) rename packages/{compiler => init-templates}/templates/library-ts/src/linter.ts (100%) rename packages/{compiler => init-templates}/templates/library-ts/src/rules/no-interfaces.rule.ts (100%) rename packages/{compiler => init-templates}/templates/library-ts/src/testing/index.ts.mu (100%) rename packages/{compiler => init-templates}/templates/library-ts/test/decorators.test.ts.mu (100%) rename packages/{compiler => init-templates}/templates/library-ts/test/rules/no-interfaces.rule.test.ts (100%) rename packages/{compiler => init-templates}/templates/library-ts/test/test-host.ts.mu (100%) rename packages/{compiler => init-templates}/templates/library-ts/tsconfig.json (100%) rename packages/{compiler => init-templates}/templates/rest/main.tsp (100%) rename packages/{compiler => init-templates}/templates/scaffolding.json (100%) create mode 100644 packages/init-templates/test/init-templates.e2e.ts create mode 100644 packages/init-templates/tsconfig.json create mode 100644 packages/init-templates/vitest.config.e2e.ts diff --git a/packages/compiler/package.json b/packages/compiler/package.json index 4c4b9adcc9d..4120165fbc9 100644 --- a/packages/compiler/package.json +++ b/packages/compiler/package.json @@ -77,8 +77,7 @@ ], "scripts": { "clean": "rimraf ./dist ./temp", - "build:init-templates-index": "tsx ./.scripts/build-init-templates.ts", - "build": "pnpm gen-manifest && pnpm build:init-templates-index && pnpm compile && pnpm generate-tmlanguage", + "build": "pnpm gen-manifest && pnpm compile && pnpm generate-tmlanguage", "api-extractor": "api-extractor run --local --verbose", "compile": "tsc -p .", "watch": "tsc -p . --watch", diff --git a/packages/init-templates/package.json b/packages/init-templates/package.json new file mode 100644 index 00000000000..38670105c9f --- /dev/null +++ b/packages/init-templates/package.json @@ -0,0 +1,56 @@ +{ + "name": "@typespec/init-templates", + "version": "0.68.0", + "author": "Microsoft Corporation", + "description": "TypeSpec init templates", + "homepage": "https://typespec.io", + "readme": "https://github.com/microsoft/typespec/blob/main/README.md", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/microsoft/typespec.git" + }, + "bugs": { + "url": "https://github.com/microsoft/typespec/issues" + }, + "keywords": [ + "typespec" + ], + "type": "module", + "exports": { + ".": { + "import": "./src/index.js" + } + }, + "engines": { + "node": ">=20.0.0" + }, + "scripts": { + "clean": "rimraf ./dist ./temp", + "build": "tsx ./.scripts/build-init-templates.ts", + "test": "vitest run", + "test:watch": "vitest -w", + "test:ui": "vitest --ui", + "test-official": "vitest run --coverage --reporter=junit --reporter=default --no-file-parallelism", + "test:e2e": "vitest run --config ./vitest.config.e2e.ts", + "lint": "eslint . --ext .ts --max-warnings=0", + "lint:fix": "eslint . --fix --ext .ts" + }, + "files": [ + "lib/*.tsp", + "dist/**", + "!dist/test/**" + ], + "//": "IMPORTANT THIS PACKAGE CANNOT HAVE A DEPENDENCY", + "devDependencies": { + "@types/node": "~22.13.11", + "@typespec/compiler": "workspace:^", + "@vitest/coverage-v8": "^3.0.9", + "@vitest/ui": "^3.0.9", + "c8": "^10.1.3", + "pathe": "^2.0.3", + "rimraf": "~6.0.1", + "typescript": "~5.8.2", + "vitest": "^3.0.9" + } +} diff --git a/packages/compiler/.scripts/build-init-templates.ts b/packages/init-templates/scripts/build.ts similarity index 96% rename from packages/compiler/.scripts/build-init-templates.ts rename to packages/init-templates/scripts/build.ts index 81616030a90..0952f9bf7ab 100644 --- a/packages/compiler/.scripts/build-init-templates.ts +++ b/packages/init-templates/scripts/build.ts @@ -1,6 +1,6 @@ import { mkdir, readFile, writeFile } from "fs/promises"; -import { resolve } from "path/posix"; -import type { InitTemplate } from "../src/init/init-template.js"; +import { resolve } from "pathe"; +import type { InitTemplate } from "../../compiler/src/init/init-template.js"; import { localDir, packageRoot } from "./helpers.js"; const pkgJson = JSON.parse( diff --git a/packages/compiler/.scripts/helpers.ts b/packages/init-templates/scripts/helpers.ts similarity index 96% rename from packages/compiler/.scripts/helpers.ts rename to packages/init-templates/scripts/helpers.ts index df8e5a023c8..0878fa498b8 100644 --- a/packages/compiler/.scripts/helpers.ts +++ b/packages/init-templates/scripts/helpers.ts @@ -1,6 +1,6 @@ import { readdir } from "fs/promises"; import { dirname } from "path"; -import { join, resolve } from "path/posix"; +import { join, resolve } from "pathe"; import { fileURLToPath } from "url"; export const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), ".."); diff --git a/packages/init-templates/src/index.d.ts b/packages/init-templates/src/index.d.ts new file mode 100644 index 00000000000..568e1441365 --- /dev/null +++ b/packages/init-templates/src/index.d.ts @@ -0,0 +1,6 @@ +declare const _default: { + readonly baseUri: string; + readonly templates: Record; +}; + +export default _default; diff --git a/packages/init-templates/src/index.js b/packages/init-templates/src/index.js new file mode 100644 index 00000000000..f60ecd69f60 --- /dev/null +++ b/packages/init-templates/src/index.js @@ -0,0 +1,10 @@ +// @ts-check +import { resolve } from "path"; +import scaffoldingJson from "../templates/scaffolding.json" with { type: "json" }; + +export const templatesDir = resolve(import.meta.dirname, "../templates").replace(/\\/g, "/"); + +export default { + baseUri: templatesDir, + templates: scaffoldingJson, +}; diff --git a/packages/compiler/templates/__snapshots__/emitter-ts/.gitignore b/packages/init-templates/templates/__snapshots__/emitter-ts/.gitignore similarity index 100% rename from packages/compiler/templates/__snapshots__/emitter-ts/.gitignore rename to packages/init-templates/templates/__snapshots__/emitter-ts/.gitignore diff --git a/packages/compiler/templates/__snapshots__/emitter-ts/eslint.config.js b/packages/init-templates/templates/__snapshots__/emitter-ts/eslint.config.js similarity index 100% rename from packages/compiler/templates/__snapshots__/emitter-ts/eslint.config.js rename to packages/init-templates/templates/__snapshots__/emitter-ts/eslint.config.js diff --git a/packages/compiler/templates/__snapshots__/emitter-ts/package.json b/packages/init-templates/templates/__snapshots__/emitter-ts/package.json similarity index 100% rename from packages/compiler/templates/__snapshots__/emitter-ts/package.json rename to packages/init-templates/templates/__snapshots__/emitter-ts/package.json diff --git a/packages/compiler/templates/__snapshots__/emitter-ts/prettierrc.yaml b/packages/init-templates/templates/__snapshots__/emitter-ts/prettierrc.yaml similarity index 100% rename from packages/compiler/templates/__snapshots__/emitter-ts/prettierrc.yaml rename to packages/init-templates/templates/__snapshots__/emitter-ts/prettierrc.yaml diff --git a/packages/compiler/templates/__snapshots__/emitter-ts/src/emitter.ts b/packages/init-templates/templates/__snapshots__/emitter-ts/src/emitter.ts similarity index 100% rename from packages/compiler/templates/__snapshots__/emitter-ts/src/emitter.ts rename to packages/init-templates/templates/__snapshots__/emitter-ts/src/emitter.ts diff --git a/packages/compiler/templates/__snapshots__/emitter-ts/src/index.ts b/packages/init-templates/templates/__snapshots__/emitter-ts/src/index.ts similarity index 100% rename from packages/compiler/templates/__snapshots__/emitter-ts/src/index.ts rename to packages/init-templates/templates/__snapshots__/emitter-ts/src/index.ts diff --git a/packages/compiler/templates/__snapshots__/emitter-ts/src/lib.ts b/packages/init-templates/templates/__snapshots__/emitter-ts/src/lib.ts similarity index 100% rename from packages/compiler/templates/__snapshots__/emitter-ts/src/lib.ts rename to packages/init-templates/templates/__snapshots__/emitter-ts/src/lib.ts diff --git a/packages/compiler/templates/__snapshots__/emitter-ts/src/testing/index.ts b/packages/init-templates/templates/__snapshots__/emitter-ts/src/testing/index.ts similarity index 100% rename from packages/compiler/templates/__snapshots__/emitter-ts/src/testing/index.ts rename to packages/init-templates/templates/__snapshots__/emitter-ts/src/testing/index.ts diff --git a/packages/compiler/templates/__snapshots__/emitter-ts/test/hello.test.ts b/packages/init-templates/templates/__snapshots__/emitter-ts/test/hello.test.ts similarity index 100% rename from packages/compiler/templates/__snapshots__/emitter-ts/test/hello.test.ts rename to packages/init-templates/templates/__snapshots__/emitter-ts/test/hello.test.ts diff --git a/packages/compiler/templates/__snapshots__/emitter-ts/test/test-host.ts b/packages/init-templates/templates/__snapshots__/emitter-ts/test/test-host.ts similarity index 100% rename from packages/compiler/templates/__snapshots__/emitter-ts/test/test-host.ts rename to packages/init-templates/templates/__snapshots__/emitter-ts/test/test-host.ts diff --git a/packages/compiler/templates/__snapshots__/emitter-ts/tsconfig.json b/packages/init-templates/templates/__snapshots__/emitter-ts/tsconfig.json similarity index 100% rename from packages/compiler/templates/__snapshots__/emitter-ts/tsconfig.json rename to packages/init-templates/templates/__snapshots__/emitter-ts/tsconfig.json diff --git a/packages/compiler/templates/__snapshots__/library-ts/.gitignore b/packages/init-templates/templates/__snapshots__/library-ts/.gitignore similarity index 100% rename from packages/compiler/templates/__snapshots__/library-ts/.gitignore rename to packages/init-templates/templates/__snapshots__/library-ts/.gitignore diff --git a/packages/compiler/templates/__snapshots__/library-ts/eslint.config.js b/packages/init-templates/templates/__snapshots__/library-ts/eslint.config.js similarity index 100% rename from packages/compiler/templates/__snapshots__/library-ts/eslint.config.js rename to packages/init-templates/templates/__snapshots__/library-ts/eslint.config.js diff --git a/packages/compiler/templates/__snapshots__/library-ts/lib/decorators.tsp b/packages/init-templates/templates/__snapshots__/library-ts/lib/decorators.tsp similarity index 100% rename from packages/compiler/templates/__snapshots__/library-ts/lib/decorators.tsp rename to packages/init-templates/templates/__snapshots__/library-ts/lib/decorators.tsp diff --git a/packages/compiler/templates/__snapshots__/library-ts/lib/main.tsp b/packages/init-templates/templates/__snapshots__/library-ts/lib/main.tsp similarity index 100% rename from packages/compiler/templates/__snapshots__/library-ts/lib/main.tsp rename to packages/init-templates/templates/__snapshots__/library-ts/lib/main.tsp diff --git a/packages/compiler/templates/__snapshots__/library-ts/package.json b/packages/init-templates/templates/__snapshots__/library-ts/package.json similarity index 100% rename from packages/compiler/templates/__snapshots__/library-ts/package.json rename to packages/init-templates/templates/__snapshots__/library-ts/package.json diff --git a/packages/compiler/templates/__snapshots__/library-ts/prettierrc.yaml b/packages/init-templates/templates/__snapshots__/library-ts/prettierrc.yaml similarity index 100% rename from packages/compiler/templates/__snapshots__/library-ts/prettierrc.yaml rename to packages/init-templates/templates/__snapshots__/library-ts/prettierrc.yaml diff --git a/packages/compiler/templates/__snapshots__/library-ts/src/decorators.ts b/packages/init-templates/templates/__snapshots__/library-ts/src/decorators.ts similarity index 100% rename from packages/compiler/templates/__snapshots__/library-ts/src/decorators.ts rename to packages/init-templates/templates/__snapshots__/library-ts/src/decorators.ts diff --git a/packages/compiler/templates/__snapshots__/library-ts/src/index.ts b/packages/init-templates/templates/__snapshots__/library-ts/src/index.ts similarity index 100% rename from packages/compiler/templates/__snapshots__/library-ts/src/index.ts rename to packages/init-templates/templates/__snapshots__/library-ts/src/index.ts diff --git a/packages/compiler/templates/__snapshots__/library-ts/src/lib.ts b/packages/init-templates/templates/__snapshots__/library-ts/src/lib.ts similarity index 100% rename from packages/compiler/templates/__snapshots__/library-ts/src/lib.ts rename to packages/init-templates/templates/__snapshots__/library-ts/src/lib.ts diff --git a/packages/compiler/templates/__snapshots__/library-ts/src/linter.ts b/packages/init-templates/templates/__snapshots__/library-ts/src/linter.ts similarity index 100% rename from packages/compiler/templates/__snapshots__/library-ts/src/linter.ts rename to packages/init-templates/templates/__snapshots__/library-ts/src/linter.ts diff --git a/packages/compiler/templates/__snapshots__/library-ts/src/rules/no-interfaces.rule.ts b/packages/init-templates/templates/__snapshots__/library-ts/src/rules/no-interfaces.rule.ts similarity index 100% rename from packages/compiler/templates/__snapshots__/library-ts/src/rules/no-interfaces.rule.ts rename to packages/init-templates/templates/__snapshots__/library-ts/src/rules/no-interfaces.rule.ts diff --git a/packages/compiler/templates/__snapshots__/library-ts/src/testing/index.ts b/packages/init-templates/templates/__snapshots__/library-ts/src/testing/index.ts similarity index 100% rename from packages/compiler/templates/__snapshots__/library-ts/src/testing/index.ts rename to packages/init-templates/templates/__snapshots__/library-ts/src/testing/index.ts diff --git a/packages/compiler/templates/__snapshots__/library-ts/test/decorators.test.ts b/packages/init-templates/templates/__snapshots__/library-ts/test/decorators.test.ts similarity index 100% rename from packages/compiler/templates/__snapshots__/library-ts/test/decorators.test.ts rename to packages/init-templates/templates/__snapshots__/library-ts/test/decorators.test.ts diff --git a/packages/compiler/templates/__snapshots__/library-ts/test/rules/no-interfaces.rule.test.ts b/packages/init-templates/templates/__snapshots__/library-ts/test/rules/no-interfaces.rule.test.ts similarity index 100% rename from packages/compiler/templates/__snapshots__/library-ts/test/rules/no-interfaces.rule.test.ts rename to packages/init-templates/templates/__snapshots__/library-ts/test/rules/no-interfaces.rule.test.ts diff --git a/packages/compiler/templates/__snapshots__/library-ts/test/test-host.ts b/packages/init-templates/templates/__snapshots__/library-ts/test/test-host.ts similarity index 100% rename from packages/compiler/templates/__snapshots__/library-ts/test/test-host.ts rename to packages/init-templates/templates/__snapshots__/library-ts/test/test-host.ts diff --git a/packages/compiler/templates/__snapshots__/library-ts/tsconfig.json b/packages/init-templates/templates/__snapshots__/library-ts/tsconfig.json similarity index 100% rename from packages/compiler/templates/__snapshots__/library-ts/tsconfig.json rename to packages/init-templates/templates/__snapshots__/library-ts/tsconfig.json diff --git a/packages/compiler/templates/__snapshots__/rest/.gitignore b/packages/init-templates/templates/__snapshots__/rest/.gitignore similarity index 100% rename from packages/compiler/templates/__snapshots__/rest/.gitignore rename to packages/init-templates/templates/__snapshots__/rest/.gitignore diff --git a/packages/compiler/templates/__snapshots__/rest/main.tsp b/packages/init-templates/templates/__snapshots__/rest/main.tsp similarity index 100% rename from packages/compiler/templates/__snapshots__/rest/main.tsp rename to packages/init-templates/templates/__snapshots__/rest/main.tsp diff --git a/packages/compiler/templates/__snapshots__/rest/package.json b/packages/init-templates/templates/__snapshots__/rest/package.json similarity index 100% rename from packages/compiler/templates/__snapshots__/rest/package.json rename to packages/init-templates/templates/__snapshots__/rest/package.json diff --git a/packages/compiler/templates/__snapshots__/rest/tspconfig.yaml b/packages/init-templates/templates/__snapshots__/rest/tspconfig.yaml similarity index 100% rename from packages/compiler/templates/__snapshots__/rest/tspconfig.yaml rename to packages/init-templates/templates/__snapshots__/rest/tspconfig.yaml diff --git a/packages/compiler/templates/emitter-ts/eslint.config.js b/packages/init-templates/templates/emitter-ts/eslint.config.js similarity index 100% rename from packages/compiler/templates/emitter-ts/eslint.config.js rename to packages/init-templates/templates/emitter-ts/eslint.config.js diff --git a/packages/compiler/templates/emitter-ts/package.json b/packages/init-templates/templates/emitter-ts/package.json similarity index 100% rename from packages/compiler/templates/emitter-ts/package.json rename to packages/init-templates/templates/emitter-ts/package.json diff --git a/packages/compiler/templates/emitter-ts/prettierrc.yaml b/packages/init-templates/templates/emitter-ts/prettierrc.yaml similarity index 100% rename from packages/compiler/templates/emitter-ts/prettierrc.yaml rename to packages/init-templates/templates/emitter-ts/prettierrc.yaml diff --git a/packages/compiler/templates/emitter-ts/src/emitter.ts b/packages/init-templates/templates/emitter-ts/src/emitter.ts similarity index 100% rename from packages/compiler/templates/emitter-ts/src/emitter.ts rename to packages/init-templates/templates/emitter-ts/src/emitter.ts diff --git a/packages/compiler/templates/emitter-ts/src/index.ts b/packages/init-templates/templates/emitter-ts/src/index.ts similarity index 100% rename from packages/compiler/templates/emitter-ts/src/index.ts rename to packages/init-templates/templates/emitter-ts/src/index.ts diff --git a/packages/compiler/templates/emitter-ts/src/lib.ts b/packages/init-templates/templates/emitter-ts/src/lib.ts similarity index 100% rename from packages/compiler/templates/emitter-ts/src/lib.ts rename to packages/init-templates/templates/emitter-ts/src/lib.ts diff --git a/packages/compiler/templates/emitter-ts/src/testing/index.ts.mu b/packages/init-templates/templates/emitter-ts/src/testing/index.ts.mu similarity index 100% rename from packages/compiler/templates/emitter-ts/src/testing/index.ts.mu rename to packages/init-templates/templates/emitter-ts/src/testing/index.ts.mu diff --git a/packages/compiler/templates/emitter-ts/test/hello.test.ts b/packages/init-templates/templates/emitter-ts/test/hello.test.ts similarity index 100% rename from packages/compiler/templates/emitter-ts/test/hello.test.ts rename to packages/init-templates/templates/emitter-ts/test/hello.test.ts diff --git a/packages/compiler/templates/emitter-ts/test/test-host.ts.mu b/packages/init-templates/templates/emitter-ts/test/test-host.ts.mu similarity index 100% rename from packages/compiler/templates/emitter-ts/test/test-host.ts.mu rename to packages/init-templates/templates/emitter-ts/test/test-host.ts.mu diff --git a/packages/compiler/templates/emitter-ts/tsconfig.json b/packages/init-templates/templates/emitter-ts/tsconfig.json similarity index 100% rename from packages/compiler/templates/emitter-ts/tsconfig.json rename to packages/init-templates/templates/emitter-ts/tsconfig.json diff --git a/packages/compiler/templates/library-ts/eslint.config.js b/packages/init-templates/templates/library-ts/eslint.config.js similarity index 100% rename from packages/compiler/templates/library-ts/eslint.config.js rename to packages/init-templates/templates/library-ts/eslint.config.js diff --git a/packages/compiler/templates/library-ts/lib/decorators.tsp.mu b/packages/init-templates/templates/library-ts/lib/decorators.tsp.mu similarity index 100% rename from packages/compiler/templates/library-ts/lib/decorators.tsp.mu rename to packages/init-templates/templates/library-ts/lib/decorators.tsp.mu diff --git a/packages/compiler/templates/library-ts/lib/main.tsp b/packages/init-templates/templates/library-ts/lib/main.tsp similarity index 100% rename from packages/compiler/templates/library-ts/lib/main.tsp rename to packages/init-templates/templates/library-ts/lib/main.tsp diff --git a/packages/compiler/templates/library-ts/package.json b/packages/init-templates/templates/library-ts/package.json similarity index 100% rename from packages/compiler/templates/library-ts/package.json rename to packages/init-templates/templates/library-ts/package.json diff --git a/packages/compiler/templates/library-ts/prettierrc.yaml b/packages/init-templates/templates/library-ts/prettierrc.yaml similarity index 100% rename from packages/compiler/templates/library-ts/prettierrc.yaml rename to packages/init-templates/templates/library-ts/prettierrc.yaml diff --git a/packages/compiler/templates/library-ts/src/decorators.ts b/packages/init-templates/templates/library-ts/src/decorators.ts similarity index 100% rename from packages/compiler/templates/library-ts/src/decorators.ts rename to packages/init-templates/templates/library-ts/src/decorators.ts diff --git a/packages/compiler/templates/library-ts/src/index.ts b/packages/init-templates/templates/library-ts/src/index.ts similarity index 100% rename from packages/compiler/templates/library-ts/src/index.ts rename to packages/init-templates/templates/library-ts/src/index.ts diff --git a/packages/compiler/templates/library-ts/src/lib.ts b/packages/init-templates/templates/library-ts/src/lib.ts similarity index 100% rename from packages/compiler/templates/library-ts/src/lib.ts rename to packages/init-templates/templates/library-ts/src/lib.ts diff --git a/packages/compiler/templates/library-ts/src/linter.ts b/packages/init-templates/templates/library-ts/src/linter.ts similarity index 100% rename from packages/compiler/templates/library-ts/src/linter.ts rename to packages/init-templates/templates/library-ts/src/linter.ts diff --git a/packages/compiler/templates/library-ts/src/rules/no-interfaces.rule.ts b/packages/init-templates/templates/library-ts/src/rules/no-interfaces.rule.ts similarity index 100% rename from packages/compiler/templates/library-ts/src/rules/no-interfaces.rule.ts rename to packages/init-templates/templates/library-ts/src/rules/no-interfaces.rule.ts diff --git a/packages/compiler/templates/library-ts/src/testing/index.ts.mu b/packages/init-templates/templates/library-ts/src/testing/index.ts.mu similarity index 100% rename from packages/compiler/templates/library-ts/src/testing/index.ts.mu rename to packages/init-templates/templates/library-ts/src/testing/index.ts.mu diff --git a/packages/compiler/templates/library-ts/test/decorators.test.ts.mu b/packages/init-templates/templates/library-ts/test/decorators.test.ts.mu similarity index 100% rename from packages/compiler/templates/library-ts/test/decorators.test.ts.mu rename to packages/init-templates/templates/library-ts/test/decorators.test.ts.mu diff --git a/packages/compiler/templates/library-ts/test/rules/no-interfaces.rule.test.ts b/packages/init-templates/templates/library-ts/test/rules/no-interfaces.rule.test.ts similarity index 100% rename from packages/compiler/templates/library-ts/test/rules/no-interfaces.rule.test.ts rename to packages/init-templates/templates/library-ts/test/rules/no-interfaces.rule.test.ts diff --git a/packages/compiler/templates/library-ts/test/test-host.ts.mu b/packages/init-templates/templates/library-ts/test/test-host.ts.mu similarity index 100% rename from packages/compiler/templates/library-ts/test/test-host.ts.mu rename to packages/init-templates/templates/library-ts/test/test-host.ts.mu diff --git a/packages/compiler/templates/library-ts/tsconfig.json b/packages/init-templates/templates/library-ts/tsconfig.json similarity index 100% rename from packages/compiler/templates/library-ts/tsconfig.json rename to packages/init-templates/templates/library-ts/tsconfig.json diff --git a/packages/compiler/templates/rest/main.tsp b/packages/init-templates/templates/rest/main.tsp similarity index 100% rename from packages/compiler/templates/rest/main.tsp rename to packages/init-templates/templates/rest/main.tsp diff --git a/packages/compiler/templates/scaffolding.json b/packages/init-templates/templates/scaffolding.json similarity index 100% rename from packages/compiler/templates/scaffolding.json rename to packages/init-templates/templates/scaffolding.json diff --git a/packages/init-templates/test/init-templates.e2e.ts b/packages/init-templates/test/init-templates.e2e.ts new file mode 100644 index 00000000000..7232d83722e --- /dev/null +++ b/packages/init-templates/test/init-templates.e2e.ts @@ -0,0 +1,147 @@ +// Enable calling @typespec/compiler/internals for the init logic +(globalThis as any).enableCompilerInternalsExport = true; +import { NodeHost } from "@typespec/compiler"; +import typeSpecCoreTemplates from "@typespec/init-templates"; +import { ok } from "assert"; +import { type SpawnOptions, spawn } from "child_process"; +import { rm } from "fs/promises"; +import { dirname, resolve } from "pathe"; +import { fileURLToPath } from "url"; +import { beforeAll, describe, it } from "vitest"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const testTempRoot = resolve(__dirname, "../../temp/scaffolded-template-tests"); +const snapshotFolder = resolve(__dirname, "../../templates/__snapshots__"); + +async function execAsync( + command: string, + args: string[] = [], + options: SpawnOptions = {}, +): Promise<{ exitCode: number; stdio: string; stdout: string; stderr: string; proc: any }> { + const child = spawn(command, args, options); + + return new Promise((resolve, reject) => { + child.on("error", (error) => { + reject(error); + }); + const stdio: Buffer[] = []; + const stdout: Buffer[] = []; + const stderr: Buffer[] = []; + child.stdout?.on("data", (data) => { + stdout.push(data); + stdio.push(data); + }); + child.stderr?.on("data", (data) => { + stderr.push(data); + stdio.push(data); + }); + + child.on("exit", (exitCode) => { + resolve({ + exitCode: exitCode ?? -1, + stdio: Buffer.concat(stdio).toString(), + stdout: Buffer.concat(stdout).toString(), + stderr: Buffer.concat(stderr).toString(), + proc: child, + }); + }); + }); +} + +interface ScaffoldedTemplateFixture { + /** Directory where the template was created. */ + readonly directory: string; + readonly checkCommand: ( + command: string, + args?: string[], + options?: SpawnOptions, + ) => Promise; +} + +describe("Init templates e2e tests", () => { + beforeAll(async () => { + await rm(testTempRoot, { recursive: true, force: true }); + }); + + async function scaffoldTemplateTo(name: string, targetFolder: string) { + const { makeScaffoldingConfig, scaffoldNewProject } = await import( + "@typespec/compiler/internals" + ); + + const template = typeSpecCoreTemplates.templates[name]; + ok(template, `Template '${name}' not found`); + await scaffoldNewProject( + NodeHost, + makeScaffoldingConfig(template, { + name, + directory: targetFolder, + baseUri: typeSpecCoreTemplates.baseUri, + }), + ); + } + async function scaffoldTemplateSnapshot(name: string): Promise { + await scaffoldTemplateTo(name, resolve(snapshotFolder, name)); + } + + async function scaffoldTemplateForTest(name: string): Promise { + const targetFolder = resolve(testTempRoot, name); + await scaffoldTemplateTo(name, targetFolder); + + return { + directory: targetFolder, + checkCommand: async (command: string, args: string[] = [], options: SpawnOptions = {}) => { + const xplatCmd = process.platform === "win32" ? `${command}.cmd` : command; + const shell = process.platform === "win32" ? true : options.shell; + const result = await execAsync(xplatCmd, args, { + shell, + ...options, + cwd: targetFolder, + }); + ok( + result.exitCode === 0, + [ + `Command '${command} ${args.join(" ")}' failed with exit code ${result.exitCode}`, + "-".repeat(100), + result.stdio, + "-".repeat(100), + ].join("\n"), + ); + }, + }; + } + + describe("create templates", () => { + beforeAll(async () => { + await rm(snapshotFolder, { recursive: true, force: true }); + }); + + it("rest", () => scaffoldTemplateSnapshot("rest")); + it("emitter-ts", () => scaffoldTemplateSnapshot("emitter-ts")); + it("library-ts", () => scaffoldTemplateSnapshot("library-ts")); + }); + + describe("validate templates", () => { + it("validate rest template", async () => { + const fixture = await scaffoldTemplateForTest("rest"); + await fixture.checkCommand("npm", ["install"]); + await fixture.checkCommand("npx", ["tsp", "compile", "."]); + }); + it("validate emitter-ts template", async () => { + const fixture = await scaffoldTemplateForTest("emitter-ts"); + await fixture.checkCommand("npm", ["install"]); + await fixture.checkCommand("npm", ["run", "build"]); + await fixture.checkCommand("npm", ["run", "test"]); + await fixture.checkCommand("npm", ["run", "lint"]); + await fixture.checkCommand("npm", ["run", "format"]); + }); + + it("validate library-ts template", async () => { + const fixture = await scaffoldTemplateForTest("library-ts"); + await fixture.checkCommand("npm", ["install"]); + await fixture.checkCommand("npm", ["run", "build"]); + await fixture.checkCommand("npm", ["run", "test"]); + await fixture.checkCommand("npm", ["run", "lint"]); + await fixture.checkCommand("npm", ["run", "format"]); + }); + }); +}); diff --git a/packages/init-templates/tsconfig.json b/packages/init-templates/tsconfig.json new file mode 100644 index 00000000000..c7d879f54c8 --- /dev/null +++ b/packages/init-templates/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "dist", + "tsBuildInfoFile": ".temp/.tsbuildinfo", + "verbatimModuleSyntax": true + }, + "include": [ + "src/**/*.ts", + "test/**/*.ts", + "scripts/**/*.ts", + "../compiler/src/init/init-template.ts" +, "src/index.js" ], +} diff --git a/packages/init-templates/vitest.config.e2e.ts b/packages/init-templates/vitest.config.e2e.ts new file mode 100644 index 00000000000..e0189885e63 --- /dev/null +++ b/packages/init-templates/vitest.config.e2e.ts @@ -0,0 +1,17 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + environment: "node", + testTimeout: 90_000, + isolate: false, + coverage: { + reporter: ["cobertura", "json", "text"], + }, + outputFile: { + junit: "./test-results.xml", + }, + + include: ["test/**/*.e2e.ts"], + }, +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b3b2bc28d68..5264b20a1f4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1029,6 +1029,36 @@ importers: specifier: ~5.8.2 version: 5.8.2 + packages/init-templates: + devDependencies: + '@types/node': + specifier: ~22.13.11 + version: 22.13.13 + '@typespec/compiler': + specifier: workspace:^ + version: link:../compiler + '@vitest/coverage-v8': + specifier: ^3.0.9 + version: 3.0.9(vitest@3.0.9(@types/debug@4.1.12)(@types/node@22.13.13)(@vitest/ui@3.0.9)(happy-dom@17.4.4)(jsdom@25.0.1)(tsx@4.19.3)(yaml@2.7.0)) + '@vitest/ui': + specifier: ^3.0.9 + version: 3.0.9(vitest@3.0.9) + c8: + specifier: ^10.1.3 + version: 10.1.3 + pathe: + specifier: ^2.0.3 + version: 2.0.3 + rimraf: + specifier: ~6.0.1 + version: 6.0.1 + typescript: + specifier: ~5.8.2 + version: 5.8.2 + vitest: + specifier: ^3.0.9 + version: 3.0.9(@types/debug@4.1.12)(@types/node@22.13.13)(@vitest/ui@3.0.9)(happy-dom@17.4.4)(jsdom@25.0.1)(tsx@4.19.3)(yaml@2.7.0) + packages/internal-build-utils: dependencies: '@pnpm/workspace.find-packages': diff --git a/tsconfig.json b/tsconfig.json index 7c25fb20eaf..cc72ba9aeb4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,6 +6,6 @@ "**/.storybook/**/*.ts", "**/.storybook/**/*.tsx", "eng/tsp-core/scripts/resolve-cli-artifacts.js" - ], +, "packages/init-templates/src/index.js" ], "exclude": ["**/node_modules/", "**/dist/", "**/build/", "**/coverage/"] } From 35d6e593b1a1ccabcca9d4824eed1877937da1d4 Mon Sep 17 00:00:00 2001 From: Timothee Guerin Date: Thu, 3 Apr 2025 13:52:12 -0700 Subject: [PATCH 2/5] Fix e2e testss --- packages/init-templates/package.json | 5 +---- packages/init-templates/test/init-templates.e2e.ts | 9 ++++----- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/packages/init-templates/package.json b/packages/init-templates/package.json index 38670105c9f..51914c2a0a6 100644 --- a/packages/init-templates/package.json +++ b/packages/init-templates/package.json @@ -28,10 +28,7 @@ "scripts": { "clean": "rimraf ./dist ./temp", "build": "tsx ./.scripts/build-init-templates.ts", - "test": "vitest run", - "test:watch": "vitest -w", - "test:ui": "vitest --ui", - "test-official": "vitest run --coverage --reporter=junit --reporter=default --no-file-parallelism", + "test": "pnpm test:e2e", "test:e2e": "vitest run --config ./vitest.config.e2e.ts", "lint": "eslint . --ext .ts --max-warnings=0", "lint:fix": "eslint . --fix --ext .ts" diff --git a/packages/init-templates/test/init-templates.e2e.ts b/packages/init-templates/test/init-templates.e2e.ts index 7232d83722e..64b15ad7ade 100644 --- a/packages/init-templates/test/init-templates.e2e.ts +++ b/packages/init-templates/test/init-templates.e2e.ts @@ -5,13 +5,12 @@ import typeSpecCoreTemplates from "@typespec/init-templates"; import { ok } from "assert"; import { type SpawnOptions, spawn } from "child_process"; import { rm } from "fs/promises"; -import { dirname, resolve } from "pathe"; -import { fileURLToPath } from "url"; +import { resolve } from "pathe"; import { beforeAll, describe, it } from "vitest"; -const __dirname = dirname(fileURLToPath(import.meta.url)); -const testTempRoot = resolve(__dirname, "../../temp/scaffolded-template-tests"); -const snapshotFolder = resolve(__dirname, "../../templates/__snapshots__"); +const projectRoot = resolve(import.meta.dirname, ".."); +const testTempRoot = resolve(projectRoot, "temp/scaffolded-template-tests"); +const snapshotFolder = resolve(projectRoot, "templates/__snapshots__"); async function execAsync( command: string, From c1cfed18198dab9782b9c88a5c4c000c9361fa97 Mon Sep 17 00:00:00 2001 From: Timothee Guerin Date: Thu, 3 Apr 2025 14:00:47 -0700 Subject: [PATCH 3/5] fix build --- packages/compiler/src/init/core-templates.ts | 16 +--------------- packages/init-templates/package.json | 2 +- packages/init-templates/scripts/build.ts | 10 ++++------ 3 files changed, 6 insertions(+), 22 deletions(-) diff --git a/packages/compiler/src/init/core-templates.ts b/packages/compiler/src/init/core-templates.ts index 8e9f3ab45cb..c93c28d4505 100644 --- a/packages/compiler/src/init/core-templates.ts +++ b/packages/compiler/src/init/core-templates.ts @@ -1,22 +1,8 @@ -import { CompilerPackageRoot } from "../core/node-host.js"; -import { resolvePath } from "../core/path-utils.js"; import type { SystemHost } from "../core/types.js"; -export const templatesDir = resolvePath(CompilerPackageRoot, "templates"); export interface LoadedCoreTemplates { readonly baseUri: string; readonly templates: Record; } -let typeSpecCoreTemplates: LoadedCoreTemplates | undefined; -export async function getTypeSpecCoreTemplates(host: SystemHost): Promise { - if (typeSpecCoreTemplates === undefined) { - const file = await host.readFile(resolvePath(templatesDir, "scaffolding.json")); - const content = JSON.parse(file.text); - typeSpecCoreTemplates = { - baseUri: templatesDir, - templates: content, - }; - } - return typeSpecCoreTemplates; -} +export async function getTypeSpecCoreTemplates(host: SystemHost): Promise {} diff --git a/packages/init-templates/package.json b/packages/init-templates/package.json index 51914c2a0a6..9ba56fed193 100644 --- a/packages/init-templates/package.json +++ b/packages/init-templates/package.json @@ -27,7 +27,7 @@ }, "scripts": { "clean": "rimraf ./dist ./temp", - "build": "tsx ./.scripts/build-init-templates.ts", + "build": "tsx ./scripts/build.ts", "test": "pnpm test:e2e", "test:e2e": "vitest run --config ./vitest.config.e2e.ts", "lint": "eslint . --ext .ts --max-warnings=0", diff --git a/packages/init-templates/scripts/build.ts b/packages/init-templates/scripts/build.ts index 0952f9bf7ab..56e6d1fc528 100644 --- a/packages/init-templates/scripts/build.ts +++ b/packages/init-templates/scripts/build.ts @@ -1,12 +1,10 @@ -import { mkdir, readFile, writeFile } from "fs/promises"; +import { MANIFEST } from "@typespec/compiler"; +import { mkdir, writeFile } from "fs/promises"; import { resolve } from "pathe"; +// @ts-ignore import type { InitTemplate } from "../../compiler/src/init/init-template.js"; import { localDir, packageRoot } from "./helpers.js"; - -const pkgJson = JSON.parse( - (await readFile(resolve(packageRoot, "package.json"))).toString("utf-8"), -); -const minCompilerVersion = pkgJson.version; +const minCompilerVersion = MANIFEST.version; const builtInTemplates: Record = { rest: { From 0bb63808b09c2898f3d47063b6c18c7b6b1568ea Mon Sep 17 00:00:00 2001 From: Timothee Guerin Date: Thu, 3 Apr 2025 15:37:37 -0700 Subject: [PATCH 4/5] Progress --- packages/compiler/src/cli/common.ts | 15 +++++++ packages/compiler/src/init/core-templates.ts | 39 ++++++++++++++++++- packages/compiler/src/init/init.ts | 2 +- .../src/package-manger/npm-registry-utils.ts | 6 ++- packages/compiler/src/server/serverlib.ts | 2 +- .../compiler/test/e2e/init-templates.e2e.ts | 2 +- 6 files changed, 60 insertions(+), 6 deletions(-) create mode 100644 packages/compiler/src/cli/common.ts diff --git a/packages/compiler/src/cli/common.ts b/packages/compiler/src/cli/common.ts new file mode 100644 index 00000000000..39a1ba3b6ee --- /dev/null +++ b/packages/compiler/src/cli/common.ts @@ -0,0 +1,15 @@ +import envPaths from "env-paths"; +import { joinPaths } from "../core/path-utils.js"; + +const paths = envPaths("typespec", { suffix: "" }); + +export const KnownDirectories = { + /** + * The directory where the package manager are installed. + */ + packageManager: joinPaths(paths.cache, "pm"), + /** + * The directory where the init template package is installed. + */ + initTemplates: joinPaths(paths.cache, "init-templates"), +} as const; diff --git a/packages/compiler/src/init/core-templates.ts b/packages/compiler/src/init/core-templates.ts index c93c28d4505..92855e89cc3 100644 --- a/packages/compiler/src/init/core-templates.ts +++ b/packages/compiler/src/init/core-templates.ts @@ -1,8 +1,43 @@ -import type { SystemHost } from "../core/types.js"; +import { mkdir, readFile, writeFile } from "fs/promises"; +import { KnownDirectories } from "../cli/common.js"; +import { joinPaths } from "../core/path-utils.js"; +import { downloadPackageVersion } from "../package-manger/npm-registry-utils.js"; export interface LoadedCoreTemplates { readonly baseUri: string; readonly templates: Record; } -export async function getTypeSpecCoreTemplates(host: SystemHost): Promise {} +const LAST_CHECK_FILE_NAME = ".last-check.json"; +const CHECK_TIMEOUT = 86400_000; // 24 hours in milliseconds + +export async function getTypeSpecCoreTemplates(): Promise { + const lastCheck = await readLastCheckFile(); + if (lastCheck === undefined || new Date().getTime() > lastCheck?.getTime() + CHECK_TIMEOUT) { + await mkdir(KnownDirectories.initTemplates, { recursive: true }); + await downloadPackageVersion("@typespec/compiler", "latest", KnownDirectories.initTemplates); + await saveLastCheckFile(); + } + + return (await import(`${KnownDirectories.initTemplates}/src/index.js`)).default; +} + +async function readLastCheckFile(): Promise { + try { + const lastCheck = await readFile( + joinPaths(KnownDirectories.initTemplates, LAST_CHECK_FILE_NAME), + "utf8", + ); + return new Date(JSON.parse(lastCheck).time); + } catch (e) { + return undefined; + } +} + +async function saveLastCheckFile() { + await writeFile( + joinPaths(KnownDirectories.initTemplates, LAST_CHECK_FILE_NAME), + JSON.stringify({ time: new Date().toISOString() }, null, 2), + "utf8", + ); +} diff --git a/packages/compiler/src/init/init.ts b/packages/compiler/src/init/init.ts index 25ee097a3f2..49c52170ee1 100644 --- a/packages/compiler/src/init/init.ts +++ b/packages/compiler/src/init/init.ts @@ -51,7 +51,7 @@ export async function initTypeSpecProjectWorker( // Download template configuration and prompt user to select a template // No validation is done until one has been selected - const typeSpecCoreTemplates = await getTypeSpecCoreTemplates(host); + const typeSpecCoreTemplates = await getTypeSpecCoreTemplates(); const result = options.templatesUrl === undefined ? (typeSpecCoreTemplates as LoadedTemplate) diff --git a/packages/compiler/src/package-manger/npm-registry-utils.ts b/packages/compiler/src/package-manger/npm-registry-utils.ts index 58447c7a483..46f6c99c583 100644 --- a/packages/compiler/src/package-manger/npm-registry-utils.ts +++ b/packages/compiler/src/package-manger/npm-registry-utils.ts @@ -93,7 +93,11 @@ export async function fetchPackageManifest( ): Promise { const url = `${registry}/${packageName}/${version}`; const res = await fetch(url); - return await res.json(); + if (res.ok) { + return await res.json(); + } else { + throw new Error(`Failed to fetch ${url}: ${res.status} ${res.statusText}`); + } } export function fetchLatestPackageManifest(packageName: string): Promise { diff --git a/packages/compiler/src/server/serverlib.ts b/packages/compiler/src/server/serverlib.ts index 07733dfd630..8cbff568908 100644 --- a/packages/compiler/src/server/serverlib.ts +++ b/packages/compiler/src/server/serverlib.ts @@ -313,7 +313,7 @@ export function createServer(host: ServerHost): Server { async function getInitProjectContext(): Promise { return { - coreInitTemplates: await getTypeSpecCoreTemplates(host.compilerHost), + coreInitTemplates: await getTypeSpecCoreTemplates(), }; } diff --git a/packages/compiler/test/e2e/init-templates.e2e.ts b/packages/compiler/test/e2e/init-templates.e2e.ts index 13045f4f05c..1020999caf1 100644 --- a/packages/compiler/test/e2e/init-templates.e2e.ts +++ b/packages/compiler/test/e2e/init-templates.e2e.ts @@ -63,7 +63,7 @@ describe("Init templates e2e tests", () => { }); async function scaffoldTemplateTo(name: string, targetFolder: string) { - const typeSpecCoreTemplates = await getTypeSpecCoreTemplates(NodeHost); + const typeSpecCoreTemplates = await getTypeSpecCoreTemplates(); const template = typeSpecCoreTemplates.templates[name]; ok(template, `Template '${name}' not found`); await scaffoldNewProject( From f609a3620882b4a2e0d0721ae8282231f8b02eb5 Mon Sep 17 00:00:00 2001 From: Timothee Guerin Date: Fri, 4 Apr 2025 08:54:12 -0700 Subject: [PATCH 5/5] Create init-template-pkg-2025-3-4-15-48-47.md --- .chronus/changes/init-template-pkg-2025-3-4-15-48-47.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .chronus/changes/init-template-pkg-2025-3-4-15-48-47.md diff --git a/.chronus/changes/init-template-pkg-2025-3-4-15-48-47.md b/.chronus/changes/init-template-pkg-2025-3-4-15-48-47.md new file mode 100644 index 00000000000..440944185d8 --- /dev/null +++ b/.chronus/changes/init-template-pkg-2025-3-4-15-48-47.md @@ -0,0 +1,9 @@ +--- +# Change versionKind to one of: internal, fix, dependencies, feature, deprecation, breaking +changeKind: internal +packages: + - "@typespec/compiler" + - "@typespec/init-templates" +--- + +Move init templates to a separate package