@contextforge/core 0.1.1 → 0.1.2
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/dist/index.d.ts +1 -1
- package/dist/index.js +75 -62
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -182,7 +182,7 @@ declare function hasScript(packageJson: PackageJson | null, scriptName: string):
|
|
|
182
182
|
|
|
183
183
|
declare function findPack(registry: LoadedPack[], packName: string): LoadedPack | undefined;
|
|
184
184
|
declare function resolvePacks(packNames: string[], registry: LoadedPack[]): LoadedPack[];
|
|
185
|
-
declare function recommendPacks(analysis: ProjectAnalysis, registry: LoadedPack[]): LoadedPack[]
|
|
185
|
+
declare function recommendPacks(analysis: ProjectAnalysis, registry: LoadedPack[]): Promise<LoadedPack[]>;
|
|
186
186
|
declare function packMatchesProject(pack: LoadedPack, root: string, packageJson: PackageJson | null): Promise<boolean>;
|
|
187
187
|
declare function packageManagerLabel(packageManager: PackageManager): string;
|
|
188
188
|
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/detect/detectProject.ts
|
|
2
|
-
import
|
|
2
|
+
import path6 from "path";
|
|
3
3
|
import fg4 from "fast-glob";
|
|
4
|
-
import
|
|
4
|
+
import fs6 from "fs-extra";
|
|
5
5
|
|
|
6
6
|
// src/detect/detectAITools.ts
|
|
7
7
|
import path from "path";
|
|
@@ -91,6 +91,28 @@ async function detectPackageManager(root) {
|
|
|
91
91
|
return "unknown";
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
// src/project/packageJson.ts
|
|
95
|
+
import path5 from "path";
|
|
96
|
+
import fs5 from "fs-extra";
|
|
97
|
+
async function readPackageJson(root) {
|
|
98
|
+
const packageJsonPath = path5.join(root, "package.json");
|
|
99
|
+
if (!await fs5.pathExists(packageJsonPath)) {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
return fs5.readJson(packageJsonPath);
|
|
103
|
+
}
|
|
104
|
+
function hasPackage(packageJson, packageName) {
|
|
105
|
+
if (!packageJson) {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
return Boolean(
|
|
109
|
+
packageJson.dependencies?.[packageName] || packageJson.devDependencies?.[packageName] || packageJson.peerDependencies?.[packageName] || packageJson.optionalDependencies?.[packageName]
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
function hasScript(packageJson, scriptName) {
|
|
113
|
+
return Boolean(packageJson?.scripts?.[scriptName]);
|
|
114
|
+
}
|
|
115
|
+
|
|
94
116
|
// src/detect/detectProject.ts
|
|
95
117
|
async function hasAny(root, patterns) {
|
|
96
118
|
const matches = await fg4(patterns, {
|
|
@@ -101,21 +123,27 @@ async function hasAny(root, patterns) {
|
|
|
101
123
|
return matches.length > 0;
|
|
102
124
|
}
|
|
103
125
|
async function detectProject(root) {
|
|
104
|
-
const resolvedRoot =
|
|
105
|
-
const [packageManager, framework, database, aiTools] = await Promise.all([
|
|
126
|
+
const resolvedRoot = path6.resolve(root);
|
|
127
|
+
const [packageManager, framework, database, aiTools, packageJson] = await Promise.all([
|
|
106
128
|
detectPackageManager(resolvedRoot),
|
|
107
129
|
detectFramework(resolvedRoot),
|
|
108
130
|
detectDatabase(resolvedRoot),
|
|
109
|
-
detectAITools(resolvedRoot)
|
|
131
|
+
detectAITools(resolvedRoot),
|
|
132
|
+
readPackageJson(resolvedRoot)
|
|
110
133
|
]);
|
|
111
|
-
const [typescript,
|
|
112
|
-
|
|
134
|
+
const [typescript, tailwindConfig, componentsJson, vitestConfig, jestConfig, playwrightConfig] = await Promise.all([
|
|
135
|
+
fs6.pathExists(path6.join(resolvedRoot, "tsconfig.json")),
|
|
113
136
|
hasAny(resolvedRoot, ["tailwind.config.{js,ts,mjs,mts,cjs,cts}"]),
|
|
114
|
-
|
|
137
|
+
fs6.pathExists(path6.join(resolvedRoot, "components.json")),
|
|
115
138
|
hasAny(resolvedRoot, ["vitest.config.{js,ts,mjs,mts,cjs,cts}"]),
|
|
116
139
|
hasAny(resolvedRoot, ["jest.config.{js,ts,mjs,mts,cjs,cts}", "jest.config.json"]),
|
|
117
140
|
hasAny(resolvedRoot, ["playwright.config.{js,ts,mjs,mts,cjs,cts}"])
|
|
118
141
|
]);
|
|
142
|
+
const tailwind = tailwindConfig || hasPackage(packageJson, "tailwindcss");
|
|
143
|
+
const shadcn = componentsJson || hasPackage(packageJson, "shadcn") || hasPackage(packageJson, "shadcn-ui");
|
|
144
|
+
const vitest = vitestConfig || hasPackage(packageJson, "vitest");
|
|
145
|
+
const jest = jestConfig || hasPackage(packageJson, "jest");
|
|
146
|
+
const playwright = playwrightConfig || hasPackage(packageJson, "@playwright/test") || hasPackage(packageJson, "playwright");
|
|
119
147
|
return {
|
|
120
148
|
root: resolvedRoot,
|
|
121
149
|
packageManager,
|
|
@@ -176,30 +204,30 @@ var RemoteRegistryIndexSchema = z.object({
|
|
|
176
204
|
});
|
|
177
205
|
|
|
178
206
|
// src/registry/loadRegistry.ts
|
|
179
|
-
import
|
|
207
|
+
import path8 from "path";
|
|
180
208
|
|
|
181
209
|
// src/registry/localRegistry.ts
|
|
182
|
-
import
|
|
183
|
-
import
|
|
210
|
+
import path7 from "path";
|
|
211
|
+
import fs7 from "fs-extra";
|
|
184
212
|
async function loadLocalRegistry(registryRoot, source) {
|
|
185
|
-
if (!await
|
|
213
|
+
if (!await fs7.pathExists(registryRoot)) {
|
|
186
214
|
return [];
|
|
187
215
|
}
|
|
188
|
-
const entries = await
|
|
216
|
+
const entries = await fs7.readdir(registryRoot, { withFileTypes: true });
|
|
189
217
|
const packs = [];
|
|
190
218
|
for (const entry of entries) {
|
|
191
219
|
if (!entry.isDirectory()) {
|
|
192
220
|
continue;
|
|
193
221
|
}
|
|
194
|
-
const directory =
|
|
195
|
-
const packPath =
|
|
196
|
-
if (!await
|
|
222
|
+
const directory = path7.join(registryRoot, entry.name);
|
|
223
|
+
const packPath = path7.join(directory, "pack.json");
|
|
224
|
+
if (!await fs7.pathExists(packPath)) {
|
|
197
225
|
continue;
|
|
198
226
|
}
|
|
199
|
-
const parsed = PackSchema.parse(await
|
|
227
|
+
const parsed = PackSchema.parse(await fs7.readJson(packPath));
|
|
200
228
|
const readOptional = async (fileName) => {
|
|
201
|
-
const filePath =
|
|
202
|
-
return await
|
|
229
|
+
const filePath = path7.join(directory, fileName);
|
|
230
|
+
return await fs7.pathExists(filePath) ? fs7.readFile(filePath, "utf8") : void 0;
|
|
203
231
|
};
|
|
204
232
|
const rules = await readOptional("rules.md");
|
|
205
233
|
if (!rules) {
|
|
@@ -325,7 +353,7 @@ async function loadRegistry(input = {}) {
|
|
|
325
353
|
const sources = input.sources ?? DEFAULT_REGISTRY_SOURCES;
|
|
326
354
|
const packs = [];
|
|
327
355
|
if (input.root) {
|
|
328
|
-
packs.push(...await loadLocalRegistry(
|
|
356
|
+
packs.push(...await loadLocalRegistry(path8.join(input.root, PROJECT_PACK_CACHE), "project-cache"));
|
|
329
357
|
}
|
|
330
358
|
for (const source of sources) {
|
|
331
359
|
packs.push(...await loadRegistrySource(source, input.timeoutMs));
|
|
@@ -335,31 +363,8 @@ async function loadRegistry(input = {}) {
|
|
|
335
363
|
|
|
336
364
|
// src/registry/resolvePack.ts
|
|
337
365
|
import path9 from "path";
|
|
366
|
+
import fg5 from "fast-glob";
|
|
338
367
|
import fs8 from "fs-extra";
|
|
339
|
-
|
|
340
|
-
// src/project/packageJson.ts
|
|
341
|
-
import path8 from "path";
|
|
342
|
-
import fs7 from "fs-extra";
|
|
343
|
-
async function readPackageJson(root) {
|
|
344
|
-
const packageJsonPath = path8.join(root, "package.json");
|
|
345
|
-
if (!await fs7.pathExists(packageJsonPath)) {
|
|
346
|
-
return null;
|
|
347
|
-
}
|
|
348
|
-
return fs7.readJson(packageJsonPath);
|
|
349
|
-
}
|
|
350
|
-
function hasPackage(packageJson, packageName) {
|
|
351
|
-
if (!packageJson) {
|
|
352
|
-
return false;
|
|
353
|
-
}
|
|
354
|
-
return Boolean(
|
|
355
|
-
packageJson.dependencies?.[packageName] || packageJson.devDependencies?.[packageName] || packageJson.peerDependencies?.[packageName] || packageJson.optionalDependencies?.[packageName]
|
|
356
|
-
);
|
|
357
|
-
}
|
|
358
|
-
function hasScript(packageJson, scriptName) {
|
|
359
|
-
return Boolean(packageJson?.scripts?.[scriptName]);
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
// src/registry/resolvePack.ts
|
|
363
368
|
function findPack(registry, packName) {
|
|
364
369
|
return registry.find((pack) => pack.name === packName);
|
|
365
370
|
}
|
|
@@ -373,29 +378,37 @@ function resolvePacks(packNames, registry) {
|
|
|
373
378
|
return pack;
|
|
374
379
|
});
|
|
375
380
|
}
|
|
376
|
-
function
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
}
|
|
385
|
-
if (analysis.styling.shadcn) {
|
|
386
|
-
names.add("shadcn-ui");
|
|
381
|
+
async function hasDetectFile(root, filePattern) {
|
|
382
|
+
if (filePattern.includes("*")) {
|
|
383
|
+
const matches = await fg5(filePattern, {
|
|
384
|
+
cwd: root,
|
|
385
|
+
onlyFiles: false,
|
|
386
|
+
dot: true
|
|
387
|
+
});
|
|
388
|
+
return matches.length > 0;
|
|
387
389
|
}
|
|
388
|
-
|
|
389
|
-
|
|
390
|
+
return fs8.pathExists(path9.join(root, filePattern));
|
|
391
|
+
}
|
|
392
|
+
function hasDetectHints(pack) {
|
|
393
|
+
return Boolean(pack.detect?.files?.length || pack.detect?.packages?.length);
|
|
394
|
+
}
|
|
395
|
+
async function recommendPacks(analysis, registry) {
|
|
396
|
+
const packageJson = await readPackageJson(analysis.root);
|
|
397
|
+
const recommended = [];
|
|
398
|
+
for (const pack of registry) {
|
|
399
|
+
if (pack.name === "env-secrets") {
|
|
400
|
+
recommended.push(pack);
|
|
401
|
+
continue;
|
|
402
|
+
}
|
|
403
|
+
if (hasDetectHints(pack) && await packMatchesProject(pack, analysis.root, packageJson)) {
|
|
404
|
+
recommended.push(pack);
|
|
405
|
+
}
|
|
390
406
|
}
|
|
391
|
-
return
|
|
392
|
-
[...names].filter((name) => findPack(registry, name)),
|
|
393
|
-
registry
|
|
394
|
-
);
|
|
407
|
+
return recommended;
|
|
395
408
|
}
|
|
396
409
|
async function packMatchesProject(pack, root, packageJson) {
|
|
397
410
|
const fileChecks = await Promise.all(
|
|
398
|
-
pack.detect?.files?.map((filePattern) =>
|
|
411
|
+
pack.detect?.files?.map((filePattern) => hasDetectFile(root, filePattern)) ?? []
|
|
399
412
|
);
|
|
400
413
|
const packageChecks = pack.detect?.packages?.map((packageName) => hasPackage(packageJson, packageName)) ?? [];
|
|
401
414
|
const checks = [...fileChecks, ...packageChecks];
|