@shrkcrft/presets 0.1.0-alpha.2 → 0.1.0-alpha.20
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/builtin/angular21-presets.d.ts +9 -0
- package/dist/builtin/angular21-presets.d.ts.map +1 -0
- package/dist/builtin/angular21-presets.js +218 -0
- package/dist/builtin/angular21-snippets.d.ts +28 -0
- package/dist/builtin/angular21-snippets.d.ts.map +1 -0
- package/dist/builtin/angular21-snippets.js +243 -0
- package/dist/builtin/builtin-presets.d.ts.map +1 -1
- package/dist/builtin/builtin-presets.js +40 -19
- package/dist/builtin/nest11-presets.d.ts +11 -0
- package/dist/builtin/nest11-presets.d.ts.map +1 -0
- package/dist/builtin/nest11-presets.js +257 -0
- package/dist/builtin/nest11-snippets.d.ts +32 -0
- package/dist/builtin/nest11-snippets.d.ts.map +1 -0
- package/dist/builtin/nest11-snippets.js +270 -0
- package/dist/builtin/r26-presets.d.ts +1 -3
- package/dist/builtin/r26-presets.d.ts.map +1 -1
- package/dist/builtin/r26-presets.js +5 -33
- package/dist/builtin/r26-snippets.d.ts +0 -2
- package/dist/builtin/r26-snippets.d.ts.map +1 -1
- package/dist/builtin/r26-snippets.js +0 -16
- package/dist/builtin/r45-presets.d.ts +1 -1
- package/dist/builtin/r45-presets.d.ts.map +1 -1
- package/dist/builtin/r45-presets.js +5 -5
- package/dist/builtin/r47-presets.d.ts +1 -1
- package/dist/builtin/r47-presets.d.ts.map +1 -1
- package/dist/builtin/r47-presets.js +4 -4
- package/dist/builtin/react19-presets.d.ts +12 -0
- package/dist/builtin/react19-presets.d.ts.map +1 -0
- package/dist/builtin/react19-presets.js +299 -0
- package/dist/builtin/react19-snippets.d.ts +43 -0
- package/dist/builtin/react19-snippets.d.ts.map +1 -0
- package/dist/builtin/react19-snippets.js +363 -0
- package/dist/builtin/shared-snippets.d.ts +25 -3
- package/dist/builtin/shared-snippets.d.ts.map +1 -1
- package/dist/builtin/shared-snippets.js +265 -0
- package/dist/emit/synthesize-files.d.ts.map +1 -1
- package/dist/emit/synthesize-files.js +76 -17
- package/dist/registry/recommend.d.ts.map +1 -1
- package/dist/registry/recommend.js +7 -3
- package/package.json +5 -5
|
@@ -210,6 +210,7 @@ export const COMMON_PATH_SERVICES = `defineKnowledgeEntry({
|
|
|
210
210
|
scope: ['app'],
|
|
211
211
|
appliesWhen: ['generate-service'],
|
|
212
212
|
content: 'Service classes live in src/services/. One service per file.',
|
|
213
|
+
metadata: { path: 'src/services' },
|
|
213
214
|
})`;
|
|
214
215
|
export const COMMON_PATH_UTILS = `defineKnowledgeEntry({
|
|
215
216
|
id: 'paths.utils',
|
|
@@ -219,6 +220,7 @@ export const COMMON_PATH_UTILS = `defineKnowledgeEntry({
|
|
|
219
220
|
tags: ['paths', 'utils'],
|
|
220
221
|
appliesWhen: ['generate-utility'],
|
|
221
222
|
content: 'Pure helpers live in src/utils/. One function per file.',
|
|
223
|
+
metadata: { path: 'src/utils' },
|
|
222
224
|
})`;
|
|
223
225
|
export const COMMON_PATH_TESTS = `defineKnowledgeEntry({
|
|
224
226
|
id: 'paths.tests',
|
|
@@ -228,6 +230,269 @@ export const COMMON_PATH_TESTS = `defineKnowledgeEntry({
|
|
|
228
230
|
tags: ['paths', 'tests'],
|
|
229
231
|
appliesWhen: ['generate-test'],
|
|
230
232
|
content: 'Unit tests live under tests/, mirroring src/. Use *.spec.ts.',
|
|
233
|
+
metadata: { path: 'tests' },
|
|
234
|
+
})`;
|
|
235
|
+
// ─── Framework-specific path snippets ─────────────────────────────────────
|
|
236
|
+
//
|
|
237
|
+
// Each snippet uses the structured `metadata: { path: '<x>' }` field so
|
|
238
|
+
// the init paths-advisory annotator can verify the path against the live
|
|
239
|
+
// workspace. When an entry is emitted into a fresh repo whose layout
|
|
240
|
+
// doesn't match, the user sees a `⚠️ Workspace-shape advisory` block
|
|
241
|
+
// listing the absent paths.
|
|
242
|
+
// Nx workspaces — `libs/<area>/src/lib/<feature>.service.ts`,
|
|
243
|
+
// `apps/<app>/src/app/`. The exact lib/app folder names are
|
|
244
|
+
// project-specific; we point at the roots.
|
|
245
|
+
export const NX_PATH_LIBS = `defineKnowledgeEntry({
|
|
246
|
+
id: 'paths.nx.libs',
|
|
247
|
+
title: 'Nx libs root',
|
|
248
|
+
type: KnowledgeType.Path,
|
|
249
|
+
priority: KnowledgePriority.High,
|
|
250
|
+
tags: ['paths', 'nx', 'libs'],
|
|
251
|
+
scope: ['nx', 'monorepo'],
|
|
252
|
+
appliesWhen: ['generate-service', 'generate-utility', 'create-feature'],
|
|
253
|
+
content: 'Shared library code lives under libs/<area>/src/lib/. Each lib has a public index.ts; cross-lib imports go through the package name, never relative paths into src/.',
|
|
254
|
+
metadata: { path: 'libs' },
|
|
255
|
+
})`;
|
|
256
|
+
export const NX_PATH_APPS = `defineKnowledgeEntry({
|
|
257
|
+
id: 'paths.nx.apps',
|
|
258
|
+
title: 'Nx apps root',
|
|
259
|
+
type: KnowledgeType.Path,
|
|
260
|
+
priority: KnowledgePriority.High,
|
|
261
|
+
tags: ['paths', 'nx', 'apps'],
|
|
262
|
+
scope: ['nx', 'monorepo'],
|
|
263
|
+
appliesWhen: ['create-feature', 'create-app'],
|
|
264
|
+
content: 'Applications live under apps/<app>/. Frontends use apps/<app>/src/app/; backends use apps/<app>/src/. Keep app-specific code here and shared code in libs/.',
|
|
265
|
+
metadata: { path: 'apps' },
|
|
266
|
+
})`;
|
|
267
|
+
// Generic workspace monorepo (Turborepo, pnpm/yarn/npm workspaces): the
|
|
268
|
+
// idiomatic layout is `apps/` + `packages/` rather than Nx's `libs/`.
|
|
269
|
+
export const WORKSPACE_PATH_PACKAGES = `defineKnowledgeEntry({
|
|
270
|
+
id: 'paths.workspace.packages',
|
|
271
|
+
title: 'Workspace packages root',
|
|
272
|
+
type: KnowledgeType.Path,
|
|
273
|
+
priority: KnowledgePriority.High,
|
|
274
|
+
tags: ['paths', 'workspaces', 'monorepo'],
|
|
275
|
+
scope: ['monorepo', 'turborepo', 'workspaces'],
|
|
276
|
+
appliesWhen: ['generate-code', 'create-feature'],
|
|
277
|
+
content: 'Shared packages live under packages/<name>/. Each package exposes a stable public entry (package.json main/exports); cross-package imports go through the package name, never relative paths into src/.',
|
|
278
|
+
metadata: { path: 'packages' },
|
|
279
|
+
})`;
|
|
280
|
+
export const WORKSPACE_PATH_APPS = `defineKnowledgeEntry({
|
|
281
|
+
id: 'paths.workspace.apps',
|
|
282
|
+
title: 'Workspace apps root',
|
|
283
|
+
type: KnowledgeType.Path,
|
|
284
|
+
priority: KnowledgePriority.High,
|
|
285
|
+
tags: ['paths', 'workspaces', 'monorepo'],
|
|
286
|
+
scope: ['monorepo', 'turborepo', 'workspaces'],
|
|
287
|
+
appliesWhen: ['create-feature', 'create-app'],
|
|
288
|
+
content: 'Applications live under apps/<app>/. Each app has its own src/ root and depends on shared packages by name.',
|
|
289
|
+
metadata: { path: 'apps' },
|
|
290
|
+
})`;
|
|
291
|
+
// Single-app Angular workspaces — angular.json + src/app convention.
|
|
292
|
+
export const ANGULAR_PATH_APP = `defineKnowledgeEntry({
|
|
293
|
+
id: 'paths.angular.app',
|
|
294
|
+
title: 'Angular app root',
|
|
295
|
+
type: KnowledgeType.Path,
|
|
296
|
+
priority: KnowledgePriority.Critical,
|
|
297
|
+
tags: ['paths', 'angular', 'app'],
|
|
298
|
+
scope: ['angular'],
|
|
299
|
+
appliesWhen: ['create-feature', 'generate-code'],
|
|
300
|
+
content: 'Angular workspace source lives under src/app/. Components, services, pipes and modules sit under here. Tests are co-located as *.spec.ts beside the unit under test.',
|
|
301
|
+
metadata: { path: 'src/app' },
|
|
302
|
+
})`;
|
|
303
|
+
export const ANGULAR_PATH_COMPONENTS = `defineKnowledgeEntry({
|
|
304
|
+
id: 'paths.angular.components',
|
|
305
|
+
title: 'Angular components',
|
|
306
|
+
type: KnowledgeType.Path,
|
|
307
|
+
priority: KnowledgePriority.High,
|
|
308
|
+
tags: ['paths', 'angular', 'components'],
|
|
309
|
+
scope: ['angular'],
|
|
310
|
+
appliesWhen: ['generate-component'],
|
|
311
|
+
content: 'Components live under src/app/components/ or src/app/<feature>/. Use the .component.ts suffix. Pair each component with a co-located *.spec.ts test.',
|
|
312
|
+
metadata: { path: 'src/app/components' },
|
|
313
|
+
})`;
|
|
314
|
+
export const ANGULAR_PATH_SERVICES = `defineKnowledgeEntry({
|
|
315
|
+
id: 'paths.angular.services',
|
|
316
|
+
title: 'Angular services',
|
|
317
|
+
type: KnowledgeType.Path,
|
|
318
|
+
priority: KnowledgePriority.High,
|
|
319
|
+
tags: ['paths', 'angular', 'services'],
|
|
320
|
+
scope: ['angular'],
|
|
321
|
+
appliesWhen: ['generate-service'],
|
|
322
|
+
content: 'Injectable services live under src/app/services/ (or alongside their feature folder). Use the .service.ts suffix. Provide via providedIn root unless feature-scoped.',
|
|
323
|
+
metadata: { path: 'src/app/services' },
|
|
324
|
+
})`;
|
|
325
|
+
// React workspaces — many flavors (Vite SPA, Next.js, Remix). The
|
|
326
|
+
// snippets below cover the most common SPA layout (src/components,
|
|
327
|
+
// src/hooks, src/pages, src/lib). Frameworks that follow a different
|
|
328
|
+
// convention (e.g. Next.js app router under app/) will trigger the
|
|
329
|
+
// init paths-advisory; the user is expected to swap them at that point.
|
|
330
|
+
export const REACT_PATH_COMPONENTS = `defineKnowledgeEntry({
|
|
331
|
+
id: 'paths.react.components',
|
|
332
|
+
title: 'React components',
|
|
333
|
+
type: KnowledgeType.Path,
|
|
334
|
+
priority: KnowledgePriority.High,
|
|
335
|
+
tags: ['paths', 'react', 'components'],
|
|
336
|
+
scope: ['react'],
|
|
337
|
+
appliesWhen: ['generate-component'],
|
|
338
|
+
content: 'Components live under src/components/ (cross-feature shared) or under their feature folder. Keep each component in its own file; pair with a co-located *.test.tsx beside it.',
|
|
339
|
+
metadata: { path: 'src/components' },
|
|
340
|
+
})`;
|
|
341
|
+
export const REACT_PATH_HOOKS = `defineKnowledgeEntry({
|
|
342
|
+
id: 'paths.react.hooks',
|
|
343
|
+
title: 'React custom hooks',
|
|
344
|
+
type: KnowledgeType.Path,
|
|
345
|
+
priority: KnowledgePriority.High,
|
|
346
|
+
tags: ['paths', 'react', 'hooks'],
|
|
347
|
+
scope: ['react'],
|
|
348
|
+
appliesWhen: ['generate-hook'],
|
|
349
|
+
content: 'Custom hooks live under src/hooks/ (cross-feature) or under their feature folder. File and exported function are both named useX. Co-locate the test as useX.test.ts beside the hook.',
|
|
350
|
+
metadata: { path: 'src/hooks' },
|
|
351
|
+
})`;
|
|
352
|
+
export const REACT_PATH_PAGES = `defineKnowledgeEntry({
|
|
353
|
+
id: 'paths.react.pages',
|
|
354
|
+
title: 'React route / page components',
|
|
355
|
+
type: KnowledgeType.Path,
|
|
356
|
+
priority: KnowledgePriority.Medium,
|
|
357
|
+
tags: ['paths', 'react', 'pages', 'routing'],
|
|
358
|
+
scope: ['react'],
|
|
359
|
+
appliesWhen: ['create-feature', 'add-route'],
|
|
360
|
+
content: 'Top-level route components live under src/pages/ (React Router / TanStack Router convention) or under src/routes/. For Next.js app router, see src/app/<segment>/page.tsx instead — adjust this entry if your project uses that layout.',
|
|
361
|
+
metadata: { path: 'src/pages' },
|
|
362
|
+
})`;
|
|
363
|
+
export const REACT_PATH_LIB = `defineKnowledgeEntry({
|
|
364
|
+
id: 'paths.react.lib',
|
|
365
|
+
title: 'React app utilities + clients',
|
|
366
|
+
type: KnowledgeType.Path,
|
|
367
|
+
priority: KnowledgePriority.Medium,
|
|
368
|
+
tags: ['paths', 'react', 'lib'],
|
|
369
|
+
scope: ['react'],
|
|
370
|
+
appliesWhen: ['generate-utility', 'generate-code'],
|
|
371
|
+
content: 'Framework-agnostic helpers (formatters, validators, API clients) live under src/lib/. Keep them pure — no React imports unless the helper is a hook (in which case it belongs under src/hooks/).',
|
|
372
|
+
metadata: { path: 'src/lib' },
|
|
373
|
+
})`;
|
|
374
|
+
// NestJS services — module-per-folder convention; e2e tests in `test/`.
|
|
375
|
+
export const NEST_PATH_SRC = `defineKnowledgeEntry({
|
|
376
|
+
id: 'paths.nest.src',
|
|
377
|
+
title: 'Nest module roots',
|
|
378
|
+
type: KnowledgeType.Path,
|
|
379
|
+
priority: KnowledgePriority.Critical,
|
|
380
|
+
tags: ['paths', 'nest', 'modules'],
|
|
381
|
+
scope: ['nestjs'],
|
|
382
|
+
appliesWhen: ['create-feature', 'generate-service', 'generate-code'],
|
|
383
|
+
content: 'Nest source lives under src/. Each feature gets a folder src/<feature>/ containing controller, service, module, and DTOs (one construct per file). Controllers stay thin; business logic lives in services.',
|
|
384
|
+
metadata: { path: 'src' },
|
|
385
|
+
})`;
|
|
386
|
+
export const NEST_PATH_E2E = `defineKnowledgeEntry({
|
|
387
|
+
id: 'paths.nest.e2e',
|
|
388
|
+
title: 'Nest e2e tests',
|
|
389
|
+
type: KnowledgeType.Path,
|
|
390
|
+
priority: KnowledgePriority.Medium,
|
|
391
|
+
tags: ['paths', 'nest', 'testing'],
|
|
392
|
+
scope: ['nestjs'],
|
|
393
|
+
appliesWhen: ['generate-test'],
|
|
394
|
+
content: 'End-to-end tests live under test/ (Nest convention, not tests/). Unit tests can be co-located as *.spec.ts next to the unit.',
|
|
395
|
+
metadata: { path: 'test' },
|
|
396
|
+
})`;
|
|
397
|
+
// ─── Polyglot path snippets ──────────────────────────────────────────────
|
|
398
|
+
export const JAVA_MAVEN_PATH_MAIN = `defineKnowledgeEntry({
|
|
399
|
+
id: 'paths.java.maven.main',
|
|
400
|
+
title: 'Java Maven main source',
|
|
401
|
+
type: KnowledgeType.Path,
|
|
402
|
+
priority: KnowledgePriority.Critical,
|
|
403
|
+
tags: ['paths', 'java', 'maven'],
|
|
404
|
+
scope: ['java', 'maven'],
|
|
405
|
+
appliesWhen: ['generate-code'],
|
|
406
|
+
content: 'Main Java source lives under src/main/java/<package>/. Resources under src/main/resources/. Mirror tests under src/test/java/.',
|
|
407
|
+
metadata: { path: 'src/main/java' },
|
|
408
|
+
})`;
|
|
409
|
+
export const JAVA_MAVEN_PATH_TESTS = `defineKnowledgeEntry({
|
|
410
|
+
id: 'paths.java.maven.tests',
|
|
411
|
+
title: 'Java Maven tests',
|
|
412
|
+
type: KnowledgeType.Path,
|
|
413
|
+
priority: KnowledgePriority.High,
|
|
414
|
+
tags: ['paths', 'java', 'maven', 'tests'],
|
|
415
|
+
scope: ['java', 'maven'],
|
|
416
|
+
appliesWhen: ['generate-test'],
|
|
417
|
+
content: 'JUnit / Spring tests live under src/test/java/. Run via mvn test.',
|
|
418
|
+
metadata: { path: 'src/test/java' },
|
|
419
|
+
})`;
|
|
420
|
+
export const PYTHON_PATH_SRC = `defineKnowledgeEntry({
|
|
421
|
+
id: 'paths.python.src',
|
|
422
|
+
title: 'Python source root',
|
|
423
|
+
type: KnowledgeType.Path,
|
|
424
|
+
priority: KnowledgePriority.Critical,
|
|
425
|
+
tags: ['paths', 'python'],
|
|
426
|
+
scope: ['python'],
|
|
427
|
+
appliesWhen: ['generate-code'],
|
|
428
|
+
content: 'Source lives under src/<package>/ (PEP 517 src layout) or directly under <package>/ at the repo root. Pick one and stay consistent.',
|
|
429
|
+
metadata: { path: 'src' },
|
|
430
|
+
})`;
|
|
431
|
+
export const PYTHON_PATH_TESTS = `defineKnowledgeEntry({
|
|
432
|
+
id: 'paths.python.tests',
|
|
433
|
+
title: 'Python tests',
|
|
434
|
+
type: KnowledgeType.Path,
|
|
435
|
+
priority: KnowledgePriority.High,
|
|
436
|
+
tags: ['paths', 'python', 'tests'],
|
|
437
|
+
scope: ['python'],
|
|
438
|
+
appliesWhen: ['generate-test'],
|
|
439
|
+
content: 'Pytest tests live under tests/. Each test_*.py mirrors a module under src/.',
|
|
440
|
+
metadata: { path: 'tests' },
|
|
441
|
+
})`;
|
|
442
|
+
export const GO_PATH_CMD = `defineKnowledgeEntry({
|
|
443
|
+
id: 'paths.go.cmd',
|
|
444
|
+
title: 'Go entry points',
|
|
445
|
+
type: KnowledgeType.Path,
|
|
446
|
+
priority: KnowledgePriority.High,
|
|
447
|
+
tags: ['paths', 'go'],
|
|
448
|
+
scope: ['go'],
|
|
449
|
+
appliesWhen: ['create-app'],
|
|
450
|
+
content: 'Binary entry points live under cmd/<name>/main.go. Shared library code under pkg/ (public) or internal/ (module-private).',
|
|
451
|
+
metadata: { path: 'cmd' },
|
|
452
|
+
})`;
|
|
453
|
+
export const GO_PATH_PKG = `defineKnowledgeEntry({
|
|
454
|
+
id: 'paths.go.pkg',
|
|
455
|
+
title: 'Go shared packages',
|
|
456
|
+
type: KnowledgeType.Path,
|
|
457
|
+
priority: KnowledgePriority.Medium,
|
|
458
|
+
tags: ['paths', 'go'],
|
|
459
|
+
scope: ['go'],
|
|
460
|
+
appliesWhen: ['generate-code'],
|
|
461
|
+
content: 'Public packages live under pkg/<name>/. Tests are co-located as <name>_test.go. Run via go test ./...',
|
|
462
|
+
metadata: { path: 'pkg' },
|
|
463
|
+
})`;
|
|
464
|
+
export const GO_PATH_INTERNAL = `defineKnowledgeEntry({
|
|
465
|
+
id: 'paths.go.internal',
|
|
466
|
+
title: 'Go internal packages',
|
|
467
|
+
type: KnowledgeType.Path,
|
|
468
|
+
priority: KnowledgePriority.Medium,
|
|
469
|
+
tags: ['paths', 'go'],
|
|
470
|
+
scope: ['go'],
|
|
471
|
+
appliesWhen: ['generate-code'],
|
|
472
|
+
content: 'Module-private packages live under internal/<name>/. The Go compiler enforces that only the parent module can import these.',
|
|
473
|
+
metadata: { path: 'internal' },
|
|
474
|
+
})`;
|
|
475
|
+
export const RUST_PATH_SRC = `defineKnowledgeEntry({
|
|
476
|
+
id: 'paths.rust.src',
|
|
477
|
+
title: 'Rust crate source',
|
|
478
|
+
type: KnowledgeType.Path,
|
|
479
|
+
priority: KnowledgePriority.Critical,
|
|
480
|
+
tags: ['paths', 'rust'],
|
|
481
|
+
scope: ['rust'],
|
|
482
|
+
appliesWhen: ['generate-code'],
|
|
483
|
+
content: 'Crate source lives under src/. The entry point is src/lib.rs (library) or src/main.rs (binary). Modules nest as src/<mod>/mod.rs or src/<mod>.rs.',
|
|
484
|
+
metadata: { path: 'src' },
|
|
485
|
+
})`;
|
|
486
|
+
export const RUST_PATH_TESTS = `defineKnowledgeEntry({
|
|
487
|
+
id: 'paths.rust.tests',
|
|
488
|
+
title: 'Rust integration tests',
|
|
489
|
+
type: KnowledgeType.Path,
|
|
490
|
+
priority: KnowledgePriority.Medium,
|
|
491
|
+
tags: ['paths', 'rust', 'tests'],
|
|
492
|
+
scope: ['rust'],
|
|
493
|
+
appliesWhen: ['generate-test'],
|
|
494
|
+
content: 'Integration tests live under tests/<name>.rs. Unit tests live inline with #[cfg(test)] modules inside src/. Run via cargo test.',
|
|
495
|
+
metadata: { path: 'tests' },
|
|
231
496
|
})`;
|
|
232
497
|
export const COMMON_RULE_INTERFACE_PREFIX = `defineKnowledgeEntry({
|
|
233
498
|
id: 'typescript.interfaces.i-prefix',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"synthesize-files.d.ts","sourceRoot":"","sources":["../../src/emit/synthesize-files.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAEnE,MAAM,WAAW,gBAAgB;IAC/B,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,IAAI,EACA,QAAQ,GACR,WAAW,GACX,OAAO,GACP,OAAO,GACP,WAAW,GACX,WAAW,GACX,MAAM,GACN,OAAO,GACP,cAAc,GACd,SAAS,CAAC;CACf;
|
|
1
|
+
{"version":3,"file":"synthesize-files.d.ts","sourceRoot":"","sources":["../../src/emit/synthesize-files.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAEnE,MAAM,WAAW,gBAAgB;IAC/B,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,IAAI,EACA,QAAQ,GACR,WAAW,GACX,OAAO,GACP,OAAO,GACP,WAAW,GACX,WAAW,GACX,MAAM,GACN,OAAO,GACP,cAAc,GACd,SAAS,CAAC;CACf;AAqMD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,OAAO,GAAG,gBAAgB,EAAE,CAEzE;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE;IACtD,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,eAAe,CAAC;IAC1B,aAAa,EAAE,SAAS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC7D,GAAG,gBAAgB,EAAE,CAErB"}
|
|
@@ -1,3 +1,62 @@
|
|
|
1
|
+
// Self-contained preambles for each emitted file kind. Generated files
|
|
2
|
+
// must work in a brand-new downstream repo where no `@shrkcrft/*`
|
|
3
|
+
// packages are installed. The loaders (knowledge / templates / pipelines)
|
|
4
|
+
// are shape-agnostic — they accept any object with the required string
|
|
5
|
+
// fields — so we just need helpers + enum-like constants the snippets
|
|
6
|
+
// reference. See `packages/knowledge/src/load/typescript-knowledge-loader.ts`
|
|
7
|
+
// for the loader contract.
|
|
8
|
+
const KNOWLEDGE_HELPERS = `// Local helpers — keep this file self-contained (no @shrkcrft/* imports).
|
|
9
|
+
const KnowledgePriority = {
|
|
10
|
+
Critical: 'critical',
|
|
11
|
+
High: 'high',
|
|
12
|
+
Medium: 'medium',
|
|
13
|
+
Low: 'low',
|
|
14
|
+
} as const;
|
|
15
|
+
|
|
16
|
+
const KnowledgeType = {
|
|
17
|
+
Rule: 'rule',
|
|
18
|
+
Path: 'path',
|
|
19
|
+
Template: 'template',
|
|
20
|
+
Architecture: 'architecture',
|
|
21
|
+
Technical: 'technical',
|
|
22
|
+
Business: 'business',
|
|
23
|
+
Command: 'command',
|
|
24
|
+
Environment: 'environment',
|
|
25
|
+
Dependency: 'dependency',
|
|
26
|
+
Feature: 'feature',
|
|
27
|
+
Task: 'task',
|
|
28
|
+
Warning: 'warning',
|
|
29
|
+
Decision: 'decision',
|
|
30
|
+
Convention: 'convention',
|
|
31
|
+
Workflow: 'workflow',
|
|
32
|
+
Testing: 'testing',
|
|
33
|
+
Security: 'security',
|
|
34
|
+
Deployment: 'deployment',
|
|
35
|
+
Integration: 'integration',
|
|
36
|
+
Custom: 'custom',
|
|
37
|
+
} as const;
|
|
38
|
+
|
|
39
|
+
function defineKnowledgeEntry<T>(entry: T): T {
|
|
40
|
+
return entry;
|
|
41
|
+
}
|
|
42
|
+
`;
|
|
43
|
+
const TEMPLATE_HELPERS = `// Local helpers — keep this file self-contained (no @shrkcrft/* imports).
|
|
44
|
+
function defineTemplate<T>(template: T): T {
|
|
45
|
+
return template;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function kebab(s: string): string {
|
|
49
|
+
return s
|
|
50
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
|
51
|
+
.replace(/[^A-Za-z0-9]+/g, '-')
|
|
52
|
+
.toLowerCase();
|
|
53
|
+
}
|
|
54
|
+
`;
|
|
55
|
+
const PIPELINE_HELPERS = `// Local helpers — keep this file self-contained (no @shrkcrft/* imports).
|
|
56
|
+
function definePipeline<T>(pipeline: T): T {
|
|
57
|
+
return pipeline;
|
|
58
|
+
}
|
|
59
|
+
`;
|
|
1
60
|
function recordToMap(v) {
|
|
2
61
|
if (!v)
|
|
3
62
|
return new Map();
|
|
@@ -11,48 +70,47 @@ function listBlock(items, indent = ' ') {
|
|
|
11
70
|
return items.map((expr) => indent + expr.replace(/\n/g, `\n${indent}`)).join(',\n') + ',\n';
|
|
12
71
|
}
|
|
13
72
|
function knowledgeFile(items) {
|
|
14
|
-
return (
|
|
15
|
-
'
|
|
73
|
+
return (KNOWLEDGE_HELPERS +
|
|
74
|
+
'\nconst knowledge = [\n' +
|
|
16
75
|
listBlock(items) +
|
|
17
76
|
'];\n\n' +
|
|
18
77
|
'export default knowledge;\n');
|
|
19
78
|
}
|
|
20
79
|
function rulesFile(items) {
|
|
21
|
-
return (
|
|
22
|
-
'
|
|
80
|
+
return (KNOWLEDGE_HELPERS +
|
|
81
|
+
'\nconst rules = [\n' +
|
|
23
82
|
listBlock(items) +
|
|
24
83
|
'];\n\n' +
|
|
25
84
|
'export default rules;\n');
|
|
26
85
|
}
|
|
27
86
|
function pathsFile(items) {
|
|
28
|
-
return (
|
|
29
|
-
'
|
|
87
|
+
return (KNOWLEDGE_HELPERS +
|
|
88
|
+
'\nconst paths = [\n' +
|
|
30
89
|
listBlock(items) +
|
|
31
90
|
'];\n\n' +
|
|
32
91
|
'export default paths;\n');
|
|
33
92
|
}
|
|
34
93
|
function templatesFile(items) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
return ("import { defineTemplate } from '@shrkcrft/templates';\n\n" +
|
|
38
|
-
'function kebab(s: string): string {\n' +
|
|
39
|
-
" return s.replace(/([a-z0-9])([A-Z])/g, '$1-$2').replace(/[^A-Za-z0-9]+/g, '-').toLowerCase();\n" +
|
|
40
|
-
'}\n\n' +
|
|
41
|
-
'const templates = [\n' +
|
|
94
|
+
return (TEMPLATE_HELPERS +
|
|
95
|
+
'\nconst templates = [\n' +
|
|
42
96
|
listBlock(items) +
|
|
43
97
|
'];\n\n' +
|
|
44
98
|
'export default templates;\n');
|
|
45
99
|
}
|
|
46
100
|
function pipelinesFile(items) {
|
|
47
|
-
return (
|
|
48
|
-
'
|
|
101
|
+
return (PIPELINE_HELPERS +
|
|
102
|
+
'\nconst pipelines = [\n' +
|
|
49
103
|
listBlock(items) +
|
|
50
104
|
'];\n\n' +
|
|
51
105
|
'export default pipelines;\n');
|
|
52
106
|
}
|
|
53
107
|
function configFile(preset) {
|
|
54
108
|
// Generic config that points at the standard knowledge/rules/paths/etc.
|
|
55
|
-
// files. Consumers can tailor it later.
|
|
109
|
+
// files. Consumers can tailor it later. Plain default-exported object —
|
|
110
|
+
// the config loader (packages/config/src/config-loader.ts) validates the
|
|
111
|
+
// shape via zod and accepts an object literal as well as a
|
|
112
|
+
// `defineSharkCraftConfig()`-wrapped value, so the generated file does
|
|
113
|
+
// not need to import anything from `@shrkcrft/*`.
|
|
56
114
|
const filesByKind = inferFiles(preset);
|
|
57
115
|
const knowledgeFiles = filesByKind.has('knowledge.ts') ? ['knowledge.ts'] : [];
|
|
58
116
|
const ruleFiles = filesByKind.has('rules.ts') ? ['rules.ts'] : [];
|
|
@@ -67,7 +125,8 @@ function configFile(preset) {
|
|
|
67
125
|
? ` surface: { profile: ${JSON.stringify(preset.surfaceProfile)} },\n`
|
|
68
126
|
: '';
|
|
69
127
|
return (`// Generated by \`shrk presets apply ${preset.id}\`.\n` +
|
|
70
|
-
'// Edit freely. SharkCraft does not regenerate this file.\n
|
|
128
|
+
'// Edit freely. SharkCraft does not regenerate this file.\n' +
|
|
129
|
+
'// Plain default export — no @shrkcrft/* import required.\n\n' +
|
|
71
130
|
'const config = {\n' +
|
|
72
131
|
` projectName: 'shrk-project',\n` +
|
|
73
132
|
` description: ${JSON.stringify(preset.description)},\n` +
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recommend.d.ts","sourceRoot":"","sources":["../../src/registry/recommend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACtC,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACtC,qEAAqE;IACrE,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,iDAAiD;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,SAAS,OAAO,EAAE,EAC3B,OAAO,EAAE,iBAAiB,GACzB,qBAAqB,EAAE,
|
|
1
|
+
{"version":3,"file":"recommend.d.ts","sourceRoot":"","sources":["../../src/registry/recommend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACtC,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACtC,qEAAqE;IACrE,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,iDAAiD;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,SAAS,OAAO,EAAE,EAC3B,OAAO,EAAE,iBAAiB,GACzB,qBAAqB,EAAE,CA8CzB"}
|
|
@@ -44,14 +44,18 @@ export function recommendPresets(presets, options) {
|
|
|
44
44
|
}
|
|
45
45
|
if (dq)
|
|
46
46
|
continue;
|
|
47
|
+
// A targeted preset (it declares `appliesTo` requirements) that matched
|
|
48
|
+
// NONE of them is not a recommendation. Without this guard a vanilla JS
|
|
49
|
+
// repo gets every Angular preset, each "recommended" with the sole reason
|
|
50
|
+
// `missing profile: has-angular` — the agent then adopts framework
|
|
51
|
+
// conventions that don't apply. Universal presets (no `appliesTo`) survive.
|
|
52
|
+
if ((preset.appliesTo?.length ?? 0) > 0 && matchedCount === 0)
|
|
53
|
+
continue;
|
|
47
54
|
if ((preset.appliesTo?.length ?? 0) === 0 && reasons.length === 0) {
|
|
48
55
|
reasons.push('universal preset');
|
|
49
56
|
}
|
|
50
57
|
const confidence = score >= 15 ? 'high' : score >= 9 ? 'medium' : 'low';
|
|
51
58
|
out.push({ preset, score, confidence, reasons });
|
|
52
|
-
// matchedCount is reserved for future tie-breaking; surface in reasons
|
|
53
|
-
// for now so the explanation captures it.
|
|
54
|
-
void matchedCount;
|
|
55
59
|
}
|
|
56
60
|
out.sort((a, b) => b.score - a.score);
|
|
57
61
|
const limit = options.limit ?? 5;
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shrkcrft/presets",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.20",
|
|
4
4
|
"description": "SharkCraft presets: reusable project setups (knowledge/rules/paths/templates/pipelines/docs) that can be applied to a target repo through the CLI.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "SharkCraft contributors",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"main": "./dist/index.js",
|
|
9
|
-
"types": "./dist/index.d.
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
10
|
"exports": {
|
|
11
11
|
".": {
|
|
12
12
|
"types": "./dist/index.d.ts",
|
|
@@ -42,9 +42,9 @@
|
|
|
42
42
|
"typecheck": "tsc --noEmit -p tsconfig.json"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@shrkcrft/core": "^0.1.0-alpha.
|
|
46
|
-
"@shrkcrft/knowledge": "^0.1.0-alpha.
|
|
47
|
-
"@shrkcrft/workspace": "^0.1.0-alpha.
|
|
45
|
+
"@shrkcrft/core": "^0.1.0-alpha.20",
|
|
46
|
+
"@shrkcrft/knowledge": "^0.1.0-alpha.20",
|
|
47
|
+
"@shrkcrft/workspace": "^0.1.0-alpha.20"
|
|
48
48
|
},
|
|
49
49
|
"publishConfig": {
|
|
50
50
|
"access": "public"
|