apotheke 0.0.1 → 0.1.1
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/LICENSE +21 -0
- package/README.md +37 -209
- package/SKILL.md +249 -0
- package/dist/cli.js +96 -90
- package/dist/index.d.ts +6 -5
- package/dist/index.js +160 -147
- package/package.json +65 -46
package/dist/index.js
CHANGED
|
@@ -1,64 +1,74 @@
|
|
|
1
1
|
// index.ts
|
|
2
|
-
import path3 from "path";
|
|
3
2
|
import { existsSync as existsSync2 } from "fs";
|
|
3
|
+
import { createRequire } from "module";
|
|
4
|
+
import path3 from "path";
|
|
4
5
|
|
|
5
|
-
// src/
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
if (
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
let namespaceImport;
|
|
17
|
-
for (const s of node.specifiers) {
|
|
18
|
-
if (s.type === "ImportDefaultSpecifier") {
|
|
19
|
-
defaultImport = s.local.name;
|
|
20
|
-
} else if (s.type === "ImportNamespaceSpecifier") {
|
|
21
|
-
namespaceImport = s.local.name;
|
|
22
|
-
} else if (s.type === "ImportSpecifier") {
|
|
23
|
-
const imported = s.imported;
|
|
24
|
-
const name = imported.type === "Identifier" ? imported.name : imported.value;
|
|
25
|
-
const localName = s.local.name;
|
|
26
|
-
const kind = s.importKind === "type" ? "type" : "value";
|
|
27
|
-
const named = { name, kind };
|
|
28
|
-
if (localName !== name) named.alias = localName;
|
|
29
|
-
namedImports.push(named);
|
|
30
|
-
}
|
|
6
|
+
// src/config.ts
|
|
7
|
+
import { existsSync, readFileSync } from "fs";
|
|
8
|
+
import path from "path";
|
|
9
|
+
function mergeConfigs(parent, child) {
|
|
10
|
+
const mergedGroups = [...parent.groups];
|
|
11
|
+
for (const childGroup of child.groups ?? []) {
|
|
12
|
+
const existingIdx = mergedGroups.findIndex((g) => g.name === childGroup.name);
|
|
13
|
+
if (existingIdx >= 0) {
|
|
14
|
+
mergedGroups[existingIdx] = childGroup;
|
|
15
|
+
} else {
|
|
16
|
+
mergedGroups.push(childGroup);
|
|
31
17
|
}
|
|
32
|
-
const importKind = node.importKind === "type" ? "type" : "value";
|
|
33
|
-
const isSideEffect = node.specifiers.length === 0 && importKind === "value";
|
|
34
|
-
const importNode = {
|
|
35
|
-
specifier,
|
|
36
|
-
namedImports,
|
|
37
|
-
isSideEffect,
|
|
38
|
-
importKind,
|
|
39
|
-
start: node.start,
|
|
40
|
-
end: node.end
|
|
41
|
-
};
|
|
42
|
-
if (defaultImport) importNode.defaultImport = defaultImport;
|
|
43
|
-
if (namespaceImport) importNode.namespaceImport = namespaceImport;
|
|
44
|
-
const attached = findAttachedComment(source, node.start, comments);
|
|
45
|
-
if (attached) importNode.attachedComment = attached;
|
|
46
|
-
nodes.push(importNode);
|
|
47
18
|
}
|
|
48
|
-
return
|
|
19
|
+
return {
|
|
20
|
+
...parent,
|
|
21
|
+
...child,
|
|
22
|
+
groups: mergedGroups,
|
|
23
|
+
aliases: { ...parent.aliases ?? {}, ...child.aliases ?? {} }
|
|
24
|
+
};
|
|
49
25
|
}
|
|
50
|
-
function
|
|
51
|
-
const
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
26
|
+
async function loadConfig(configPath) {
|
|
27
|
+
const mod = await import(configPath);
|
|
28
|
+
const userConfig = mod.default ?? mod;
|
|
29
|
+
const configDir = path.dirname(configPath);
|
|
30
|
+
const config = { ...userConfig };
|
|
31
|
+
const tsconfig = loadTsConfig(configDir);
|
|
32
|
+
if (tsconfig) {
|
|
33
|
+
const opts = tsconfig.compilerOptions ?? {};
|
|
34
|
+
if (opts.baseUrl && !config.baseUrl) {
|
|
35
|
+
config.baseUrl = opts.baseUrl;
|
|
36
|
+
}
|
|
37
|
+
if (opts.paths) {
|
|
38
|
+
const aliases = { ...config.aliases ?? {} };
|
|
39
|
+
for (const [aliasPattern, targets] of Object.entries(
|
|
40
|
+
opts.paths
|
|
41
|
+
)) {
|
|
42
|
+
const alias = aliasPattern.replace(/\/\*$/, "");
|
|
43
|
+
const target = (targets[0] ?? "").replace(/\/\*$/, "");
|
|
44
|
+
if (!aliases[alias]) aliases[alias] = target;
|
|
45
|
+
}
|
|
46
|
+
config.aliases = aliases;
|
|
59
47
|
}
|
|
60
48
|
}
|
|
61
|
-
|
|
49
|
+
if (userConfig.extends) {
|
|
50
|
+
const parentPath = path.resolve(configDir, userConfig.extends);
|
|
51
|
+
if (!existsSync(parentPath)) {
|
|
52
|
+
throw new Error(
|
|
53
|
+
`apotheke: extended config not found: ${parentPath}
|
|
54
|
+
(referenced from ${configPath} via "extends": "${userConfig.extends}")`
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
const parent = await loadConfig(parentPath);
|
|
58
|
+
return mergeConfigs(parent, config);
|
|
59
|
+
}
|
|
60
|
+
return config;
|
|
61
|
+
}
|
|
62
|
+
function loadTsConfig(dir) {
|
|
63
|
+
const tsconfigPath = path.join(dir, "tsconfig.json");
|
|
64
|
+
if (!existsSync(tsconfigPath)) return null;
|
|
65
|
+
try {
|
|
66
|
+
const text = readFileSync(tsconfigPath, "utf8");
|
|
67
|
+
const cleaned = text.replace(/\/\/[^\n]*/g, "").replace(/\/\*[\s\S]*?\*\//g, "");
|
|
68
|
+
return JSON.parse(cleaned);
|
|
69
|
+
} catch {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
62
72
|
}
|
|
63
73
|
|
|
64
74
|
// src/deduplicator.ts
|
|
@@ -88,7 +98,9 @@ function deduplicateImports(imports) {
|
|
|
88
98
|
}
|
|
89
99
|
|
|
90
100
|
// src/grouper.ts
|
|
91
|
-
import
|
|
101
|
+
import path2 from "path";
|
|
102
|
+
var SIDE_EFFECTS_GROUP = "SideEffects";
|
|
103
|
+
var OTHERS_GROUP = "Others";
|
|
92
104
|
function groupImports(imports, config, options = {}) {
|
|
93
105
|
const buckets = /* @__PURE__ */ new Map();
|
|
94
106
|
for (const node of imports) {
|
|
@@ -97,21 +109,21 @@ function groupImports(imports, config, options = {}) {
|
|
|
97
109
|
buckets.get(groupName).push(node);
|
|
98
110
|
}
|
|
99
111
|
const result = [];
|
|
100
|
-
if (buckets.has(
|
|
101
|
-
result.push({ name:
|
|
112
|
+
if (buckets.has(SIDE_EFFECTS_GROUP)) {
|
|
113
|
+
result.push({ name: SIDE_EFFECTS_GROUP, imports: buckets.get(SIDE_EFFECTS_GROUP) });
|
|
102
114
|
}
|
|
103
115
|
for (const group of config.groups) {
|
|
104
116
|
if (buckets.has(group.name)) {
|
|
105
117
|
result.push({ name: group.name, imports: buckets.get(group.name) });
|
|
106
118
|
}
|
|
107
119
|
}
|
|
108
|
-
if (buckets.has(
|
|
109
|
-
result.push({ name:
|
|
120
|
+
if (buckets.has(OTHERS_GROUP)) {
|
|
121
|
+
result.push({ name: OTHERS_GROUP, imports: buckets.get(OTHERS_GROUP) });
|
|
110
122
|
}
|
|
111
123
|
return result;
|
|
112
124
|
}
|
|
113
125
|
function assignGroup(node, config, options) {
|
|
114
|
-
if (node.isSideEffect) return
|
|
126
|
+
if (node.isSideEffect) return SIDE_EFFECTS_GROUP;
|
|
115
127
|
const canonicalPath = resolveCanonicalPath(node.specifier, config, options);
|
|
116
128
|
for (const group of config.groups) {
|
|
117
129
|
for (const pattern of group.match) {
|
|
@@ -119,12 +131,12 @@ function assignGroup(node, config, options) {
|
|
|
119
131
|
if (canonicalPath && matches(canonicalPath, pattern)) return group.name;
|
|
120
132
|
}
|
|
121
133
|
}
|
|
122
|
-
return
|
|
134
|
+
return OTHERS_GROUP;
|
|
123
135
|
}
|
|
124
136
|
function resolveCanonicalPath(specifier, config, options) {
|
|
125
137
|
if (specifier.startsWith(".") || specifier.startsWith("/")) {
|
|
126
138
|
const base = options.fileDir ?? process.cwd();
|
|
127
|
-
return
|
|
139
|
+
return path2.resolve(base, specifier);
|
|
128
140
|
}
|
|
129
141
|
const aliases = config.aliases ?? {};
|
|
130
142
|
for (const [alias, target] of Object.entries(aliases)) {
|
|
@@ -132,7 +144,7 @@ function resolveCanonicalPath(specifier, config, options) {
|
|
|
132
144
|
if (specifier === alias || specifier.startsWith(prefix)) {
|
|
133
145
|
const rest = specifier.slice(prefix.length);
|
|
134
146
|
const root = options.rootDir ?? process.cwd();
|
|
135
|
-
const resolved =
|
|
147
|
+
const resolved = path2.resolve(root, target, rest);
|
|
136
148
|
return resolved;
|
|
137
149
|
}
|
|
138
150
|
}
|
|
@@ -169,21 +181,63 @@ function globToRegex(pattern) {
|
|
|
169
181
|
return new RegExp(re + "$");
|
|
170
182
|
}
|
|
171
183
|
|
|
172
|
-
// src/
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
184
|
+
// src/parser.ts
|
|
185
|
+
import { parseSync } from "oxc-parser";
|
|
186
|
+
function parseImports(source) {
|
|
187
|
+
const result = parseSync("file.tsx", source);
|
|
188
|
+
const comments = result.comments;
|
|
189
|
+
const nodes = [];
|
|
190
|
+
for (const node of result.program.body) {
|
|
191
|
+
if (node.type !== "ImportDeclaration") continue;
|
|
192
|
+
const specifier = node.source.value;
|
|
193
|
+
let defaultImport;
|
|
194
|
+
const namedImports = [];
|
|
195
|
+
let namespaceImport;
|
|
196
|
+
for (const s of node.specifiers) {
|
|
197
|
+
if (s.type === "ImportDefaultSpecifier") {
|
|
198
|
+
defaultImport = s.local.name;
|
|
199
|
+
} else if (s.type === "ImportNamespaceSpecifier") {
|
|
200
|
+
namespaceImport = s.local.name;
|
|
201
|
+
} else if (s.type === "ImportSpecifier") {
|
|
202
|
+
const imported = s.imported;
|
|
203
|
+
const name = imported.type === "Identifier" ? imported.name : imported.value;
|
|
204
|
+
const localName = s.local.name;
|
|
205
|
+
const kind = s.importKind === "type" ? "type" : "value";
|
|
206
|
+
const named = { name, kind };
|
|
207
|
+
if (localName !== name) named.alias = localName;
|
|
208
|
+
namedImports.push(named);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
const importKind = node.importKind === "type" ? "type" : "value";
|
|
212
|
+
const isSideEffect = node.specifiers.length === 0 && importKind === "value";
|
|
213
|
+
const importNode = {
|
|
214
|
+
specifier,
|
|
215
|
+
namedImports,
|
|
216
|
+
isSideEffect,
|
|
217
|
+
importKind,
|
|
218
|
+
start: node.start,
|
|
219
|
+
end: node.end
|
|
220
|
+
};
|
|
221
|
+
if (defaultImport) importNode.defaultImport = defaultImport;
|
|
222
|
+
if (namespaceImport) importNode.namespaceImport = namespaceImport;
|
|
223
|
+
const attached = findAttachedComment(source, node.start, comments);
|
|
224
|
+
if (attached) importNode.attachedComment = attached;
|
|
225
|
+
nodes.push(importNode);
|
|
226
|
+
}
|
|
227
|
+
return nodes;
|
|
179
228
|
}
|
|
180
|
-
function
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
229
|
+
function findAttachedComment(source, importStart, comments) {
|
|
230
|
+
const linesBefore = source.slice(0, importStart).split("\n");
|
|
231
|
+
const importLine = linesBefore.length - 1;
|
|
232
|
+
for (const comment of comments) {
|
|
233
|
+
if (comment.type !== "Line") continue;
|
|
234
|
+
const commentLines = source.slice(0, comment.end).split("\n");
|
|
235
|
+
const commentLine = commentLines.length - 1;
|
|
236
|
+
if (commentLine === importLine - 1) {
|
|
237
|
+
return `//${comment.value}`;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return void 0;
|
|
187
241
|
}
|
|
188
242
|
|
|
189
243
|
// src/printer.ts
|
|
@@ -235,6 +289,23 @@ function buildImportStatement(node, q) {
|
|
|
235
289
|
return `import ${typePrefix}${parts.join(", ")} from ${q}${node.specifier}${q};`;
|
|
236
290
|
}
|
|
237
291
|
|
|
292
|
+
// src/sorter.ts
|
|
293
|
+
function sortGroup(imports) {
|
|
294
|
+
return [...imports].sort((a, b) => {
|
|
295
|
+
if (a.importKind === "type" && b.importKind !== "type") return -1;
|
|
296
|
+
if (a.importKind !== "type" && b.importKind === "type") return 1;
|
|
297
|
+
return a.specifier.localeCompare(b.specifier);
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
function sortNamedImports(node) {
|
|
301
|
+
const sorted = [...node.namedImports].sort((a, b) => {
|
|
302
|
+
if (a.kind === "type" && b.kind !== "type") return -1;
|
|
303
|
+
if (a.kind !== "type" && b.kind === "type") return 1;
|
|
304
|
+
return a.name.localeCompare(b.name);
|
|
305
|
+
});
|
|
306
|
+
return { ...node, namedImports: sorted };
|
|
307
|
+
}
|
|
308
|
+
|
|
238
309
|
// src/format.ts
|
|
239
310
|
function collectOrphanSegments(source, imports) {
|
|
240
311
|
const orphans = [];
|
|
@@ -263,7 +334,9 @@ function formatImports(source, config, options = {}) {
|
|
|
263
334
|
const deduped = deduplicateImports(clean);
|
|
264
335
|
const sorted = deduped.map(sortNamedImports);
|
|
265
336
|
const grouped = groupImports(sorted, config, options);
|
|
266
|
-
const sortedGroups = grouped.map(
|
|
337
|
+
const sortedGroups = grouped.map(
|
|
338
|
+
(g) => g.name === SIDE_EFFECTS_GROUP ? g : { ...g, imports: sortGroup(g.imports) }
|
|
339
|
+
);
|
|
267
340
|
const q = detectQuoteChar(source);
|
|
268
341
|
const newImportBlock = printGroups(sortedGroups, config, q);
|
|
269
342
|
const firstImport = imports[0];
|
|
@@ -282,76 +355,7 @@ function formatImports(source, config, options = {}) {
|
|
|
282
355
|
return before + newImportBlock + "\n" + orphanSuffix + after;
|
|
283
356
|
}
|
|
284
357
|
|
|
285
|
-
// src/config.ts
|
|
286
|
-
import path2 from "path";
|
|
287
|
-
import { existsSync, readFileSync } from "fs";
|
|
288
|
-
function mergeConfigs(parent, child) {
|
|
289
|
-
const mergedGroups = [...parent.groups];
|
|
290
|
-
for (const childGroup of child.groups ?? []) {
|
|
291
|
-
const existingIdx = mergedGroups.findIndex((g) => g.name === childGroup.name);
|
|
292
|
-
if (existingIdx >= 0) {
|
|
293
|
-
mergedGroups[existingIdx] = childGroup;
|
|
294
|
-
} else {
|
|
295
|
-
mergedGroups.push(childGroup);
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
return {
|
|
299
|
-
...parent,
|
|
300
|
-
...child,
|
|
301
|
-
groups: mergedGroups,
|
|
302
|
-
aliases: { ...parent.aliases ?? {}, ...child.aliases ?? {} }
|
|
303
|
-
};
|
|
304
|
-
}
|
|
305
|
-
async function loadConfig(configPath) {
|
|
306
|
-
const mod = await import(configPath);
|
|
307
|
-
const userConfig = mod.default ?? mod;
|
|
308
|
-
const configDir = path2.dirname(configPath);
|
|
309
|
-
const config = { ...userConfig };
|
|
310
|
-
const tsconfig = loadTsConfig(configDir);
|
|
311
|
-
if (tsconfig) {
|
|
312
|
-
const opts = tsconfig.compilerOptions ?? {};
|
|
313
|
-
if (opts.baseUrl && !config.baseUrl) {
|
|
314
|
-
config.baseUrl = opts.baseUrl;
|
|
315
|
-
}
|
|
316
|
-
if (opts.paths) {
|
|
317
|
-
const aliases = { ...config.aliases ?? {} };
|
|
318
|
-
for (const [aliasPattern, targets] of Object.entries(
|
|
319
|
-
opts.paths
|
|
320
|
-
)) {
|
|
321
|
-
const alias = aliasPattern.replace(/\/\*$/, "");
|
|
322
|
-
const target = (targets[0] ?? "").replace(/\/\*$/, "");
|
|
323
|
-
if (!aliases[alias]) aliases[alias] = target;
|
|
324
|
-
}
|
|
325
|
-
config.aliases = aliases;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
if (userConfig.extends) {
|
|
329
|
-
const parentPath = path2.resolve(configDir, userConfig.extends);
|
|
330
|
-
if (!existsSync(parentPath)) {
|
|
331
|
-
throw new Error(
|
|
332
|
-
`apotheke: extended config not found: ${parentPath}
|
|
333
|
-
(referenced from ${configPath} via "extends": "${userConfig.extends}")`
|
|
334
|
-
);
|
|
335
|
-
}
|
|
336
|
-
const parent = await loadConfig(parentPath);
|
|
337
|
-
return mergeConfigs(parent, config);
|
|
338
|
-
}
|
|
339
|
-
return config;
|
|
340
|
-
}
|
|
341
|
-
function loadTsConfig(dir) {
|
|
342
|
-
const tsconfigPath = path2.join(dir, "tsconfig.json");
|
|
343
|
-
if (!existsSync(tsconfigPath)) return null;
|
|
344
|
-
try {
|
|
345
|
-
const text = readFileSync(tsconfigPath, "utf8");
|
|
346
|
-
const cleaned = text.replace(/\/\/[^\n]*/g, "").replace(/\/\*[\s\S]*?\*\//g, "");
|
|
347
|
-
return JSON.parse(cleaned);
|
|
348
|
-
} catch {
|
|
349
|
-
return null;
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
|
|
353
358
|
// index.ts
|
|
354
|
-
import { createRequire } from "module";
|
|
355
359
|
async function resolveConfig(filePath) {
|
|
356
360
|
const candidates = ["apotheke.config.mjs", "apotheke.config.js"];
|
|
357
361
|
let dir = path3.dirname(path3.resolve(filePath));
|
|
@@ -368,7 +372,12 @@ async function resolveConfig(filePath) {
|
|
|
368
372
|
`apotheke: no config found for ${filePath}. Create an apotheke.config.mjs in your project root.`
|
|
369
373
|
);
|
|
370
374
|
}
|
|
375
|
+
var DOCUMENT_PARSERS = /* @__PURE__ */ new Set(["markdown", "mdx"]);
|
|
376
|
+
function isDocumentSnippet(parentParser) {
|
|
377
|
+
return typeof parentParser === "string" && DOCUMENT_PARSERS.has(parentParser);
|
|
378
|
+
}
|
|
371
379
|
async function preprocess(text, options) {
|
|
380
|
+
if (isDocumentSnippet(options.parentParser)) return text;
|
|
372
381
|
try {
|
|
373
382
|
const config = await resolveConfig(options.filepath ?? process.cwd());
|
|
374
383
|
const fileDir = options.filepath ? path3.dirname(path3.resolve(options.filepath)) : void 0;
|
|
@@ -436,7 +445,10 @@ function makeParser(pluginPath, parserName) {
|
|
|
436
445
|
async preprocess(text, opts) {
|
|
437
446
|
const base = getBase(opts?.filepath);
|
|
438
447
|
const basePreprocess = base?.preprocess;
|
|
439
|
-
const after = basePreprocess ? await basePreprocess(
|
|
448
|
+
const after = basePreprocess ? await basePreprocess(
|
|
449
|
+
text,
|
|
450
|
+
opts
|
|
451
|
+
) : text;
|
|
440
452
|
return preprocess(after, opts);
|
|
441
453
|
}
|
|
442
454
|
};
|
|
@@ -449,5 +461,6 @@ var parsers = {
|
|
|
449
461
|
};
|
|
450
462
|
export {
|
|
451
463
|
formatImports,
|
|
464
|
+
isDocumentSnippet,
|
|
452
465
|
parsers
|
|
453
466
|
};
|
package/package.json
CHANGED
|
@@ -1,48 +1,67 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
"
|
|
34
|
-
|
|
2
|
+
"name": "apotheke",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Prettier for imports — deterministic import organization as a Prettier plugin or CLI",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "Marco Raffaello",
|
|
8
|
+
"homepage": "https://marcoraffaello.com/apotheke",
|
|
9
|
+
"keywords": [
|
|
10
|
+
"imports",
|
|
11
|
+
"import-sorter",
|
|
12
|
+
"organize-imports",
|
|
13
|
+
"prettier",
|
|
14
|
+
"prettier-plugin",
|
|
15
|
+
"typescript",
|
|
16
|
+
"javascript",
|
|
17
|
+
"codemod",
|
|
18
|
+
"monorepo"
|
|
19
|
+
],
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "https://github.com/mRaffaello/apotheke",
|
|
23
|
+
"directory": "packages/apotheke"
|
|
24
|
+
},
|
|
25
|
+
"bugs": {
|
|
26
|
+
"url": "https://github.com/mRaffaello/apotheke/issues"
|
|
27
|
+
},
|
|
28
|
+
"exports": {
|
|
29
|
+
".": "./dist/index.js"
|
|
30
|
+
},
|
|
31
|
+
"main": "./dist/index.js",
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"bin": {
|
|
34
|
+
"apotheke": "./dist/cli.js"
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"dist",
|
|
38
|
+
"SKILL.md"
|
|
39
|
+
],
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "tsup",
|
|
42
|
+
"lint": "eslint .",
|
|
43
|
+
"lint:fix": "eslint . --fix",
|
|
44
|
+
"typecheck": "tsc --noEmit",
|
|
45
|
+
"test": "vitest run",
|
|
46
|
+
"test:unit": "vitest run tests/unit",
|
|
47
|
+
"test:e2e": "vitest run tests/e2e/e2e.test.ts"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@types/node": "^25.6.0",
|
|
51
|
+
"tsup": "^8.5.1",
|
|
52
|
+
"typescript": "~5.9.3",
|
|
53
|
+
"vitest": "^4.1.5"
|
|
54
|
+
},
|
|
55
|
+
"peerDependencies": {
|
|
56
|
+
"prettier": ">=3"
|
|
57
|
+
},
|
|
58
|
+
"peerDependenciesMeta": {
|
|
59
|
+
"prettier": {
|
|
60
|
+
"optional": true
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
"dependencies": {
|
|
64
|
+
"fast-glob": "^3.3.3",
|
|
65
|
+
"oxc-parser": "^0.129.0"
|
|
35
66
|
}
|
|
36
|
-
|
|
37
|
-
"dependencies": {
|
|
38
|
-
"fast-glob": "^3.3.3",
|
|
39
|
-
"oxc-parser": "^0.129.0"
|
|
40
|
-
},
|
|
41
|
-
"scripts": {
|
|
42
|
-
"build": "tsup",
|
|
43
|
-
"typecheck": "tsc --noEmit",
|
|
44
|
-
"test": "vitest run",
|
|
45
|
-
"test:unit": "vitest run tests/unit",
|
|
46
|
-
"test:e2e": "vitest run tests/e2e/e2e.test.ts"
|
|
47
|
-
}
|
|
48
|
-
}
|
|
67
|
+
}
|