Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/hungry-numbers-stay.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'sv': patch
---

feat(eslint): with `[email protected]` ESLint extension, we don't need to set `eslint.validate` anymore
22 changes: 14 additions & 8 deletions packages/sv/lib/addons/drizzle/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ import {
object,
variables
} from '../../core/tooling/js/index.ts';
import { defineAddon, defineAddonOptions, dedent, type OptionValues } from '../../core/index.ts';
import {
defineAddon,
defineAddonOptions,
dedent,
type OptionValues,
json
} from '../../core/index.ts';
import { parseJson, parseScript } from '../../core/tooling/parsers.ts';
import { resolveCommand } from 'package-manager-detector/commands';
import { getNodeTypesVersion } from '../common.ts';
Expand Down Expand Up @@ -186,13 +192,13 @@ export default defineAddon({

sv.file(files.package, (content) => {
const { data, generateCode } = parseJson(content);
data.scripts ??= {};
const scripts: Record<string, string> = data.scripts;
if (options.docker) scripts['db:start'] ??= 'docker compose up';
scripts['db:push'] ??= 'drizzle-kit push';
scripts['db:generate'] ??= 'drizzle-kit generate';
scripts['db:migrate'] ??= 'drizzle-kit migrate';
scripts['db:studio'] ??= 'drizzle-kit studio';

if (options.docker) json.packageScriptsUpsert(data, 'db:start', 'docker compose up');
json.packageScriptsUpsert(data, 'db:push', 'drizzle-kit push');
json.packageScriptsUpsert(data, 'db:generate', 'drizzle-kit generate');
json.packageScriptsUpsert(data, 'db:migrate', 'drizzle-kit migrate');
json.packageScriptsUpsert(data, 'db:studio', 'drizzle-kit studio');

return generateCode();
});

Expand Down
17 changes: 2 additions & 15 deletions packages/sv/lib/addons/eslint/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { defineAddon, log } from '../../core/index.ts';
import { defineAddon, log, json } from '../../core/index.ts';
import {
array,
common,
Expand Down Expand Up @@ -34,22 +34,9 @@ export default defineAddon({

sv.file(files.package, (content) => {
const { data, generateCode } = parseJson(content);
data.scripts ??= {};
const scripts: Record<string, string> = data.scripts;
const LINT_CMD = 'eslint .';
scripts['lint'] ??= LINT_CMD;
if (!scripts['lint'].includes(LINT_CMD)) scripts['lint'] += ` && ${LINT_CMD}`;
return generateCode();
});

sv.file(files.vscodeSettings, (content) => {
if (!content) return content;
json.packageScriptsUpsert(data, 'lint', 'eslint .');

const { data, generateCode } = parseJson(content);
const validate: string[] | undefined = data['eslint.validate'];
if (validate && !validate.includes('svelte')) {
validate.push('svelte');
}
return generateCode();
});

Expand Down
13 changes: 5 additions & 8 deletions packages/sv/lib/addons/playwright/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { dedent, defineAddon, log } from '../../core/index.ts';
import { dedent, defineAddon, json, log } from '../../core/index.ts';
import { common, exports, imports, object } from '../../core/tooling/js/index.ts';
import { parseJson, parseScript } from '../../core/tooling/parsers.ts';

Expand All @@ -12,13 +12,10 @@ export default defineAddon({

sv.file(files.package, (content) => {
const { data, generateCode } = parseJson(content);
data.scripts ??= {};
const scripts: Record<string, string> = data.scripts;
const TEST_CMD = 'playwright test';
const RUN_TEST = 'npm run test:e2e';
scripts['test:e2e'] ??= TEST_CMD;
scripts['test'] ??= RUN_TEST;
if (!scripts['test'].includes(RUN_TEST)) scripts['test'] += ` && ${RUN_TEST}`;

json.packageScriptsUpsert(data, 'test:e2e', 'playwright test');
json.packageScriptsUpsert(data, 'test', 'npm run test:e2e');

return generateCode();
});

Expand Down
26 changes: 7 additions & 19 deletions packages/sv/lib/addons/prettier/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { dedent, defineAddon, log, colors } from '../../core/index.ts';
import { dedent, defineAddon, log, colors, json } from '../../core/index.ts';
import { addEslintConfigPrettier } from '../common.ts';
import { parseJson } from '../../core/tooling/parsers.ts';

Expand Down Expand Up @@ -47,15 +47,10 @@ export default defineAddon({
data.printWidth = 100;
}

data.plugins ??= [];
const plugins: string[] = data.plugins;
{
const PLUGIN_NAME = 'prettier-plugin-svelte';
if (!plugins.includes(PLUGIN_NAME)) plugins.push(PLUGIN_NAME);
}
json.arrayUpsert(data, 'plugins', 'prettier-plugin-svelte');

if (tailwindcssInstalled) {
const PLUGIN_NAME = 'prettier-plugin-tailwindcss';
if (!plugins.includes(PLUGIN_NAME)) plugins.push(PLUGIN_NAME);
json.arrayUpsert(data, 'plugins', 'prettier-plugin-tailwindcss');
data.tailwindStylesheet ??= files.getRelative({ to: files.stylesheet });
}

Expand All @@ -75,17 +70,10 @@ export default defineAddon({
sv.file(files.package, (content) => {
const { data, generateCode } = parseJson(content);

data.scripts ??= {};
const scripts: Record<string, string> = data.scripts;
const CHECK_CMD = 'prettier --check .';
scripts['format'] ??= 'prettier --write .';
const cmd = `prettier --check .${eslintInstalled ? ` && eslint .` : ''}`;
json.packageScriptsUpsert(data, 'lint', cmd);
json.packageScriptsUpsert(data, 'format', 'prettier --write .');

if (eslintInstalled) {
scripts['lint'] ??= `${CHECK_CMD} && eslint .`;
if (!scripts['lint'].includes(CHECK_CMD)) scripts['lint'] += ` && ${CHECK_CMD}`;
} else {
scripts['lint'] ??= CHECK_CMD;
}
return generateCode();
});

Expand Down
7 changes: 2 additions & 5 deletions packages/sv/lib/addons/tailwindcss/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { defineAddon, defineAddonOptions } from '../../core/index.ts';
import { defineAddon, defineAddonOptions, json } from '../../core/index.ts';
import { imports, vite } from '../../core/tooling/js/index.ts';
import * as svelte from '../../core/tooling/svelte/index.ts';
import * as css from '../../core/tooling/css/index.ts';
Expand Down Expand Up @@ -126,10 +126,7 @@ export default defineAddon({
sv.file(files.prettierrc, (content) => {
const { data, generateCode } = parseJson(content);

data.plugins ??= [];
const plugins: string[] = data.plugins;
const PLUGIN_NAME = 'prettier-plugin-tailwindcss';
if (!plugins.includes(PLUGIN_NAME)) plugins.push(PLUGIN_NAME);
json.arrayUpsert(data, 'plugins', 'prettier-plugin-tailwindcss');
data.tailwindStylesheet ??= files.getRelative({ to: files.stylesheet });

return generateCode();
Expand Down
13 changes: 5 additions & 8 deletions packages/sv/lib/addons/vitest-addon/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { dedent, defineAddon, defineAddonOptions } from '../../core/index.ts';
import { dedent, defineAddon, defineAddonOptions, json } from '../../core/index.ts';
import { array, imports, object, functions, vite } from '../../core/tooling/js/index.ts';
import { parseJson, parseScript } from '../../core/tooling/parsers.ts';

Expand Down Expand Up @@ -43,14 +43,11 @@ export default defineAddon({

sv.file(files.package, (content) => {
const { data, generateCode } = parseJson(content);
data.scripts ??= {};
const scripts: Record<string, string> = data.scripts;
const TEST_CMD = 'vitest';

json.packageScriptsUpsert(data, 'test:unit', 'vitest');
// we use `--run` so that vitest doesn't run in watch mode when running `npm run test`
const RUN_TEST = 'npm run test:unit -- --run';
scripts['test:unit'] ??= TEST_CMD;
scripts['test'] ??= RUN_TEST;
if (!scripts['test'].includes(RUN_TEST)) scripts['test'] += ` && ${RUN_TEST}`;
json.packageScriptsUpsert(data, 'test', 'npm run test:unit -- --run');

return generateCode();
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
"prepare": "svelte-kit sync || echo ''",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"format": "prettier --write .",
"lint": "prettier --check . && eslint .",
"format": "prettier --write .",
"test:unit": "vitest",
"test": "npm run test:unit -- --run && npm run test:e2e",
"test:e2e": "playwright test",
Expand Down
8 changes: 8 additions & 0 deletions packages/sv/lib/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ export type * from './addon/processors.ts';
export type * from './addon/options.ts';
export type * from './addon/config.ts';
export type * from './addon/workspace.ts';
import { arrayUpsert, packageScriptsUpsert } from './tooling/json.ts';
export const json: {
arrayUpsert: typeof arrayUpsert;
packageScriptsUpsert: typeof packageScriptsUpsert;
} = {
arrayUpsert,
packageScriptsUpsert
};

export { Walker } from './tooling/index.ts';
export * as js from './tooling/js/index.ts';
Expand Down
42 changes: 42 additions & 0 deletions packages/sv/lib/core/tests/json.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { describe, expect, it } from 'vitest';
import { arrayUpsert, packageScriptsUpsert } from '../tooling/json.ts';

describe('arrayUpsert', () => {
it('append', () => {
const data = { a: ['b'] };
arrayUpsert(data, 'a', 'c');
expect(data).toEqual({ a: ['b', 'c'] });
});

it('prepend', () => {
const data = { a: ['b'] };
arrayUpsert(data, 'a', 'c', { mode: 'prepend' });
expect(data).toEqual({ a: ['c', 'b'] });
});

it('create', () => {
const data = { a: ['b'] };
arrayUpsert(data, 'z', 'c');
expect(data).toEqual({ a: ['b'], z: ['c'] });
});

it('no change', () => {
const data = { a: ['b', 'c'] };
arrayUpsert(data, 'a', 'b');
expect(data).toEqual({ a: ['b', 'c'] });
});
});

describe('objectUpsert', () => {
it('create', () => {
const data = {};
packageScriptsUpsert(data, 'lint', 'cmd');
expect(data).toEqual({ scripts: { lint: 'cmd' } });
});

it('add', () => {
const data = { scripts: { lint: 'b' } };
packageScriptsUpsert(data, 'lint', 'cmd');
expect(data).toEqual({ scripts: { lint: 'b && cmd' } });
});
});
29 changes: 29 additions & 0 deletions packages/sv/lib/core/tooling/json.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
export function arrayUpsert(
data: any,
key: string,
value: any,
options?: {
/** default: `append` */
mode?: 'append' | 'prepend';
}
): void {
const array = data[key] ?? [];

if (array.includes(value)) return;

if (options?.mode === 'prepend') {
array.unshift(value);
} else {
array.push(value);
}
data[key] = array;
}

export function packageScriptsUpsert(data: any, key: string, value: any): void {
data.scripts ??= {};
const scripts: Record<string, string> = data.scripts;
scripts[key] ??= value;
if (!scripts[key].includes(value)) {
scripts[key] += ` && ${value}`;
}
}
Loading