Skip to content

Commit

Permalink
feat: support specifying the tsconfig in svelte-package (#11698)
Browse files Browse the repository at this point in the history
closes #9373

Adds the option tsconfig to svelte-package, allowing to specify which tsconfig / jsconfig to use during the packaging.
  • Loading branch information
quentinderoubaix authored Mar 6, 2024
1 parent 41bb2c0 commit b3c0105
Show file tree
Hide file tree
Showing 14 changed files with 99 additions and 23 deletions.
5 changes: 5 additions & 0 deletions .changeset/clean-dots-switch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@sveltejs/package": minor
---

feat: add option to specify the tsconfig/jsconfig
1 change: 1 addition & 0 deletions documentation/docs/30-advanced/70-packaging.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ You should think carefully about whether or not the changes you make to your pac
- `-i`/`--input` — the input directory which contains all the files of the package. Defaults to `src/lib`
- `-o`/`--o` — the output directory where the processed files are written to. Your `package.json`'s `exports` should point to files inside there, and the `files` array should include that folder. Defaults to `dist`
- `-t`/`--types` — whether or not to create type definitions (`d.ts` files). We strongly recommend doing this as it fosters ecosystem library quality. Defaults to `true`
- `--tsconfig` - the path to a tsconfig or jsconfig. When not provided, searches for the next upper tsconfig/jsconfig in the workspace path.

## Publishing

Expand Down
5 changes: 5 additions & 0 deletions packages/package/src/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ prog
.option('-o, --output', 'Output directory', 'dist')
.option('-t, --types', 'Emit type declarations', true)
.option('-w, --watch', 'Rerun when files change', false)
.option(
'--tsconfig',
'A path to a tsconfig or jsconfig file. When not provided, searches for the next upper tsconfig/jsconfig in the workspace path.'
)
.action(async (args) => {
try {
const config = await load_config();
Expand All @@ -42,6 +46,7 @@ prog
cwd: process.cwd(),
input: args.input ?? config.kit?.files?.lib ?? 'src/lib',
output: args.output,
tsconfig: args.tsconfig,
types: args.types,
config
};
Expand Down
25 changes: 18 additions & 7 deletions packages/package/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export async function build(options) {
* @param {(name: string, code: string) => void} analyse_code
*/
async function do_build(options, analyse_code) {
const { input, output, temp, extensions, alias } = normalize_options(options);
const { input, output, temp, extensions, alias, tsconfig } = normalize_options(options);

if (!fs.existsSync(input)) {
throw new Error(`${path.relative('.', input)} does not exist`);
Expand All @@ -38,7 +38,7 @@ async function do_build(options, analyse_code) {
}

for (const file of files) {
await process_file(input, temp, file, options.config.preprocess, alias, analyse_code);
await process_file(input, temp, file, options.config.preprocess, alias, tsconfig, analyse_code);
}

rimraf(output);
Expand All @@ -62,7 +62,7 @@ export async function watch(options) {

validate();

const { input, output, extensions, alias } = normalize_options(options);
const { input, output, extensions, alias, tsconfig } = normalize_options(options);

const message = `\nWatching ${path.relative(options.cwd, input)} for changes...\n`;

Expand Down Expand Up @@ -119,7 +119,15 @@ export async function watch(options) {
if (type === 'add' || type === 'change') {
console.log(`Processing ${file.name}`);
try {
await process_file(input, output, file, options.config.preprocess, alias, analyse_code);
await process_file(
input,
output,
file,
options.config.preprocess,
alias,
tsconfig,
analyse_code
);
} catch (e) {
errored = true;
console.error(e);
Expand Down Expand Up @@ -170,6 +178,7 @@ function normalize_options(options) {
'__package__'
);
const extensions = options.config.extensions ?? ['.svelte'];
const tsconfig = options.tsconfig ? path.resolve(options.cwd, options.tsconfig) : undefined;

const alias = {
$lib: path.resolve(options.cwd, options.config.kit?.files?.lib ?? 'src/lib'),
Expand All @@ -181,7 +190,8 @@ function normalize_options(options) {
output,
temp,
extensions,
alias
alias,
tsconfig
};
}

Expand All @@ -191,9 +201,10 @@ function normalize_options(options) {
* @param {import('./types.js').File} file
* @param {import('svelte/types/compiler/preprocess').PreprocessorGroup | undefined} preprocessor
* @param {Record<string, string>} aliases
* @param {string | undefined} tsconfig
* @param {(name: string, code: string) => void} analyse_code
*/
async function process_file(input, output, file, preprocessor, aliases, analyse_code) {
async function process_file(input, output, file, preprocessor, aliases, tsconfig, analyse_code) {
const filename = path.join(input, file.name);
const dest = path.join(output, file.dest);

Expand All @@ -208,7 +219,7 @@ async function process_file(input, output, file, preprocessor, aliases, analyse_
}

if (file.name.endsWith('.ts') && !file.name.endsWith('.d.ts')) {
contents = await transpile_ts(filename, contents);
contents = await transpile_ts(tsconfig, filename, contents);
}

contents = resolve_aliases(input, file.name, contents, aliases);
Expand Down
1 change: 1 addition & 0 deletions packages/package/src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export interface Options {
input: string;
output: string;
types: boolean;
tsconfig?: string;
config: {
extensions?: string[];
kit?: {
Expand Down
42 changes: 26 additions & 16 deletions packages/package/src/typescript.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,13 @@ export async function emit_dts(input, output, cwd, alias, files) {
/**
* TS -> JS
*
* @param {string | undefined} tsconfig
* @param {string} filename
* @param {string} source
*/
export async function transpile_ts(filename, source) {
export async function transpile_ts(tsconfig, filename, source) {
const ts = await try_load_ts();
const options = load_tsconfig(filename, ts);
const options = load_tsconfig(tsconfig, filename, ts);
// transpileModule treats NodeNext as CommonJS because it doesn't read the package.json. Therefore we need to override it.
// Also see https://github.com/microsoft/TypeScript/issues/53022 (the filename workaround doesn't work).
return ts.transpileModule(source, {
Expand All @@ -91,28 +92,37 @@ async function try_load_ts() {
}

/**
* @param {string | undefined} tsconfig
* @param {string} filename
* @param {import('typescript')} ts
*/
function load_tsconfig(filename, ts) {
function load_tsconfig(tsconfig, filename, ts) {
let config_filename;

// ts.findConfigFile is broken (it will favour a distant tsconfig
// over a near jsconfig, and then only when you call it twice)
// so we implement it ourselves
let dir = filename;
while (dir !== (dir = path.dirname(dir))) {
const tsconfig = path.join(dir, 'tsconfig.json');
const jsconfig = path.join(dir, 'jsconfig.json');

if (tsconfig) {
if (fs.existsSync(tsconfig)) {
config_filename = tsconfig;
break;
} else {
throw new Error('Failed to locate provided tsconfig or jsconfig');
}

if (fs.existsSync(jsconfig)) {
config_filename = jsconfig;
break;
} else {
// ts.findConfigFile is broken (it will favour a distant tsconfig
// over a near jsconfig, and then only when you call it twice)
// so we implement it ourselves
let dir = filename;
while (dir !== (dir = path.dirname(dir))) {
const tsconfig = path.join(dir, 'tsconfig.json');
const jsconfig = path.join(dir, 'jsconfig.json');

if (fs.existsSync(tsconfig)) {
config_filename = tsconfig;
break;
}

if (fs.existsSync(jsconfig)) {
config_filename = jsconfig;
break;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export declare const x = true;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const x = true;
16 changes: 16 additions & 0 deletions packages/package/test/fixtures/tsconfig-specified/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "typescript",
"private": true,
"version": "1.0.0",
"description": "typescript package using esnext",
"type": "module",
"peerDependencies": {
"svelte": "^4.0.0"
},
"exports": {
".": {
"types": "./dist/index.d.ts",
"svelte": "./dist/index.js"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// a comment to delete
export const x = true;
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import preprocess from 'svelte-preprocess';

export default {
preprocess: preprocess({
preserve: ['ld+json']
})
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"removeComments": true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext"
}
}
4 changes: 4 additions & 0 deletions packages/package/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ test('SvelteKit interop', async () => {
await test_make_package('svelte-kit');
});

test('create package with tsconfig specified', async () => {
await test_make_package('tsconfig-specified', { tsconfig: 'tsconfig.build.json' });
});

// chokidar doesn't fire events in github actions :shrug:
if (!process.env.CI) {
test('watches for changes', async () => {
Expand Down

0 comments on commit b3c0105

Please sign in to comment.