decantr 0.9.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/AGENTS.md +868 -0
- package/CHANGELOG.md +255 -0
- package/CLAUDE.md +178 -0
- package/LICENSE +21 -0
- package/README.md +229 -0
- package/cli/art.js +127 -0
- package/cli/commands/a11y.js +61 -0
- package/cli/commands/audit.js +225 -0
- package/cli/commands/build.js +38 -0
- package/cli/commands/dev.js +18 -0
- package/cli/commands/doctor.js +197 -0
- package/cli/commands/figma-sync.js +48 -0
- package/cli/commands/figma-tokens.js +55 -0
- package/cli/commands/generate.js +26 -0
- package/cli/commands/init.js +116 -0
- package/cli/commands/lint.js +209 -0
- package/cli/commands/mcp.js +530 -0
- package/cli/commands/migrate.js +175 -0
- package/cli/commands/test.js +38 -0
- package/cli/commands/validate.js +354 -0
- package/cli/index.js +113 -0
- package/package.json +95 -0
- package/reference/atoms.md +517 -0
- package/reference/behaviors.md +384 -0
- package/reference/build-tooling.md +275 -0
- package/reference/color-guidelines.md +965 -0
- package/reference/component-lifecycle.md +137 -0
- package/reference/compound-spacing.md +95 -0
- package/reference/decantation-process.md +499 -0
- package/reference/dev-server-routes.md +93 -0
- package/reference/form-system.md +253 -0
- package/reference/i18n.md +336 -0
- package/reference/icons.md +576 -0
- package/reference/llm-primer.md +953 -0
- package/reference/plugins.md +252 -0
- package/reference/registry-consumption.md +76 -0
- package/reference/router.md +217 -0
- package/reference/shells.md +116 -0
- package/reference/spatial-guidelines.md +541 -0
- package/reference/ssr.md +234 -0
- package/reference/state-data.md +215 -0
- package/reference/state-patterns.md +166 -0
- package/reference/state.md +194 -0
- package/reference/style-system.md +110 -0
- package/reference/tokens.md +460 -0
- package/src/app.js +19 -0
- package/src/chart/_animate.js +266 -0
- package/src/chart/_base.js +109 -0
- package/src/chart/_data.js +209 -0
- package/src/chart/_format.js +106 -0
- package/src/chart/_interact.js +364 -0
- package/src/chart/_palette.js +105 -0
- package/src/chart/_renderer.js +52 -0
- package/src/chart/_scene.js +262 -0
- package/src/chart/_shared.js +371 -0
- package/src/chart/index.js +637 -0
- package/src/chart/layouts/_layout-base.js +328 -0
- package/src/chart/layouts/cartesian.js +148 -0
- package/src/chart/layouts/hierarchy.js +562 -0
- package/src/chart/layouts/polar.js +101 -0
- package/src/chart/renderers/canvas.js +179 -0
- package/src/chart/renderers/svg.js +256 -0
- package/src/chart/renderers/webgpu.js +715 -0
- package/src/chart/types/_type-base.js +26 -0
- package/src/chart/types/area.js +134 -0
- package/src/chart/types/bar.js +173 -0
- package/src/chart/types/box-plot.js +125 -0
- package/src/chart/types/bubble.js +63 -0
- package/src/chart/types/candlestick.js +115 -0
- package/src/chart/types/chord.js +85 -0
- package/src/chart/types/combination.js +108 -0
- package/src/chart/types/funnel.js +68 -0
- package/src/chart/types/gauge.js +163 -0
- package/src/chart/types/heatmap.js +98 -0
- package/src/chart/types/histogram.js +71 -0
- package/src/chart/types/line.js +111 -0
- package/src/chart/types/org-chart.js +93 -0
- package/src/chart/types/pie.js +81 -0
- package/src/chart/types/radar.js +96 -0
- package/src/chart/types/radial.js +68 -0
- package/src/chart/types/range-area.js +55 -0
- package/src/chart/types/range-bar.js +61 -0
- package/src/chart/types/sankey.js +73 -0
- package/src/chart/types/scatter.js +66 -0
- package/src/chart/types/sparkline.js +81 -0
- package/src/chart/types/sunburst.js +69 -0
- package/src/chart/types/swimlane.js +88 -0
- package/src/chart/types/treemap.js +62 -0
- package/src/chart/types/waterfall.js +100 -0
- package/src/components/_base.js +1658 -0
- package/src/components/_behaviors.js +1140 -0
- package/src/components/_primitives.js +534 -0
- package/src/components/_qr-encoder.js +539 -0
- package/src/components/accordion.js +207 -0
- package/src/components/affix.js +62 -0
- package/src/components/alert-dialog.js +75 -0
- package/src/components/alert.js +47 -0
- package/src/components/aspect-ratio.js +24 -0
- package/src/components/avatar-group.js +55 -0
- package/src/components/avatar.js +38 -0
- package/src/components/back-top.js +75 -0
- package/src/components/badge.js +74 -0
- package/src/components/banner.js +68 -0
- package/src/components/breadcrumb.js +162 -0
- package/src/components/button.js +115 -0
- package/src/components/calendar.js +131 -0
- package/src/components/card.js +192 -0
- package/src/components/carousel.js +98 -0
- package/src/components/cascader.js +261 -0
- package/src/components/checkbox.js +80 -0
- package/src/components/chip.js +81 -0
- package/src/components/code-block.js +82 -0
- package/src/components/collapsible.js +50 -0
- package/src/components/color-palette.js +438 -0
- package/src/components/color-picker.js +314 -0
- package/src/components/combobox.js +181 -0
- package/src/components/command.js +174 -0
- package/src/components/comment.js +206 -0
- package/src/components/context-menu.js +76 -0
- package/src/components/data-table.js +724 -0
- package/src/components/date-picker.js +217 -0
- package/src/components/date-range-picker.js +244 -0
- package/src/components/datetime-picker.js +271 -0
- package/src/components/descriptions.js +68 -0
- package/src/components/drawer.js +179 -0
- package/src/components/dropdown.js +88 -0
- package/src/components/empty.js +41 -0
- package/src/components/float-button.js +90 -0
- package/src/components/form.js +106 -0
- package/src/components/hover-card.js +49 -0
- package/src/components/icon.js +87 -0
- package/src/components/image.js +97 -0
- package/src/components/index.js +117 -0
- package/src/components/input-group.js +75 -0
- package/src/components/input-number.js +155 -0
- package/src/components/input-otp.js +178 -0
- package/src/components/input.js +91 -0
- package/src/components/kbd.js +36 -0
- package/src/components/label.js +25 -0
- package/src/components/list.js +118 -0
- package/src/components/masked-input.js +236 -0
- package/src/components/mentions.js +165 -0
- package/src/components/menu.js +259 -0
- package/src/components/message.js +80 -0
- package/src/components/modal.js +147 -0
- package/src/components/navigation-menu.js +166 -0
- package/src/components/notification.js +84 -0
- package/src/components/pagination.js +104 -0
- package/src/components/placeholder.js +132 -0
- package/src/components/popconfirm.js +70 -0
- package/src/components/popover.js +58 -0
- package/src/components/progress.js +61 -0
- package/src/components/qrcode.js +251 -0
- package/src/components/radiogroup.js +120 -0
- package/src/components/range-slider.js +176 -0
- package/src/components/rate.js +186 -0
- package/src/components/resizable.js +83 -0
- package/src/components/result.js +57 -0
- package/src/components/scroll-area.js +43 -0
- package/src/components/segmented.js +97 -0
- package/src/components/select.js +165 -0
- package/src/components/separator.js +31 -0
- package/src/components/shell.js +407 -0
- package/src/components/skeleton.js +39 -0
- package/src/components/slider.js +141 -0
- package/src/components/sortable-list.js +176 -0
- package/src/components/space.js +42 -0
- package/src/components/spinner.js +112 -0
- package/src/components/splitter.js +147 -0
- package/src/components/statistic.js +136 -0
- package/src/components/steps.js +99 -0
- package/src/components/switch.js +95 -0
- package/src/components/table.js +44 -0
- package/src/components/tabs.js +216 -0
- package/src/components/tag.js +115 -0
- package/src/components/textarea.js +82 -0
- package/src/components/time-picker.js +153 -0
- package/src/components/time-range-picker.js +170 -0
- package/src/components/timeline.js +226 -0
- package/src/components/toast.js +71 -0
- package/src/components/toggle.js +213 -0
- package/src/components/tooltip.js +57 -0
- package/src/components/tour.js +159 -0
- package/src/components/transfer.js +163 -0
- package/src/components/tree-select.js +274 -0
- package/src/components/tree.js +141 -0
- package/src/components/typography.js +136 -0
- package/src/components/upload.js +118 -0
- package/src/components/visually-hidden.js +20 -0
- package/src/components/watermark.js +124 -0
- package/src/core/index.js +539 -0
- package/src/core/lifecycle.js +69 -0
- package/src/css/atoms.js +651 -0
- package/src/css/components.js +940 -0
- package/src/css/derive.js +1296 -0
- package/src/css/index.js +265 -0
- package/src/css/runtime.js +268 -0
- package/src/css/styles/addons/bioluminescent.js +93 -0
- package/src/css/styles/addons/clay.js +70 -0
- package/src/css/styles/addons/clean.js +57 -0
- package/src/css/styles/addons/command-center.js +143 -0
- package/src/css/styles/addons/dopamine.js +83 -0
- package/src/css/styles/addons/editorial.js +80 -0
- package/src/css/styles/addons/glassmorphism.js +99 -0
- package/src/css/styles/addons/liquid-glass.js +105 -0
- package/src/css/styles/addons/prismatic.js +100 -0
- package/src/css/styles/addons/retro.js +63 -0
- package/src/css/styles/auradecantism.js +96 -0
- package/src/css/theme-registry.js +444 -0
- package/src/data/entity.js +281 -0
- package/src/data/index.js +13 -0
- package/src/data/persist.js +225 -0
- package/src/data/query.js +839 -0
- package/src/data/realtime.js +299 -0
- package/src/data/url.js +177 -0
- package/src/data/worker.js +134 -0
- package/src/explorer/archetypes.js +243 -0
- package/src/explorer/atoms.js +228 -0
- package/src/explorer/charts.js +497 -0
- package/src/explorer/components.js +129 -0
- package/src/explorer/foundations.js +949 -0
- package/src/explorer/icons.js +178 -0
- package/src/explorer/patterns.js +247 -0
- package/src/explorer/recipes.js +194 -0
- package/src/explorer/shared/pattern-examples.js +1337 -0
- package/src/explorer/shared/showcase-renderer.js +958 -0
- package/src/explorer/shared/spec-table.js +41 -0
- package/src/explorer/shared/usage-links.js +87 -0
- package/src/explorer/shell-config.js +10 -0
- package/src/explorer/shells.js +551 -0
- package/src/explorer/styles.js +161 -0
- package/src/explorer/tokens.js +262 -0
- package/src/explorer/tools.js +525 -0
- package/src/form/index.js +804 -0
- package/src/i18n/index.js +251 -0
- package/src/icons/essential.js +479 -0
- package/src/icons/index.js +53 -0
- package/src/plugins/index.js +282 -0
- package/src/registry/archetypes/content-site.json +71 -0
- package/src/registry/archetypes/docs-explorer.json +23 -0
- package/src/registry/archetypes/ecommerce.json +104 -0
- package/src/registry/archetypes/financial-dashboard.json +77 -0
- package/src/registry/archetypes/index.json +41 -0
- package/src/registry/archetypes/portfolio.json +82 -0
- package/src/registry/archetypes/recipe-community.json +159 -0
- package/src/registry/archetypes/saas-dashboard.json +86 -0
- package/src/registry/architect/cross-cutting.json +45 -0
- package/src/registry/architect/domains/ecommerce.json +294 -0
- package/src/registry/architect/domains/financial-services.json +302 -0
- package/src/registry/architect/index.json +26 -0
- package/src/registry/architect/traits.json +379 -0
- package/src/registry/atoms.json +16 -0
- package/src/registry/chart-showcase.json +160 -0
- package/src/registry/chart.json +136 -0
- package/src/registry/components.json +8616 -0
- package/src/registry/core.json +216 -0
- package/src/registry/css.json +319 -0
- package/src/registry/data.json +135 -0
- package/src/registry/foundations.json +11 -0
- package/src/registry/icons.json +463 -0
- package/src/registry/index.json +101 -0
- package/src/registry/patterns/activity-feed.json +37 -0
- package/src/registry/patterns/article-content.json +27 -0
- package/src/registry/patterns/auth-form.json +37 -0
- package/src/registry/patterns/author-card.json +20 -0
- package/src/registry/patterns/card-grid.json +127 -0
- package/src/registry/patterns/category-nav.json +26 -0
- package/src/registry/patterns/chart-grid.json +36 -0
- package/src/registry/patterns/chat-interface.json +37 -0
- package/src/registry/patterns/checklist-card.json +55 -0
- package/src/registry/patterns/comparison-panel.json +27 -0
- package/src/registry/patterns/component-showcase.json +24 -0
- package/src/registry/patterns/contact-form.json +31 -0
- package/src/registry/patterns/cta-section.json +20 -0
- package/src/registry/patterns/data-table.json +37 -0
- package/src/registry/patterns/detail-header.json +83 -0
- package/src/registry/patterns/detail-panel.json +27 -0
- package/src/registry/patterns/explorer-shell.json +22 -0
- package/src/registry/patterns/filter-bar.json +33 -0
- package/src/registry/patterns/filter-sidebar.json +27 -0
- package/src/registry/patterns/form-sections.json +110 -0
- package/src/registry/patterns/goal-tracker.json +27 -0
- package/src/registry/patterns/hero.json +107 -0
- package/src/registry/patterns/index.json +47 -0
- package/src/registry/patterns/kpi-grid.json +36 -0
- package/src/registry/patterns/media-gallery.json +20 -0
- package/src/registry/patterns/order-history.json +20 -0
- package/src/registry/patterns/pagination.json +19 -0
- package/src/registry/patterns/photo-to-recipe.json +36 -0
- package/src/registry/patterns/pipeline-tracker.json +28 -0
- package/src/registry/patterns/post-list.json +27 -0
- package/src/registry/patterns/pricing-table.json +32 -0
- package/src/registry/patterns/scorecard.json +28 -0
- package/src/registry/patterns/search-bar.json +20 -0
- package/src/registry/patterns/specimen-grid.json +19 -0
- package/src/registry/patterns/stat-card.json +55 -0
- package/src/registry/patterns/stats-bar.json +55 -0
- package/src/registry/patterns/steps-card.json +55 -0
- package/src/registry/patterns/table-of-contents.json +19 -0
- package/src/registry/patterns/testimonials.json +21 -0
- package/src/registry/patterns/timeline.json +27 -0
- package/src/registry/patterns/token-inspector.json +21 -0
- package/src/registry/patterns/wizard.json +27 -0
- package/src/registry/recipe-auradecantism.json +69 -0
- package/src/registry/recipe-clean.json +65 -0
- package/src/registry/recipe-command-center.json +78 -0
- package/src/registry/router.json +73 -0
- package/src/registry/schema/README.md +197 -0
- package/src/registry/skeletons.json +259 -0
- package/src/registry/state.json +137 -0
- package/src/registry/tokens.json +40 -0
- package/src/router/hash.js +17 -0
- package/src/router/history.js +18 -0
- package/src/router/index.js +598 -0
- package/src/ssr/index.js +922 -0
- package/src/state/arrays.js +181 -0
- package/src/state/devtools.js +647 -0
- package/src/state/index.js +498 -0
- package/src/state/middleware.js +288 -0
- package/src/state/scheduler.js +206 -0
- package/src/state/store.js +300 -0
- package/src/tags/index.js +19 -0
- package/src/tannins/auth.js +396 -0
- package/src/test/dom.js +352 -0
- package/src/test/index.js +62 -0
- package/src/test/state.js +306 -0
- package/tools/a11y-audit.js +487 -0
- package/tools/analyzer.js +315 -0
- package/tools/audit.js +706 -0
- package/tools/builder.js +1422 -0
- package/tools/css-extract.js +188 -0
- package/tools/dev-server.js +316 -0
- package/tools/dts-gen.js +1260 -0
- package/tools/figma-components.js +329 -0
- package/tools/figma-patterns.js +516 -0
- package/tools/figma-plugin/code.js +453 -0
- package/tools/figma-plugin/manifest.json +14 -0
- package/tools/figma-plugin/ui.html +268 -0
- package/tools/figma-render.js +293 -0
- package/tools/figma-tokens.js +712 -0
- package/tools/figma-upload.js +318 -0
- package/tools/generate.js +738 -0
- package/tools/icons.js +133 -0
- package/tools/init-templates.js +265 -0
- package/tools/install-hooks.sh +5 -0
- package/tools/migrations/0.5.0.js +53 -0
- package/tools/migrations/0.6.0.js +95 -0
- package/tools/minify.js +170 -0
- package/tools/pre-commit +4 -0
- package/tools/registry.js +662 -0
- package/tools/reset-playground.js +61 -0
- package/tools/starter-templates/content-site/app.js +49 -0
- package/tools/starter-templates/content-site/essence.js +19 -0
- package/tools/starter-templates/content-site/pages.js +31 -0
- package/tools/starter-templates/ecommerce/app.js +50 -0
- package/tools/starter-templates/ecommerce/essence.js +19 -0
- package/tools/starter-templates/ecommerce/pages.js +31 -0
- package/tools/starter-templates/landing-page/app.js +38 -0
- package/tools/starter-templates/landing-page/essence.js +18 -0
- package/tools/starter-templates/landing-page/pages.js +21 -0
- package/tools/starter-templates/portfolio/app.js +45 -0
- package/tools/starter-templates/portfolio/essence.js +19 -0
- package/tools/starter-templates/portfolio/pages.js +33 -0
- package/tools/starter-templates/saas-dashboard/app.js +70 -0
- package/tools/starter-templates/saas-dashboard/essence.js +19 -0
- package/tools/starter-templates/saas-dashboard/pages.js +31 -0
- package/tools/verify-pack.js +203 -0
- package/types/chart.d.ts +77 -0
- package/types/components.d.ts +587 -0
- package/types/core.d.ts +89 -0
- package/types/css.d.ts +149 -0
- package/types/data.d.ts +238 -0
- package/types/form.d.ts +164 -0
- package/types/i18n.d.ts +51 -0
- package/types/icons.d.ts +27 -0
- package/types/index.d.ts +13 -0
- package/types/router.d.ts +116 -0
- package/types/ssr.d.ts +102 -0
- package/types/state.d.ts +83 -0
- package/types/tags.d.ts +62 -0
- package/types/tannins.d.ts +63 -0
- package/types/test.d.ts +48 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { glob } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
|
|
5
|
+
export async function run() {
|
|
6
|
+
const cwd = process.cwd();
|
|
7
|
+
const args = process.argv.slice(3);
|
|
8
|
+
const watch = args.includes('--watch');
|
|
9
|
+
|
|
10
|
+
const testArgs = ['--test'];
|
|
11
|
+
if (watch) testArgs.push('--watch');
|
|
12
|
+
|
|
13
|
+
// Find test files
|
|
14
|
+
const testFiles = [];
|
|
15
|
+
const pattern = join(cwd, 'test', '**', '*.test.js');
|
|
16
|
+
|
|
17
|
+
// Use node:fs glob (Node 22+)
|
|
18
|
+
const { glob: fsGlob } = await import('node:fs/promises');
|
|
19
|
+
for await (const file of fsGlob(pattern)) {
|
|
20
|
+
testFiles.push(file);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (testFiles.length === 0) {
|
|
24
|
+
console.log('No test files found in test/**/*.test.js');
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
testArgs.push(...testFiles);
|
|
29
|
+
|
|
30
|
+
const child = spawn('node', testArgs, {
|
|
31
|
+
cwd,
|
|
32
|
+
stdio: 'inherit'
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
child.on('exit', (code) => {
|
|
36
|
+
process.exit(code || 0);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
import { readFile, readdir } from 'node:fs/promises';
|
|
2
|
+
import { join, dirname } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
|
|
5
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
|
|
7
|
+
export async function run() {
|
|
8
|
+
const cwd = process.cwd();
|
|
9
|
+
const essencePath = join(cwd, 'decantr.essence.json');
|
|
10
|
+
const configPath = join(cwd, 'decantr.config.json');
|
|
11
|
+
const registryRoot = join(__dirname, '..', '..', 'src', 'registry');
|
|
12
|
+
|
|
13
|
+
// Read essence
|
|
14
|
+
let essence;
|
|
15
|
+
try {
|
|
16
|
+
essence = JSON.parse(await readFile(essencePath, 'utf-8'));
|
|
17
|
+
} catch (e) {
|
|
18
|
+
console.error(' ✗ decantr.essence.json not found or invalid JSON');
|
|
19
|
+
console.error(' Run the CLARIFY stage to create your project essence.');
|
|
20
|
+
process.exitCode = 1;
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const errors = [];
|
|
25
|
+
const warnings = [];
|
|
26
|
+
|
|
27
|
+
// Detect schema form
|
|
28
|
+
const isSectioned = Array.isArray(essence.sections);
|
|
29
|
+
const isSimple = typeof essence.terroir === 'string' || essence.terroir === null;
|
|
30
|
+
|
|
31
|
+
if (!isSectioned && !isSimple) {
|
|
32
|
+
errors.push('Essence must have either "terroir" (simple) or "sections" (sectioned)');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Known archetypes
|
|
36
|
+
const KNOWN_ARCHETYPES = ['ecommerce', 'saas-dashboard', 'portfolio', 'content-site', 'docs-explorer', 'financial-dashboard', 'recipe-community'];
|
|
37
|
+
|
|
38
|
+
// Known styles
|
|
39
|
+
const KNOWN_STYLES = ['auradecantism', 'clean', 'retro', 'glassmorphism', 'command-center'];
|
|
40
|
+
|
|
41
|
+
// Validate vintage
|
|
42
|
+
function validateVintage(vintage, prefix) {
|
|
43
|
+
if (!vintage) return;
|
|
44
|
+
if (vintage.style && !KNOWN_STYLES.includes(vintage.style)) {
|
|
45
|
+
warnings.push(`${prefix}vintage.style "${vintage.style}" is not a built-in style (may be registered via registerStyle()). Built-in: ${KNOWN_STYLES.join(', ')}`);
|
|
46
|
+
}
|
|
47
|
+
if (vintage.mode && !['light', 'dark', 'auto'].includes(vintage.mode)) {
|
|
48
|
+
errors.push(`${prefix}vintage.mode must be light|dark|auto, got "${vintage.mode}"`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Valid responsive breakpoints for blend items
|
|
53
|
+
const VALID_BREAKPOINTS = ['sm', 'md', 'lg', 'xl', '2xl'];
|
|
54
|
+
|
|
55
|
+
// Validate blend item depth (Gap 2.3)
|
|
56
|
+
function validateBlendItems(blend, pageId, prefix) {
|
|
57
|
+
if (!Array.isArray(blend)) return;
|
|
58
|
+
for (let i = 0; i < blend.length; i++) {
|
|
59
|
+
const item = blend[i];
|
|
60
|
+
if (typeof item === 'string') continue;
|
|
61
|
+
if (item && typeof item === 'object' && !item.cols && item.pattern) continue; // v2 preset ref
|
|
62
|
+
|
|
63
|
+
if (item && typeof item === 'object' && item.cols) {
|
|
64
|
+
// Validate breakpoint
|
|
65
|
+
if (item.at != null) {
|
|
66
|
+
if (!VALID_BREAKPOINTS.includes(item.at)) {
|
|
67
|
+
errors.push(`${prefix}Page "${pageId}": blend row ${i} has invalid breakpoint "${item.at}". Valid: ${VALID_BREAKPOINTS.join(', ')}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Validate span values
|
|
72
|
+
if (item.span != null) {
|
|
73
|
+
if (typeof item.span !== 'object' || Array.isArray(item.span)) {
|
|
74
|
+
errors.push(`${prefix}Page "${pageId}": blend row ${i} "span" must be an object mapping column IDs to weights`);
|
|
75
|
+
} else {
|
|
76
|
+
for (const [key, value] of Object.entries(item.span)) {
|
|
77
|
+
// Validate span values are positive integers
|
|
78
|
+
if (!Number.isInteger(value) || value < 1) {
|
|
79
|
+
errors.push(`${prefix}Page "${pageId}": blend row ${i} span["${key}"] must be a positive integer, got ${JSON.stringify(value)}`);
|
|
80
|
+
}
|
|
81
|
+
// Validate span keys match cols entries
|
|
82
|
+
if (!item.cols.includes(key)) {
|
|
83
|
+
errors.push(`${prefix}Page "${pageId}": blend row ${i} span key "${key}" does not match any cols entry. Cols: ${item.cols.join(', ')}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Validate structure entries
|
|
93
|
+
function validateStructure(structure, prefix) {
|
|
94
|
+
if (!Array.isArray(structure)) return;
|
|
95
|
+
for (const page of structure) {
|
|
96
|
+
if (!page.id) errors.push(`${prefix}structure entry missing "id"`);
|
|
97
|
+
if (!page.skeleton) warnings.push(`${prefix}structure entry "${page.id || '?'}" missing "skeleton"`);
|
|
98
|
+
if (!page.blend && !page.patterns) warnings.push(`${prefix}structure entry "${page.id || '?'}" missing "blend"`);
|
|
99
|
+
// Validate blend item depth
|
|
100
|
+
if (page.blend) validateBlendItems(page.blend, page.id || '?', prefix);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (isSectioned) {
|
|
105
|
+
// Sectioned validation
|
|
106
|
+
const sectionPaths = new Set();
|
|
107
|
+
for (const section of essence.sections) {
|
|
108
|
+
if (!section.id) errors.push('Section missing "id"');
|
|
109
|
+
if (!section.path) errors.push(`Section "${section.id || '?'}" missing "path"`);
|
|
110
|
+
if (section.path && sectionPaths.has(section.path)) {
|
|
111
|
+
errors.push(`Duplicate section path: "${section.path}"`);
|
|
112
|
+
}
|
|
113
|
+
if (section.path) sectionPaths.add(section.path);
|
|
114
|
+
|
|
115
|
+
if (section.terroir && !KNOWN_ARCHETYPES.includes(section.terroir)) {
|
|
116
|
+
errors.push(`Section "${section.id}": terroir "${section.terroir}" is not a known archetype`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
validateVintage(section.vintage, `Section "${section.id || '?'}": `);
|
|
120
|
+
validateStructure(section.structure, `Section "${section.id || '?'}": `);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Check shared_tannins not duplicated in sections
|
|
124
|
+
if (Array.isArray(essence.shared_tannins)) {
|
|
125
|
+
for (const section of essence.sections) {
|
|
126
|
+
if (Array.isArray(section.tannins)) {
|
|
127
|
+
for (const t of section.tannins) {
|
|
128
|
+
if (essence.shared_tannins.includes(t)) {
|
|
129
|
+
warnings.push(`Tannin "${t}" is in both shared_tannins and section "${section.id}"`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
} else {
|
|
136
|
+
// Simple validation
|
|
137
|
+
if (essence.terroir && !KNOWN_ARCHETYPES.includes(essence.terroir)) {
|
|
138
|
+
errors.push(`terroir "${essence.terroir}" is not a known archetype. Known: ${KNOWN_ARCHETYPES.join(', ')}`);
|
|
139
|
+
}
|
|
140
|
+
validateVintage(essence.vintage, '');
|
|
141
|
+
validateStructure(essence.structure, '');
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Vessel validation
|
|
145
|
+
if (essence.vessel) {
|
|
146
|
+
if (essence.vessel.type && !['spa', 'mpa'].includes(essence.vessel.type)) {
|
|
147
|
+
warnings.push(`vessel.type "${essence.vessel.type}" is unusual (expected spa|mpa)`);
|
|
148
|
+
}
|
|
149
|
+
if (essence.vessel.routing && !['hash', 'history'].includes(essence.vessel.routing)) {
|
|
150
|
+
errors.push(`vessel.routing must be hash|history, got "${essence.vessel.routing}"`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Version field validation (Gap 2.5)
|
|
155
|
+
if (essence.version != null) {
|
|
156
|
+
if (typeof essence.version !== 'string') {
|
|
157
|
+
errors.push('version must be a string (semver format, e.g. "1.0.0")');
|
|
158
|
+
} else if (!/^\d+\.\d+\.\d+$/.test(essence.version)) {
|
|
159
|
+
warnings.push(`version "${essence.version}" is not standard semver (expected "X.Y.Z")`);
|
|
160
|
+
}
|
|
161
|
+
} else {
|
|
162
|
+
warnings.push('No "version" field in essence. Consider adding a semver version (e.g. "1.0.0") to track essence evolution.');
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Cork validation
|
|
166
|
+
if (essence.cork && typeof essence.cork !== 'object') {
|
|
167
|
+
errors.push('cork must be an object');
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Cross-reference with config
|
|
171
|
+
try {
|
|
172
|
+
const config = JSON.parse(await readFile(configPath, 'utf-8'));
|
|
173
|
+
const essenceStyle = isSectioned ? null : essence.vintage?.style;
|
|
174
|
+
const essenceMode = isSectioned ? null : essence.vintage?.mode;
|
|
175
|
+
|
|
176
|
+
if (essenceStyle && config.style && essenceStyle !== config.style) {
|
|
177
|
+
warnings.push(`Style mismatch: essence="${essenceStyle}", config="${config.style}". Essence is authoritative.`);
|
|
178
|
+
}
|
|
179
|
+
if (essenceMode && config.mode && essenceMode !== config.mode) {
|
|
180
|
+
warnings.push(`Mode mismatch: essence="${essenceMode}", config="${config.mode}". Essence is authoritative.`);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Validate icons config
|
|
184
|
+
if (config.icons != null) {
|
|
185
|
+
if (typeof config.icons !== 'object' || Array.isArray(config.icons)) {
|
|
186
|
+
errors.push('icons must be an object');
|
|
187
|
+
} else if (config.icons.library != null && typeof config.icons.library !== 'string') {
|
|
188
|
+
errors.push('icons.library must be a string');
|
|
189
|
+
} else if (config.icons.library) {
|
|
190
|
+
const KNOWN_LIBS = ['lucide', 'heroicons', 'material', 'fontawesome', 'phosphor', 'tabler', 'feather'];
|
|
191
|
+
if (!KNOWN_LIBS.includes(config.icons.library)) {
|
|
192
|
+
warnings.push(`icons.library "${config.icons.library}" is not a recognized library (known: ${KNOWN_LIBS.join(', ')}). LLM code generation will use it as-is.`);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
} catch {
|
|
197
|
+
// No config file — that's fine
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// ─── Archetype inheritance validation ─────────────────────────
|
|
201
|
+
// If an archetype uses `extends`, verify the chain is valid
|
|
202
|
+
try {
|
|
203
|
+
const archetypeIdx = JSON.parse(await readFile(join(registryRoot, 'archetypes', 'index.json'), 'utf-8'));
|
|
204
|
+
const knownArchetypeIds = new Set(Object.keys(archetypeIdx.archetypes || {}));
|
|
205
|
+
|
|
206
|
+
// Load all archetypes to check extends chains
|
|
207
|
+
const archetypeData = {};
|
|
208
|
+
for (const [aid, meta] of Object.entries(archetypeIdx.archetypes || {})) {
|
|
209
|
+
try {
|
|
210
|
+
archetypeData[aid] = JSON.parse(await readFile(join(registryRoot, 'archetypes', meta.file), 'utf-8'));
|
|
211
|
+
} catch { /* skip unreadable */ }
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
for (const [aid, arch] of Object.entries(archetypeData)) {
|
|
215
|
+
if (!arch.extends) continue;
|
|
216
|
+
|
|
217
|
+
// Check that extends references an existing archetype
|
|
218
|
+
if (!knownArchetypeIds.has(arch.extends)) {
|
|
219
|
+
errors.push(`Archetype "${aid}": extends "${arch.extends}" is not a known archetype. Known: ${[...knownArchetypeIds].join(', ')}`);
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Check for circular inheritance by following the chain
|
|
224
|
+
const visited = new Set();
|
|
225
|
+
let current = aid;
|
|
226
|
+
let depth = 0;
|
|
227
|
+
while (current && depth < 10) {
|
|
228
|
+
if (visited.has(current)) {
|
|
229
|
+
errors.push(`Archetype "${aid}": circular inheritance detected: ${[...visited, current].join(' → ')}`);
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
visited.add(current);
|
|
233
|
+
const currentArch = archetypeData[current];
|
|
234
|
+
current = currentArch?.extends || null;
|
|
235
|
+
depth++;
|
|
236
|
+
}
|
|
237
|
+
if (depth >= 10) {
|
|
238
|
+
errors.push(`Archetype "${aid}": inheritance chain exceeds depth limit (10)`);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
} catch {
|
|
242
|
+
// Archetype registry not accessible — skip inheritance validation
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// ─── Generate prerequisites ───────────────────────────────────
|
|
246
|
+
|
|
247
|
+
// Collect all structures for validation
|
|
248
|
+
const allStructures = isSectioned
|
|
249
|
+
? essence.sections.flatMap(s => s.structure || [])
|
|
250
|
+
: (essence.structure || []);
|
|
251
|
+
|
|
252
|
+
// Warn on empty structure
|
|
253
|
+
if (allStructures.length === 0) {
|
|
254
|
+
warnings.push('No pages in structure — `decantr generate` will have nothing to produce');
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Check patterns in blend arrays exist in registry (supports v2 preset references)
|
|
258
|
+
try {
|
|
259
|
+
const patternFiles = await readdir(join(registryRoot, 'patterns'));
|
|
260
|
+
const knownPatterns = new Set(patternFiles.filter(f => f.endsWith('.json') && f !== 'index.json').map(f => f.replace('.json', '')));
|
|
261
|
+
|
|
262
|
+
// Load pattern index for preset validation
|
|
263
|
+
let patternIndex = {};
|
|
264
|
+
try {
|
|
265
|
+
const indexData = JSON.parse(await readFile(join(registryRoot, 'patterns', 'index.json'), 'utf-8'));
|
|
266
|
+
patternIndex = indexData.patterns || {};
|
|
267
|
+
} catch { /* skip */ }
|
|
268
|
+
|
|
269
|
+
function validateBlendRef(ref, pageId) {
|
|
270
|
+
if (typeof ref === 'string') {
|
|
271
|
+
if (!knownPatterns.has(ref)) {
|
|
272
|
+
warnings.push(`Page "${pageId}": pattern "${ref}" in blend not found in registry`);
|
|
273
|
+
}
|
|
274
|
+
} else if (ref && ref.pattern) {
|
|
275
|
+
// v2 preset reference: { pattern, preset, as }
|
|
276
|
+
if (!knownPatterns.has(ref.pattern)) {
|
|
277
|
+
warnings.push(`Page "${pageId}": pattern "${ref.pattern}" in blend not found in registry`);
|
|
278
|
+
} else if (ref.preset && patternIndex[ref.pattern]?.presets) {
|
|
279
|
+
if (!patternIndex[ref.pattern].presets.includes(ref.preset)) {
|
|
280
|
+
warnings.push(`Page "${pageId}": preset "${ref.preset}" not found on pattern "${ref.pattern}". Known presets: ${patternIndex[ref.pattern].presets.join(', ')}`);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
for (const page of allStructures) {
|
|
287
|
+
const blend = page.blend || page.patterns || [];
|
|
288
|
+
for (const item of blend) {
|
|
289
|
+
if (typeof item === 'string') {
|
|
290
|
+
validateBlendRef(item, page.id);
|
|
291
|
+
} else if (item.pattern) {
|
|
292
|
+
// v2 preset reference at top level
|
|
293
|
+
validateBlendRef(item, page.id);
|
|
294
|
+
} else if (item.cols) {
|
|
295
|
+
for (const col of item.cols) {
|
|
296
|
+
validateBlendRef(col, page.id);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
} catch {
|
|
302
|
+
// Registry not accessible — skip pattern validation
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Check skeletons referenced exist
|
|
306
|
+
try {
|
|
307
|
+
const skeletonsData = JSON.parse(await readFile(join(registryRoot, 'skeletons.json'), 'utf-8'));
|
|
308
|
+
const knownSkeletons = new Set(Object.keys(skeletonsData.skeletons || {}));
|
|
309
|
+
|
|
310
|
+
for (const page of allStructures) {
|
|
311
|
+
if (page.skeleton && !knownSkeletons.has(page.skeleton)) {
|
|
312
|
+
warnings.push(`Page "${page.id}": skeleton "${page.skeleton}" not found in skeletons.json`);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
} catch {
|
|
316
|
+
// skeletons.json not accessible — skip
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// Check recipe referenced in vintage exists
|
|
320
|
+
const allVintages = isSectioned
|
|
321
|
+
? essence.sections.map(s => s.vintage).filter(Boolean)
|
|
322
|
+
: (essence.vintage ? [essence.vintage] : []);
|
|
323
|
+
|
|
324
|
+
try {
|
|
325
|
+
const registryFiles = await readdir(registryRoot);
|
|
326
|
+
const knownRecipes = new Set(
|
|
327
|
+
registryFiles.filter(f => f.startsWith('recipe-') && f.endsWith('.json')).map(f => f.replace('recipe-', '').replace('.json', ''))
|
|
328
|
+
);
|
|
329
|
+
|
|
330
|
+
for (const vintage of allVintages) {
|
|
331
|
+
if (vintage.recipe && !knownRecipes.has(vintage.recipe)) {
|
|
332
|
+
warnings.push(`Recipe "${vintage.recipe}" referenced in vintage not found in registry. Known: ${[...knownRecipes].join(', ')}`);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
} catch {
|
|
336
|
+
// Registry not accessible — skip
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Report
|
|
340
|
+
if (errors.length === 0 && warnings.length === 0) {
|
|
341
|
+
const mode = isSectioned ? `sectioned (${essence.sections.length} sections)` : `simple (${essence.terroir || 'unset'})`;
|
|
342
|
+
console.log(` ✓ Essence valid — ${mode}`);
|
|
343
|
+
} else {
|
|
344
|
+
if (errors.length > 0) {
|
|
345
|
+
console.error(`\n ${errors.length} error(s):`);
|
|
346
|
+
for (const e of errors) console.error(` ✗ ${e}`);
|
|
347
|
+
}
|
|
348
|
+
if (warnings.length > 0) {
|
|
349
|
+
console.log(`\n ${warnings.length} warning(s):`);
|
|
350
|
+
for (const w of warnings) console.log(` ⚠ ${w}`);
|
|
351
|
+
}
|
|
352
|
+
if (errors.length > 0) process.exitCode = 1;
|
|
353
|
+
}
|
|
354
|
+
}
|
package/cli/index.js
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { parseArgs } from 'node:util';
|
|
4
|
+
import { readFile } from 'node:fs/promises';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
import { loadPlugins, runHook } from '../src/plugins/index.js';
|
|
7
|
+
|
|
8
|
+
const { positionals } = parseArgs({ allowPositionals: true, strict: false });
|
|
9
|
+
const command = positionals[0];
|
|
10
|
+
|
|
11
|
+
// Load project config and plugins for commands that benefit from them
|
|
12
|
+
const cwd = process.cwd();
|
|
13
|
+
let _config = null;
|
|
14
|
+
|
|
15
|
+
async function getConfig() {
|
|
16
|
+
if (_config) return _config;
|
|
17
|
+
try {
|
|
18
|
+
const raw = await readFile(join(cwd, 'decantr.config.json'), 'utf-8');
|
|
19
|
+
_config = JSON.parse(raw);
|
|
20
|
+
} catch {
|
|
21
|
+
_config = {};
|
|
22
|
+
}
|
|
23
|
+
// Load plugins from config
|
|
24
|
+
await loadPlugins(_config, { cwd });
|
|
25
|
+
return _config;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
switch (command) {
|
|
29
|
+
case 'init':
|
|
30
|
+
await import('./commands/init.js').then(m => m.run());
|
|
31
|
+
break;
|
|
32
|
+
case 'dev':
|
|
33
|
+
await getConfig();
|
|
34
|
+
await runHook('onDev', { cwd, command });
|
|
35
|
+
await import('./commands/dev.js').then(m => m.run());
|
|
36
|
+
break;
|
|
37
|
+
case 'build':
|
|
38
|
+
await getConfig();
|
|
39
|
+
await runHook('onBuild', { cwd, command });
|
|
40
|
+
await import('./commands/build.js').then(m => m.run());
|
|
41
|
+
break;
|
|
42
|
+
case 'test':
|
|
43
|
+
await import('./commands/test.js').then(m => m.run());
|
|
44
|
+
break;
|
|
45
|
+
case 'validate':
|
|
46
|
+
await import('./commands/validate.js').then(m => m.run());
|
|
47
|
+
break;
|
|
48
|
+
case 'lint':
|
|
49
|
+
await import('./commands/lint.js').then(m => m.run());
|
|
50
|
+
break;
|
|
51
|
+
case 'a11y':
|
|
52
|
+
await import('./commands/a11y.js').then(m => m.run());
|
|
53
|
+
break;
|
|
54
|
+
case 'audit':
|
|
55
|
+
if (process.argv.includes('--a11y')) {
|
|
56
|
+
await import('./commands/a11y.js').then(m => m.run());
|
|
57
|
+
} else {
|
|
58
|
+
await import('./commands/audit.js').then(m => m.run());
|
|
59
|
+
}
|
|
60
|
+
break;
|
|
61
|
+
case 'generate':
|
|
62
|
+
await getConfig();
|
|
63
|
+
await runHook('onGenerate', { cwd, command });
|
|
64
|
+
await import('./commands/generate.js').then(m => m.run());
|
|
65
|
+
break;
|
|
66
|
+
case 'mcp':
|
|
67
|
+
await import('./commands/mcp.js').then(m => m.run());
|
|
68
|
+
break;
|
|
69
|
+
case 'figma:tokens':
|
|
70
|
+
await import('./commands/figma-tokens.js').then(m => m.run());
|
|
71
|
+
break;
|
|
72
|
+
case 'figma:sync':
|
|
73
|
+
await import('./commands/figma-sync.js').then(m => m.run());
|
|
74
|
+
break;
|
|
75
|
+
case 'migrate':
|
|
76
|
+
await import('./commands/migrate.js').then(m => m.run());
|
|
77
|
+
break;
|
|
78
|
+
case 'doctor':
|
|
79
|
+
await import('./commands/doctor.js').then(m => m.run());
|
|
80
|
+
break;
|
|
81
|
+
default: {
|
|
82
|
+
const { art } = await import('./art.js');
|
|
83
|
+
console.log(art());
|
|
84
|
+
console.log(`
|
|
85
|
+
\x1b[1mdecantr\x1b[0m v0.9.0 \x1b[2m— AI-first web framework\x1b[0m
|
|
86
|
+
|
|
87
|
+
\x1b[1mCommands:\x1b[0m
|
|
88
|
+
init Create a new decantr project
|
|
89
|
+
dev Start development server
|
|
90
|
+
build Build for production
|
|
91
|
+
test Run tests
|
|
92
|
+
validate Validate decantr.essence.json
|
|
93
|
+
lint Code quality gates (atoms, essence drift, inline styles)
|
|
94
|
+
generate Generate code from decantr.essence.json
|
|
95
|
+
a11y Accessibility audit (8 WCAG rules, static analysis)
|
|
96
|
+
audit Audit project: framework coverage, quality, bundle size
|
|
97
|
+
mcp Start MCP server (stdio transport) for AI tool integration
|
|
98
|
+
migrate Migrate decantr.essence.json between versions
|
|
99
|
+
figma:tokens Export design tokens in W3C DTCG / Figma format
|
|
100
|
+
doctor Check project health and environment
|
|
101
|
+
figma:sync Push tokens to Figma file via REST API
|
|
102
|
+
|
|
103
|
+
\x1b[1mUsage:\x1b[0m
|
|
104
|
+
npx decantr init
|
|
105
|
+
npx decantr dev
|
|
106
|
+
npx decantr build
|
|
107
|
+
npx decantr test [--watch]
|
|
108
|
+
npx decantr generate [--force] [--dry-run] [--page <id>]
|
|
109
|
+
npx decantr migrate [--dry-run] [--target=<version>]
|
|
110
|
+
`);
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "decantr",
|
|
3
|
+
"version": "0.9.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "AI-first web framework with signal-based reactivity, atomic CSS, and a structured registry of 100+ components.",
|
|
6
|
+
"homepage": "https://decantr.ai",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/decantr-ai/decantr"
|
|
10
|
+
},
|
|
11
|
+
"author": "David Aimi",
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"keywords": [
|
|
14
|
+
"web-framework",
|
|
15
|
+
"ai-first",
|
|
16
|
+
"mcp",
|
|
17
|
+
"mcp-server",
|
|
18
|
+
"components",
|
|
19
|
+
"design-system",
|
|
20
|
+
"atomic-css"
|
|
21
|
+
],
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=20.0.0"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"src/",
|
|
27
|
+
"cli/",
|
|
28
|
+
"tools/",
|
|
29
|
+
"types/",
|
|
30
|
+
"reference/",
|
|
31
|
+
"AGENTS.md",
|
|
32
|
+
"CLAUDE.md",
|
|
33
|
+
"CHANGELOG.md",
|
|
34
|
+
"README.md",
|
|
35
|
+
"LICENSE"
|
|
36
|
+
],
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"mcpName": "decantr.ai/decantr",
|
|
41
|
+
"bin": {
|
|
42
|
+
"decantr": "./cli/index.js"
|
|
43
|
+
},
|
|
44
|
+
"scripts": {
|
|
45
|
+
"dev": "decantr dev",
|
|
46
|
+
"build": "decantr build",
|
|
47
|
+
"test": "decantr test"
|
|
48
|
+
},
|
|
49
|
+
"exports": {
|
|
50
|
+
"./core": "./src/core/index.js",
|
|
51
|
+
"./tags": "./src/tags/index.js",
|
|
52
|
+
"./css": "./src/css/index.js",
|
|
53
|
+
"./state": "./src/state/index.js",
|
|
54
|
+
"./state/store": "./src/state/store.js",
|
|
55
|
+
"./state/arrays": "./src/state/arrays.js",
|
|
56
|
+
"./state/devtools": "./src/state/devtools.js",
|
|
57
|
+
"./state/middleware": "./src/state/middleware.js",
|
|
58
|
+
"./data": "./src/data/index.js",
|
|
59
|
+
"./router": "./src/router/index.js",
|
|
60
|
+
"./components": "./src/components/index.js",
|
|
61
|
+
"./form": "./src/form/index.js",
|
|
62
|
+
"./chart": "./src/chart/index.js",
|
|
63
|
+
"./test": "./src/test/index.js",
|
|
64
|
+
"./plugins": "./src/plugins/index.js",
|
|
65
|
+
"./i18n": "./src/i18n/index.js",
|
|
66
|
+
"./ssr": "./src/ssr/index.js",
|
|
67
|
+
"./tannins/auth": "./src/tannins/auth.js",
|
|
68
|
+
"./styles/clean": "./src/css/styles/addons/clean.js",
|
|
69
|
+
"./styles/retro": "./src/css/styles/addons/retro.js",
|
|
70
|
+
"./styles/glassmorphism": "./src/css/styles/addons/glassmorphism.js",
|
|
71
|
+
"./styles/command-center": "./src/css/styles/addons/command-center.js",
|
|
72
|
+
"./styles/clay": "./src/css/styles/addons/clay.js",
|
|
73
|
+
"./styles/liquid-glass": "./src/css/styles/addons/liquid-glass.js",
|
|
74
|
+
"./styles/dopamine": "./src/css/styles/addons/dopamine.js",
|
|
75
|
+
"./styles/prismatic": "./src/css/styles/addons/prismatic.js",
|
|
76
|
+
"./styles/bioluminescent": "./src/css/styles/addons/bioluminescent.js",
|
|
77
|
+
"./styles/editorial": "./src/css/styles/addons/editorial.js",
|
|
78
|
+
"./explorer/patterns.js": "./src/explorer/patterns.js",
|
|
79
|
+
"./explorer/icons.js": "./src/explorer/icons.js",
|
|
80
|
+
"./explorer/tokens.js": "./src/explorer/tokens.js",
|
|
81
|
+
"./explorer/foundations.js": "./src/explorer/foundations.js",
|
|
82
|
+
"./explorer/archetypes.js": "./src/explorer/archetypes.js",
|
|
83
|
+
"./explorer/charts.js": "./src/explorer/charts.js",
|
|
84
|
+
"./explorer/shells.js": "./src/explorer/shells.js",
|
|
85
|
+
"./explorer/recipes.js": "./src/explorer/recipes.js",
|
|
86
|
+
"./explorer/tools.js": "./src/explorer/tools.js",
|
|
87
|
+
"./explorer/components.js": "./src/explorer/components.js",
|
|
88
|
+
"./explorer/atoms.js": "./src/explorer/atoms.js",
|
|
89
|
+
"./explorer/styles.js": "./src/explorer/styles.js"
|
|
90
|
+
},
|
|
91
|
+
"sideEffects": false,
|
|
92
|
+
"dependencies": {
|
|
93
|
+
"@modelcontextprotocol/sdk": "^1.27.1"
|
|
94
|
+
}
|
|
95
|
+
}
|