prettier-plugin-sort 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -283,9 +283,10 @@ Top-level key order follows the field list maintained by [sort-package-json](htt
283
283
  Rules the plugin follows:
284
284
 
285
285
  - Top-level keys are reordered to the canonical sequence (`name` → `version` → ... → `dependencies`)
286
- - Top-level string-only arrays are sorted alphabetically, e.g. `keywords`, `files`
286
+ - `scripts` and `betterScripts` keys are sorted with pre/post lifecycle grouping and `:` namespace ordering
287
+ - `exports` keys are sorted: path subkeys first, conditions alphabetically with `default` moved to the end; nested export maps are recursively sorted
287
288
  - `dependencies`, `devDependencies`, `peerDependencies` and other dependency maps are always sorted alphabetically, even if `packageJsonOrder` is set to `false`, because `npm install` rewrites them in alphabetical order every time
288
- - `scripts`, `exports`, `imports` and other nested objects are not sorted recursively, because their key order carries runtime semantics
289
+ - String arrays are handled by field: `keywords`, `files`, `activationEvents` are deduplicated preserving original order; `bundledDependencies`, `bundleDependencies`, `extensionPack`, `extensionDependencies` are deduplicated then sorted; `workspaces` arrays are left untouched; all other string arrays are sorted alphabetically
289
290
  - Use `packageJsonOrderExcludeKeys` to opt specific top-level keys out of sorting entirely
290
291
 
291
292
  ## Options
@@ -300,7 +301,7 @@ Prettier plugin options are flat, so these options are prefixed with `importOrde
300
301
  | `importOrderTypeImports` | How to place `type` imports: `separate`, `inline-first`, `inline-last`, `mixed` | `"separate"` |
301
302
  | `importOrderMergeDuplicates` | Merge multiple `import` statements from the same source (except side-effect imports) | `true` |
302
303
  | `exportOrder` | Sort named specifiers inside `export { … }` alphabetically | `true` |
303
- | `packageJsonOrder` | Sort top-level keys and string arrays in `package.json` | `true` |
304
+ | `packageJsonOrder` | Sort top-level keys, scripts/exports subkeys, and string arrays in `package.json` | `true` |
304
305
  | `packageJsonOrderExcludeKeys` | Top-level `package.json` keys to leave untouched | `[]` |
305
306
 
306
307
  ## Example
package/README.zh.md CHANGED
@@ -286,9 +286,10 @@ export { type FC, useEffect, useState } from 'react';
286
286
  排序规则:
287
287
 
288
288
  - 顶层字段按常用顺序排列(`name` → `version` → ... → `dependencies`)
289
- - 顶层的纯字符串数组按字母序排列,如 `keywords`、`files`
289
+ - `scripts` `betterScripts` 的键名按 pre/post 生命周期包围和 `:` 命名空间分组排序
290
+ - `exports` 键按路径优先、条件字母序、`default` 置底排序,嵌套的 export 对象递归处理
290
291
  - `dependencies`、`devDependencies`、`peerDependencies` 等依赖表永远按字母序排列,即使 `packageJsonOrder` 设为 `false` 也不例外。因为 `npm install` 每次都会按照字母序写回
291
- - `scripts`、`exports`、`imports` 等嵌套对象不会递归排序,它们的键顺序有运行时语义
292
+ - 字符串数组按字段分类处理:`keywords`、`files`、`activationEvents` 只去重不排序,保留原始语义顺序;`bundledDependencies`、`bundleDependencies`、`extensionPack`、`extensionDependencies` 去重后按字母序排列;`workspaces` 数组不排序;其余字符串数组按字母序排列
292
293
  - 想让某些顶层字段完全跳过排序,可以在 `packageJsonOrderExcludeKeys` 里列出
293
294
 
294
295
  ## 配置项
@@ -303,7 +304,7 @@ Prettier 的插件选项是扁平的,所以这些配置都以 `importOrder`、
303
304
  | `importOrderTypeImports` | `type` import 的处理方式:`separate`、`inline-first`、`inline-last`、`mixed` | `"separate"` |
304
305
  | `importOrderMergeDuplicates` | 是否合并同来源的多条 import 语句(副作用导入除外) | `true` |
305
306
  | `exportOrder` | 是否按字母序排列 `export { … }` 花括号内的命名导出 | `true` |
306
- | `packageJsonOrder` | 是否排序 package.json 的顶层字段和字符串数组 | `true` |
307
+ | `packageJsonOrder` | 是否排序 package.json 的顶层字段、scripts/exports 子键和字符串数组 | `true` |
307
308
  | `packageJsonOrderExcludeKeys` | 不参与 package.json 排序的顶层字段 | `[]` |
308
309
 
309
310
  ## 示例
package/dist/index.d.ts CHANGED
@@ -1,28 +1,5 @@
1
- // Generated by dts-bundle-generator v9.5.1
2
-
3
- import { Plugin, SupportOptions } from 'prettier';
4
-
5
- /** import 分组,参考 eslint-plugin-import 的 import/order 规则。 */
6
- export type ImportGroup = "builtin" | "external" | "internal" | "parent" | "sibling" | "index";
7
- /** `import type` 内联风格,参考 @typescript-eslint/consistent-type-imports 的 fixStyle 选项。 */
8
- export type TypeImportsStyle = "separate" | "inline-first" | "inline-last" | "mixed";
9
- /** 插件排序配置。 */
10
- export interface SortOptions {
11
- importOrder?: boolean;
12
- importOrderGroups?: ImportGroup[];
13
- importOrderSeparation?: boolean;
14
- importOrderTypeImports?: TypeImportsStyle;
15
- importOrderMergeDuplicates?: boolean;
16
- exportOrder?: boolean;
17
- packageJsonOrder?: boolean;
18
- packageJsonOrderExcludeKeys?: string[];
19
- }
20
- /** 向 Prettier 注册的选项。使用功能名词前缀命名,因为 Prettier API 不支持嵌套选项对象。 */
21
- export declare const options: SupportOptions;
1
+ import { type Plugin } from 'prettier';
22
2
  declare const plugin: Plugin;
23
-
24
- export {
25
- plugin as default,
26
- };
27
-
28
- export {};
3
+ export default plugin;
4
+ export { options } from './options';
5
+ export type { ImportGroup, SortOptions, TypeImportsStyle } from './options';
package/dist/index.js CHANGED
@@ -172,6 +172,7 @@ function stripTypePrefix(member) {
172
172
  // src/sort-imports.ts
173
173
  import { builtinModules } from "node:module";
174
174
  var NODE_BUILTINS = new Set(builtinModules);
175
+ var INDEX_PATTERN = /^\.\/index(\.[a-z]+)?$/;
175
176
  function detectGroup(source) {
176
177
  if (source === "bun" || source.startsWith("bun:") || source.startsWith("node:")) {
177
178
  return "builtin";
@@ -181,7 +182,7 @@ function detectGroup(source) {
181
182
  if (head && NODE_BUILTINS.has(head)) {
182
183
  return "builtin";
183
184
  }
184
- if (source === "." || source === "./" || /^\.\/index(\.[a-z]+)?$/.test(source)) {
185
+ if (source === "." || source === "./" || INDEX_PATTERN.test(source)) {
185
186
  return "index";
186
187
  }
187
188
  if (source.startsWith("../") || source === "..") {
@@ -195,7 +196,7 @@ function detectGroup(source) {
195
196
  }
196
197
  return "external";
197
198
  }
198
- var TYPE_PREFIX = /^type\s+(.+)$/s;
199
+ var TYPE_PREFIX = /^type\s+(.+)$/;
199
200
  function splitMembers(inner) {
200
201
  return splitTopLevel(inner, ",").map((part) => {
201
202
  const match = TYPE_PREFIX.exec(part);
@@ -279,9 +280,6 @@ function extractImportBlock(text) {
279
280
  const leadingLines = [];
280
281
  for (let i = commentLines.length - 1;i >= 0; i--) {
281
282
  const line = commentLines[i];
282
- if (line === undefined) {
283
- continue;
284
- }
285
283
  if (line.trim() === "") {
286
284
  break;
287
285
  }
@@ -377,9 +375,9 @@ function applyTypeImports(importDecl, style) {
377
375
  }
378
376
  const typeMembers2 = importDecl.members.filter((member) => member.isType);
379
377
  const valueMembers2 = importDecl.members.filter((member) => !member.isType);
380
- const out = [];
378
+ const output = [];
381
379
  if (typeMembers2.length > 0) {
382
- out.push({
380
+ output.push({
383
381
  source: importDecl.source,
384
382
  typeClause: true,
385
383
  sideEffect: false,
@@ -392,13 +390,13 @@ function applyTypeImports(importDecl, style) {
392
390
  }
393
391
  const hasValueBody = valueMembers2.length > 0 || importDecl.defaultSpec !== null || importDecl.namespaceSpec !== null;
394
392
  if (hasValueBody) {
395
- out.push({
393
+ output.push({
396
394
  ...importDecl,
397
395
  members: valueMembers2.length > 0 ? sortMembersAlpha(valueMembers2) : null,
398
396
  leadingComments: typeMembers2.length > 0 ? "" : importDecl.leadingComments
399
397
  });
400
398
  }
401
- return out.length > 0 ? out : [importDecl];
399
+ return output.length > 0 ? output : [importDecl];
402
400
  }
403
401
  const inlineBase = importDecl.typeClause ? {
404
402
  ...importDecl,
@@ -423,8 +421,8 @@ function sortSegment(imports, options2, groupIndex, fallback) {
423
421
  return [];
424
422
  }
425
423
  const style = options2.importOrderTypeImports;
426
- const deduped = options2.importOrderMergeDuplicates ? mergeImportsFromSameSource(imports) : imports;
427
- const rewritten = deduped.flatMap((importDecl) => applyTypeImports(importDecl, style));
424
+ const deduplicated = options2.importOrderMergeDuplicates ? mergeImportsFromSameSource(imports) : imports;
425
+ const rewritten = deduplicated.flatMap((importDecl) => applyTypeImports(importDecl, style));
428
426
  const decorated = rewritten.map((importDecl, index) => ({
429
427
  importDecl,
430
428
  group: detectGroup(importDecl.source),
@@ -507,9 +505,10 @@ function sortImports(text, rawOptions) {
507
505
  const replacement = allLines.join(`
508
506
  `);
509
507
  const trailing = text.slice(block.end);
510
- const suffix = trailing.trim() ? `
508
+ const nonBlankIndex = trailing.search(/\S/);
509
+ const suffix = nonBlankIndex >= 0 ? `
511
510
 
512
- ` + trailing.trimStart() : trailing;
511
+ ` + trailing.slice(nonBlankIndex) : trailing;
513
512
  return text.slice(0, block.start) + replacement + suffix;
514
513
  }
515
514
 
@@ -634,8 +633,6 @@ var DEPENDENCY_FIELDS = [
634
633
  "devDependencies",
635
634
  "peerDependencies",
636
635
  "optionalDependencies",
637
- "bundledDependencies",
638
- "bundleDependencies",
639
636
  "resolutions",
640
637
  "overrides"
641
638
  ];
@@ -647,8 +644,8 @@ function isPlainObject(value) {
647
644
  function isStringArray(value) {
648
645
  return Array.isArray(value) && value.every((item) => typeof item === "string");
649
646
  }
650
- function sortObjectKeysByOrder(record, order) {
651
- const orderIndex = new Map(order.map((key, index) => [key, index]));
647
+ var TOP_LEVEL_ORDER_INDEX = new Map(PACKAGE_JSON_TOP_LEVEL_ORDER.map((key, index) => [key, index]));
648
+ function sortObjectKeysByOrder(record, orderIndex) {
652
649
  const known = [];
653
650
  const rest = [];
654
651
  for (const entry of Object.entries(record)) {
@@ -672,6 +669,9 @@ function sortObjectKeysAlpha(value) {
672
669
  function sortStringArrayAlpha(value) {
673
670
  return [...value].sort((a, b) => a.localeCompare(b, "en"));
674
671
  }
672
+ function uniqueStringArray(value) {
673
+ return [...new Set(value)];
674
+ }
675
675
  function isPackageJson(filepath) {
676
676
  if (!filepath) {
677
677
  return false;
@@ -682,6 +682,116 @@ function detectIndent(source) {
682
682
  const match = /\n([ \t]+)\S/.exec(source);
683
683
  return match ? match[1] ?? " " : " ";
684
684
  }
685
+ var DEFAULT_NPM_SCRIPTS = new Set([
686
+ "install",
687
+ "pack",
688
+ "prepare",
689
+ "publish",
690
+ "restart",
691
+ "shrinkwrap",
692
+ "start",
693
+ "stop",
694
+ "test",
695
+ "uninstall",
696
+ "version"
697
+ ]);
698
+ var RUN_S_PATTERN = /(?<=^|[\s&;<>|(])(?:run-s|npm-run-all2? .*(?:--sequential|--serial|-s))(?=$|[\s&;<>|)])/;
699
+ function hasSequentialScript(packageObject) {
700
+ const devDependencies = packageObject["devDependencies"];
701
+ if (!isPlainObject(devDependencies) || !Object.hasOwn(devDependencies, "npm-run-all") && !Object.hasOwn(devDependencies, "npm-run-all2")) {
702
+ return false;
703
+ }
704
+ const scriptCommands = ["scripts", "betterScripts"].flatMap((field) => {
705
+ const scriptsObject = packageObject[field];
706
+ return isPlainObject(scriptsObject) ? Object.values(scriptsObject) : [];
707
+ });
708
+ return scriptCommands.some((script) => typeof script === "string" && script.includes("*") && RUN_S_PATTERN.test(script));
709
+ }
710
+ function sortScriptNames(keys, prefix = "") {
711
+ const groupMap = new Map;
712
+ for (const key of keys) {
713
+ const rest = prefix ? key.slice(prefix.length + 1) : key;
714
+ const colonIndex = rest.indexOf(":");
715
+ if (colonIndex > 0) {
716
+ const base = key.slice(0, (prefix ? prefix.length + 1 : 0) + colonIndex);
717
+ let group = groupMap.get(base);
718
+ if (!group) {
719
+ group = [];
720
+ groupMap.set(base, group);
721
+ }
722
+ group.push(key);
723
+ } else {
724
+ let group = groupMap.get(key);
725
+ if (!group) {
726
+ group = [];
727
+ groupMap.set(key, group);
728
+ }
729
+ group.push(key);
730
+ }
731
+ }
732
+ return [...groupMap.keys()].sort((a, b) => a.localeCompare(b, "en")).flatMap((groupKey) => {
733
+ const children = groupMap.get(groupKey);
734
+ if (children.length > 1 && children.some((key) => key !== groupKey && key.startsWith(groupKey + ":"))) {
735
+ const direct = children.filter((key) => key === groupKey || !key.startsWith(groupKey + ":")).sort((a, b) => a.localeCompare(b, "en"));
736
+ const nested = children.filter((key) => key.startsWith(groupKey + ":"));
737
+ return [...direct, ...sortScriptNames(nested, groupKey)];
738
+ }
739
+ return children.sort((a, b) => a.localeCompare(b, "en"));
740
+ });
741
+ }
742
+ function sortScripts(scripts, packageObject) {
743
+ const names = Object.keys(scripts);
744
+ const prefixable = new Set;
745
+ const normalized = names.map((name) => {
746
+ const base = name.replace(/^(?:pre|post)/, "");
747
+ if (DEFAULT_NPM_SCRIPTS.has(base) || names.includes(base)) {
748
+ prefixable.add(base);
749
+ return base;
750
+ }
751
+ return name;
752
+ });
753
+ let sortedNames;
754
+ if (hasSequentialScript(packageObject)) {
755
+ sortedNames = [...new Set(normalized)];
756
+ } else {
757
+ sortedNames = sortScriptNames(normalized);
758
+ }
759
+ const orderedNames = sortedNames.flatMap((key) => prefixable.has(key) ? [`pre${key}`, key, `post${key}`] : [key]);
760
+ return Object.fromEntries(orderedNames.filter((name) => Object.hasOwn(scripts, name)).map((name) => [name, scripts[name]]));
761
+ }
762
+ function sortExportsField(exports) {
763
+ const keys = Object.keys(exports);
764
+ const paths = keys.filter((key) => key.startsWith(".")).sort();
765
+ const conditions = keys.filter((key) => !key.startsWith(".")).sort();
766
+ const defaultIndex = conditions.indexOf("default");
767
+ if (defaultIndex >= 0) {
768
+ conditions.splice(defaultIndex, 1);
769
+ conditions.push("default");
770
+ }
771
+ const orderedKeys = [...paths, ...conditions];
772
+ return Object.fromEntries(orderedKeys.map((key) => {
773
+ const value = exports[key];
774
+ return [
775
+ key,
776
+ isPlainObject(value) ? sortExportsField(value) : value
777
+ ];
778
+ }));
779
+ }
780
+ var UNIQUE_ONLY_FIELDS = new Set(["keywords", "files", "activationEvents"]);
781
+ var UNIQUE_AND_SORT_FIELDS = new Set([
782
+ "bundledDependencies",
783
+ "bundleDependencies",
784
+ "extensionPack",
785
+ "extensionDependencies"
786
+ ]);
787
+ var NO_SORT_ARRAY_FIELDS = new Set(["workspaces"]);
788
+ function detectNewline(source) {
789
+ const crlfIndex = source.indexOf(`\r
790
+ `);
791
+ return crlfIndex >= 0 ? `\r
792
+ ` : `
793
+ `;
794
+ }
685
795
  function sortPackageJson(text, rawOptions) {
686
796
  if (!isPackageJson(rawOptions.filepath)) {
687
797
  return text;
@@ -705,21 +815,51 @@ function sortPackageJson(text, rawOptions) {
705
815
  }
706
816
  }
707
817
  if (options2.packageJsonOrder) {
708
- result = sortObjectKeysByOrder(result, PACKAGE_JSON_TOP_LEVEL_ORDER);
818
+ result = sortObjectKeysByOrder(result, TOP_LEVEL_ORDER_INDEX);
819
+ for (const field of ["scripts", "betterScripts"]) {
820
+ const scriptsValue = result[field];
821
+ if (scriptsValue !== undefined && isPlainObject(scriptsValue) && !exclude.has(field)) {
822
+ result[field] = sortScripts(scriptsValue, result);
823
+ }
824
+ }
825
+ const exportsValue = result["exports"];
826
+ if (exportsValue !== undefined && isPlainObject(exportsValue) && !exclude.has("exports")) {
827
+ result["exports"] = sortExportsField(exportsValue);
828
+ }
709
829
  for (const [key, value] of Object.entries(result)) {
710
830
  if (exclude.has(key)) {
711
831
  continue;
712
832
  }
713
- if (isStringArray(value)) {
714
- result[key] = sortStringArrayAlpha(value);
833
+ if (!isStringArray(value)) {
834
+ continue;
835
+ }
836
+ if (NO_SORT_ARRAY_FIELDS.has(key)) {
837
+ continue;
838
+ }
839
+ if (UNIQUE_ONLY_FIELDS.has(key)) {
840
+ result[key] = uniqueStringArray(value);
841
+ continue;
842
+ }
843
+ if (UNIQUE_AND_SORT_FIELDS.has(key)) {
844
+ result[key] = sortStringArrayAlpha(uniqueStringArray(value));
845
+ continue;
715
846
  }
847
+ result[key] = sortStringArrayAlpha(value);
716
848
  }
717
849
  }
718
850
  const indent = detectIndent(text);
851
+ const newline = detectNewline(text);
719
852
  const output = JSON.stringify(result, null, indent);
720
- return text.endsWith(`
721
- `) ? output + `
722
- ` : output;
853
+ if (text.endsWith(newline)) {
854
+ return newline === `\r
855
+ ` ? output.replace(/\n/g, `\r
856
+ `) + `\r
857
+ ` : output + `
858
+ `;
859
+ }
860
+ return newline === `\r
861
+ ` ? output.replace(/\n/g, `\r
862
+ `) : output;
723
863
  }
724
864
 
725
865
  // src/index.ts
@@ -0,0 +1,26 @@
1
+ import { type ParserOptions, type SupportOptions } from 'prettier';
2
+ /** import 分组,参考 eslint-plugin-import 的 import/order 规则。 */
3
+ export type ImportGroup = 'builtin' | 'external' | 'internal' | 'parent' | 'sibling' | 'index';
4
+ /** `import type` 内联风格,参考 @typescript-eslint/consistent-type-imports 的 fixStyle 选项。 */
5
+ export type TypeImportsStyle = 'separate' | 'inline-first' | 'inline-last' | 'mixed';
6
+ /** 插件排序配置。 */
7
+ export interface SortOptions {
8
+ importOrder?: boolean;
9
+ importOrderGroups?: ImportGroup[];
10
+ importOrderSeparation?: boolean;
11
+ importOrderTypeImports?: TypeImportsStyle;
12
+ importOrderMergeDuplicates?: boolean;
13
+ exportOrder?: boolean;
14
+ packageJsonOrder?: boolean;
15
+ packageJsonOrderExcludeKeys?: string[];
16
+ }
17
+ /** 默认排序配置。 */
18
+ export declare const DEFAULT_SORT_OPTIONS: Required<SortOptions>;
19
+ type RawSortOptions = ParserOptions & Partial<SortOptions>;
20
+ /**
21
+ * 从 Prettier 选项中提取插件配置,缺失或非法的参数会回退为默认值。
22
+ */
23
+ export declare function resolveSortOptions(rawOptions: RawSortOptions): Required<SortOptions>;
24
+ /** 注册到 Prettier 的选项定义。使用功能名词前缀命名,因为 Prettier API 不支持嵌套的选项对象。 */
25
+ export declare const options: SupportOptions;
26
+ export {};
@@ -0,0 +1,10 @@
1
+ /**
2
+ * `package.json` 顶层字段的排列顺序。
3
+ * 参考社区标准 sort-package-json 的字段列表:https://github.com/keithamus/sort-package-json/blob/main/index.js#L433-L564
4
+ */
5
+ export declare const PACKAGE_JSON_TOP_LEVEL_ORDER: readonly string[];
6
+ /**
7
+ * 值为 `{ name: range }` 映射的依赖表字段。
8
+ * 始终按字母序排列,不受用户选项影响——npm install 每次都会按字母序重写。
9
+ */
10
+ export declare const DEPENDENCY_FIELDS: readonly string[];
@@ -0,0 +1,12 @@
1
+ import { type ParserOptions } from 'prettier';
2
+ /**
3
+ * 按字母序排列 `export { … }` 花括号内的命名导出。
4
+ * 不改变语句位置,不跨语句合并,只针对单条 export 语句的花括号内部。
5
+ *
6
+ * 覆盖的语法形式:
7
+ * export { a, b };
8
+ * export { a, b } from 'mod';
9
+ * export type { A, B };
10
+ * export type { A, B } from 'mod';
11
+ */
12
+ export declare function sortExports(text: string, rawOptions: ParserOptions): string;
@@ -0,0 +1,2 @@
1
+ import { type ParserOptions } from 'prettier';
2
+ export declare function sortImports(text: string, rawOptions: ParserOptions): string;
@@ -0,0 +1,2 @@
1
+ import { type ParserOptions } from 'prettier';
2
+ export declare function sortPackageJson(text: string, rawOptions: ParserOptions): string;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * 按 `separator` 分割字符串,忽略嵌套在 `{}` / `()` / `[]` 中的分隔符。
3
+ * 仅在顶层(深度为 0 的位置)分隔。返回结果会 trim 并剔除空段。
4
+ *
5
+ * 不使用 `String.prototype.split` 直接分隔,因为 import / export 的花括号内可能
6
+ * 出现形如 `{ a, b as c }`,其中嵌套结构内的逗号不应被当作分隔符。
7
+ */
8
+ export declare function splitTopLevel(input: string, separator: string): string[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prettier-plugin-sort",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "An all-in-one Prettier plugin to sort imports, package.json keys, and more.",
5
5
  "keywords": [
6
6
  "imports",
@@ -35,24 +35,25 @@
35
35
  "dist"
36
36
  ],
37
37
  "scripts": {
38
- "build": "bun run scripts/build/index.ts",
39
- "format": "prettier \"{src,scripts}/**/*.ts\" \"*.ts\" --write",
40
- "lint": "eslint \"{src,scripts}/**/*.ts\" \"*.ts\"",
38
+ "build": "bun run scripts/build/",
39
+ "format": "prettier **/*.ts --write",
40
+ "lint": "eslint **/*.ts",
41
41
  "prepare": "husky",
42
- "test": "bun test"
42
+ "test": "bun test scripts/test/",
43
+ "typecheck": "tsc --noEmit"
43
44
  },
44
45
  "devDependencies": {
45
- "@commitlint/cli": "^20.5.0",
46
- "@commitlint/config-conventional": "^20.5.0",
47
- "@commitlint/types": "^20.5.0",
46
+ "@commitlint/cli": "^21.0.1",
47
+ "@commitlint/config-conventional": "^21.0.1",
48
+ "@commitlint/types": "^21.0.1",
48
49
  "@eslint/js": "^10.0.1",
49
- "@types/bun": "^1.3.13",
50
- "bun-plugin-dts": "^0.4.0",
51
- "eslint": "^10.2.1",
50
+ "@types/bun": "^1.3.14",
51
+ "annal": "^0.0.2",
52
+ "eslint": "^10.4.0",
52
53
  "husky": "^9.1.7",
53
54
  "prettier": "^3.8.3",
54
55
  "typescript": "^6.0.3",
55
- "typescript-eslint": "^8.59.0"
56
+ "typescript-eslint": "^8.59.3"
56
57
  },
57
58
  "peerDependencies": {
58
59
  "prettier": ">=3.0.0"