From f989838b35033d4d53aeb033143992386ca090b2 Mon Sep 17 00:00:00 2001 From: jycouet Date: Sat, 4 Apr 2026 12:29:22 +0200 Subject: [PATCH 1/7] chore: add api-surface generator and tsdown hooks Wire generateApiSurface into each config's build:done (with a shared counter so it runs once after all parallel builds). Add scripts/ generate-api-surface.js (strip regions, sourceMappingURL, optional JSDoc; keep @deprecated blocks). Made-with: Cursor --- scripts/generate-api-surface.js | 125 ++++++++++++++++++++++++++++++++ tsdown.config.ts | 26 ++++++- 2 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 scripts/generate-api-surface.js diff --git a/scripts/generate-api-surface.js b/scripts/generate-api-surface.js new file mode 100644 index 000000000..d34bf160b --- /dev/null +++ b/scripts/generate-api-surface.js @@ -0,0 +1,125 @@ +/** + * Reads the generated .d.mts files and produces a cleaned-up + * api-surface.md for each package. Strips `//#region` / `//#endregion` + * directives, `//# sourceMappingURL=...` lines, non-deprecated JSDoc, import-only lines, + * and blank runs so the result is a compact, diff-friendly snapshot + * of the public API. JSDoc blocks that contain `@deprecated` are kept + * in full. + * + * Run: node scripts/generate-api-surface.js + * Or: invoked from tsdown `build:done` after all configs finish (see tsdown.config.ts). + */ + +import fs from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const ROOT = path.dirname(path.dirname(fileURLToPath(import.meta.url))); + +const packages = [ + { + name: 'sv', + dts: 'packages/sv/dist/src/index.d.mts', + out: 'packages/sv/api-surface.md' + }, + { + name: 'sv (testing)', + dts: 'packages/sv/dist/src/testing.d.mts', + out: 'packages/sv/api-surface-testing.md' + }, + { + name: '@sveltejs/sv-utils', + dts: 'packages/sv-utils/dist/index.d.mts', + out: 'packages/sv-utils/api-surface.md' + } +]; + +/** Remove `//#region` / `//#endregion` lines emitted by the DTS bundler. */ +function stripRegionDirectives(source) { + return source + .split('\n') + .filter((line) => !/^\s*\/\/#(region|endregion)\b/.test(line)) + .join('\n'); +} + +/** Remove `//# sourceMappingURL=...` lines from declaration emit. */ +function stripSourceMappingUrl(source) { + return source + .split('\n') + .filter((line) => !/^\s*\/\/#\s*sourceMappingURL=/.test(line)) + .join('\n'); +} + +/** + * Remove `/** ... *\/` blocks unless they contain `@deprecated`, in which case + * the full block is preserved (including inline trailing JSDoc on a line). + */ +function stripJsDoc(source) { + return source.replace(/\/\*\*[\s\S]*?\*\//g, (match) => { + if (/@deprecated\b/.test(match)) { + return match; + } + return ''; + }); +} + +function stripImportLines(source) { + // Remove `import ...` lines that are only used for type resolution + return source + .split('\n') + .filter((line) => !line.match(/^import\s/)) + .join('\n'); +} + +function collapseBlankLines(source) { + return source.replace(/\n{3,}/g, '\n\n'); +} + +function clean(source) { + let result = stripRegionDirectives(source); + result = stripSourceMappingUrl(result); + result = stripJsDoc(result); + result = stripImportLines(result); + result = collapseBlankLines(result); + return result.trim() + '\n'; +} + +/** @returns {number} number of api-surface files written */ +export function generateApiSurface() { + let generated = 0; + for (const pkg of packages) { + const dtsPath = path.resolve(ROOT, pkg.dts); + if (!fs.existsSync(dtsPath)) { + console.warn(` skipped ${pkg.name} - ${pkg.dts} not found (run build first)`); + continue; + } + + const raw = fs.readFileSync(dtsPath, 'utf8'); + const cleaned = clean(raw); + + const header = + `# ${pkg.name} - Public API Surface\n\n` + + `\n\n` + + '```ts\n'; + const footer = '```\n'; + + const outPath = path.resolve(ROOT, pkg.out); + fs.writeFileSync(outPath, header + cleaned + footer, 'utf8'); + generated++; + console.log(` ${pkg.name} -> ${pkg.out}`); + } + + if (generated === 0) { + console.warn('No .d.mts files found - run `pnpm build` first.'); + process.exit(1); + } + + return generated; +} + +const isMain = + process.argv[1] && fileURLToPath(import.meta.url) === path.resolve(process.argv[1]); + +if (isMain) { + generateApiSurface(); +} diff --git a/tsdown.config.ts b/tsdown.config.ts index 1a564bdcc..7de467cb0 100644 --- a/tsdown.config.ts +++ b/tsdown.config.ts @@ -3,6 +3,23 @@ import process from 'node:process'; import { defineConfig } from 'tsdown'; import { buildTemplates } from './packages/sv/src/create/scripts/build-templates.js'; +/** + * tsdown runs each `defineConfig` entry in parallel. There is no single + * "all builds finished" hook, so we count `build:done` (must match the number + * of config objects below) and run api-surface generation once all `.d.mts` + * outputs exist. + */ +const API_SURFACE_CONFIG_COUNT = 3; +let apiSurfaceBuildsDone = 0; + +function hookApiSurfaceBuildDone(): void | Promise { + apiSurfaceBuildsDone++; + if (apiSurfaceBuildsDone === API_SURFACE_CONFIG_COUNT) { + apiSurfaceBuildsDone = 0; + return import('./scripts/generate-api-surface.js').then((m) => m.generateApiSurface()); + } +} + export default defineConfig([ { cwd: path.resolve('packages/sv'), @@ -57,7 +74,8 @@ export default defineConfig([ hooks: { async 'build:before'() { await buildCliTemplates(); - } + }, + 'build:done': () => hookApiSurfaceBuildDone() } }, // sv-utils: runtime build (bundles everything including svelte) @@ -88,6 +106,9 @@ export default defineConfig([ 'yaml', 'zimmerframe' ] + }, + hooks: { + 'build:done': () => hookApiSurfaceBuildDone() } }, // sv-utils: DTS-only build (svelte externalized) @@ -105,6 +126,9 @@ export default defineConfig([ deps: { neverBundle: [/^svelte/, '@types/estree', 'estree'], onlyBundle: ['dedent', 'package-manager-detector', 'smol-toml', 'yaml', 'zimmerframe'] + }, + hooks: { + 'build:done': () => hookApiSurfaceBuildDone() } } ]); From 409c94322a643a22774bf0d711725eaac8e621b1 Mon Sep 17 00:00:00 2001 From: jycouet Date: Sat, 4 Apr 2026 12:29:27 +0200 Subject: [PATCH 2/7] chore: add generated public API surface snapshots Snapshots from built .d.mts (baseline before coupling/deprecation work). Made-with: Cursor --- packages/sv-utils/api-surface.md | 1310 ++++++++++++++++++++++++++++ packages/sv/api-surface-testing.md | 109 +++ packages/sv/api-surface.md | 25 + 3 files changed, 1444 insertions(+) create mode 100644 packages/sv-utils/api-surface.md create mode 100644 packages/sv/api-surface-testing.md create mode 100644 packages/sv/api-surface.md diff --git a/packages/sv-utils/api-surface.md b/packages/sv-utils/api-surface.md new file mode 100644 index 000000000..983b6d046 --- /dev/null +++ b/packages/sv-utils/api-surface.md @@ -0,0 +1,1310 @@ +# @sveltejs/sv-utils - Public API Surface + + + +```ts +type Agent = 'npm' | 'yarn' | 'yarn@berry' | 'pnpm' | 'pnpm@6' | 'bun' | 'deno'; +type AgentName = 'npm' | 'yarn' | 'pnpm' | 'bun' | 'deno'; +type AgentCommandValue = (string | number)[] | ((args: string[]) => string[]) | null; +interface AgentCommands { + 'agent': AgentCommandValue; + 'run': AgentCommandValue; + 'install': AgentCommandValue; + 'frozen': AgentCommandValue; + 'global': AgentCommandValue; + 'add': AgentCommandValue; + 'upgrade': AgentCommandValue; + 'upgrade-interactive': AgentCommandValue; + 'dedupe': AgentCommandValue; + 'execute': AgentCommandValue; + 'execute-local': AgentCommandValue; + 'uninstall': AgentCommandValue; + 'global_uninstall': AgentCommandValue; +} +type Command = keyof AgentCommands; +interface ResolvedCommand { + + command: string; + + args: string[]; +} +type DetectStrategy = 'lockfile' | 'packageManager-field' | 'devEngines-field' | 'install-metadata'; +interface DetectOptions { + + cwd?: string; + + strategies?: DetectStrategy[]; + + onUnknown?: (packageManager: string) => DetectResult | null | undefined; + + stopDir?: string | ((currentDir: string) => boolean); + + packageJsonParser?: (content: string, filepath: string) => any | Promise; +} +interface DetectResult { + + name: AgentName; + + agent: Agent; + + version?: string; +} +declare const COMMANDS: { + npm: AgentCommands; + yarn: AgentCommands; + 'yarn@berry': AgentCommands; + pnpm: AgentCommands; + 'pnpm@6': AgentCommands; + bun: AgentCommands; + deno: AgentCommands; +}; + +declare function resolveCommand(agent: Agent, command: Command, args: string[]): ResolvedCommand | null; + +declare function constructCommand(value: AgentCommandValue, args: string[]): ResolvedCommand | null; +declare const AGENTS: Agent[]; + +declare function detect(options?: DetectOptions): Promise; +/*! + * Copyright (c) Squirrel Chat et al., All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +declare class TomlDate extends Date { + #private; + constructor(date: string | Date); + isDateTime(): boolean; + isLocal(): boolean; + isDate(): boolean; + isTime(): boolean; + isValid(): boolean; + toISOString(): string; + static wrapAsOffsetDateTime(jsDate: Date, offset?: string): TomlDate; + static wrapAsLocalDateTime(jsDate: Date): TomlDate; + static wrapAsLocalDate(jsDate: Date): TomlDate; + static wrapAsLocalTime(jsDate: Date): TomlDate; +} +type TomlPrimitive = string | number | bigint | boolean | TomlDate; +type TomlTable = { + [key: string]: TomlValue; +}; +type TomlValue = TomlPrimitive | TomlValue[] | TomlTable; + +declare class LineCounter { + lineStarts: number[]; + + addNewLine: (offset: number) => number; + + linePos: (offset: number) => { + line: number; + col: number; + }; +} +type ErrorCode = 'ALIAS_PROPS' | 'BAD_ALIAS' | 'BAD_DIRECTIVE' | 'BAD_DQ_ESCAPE' | 'BAD_INDENT' | 'BAD_PROP_ORDER' | 'BAD_SCALAR_START' | 'BLOCK_AS_IMPLICIT_KEY' | 'BLOCK_IN_FLOW' | 'DUPLICATE_KEY' | 'IMPOSSIBLE' | 'KEY_OVER_1024_CHARS' | 'MISSING_CHAR' | 'MULTILINE_IMPLICIT_KEY' | 'MULTIPLE_ANCHORS' | 'MULTIPLE_DOCS' | 'MULTIPLE_TAGS' | 'NON_STRING_KEY' | 'TAB_AS_INDENT' | 'TAG_RESOLVE_FAILED' | 'UNEXPECTED_TOKEN' | 'BAD_COLLECTION_TYPE'; +type LinePos = { + line: number; + col: number; +}; +declare class YAMLError extends Error { + name: 'YAMLParseError' | 'YAMLWarning'; + code: ErrorCode; + message: string; + pos: [number, number]; + linePos?: [LinePos] | [LinePos, LinePos]; + constructor(name: YAMLError['name'], pos: [number, number], code: ErrorCode, message: string); +} +declare class YAMLWarning extends YAMLError { + constructor(pos: [number, number], code: ErrorCode, message: string); +} +type Reviver = (key: unknown, value: unknown) => unknown; +type LogLevelId = 'silent' | 'error' | 'warn' | 'debug'; +interface AnchorData { + aliasCount: number; + count: number; + res: unknown; +} +interface ToJSContext { + anchors: Map; + + aliasResolveCache?: Node[]; + doc: Document; + keep: boolean; + mapAsMap: boolean; + mapKeyWarned: boolean; + maxAliasCount: number; + onCreate?: (res: unknown) => void; +} +declare namespace Scalar { + interface Parsed extends Scalar { + range: Range; + source: string; + srcToken?: FlowScalar | BlockScalar; + } + type BLOCK_FOLDED = 'BLOCK_FOLDED'; + type BLOCK_LITERAL = 'BLOCK_LITERAL'; + type PLAIN = 'PLAIN'; + type QUOTE_DOUBLE = 'QUOTE_DOUBLE'; + type QUOTE_SINGLE = 'QUOTE_SINGLE'; + type Type = BLOCK_FOLDED | BLOCK_LITERAL | PLAIN | QUOTE_DOUBLE | QUOTE_SINGLE; +} +declare class Scalar extends NodeBase { + static readonly BLOCK_FOLDED = "BLOCK_FOLDED"; + static readonly BLOCK_LITERAL = "BLOCK_LITERAL"; + static readonly PLAIN = "PLAIN"; + static readonly QUOTE_DOUBLE = "QUOTE_DOUBLE"; + static readonly QUOTE_SINGLE = "QUOTE_SINGLE"; + value: T; + + anchor?: string; + + format?: string; + + minFractionDigits?: number; + + source?: string; + + type?: Scalar.Type; + constructor(value: T); + toJSON(arg?: any, ctx?: ToJSContext): any; + toString(): string; +} +type StringifyContext = { + actualString?: boolean; + allNullValues?: boolean; + anchors: Set; + doc: Document; + forceBlockIndent?: boolean; + implicitKey?: boolean; + indent: string; + indentStep: string; + indentAtStart?: number; + inFlow: boolean | null; + inStringifyKey?: boolean; + flowCollectionPadding: string; + options: Readonly>>; + resolvedAliases?: Set; +}; +declare abstract class Collection extends NodeBase { + schema: Schema | undefined; + [NODE_TYPE]: symbol; + items: unknown[]; + + anchor?: string; + + flow?: boolean; + constructor(type: symbol, schema?: Schema); + + clone(schema?: Schema): Collection; + + abstract add(value: unknown): void; + + abstract delete(key: unknown): boolean; + + abstract get(key: unknown, keepScalar?: boolean): unknown; + + abstract has(key: unknown): boolean; + + abstract set(key: unknown, value: unknown): void; + + addIn(path: Iterable, value: unknown): void; + + deleteIn(path: Iterable): boolean; + + getIn(path: Iterable, keepScalar?: boolean): unknown; + hasAllNullValues(allowScalar?: boolean): boolean; + + hasIn(path: Iterable): boolean; + + setIn(path: Iterable, value: unknown): void; +} +declare namespace YAMLSeq { + interface Parsed = ParsedNode> extends YAMLSeq { + items: T[]; + range: Range; + srcToken?: BlockSequence | FlowCollection; + } +} +declare class YAMLSeq extends Collection { + static get tagName(): 'tag:yaml.org,2002:seq'; + items: T[]; + constructor(schema?: Schema); + add(value: T): void; + + delete(key: unknown): boolean; + + get(key: unknown, keepScalar: true): Scalar | undefined; + get(key: unknown, keepScalar?: false): T | undefined; + get(key: unknown, keepScalar?: boolean): T | Scalar | undefined; + + has(key: unknown): boolean; + + set(key: unknown, value: T): void; + toJSON(_?: unknown, ctx?: ToJSContext): unknown[]; + toString(ctx?: StringifyContext, onComment?: () => void, onChompKeep?: () => void): string; + static from(schema: Schema, obj: unknown, ctx: CreateNodeContext): YAMLSeq; +} +interface TagBase { + + createNode?: (schema: Schema, value: unknown, ctx: CreateNodeContext) => Node; + + default?: boolean | 'key'; + + format?: string; + + identify?: (value: unknown) => boolean; + + tag: string; +} +interface ScalarTag extends TagBase { + collection?: never; + nodeClass?: never; + + resolve(value: string, onError: (message: string) => void, options: ParseOptions): unknown; + + stringify?: (item: Scalar, ctx: StringifyContext, onComment?: () => void, onChompKeep?: () => void) => string; + + test?: RegExp; +} +interface CollectionTag extends TagBase { + stringify?: never; + test?: never; + + collection: 'map' | 'seq'; + + nodeClass?: { + new (schema?: Schema): Node; + from?: (schema: Schema, obj: unknown, ctx: CreateNodeContext) => Node; + }; + + resolve?: (value: YAMLMap.Parsed | YAMLSeq.Parsed, onError: (message: string) => void, options: ParseOptions) => unknown; +} +type MapLike = Map | Set | Record; +declare namespace YAMLMap { + interface Parsed extends YAMLMap { + items: Pair[]; + range: Range; + srcToken?: BlockMap | FlowCollection; + } +} +declare class YAMLMap extends Collection { + static get tagName(): 'tag:yaml.org,2002:map'; + items: Pair[]; + constructor(schema?: Schema); + + static from(schema: Schema, obj: unknown, ctx: CreateNodeContext): YAMLMap; + + add(pair: Pair | { + key: K; + value: V; + }, overwrite?: boolean): void; + delete(key: unknown): boolean; + get(key: unknown, keepScalar: true): Scalar | undefined; + get(key: unknown, keepScalar?: false): V | undefined; + get(key: unknown, keepScalar?: boolean): V | Scalar | undefined; + has(key: unknown): boolean; + set(key: K, value: V): void; + + toJSON>(_?: unknown, ctx?: ToJSContext, Type?: { + new (): T; + }): any; + toString(ctx?: StringifyContext, onComment?: () => void, onChompKeep?: () => void): string; +} +declare const MAP: unique symbol; +declare const SCALAR: unique symbol; +declare const SEQ: unique symbol; +declare const NODE_TYPE: unique symbol; +declare class Schema { + compat: Array | null; + knownTags: Record; + name: string; + sortMapEntries: ((a: Pair, b: Pair) => number) | null; + tags: Array; + toStringOptions: Readonly | null; + readonly [MAP]: CollectionTag; + readonly [SCALAR]: ScalarTag; + readonly [SEQ]: CollectionTag; + constructor({ + compat, + customTags, + merge, + resolveKnownTags, + schema, + sortMapEntries, + toStringDefaults + }: SchemaOptions); + clone(): Schema; +} +interface CreateNodeContext { + aliasDuplicateObjects: boolean; + keepUndefined: boolean; + onAnchor: (source: unknown) => string; + onTagObj?: (tagObj: ScalarTag | CollectionTag) => void; + sourceObjects: Map; + replacer?: Replacer; + schema: Schema; +} +declare function addPairToJSMap(ctx: ToJSContext | undefined, map: MapLike, { + key, + value +}: Pair): MapLike; +declare class Pair { + readonly [NODE_TYPE]: symbol; + + key: K; + + value: V | null; + + srcToken?: CollectionItem; + constructor(key: K, value?: V | null); + clone(schema?: Schema): Pair; + toJSON(_?: unknown, ctx?: ToJSContext): ReturnType; + toString(ctx?: StringifyContext, onComment?: () => void, onChompKeep?: () => void): string; +} +declare const tagsByName: { + binary: ScalarTag; + bool: ScalarTag & { + test: RegExp; + }; + float: ScalarTag; + floatExp: ScalarTag; + floatNaN: ScalarTag; + floatTime: ScalarTag; + int: ScalarTag; + intHex: ScalarTag; + intOct: ScalarTag; + intTime: ScalarTag; + map: CollectionTag; + merge: ScalarTag & { + identify(value: unknown): boolean; + test: RegExp; + }; + null: ScalarTag & { + test: RegExp; + }; + omap: CollectionTag; + pairs: CollectionTag; + seq: CollectionTag; + set: CollectionTag; + timestamp: ScalarTag & { + test: RegExp; + }; +}; +type TagId = keyof typeof tagsByName; +type Tags = Array; +type ParseOptions = { + + intAsBigInt?: boolean; + + keepSourceTokens?: boolean; + + lineCounter?: LineCounter; + + prettyErrors?: boolean; + + strict?: boolean; + + stringKeys?: boolean; + + uniqueKeys?: boolean | ((a: ParsedNode, b: ParsedNode) => boolean); +}; +type DocumentOptions = { + + _directives?: Directives; + + logLevel?: LogLevelId; + + version?: '1.1' | '1.2' | 'next'; +}; +type SchemaOptions = { + + compat?: string | Tags | null; + + customTags?: Tags | ((tags: Tags) => Tags) | null; + + merge?: boolean; + + resolveKnownTags?: boolean; + + schema?: string | Schema; + + sortMapEntries?: boolean | ((a: Pair, b: Pair) => number); + + toStringDefaults?: ToStringOptions; +}; +type CreateNodeOptions = { + + aliasDuplicateObjects?: boolean; + + anchorPrefix?: string; + flow?: boolean; + + keepUndefined?: boolean | null; + onTagObj?: (tagObj: ScalarTag | CollectionTag) => void; + + tag?: string; +}; +type ToJSOptions = { + + mapAsMap?: boolean; + + maxAliasCount?: number; + + onAnchor?: (value: unknown, count: number) => void; + + reviver?: Reviver; +}; +type ToStringOptions = { + + blockQuote?: boolean | 'folded' | 'literal'; + + collectionStyle?: 'any' | 'block' | 'flow'; + + commentString?: (comment: string) => string; + + defaultKeyType?: Scalar.Type | null; + + defaultStringType?: Scalar.Type; + + directives?: boolean | null; + + doubleQuotedAsJSON?: boolean; + + doubleQuotedMinMultiLineLength?: number; + + falseStr?: string; + + flowCollectionPadding?: boolean; + + indent?: number; + + indentSeq?: boolean; + + lineWidth?: number; + + minContentWidth?: number; + + nullStr?: string; + + simpleKeys?: boolean; + + singleQuote?: boolean | null; + + trueStr?: string; + + verifyAliasOrder?: boolean; +}; +type Node = Alias | Scalar | YAMLMap | YAMLSeq; + +type NodeType = T extends string | number | bigint | boolean | null | undefined ? Scalar : T extends Date ? Scalar : T extends Array ? YAMLSeq> : T extends { + [key: string]: any; +} ? YAMLMap, NodeType> : T extends { + [key: number]: any; +} ? YAMLMap, NodeType> : Node; +type ParsedNode = Alias.Parsed | Scalar.Parsed | YAMLMap.Parsed | YAMLSeq.Parsed; + +type Range = [number, number, number]; +declare abstract class NodeBase { + readonly [NODE_TYPE]: symbol; + + comment?: string | null; + + commentBefore?: string | null; + + range?: Range | null; + + spaceBefore?: boolean; + + srcToken?: Token; + + tag?: string; + + addToJSMap?: (ctx: ToJSContext | undefined, map: MapLike, value: unknown) => void; + + abstract toJSON(): any; + abstract toString(ctx?: StringifyContext, onComment?: () => void, onChompKeep?: () => void): string; + constructor(type: symbol); + + clone(): NodeBase; + + toJS(doc: Document, { + mapAsMap, + maxAliasCount, + onAnchor, + reviver + }?: ToJSOptions): any; +} +interface SourceToken { + type: 'byte-order-mark' | 'doc-mode' | 'doc-start' | 'space' | 'comment' | 'newline' | 'directive-line' | 'anchor' | 'tag' | 'seq-item-ind' | 'explicit-key-ind' | 'map-value-ind' | 'flow-map-start' | 'flow-map-end' | 'flow-seq-start' | 'flow-seq-end' | 'flow-error-end' | 'comma' | 'block-scalar-header'; + offset: number; + indent: number; + source: string; +} +interface ErrorToken { + type: 'error'; + offset: number; + source: string; + message: string; +} +interface Directive$1 { + type: 'directive'; + offset: number; + source: string; +} +interface Document$1 { + type: 'document'; + offset: number; + start: SourceToken[]; + value?: Token; + end?: SourceToken[]; +} +interface DocumentEnd { + type: 'doc-end'; + offset: number; + source: string; + end?: SourceToken[]; +} +interface FlowScalar { + type: 'alias' | 'scalar' | 'single-quoted-scalar' | 'double-quoted-scalar'; + offset: number; + indent: number; + source: string; + end?: SourceToken[]; +} +interface BlockScalar { + type: 'block-scalar'; + offset: number; + indent: number; + props: Token[]; + source: string; +} +interface BlockMap { + type: 'block-map'; + offset: number; + indent: number; + items: Array<{ + start: SourceToken[]; + explicitKey?: true; + key?: never; + sep?: never; + value?: never; + } | { + start: SourceToken[]; + explicitKey?: true; + key: Token | null; + sep: SourceToken[]; + value?: Token; + }>; +} +interface BlockSequence { + type: 'block-seq'; + offset: number; + indent: number; + items: Array<{ + start: SourceToken[]; + key?: never; + sep?: never; + value?: Token; + }>; +} +type CollectionItem = { + start: SourceToken[]; + key?: Token | null; + sep?: SourceToken[]; + value?: Token; +}; +interface FlowCollection { + type: 'flow-collection'; + offset: number; + indent: number; + start: SourceToken; + items: CollectionItem[]; + end: SourceToken[]; +} +type Token = SourceToken | ErrorToken | Directive$1 | Document$1 | DocumentEnd | FlowScalar | BlockScalar | BlockMap | BlockSequence | FlowCollection; +declare namespace Alias { + interface Parsed extends Alias { + range: Range; + srcToken?: FlowScalar & { + type: 'alias'; + }; + } +} +declare class Alias extends NodeBase { + source: string; + anchor?: never; + constructor(source: string); + + resolve(doc: Document, ctx?: ToJSContext): Scalar | YAMLMap | YAMLSeq | undefined; + toJSON(_arg?: unknown, ctx?: ToJSContext): unknown; + toString(ctx?: StringifyContext, _onComment?: () => void, _onChompKeep?: () => void): string; +} +type Replacer = any[] | ((key: any, value: any) => unknown); +declare namespace Document { + + interface Parsed extends Document { + directives: Directives; + range: Range; + } +} +declare class Document { + readonly [NODE_TYPE]: symbol; + + commentBefore: string | null; + + comment: string | null; + + contents: Strict extends true ? Contents | null : Contents; + directives: Strict extends true ? Directives | undefined : Directives; + + errors: YAMLError[]; + options: Required>; + + range?: Range; + + schema: Schema; + + warnings: YAMLWarning[]; + + constructor(value?: any, options?: DocumentOptions & SchemaOptions & ParseOptions & CreateNodeOptions); + constructor(value: any, replacer: null | Replacer, options?: DocumentOptions & SchemaOptions & ParseOptions & CreateNodeOptions); + + clone(): Document; + + add(value: any): void; + + addIn(path: Iterable, value: unknown): void; + + createAlias(node: Strict extends true ? Scalar | YAMLMap | YAMLSeq : Node, name?: string): Alias; + + createNode(value: T, options?: CreateNodeOptions): NodeType; + createNode(value: T, replacer: Replacer | CreateNodeOptions | null, options?: CreateNodeOptions): NodeType; + + createPair(key: unknown, value: unknown, options?: CreateNodeOptions): Pair; + + delete(key: unknown): boolean; + + deleteIn(path: Iterable | null): boolean; + + get(key: unknown, keepScalar?: boolean): Strict extends true ? unknown : any; + + getIn(path: Iterable | null, keepScalar?: boolean): Strict extends true ? unknown : any; + + has(key: unknown): boolean; + + hasIn(path: Iterable | null): boolean; + + set(key: any, value: unknown): void; + + setIn(path: Iterable | null, value: unknown): void; + + setSchema(version: '1.1' | '1.2' | 'next' | null, options?: SchemaOptions): void; + + toJS(opt?: ToJSOptions & { + [ignored: string]: unknown; + }): any; + + toJSON(jsonArg?: string | null, onAnchor?: ToJSOptions['onAnchor']): any; + + toString(options?: ToStringOptions): string; +} +declare class Directives { + static defaultYaml: Directives['yaml']; + static defaultTags: Directives['tags']; + yaml: { + version: '1.1' | '1.2' | 'next'; + explicit?: boolean; + }; + tags: Record; + + docStart: true | null; + + docEnd: boolean; + + private atNextDocument?; + constructor(yaml?: Directives['yaml'], tags?: Directives['tags']); + clone(): Directives; + + atDocument(): Directives; + + add(line: string, onError: (offset: number, message: string, warning?: boolean) => void): boolean; + + tagName(source: string, onError: (message: string) => void): string | null; + + tagString(tag: string): string; + toString(doc?: Document): string; +} + +declare function parseDocument(source: string, options?: ParseOptions & DocumentOptions & SchemaOptions): Contents extends ParsedNode ? Document.Parsed : Document; +declare module "estree" { + interface TSTypeAnnotation { + type: "TSTypeAnnotation"; + typeAnnotation: TSStringKeyword | TSTypeReference | TSUnionType | TSIndexedAccessType; + } + interface TSStringKeyword { + type: "TSStringKeyword"; + } + interface TSNullKeyword { + type: "TSNullKeyword"; + } + interface TSTypeReference { + type: "TSTypeReference"; + typeName: Identifier; + } + interface TSAsExpression extends BaseNode { + type: "TSAsExpression"; + expression: Expression; + typeAnnotation: TSTypeAnnotation["typeAnnotation"]; + } + interface TSModuleDeclaration extends BaseNode { + type: "TSModuleDeclaration"; + global: boolean; + declare: boolean; + id: Identifier; + body: TSModuleBlock; + } + interface TSModuleBlock extends BaseNode { + type: "TSModuleBlock"; + body: Array; + } + interface TSInterfaceDeclaration extends BaseNode { + type: "TSInterfaceDeclaration"; + id: Identifier; + body: TSInterfaceBody; + } + interface TSInterfaceBody extends BaseNode { + type: "TSInterfaceBody"; + body: TSPropertySignature[]; + } + interface TSPropertySignature extends BaseNode { + type: "TSPropertySignature"; + computed: boolean; + key: Identifier; + optional?: boolean; + typeAnnotation: TSTypeAnnotation; + } + interface TSProgram extends Omit { + body: Array; + } + interface TSUnionType { + type: "TSUnionType"; + types: Array; + } + interface TSImportType { + type: "TSImportType"; + argument: Literal; + qualifier: Identifier; + } + interface TSIndexedAccessType { + type: "TSIndexedAccessType"; + objectType: TSImportType; + indexType: TSLiteralType; + } + interface TSLiteralType { + type: "TSLiteralType"; + literal: Literal; + } + interface TSSatisfiesExpression extends BaseNode { + type: "TSSatisfiesExpression"; + expression: Expression; + typeAnnotation: TSTypeAnnotation["typeAnnotation"]; + } + interface BaseNodeWithoutComments { + type: string; + loc?: SourceLocation | null | undefined; + range?: [number, number] | undefined; + start?: number; + end?: number; + } + interface Identifier { + typeAnnotation?: TSTypeAnnotation; + } + interface ExpressionMap { + TSAsExpression: TSAsExpression; + TSSatisfiesExpression: TSSatisfiesExpression; + } + interface NodeMap { + TSModuleDeclaration: TSModuleDeclaration; + TSInterfaceDeclaration: TSInterfaceDeclaration; + } + interface ImportDeclaration { + importKind: "type" | "value"; + } +} +declare function parseYaml$1(content: string): ReturnType; +type CommentType = { + type: "Line" | "Block"; + value: string; +}; +declare class Comments { + private original; + private leading; + private trailing; + constructor(); + add(node: BaseNode$1, comment: CommentType, options?: { + position?: "leading" | "trailing"; + }): void; + remove(predicate: (comment: estree.Comment) => boolean | undefined | null): void; +} +type ParseBase = { + source: string; + + generateCode(): string; +}; +declare function parseScript(source: string): { + ast: estree.Program; + comments: Comments; +} & ParseBase; +declare function parseCss(source: string): { + ast: Omit; +} & ParseBase; +declare function parseHtml(source: string): { + ast: SvelteAst.Fragment; +} & ParseBase; +declare function parseJson(source: string): { + data: any; +} & ParseBase; +declare function parseYaml(source: string): { + data: ReturnType; +} & ParseBase; +declare function parseSvelte(source: string): { + ast: SvelteAst.Root; +} & ParseBase; +declare function parseToml(source: string): { + data: TomlTable; +} & ParseBase; +interface DedentOptions { + alignValues?: boolean; + escapeSpecialCharacters?: boolean; + trimWhitespace?: boolean; +} +interface Dedent { + (literals: string): string; + (strings: TemplateStringsArray, ...values: unknown[]): string; + withOptions: CreateDedent; +} +type CreateDedent = (options: DedentOptions) => Dedent; +declare const dedent: Dedent; +declare module 'zimmerframe' { + export function walk | null>(node: T, state: U, visitors: Visitors): T; + type BaseNode = { + type: string; + }; + type NodeOf = X extends { + type: T; + } ? X : never; + type SpecialisedVisitors = { [K in T['type']]?: Visitor, U, T> }; + export type Visitor = (node: T, context: Context) => V | void; + export type Visitors = T['type'] extends '_' ? never : SpecialisedVisitors & { + _?: Visitor; + }; + export interface Context { + next: (state?: U) => T | void; + path: T[]; + state: U; + stop: () => void; + visit: (node: T, state?: U) => T; + } + export {}; +} //# sourceMappingURL=index.d.ts.map +declare namespace index_d_exports$1 { + export { addAtRule, addDeclaration, addImports, addRule }; +} +declare function addRule(node: SvelteAst.CSS.StyleSheetBase, options: { + selector: string; +}): SvelteAst.CSS.Rule; +declare function addDeclaration(node: SvelteAst.CSS.Rule, options: { + property: string; + value: string; +}): void; +declare function addImports(node: SvelteAst.CSS.StyleSheetBase, options: { + imports: string[]; +}): void; +declare function addAtRule(node: SvelteAst.CSS.StyleSheetBase, options: { + name: string; + params: string; + append: boolean; +}): SvelteAst.CSS.Atrule; +declare namespace array_d_exports { + export { append, create$1 as create, prepend }; +} +declare function create$1(): estree.ArrayExpression; +declare function append(node: estree.ArrayExpression, element: string | estree.Expression | estree.SpreadElement): void; +declare function prepend(node: estree.ArrayExpression, element: string | estree.Expression | estree.SpreadElement): void; +declare namespace object_d_exports { + export { create, overrideProperties, property, propertyNode }; +} +type ObjectPrimitiveValues = string | number | boolean | undefined | null; +type ObjectValues = ObjectPrimitiveValues | Record | ObjectValues[]; +type ObjectMap = Record; +declare function property(node: estree.ObjectExpression, options: { + name: string; + fallback: T; +}): T; +declare function propertyNode(node: estree.ObjectExpression, options: { + name: string; + fallback: T; +}): estree.Property; +declare function create(properties: ObjectMap): estree.ObjectExpression; +declare function overrideProperties(objectExpression: estree.ObjectExpression, properties: ObjectMap): void; +declare namespace common_d_exports { + export { addJsDocComment, addJsDocTypeComment, appendFromString, appendStatement, areNodesEqual, contains, createBlockStatement, createExpressionStatement, createLiteral, createSatisfies, createSpread, createTypeProperty, hasTypeProperty, parseExpression, parseFromString, parseStatement, typeAnnotate }; +} +declare function addJsDocTypeComment(node: estree.Node, comments: Comments, options: { + type: string; +}): void; +declare function addJsDocComment(node: estree.Node, comments: Comments, options: { + params: Record; +}): void; +declare function typeAnnotate(node: estree.Expression, options: { + type: string; +}): estree.TSAsExpression; +declare function createSatisfies(node: estree.Expression, options: { + type: string; +}): estree.TSSatisfiesExpression; +declare function createSpread(argument: estree.Expression): estree.SpreadElement; +declare function createLiteral(value: string | number | boolean | null): estree.Literal; +declare function areNodesEqual(node: estree.Node, otherNode: estree.Node): boolean; +declare function createBlockStatement(): estree.BlockStatement; +declare function createExpressionStatement(options: { + expression: estree.Expression; +}): estree.ExpressionStatement; +declare function appendFromString(node: estree.BlockStatement | estree.Program, options: { + code: string; + comments?: Comments; +}): void; +declare function parseExpression(code: string): estree.Expression; +declare function parseStatement(code: string): estree.Statement; +declare function parseFromString(code: string): T; + +declare function appendStatement(node: estree.BlockStatement | estree.Program, options: { + statement: estree.Statement; +}): void; + +declare function contains(node: estree.Node, targetNode: estree.Node): boolean; +declare function hasTypeProperty(node: estree.TSInterfaceDeclaration["body"]["body"][number], options: { + name: string; +}): boolean; +declare function createTypeProperty(name: string, value: string, optional?: boolean): estree.TSInterfaceBody["body"][number]; +declare namespace function_d_exports { + export { createArrow, createCall, getArgument }; +} +declare function createCall(options: { + name: string; + args: string[]; + useIdentifiers?: boolean; +}): estree.CallExpression; +declare function createArrow(options: { + body: estree.Expression | estree.BlockStatement; + async: boolean; +}): estree.ArrowFunctionExpression; +declare function getArgument(node: estree.CallExpression, options: { + index: number; + fallback: T; +}): T; +declare namespace imports_d_exports { + export { addDefault, addEmpty, addNamed, addNamespace$1 as addNamespace, find, remove }; +} +declare function addEmpty(node: estree.Program, options: { + from: string; +}): void; +declare function addNamespace$1(node: estree.Program, options: { + from: string; + as: string; +}): void; +declare function addDefault(node: estree.Program, options: { + from: string; + as: string; +}): void; +declare function addNamed(node: estree.Program, options: { + + imports: Record | string[]; + from: string; + isType?: boolean; +}): void; +declare function find(ast: estree.Program, options: { + name: string; + from: string; +}): { + statement: estree.ImportDeclaration; + alias: string; +} | { + statement: undefined; + alias: undefined; +}; +declare function remove(ast: estree.Program, options: { + name: string; + from: string; + statement?: estree.ImportDeclaration; +}): void; +declare namespace variables_d_exports { + export { createIdentifier, declaration, typeAnnotateDeclarator }; +} +declare function declaration(node: estree.Program | estree.Declaration, options: { + kind: "const" | "let" | "var"; + name: string; + value: estree.Expression; +}): estree.VariableDeclaration; +declare function createIdentifier(name: string): estree.Identifier; +declare function typeAnnotateDeclarator(node: estree.VariableDeclarator, options: { + typeName: string; +}): estree.VariableDeclarator; +declare namespace exports_d_exports { + export { ExportDefaultResult, addNamespace, createDefault, createNamed }; +} +type ExportDefaultResult = { + astNode: estree.ExportDefaultDeclaration; + value: T; + isFallback: boolean; +}; +declare function createDefault(node: estree.Program, options: { + fallback: T; +}): ExportDefaultResult; +declare function createNamed(node: estree.Program, options: { + name: string; + fallback: estree.VariableDeclaration; +}): estree.ExportNamedDeclaration; +declare function addNamespace(node: estree.Program, options: { + from: string; + as?: string; +}): void; +declare namespace kit_d_exports { + export { addGlobalAppInterface, addHooksHandle }; +} +declare function addGlobalAppInterface(node: estree.TSProgram, options: { + name: "Error" | "Locals" | "PageData" | "PageState" | "Platform"; +}): estree.TSInterfaceDeclaration; +declare function addHooksHandle(node: estree.Program, options: { + language: "ts" | "js"; + newHandleName: string; + handleContent: string; + comments: Comments; +}): void; +declare namespace vite_d_exports { + export { addPlugin, configProperty, getConfig }; +} +declare const addPlugin: (ast: estree.Program, options: { + code: string; + mode?: "append" | "prepend"; +}) => void; + +declare function configProperty(ast: estree.Program, config: estree.ObjectExpression, options: { + name: string; + fallback: T; +}): T; +declare const getConfig: (ast: estree.Program) => estree.ObjectExpression; +declare namespace index_d_exports$3 { + export { array_d_exports as array, common_d_exports as common, exports_d_exports as exports, function_d_exports as functions, imports_d_exports as imports, kit_d_exports as kit, object_d_exports as object, variables_d_exports as variables, vite_d_exports as vite }; +} +declare namespace index_d_exports$2 { + export { addAttribute, addFromRawHtml, appendElement, createElement, insertElement }; +} +declare function createElement(tagName: string, attributes?: Record): SvelteAst.RegularElement; +declare function addAttribute(element: SvelteAst.RegularElement, name: string, value: string): void; +declare function insertElement(fragment: SvelteAst.Fragment, elementToInsert: SvelteAst.Fragment["nodes"][0]): void; +declare function appendElement(fragment: SvelteAst.Fragment, elementToAppend: SvelteAst.Fragment["nodes"][0]): void; +declare function addFromRawHtml(fragment: SvelteAst.Fragment, html: string): void; +declare namespace text_d_exports { + export { upsert }; +} +type CommentEntry = { + text: string; + mode: "append" | "prepend"; +}; +type CommentOption = string | Array; + +declare function upsert(content: string, key: string, options?: { + value?: string; + comment?: CommentOption; + separator?: boolean; +}): string; +declare namespace json_d_exports { + export { arrayUpsert, packageScriptsUpsert }; +} +declare function arrayUpsert(data: any, key: string, value: any, options?: { + mode?: "append" | "prepend"; +}): void; +declare function packageScriptsUpsert(data: any, key: string, value: string, options?: { + mode?: "append" | "prepend"; +}): void; +declare namespace index_d_exports$4 { + export { RootWithInstance, addFragment, addSlot, ensureScript }; +} +type RootWithInstance = SvelteAst.Root & { + instance: SvelteAst.Script; +}; +declare function ensureScript(ast: SvelteAst.Root, options?: { + language?: "ts" | "js"; +}): asserts ast is RootWithInstance; +declare function addSlot(ast: SvelteAst.Root, options: { + svelteVersion: string; + language?: "ts" | "js"; +}): void; +declare function addFragment(ast: SvelteAst.Root, content: string, options?: { + mode?: "append" | "prepend"; +}): void; +type TransformFn = (content: string) => string; +type TransformOptions = { + onError?: (error: unknown) => void; +}; + +declare const transforms: { + + script(cb: (file: { + ast: estree.Program; + comments: Comments; + content: string; + js: typeof index_d_exports$3; + }) => void | false, options?: TransformOptions): (content: string) => string; + + svelte(cb: (file: { + ast: SvelteAst.Root; + content: string; + svelte: typeof index_d_exports$4; + js: typeof index_d_exports$3; + }) => void | false, options?: TransformOptions): (content: string) => string; + + svelteScript(scriptOptions: { + language: "ts" | "js"; + }, cb: (file: { + ast: RootWithInstance; + content: string; + svelte: typeof index_d_exports$4; + js: typeof index_d_exports$3; + }) => void | false, options?: TransformOptions): TransformFn; + + css(cb: (file: { + ast: Omit; + content: string; + css: typeof index_d_exports$1; + }) => void | false, options?: TransformOptions): TransformFn; + + json(cb: (file: { + data: T; + content: string; + json: typeof json_d_exports; + }) => void | false, options?: TransformOptions): TransformFn; + + yaml(cb: (file: { + data: ReturnType["data"]; + content: string; + }) => void | false, options?: TransformOptions): TransformFn; + + toml(cb: (file: { + data: TomlTable; + content: string; + }) => void | false, options?: TransformOptions): TransformFn; + + html(cb: (file: { + ast: SvelteAst.Fragment; + content: string; + html: typeof index_d_exports$2; + }) => void | false, options?: TransformOptions): TransformFn; + + text(cb: (file: { + content: string; + text: typeof text_d_exports; + }) => string | false): TransformFn; +}; +type Version = { + major?: number; + minor?: number; + patch?: number; +}; +declare function splitVersion(str: string): Version; +declare function isVersionUnsupportedBelow(versionStr: string, belowStr: string): boolean | undefined; +type Printer = (content: string, alt?: string) => string; +declare function createPrinter(...conditions: boolean[]): Printer[]; + +declare function sanitizeName(name: string, style: "package" | "wrangler"): string; +declare const downloadJson: (url: string) => Promise; +type Package = { + name: string; + version: string; + dependencies?: Record; + devDependencies?: Record; + bugs?: string; + repository?: { + type: string; + url: string; + }; + keywords?: string[]; + workspaces?: string[]; +}; +declare function getPackageJson(cwd: string): { + source: string; + data: Package; + generateCode: () => string; +}; +declare function readFile(cwd: string, filePath: string): string; +declare function fileExists(cwd: string, filePath: string): boolean; +declare function writeFile(cwd: string, filePath: string, content: string): void; +declare function installPackages(dependencies: Array<{ + pkg: string; + version: string; + dev: boolean; +}>, cwd: string): string; +declare const commonFilePaths: { + readonly packageJson: "package.json"; + readonly svelteConfig: "svelte.config.js"; + readonly svelteConfigTS: "svelte.config.ts"; + readonly jsconfig: "jsconfig.json"; + readonly tsconfig: "tsconfig.json"; + readonly viteConfig: "vite.config.js"; + readonly viteConfigTS: "vite.config.ts"; +}; +type ColorInput = string | string[]; +declare const color: { + addon: (str: ColorInput) => string; + command: (str: ColorInput) => string; + env: (str: ColorInput) => string; + path: (str: ColorInput) => string; + route: (str: ColorInput) => string; + website: (str: ColorInput) => string; + optional: (str: ColorInput) => string; + dim: (str: ColorInput) => string; + success: (str: ColorInput) => string; + warning: (str: ColorInput) => string; + error: (str: ColorInput) => string; + hidden: (str: ColorInput) => string; +}; + +declare function resolveCommandArray(agent: Agent, command: Command, args: string[]): string[]; + +declare const parse: { + css: typeof parseCss; + html: typeof parseHtml; + json: typeof parseJson; + script: typeof parseScript; + svelte: typeof parseSvelte; + toml: typeof parseToml; + yaml: typeof parseYaml; +}; +export { AGENTS, type AgentName, type estree as AstTypes, COMMANDS, type Comments, type Package, type SvelteAst, type TransformFn, index_d_exports as Walker, color, commonFilePaths, constructCommand, createPrinter, index_d_exports$1 as css, dedent, detect, downloadJson, fileExists, getPackageJson, index_d_exports$2 as html, installPackages, isVersionUnsupportedBelow, index_d_exports$3 as js, json_d_exports as json, parse, readFile, resolveCommand, resolveCommandArray, sanitizeName, splitVersion, index_d_exports$4 as svelte, text_d_exports as text, transforms, writeFile }; +``` diff --git a/packages/sv/api-surface-testing.md b/packages/sv/api-surface-testing.md new file mode 100644 index 000000000..116eefd8c --- /dev/null +++ b/packages/sv/api-surface-testing.md @@ -0,0 +1,109 @@ +# sv (testing) - Public API Surface + + + +```ts +declare function addPnpmBuildDependencies(cwd: string, packageManager: AgentName | null | undefined, allowedPackages: string[]): Promise; +type ProjectVariant = "kit-js" | "kit-ts" | "vite-js" | "vite-ts"; +declare const variants: ProjectVariant[]; +type CreateProject = (options: { + testId: string; + variant: ProjectVariant; + clean?: boolean; +}) => string; +type SetupOptions = { + cwd: string; + variants: readonly ProjectVariant[]; + clean?: boolean; +}; +declare function setup({ + cwd, + clean, + variants +}: SetupOptions): { + templatesDir: string; +}; +type CreateOptions = { + cwd: string; + testName: string; + templatesDir: string; +}; +declare function createProject({ + cwd, + testName, + templatesDir +}: CreateOptions): CreateProject; +type PreviewOptions = { + cwd: string; + command?: string; +}; +declare function startPreview({ + cwd, + command +}: PreviewOptions): Promise<{ + url: string; + close: () => Promise; +}>; +declare module "vitest" { + interface ProvidedContext { + testDir: string; + templatesDir: string; + variants: ProjectVariant[]; + } +} +declare function setupGlobal({ + TEST_DIR, + pre, + post +}: { + TEST_DIR: string; + pre?: () => Promise; + post?: () => Promise; +}): ({ + provide +}: TestProject) => Promise<() => Promise>; +type Fixtures = { + page: Page; + cwd(addonTestCase: AddonTestCase): string; +}; +type AddonTestCase = { + variant: ProjectVariant; + kind: { + type: string; + options: OptionMap; + }; +}; +type SetupTestOptions = { + kinds: Array["kind"]>; + filter?: (addonTestCase: AddonTestCase) => boolean; + browser?: boolean; + preAdd?: (o: { + addonTestCase: AddonTestCase; + cwd: string; + }) => Promise | void; +}; +type PrepareServerOptions = { + cwd: string; + page: Page; + buildCommand?: string; + previewCommand?: string; +}; +type PrepareServerReturn = { + url: string; + close: () => Promise; +}; +declare function prepareServer({ + cwd, + page, + buildCommand, + previewCommand +}: PrepareServerOptions): Promise; +type PlaywrightContext = Pick; +type VitestContext = Pick; +declare function createSetupTest(vitest: VitestContext, playwright?: PlaywrightContext): (addons: Addons, options?: SetupTestOptions) => { + test: vitest.TestAPI; + testCases: Array>; + prepareServer: typeof prepareServer; +}; +export { AddonTestCase, CreateProject, Fixtures, PlaywrightContext, PrepareServerOptions, PrepareServerReturn, ProjectVariant, SetupTestOptions, VitestContext, addPnpmBuildDependencies, createProject, createSetupTest, prepareServer, setup, setupGlobal, startPreview, variants }; +``` diff --git a/packages/sv/api-surface.md b/packages/sv/api-surface.md new file mode 100644 index 000000000..d5ecc3556 --- /dev/null +++ b/packages/sv/api-surface.md @@ -0,0 +1,25 @@ +# sv - Public API Surface + + + +```ts +type TemplateType = (typeof templateTypes)[number]; +type LanguageType = (typeof languageTypes)[number]; +declare const templateTypes: readonly ["minimal", "demo", "library", "addon", "svelte"]; +declare const languageTypes: readonly ["typescript", "checkjs", "none"]; +type Options = { + name: string; + template: TemplateType; + types: LanguageType; +}; +declare function create(cwd: string, options: Options): void; +type FileEditor = Workspace & { + content: string; +}; +type FileType = { + name: (options: Workspace) => string; + condition?: ConditionDefinition; + content: (editor: FileEditor) => string; +}; +export { Addon, AddonDefinition, AddonInput, type AddonMap, AddonReference, AddonResult, AddonSource, BaseQuestion, BooleanQuestion, ConditionDefinition, ConfiguredAddon, FileEditor, FileType, type InstallOptions, type LanguageType, LoadedAddon, MultiSelectQuestion, NumberQuestion, OptionBuilder, OptionDefinition, type OptionMap, OptionValues, PackageDefinition, PreparedAddon, Question, Scripts, SelectQuestion, SetupResult, StringQuestion, SvApi, type TemplateType, TestDefinition, Tests, Verification, Workspace, WorkspaceOptions, add, create, createWorkspace, defineAddon, defineAddonOptions, getErrorHint, officialAddons }; +``` From 7650cf374b402e6604db7f8ea76c44ce97388b2e Mon Sep 17 00:00:00 2001 From: jycouet Date: Sat, 4 Apr 2026 12:38:18 +0200 Subject: [PATCH 3/7] align --- packages/sv-utils/api-surface.md | 3 ++ packages/sv-utils/src/files.ts | 3 ++ packages/sv-utils/src/index.ts | 4 ++- packages/sv/api-surface-testing.md | 3 ++ packages/sv/api-surface.md | 9 +++-- packages/sv/src/cli/create.ts | 3 +- packages/sv/src/core/engine.ts | 4 +-- packages/sv/src/core/processors.ts | 2 ++ packages/sv/src/core/workspace.ts | 5 +++ packages/sv/src/create/index.ts | 23 +++++++++++-- packages/sv/src/create/tests/check.ts | 2 +- packages/sv/src/create/tests/playground.ts | 6 ++-- packages/sv/src/index.ts | 40 +++++++++++++++++++--- packages/sv/src/testing.ts | 12 ++++--- 14 files changed, 99 insertions(+), 20 deletions(-) diff --git a/packages/sv-utils/api-surface.md b/packages/sv-utils/api-surface.md index 983b6d046..75a9b392c 100644 --- a/packages/sv-utils/api-surface.md +++ b/packages/sv-utils/api-surface.md @@ -1265,6 +1265,9 @@ declare function getPackageJson(cwd: string): { declare function readFile(cwd: string, filePath: string): string; declare function fileExists(cwd: string, filePath: string): boolean; declare function writeFile(cwd: string, filePath: string, content: string): void; +/** +* @deprecated Internal to sv — merged into `package.json` by the add-on runner only. Will be removed from the public API in a future version. +*/ declare function installPackages(dependencies: Array<{ pkg: string; version: string; diff --git a/packages/sv-utils/src/files.ts b/packages/sv-utils/src/files.ts index 4dd22c359..8212a637b 100644 --- a/packages/sv-utils/src/files.ts +++ b/packages/sv-utils/src/files.ts @@ -58,6 +58,9 @@ export function writeFile(cwd: string, filePath: string, content: string): void fs.writeFileSync(fullFilePath, content, 'utf8'); } +/** + * @deprecated Internal to sv — merged into `package.json` by the add-on runner only. Will be removed from the public API in a future version. + */ export function installPackages( dependencies: Array<{ pkg: string; version: string; dev: boolean }>, cwd: string diff --git a/packages/sv-utils/src/index.ts b/packages/sv-utils/src/index.ts index 29005fa4a..965a974fd 100644 --- a/packages/sv-utils/src/index.ts +++ b/packages/sv-utils/src/index.ts @@ -82,12 +82,14 @@ export { commonFilePaths, fileExists, getPackageJson, - installPackages, readFile, writeFile, type Package } from './files.ts'; +/** @deprecated Internal to sv — will be removed from the public API in a future version. */ +export { installPackages } from './files.ts'; + // Terminal styling export { color } from './color.ts'; diff --git a/packages/sv/api-surface-testing.md b/packages/sv/api-surface-testing.md index 116eefd8c..7ce75ece3 100644 --- a/packages/sv/api-surface-testing.md +++ b/packages/sv/api-surface-testing.md @@ -16,6 +16,7 @@ type SetupOptions = { variants: readonly ProjectVariant[]; clean?: boolean; }; +/** @deprecated Internal helper used by `createSetupTest` - will be removed from public API in a future version. */ declare function setup({ cwd, clean, @@ -28,6 +29,7 @@ type CreateOptions = { testName: string; templatesDir: string; }; +/** @deprecated Internal helper used by `createSetupTest` - will be removed from public API in a future version. */ declare function createProject({ cwd, testName, @@ -37,6 +39,7 @@ type PreviewOptions = { cwd: string; command?: string; }; +/** @deprecated Internal helper used by `prepareServer` - will be removed from public API in a future version. */ declare function startPreview({ cwd, command diff --git a/packages/sv/api-surface.md b/packages/sv/api-surface.md index d5ecc3556..ab42a9bb4 100644 --- a/packages/sv/api-surface.md +++ b/packages/sv/api-surface.md @@ -8,18 +8,23 @@ type LanguageType = (typeof languageTypes)[number]; declare const templateTypes: readonly ["minimal", "demo", "library", "addon", "svelte"]; declare const languageTypes: readonly ["typescript", "checkjs", "none"]; type Options = { + cwd: string; name: string; template: TemplateType; types: LanguageType; }; -declare function create(cwd: string, options: Options): void; +/** @deprecated Use `create({ cwd, name, template, types })` instead. */ +declare function create(cwd: string, options: Omit): void; +declare function create(options: Options): void; +/** @deprecated Unused type, will be removed in a future version. */ type FileEditor = Workspace & { content: string; }; +/** @deprecated Unused type, will be removed in a future version. */ type FileType = { name: (options: Workspace) => string; condition?: ConditionDefinition; content: (editor: FileEditor) => string; }; -export { Addon, AddonDefinition, AddonInput, type AddonMap, AddonReference, AddonResult, AddonSource, BaseQuestion, BooleanQuestion, ConditionDefinition, ConfiguredAddon, FileEditor, FileType, type InstallOptions, type LanguageType, LoadedAddon, MultiSelectQuestion, NumberQuestion, OptionBuilder, OptionDefinition, type OptionMap, OptionValues, PackageDefinition, PreparedAddon, Question, Scripts, SelectQuestion, SetupResult, StringQuestion, SvApi, type TemplateType, TestDefinition, Tests, Verification, Workspace, WorkspaceOptions, add, create, createWorkspace, defineAddon, defineAddonOptions, getErrorHint, officialAddons }; +export { type Addon, type AddonDefinition, type AddonInput, type AddonMap, type AddonReference, type AddonResult, type AddonSource, type BaseQuestion, type BooleanQuestion, type ConfiguredAddon, type FileEditor, type FileType, type InstallOptions, type LanguageType, type LoadedAddon, type MultiSelectQuestion, type NumberQuestion, type OptionBuilder, type OptionDefinition, type OptionMap, type OptionValues, type PreparedAddon, type Question, type SelectQuestion, type SetupResult, type StringQuestion, type SvApi, type TemplateType, type Workspace, type WorkspaceOptions, add, create, defineAddon, defineAddonOptions, officialAddons }; ``` diff --git a/packages/sv/src/cli/create.ts b/packages/sv/src/cli/create.ts index 65697c24e..8d0722015 100644 --- a/packages/sv/src/cli/create.ts +++ b/packages/sv/src/cli/create.ts @@ -324,7 +324,8 @@ async function createProject(cwd: ProjectPath, options: Options) { answers = result.answers; } - createKit(projectPath, { + createKit({ + cwd: projectPath, name: projectName, template, types: language diff --git a/packages/sv/src/core/engine.ts b/packages/sv/src/core/engine.ts index b0bc4d053..99a1edba1 100644 --- a/packages/sv/src/core/engine.ts +++ b/packages/sv/src/core/engine.ts @@ -4,7 +4,7 @@ import { resolveCommand, type AgentName, fileExists, - installPackages, + installPackages as updatePackages, readFile, writeFile } from '@sveltejs/sv-utils'; @@ -250,7 +250,7 @@ async function runAddon({ addon, loaded, multiple, workspace, workspaceOptions } } if (cancels.length === 0) { - const pkgPath = installPackages(dependencies, workspace.cwd); + const pkgPath = updatePackages(dependencies, workspace.cwd); files.add(pkgPath); } diff --git a/packages/sv/src/core/processors.ts b/packages/sv/src/core/processors.ts index bde28a7c1..a56240d15 100644 --- a/packages/sv/src/core/processors.ts +++ b/packages/sv/src/core/processors.ts @@ -1,8 +1,10 @@ import type { ConditionDefinition } from './config.ts'; import type { Workspace } from './workspace.ts'; +/** @deprecated Unused type, will be removed in a future version. */ export type FileEditor = Workspace & { content: string }; +/** @deprecated Unused type, will be removed in a future version. */ export type FileType = { name: (options: Workspace) => string; condition?: ConditionDefinition; diff --git a/packages/sv/src/core/workspace.ts b/packages/sv/src/core/workspace.ts index 987787419..4efb8c136 100644 --- a/packages/sv/src/core/workspace.ts +++ b/packages/sv/src/core/workspace.ts @@ -37,11 +37,16 @@ export type Workspace = { package: 'package.json'; gitignore: '.gitignore'; + /** @deprecated Addon-specific path - use the string literal '.prettierignore' directly. Will be removed in a future version. */ prettierignore: '.prettierignore'; + /** @deprecated Addon-specific path - use the string literal '.prettierrc' directly. Will be removed in a future version. */ prettierrc: '.prettierrc'; + /** @deprecated Addon-specific path - use the string literal 'eslint.config.js' directly. Will be removed in a future version. */ eslintConfig: 'eslint.config.js'; + /** @deprecated Addon-specific path - use the string literal '.vscode/settings.json' directly. Will be removed in a future version. */ vscodeSettings: '.vscode/settings.json'; + /** @deprecated Addon-specific path - use the string literal '.vscode/extensions.json' directly. Will be removed in a future version. */ vscodeExtensions: '.vscode/extensions.json'; /** Get the relative path between two files */ diff --git a/packages/sv/src/create/index.ts b/packages/sv/src/create/index.ts index 5a2947cbe..5ee524d0c 100644 --- a/packages/sv/src/create/index.ts +++ b/packages/sv/src/create/index.ts @@ -11,6 +11,7 @@ const templateTypes = ['minimal', 'demo', 'library', 'addon', 'svelte'] as const const languageTypes = ['typescript', 'checkjs', 'none'] as const; export type Options = { + cwd: string; name: string; template: TemplateType; types: LanguageType; @@ -32,7 +33,23 @@ export type Common = { }>; }; -export function create(cwd: string, options: Options): void { +/** @deprecated Use `create({ cwd, name, template, types })` instead. */ +export function create(cwd: string, options: Omit): void; +export function create(options: Options): void; +export function create( + cwdOrOptions: string | Options, + legacyOptions?: Omit +): void { + let cwd: string; + let options: Omit; + if (typeof cwdOrOptions === 'string') { + cwd = cwdOrOptions; + options = legacyOptions!; + } else { + cwd = cwdOrOptions.cwd; + options = cwdOrOptions; + } + mkdirp(cwd); write_template_files(options.template, options.types, options.name, cwd); @@ -76,7 +93,7 @@ function write_template_files(template: string, types: LanguageType, name: strin }); } -function write_common_files(cwd: string, options: Options, name: string) { +function write_common_files(cwd: string, options: Omit, name: string) { const files = getSharedFiles(); const pkg_file = path.join(cwd, commonFilePaths.packageJson); @@ -105,7 +122,7 @@ function write_common_files(cwd: string, options: Options, name: string) { fs.writeFileSync(pkg_file, JSON.stringify(pkg, null, '\t') + '\n'); } -function matches_condition(condition: Condition, options: Options) { +function matches_condition(condition: Condition, options: Omit) { if (templateTypes.includes(condition as TemplateType)) { return options.template === condition; } diff --git a/packages/sv/src/create/tests/check.ts b/packages/sv/src/create/tests/check.ts index e00b3c33f..c214a375b 100644 --- a/packages/sv/src/create/tests/check.ts +++ b/packages/sv/src/create/tests/check.ts @@ -42,7 +42,7 @@ for (const template of templates.filter((t) => t !== 'addon')) { const cwd = path.join(test_workspace_dir, `${template}-${types}`); fs.rmSync(cwd, { recursive: true, force: true }); - create(cwd, { name: `create-svelte-test-${template}-${types}`, template, types }); + create({ cwd, name: `create-svelte-test-${template}-${types}`, template, types }); await add({ cwd, addons: { eslint: officialAddons.eslint }, options: { eslint: {} } }); const pkg = JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), 'utf-8')); diff --git a/packages/sv/src/create/tests/playground.ts b/packages/sv/src/create/tests/playground.ts index fbc79b5d1..5d7778de0 100644 --- a/packages/sv/src/create/tests/playground.ts +++ b/packages/sv/src/create/tests/playground.ts @@ -153,7 +153,8 @@ test('real world download and convert playground async', async () => { fs.rmSync(directory, { recursive: true }); } - create(directory, { + create({ + cwd: directory, name: 'real-world-playground', template: 'minimal', types: 'typescript' @@ -204,7 +205,8 @@ test('real world download and convert playground without async', async () => { fs.rmSync(directory, { recursive: true }); } - create(directory, { + create({ + cwd: directory, name: 'real-world-playground-old', template: 'minimal', types: 'typescript' diff --git a/packages/sv/src/index.ts b/packages/sv/src/index.ts index 874abb260..6b5c64d4a 100644 --- a/packages/sv/src/index.ts +++ b/packages/sv/src/index.ts @@ -4,7 +4,39 @@ export type { AddonMap, InstallOptions, OptionMap } from './core/engine.ts'; export { officialAddons } from './addons/index.ts'; // Addon authoring API export { defineAddon, defineAddonOptions } from './core/config.ts'; -export type * from './core/processors.ts'; -export type * from './core/options.ts'; -export type * from './core/config.ts'; -export type * from './core/workspace.ts'; + +// options.ts - question types for addon options +export type { + Question, + OptionDefinition, + OptionValues, + BooleanQuestion, + StringQuestion, + NumberQuestion, + SelectQuestion, + MultiSelectQuestion, + BaseQuestion +} from './core/options.ts'; + +// config.ts - addon definition and pipeline types +export type { + Addon, + SvApi, + AddonDefinition, + SetupResult, + OptionBuilder, + AddonInput, + AddonSource, + AddonReference, + LoadedAddon, + PreparedAddon, + ConfiguredAddon, + AddonResult +} from './core/config.ts'; + +// workspace.ts +export type { Workspace, WorkspaceOptions } from './core/workspace.ts'; + +// processors.ts - deprecated, will be removed +/** @deprecated Unused type, will be removed in a future version. */ +export type { FileEditor, FileType } from './core/processors.ts'; diff --git a/packages/sv/src/testing.ts b/packages/sv/src/testing.ts index 285592dd5..5c892e605 100644 --- a/packages/sv/src/testing.ts +++ b/packages/sv/src/testing.ts @@ -10,6 +10,7 @@ import { add, type AddonMap, type OptionMap } from './core/engine.ts'; import { addPnpmBuildDependencies } from './core/package-manager.ts'; import { create } from './create/index.ts'; +/** @deprecated Internal helper - will be removed from public API in a future version. */ export { addPnpmBuildDependencies } from './core/package-manager.ts'; export type ProjectVariant = 'kit-js' | 'kit-ts' | 'vite-js' | 'vite-ts'; export const variants: ProjectVariant[] = ['kit-js', 'kit-ts', 'vite-js', 'vite-ts']; @@ -29,6 +30,7 @@ type SetupOptions = { /** @default false */ clean?: boolean; }; +/** @deprecated Internal helper used by `createSetupTest` - will be removed from public API in a future version. */ export function setup({ cwd, clean = false, variants }: SetupOptions): { templatesDir: string } { const workingDir = path.resolve(cwd); if (clean && fs.existsSync(workingDir)) { @@ -43,13 +45,13 @@ export function setup({ cwd, clean = false, variants }: SetupOptions): { templat if (fs.existsSync(templatePath)) continue; if (variant === 'kit-js') { - create(templatePath, { name: variant, template: 'minimal', types: 'checkjs' }); + create({ cwd: templatePath, name: variant, template: 'minimal', types: 'checkjs' }); } else if (variant === 'kit-ts') { - create(templatePath, { name: variant, template: 'minimal', types: 'typescript' }); + create({ cwd: templatePath, name: variant, template: 'minimal', types: 'typescript' }); } else if (variant === 'vite-js') { - create(templatePath, { name: variant, template: 'svelte', types: 'none' }); + create({ cwd: templatePath, name: variant, template: 'svelte', types: 'none' }); } else if (variant === 'vite-ts') { - create(templatePath, { name: variant, template: 'svelte', types: 'typescript' }); + create({ cwd: templatePath, name: variant, template: 'svelte', types: 'typescript' }); } else { throw new Error(`Unknown project variant: ${variant}`); } @@ -59,6 +61,7 @@ export function setup({ cwd, clean = false, variants }: SetupOptions): { templat } type CreateOptions = { cwd: string; testName: string; templatesDir: string }; +/** @deprecated Internal helper used by `createSetupTest` - will be removed from public API in a future version. */ export function createProject({ cwd, testName, templatesDir }: CreateOptions): CreateProject { // create the reference dir const testDir = path.resolve(cwd, testName); @@ -75,6 +78,7 @@ export function createProject({ cwd, testName, templatesDir }: CreateOptions): C } type PreviewOptions = { cwd: string; command?: string }; +/** @deprecated Internal helper used by `prepareServer` - will be removed from public API in a future version. */ export async function startPreview({ cwd, command = 'npm run preview' From bed20838aa50d248fb466f3e8c314e5b359cc604 Mon Sep 17 00:00:00 2001 From: jycouet Date: Sat, 4 Apr 2026 12:47:59 +0200 Subject: [PATCH 4/7] refactor: loadFile/saveFile/loadPackageJson; trim workspace addon paths - sv-utils: add loadFile, saveFile, loadPackageJson; deprecate readFile, writeFile, getPackageJson; remove installPackages (logic lives in sv engine). - sv: inline updatePackages in engine; use new helpers; drop deprecated workspace.file paths; addons use string literals; remove stale @deprecated on processors/create exports. - Regenerate api-surface snapshots. Made-with: Cursor --- packages/sv-utils/api-surface.md | 34 ++++---- packages/sv-utils/src/files.ts | 92 ++++++++------------- packages/sv-utils/src/index.ts | 16 ++-- packages/sv/api-surface.md | 3 - packages/sv/src/addons/drizzle.ts | 2 +- packages/sv/src/addons/eslint.ts | 6 +- packages/sv/src/addons/prettier.ts | 8 +- packages/sv/src/addons/sveltekit-adapter.ts | 4 +- packages/sv/src/addons/tailwindcss.ts | 6 +- packages/sv/src/cli/create.ts | 4 +- packages/sv/src/core/engine.ts | 43 ++++++++-- packages/sv/src/core/processors.ts | 2 - packages/sv/src/core/workspace.ts | 27 ++---- packages/sv/src/create/index.ts | 1 - packages/sv/src/index.ts | 2 - 15 files changed, 119 insertions(+), 131 deletions(-) diff --git a/packages/sv-utils/api-surface.md b/packages/sv-utils/api-surface.md index 75a9b392c..dba9a2978 100644 --- a/packages/sv-utils/api-surface.md +++ b/packages/sv-utils/api-surface.md @@ -1257,22 +1257,6 @@ type Package = { keywords?: string[]; workspaces?: string[]; }; -declare function getPackageJson(cwd: string): { - source: string; - data: Package; - generateCode: () => string; -}; -declare function readFile(cwd: string, filePath: string): string; -declare function fileExists(cwd: string, filePath: string): boolean; -declare function writeFile(cwd: string, filePath: string, content: string): void; -/** -* @deprecated Internal to sv — merged into `package.json` by the add-on runner only. Will be removed from the public API in a future version. -*/ -declare function installPackages(dependencies: Array<{ - pkg: string; - version: string; - dev: boolean; -}>, cwd: string): string; declare const commonFilePaths: { readonly packageJson: "package.json"; readonly svelteConfig: "svelte.config.js"; @@ -1282,6 +1266,22 @@ declare const commonFilePaths: { readonly viteConfig: "vite.config.js"; readonly viteConfigTS: "vite.config.ts"; }; +declare function fileExists(cwd: string, filePath: string): boolean; + +declare function loadFile(cwd: string, filePath: string): string; + +declare function saveFile(cwd: string, filePath: string, content: string): void; +declare function loadPackageJson(cwd: string): { + source: string; + data: Package; + generateCode: () => string; +}; +/** @deprecated Use `loadFile` instead. */ +declare const readFile: typeof loadFile; +/** @deprecated Use `saveFile` instead. */ +declare const writeFile: typeof saveFile; +/** @deprecated Use `loadPackageJson` instead. */ +declare const getPackageJson: typeof loadPackageJson; type ColorInput = string | string[]; declare const color: { addon: (str: ColorInput) => string; @@ -1309,5 +1309,5 @@ declare const parse: { toml: typeof parseToml; yaml: typeof parseYaml; }; -export { AGENTS, type AgentName, type estree as AstTypes, COMMANDS, type Comments, type Package, type SvelteAst, type TransformFn, index_d_exports as Walker, color, commonFilePaths, constructCommand, createPrinter, index_d_exports$1 as css, dedent, detect, downloadJson, fileExists, getPackageJson, index_d_exports$2 as html, installPackages, isVersionUnsupportedBelow, index_d_exports$3 as js, json_d_exports as json, parse, readFile, resolveCommand, resolveCommandArray, sanitizeName, splitVersion, index_d_exports$4 as svelte, text_d_exports as text, transforms, writeFile }; +export { AGENTS, type AgentName, type estree as AstTypes, COMMANDS, type Comments, type Package, type SvelteAst, type TransformFn, index_d_exports as Walker, color, commonFilePaths, constructCommand, createPrinter, index_d_exports$1 as css, dedent, detect, downloadJson, fileExists, getPackageJson, index_d_exports$2 as html, isVersionUnsupportedBelow, index_d_exports$3 as js, json_d_exports as json, loadFile, loadPackageJson, parse, readFile, resolveCommand, resolveCommandArray, sanitizeName, saveFile, splitVersion, index_d_exports$4 as svelte, text_d_exports as text, transforms, writeFile }; ``` diff --git a/packages/sv-utils/src/files.ts b/packages/sv-utils/src/files.ts index 8212a637b..540e80602 100644 --- a/packages/sv-utils/src/files.ts +++ b/packages/sv-utils/src/files.ts @@ -13,22 +13,23 @@ export type Package = { workspaces?: string[]; }; -export function getPackageJson(cwd: string): { - source: string; - data: Package; - generateCode: () => string; -} { - const packageText = readFile(cwd, commonFilePaths.packageJson); - if (!packageText) { - const pkgPath = path.join(cwd, commonFilePaths.packageJson); - throw new Error(`Invalid workspace: missing '${pkgPath}'`); - } +export const commonFilePaths = { + packageJson: 'package.json', + svelteConfig: 'svelte.config.js', + svelteConfigTS: 'svelte.config.ts', + jsconfig: 'jsconfig.json', + tsconfig: 'tsconfig.json', + viteConfig: 'vite.config.js', + viteConfigTS: 'vite.config.ts' +} as const; - const { data, generateCode } = parseJson(packageText); - return { source: packageText, data: data as Package, generateCode }; +export function fileExists(cwd: string, filePath: string): boolean { + const fullFilePath = path.resolve(cwd, filePath); + return fs.existsSync(fullFilePath); } -export function readFile(cwd: string, filePath: string): string { +/** Synchronous load of a workspace-relative file as UTF-8 text; missing files yield `''`. */ +export function loadFile(cwd: string, filePath: string): string { const fullFilePath = path.resolve(cwd, filePath); if (!fileExists(cwd, filePath)) { @@ -40,12 +41,8 @@ export function readFile(cwd: string, filePath: string): string { return text; } -export function fileExists(cwd: string, filePath: string): boolean { - const fullFilePath = path.resolve(cwd, filePath); - return fs.existsSync(fullFilePath); -} - -export function writeFile(cwd: string, filePath: string, content: string): void { +/** Synchronous write of a workspace-relative file (creates parent dirs). */ +export function saveFile(cwd: string, filePath: string, content: string): void { const fullFilePath = path.resolve(cwd, filePath); const fullDirectoryPath = path.dirname(fullFilePath); @@ -58,47 +55,26 @@ export function writeFile(cwd: string, filePath: string, content: string): void fs.writeFileSync(fullFilePath, content, 'utf8'); } -/** - * @deprecated Internal to sv — merged into `package.json` by the add-on runner only. Will be removed from the public API in a future version. - */ -export function installPackages( - dependencies: Array<{ pkg: string; version: string; dev: boolean }>, - cwd: string -): string { - const { data, generateCode } = getPackageJson(cwd); - - for (const dependency of dependencies) { - if (dependency.dev) { - data.devDependencies ??= {}; - data.devDependencies[dependency.pkg] = dependency.version; - } else { - data.dependencies ??= {}; - data.dependencies[dependency.pkg] = dependency.version; - } +export function loadPackageJson(cwd: string): { + source: string; + data: Package; + generateCode: () => string; +} { + const packageText = loadFile(cwd, commonFilePaths.packageJson); + if (!packageText) { + const pkgPath = path.join(cwd, commonFilePaths.packageJson); + throw new Error(`Invalid workspace: missing '${pkgPath}'`); } - if (data.dependencies) data.dependencies = alphabetizeProperties(data.dependencies); - if (data.devDependencies) data.devDependencies = alphabetizeProperties(data.devDependencies); - - writeFile(cwd, commonFilePaths.packageJson, generateCode()); - return commonFilePaths.packageJson; + const { data, generateCode } = parseJson(packageText); + return { source: packageText, data: data as Package, generateCode }; } -function alphabetizeProperties(obj: Record) { - const orderedObj: Record = {}; - const sortedEntries = Object.entries(obj).sort(([a], [b]) => a.localeCompare(b)); - for (const [key, value] of sortedEntries) { - orderedObj[key] = value; - } - return orderedObj; -} +/** @deprecated Use {@link loadFile} instead. */ +export const readFile: typeof loadFile = loadFile; -export const commonFilePaths = { - packageJson: 'package.json', - svelteConfig: 'svelte.config.js', - svelteConfigTS: 'svelte.config.ts', - jsconfig: 'jsconfig.json', - tsconfig: 'tsconfig.json', - viteConfig: 'vite.config.js', - viteConfigTS: 'vite.config.ts' -} as const; +/** @deprecated Use {@link saveFile} instead. */ +export const writeFile: typeof saveFile = saveFile; + +/** @deprecated Use {@link loadPackageJson} instead. */ +export const getPackageJson: typeof loadPackageJson = loadPackageJson; diff --git a/packages/sv-utils/src/index.ts b/packages/sv-utils/src/index.ts index 965a974fd..37db2b10b 100644 --- a/packages/sv-utils/src/index.ts +++ b/packages/sv-utils/src/index.ts @@ -77,18 +77,22 @@ export { createPrinter } from './utils.ts'; export { sanitizeName } from './sanitize.ts'; export { downloadJson } from './downloadJson.ts'; -// File system helpers +// File system helpers (sync, workspace-relative paths) export { commonFilePaths, fileExists, - getPackageJson, - readFile, - writeFile, + loadFile, + loadPackageJson, + saveFile, type Package } from './files.ts'; -/** @deprecated Internal to sv — will be removed from the public API in a future version. */ -export { installPackages } from './files.ts'; +/** @deprecated Use {@link loadFile} instead. */ +export { readFile } from './files.ts'; +/** @deprecated Use {@link saveFile} instead. */ +export { writeFile } from './files.ts'; +/** @deprecated Use {@link loadPackageJson} instead. */ +export { getPackageJson } from './files.ts'; // Terminal styling export { color } from './color.ts'; diff --git a/packages/sv/api-surface.md b/packages/sv/api-surface.md index ab42a9bb4..5651f3483 100644 --- a/packages/sv/api-surface.md +++ b/packages/sv/api-surface.md @@ -13,14 +13,11 @@ type Options = { template: TemplateType; types: LanguageType; }; -/** @deprecated Use `create({ cwd, name, template, types })` instead. */ declare function create(cwd: string, options: Omit): void; declare function create(options: Options): void; -/** @deprecated Unused type, will be removed in a future version. */ type FileEditor = Workspace & { content: string; }; -/** @deprecated Unused type, will be removed in a future version. */ type FileType = { name: (options: Workspace) => string; condition?: ConditionDefinition; diff --git a/packages/sv/src/addons/drizzle.ts b/packages/sv/src/addons/drizzle.ts index f807f11cc..c8bd70d79 100644 --- a/packages/sv/src/addons/drizzle.ts +++ b/packages/sv/src/addons/drizzle.ts @@ -206,7 +206,7 @@ export default defineAddon({ const hasPrettier = Boolean(dependencyVersion('prettier')); if (hasPrettier) { sv.file( - file.prettierignore, + '.prettierignore', transforms.text(({ content, text }) => text.upsert(content, '/drizzle/')) ); } diff --git a/packages/sv/src/addons/eslint.ts b/packages/sv/src/addons/eslint.ts index 58b1d00a4..4d6197676 100644 --- a/packages/sv/src/addons/eslint.ts +++ b/packages/sv/src/addons/eslint.ts @@ -31,7 +31,7 @@ export default defineAddon({ ); sv.file( - file.eslintConfig, + 'eslint.config.js', transforms.script(({ ast, comments, js }) => { const eslintConfigs: Array = []; js.imports.addDefault(ast, { from: './svelte.config.js', as: 'svelteConfig' }); @@ -156,14 +156,14 @@ export default defineAddon({ ); sv.file( - file.vscodeExtensions, + '.vscode/extensions.json', transforms.json(({ data, json }) => { json.arrayUpsert(data, 'recommendations', 'dbaeumer.vscode-eslint'); }) ); if (prettierInstalled) { - sv.file(file.eslintConfig, addEslintConfigPrettier); + sv.file('eslint.config.js', addEslintConfigPrettier); } } }); diff --git a/packages/sv/src/addons/prettier.ts b/packages/sv/src/addons/prettier.ts index eea8f1252..69629f2cc 100644 --- a/packages/sv/src/addons/prettier.ts +++ b/packages/sv/src/addons/prettier.ts @@ -16,7 +16,7 @@ export default defineAddon({ sv.devDependency('prettier-plugin-svelte', '^3.4.1'); sv.file( - file.prettierignore, + '.prettierignore', transforms.text(({ content }) => { if (content) return false; return dedent` @@ -34,7 +34,7 @@ export default defineAddon({ ); sv.file( - file.prettierrc, + '.prettierrc', transforms.json( ({ data, json }) => { if (Object.keys(data).length === 0) { @@ -82,7 +82,7 @@ export default defineAddon({ ); sv.file( - file.vscodeExtensions, + '.vscode/extensions.json', transforms.json(({ data, json }) => { json.arrayUpsert(data, 'recommendations', 'esbenp.prettier-vscode'); }) @@ -98,7 +98,7 @@ export default defineAddon({ if (eslintInstalled) { sv.devDependency('eslint-config-prettier', '^10.1.8'); - sv.file(file.eslintConfig, addEslintConfigPrettier); + sv.file('eslint.config.js', addEslintConfigPrettier); } } }); diff --git a/packages/sv/src/addons/sveltekit-adapter.ts b/packages/sv/src/addons/sveltekit-adapter.ts index dd3f9a3a2..739e89896 100644 --- a/packages/sv/src/addons/sveltekit-adapter.ts +++ b/packages/sv/src/addons/sveltekit-adapter.ts @@ -4,7 +4,7 @@ import { text, transforms, fileExists, - getPackageJson, + loadPackageJson, sanitizeName } from '@sveltejs/sv-utils'; import { defineAddon, defineAddonOptions } from '../core/config.ts'; @@ -140,7 +140,7 @@ export default defineAddon({ } if (!data.name) { - const pkg = getPackageJson(cwd); + const pkg = loadPackageJson(cwd); data.name = sanitizeName(pkg.data.name, 'wrangler'); } diff --git a/packages/sv/src/addons/tailwindcss.ts b/packages/sv/src/addons/tailwindcss.ts index 5dd26ce2c..97deeac55 100644 --- a/packages/sv/src/addons/tailwindcss.ts +++ b/packages/sv/src/addons/tailwindcss.ts @@ -106,7 +106,7 @@ export default defineAddon({ } sv.file( - file.vscodeSettings, + '.vscode/settings.json', transforms.json(({ data }) => { data['files.associations'] ??= {}; data['files.associations']['*.css'] = 'tailwindcss'; @@ -114,7 +114,7 @@ export default defineAddon({ ); sv.file( - file.vscodeExtensions, + '.vscode/extensions.json', transforms.json(({ data, json }) => { json.arrayUpsert(data, 'recommendations', 'bradlc.vscode-tailwindcss'); }) @@ -122,7 +122,7 @@ export default defineAddon({ if (prettierInstalled) { sv.file( - file.prettierrc, + '.prettierrc', transforms.json(({ data, json }) => { json.arrayUpsert(data, 'plugins', 'prettier-plugin-tailwindcss'); data.tailwindStylesheet ??= file.getRelative({ to: file.stylesheet }); diff --git a/packages/sv/src/cli/create.ts b/packages/sv/src/cli/create.ts index 8d0722015..c7888c575 100644 --- a/packages/sv/src/cli/create.ts +++ b/packages/sv/src/cli/create.ts @@ -1,5 +1,5 @@ import * as p from '@clack/prompts'; -import { color, resolveCommandArray, commonFilePaths, getPackageJson } from '@sveltejs/sv-utils'; +import { color, resolveCommandArray, commonFilePaths, loadPackageJson } from '@sveltejs/sv-utils'; import { Command, Option } from 'commander'; import fs from 'node:fs'; import path from 'node:path'; @@ -465,7 +465,7 @@ export async function createVirtualWorkspace({ // Let's read the package.json of the template we will use and add the dependencies to the override const templatePackageJsonPath = dist(`templates/${template}`); - const { data: packageJson } = getPackageJson(templatePackageJsonPath); + const { data: packageJson } = loadPackageJson(templatePackageJsonPath); override.dependencies = { ...packageJson.devDependencies, ...packageJson.dependencies, diff --git a/packages/sv/src/core/engine.ts b/packages/sv/src/core/engine.ts index 99a1edba1..9e2028c42 100644 --- a/packages/sv/src/core/engine.ts +++ b/packages/sv/src/core/engine.ts @@ -1,12 +1,13 @@ import * as p from '@clack/prompts'; import { color, + commonFilePaths, resolveCommand, type AgentName, fileExists, - installPackages as updatePackages, - readFile, - writeFile + loadFile, + loadPackageJson, + saveFile } from '@sveltejs/sv-utils'; import { NonZeroExitError, exec } from 'tinyexec'; import { createLoadedAddon } from '../cli/add.ts'; @@ -22,6 +23,38 @@ import { import { TESTING } from './env.ts'; import { createWorkspace, type Workspace } from './workspace.ts'; +function alphabetizePackageJsonDependencies(obj: Record) { + const ordered: Record = {}; + for (const [key, value] of Object.entries(obj).sort(([a], [b]) => a.localeCompare(b))) { + ordered[key] = value; + } + return ordered; +} + +function updatePackages( + dependencies: Array<{ pkg: string; version: string; dev: boolean }>, + cwd: string +): string { + const { data, generateCode } = loadPackageJson(cwd); + + for (const dependency of dependencies) { + if (dependency.dev) { + data.devDependencies ??= {}; + data.devDependencies[dependency.pkg] = dependency.version; + } else { + data.dependencies ??= {}; + data.dependencies[dependency.pkg] = dependency.version; + } + } + + if (data.dependencies) data.dependencies = alphabetizePackageJsonDependencies(data.dependencies); + if (data.devDependencies) + data.devDependencies = alphabetizePackageJsonDependencies(data.devDependencies); + + saveFile(cwd, commonFilePaths.packageJson, generateCode()); + return commonFilePaths.packageJson; +} + export type InstallOptions = { cwd: string; addons: Addons; @@ -180,11 +213,11 @@ async function runAddon({ addon, loaded, multiple, workspace, workspaceOptions } const sv: SvApi = { file: (path, edit) => { try { - const content = fileExists(workspace.cwd, path) ? readFile(workspace.cwd, path) : ''; + const content = fileExists(workspace.cwd, path) ? loadFile(workspace.cwd, path) : ''; const editedContent = edit(content); if (editedContent === '' || editedContent === false) return content; - writeFile(workspace.cwd, path, editedContent); + saveFile(workspace.cwd, path, editedContent); files.add(path); } catch (e) { if (e instanceof Error) { diff --git a/packages/sv/src/core/processors.ts b/packages/sv/src/core/processors.ts index a56240d15..bde28a7c1 100644 --- a/packages/sv/src/core/processors.ts +++ b/packages/sv/src/core/processors.ts @@ -1,10 +1,8 @@ import type { ConditionDefinition } from './config.ts'; import type { Workspace } from './workspace.ts'; -/** @deprecated Unused type, will be removed in a future version. */ export type FileEditor = Workspace & { content: string }; -/** @deprecated Unused type, will be removed in a future version. */ export type FileType = { name: (options: Workspace) => string; condition?: ConditionDefinition; diff --git a/packages/sv/src/core/workspace.ts b/packages/sv/src/core/workspace.ts index 4efb8c136..b04af63f4 100644 --- a/packages/sv/src/core/workspace.ts +++ b/packages/sv/src/core/workspace.ts @@ -4,8 +4,8 @@ import { js, parse, commonFilePaths, - getPackageJson, - readFile + loadFile, + loadPackageJson } from '@sveltejs/sv-utils'; import * as find from 'empathic/find'; import fs from 'node:fs'; @@ -37,18 +37,6 @@ export type Workspace = { package: 'package.json'; gitignore: '.gitignore'; - /** @deprecated Addon-specific path - use the string literal '.prettierignore' directly. Will be removed in a future version. */ - prettierignore: '.prettierignore'; - /** @deprecated Addon-specific path - use the string literal '.prettierrc' directly. Will be removed in a future version. */ - prettierrc: '.prettierrc'; - /** @deprecated Addon-specific path - use the string literal 'eslint.config.js' directly. Will be removed in a future version. */ - eslintConfig: 'eslint.config.js'; - - /** @deprecated Addon-specific path - use the string literal '.vscode/settings.json' directly. Will be removed in a future version. */ - vscodeSettings: '.vscode/settings.json'; - /** @deprecated Addon-specific path - use the string literal '.vscode/extensions.json' directly. Will be removed in a future version. */ - vscodeExtensions: '.vscode/extensions.json'; - /** Get the relative path between two files */ getRelative: ({ from, to }: { from?: string; to: string }) => string; }; @@ -108,7 +96,7 @@ export async function createWorkspace({ directory.length >= workspaceRoot.length ) { if (fs.existsSync(path.join(directory, commonFilePaths.packageJson))) { - const { data: packageJson } = getPackageJson(directory); + const { data: packageJson } = loadPackageJson(directory); dependencies = { ...packageJson.devDependencies, ...packageJson.dependencies, @@ -147,11 +135,6 @@ export async function createWorkspace({ stylesheet, package: 'package.json', gitignore: '.gitignore', - prettierignore: '.prettierignore', - prettierrc: '.prettierrc', - eslintConfig: 'eslint.config.js', - vscodeSettings: '.vscode/settings.json', - vscodeExtensions: '.vscode/extensions.json', getRelative({ from, to }) { from = from ?? ''; let relativePath = path.posix.relative(path.posix.dirname(from), to); @@ -178,7 +161,7 @@ function findWorkspaceRoot(cwd: string): string { return directory; } // in other package managers it's a workspaces key in the package.json - const { data } = getPackageJson(directory); + const { data } = loadPackageJson(directory); if (data.workspaces) { return directory; } @@ -194,7 +177,7 @@ function findWorkspaceRoot(cwd: string): string { } function parseKitOptions(cwd: string, svelteConfigPath: string) { - const configSource = readFile(cwd, svelteConfigPath); + const configSource = loadFile(cwd, svelteConfigPath); const { ast } = parse.script(configSource); const defaultExport = ast.body.find((s) => s.type === 'ExportDefaultDeclaration'); diff --git a/packages/sv/src/create/index.ts b/packages/sv/src/create/index.ts index 5ee524d0c..1c30c199b 100644 --- a/packages/sv/src/create/index.ts +++ b/packages/sv/src/create/index.ts @@ -33,7 +33,6 @@ export type Common = { }>; }; -/** @deprecated Use `create({ cwd, name, template, types })` instead. */ export function create(cwd: string, options: Omit): void; export function create(options: Options): void; export function create( diff --git a/packages/sv/src/index.ts b/packages/sv/src/index.ts index 6b5c64d4a..3c3fe50b0 100644 --- a/packages/sv/src/index.ts +++ b/packages/sv/src/index.ts @@ -37,6 +37,4 @@ export type { // workspace.ts export type { Workspace, WorkspaceOptions } from './core/workspace.ts'; -// processors.ts - deprecated, will be removed -/** @deprecated Unused type, will be removed in a future version. */ export type { FileEditor, FileType } from './core/processors.ts'; From 7e203ce9b79c9930cd7fac0398d922e3b793f133 Mon Sep 17 00:00:00 2001 From: jycouet Date: Sat, 4 Apr 2026 12:48:29 +0200 Subject: [PATCH 5/7] docs(sv-utils): clarify deprecation on readFile/writeFile/getPackageJson aliases Made-with: Cursor --- packages/sv-utils/api-surface.md | 12 +++++++++--- packages/sv-utils/src/files.ts | 12 +++++++++--- packages/sv-utils/src/index.ts | 12 +++++++++--- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/packages/sv-utils/api-surface.md b/packages/sv-utils/api-surface.md index dba9a2978..0637ba830 100644 --- a/packages/sv-utils/api-surface.md +++ b/packages/sv-utils/api-surface.md @@ -1276,11 +1276,17 @@ declare function loadPackageJson(cwd: string): { data: Package; generateCode: () => string; }; -/** @deprecated Use `loadFile` instead. */ +/** +* @deprecated Use {@link loadFile} instead. This alias will be removed in a future version. +*/ declare const readFile: typeof loadFile; -/** @deprecated Use `saveFile` instead. */ +/** +* @deprecated Use {@link saveFile} instead. This alias will be removed in a future version. +*/ declare const writeFile: typeof saveFile; -/** @deprecated Use `loadPackageJson` instead. */ +/** +* @deprecated Use {@link loadPackageJson} instead. This alias will be removed in a future version. +*/ declare const getPackageJson: typeof loadPackageJson; type ColorInput = string | string[]; declare const color: { diff --git a/packages/sv-utils/src/files.ts b/packages/sv-utils/src/files.ts index 540e80602..8b6dc2488 100644 --- a/packages/sv-utils/src/files.ts +++ b/packages/sv-utils/src/files.ts @@ -70,11 +70,17 @@ export function loadPackageJson(cwd: string): { return { source: packageText, data: data as Package, generateCode }; } -/** @deprecated Use {@link loadFile} instead. */ +/** + * @deprecated Use {@link loadFile} instead. This alias will be removed in a future version. + */ export const readFile: typeof loadFile = loadFile; -/** @deprecated Use {@link saveFile} instead. */ +/** + * @deprecated Use {@link saveFile} instead. This alias will be removed in a future version. + */ export const writeFile: typeof saveFile = saveFile; -/** @deprecated Use {@link loadPackageJson} instead. */ +/** + * @deprecated Use {@link loadPackageJson} instead. This alias will be removed in a future version. + */ export const getPackageJson: typeof loadPackageJson = loadPackageJson; diff --git a/packages/sv-utils/src/index.ts b/packages/sv-utils/src/index.ts index 37db2b10b..d191059fc 100644 --- a/packages/sv-utils/src/index.ts +++ b/packages/sv-utils/src/index.ts @@ -87,11 +87,17 @@ export { type Package } from './files.ts'; -/** @deprecated Use {@link loadFile} instead. */ +/** + * @deprecated Use {@link loadFile} instead. This alias will be removed in a future version. + */ export { readFile } from './files.ts'; -/** @deprecated Use {@link saveFile} instead. */ +/** + * @deprecated Use {@link saveFile} instead. This alias will be removed in a future version. + */ export { writeFile } from './files.ts'; -/** @deprecated Use {@link loadPackageJson} instead. */ +/** + * @deprecated Use {@link loadPackageJson} instead. This alias will be removed in a future version. + */ export { getPackageJson } from './files.ts'; // Terminal styling From 157d3626885e553744451b223ecc9a885a69d183 Mon Sep 17 00:00:00 2001 From: jycouet Date: Sat, 4 Apr 2026 12:54:37 +0200 Subject: [PATCH 6/7] fmt --- packages/sv-utils/api-surface.md | 1498 ++++++++++++++++++---------- packages/sv/api-surface-testing.md | 64 +- packages/sv/api-surface.md | 46 +- packages/sv/src/create/index.ts | 5 +- scripts/generate-api-surface.js | 22 +- 5 files changed, 1101 insertions(+), 534 deletions(-) diff --git a/packages/sv-utils/api-surface.md b/packages/sv-utils/api-surface.md index 0637ba830..a4f243206 100644 --- a/packages/sv-utils/api-surface.md +++ b/packages/sv-utils/api-surface.md @@ -3,65 +3,76 @@ ```ts -type Agent = 'npm' | 'yarn' | 'yarn@berry' | 'pnpm' | 'pnpm@6' | 'bun' | 'deno'; -type AgentName = 'npm' | 'yarn' | 'pnpm' | 'bun' | 'deno'; -type AgentCommandValue = (string | number)[] | ((args: string[]) => string[]) | null; +type Agent = "npm" | "yarn" | "yarn@berry" | "pnpm" | "pnpm@6" | "bun" | "deno"; +type AgentName = "npm" | "yarn" | "pnpm" | "bun" | "deno"; +type AgentCommandValue = + | (string | number)[] + | ((args: string[]) => string[]) + | null; interface AgentCommands { - 'agent': AgentCommandValue; - 'run': AgentCommandValue; - 'install': AgentCommandValue; - 'frozen': AgentCommandValue; - 'global': AgentCommandValue; - 'add': AgentCommandValue; - 'upgrade': AgentCommandValue; - 'upgrade-interactive': AgentCommandValue; - 'dedupe': AgentCommandValue; - 'execute': AgentCommandValue; - 'execute-local': AgentCommandValue; - 'uninstall': AgentCommandValue; - 'global_uninstall': AgentCommandValue; + agent: AgentCommandValue; + run: AgentCommandValue; + install: AgentCommandValue; + frozen: AgentCommandValue; + global: AgentCommandValue; + add: AgentCommandValue; + upgrade: AgentCommandValue; + "upgrade-interactive": AgentCommandValue; + dedupe: AgentCommandValue; + execute: AgentCommandValue; + "execute-local": AgentCommandValue; + uninstall: AgentCommandValue; + global_uninstall: AgentCommandValue; } type Command = keyof AgentCommands; interface ResolvedCommand { - command: string; - + args: string[]; } -type DetectStrategy = 'lockfile' | 'packageManager-field' | 'devEngines-field' | 'install-metadata'; +type DetectStrategy = + | "lockfile" + | "packageManager-field" + | "devEngines-field" + | "install-metadata"; interface DetectOptions { - cwd?: string; - + strategies?: DetectStrategy[]; - + onUnknown?: (packageManager: string) => DetectResult | null | undefined; - + stopDir?: string | ((currentDir: string) => boolean); - + packageJsonParser?: (content: string, filepath: string) => any | Promise; } interface DetectResult { - name: AgentName; - + agent: Agent; - + version?: string; } declare const COMMANDS: { npm: AgentCommands; yarn: AgentCommands; - 'yarn@berry': AgentCommands; + "yarn@berry": AgentCommands; pnpm: AgentCommands; - 'pnpm@6': AgentCommands; + "pnpm@6": AgentCommands; bun: AgentCommands; deno: AgentCommands; }; -declare function resolveCommand(agent: Agent, command: Command, args: string[]): ResolvedCommand | null; +declare function resolveCommand( + agent: Agent, + command: Command, + args: string[], +): ResolvedCommand | null; -declare function constructCommand(value: AgentCommandValue, args: string[]): ResolvedCommand | null; +declare function constructCommand( + value: AgentCommandValue, + args: string[], +): ResolvedCommand | null; declare const AGENTS: Agent[]; declare function detect(options?: DetectOptions): Promise; @@ -114,32 +125,59 @@ type TomlValue = TomlPrimitive | TomlValue[] | TomlTable; declare class LineCounter { lineStarts: number[]; - + addNewLine: (offset: number) => number; - + linePos: (offset: number) => { line: number; col: number; }; } -type ErrorCode = 'ALIAS_PROPS' | 'BAD_ALIAS' | 'BAD_DIRECTIVE' | 'BAD_DQ_ESCAPE' | 'BAD_INDENT' | 'BAD_PROP_ORDER' | 'BAD_SCALAR_START' | 'BLOCK_AS_IMPLICIT_KEY' | 'BLOCK_IN_FLOW' | 'DUPLICATE_KEY' | 'IMPOSSIBLE' | 'KEY_OVER_1024_CHARS' | 'MISSING_CHAR' | 'MULTILINE_IMPLICIT_KEY' | 'MULTIPLE_ANCHORS' | 'MULTIPLE_DOCS' | 'MULTIPLE_TAGS' | 'NON_STRING_KEY' | 'TAB_AS_INDENT' | 'TAG_RESOLVE_FAILED' | 'UNEXPECTED_TOKEN' | 'BAD_COLLECTION_TYPE'; +type ErrorCode = + | "ALIAS_PROPS" + | "BAD_ALIAS" + | "BAD_DIRECTIVE" + | "BAD_DQ_ESCAPE" + | "BAD_INDENT" + | "BAD_PROP_ORDER" + | "BAD_SCALAR_START" + | "BLOCK_AS_IMPLICIT_KEY" + | "BLOCK_IN_FLOW" + | "DUPLICATE_KEY" + | "IMPOSSIBLE" + | "KEY_OVER_1024_CHARS" + | "MISSING_CHAR" + | "MULTILINE_IMPLICIT_KEY" + | "MULTIPLE_ANCHORS" + | "MULTIPLE_DOCS" + | "MULTIPLE_TAGS" + | "NON_STRING_KEY" + | "TAB_AS_INDENT" + | "TAG_RESOLVE_FAILED" + | "UNEXPECTED_TOKEN" + | "BAD_COLLECTION_TYPE"; type LinePos = { line: number; col: number; }; declare class YAMLError extends Error { - name: 'YAMLParseError' | 'YAMLWarning'; + name: "YAMLParseError" | "YAMLWarning"; code: ErrorCode; message: string; pos: [number, number]; linePos?: [LinePos] | [LinePos, LinePos]; - constructor(name: YAMLError['name'], pos: [number, number], code: ErrorCode, message: string); + constructor( + name: YAMLError["name"], + pos: [number, number], + code: ErrorCode, + message: string, + ); } declare class YAMLWarning extends YAMLError { constructor(pos: [number, number], code: ErrorCode, message: string); } type Reviver = (key: unknown, value: unknown) => unknown; -type LogLevelId = 'silent' | 'error' | 'warn' | 'debug'; +type LogLevelId = "silent" | "error" | "warn" | "debug"; interface AnchorData { aliasCount: number; count: number; @@ -147,7 +185,7 @@ interface AnchorData { } interface ToJSContext { anchors: Map; - + aliasResolveCache?: Node[]; doc: Document; keep: boolean; @@ -162,12 +200,17 @@ declare namespace Scalar { source: string; srcToken?: FlowScalar | BlockScalar; } - type BLOCK_FOLDED = 'BLOCK_FOLDED'; - type BLOCK_LITERAL = 'BLOCK_LITERAL'; - type PLAIN = 'PLAIN'; - type QUOTE_DOUBLE = 'QUOTE_DOUBLE'; - type QUOTE_SINGLE = 'QUOTE_SINGLE'; - type Type = BLOCK_FOLDED | BLOCK_LITERAL | PLAIN | QUOTE_DOUBLE | QUOTE_SINGLE; + type BLOCK_FOLDED = "BLOCK_FOLDED"; + type BLOCK_LITERAL = "BLOCK_LITERAL"; + type PLAIN = "PLAIN"; + type QUOTE_DOUBLE = "QUOTE_DOUBLE"; + type QUOTE_SINGLE = "QUOTE_SINGLE"; + type Type = + | BLOCK_FOLDED + | BLOCK_LITERAL + | PLAIN + | QUOTE_DOUBLE + | QUOTE_SINGLE; } declare class Scalar extends NodeBase { static readonly BLOCK_FOLDED = "BLOCK_FOLDED"; @@ -176,15 +219,15 @@ declare class Scalar extends NodeBase { static readonly QUOTE_DOUBLE = "QUOTE_DOUBLE"; static readonly QUOTE_SINGLE = "QUOTE_SINGLE"; value: T; - + anchor?: string; - + format?: string; - + minFractionDigits?: number; - + source?: string; - + type?: Scalar.Type; constructor(value: T); toJSON(arg?: any, ctx?: ToJSContext): any; @@ -203,133 +246,172 @@ type StringifyContext = { inFlow: boolean | null; inStringifyKey?: boolean; flowCollectionPadding: string; - options: Readonly>>; + options: Readonly< + Required> + >; resolvedAliases?: Set; }; declare abstract class Collection extends NodeBase { schema: Schema | undefined; [NODE_TYPE]: symbol; items: unknown[]; - + anchor?: string; - + flow?: boolean; constructor(type: symbol, schema?: Schema); - + clone(schema?: Schema): Collection; - + abstract add(value: unknown): void; - + abstract delete(key: unknown): boolean; - + abstract get(key: unknown, keepScalar?: boolean): unknown; - + abstract has(key: unknown): boolean; - + abstract set(key: unknown, value: unknown): void; - + addIn(path: Iterable, value: unknown): void; - + deleteIn(path: Iterable): boolean; - + getIn(path: Iterable, keepScalar?: boolean): unknown; hasAllNullValues(allowScalar?: boolean): boolean; - + hasIn(path: Iterable): boolean; - + setIn(path: Iterable, value: unknown): void; } declare namespace YAMLSeq { - interface Parsed = ParsedNode> extends YAMLSeq { + interface Parsed< + T extends ParsedNode | Pair = ParsedNode, + > extends YAMLSeq { items: T[]; range: Range; srcToken?: BlockSequence | FlowCollection; } } declare class YAMLSeq extends Collection { - static get tagName(): 'tag:yaml.org,2002:seq'; + static get tagName(): "tag:yaml.org,2002:seq"; items: T[]; constructor(schema?: Schema); add(value: T): void; - + delete(key: unknown): boolean; - + get(key: unknown, keepScalar: true): Scalar | undefined; get(key: unknown, keepScalar?: false): T | undefined; get(key: unknown, keepScalar?: boolean): T | Scalar | undefined; - + has(key: unknown): boolean; - + set(key: unknown, value: T): void; toJSON(_?: unknown, ctx?: ToJSContext): unknown[]; - toString(ctx?: StringifyContext, onComment?: () => void, onChompKeep?: () => void): string; + toString( + ctx?: StringifyContext, + onComment?: () => void, + onChompKeep?: () => void, + ): string; static from(schema: Schema, obj: unknown, ctx: CreateNodeContext): YAMLSeq; } interface TagBase { - createNode?: (schema: Schema, value: unknown, ctx: CreateNodeContext) => Node; - - default?: boolean | 'key'; - + + default?: boolean | "key"; + format?: string; - + identify?: (value: unknown) => boolean; - + tag: string; } interface ScalarTag extends TagBase { collection?: never; nodeClass?: never; - - resolve(value: string, onError: (message: string) => void, options: ParseOptions): unknown; - - stringify?: (item: Scalar, ctx: StringifyContext, onComment?: () => void, onChompKeep?: () => void) => string; - + + resolve( + value: string, + onError: (message: string) => void, + options: ParseOptions, + ): unknown; + + stringify?: ( + item: Scalar, + ctx: StringifyContext, + onComment?: () => void, + onChompKeep?: () => void, + ) => string; + test?: RegExp; } interface CollectionTag extends TagBase { stringify?: never; test?: never; - - collection: 'map' | 'seq'; - + + collection: "map" | "seq"; + nodeClass?: { new (schema?: Schema): Node; from?: (schema: Schema, obj: unknown, ctx: CreateNodeContext) => Node; }; - - resolve?: (value: YAMLMap.Parsed | YAMLSeq.Parsed, onError: (message: string) => void, options: ParseOptions) => unknown; + + resolve?: ( + value: YAMLMap.Parsed | YAMLSeq.Parsed, + onError: (message: string) => void, + options: ParseOptions, + ) => unknown; } -type MapLike = Map | Set | Record; +type MapLike = + | Map + | Set + | Record; declare namespace YAMLMap { - interface Parsed extends YAMLMap { + interface Parsed< + K extends ParsedNode = ParsedNode, + V extends ParsedNode | null = ParsedNode | null, + > extends YAMLMap { items: Pair[]; range: Range; srcToken?: BlockMap | FlowCollection; } } declare class YAMLMap extends Collection { - static get tagName(): 'tag:yaml.org,2002:map'; + static get tagName(): "tag:yaml.org,2002:map"; items: Pair[]; constructor(schema?: Schema); - + static from(schema: Schema, obj: unknown, ctx: CreateNodeContext): YAMLMap; - - add(pair: Pair | { - key: K; - value: V; - }, overwrite?: boolean): void; + + add( + pair: + | Pair + | { + key: K; + value: V; + }, + overwrite?: boolean, + ): void; delete(key: unknown): boolean; get(key: unknown, keepScalar: true): Scalar | undefined; get(key: unknown, keepScalar?: false): V | undefined; get(key: unknown, keepScalar?: boolean): V | Scalar | undefined; has(key: unknown): boolean; set(key: K, value: V): void; - - toJSON>(_?: unknown, ctx?: ToJSContext, Type?: { - new (): T; - }): any; - toString(ctx?: StringifyContext, onComment?: () => void, onChompKeep?: () => void): string; + + toJSON>( + _?: unknown, + ctx?: ToJSContext, + Type?: { + new (): T; + }, + ): any; + toString( + ctx?: StringifyContext, + onComment?: () => void, + onChompKeep?: () => void, + ): string; } declare const MAP: unique symbol; declare const SCALAR: unique symbol; @@ -352,7 +434,7 @@ declare class Schema { resolveKnownTags, schema, sortMapEntries, - toStringDefaults + toStringDefaults, }: SchemaOptions); clone(): Schema; } @@ -361,29 +443,37 @@ interface CreateNodeContext { keepUndefined: boolean; onAnchor: (source: unknown) => string; onTagObj?: (tagObj: ScalarTag | CollectionTag) => void; - sourceObjects: Map; + sourceObjects: Map< + unknown, + { + anchor: string | null; + node: Node | null; + } + >; replacer?: Replacer; schema: Schema; } -declare function addPairToJSMap(ctx: ToJSContext | undefined, map: MapLike, { - key, - value -}: Pair): MapLike; +declare function addPairToJSMap( + ctx: ToJSContext | undefined, + map: MapLike, + { key, value }: Pair, +): MapLike; declare class Pair { readonly [NODE_TYPE]: symbol; - + key: K; - + value: V | null; - + srcToken?: CollectionItem; constructor(key: K, value?: V | null); clone(schema?: Schema): Pair; toJSON(_?: unknown, ctx?: ToJSContext): ReturnType; - toString(ctx?: StringifyContext, onComment?: () => void, onChompKeep?: () => void): string; + toString( + ctx?: StringifyContext, + onComment?: () => void, + onChompKeep?: () => void, + ): string; } declare const tagsByName: { binary: ScalarTag; @@ -417,211 +507,253 @@ declare const tagsByName: { type TagId = keyof typeof tagsByName; type Tags = Array; type ParseOptions = { - intAsBigInt?: boolean; - + keepSourceTokens?: boolean; - + lineCounter?: LineCounter; - + prettyErrors?: boolean; - + strict?: boolean; - + stringKeys?: boolean; - + uniqueKeys?: boolean | ((a: ParsedNode, b: ParsedNode) => boolean); }; type DocumentOptions = { - _directives?: Directives; - + logLevel?: LogLevelId; - - version?: '1.1' | '1.2' | 'next'; + + version?: "1.1" | "1.2" | "next"; }; type SchemaOptions = { - compat?: string | Tags | null; - + customTags?: Tags | ((tags: Tags) => Tags) | null; - + merge?: boolean; - + resolveKnownTags?: boolean; - + schema?: string | Schema; - + sortMapEntries?: boolean | ((a: Pair, b: Pair) => number); - + toStringDefaults?: ToStringOptions; }; type CreateNodeOptions = { - aliasDuplicateObjects?: boolean; - - anchorPrefix?: string; + + anchorPrefix?: string; flow?: boolean; - + keepUndefined?: boolean | null; onTagObj?: (tagObj: ScalarTag | CollectionTag) => void; - + tag?: string; }; type ToJSOptions = { - mapAsMap?: boolean; - + maxAliasCount?: number; - + onAnchor?: (value: unknown, count: number) => void; - + reviver?: Reviver; }; type ToStringOptions = { - - blockQuote?: boolean | 'folded' | 'literal'; - - collectionStyle?: 'any' | 'block' | 'flow'; - + blockQuote?: boolean | "folded" | "literal"; + + collectionStyle?: "any" | "block" | "flow"; + commentString?: (comment: string) => string; - + defaultKeyType?: Scalar.Type | null; - + defaultStringType?: Scalar.Type; - + directives?: boolean | null; - + doubleQuotedAsJSON?: boolean; - + doubleQuotedMinMultiLineLength?: number; - + falseStr?: string; - + flowCollectionPadding?: boolean; - + indent?: number; - + indentSeq?: boolean; - + lineWidth?: number; - + minContentWidth?: number; - + nullStr?: string; - + simpleKeys?: boolean; - + singleQuote?: boolean | null; - + trueStr?: string; - + verifyAliasOrder?: boolean; }; type Node = Alias | Scalar | YAMLMap | YAMLSeq; -type NodeType = T extends string | number | bigint | boolean | null | undefined ? Scalar : T extends Date ? Scalar : T extends Array ? YAMLSeq> : T extends { - [key: string]: any; -} ? YAMLMap, NodeType> : T extends { - [key: number]: any; -} ? YAMLMap, NodeType> : Node; -type ParsedNode = Alias.Parsed | Scalar.Parsed | YAMLMap.Parsed | YAMLSeq.Parsed; +type NodeType = T extends + | string + | number + | bigint + | boolean + | null + | undefined + ? Scalar + : T extends Date + ? Scalar + : T extends Array + ? YAMLSeq> + : T extends { + [key: string]: any; + } + ? YAMLMap, NodeType> + : T extends { + [key: number]: any; + } + ? YAMLMap, NodeType> + : Node; +type ParsedNode = + | Alias.Parsed + | Scalar.Parsed + | YAMLMap.Parsed + | YAMLSeq.Parsed; type Range = [number, number, number]; declare abstract class NodeBase { readonly [NODE_TYPE]: symbol; - + comment?: string | null; - + commentBefore?: string | null; - + range?: Range | null; - + spaceBefore?: boolean; - + srcToken?: Token; - + tag?: string; - - addToJSMap?: (ctx: ToJSContext | undefined, map: MapLike, value: unknown) => void; - + + addToJSMap?: ( + ctx: ToJSContext | undefined, + map: MapLike, + value: unknown, + ) => void; + abstract toJSON(): any; - abstract toString(ctx?: StringifyContext, onComment?: () => void, onChompKeep?: () => void): string; + abstract toString( + ctx?: StringifyContext, + onComment?: () => void, + onChompKeep?: () => void, + ): string; constructor(type: symbol); - + clone(): NodeBase; - - toJS(doc: Document, { - mapAsMap, - maxAliasCount, - onAnchor, - reviver - }?: ToJSOptions): any; + + toJS( + doc: Document, + { mapAsMap, maxAliasCount, onAnchor, reviver }?: ToJSOptions, + ): any; } interface SourceToken { - type: 'byte-order-mark' | 'doc-mode' | 'doc-start' | 'space' | 'comment' | 'newline' | 'directive-line' | 'anchor' | 'tag' | 'seq-item-ind' | 'explicit-key-ind' | 'map-value-ind' | 'flow-map-start' | 'flow-map-end' | 'flow-seq-start' | 'flow-seq-end' | 'flow-error-end' | 'comma' | 'block-scalar-header'; + type: + | "byte-order-mark" + | "doc-mode" + | "doc-start" + | "space" + | "comment" + | "newline" + | "directive-line" + | "anchor" + | "tag" + | "seq-item-ind" + | "explicit-key-ind" + | "map-value-ind" + | "flow-map-start" + | "flow-map-end" + | "flow-seq-start" + | "flow-seq-end" + | "flow-error-end" + | "comma" + | "block-scalar-header"; offset: number; indent: number; source: string; } interface ErrorToken { - type: 'error'; + type: "error"; offset: number; source: string; message: string; } interface Directive$1 { - type: 'directive'; + type: "directive"; offset: number; source: string; } interface Document$1 { - type: 'document'; + type: "document"; offset: number; start: SourceToken[]; value?: Token; end?: SourceToken[]; } interface DocumentEnd { - type: 'doc-end'; + type: "doc-end"; offset: number; source: string; end?: SourceToken[]; } interface FlowScalar { - type: 'alias' | 'scalar' | 'single-quoted-scalar' | 'double-quoted-scalar'; + type: "alias" | "scalar" | "single-quoted-scalar" | "double-quoted-scalar"; offset: number; indent: number; source: string; end?: SourceToken[]; } interface BlockScalar { - type: 'block-scalar'; + type: "block-scalar"; offset: number; indent: number; props: Token[]; source: string; } interface BlockMap { - type: 'block-map'; + type: "block-map"; offset: number; indent: number; - items: Array<{ - start: SourceToken[]; - explicitKey?: true; - key?: never; - sep?: never; - value?: never; - } | { - start: SourceToken[]; - explicitKey?: true; - key: Token | null; - sep: SourceToken[]; - value?: Token; - }>; + items: Array< + | { + start: SourceToken[]; + explicitKey?: true; + key?: never; + sep?: never; + value?: never; + } + | { + start: SourceToken[]; + explicitKey?: true; + key: Token | null; + sep: SourceToken[]; + value?: Token; + } + >; } interface BlockSequence { - type: 'block-seq'; + type: "block-seq"; offset: number; indent: number; items: Array<{ @@ -638,19 +770,29 @@ type CollectionItem = { value?: Token; }; interface FlowCollection { - type: 'flow-collection'; + type: "flow-collection"; offset: number; indent: number; start: SourceToken; items: CollectionItem[]; end: SourceToken[]; } -type Token = SourceToken | ErrorToken | Directive$1 | Document$1 | DocumentEnd | FlowScalar | BlockScalar | BlockMap | BlockSequence | FlowCollection; +type Token = + | SourceToken + | ErrorToken + | Directive$1 + | Document$1 + | DocumentEnd + | FlowScalar + | BlockScalar + | BlockMap + | BlockSequence + | FlowCollection; declare namespace Alias { interface Parsed extends Alias { range: Range; srcToken?: FlowScalar & { - type: 'alias'; + type: "alias"; }; } } @@ -658,112 +800,176 @@ declare class Alias extends NodeBase { source: string; anchor?: never; constructor(source: string); - - resolve(doc: Document, ctx?: ToJSContext): Scalar | YAMLMap | YAMLSeq | undefined; + + resolve( + doc: Document, + ctx?: ToJSContext, + ): Scalar | YAMLMap | YAMLSeq | undefined; toJSON(_arg?: unknown, ctx?: ToJSContext): unknown; - toString(ctx?: StringifyContext, _onComment?: () => void, _onChompKeep?: () => void): string; + toString( + ctx?: StringifyContext, + _onComment?: () => void, + _onChompKeep?: () => void, + ): string; } type Replacer = any[] | ((key: any, value: any) => unknown); declare namespace Document { - - interface Parsed extends Document { + interface Parsed< + Contents extends ParsedNode = ParsedNode, + Strict extends boolean = true, + > extends Document { directives: Directives; range: Range; } } -declare class Document { +declare class Document< + Contents extends Node = Node, + Strict extends boolean = true, +> { readonly [NODE_TYPE]: symbol; - + commentBefore: string | null; - + comment: string | null; - + contents: Strict extends true ? Contents | null : Contents; directives: Strict extends true ? Directives | undefined : Directives; - + errors: YAMLError[]; - options: Required>; - + options: Required< + Omit< + ParseOptions & DocumentOptions, + "_directives" | "lineCounter" | "version" + > + >; + range?: Range; - + schema: Schema; - + warnings: YAMLWarning[]; - - constructor(value?: any, options?: DocumentOptions & SchemaOptions & ParseOptions & CreateNodeOptions); - constructor(value: any, replacer: null | Replacer, options?: DocumentOptions & SchemaOptions & ParseOptions & CreateNodeOptions); - + + constructor( + value?: any, + options?: DocumentOptions & + SchemaOptions & + ParseOptions & + CreateNodeOptions, + ); + constructor( + value: any, + replacer: null | Replacer, + options?: DocumentOptions & + SchemaOptions & + ParseOptions & + CreateNodeOptions, + ); + clone(): Document; - + add(value: any): void; - + addIn(path: Iterable, value: unknown): void; - - createAlias(node: Strict extends true ? Scalar | YAMLMap | YAMLSeq : Node, name?: string): Alias; - + + createAlias( + node: Strict extends true ? Scalar | YAMLMap | YAMLSeq : Node, + name?: string, + ): Alias; + createNode(value: T, options?: CreateNodeOptions): NodeType; - createNode(value: T, replacer: Replacer | CreateNodeOptions | null, options?: CreateNodeOptions): NodeType; - - createPair(key: unknown, value: unknown, options?: CreateNodeOptions): Pair; - + createNode( + value: T, + replacer: Replacer | CreateNodeOptions | null, + options?: CreateNodeOptions, + ): NodeType; + + createPair( + key: unknown, + value: unknown, + options?: CreateNodeOptions, + ): Pair; + delete(key: unknown): boolean; - + deleteIn(path: Iterable | null): boolean; - + get(key: unknown, keepScalar?: boolean): Strict extends true ? unknown : any; - - getIn(path: Iterable | null, keepScalar?: boolean): Strict extends true ? unknown : any; - + + getIn( + path: Iterable | null, + keepScalar?: boolean, + ): Strict extends true ? unknown : any; + has(key: unknown): boolean; - + hasIn(path: Iterable | null): boolean; - + set(key: any, value: unknown): void; - + setIn(path: Iterable | null, value: unknown): void; - - setSchema(version: '1.1' | '1.2' | 'next' | null, options?: SchemaOptions): void; - - toJS(opt?: ToJSOptions & { - [ignored: string]: unknown; - }): any; - - toJSON(jsonArg?: string | null, onAnchor?: ToJSOptions['onAnchor']): any; - + + setSchema( + version: "1.1" | "1.2" | "next" | null, + options?: SchemaOptions, + ): void; + + toJS( + opt?: ToJSOptions & { + [ignored: string]: unknown; + }, + ): any; + + toJSON(jsonArg?: string | null, onAnchor?: ToJSOptions["onAnchor"]): any; + toString(options?: ToStringOptions): string; } declare class Directives { - static defaultYaml: Directives['yaml']; - static defaultTags: Directives['tags']; + static defaultYaml: Directives["yaml"]; + static defaultTags: Directives["tags"]; yaml: { - version: '1.1' | '1.2' | 'next'; + version: "1.1" | "1.2" | "next"; explicit?: boolean; }; tags: Record; - + docStart: true | null; - + docEnd: boolean; - + private atNextDocument?; - constructor(yaml?: Directives['yaml'], tags?: Directives['tags']); + constructor(yaml?: Directives["yaml"], tags?: Directives["tags"]); clone(): Directives; - + atDocument(): Directives; - - add(line: string, onError: (offset: number, message: string, warning?: boolean) => void): boolean; - + + add( + line: string, + onError: (offset: number, message: string, warning?: boolean) => void, + ): boolean; + tagName(source: string, onError: (message: string) => void): string | null; - + tagString(tag: string): string; toString(doc?: Document): string; } -declare function parseDocument(source: string, options?: ParseOptions & DocumentOptions & SchemaOptions): Contents extends ParsedNode ? Document.Parsed : Document; +declare function parseDocument< + Contents extends Node = ParsedNode, + Strict extends boolean = true, +>( + source: string, + options?: ParseOptions & DocumentOptions & SchemaOptions, +): Contents extends ParsedNode + ? Document.Parsed + : Document; declare module "estree" { interface TSTypeAnnotation { type: "TSTypeAnnotation"; - typeAnnotation: TSStringKeyword | TSTypeReference | TSUnionType | TSIndexedAccessType; + typeAnnotation: + | TSStringKeyword + | TSTypeReference + | TSUnionType + | TSIndexedAccessType; } interface TSStringKeyword { type: "TSStringKeyword"; @@ -808,7 +1014,9 @@ declare module "estree" { typeAnnotation: TSTypeAnnotation; } interface TSProgram extends Omit { - body: Array; + body: Array< + Directive | Statement | ModuleDeclaration | TSModuleDeclaration + >; } interface TSUnionType { type: "TSUnionType"; @@ -865,14 +1073,20 @@ declare class Comments { private leading; private trailing; constructor(); - add(node: BaseNode$1, comment: CommentType, options?: { - position?: "leading" | "trailing"; - }): void; - remove(predicate: (comment: estree.Comment) => boolean | undefined | null): void; + add( + node: BaseNode$1, + comment: CommentType, + options?: { + position?: "leading" | "trailing"; + }, + ): void; + remove( + predicate: (comment: estree.Comment) => boolean | undefined | null, + ): void; } type ParseBase = { source: string; - + generateCode(): string; }; declare function parseScript(source: string): { @@ -909,21 +1123,30 @@ interface Dedent { } type CreateDedent = (options: DedentOptions) => Dedent; declare const dedent: Dedent; -declare module 'zimmerframe' { - export function walk | null>(node: T, state: U, visitors: Visitors): T; +declare module "zimmerframe" { + export function walk< + T extends { + type: string; + }, + U extends Record | null, + >(node: T, state: U, visitors: Visitors): T; type BaseNode = { type: string; }; type NodeOf = X extends { type: T; - } ? X : never; - type SpecialisedVisitors = { [K in T['type']]?: Visitor, U, T> }; - export type Visitor = (node: T, context: Context) => V | void; - export type Visitors = T['type'] extends '_' ? never : SpecialisedVisitors & { - _?: Visitor; + } + ? X + : never; + type SpecialisedVisitors = { + [K in T["type"]]?: Visitor, U, T>; }; + export type Visitor = (node: T, context: Context) => V | void; + export type Visitors = T["type"] extends "_" + ? never + : SpecialisedVisitors & { + _?: Visitor; + }; export interface Context { next: (state?: U) => T | void; path: T[]; @@ -936,82 +1159,164 @@ declare module 'zimmerframe' { declare namespace index_d_exports$1 { export { addAtRule, addDeclaration, addImports, addRule }; } -declare function addRule(node: SvelteAst.CSS.StyleSheetBase, options: { - selector: string; -}): SvelteAst.CSS.Rule; -declare function addDeclaration(node: SvelteAst.CSS.Rule, options: { - property: string; - value: string; -}): void; -declare function addImports(node: SvelteAst.CSS.StyleSheetBase, options: { - imports: string[]; -}): void; -declare function addAtRule(node: SvelteAst.CSS.StyleSheetBase, options: { - name: string; - params: string; - append: boolean; -}): SvelteAst.CSS.Atrule; +declare function addRule( + node: SvelteAst.CSS.StyleSheetBase, + options: { + selector: string; + }, +): SvelteAst.CSS.Rule; +declare function addDeclaration( + node: SvelteAst.CSS.Rule, + options: { + property: string; + value: string; + }, +): void; +declare function addImports( + node: SvelteAst.CSS.StyleSheetBase, + options: { + imports: string[]; + }, +): void; +declare function addAtRule( + node: SvelteAst.CSS.StyleSheetBase, + options: { + name: string; + params: string; + append: boolean; + }, +): SvelteAst.CSS.Atrule; declare namespace array_d_exports { export { append, create$1 as create, prepend }; } declare function create$1(): estree.ArrayExpression; -declare function append(node: estree.ArrayExpression, element: string | estree.Expression | estree.SpreadElement): void; -declare function prepend(node: estree.ArrayExpression, element: string | estree.Expression | estree.SpreadElement): void; +declare function append( + node: estree.ArrayExpression, + element: string | estree.Expression | estree.SpreadElement, +): void; +declare function prepend( + node: estree.ArrayExpression, + element: string | estree.Expression | estree.SpreadElement, +): void; declare namespace object_d_exports { export { create, overrideProperties, property, propertyNode }; } type ObjectPrimitiveValues = string | number | boolean | undefined | null; -type ObjectValues = ObjectPrimitiveValues | Record | ObjectValues[]; +type ObjectValues = + | ObjectPrimitiveValues + | Record + | ObjectValues[]; type ObjectMap = Record; -declare function property(node: estree.ObjectExpression, options: { - name: string; - fallback: T; -}): T; -declare function propertyNode(node: estree.ObjectExpression, options: { - name: string; - fallback: T; -}): estree.Property; +declare function property( + node: estree.ObjectExpression, + options: { + name: string; + fallback: T; + }, +): T; +declare function propertyNode( + node: estree.ObjectExpression, + options: { + name: string; + fallback: T; + }, +): estree.Property; declare function create(properties: ObjectMap): estree.ObjectExpression; -declare function overrideProperties(objectExpression: estree.ObjectExpression, properties: ObjectMap): void; +declare function overrideProperties( + objectExpression: estree.ObjectExpression, + properties: ObjectMap, +): void; declare namespace common_d_exports { - export { addJsDocComment, addJsDocTypeComment, appendFromString, appendStatement, areNodesEqual, contains, createBlockStatement, createExpressionStatement, createLiteral, createSatisfies, createSpread, createTypeProperty, hasTypeProperty, parseExpression, parseFromString, parseStatement, typeAnnotate }; + export { + addJsDocComment, + addJsDocTypeComment, + appendFromString, + appendStatement, + areNodesEqual, + contains, + createBlockStatement, + createExpressionStatement, + createLiteral, + createSatisfies, + createSpread, + createTypeProperty, + hasTypeProperty, + parseExpression, + parseFromString, + parseStatement, + typeAnnotate, + }; } -declare function addJsDocTypeComment(node: estree.Node, comments: Comments, options: { - type: string; -}): void; -declare function addJsDocComment(node: estree.Node, comments: Comments, options: { - params: Record; -}): void; -declare function typeAnnotate(node: estree.Expression, options: { - type: string; -}): estree.TSAsExpression; -declare function createSatisfies(node: estree.Expression, options: { - type: string; -}): estree.TSSatisfiesExpression; -declare function createSpread(argument: estree.Expression): estree.SpreadElement; -declare function createLiteral(value: string | number | boolean | null): estree.Literal; -declare function areNodesEqual(node: estree.Node, otherNode: estree.Node): boolean; +declare function addJsDocTypeComment( + node: estree.Node, + comments: Comments, + options: { + type: string; + }, +): void; +declare function addJsDocComment( + node: estree.Node, + comments: Comments, + options: { + params: Record; + }, +): void; +declare function typeAnnotate( + node: estree.Expression, + options: { + type: string; + }, +): estree.TSAsExpression; +declare function createSatisfies( + node: estree.Expression, + options: { + type: string; + }, +): estree.TSSatisfiesExpression; +declare function createSpread( + argument: estree.Expression, +): estree.SpreadElement; +declare function createLiteral( + value: string | number | boolean | null, +): estree.Literal; +declare function areNodesEqual( + node: estree.Node, + otherNode: estree.Node, +): boolean; declare function createBlockStatement(): estree.BlockStatement; declare function createExpressionStatement(options: { expression: estree.Expression; }): estree.ExpressionStatement; -declare function appendFromString(node: estree.BlockStatement | estree.Program, options: { - code: string; - comments?: Comments; -}): void; +declare function appendFromString( + node: estree.BlockStatement | estree.Program, + options: { + code: string; + comments?: Comments; + }, +): void; declare function parseExpression(code: string): estree.Expression; declare function parseStatement(code: string): estree.Statement; declare function parseFromString(code: string): T; -declare function appendStatement(node: estree.BlockStatement | estree.Program, options: { - statement: estree.Statement; -}): void; +declare function appendStatement( + node: estree.BlockStatement | estree.Program, + options: { + statement: estree.Statement; + }, +): void; declare function contains(node: estree.Node, targetNode: estree.Node): boolean; -declare function hasTypeProperty(node: estree.TSInterfaceDeclaration["body"]["body"][number], options: { - name: string; -}): boolean; -declare function createTypeProperty(name: string, value: string, optional?: boolean): estree.TSInterfaceBody["body"][number]; +declare function hasTypeProperty( + node: estree.TSInterfaceDeclaration["body"]["body"][number], + options: { + name: string; + }, +): boolean; +declare function createTypeProperty( + name: string, + value: string, + optional?: boolean, +): estree.TSInterfaceBody["body"][number]; declare namespace function_d_exports { export { createArrow, createCall, getArgument }; } @@ -1024,57 +1329,92 @@ declare function createArrow(options: { body: estree.Expression | estree.BlockStatement; async: boolean; }): estree.ArrowFunctionExpression; -declare function getArgument(node: estree.CallExpression, options: { - index: number; - fallback: T; -}): T; +declare function getArgument( + node: estree.CallExpression, + options: { + index: number; + fallback: T; + }, +): T; declare namespace imports_d_exports { - export { addDefault, addEmpty, addNamed, addNamespace$1 as addNamespace, find, remove }; + export { + addDefault, + addEmpty, + addNamed, + addNamespace$1 as addNamespace, + find, + remove, + }; } -declare function addEmpty(node: estree.Program, options: { - from: string; -}): void; -declare function addNamespace$1(node: estree.Program, options: { - from: string; - as: string; -}): void; -declare function addDefault(node: estree.Program, options: { - from: string; - as: string; -}): void; -declare function addNamed(node: estree.Program, options: { - - imports: Record | string[]; - from: string; - isType?: boolean; -}): void; -declare function find(ast: estree.Program, options: { - name: string; - from: string; -}): { - statement: estree.ImportDeclaration; - alias: string; -} | { - statement: undefined; - alias: undefined; -}; -declare function remove(ast: estree.Program, options: { - name: string; - from: string; - statement?: estree.ImportDeclaration; -}): void; +declare function addEmpty( + node: estree.Program, + options: { + from: string; + }, +): void; +declare function addNamespace$1( + node: estree.Program, + options: { + from: string; + as: string; + }, +): void; +declare function addDefault( + node: estree.Program, + options: { + from: string; + as: string; + }, +): void; +declare function addNamed( + node: estree.Program, + options: { + imports: Record | string[]; + from: string; + isType?: boolean; + }, +): void; +declare function find( + ast: estree.Program, + options: { + name: string; + from: string; + }, +): + | { + statement: estree.ImportDeclaration; + alias: string; + } + | { + statement: undefined; + alias: undefined; + }; +declare function remove( + ast: estree.Program, + options: { + name: string; + from: string; + statement?: estree.ImportDeclaration; + }, +): void; declare namespace variables_d_exports { export { createIdentifier, declaration, typeAnnotateDeclarator }; } -declare function declaration(node: estree.Program | estree.Declaration, options: { - kind: "const" | "let" | "var"; - name: string; - value: estree.Expression; -}): estree.VariableDeclaration; +declare function declaration( + node: estree.Program | estree.Declaration, + options: { + kind: "const" | "let" | "var"; + name: string; + value: estree.Expression; + }, +): estree.VariableDeclaration; declare function createIdentifier(name: string): estree.Identifier; -declare function typeAnnotateDeclarator(node: estree.VariableDeclarator, options: { - typeName: string; -}): estree.VariableDeclarator; +declare function typeAnnotateDeclarator( + node: estree.VariableDeclarator, + options: { + typeName: string; + }, +): estree.VariableDeclarator; declare namespace exports_d_exports { export { ExportDefaultResult, addNamespace, createDefault, createNamed }; } @@ -1083,53 +1423,109 @@ type ExportDefaultResult = { value: T; isFallback: boolean; }; -declare function createDefault(node: estree.Program, options: { - fallback: T; -}): ExportDefaultResult; -declare function createNamed(node: estree.Program, options: { - name: string; - fallback: estree.VariableDeclaration; -}): estree.ExportNamedDeclaration; -declare function addNamespace(node: estree.Program, options: { - from: string; - as?: string; -}): void; +declare function createDefault( + node: estree.Program, + options: { + fallback: T; + }, +): ExportDefaultResult; +declare function createNamed( + node: estree.Program, + options: { + name: string; + fallback: estree.VariableDeclaration; + }, +): estree.ExportNamedDeclaration; +declare function addNamespace( + node: estree.Program, + options: { + from: string; + as?: string; + }, +): void; declare namespace kit_d_exports { export { addGlobalAppInterface, addHooksHandle }; } -declare function addGlobalAppInterface(node: estree.TSProgram, options: { - name: "Error" | "Locals" | "PageData" | "PageState" | "Platform"; -}): estree.TSInterfaceDeclaration; -declare function addHooksHandle(node: estree.Program, options: { - language: "ts" | "js"; - newHandleName: string; - handleContent: string; - comments: Comments; -}): void; +declare function addGlobalAppInterface( + node: estree.TSProgram, + options: { + name: "Error" | "Locals" | "PageData" | "PageState" | "Platform"; + }, +): estree.TSInterfaceDeclaration; +declare function addHooksHandle( + node: estree.Program, + options: { + language: "ts" | "js"; + newHandleName: string; + handleContent: string; + comments: Comments; + }, +): void; declare namespace vite_d_exports { export { addPlugin, configProperty, getConfig }; } -declare const addPlugin: (ast: estree.Program, options: { - code: string; - mode?: "append" | "prepend"; -}) => void; +declare const addPlugin: ( + ast: estree.Program, + options: { + code: string; + mode?: "append" | "prepend"; + }, +) => void; -declare function configProperty(ast: estree.Program, config: estree.ObjectExpression, options: { - name: string; - fallback: T; -}): T; +declare function configProperty< + T extends estree.Expression | estree.Identifier, +>( + ast: estree.Program, + config: estree.ObjectExpression, + options: { + name: string; + fallback: T; + }, +): T; declare const getConfig: (ast: estree.Program) => estree.ObjectExpression; declare namespace index_d_exports$3 { - export { array_d_exports as array, common_d_exports as common, exports_d_exports as exports, function_d_exports as functions, imports_d_exports as imports, kit_d_exports as kit, object_d_exports as object, variables_d_exports as variables, vite_d_exports as vite }; + export { + array_d_exports as array, + common_d_exports as common, + exports_d_exports as exports, + function_d_exports as functions, + imports_d_exports as imports, + kit_d_exports as kit, + object_d_exports as object, + variables_d_exports as variables, + vite_d_exports as vite, + }; } declare namespace index_d_exports$2 { - export { addAttribute, addFromRawHtml, appendElement, createElement, insertElement }; + export { + addAttribute, + addFromRawHtml, + appendElement, + createElement, + insertElement, + }; } -declare function createElement(tagName: string, attributes?: Record): SvelteAst.RegularElement; -declare function addAttribute(element: SvelteAst.RegularElement, name: string, value: string): void; -declare function insertElement(fragment: SvelteAst.Fragment, elementToInsert: SvelteAst.Fragment["nodes"][0]): void; -declare function appendElement(fragment: SvelteAst.Fragment, elementToAppend: SvelteAst.Fragment["nodes"][0]): void; -declare function addFromRawHtml(fragment: SvelteAst.Fragment, html: string): void; +declare function createElement( + tagName: string, + attributes?: Record, +): SvelteAst.RegularElement; +declare function addAttribute( + element: SvelteAst.RegularElement, + name: string, + value: string, +): void; +declare function insertElement( + fragment: SvelteAst.Fragment, + elementToInsert: SvelteAst.Fragment["nodes"][0], +): void; +declare function appendElement( + fragment: SvelteAst.Fragment, + elementToAppend: SvelteAst.Fragment["nodes"][0], +): void; +declare function addFromRawHtml( + fragment: SvelteAst.Fragment, + html: string, +): void; declare namespace text_d_exports { export { upsert }; } @@ -1139,98 +1535,145 @@ type CommentEntry = { }; type CommentOption = string | Array; -declare function upsert(content: string, key: string, options?: { - value?: string; - comment?: CommentOption; - separator?: boolean; -}): string; +declare function upsert( + content: string, + key: string, + options?: { + value?: string; + comment?: CommentOption; + separator?: boolean; + }, +): string; declare namespace json_d_exports { export { arrayUpsert, packageScriptsUpsert }; } -declare function arrayUpsert(data: any, key: string, value: any, options?: { - mode?: "append" | "prepend"; -}): void; -declare function packageScriptsUpsert(data: any, key: string, value: string, options?: { - mode?: "append" | "prepend"; -}): void; +declare function arrayUpsert( + data: any, + key: string, + value: any, + options?: { + mode?: "append" | "prepend"; + }, +): void; +declare function packageScriptsUpsert( + data: any, + key: string, + value: string, + options?: { + mode?: "append" | "prepend"; + }, +): void; declare namespace index_d_exports$4 { export { RootWithInstance, addFragment, addSlot, ensureScript }; } type RootWithInstance = SvelteAst.Root & { instance: SvelteAst.Script; }; -declare function ensureScript(ast: SvelteAst.Root, options?: { - language?: "ts" | "js"; -}): asserts ast is RootWithInstance; -declare function addSlot(ast: SvelteAst.Root, options: { - svelteVersion: string; - language?: "ts" | "js"; -}): void; -declare function addFragment(ast: SvelteAst.Root, content: string, options?: { - mode?: "append" | "prepend"; -}): void; +declare function ensureScript( + ast: SvelteAst.Root, + options?: { + language?: "ts" | "js"; + }, +): asserts ast is RootWithInstance; +declare function addSlot( + ast: SvelteAst.Root, + options: { + svelteVersion: string; + language?: "ts" | "js"; + }, +): void; +declare function addFragment( + ast: SvelteAst.Root, + content: string, + options?: { + mode?: "append" | "prepend"; + }, +): void; type TransformFn = (content: string) => string; type TransformOptions = { onError?: (error: unknown) => void; }; declare const transforms: { - - script(cb: (file: { - ast: estree.Program; - comments: Comments; - content: string; - js: typeof index_d_exports$3; - }) => void | false, options?: TransformOptions): (content: string) => string; - - svelte(cb: (file: { - ast: SvelteAst.Root; - content: string; - svelte: typeof index_d_exports$4; - js: typeof index_d_exports$3; - }) => void | false, options?: TransformOptions): (content: string) => string; - - svelteScript(scriptOptions: { - language: "ts" | "js"; - }, cb: (file: { - ast: RootWithInstance; - content: string; - svelte: typeof index_d_exports$4; - js: typeof index_d_exports$3; - }) => void | false, options?: TransformOptions): TransformFn; - - css(cb: (file: { - ast: Omit; - content: string; - css: typeof index_d_exports$1; - }) => void | false, options?: TransformOptions): TransformFn; - - json(cb: (file: { - data: T; - content: string; - json: typeof json_d_exports; - }) => void | false, options?: TransformOptions): TransformFn; - - yaml(cb: (file: { - data: ReturnType["data"]; - content: string; - }) => void | false, options?: TransformOptions): TransformFn; - - toml(cb: (file: { - data: TomlTable; - content: string; - }) => void | false, options?: TransformOptions): TransformFn; - - html(cb: (file: { - ast: SvelteAst.Fragment; - content: string; - html: typeof index_d_exports$2; - }) => void | false, options?: TransformOptions): TransformFn; - - text(cb: (file: { - content: string; - text: typeof text_d_exports; - }) => string | false): TransformFn; + script( + cb: (file: { + ast: estree.Program; + comments: Comments; + content: string; + js: typeof index_d_exports$3; + }) => void | false, + options?: TransformOptions, + ): (content: string) => string; + + svelte( + cb: (file: { + ast: SvelteAst.Root; + content: string; + svelte: typeof index_d_exports$4; + js: typeof index_d_exports$3; + }) => void | false, + options?: TransformOptions, + ): (content: string) => string; + + svelteScript( + scriptOptions: { + language: "ts" | "js"; + }, + cb: (file: { + ast: RootWithInstance; + content: string; + svelte: typeof index_d_exports$4; + js: typeof index_d_exports$3; + }) => void | false, + options?: TransformOptions, + ): TransformFn; + + css( + cb: (file: { + ast: Omit; + content: string; + css: typeof index_d_exports$1; + }) => void | false, + options?: TransformOptions, + ): TransformFn; + + json( + cb: (file: { + data: T; + content: string; + json: typeof json_d_exports; + }) => void | false, + options?: TransformOptions, + ): TransformFn; + + yaml( + cb: (file: { + data: ReturnType["data"]; + content: string; + }) => void | false, + options?: TransformOptions, + ): TransformFn; + + toml( + cb: (file: { data: TomlTable; content: string }) => void | false, + options?: TransformOptions, + ): TransformFn; + + html( + cb: (file: { + ast: SvelteAst.Fragment; + content: string; + html: typeof index_d_exports$2; + }) => void | false, + options?: TransformOptions, + ): TransformFn; + + text( + cb: (file: { + content: string; + text: typeof text_d_exports; + }) => string | false, + ): TransformFn; }; type Version = { major?: number; @@ -1238,11 +1681,17 @@ type Version = { patch?: number; }; declare function splitVersion(str: string): Version; -declare function isVersionUnsupportedBelow(versionStr: string, belowStr: string): boolean | undefined; +declare function isVersionUnsupportedBelow( + versionStr: string, + belowStr: string, +): boolean | undefined; type Printer = (content: string, alt?: string) => string; declare function createPrinter(...conditions: boolean[]): Printer[]; -declare function sanitizeName(name: string, style: "package" | "wrangler"): string; +declare function sanitizeName( + name: string, + style: "package" | "wrangler", +): string; declare const downloadJson: (url: string) => Promise; type Package = { name: string; @@ -1277,16 +1726,16 @@ declare function loadPackageJson(cwd: string): { generateCode: () => string; }; /** -* @deprecated Use {@link loadFile} instead. This alias will be removed in a future version. -*/ + * @deprecated Use {@link loadFile} instead. This alias will be removed in a future version. + */ declare const readFile: typeof loadFile; /** -* @deprecated Use {@link saveFile} instead. This alias will be removed in a future version. -*/ + * @deprecated Use {@link saveFile} instead. This alias will be removed in a future version. + */ declare const writeFile: typeof saveFile; /** -* @deprecated Use {@link loadPackageJson} instead. This alias will be removed in a future version. -*/ + * @deprecated Use {@link loadPackageJson} instead. This alias will be removed in a future version. + */ declare const getPackageJson: typeof loadPackageJson; type ColorInput = string | string[]; declare const color: { @@ -1304,7 +1753,11 @@ declare const color: { hidden: (str: ColorInput) => string; }; -declare function resolveCommandArray(agent: Agent, command: Command, args: string[]): string[]; +declare function resolveCommandArray( + agent: Agent, + command: Command, + args: string[], +): string[]; declare const parse: { css: typeof parseCss; @@ -1315,5 +1768,42 @@ declare const parse: { toml: typeof parseToml; yaml: typeof parseYaml; }; -export { AGENTS, type AgentName, type estree as AstTypes, COMMANDS, type Comments, type Package, type SvelteAst, type TransformFn, index_d_exports as Walker, color, commonFilePaths, constructCommand, createPrinter, index_d_exports$1 as css, dedent, detect, downloadJson, fileExists, getPackageJson, index_d_exports$2 as html, isVersionUnsupportedBelow, index_d_exports$3 as js, json_d_exports as json, loadFile, loadPackageJson, parse, readFile, resolveCommand, resolveCommandArray, sanitizeName, saveFile, splitVersion, index_d_exports$4 as svelte, text_d_exports as text, transforms, writeFile }; +export { + AGENTS, + type AgentName, + type estree as AstTypes, + COMMANDS, + type Comments, + type Package, + type SvelteAst, + type TransformFn, + index_d_exports as Walker, + color, + commonFilePaths, + constructCommand, + createPrinter, + index_d_exports$1 as css, + dedent, + detect, + downloadJson, + fileExists, + getPackageJson, + index_d_exports$2 as html, + isVersionUnsupportedBelow, + index_d_exports$3 as js, + json_d_exports as json, + loadFile, + loadPackageJson, + parse, + readFile, + resolveCommand, + resolveCommandArray, + sanitizeName, + saveFile, + splitVersion, + index_d_exports$4 as svelte, + text_d_exports as text, + transforms, + writeFile, +}; ``` diff --git a/packages/sv/api-surface-testing.md b/packages/sv/api-surface-testing.md index 7ce75ece3..855db11e7 100644 --- a/packages/sv/api-surface-testing.md +++ b/packages/sv/api-surface-testing.md @@ -3,25 +3,25 @@ ```ts -declare function addPnpmBuildDependencies(cwd: string, packageManager: AgentName | null | undefined, allowedPackages: string[]): Promise; +declare function addPnpmBuildDependencies( + cwd: string, + packageManager: AgentName | null | undefined, + allowedPackages: string[], +): Promise; type ProjectVariant = "kit-js" | "kit-ts" | "vite-js" | "vite-ts"; declare const variants: ProjectVariant[]; type CreateProject = (options: { testId: string; - variant: ProjectVariant; + variant: ProjectVariant; clean?: boolean; }) => string; type SetupOptions = { cwd: string; - variants: readonly ProjectVariant[]; + variants: readonly ProjectVariant[]; clean?: boolean; }; /** @deprecated Internal helper used by `createSetupTest` - will be removed from public API in a future version. */ -declare function setup({ - cwd, - clean, - variants -}: SetupOptions): { +declare function setup({ cwd, clean, variants }: SetupOptions): { templatesDir: string; }; type CreateOptions = { @@ -33,17 +33,14 @@ type CreateOptions = { declare function createProject({ cwd, testName, - templatesDir + templatesDir, }: CreateOptions): CreateProject; type PreviewOptions = { cwd: string; command?: string; }; /** @deprecated Internal helper used by `prepareServer` - will be removed from public API in a future version. */ -declare function startPreview({ - cwd, - command -}: PreviewOptions): Promise<{ +declare function startPreview({ cwd, command }: PreviewOptions): Promise<{ url: string; close: () => Promise; }>; @@ -57,14 +54,12 @@ declare module "vitest" { declare function setupGlobal({ TEST_DIR, pre, - post + post, }: { TEST_DIR: string; pre?: () => Promise; post?: () => Promise; -}): ({ - provide -}: TestProject) => Promise<() => Promise>; +}): ({ provide }: TestProject) => Promise<() => Promise>; type Fixtures = { page: Page; cwd(addonTestCase: AddonTestCase): string; @@ -99,14 +94,41 @@ declare function prepareServer({ cwd, page, buildCommand, - previewCommand + previewCommand, }: PrepareServerOptions): Promise; type PlaywrightContext = Pick; -type VitestContext = Pick; -declare function createSetupTest(vitest: VitestContext, playwright?: PlaywrightContext): (addons: Addons, options?: SetupTestOptions) => { +type VitestContext = Pick< + typeof vitest, + "inject" | "test" | "beforeAll" | "beforeEach" +>; +declare function createSetupTest( + vitest: VitestContext, + playwright?: PlaywrightContext, +): ( + addons: Addons, + options?: SetupTestOptions, +) => { test: vitest.TestAPI; testCases: Array>; prepareServer: typeof prepareServer; }; -export { AddonTestCase, CreateProject, Fixtures, PlaywrightContext, PrepareServerOptions, PrepareServerReturn, ProjectVariant, SetupTestOptions, VitestContext, addPnpmBuildDependencies, createProject, createSetupTest, prepareServer, setup, setupGlobal, startPreview, variants }; +export { + AddonTestCase, + CreateProject, + Fixtures, + PlaywrightContext, + PrepareServerOptions, + PrepareServerReturn, + ProjectVariant, + SetupTestOptions, + VitestContext, + addPnpmBuildDependencies, + createProject, + createSetupTest, + prepareServer, + setup, + setupGlobal, + startPreview, + variants, +}; ``` diff --git a/packages/sv/api-surface.md b/packages/sv/api-surface.md index 5651f3483..f9ccdfbd9 100644 --- a/packages/sv/api-surface.md +++ b/packages/sv/api-surface.md @@ -5,7 +5,13 @@ ```ts type TemplateType = (typeof templateTypes)[number]; type LanguageType = (typeof languageTypes)[number]; -declare const templateTypes: readonly ["minimal", "demo", "library", "addon", "svelte"]; +declare const templateTypes: readonly [ + "minimal", + "demo", + "library", + "addon", + "svelte", +]; declare const languageTypes: readonly ["typescript", "checkjs", "none"]; type Options = { cwd: string; @@ -23,5 +29,41 @@ type FileType = { condition?: ConditionDefinition; content: (editor: FileEditor) => string; }; -export { type Addon, type AddonDefinition, type AddonInput, type AddonMap, type AddonReference, type AddonResult, type AddonSource, type BaseQuestion, type BooleanQuestion, type ConfiguredAddon, type FileEditor, type FileType, type InstallOptions, type LanguageType, type LoadedAddon, type MultiSelectQuestion, type NumberQuestion, type OptionBuilder, type OptionDefinition, type OptionMap, type OptionValues, type PreparedAddon, type Question, type SelectQuestion, type SetupResult, type StringQuestion, type SvApi, type TemplateType, type Workspace, type WorkspaceOptions, add, create, defineAddon, defineAddonOptions, officialAddons }; +export { + type Addon, + type AddonDefinition, + type AddonInput, + type AddonMap, + type AddonReference, + type AddonResult, + type AddonSource, + type BaseQuestion, + type BooleanQuestion, + type ConfiguredAddon, + type FileEditor, + type FileType, + type InstallOptions, + type LanguageType, + type LoadedAddon, + type MultiSelectQuestion, + type NumberQuestion, + type OptionBuilder, + type OptionDefinition, + type OptionMap, + type OptionValues, + type PreparedAddon, + type Question, + type SelectQuestion, + type SetupResult, + type StringQuestion, + type SvApi, + type TemplateType, + type Workspace, + type WorkspaceOptions, + add, + create, + defineAddon, + defineAddonOptions, + officialAddons, +}; ``` diff --git a/packages/sv/src/create/index.ts b/packages/sv/src/create/index.ts index 1c30c199b..5b78b6c45 100644 --- a/packages/sv/src/create/index.ts +++ b/packages/sv/src/create/index.ts @@ -35,10 +35,7 @@ export type Common = { export function create(cwd: string, options: Omit): void; export function create(options: Options): void; -export function create( - cwdOrOptions: string | Options, - legacyOptions?: Omit -): void { +export function create(cwdOrOptions: string | Options, legacyOptions?: Omit): void { let cwd: string; let options: Omit; if (typeof cwdOrOptions === 'string') { diff --git a/scripts/generate-api-surface.js b/scripts/generate-api-surface.js index d34bf160b..bc7a5deaf 100644 --- a/scripts/generate-api-surface.js +++ b/scripts/generate-api-surface.js @@ -8,11 +8,14 @@ * * Run: node scripts/generate-api-surface.js * Or: invoked from tsdown `build:done` after all configs finish (see tsdown.config.ts). + * + * Finishes with Prettier (repo root config) so snapshots match `pnpm format`. */ import fs from 'node:fs'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; +import * as prettier from 'prettier'; const ROOT = path.dirname(path.dirname(fileURLToPath(import.meta.url))); @@ -84,8 +87,17 @@ function clean(source) { return result.trim() + '\n'; } -/** @returns {number} number of api-surface files written */ -export function generateApiSurface() { +/** + * @param {string} absPath absolute path to the markdown file + */ +async function formatWithPrettier(absPath) { + const raw = fs.readFileSync(absPath, 'utf8'); + const formatted = await prettier.format(raw, { filepath: absPath }); + fs.writeFileSync(absPath, formatted, 'utf8'); +} + +/** @returns {Promise} number of api-surface files written */ +export async function generateApiSurface() { let generated = 0; for (const pkg of packages) { const dtsPath = path.resolve(ROOT, pkg.dts); @@ -105,6 +117,7 @@ export function generateApiSurface() { const outPath = path.resolve(ROOT, pkg.out); fs.writeFileSync(outPath, header + cleaned + footer, 'utf8'); + await formatWithPrettier(outPath); generated++; console.log(` ${pkg.name} -> ${pkg.out}`); } @@ -121,5 +134,8 @@ const isMain = process.argv[1] && fileURLToPath(import.meta.url) === path.resolve(process.argv[1]); if (isMain) { - generateApiSurface(); + generateApiSurface().catch((err) => { + console.error(err); + process.exit(1); + }); } From b9f7365f568549d9f14adf3d69f9c489fbe3c69d Mon Sep 17 00:00:00 2001 From: jycouet Date: Sat, 4 Apr 2026 16:13:28 +0200 Subject: [PATCH 7/7] cleanup types --- packages/sv-utils/api-surface.md | 952 +------------------- packages/sv-utils/src/dedent.ts | 13 + packages/sv-utils/src/index.ts | 21 +- packages/sv-utils/src/pm.ts | 23 + packages/sv-utils/src/tooling/parsers.ts | 18 +- packages/sv-utils/src/tooling/transforms.ts | 5 +- packages/sv/src/addons/sveltekit-adapter.ts | 2 +- packages/sv/src/cli/create.ts | 2 +- packages/sv/src/core/common.ts | 6 +- packages/sv/src/core/engine.ts | 6 +- packages/sv/src/core/package-manager.ts | 6 +- tsdown.config.ts | 11 +- 12 files changed, 97 insertions(+), 968 deletions(-) create mode 100644 packages/sv-utils/src/dedent.ts create mode 100644 packages/sv-utils/src/pm.ts diff --git a/packages/sv-utils/api-surface.md b/packages/sv-utils/api-surface.md index a4f243206..fda21143d 100644 --- a/packages/sv-utils/api-surface.md +++ b/packages/sv-utils/api-surface.md @@ -3,79 +3,6 @@ ```ts -type Agent = "npm" | "yarn" | "yarn@berry" | "pnpm" | "pnpm@6" | "bun" | "deno"; -type AgentName = "npm" | "yarn" | "pnpm" | "bun" | "deno"; -type AgentCommandValue = - | (string | number)[] - | ((args: string[]) => string[]) - | null; -interface AgentCommands { - agent: AgentCommandValue; - run: AgentCommandValue; - install: AgentCommandValue; - frozen: AgentCommandValue; - global: AgentCommandValue; - add: AgentCommandValue; - upgrade: AgentCommandValue; - "upgrade-interactive": AgentCommandValue; - dedupe: AgentCommandValue; - execute: AgentCommandValue; - "execute-local": AgentCommandValue; - uninstall: AgentCommandValue; - global_uninstall: AgentCommandValue; -} -type Command = keyof AgentCommands; -interface ResolvedCommand { - command: string; - - args: string[]; -} -type DetectStrategy = - | "lockfile" - | "packageManager-field" - | "devEngines-field" - | "install-metadata"; -interface DetectOptions { - cwd?: string; - - strategies?: DetectStrategy[]; - - onUnknown?: (packageManager: string) => DetectResult | null | undefined; - - stopDir?: string | ((currentDir: string) => boolean); - - packageJsonParser?: (content: string, filepath: string) => any | Promise; -} -interface DetectResult { - name: AgentName; - - agent: Agent; - - version?: string; -} -declare const COMMANDS: { - npm: AgentCommands; - yarn: AgentCommands; - "yarn@berry": AgentCommands; - pnpm: AgentCommands; - "pnpm@6": AgentCommands; - bun: AgentCommands; - deno: AgentCommands; -}; - -declare function resolveCommand( - agent: Agent, - command: Command, - args: string[], -): ResolvedCommand | null; - -declare function constructCommand( - value: AgentCommandValue, - args: string[], -): ResolvedCommand | null; -declare const AGENTS: Agent[]; - -declare function detect(options?: DetectOptions): Promise; /*! * Copyright (c) Squirrel Chat et al., All rights reserved. * SPDX-License-Identifier: BSD-3-Clause @@ -122,846 +49,6 @@ type TomlTable = { [key: string]: TomlValue; }; type TomlValue = TomlPrimitive | TomlValue[] | TomlTable; - -declare class LineCounter { - lineStarts: number[]; - - addNewLine: (offset: number) => number; - - linePos: (offset: number) => { - line: number; - col: number; - }; -} -type ErrorCode = - | "ALIAS_PROPS" - | "BAD_ALIAS" - | "BAD_DIRECTIVE" - | "BAD_DQ_ESCAPE" - | "BAD_INDENT" - | "BAD_PROP_ORDER" - | "BAD_SCALAR_START" - | "BLOCK_AS_IMPLICIT_KEY" - | "BLOCK_IN_FLOW" - | "DUPLICATE_KEY" - | "IMPOSSIBLE" - | "KEY_OVER_1024_CHARS" - | "MISSING_CHAR" - | "MULTILINE_IMPLICIT_KEY" - | "MULTIPLE_ANCHORS" - | "MULTIPLE_DOCS" - | "MULTIPLE_TAGS" - | "NON_STRING_KEY" - | "TAB_AS_INDENT" - | "TAG_RESOLVE_FAILED" - | "UNEXPECTED_TOKEN" - | "BAD_COLLECTION_TYPE"; -type LinePos = { - line: number; - col: number; -}; -declare class YAMLError extends Error { - name: "YAMLParseError" | "YAMLWarning"; - code: ErrorCode; - message: string; - pos: [number, number]; - linePos?: [LinePos] | [LinePos, LinePos]; - constructor( - name: YAMLError["name"], - pos: [number, number], - code: ErrorCode, - message: string, - ); -} -declare class YAMLWarning extends YAMLError { - constructor(pos: [number, number], code: ErrorCode, message: string); -} -type Reviver = (key: unknown, value: unknown) => unknown; -type LogLevelId = "silent" | "error" | "warn" | "debug"; -interface AnchorData { - aliasCount: number; - count: number; - res: unknown; -} -interface ToJSContext { - anchors: Map; - - aliasResolveCache?: Node[]; - doc: Document; - keep: boolean; - mapAsMap: boolean; - mapKeyWarned: boolean; - maxAliasCount: number; - onCreate?: (res: unknown) => void; -} -declare namespace Scalar { - interface Parsed extends Scalar { - range: Range; - source: string; - srcToken?: FlowScalar | BlockScalar; - } - type BLOCK_FOLDED = "BLOCK_FOLDED"; - type BLOCK_LITERAL = "BLOCK_LITERAL"; - type PLAIN = "PLAIN"; - type QUOTE_DOUBLE = "QUOTE_DOUBLE"; - type QUOTE_SINGLE = "QUOTE_SINGLE"; - type Type = - | BLOCK_FOLDED - | BLOCK_LITERAL - | PLAIN - | QUOTE_DOUBLE - | QUOTE_SINGLE; -} -declare class Scalar extends NodeBase { - static readonly BLOCK_FOLDED = "BLOCK_FOLDED"; - static readonly BLOCK_LITERAL = "BLOCK_LITERAL"; - static readonly PLAIN = "PLAIN"; - static readonly QUOTE_DOUBLE = "QUOTE_DOUBLE"; - static readonly QUOTE_SINGLE = "QUOTE_SINGLE"; - value: T; - - anchor?: string; - - format?: string; - - minFractionDigits?: number; - - source?: string; - - type?: Scalar.Type; - constructor(value: T); - toJSON(arg?: any, ctx?: ToJSContext): any; - toString(): string; -} -type StringifyContext = { - actualString?: boolean; - allNullValues?: boolean; - anchors: Set; - doc: Document; - forceBlockIndent?: boolean; - implicitKey?: boolean; - indent: string; - indentStep: string; - indentAtStart?: number; - inFlow: boolean | null; - inStringifyKey?: boolean; - flowCollectionPadding: string; - options: Readonly< - Required> - >; - resolvedAliases?: Set; -}; -declare abstract class Collection extends NodeBase { - schema: Schema | undefined; - [NODE_TYPE]: symbol; - items: unknown[]; - - anchor?: string; - - flow?: boolean; - constructor(type: symbol, schema?: Schema); - - clone(schema?: Schema): Collection; - - abstract add(value: unknown): void; - - abstract delete(key: unknown): boolean; - - abstract get(key: unknown, keepScalar?: boolean): unknown; - - abstract has(key: unknown): boolean; - - abstract set(key: unknown, value: unknown): void; - - addIn(path: Iterable, value: unknown): void; - - deleteIn(path: Iterable): boolean; - - getIn(path: Iterable, keepScalar?: boolean): unknown; - hasAllNullValues(allowScalar?: boolean): boolean; - - hasIn(path: Iterable): boolean; - - setIn(path: Iterable, value: unknown): void; -} -declare namespace YAMLSeq { - interface Parsed< - T extends ParsedNode | Pair = ParsedNode, - > extends YAMLSeq { - items: T[]; - range: Range; - srcToken?: BlockSequence | FlowCollection; - } -} -declare class YAMLSeq extends Collection { - static get tagName(): "tag:yaml.org,2002:seq"; - items: T[]; - constructor(schema?: Schema); - add(value: T): void; - - delete(key: unknown): boolean; - - get(key: unknown, keepScalar: true): Scalar | undefined; - get(key: unknown, keepScalar?: false): T | undefined; - get(key: unknown, keepScalar?: boolean): T | Scalar | undefined; - - has(key: unknown): boolean; - - set(key: unknown, value: T): void; - toJSON(_?: unknown, ctx?: ToJSContext): unknown[]; - toString( - ctx?: StringifyContext, - onComment?: () => void, - onChompKeep?: () => void, - ): string; - static from(schema: Schema, obj: unknown, ctx: CreateNodeContext): YAMLSeq; -} -interface TagBase { - createNode?: (schema: Schema, value: unknown, ctx: CreateNodeContext) => Node; - - default?: boolean | "key"; - - format?: string; - - identify?: (value: unknown) => boolean; - - tag: string; -} -interface ScalarTag extends TagBase { - collection?: never; - nodeClass?: never; - - resolve( - value: string, - onError: (message: string) => void, - options: ParseOptions, - ): unknown; - - stringify?: ( - item: Scalar, - ctx: StringifyContext, - onComment?: () => void, - onChompKeep?: () => void, - ) => string; - - test?: RegExp; -} -interface CollectionTag extends TagBase { - stringify?: never; - test?: never; - - collection: "map" | "seq"; - - nodeClass?: { - new (schema?: Schema): Node; - from?: (schema: Schema, obj: unknown, ctx: CreateNodeContext) => Node; - }; - - resolve?: ( - value: YAMLMap.Parsed | YAMLSeq.Parsed, - onError: (message: string) => void, - options: ParseOptions, - ) => unknown; -} -type MapLike = - | Map - | Set - | Record; -declare namespace YAMLMap { - interface Parsed< - K extends ParsedNode = ParsedNode, - V extends ParsedNode | null = ParsedNode | null, - > extends YAMLMap { - items: Pair[]; - range: Range; - srcToken?: BlockMap | FlowCollection; - } -} -declare class YAMLMap extends Collection { - static get tagName(): "tag:yaml.org,2002:map"; - items: Pair[]; - constructor(schema?: Schema); - - static from(schema: Schema, obj: unknown, ctx: CreateNodeContext): YAMLMap; - - add( - pair: - | Pair - | { - key: K; - value: V; - }, - overwrite?: boolean, - ): void; - delete(key: unknown): boolean; - get(key: unknown, keepScalar: true): Scalar | undefined; - get(key: unknown, keepScalar?: false): V | undefined; - get(key: unknown, keepScalar?: boolean): V | Scalar | undefined; - has(key: unknown): boolean; - set(key: K, value: V): void; - - toJSON>( - _?: unknown, - ctx?: ToJSContext, - Type?: { - new (): T; - }, - ): any; - toString( - ctx?: StringifyContext, - onComment?: () => void, - onChompKeep?: () => void, - ): string; -} -declare const MAP: unique symbol; -declare const SCALAR: unique symbol; -declare const SEQ: unique symbol; -declare const NODE_TYPE: unique symbol; -declare class Schema { - compat: Array | null; - knownTags: Record; - name: string; - sortMapEntries: ((a: Pair, b: Pair) => number) | null; - tags: Array; - toStringOptions: Readonly | null; - readonly [MAP]: CollectionTag; - readonly [SCALAR]: ScalarTag; - readonly [SEQ]: CollectionTag; - constructor({ - compat, - customTags, - merge, - resolveKnownTags, - schema, - sortMapEntries, - toStringDefaults, - }: SchemaOptions); - clone(): Schema; -} -interface CreateNodeContext { - aliasDuplicateObjects: boolean; - keepUndefined: boolean; - onAnchor: (source: unknown) => string; - onTagObj?: (tagObj: ScalarTag | CollectionTag) => void; - sourceObjects: Map< - unknown, - { - anchor: string | null; - node: Node | null; - } - >; - replacer?: Replacer; - schema: Schema; -} -declare function addPairToJSMap( - ctx: ToJSContext | undefined, - map: MapLike, - { key, value }: Pair, -): MapLike; -declare class Pair { - readonly [NODE_TYPE]: symbol; - - key: K; - - value: V | null; - - srcToken?: CollectionItem; - constructor(key: K, value?: V | null); - clone(schema?: Schema): Pair; - toJSON(_?: unknown, ctx?: ToJSContext): ReturnType; - toString( - ctx?: StringifyContext, - onComment?: () => void, - onChompKeep?: () => void, - ): string; -} -declare const tagsByName: { - binary: ScalarTag; - bool: ScalarTag & { - test: RegExp; - }; - float: ScalarTag; - floatExp: ScalarTag; - floatNaN: ScalarTag; - floatTime: ScalarTag; - int: ScalarTag; - intHex: ScalarTag; - intOct: ScalarTag; - intTime: ScalarTag; - map: CollectionTag; - merge: ScalarTag & { - identify(value: unknown): boolean; - test: RegExp; - }; - null: ScalarTag & { - test: RegExp; - }; - omap: CollectionTag; - pairs: CollectionTag; - seq: CollectionTag; - set: CollectionTag; - timestamp: ScalarTag & { - test: RegExp; - }; -}; -type TagId = keyof typeof tagsByName; -type Tags = Array; -type ParseOptions = { - intAsBigInt?: boolean; - - keepSourceTokens?: boolean; - - lineCounter?: LineCounter; - - prettyErrors?: boolean; - - strict?: boolean; - - stringKeys?: boolean; - - uniqueKeys?: boolean | ((a: ParsedNode, b: ParsedNode) => boolean); -}; -type DocumentOptions = { - _directives?: Directives; - - logLevel?: LogLevelId; - - version?: "1.1" | "1.2" | "next"; -}; -type SchemaOptions = { - compat?: string | Tags | null; - - customTags?: Tags | ((tags: Tags) => Tags) | null; - - merge?: boolean; - - resolveKnownTags?: boolean; - - schema?: string | Schema; - - sortMapEntries?: boolean | ((a: Pair, b: Pair) => number); - - toStringDefaults?: ToStringOptions; -}; -type CreateNodeOptions = { - aliasDuplicateObjects?: boolean; - - anchorPrefix?: string; - flow?: boolean; - - keepUndefined?: boolean | null; - onTagObj?: (tagObj: ScalarTag | CollectionTag) => void; - - tag?: string; -}; -type ToJSOptions = { - mapAsMap?: boolean; - - maxAliasCount?: number; - - onAnchor?: (value: unknown, count: number) => void; - - reviver?: Reviver; -}; -type ToStringOptions = { - blockQuote?: boolean | "folded" | "literal"; - - collectionStyle?: "any" | "block" | "flow"; - - commentString?: (comment: string) => string; - - defaultKeyType?: Scalar.Type | null; - - defaultStringType?: Scalar.Type; - - directives?: boolean | null; - - doubleQuotedAsJSON?: boolean; - - doubleQuotedMinMultiLineLength?: number; - - falseStr?: string; - - flowCollectionPadding?: boolean; - - indent?: number; - - indentSeq?: boolean; - - lineWidth?: number; - - minContentWidth?: number; - - nullStr?: string; - - simpleKeys?: boolean; - - singleQuote?: boolean | null; - - trueStr?: string; - - verifyAliasOrder?: boolean; -}; -type Node = Alias | Scalar | YAMLMap | YAMLSeq; - -type NodeType = T extends - | string - | number - | bigint - | boolean - | null - | undefined - ? Scalar - : T extends Date - ? Scalar - : T extends Array - ? YAMLSeq> - : T extends { - [key: string]: any; - } - ? YAMLMap, NodeType> - : T extends { - [key: number]: any; - } - ? YAMLMap, NodeType> - : Node; -type ParsedNode = - | Alias.Parsed - | Scalar.Parsed - | YAMLMap.Parsed - | YAMLSeq.Parsed; - -type Range = [number, number, number]; -declare abstract class NodeBase { - readonly [NODE_TYPE]: symbol; - - comment?: string | null; - - commentBefore?: string | null; - - range?: Range | null; - - spaceBefore?: boolean; - - srcToken?: Token; - - tag?: string; - - addToJSMap?: ( - ctx: ToJSContext | undefined, - map: MapLike, - value: unknown, - ) => void; - - abstract toJSON(): any; - abstract toString( - ctx?: StringifyContext, - onComment?: () => void, - onChompKeep?: () => void, - ): string; - constructor(type: symbol); - - clone(): NodeBase; - - toJS( - doc: Document, - { mapAsMap, maxAliasCount, onAnchor, reviver }?: ToJSOptions, - ): any; -} -interface SourceToken { - type: - | "byte-order-mark" - | "doc-mode" - | "doc-start" - | "space" - | "comment" - | "newline" - | "directive-line" - | "anchor" - | "tag" - | "seq-item-ind" - | "explicit-key-ind" - | "map-value-ind" - | "flow-map-start" - | "flow-map-end" - | "flow-seq-start" - | "flow-seq-end" - | "flow-error-end" - | "comma" - | "block-scalar-header"; - offset: number; - indent: number; - source: string; -} -interface ErrorToken { - type: "error"; - offset: number; - source: string; - message: string; -} -interface Directive$1 { - type: "directive"; - offset: number; - source: string; -} -interface Document$1 { - type: "document"; - offset: number; - start: SourceToken[]; - value?: Token; - end?: SourceToken[]; -} -interface DocumentEnd { - type: "doc-end"; - offset: number; - source: string; - end?: SourceToken[]; -} -interface FlowScalar { - type: "alias" | "scalar" | "single-quoted-scalar" | "double-quoted-scalar"; - offset: number; - indent: number; - source: string; - end?: SourceToken[]; -} -interface BlockScalar { - type: "block-scalar"; - offset: number; - indent: number; - props: Token[]; - source: string; -} -interface BlockMap { - type: "block-map"; - offset: number; - indent: number; - items: Array< - | { - start: SourceToken[]; - explicitKey?: true; - key?: never; - sep?: never; - value?: never; - } - | { - start: SourceToken[]; - explicitKey?: true; - key: Token | null; - sep: SourceToken[]; - value?: Token; - } - >; -} -interface BlockSequence { - type: "block-seq"; - offset: number; - indent: number; - items: Array<{ - start: SourceToken[]; - key?: never; - sep?: never; - value?: Token; - }>; -} -type CollectionItem = { - start: SourceToken[]; - key?: Token | null; - sep?: SourceToken[]; - value?: Token; -}; -interface FlowCollection { - type: "flow-collection"; - offset: number; - indent: number; - start: SourceToken; - items: CollectionItem[]; - end: SourceToken[]; -} -type Token = - | SourceToken - | ErrorToken - | Directive$1 - | Document$1 - | DocumentEnd - | FlowScalar - | BlockScalar - | BlockMap - | BlockSequence - | FlowCollection; -declare namespace Alias { - interface Parsed extends Alias { - range: Range; - srcToken?: FlowScalar & { - type: "alias"; - }; - } -} -declare class Alias extends NodeBase { - source: string; - anchor?: never; - constructor(source: string); - - resolve( - doc: Document, - ctx?: ToJSContext, - ): Scalar | YAMLMap | YAMLSeq | undefined; - toJSON(_arg?: unknown, ctx?: ToJSContext): unknown; - toString( - ctx?: StringifyContext, - _onComment?: () => void, - _onChompKeep?: () => void, - ): string; -} -type Replacer = any[] | ((key: any, value: any) => unknown); -declare namespace Document { - interface Parsed< - Contents extends ParsedNode = ParsedNode, - Strict extends boolean = true, - > extends Document { - directives: Directives; - range: Range; - } -} -declare class Document< - Contents extends Node = Node, - Strict extends boolean = true, -> { - readonly [NODE_TYPE]: symbol; - - commentBefore: string | null; - - comment: string | null; - - contents: Strict extends true ? Contents | null : Contents; - directives: Strict extends true ? Directives | undefined : Directives; - - errors: YAMLError[]; - options: Required< - Omit< - ParseOptions & DocumentOptions, - "_directives" | "lineCounter" | "version" - > - >; - - range?: Range; - - schema: Schema; - - warnings: YAMLWarning[]; - - constructor( - value?: any, - options?: DocumentOptions & - SchemaOptions & - ParseOptions & - CreateNodeOptions, - ); - constructor( - value: any, - replacer: null | Replacer, - options?: DocumentOptions & - SchemaOptions & - ParseOptions & - CreateNodeOptions, - ); - - clone(): Document; - - add(value: any): void; - - addIn(path: Iterable, value: unknown): void; - - createAlias( - node: Strict extends true ? Scalar | YAMLMap | YAMLSeq : Node, - name?: string, - ): Alias; - - createNode(value: T, options?: CreateNodeOptions): NodeType; - createNode( - value: T, - replacer: Replacer | CreateNodeOptions | null, - options?: CreateNodeOptions, - ): NodeType; - - createPair( - key: unknown, - value: unknown, - options?: CreateNodeOptions, - ): Pair; - - delete(key: unknown): boolean; - - deleteIn(path: Iterable | null): boolean; - - get(key: unknown, keepScalar?: boolean): Strict extends true ? unknown : any; - - getIn( - path: Iterable | null, - keepScalar?: boolean, - ): Strict extends true ? unknown : any; - - has(key: unknown): boolean; - - hasIn(path: Iterable | null): boolean; - - set(key: any, value: unknown): void; - - setIn(path: Iterable | null, value: unknown): void; - - setSchema( - version: "1.1" | "1.2" | "next" | null, - options?: SchemaOptions, - ): void; - - toJS( - opt?: ToJSOptions & { - [ignored: string]: unknown; - }, - ): any; - - toJSON(jsonArg?: string | null, onAnchor?: ToJSOptions["onAnchor"]): any; - - toString(options?: ToStringOptions): string; -} -declare class Directives { - static defaultYaml: Directives["yaml"]; - static defaultTags: Directives["tags"]; - yaml: { - version: "1.1" | "1.2" | "next"; - explicit?: boolean; - }; - tags: Record; - - docStart: true | null; - - docEnd: boolean; - - private atNextDocument?; - constructor(yaml?: Directives["yaml"], tags?: Directives["tags"]); - clone(): Directives; - - atDocument(): Directives; - - add( - line: string, - onError: (offset: number, message: string, warning?: boolean) => void, - ): boolean; - - tagName(source: string, onError: (message: string) => void): string | null; - - tagString(tag: string): string; - toString(doc?: Document): string; -} - -declare function parseDocument< - Contents extends Node = ParsedNode, - Strict extends boolean = true, ->( - source: string, - options?: ParseOptions & DocumentOptions & SchemaOptions, -): Contents extends ParsedNode - ? Document.Parsed - : Document; declare module "estree" { interface TSTypeAnnotation { type: "TSTypeAnnotation"; @@ -1063,7 +150,6 @@ declare module "estree" { importKind: "type" | "value"; } } -declare function parseYaml$1(content: string): ReturnType; type CommentType = { type: "Line" | "Block"; value: string; @@ -1084,6 +170,11 @@ declare class Comments { predicate: (comment: estree.Comment) => boolean | undefined | null, ): void; } + +type YamlDocument = { + get(key: string): unknown; + set(key: string, value: unknown): void; +}; type ParseBase = { source: string; @@ -1103,7 +194,7 @@ declare function parseJson(source: string): { data: any; } & ParseBase; declare function parseYaml(source: string): { - data: ReturnType; + data: YamlDocument; } & ParseBase; declare function parseSvelte(source: string): { ast: SvelteAst.Root; @@ -1111,17 +202,11 @@ declare function parseSvelte(source: string): { declare function parseToml(source: string): { data: TomlTable; } & ParseBase; -interface DedentOptions { - alignValues?: boolean; - escapeSpecialCharacters?: boolean; - trimWhitespace?: boolean; -} -interface Dedent { - (literals: string): string; + +type Dedent = { (strings: TemplateStringsArray, ...values: unknown[]): string; - withOptions: CreateDedent; -} -type CreateDedent = (options: DedentOptions) => Dedent; + (source: string): string; +}; declare const dedent: Dedent; declare module "zimmerframe" { export function walk< @@ -1156,6 +241,11 @@ declare module "zimmerframe" { } export {}; } //# sourceMappingURL=index.d.ts.map +declare function resolveCommandArray( + agent: Agent, + command: Command, + args: string[], +): string[]; declare namespace index_d_exports$1 { export { addAtRule, addDeclaration, addImports, addRule }; } @@ -1647,10 +737,7 @@ declare const transforms: { ): TransformFn; yaml( - cb: (file: { - data: ReturnType["data"]; - content: string; - }) => void | false, + cb: (file: { data: YamlDocument; content: string }) => void | false, options?: TransformOptions, ): TransformFn; @@ -1753,12 +840,6 @@ declare const color: { hidden: (str: ColorInput) => string; }; -declare function resolveCommandArray( - agent: Agent, - command: Command, - args: string[], -): string[]; - declare const parse: { css: typeof parseCss; html: typeof parseHtml; @@ -1778,6 +859,7 @@ export { type SvelteAst, type TransformFn, index_d_exports as Walker, + type YamlDocument, color, commonFilePaths, constructCommand, diff --git a/packages/sv-utils/src/dedent.ts b/packages/sv-utils/src/dedent.ts new file mode 100644 index 000000000..1210bdac9 --- /dev/null +++ b/packages/sv-utils/src/dedent.ts @@ -0,0 +1,13 @@ +import dedentImpl from 'dedent'; + +/** + * Template-tag or single-string dedent helper (same behavior as the `dedent` package). + * Types are hand-written so the public `.d.mts` does not inline `dedent`'s full declarations. + */ +export type Dedent = { + (strings: TemplateStringsArray, ...values: unknown[]): string; + (source: string): string; +}; + +const dedent: Dedent = dedentImpl as Dedent; +export default dedent; diff --git a/packages/sv-utils/src/index.ts b/packages/sv-utils/src/index.ts index d191059fc..8e42b4c3a 100644 --- a/packages/sv-utils/src/index.ts +++ b/packages/sv-utils/src/index.ts @@ -1,8 +1,3 @@ -import { - resolveCommand as _resolveCommand, - type Agent, - type Command -} from 'package-manager-detector'; import { parseCss, parseHtml, @@ -14,22 +9,19 @@ import { } from './tooling/parsers.ts'; // External re-exports -export { default as dedent } from 'dedent'; +export { default as dedent } from './dedent.ts'; export * as Walker from 'zimmerframe'; + +// Package managers (delegates to `package-manager-detector`; see `pm.ts`) export { AGENTS, type AgentName, COMMANDS, constructCommand, detect, - resolveCommand -} from 'package-manager-detector'; - -/** Resolves a package manager command and returns it as a string array (command + args). */ -export function resolveCommandArray(agent: Agent, command: Command, args: string[]): string[] { - const cmd = _resolveCommand(agent, command, args)!; - return [cmd.command, ...cmd.args]; -} + resolveCommand, + resolveCommandArray +} from './pm.ts'; // Parsing & language namespaces export * as css from './tooling/css/index.ts'; @@ -106,3 +98,4 @@ export { color } from './color.ts'; // Types export type { Comments, AstTypes, SvelteAst } from './tooling/index.ts'; export type { TransformFn } from './tooling/transforms.ts'; +export type { YamlDocument } from './tooling/parsers.ts'; diff --git a/packages/sv-utils/src/pm.ts b/packages/sv-utils/src/pm.ts new file mode 100644 index 000000000..fd01d791c --- /dev/null +++ b/packages/sv-utils/src/pm.ts @@ -0,0 +1,23 @@ +/** + * Thin wrapper around [`package-manager-detector`](https://github.com/antfu/package-manager-detector). + * Only the symbols re-exported from the package root are public — we keep this module small and + * avoid exposing the full upstream surface. + */ +import { + resolveCommand as _resolveCommand, + type Agent, + type Command +} from 'package-manager-detector'; +export { + AGENTS, + type AgentName, + COMMANDS, + constructCommand, + detect, + resolveCommand +} from 'package-manager-detector'; + +export function resolveCommandArray(agent: Agent, command: Command, args: string[]): string[] { + const cmd = _resolveCommand(agent, command, args)!; + return [cmd.command, ...cmd.args]; +} diff --git a/packages/sv-utils/src/tooling/parsers.ts b/packages/sv-utils/src/tooling/parsers.ts index f5661ebc2..a20a93803 100644 --- a/packages/sv-utils/src/tooling/parsers.ts +++ b/packages/sv-utils/src/tooling/parsers.ts @@ -1,6 +1,15 @@ import type { TomlTable } from 'smol-toml'; import * as utils from './index.ts'; +/** + * Minimal shape for YAML document roots from `parse.yaml` — avoids re-exporting the full `yaml` types. + * At runtime this is the library’s document type; only `get` / `set` are part of the public contract. + */ +export type YamlDocument = { + get(key: string): unknown; + set(key: string, value: unknown): void; +}; + type ParseBase = { source: string; /** @@ -52,14 +61,13 @@ export function parseJson(source: string): { data: any } & ParseBase { return { data, source, generateCode }; } -export function parseYaml( - source: string -): { data: ReturnType } & ParseBase { +export function parseYaml(source: string): { data: YamlDocument } & ParseBase { if (!source) source = ''; const data = utils.parseYaml(source); - const generateCode = () => utils.serializeYaml(data); + const generateCode = () => + utils.serializeYaml(data as Parameters[0]); - return { data, source, generateCode }; + return { data: data as YamlDocument, source, generateCode }; } export function parseSvelte(source: string): { ast: utils.SvelteAst.Root } & ParseBase { diff --git a/packages/sv-utils/src/tooling/transforms.ts b/packages/sv-utils/src/tooling/transforms.ts index 5d27c1696..361b5925b 100644 --- a/packages/sv-utils/src/tooling/transforms.ts +++ b/packages/sv-utils/src/tooling/transforms.ts @@ -12,7 +12,8 @@ import { parseScript, parseSvelte, parseToml, - parseYaml + parseYaml, + type YamlDocument } from './parsers.ts'; import { type RootWithInstance, ensureScript } from './svelte/index.ts'; import * as svelteNs from './svelte/index.ts'; @@ -190,7 +191,7 @@ export const transforms = { * Return `false` from the callback to abort - the original content is returned unchanged. */ yaml( - cb: (file: { data: ReturnType['data']; content: string }) => void | false, + cb: (file: { data: YamlDocument; content: string }) => void | false, options?: TransformOptions ): TransformFn { return (content) => { diff --git a/packages/sv/src/addons/sveltekit-adapter.ts b/packages/sv/src/addons/sveltekit-adapter.ts index 739e89896..4f2340da7 100644 --- a/packages/sv/src/addons/sveltekit-adapter.ts +++ b/packages/sv/src/addons/sveltekit-adapter.ts @@ -1,8 +1,8 @@ import { color, - resolveCommandArray, text, transforms, + resolveCommandArray, fileExists, loadPackageJson, sanitizeName diff --git a/packages/sv/src/cli/create.ts b/packages/sv/src/cli/create.ts index c7888c575..8dddfe6ad 100644 --- a/packages/sv/src/cli/create.ts +++ b/packages/sv/src/cli/create.ts @@ -1,5 +1,5 @@ import * as p from '@clack/prompts'; -import { color, resolveCommandArray, commonFilePaths, loadPackageJson } from '@sveltejs/sv-utils'; +import { color, commonFilePaths, loadPackageJson, resolveCommandArray } from '@sveltejs/sv-utils'; import { Command, Option } from 'commander'; import fs from 'node:fs'; import path from 'node:path'; diff --git a/packages/sv/src/core/common.ts b/packages/sv/src/core/common.ts index 856b8e0c5..aace74cc8 100644 --- a/packages/sv/src/core/common.ts +++ b/packages/sv/src/core/common.ts @@ -1,9 +1,9 @@ import * as p from '@clack/prompts'; import { - type AgentName, color, - resolveCommandArray, - isVersionUnsupportedBelow + isVersionUnsupportedBelow, + type AgentName, + resolveCommandArray } from '@sveltejs/sv-utils'; import type { Argument, Command, Help, HelpConfiguration, Option } from 'commander'; import fs from 'node:fs'; diff --git a/packages/sv/src/core/engine.ts b/packages/sv/src/core/engine.ts index 9e2028c42..b832dbc04 100644 --- a/packages/sv/src/core/engine.ts +++ b/packages/sv/src/core/engine.ts @@ -2,12 +2,12 @@ import * as p from '@clack/prompts'; import { color, commonFilePaths, - resolveCommand, - type AgentName, fileExists, loadFile, loadPackageJson, - saveFile + saveFile, + resolveCommand, + type AgentName } from '@sveltejs/sv-utils'; import { NonZeroExitError, exec } from 'tinyexec'; import { createLoadedAddon } from '../cli/add.ts'; diff --git a/packages/sv/src/core/package-manager.ts b/packages/sv/src/core/package-manager.ts index c0ed185c7..3edb1aaf9 100644 --- a/packages/sv/src/core/package-manager.ts +++ b/packages/sv/src/core/package-manager.ts @@ -3,9 +3,9 @@ import { AGENTS, type AgentName, COMMANDS, - color, constructCommand, detect, + color, isVersionUnsupportedBelow, parse } from '@sveltejs/sv-utils'; @@ -116,7 +116,9 @@ export async function addPnpmBuildDependencies( const content = found ? fs.readFileSync(found, 'utf-8') : ''; const { data, generateCode } = parse.yaml(content); - const onlyBuiltDependencies = data.get('onlyBuiltDependencies'); + const onlyBuiltDependencies = data.get('onlyBuiltDependencies') as + | { items?: Array<{ value: string } | string> } + | undefined; const items: Array<{ value: string } | string> = onlyBuiltDependencies?.items ?? []; for (const item of allowedPackages) { diff --git a/tsdown.config.ts b/tsdown.config.ts index 7de467cb0..ce4017a73 100644 --- a/tsdown.config.ts +++ b/tsdown.config.ts @@ -124,8 +124,15 @@ export default defineConfig([ }, failOnWarn: true, deps: { - neverBundle: [/^svelte/, '@types/estree', 'estree'], - onlyBundle: ['dedent', 'package-manager-detector', 'smol-toml', 'yaml', 'zimmerframe'] + neverBundle: [ + /^svelte/, + '@types/estree', + 'estree', + 'yaml', + 'dedent', + 'package-manager-detector' + ], + onlyBundle: ['smol-toml', 'zimmerframe'] }, hooks: { 'build:done': () => hookApiSurfaceBuildDone()