@cronus-ui/stack 0.6.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/dist/schema.js ADDED
@@ -0,0 +1,133 @@
1
+ import { catalog } from "./catalog.js";
2
+ import { STACK_BUILDER_GENERATOR, STACK_CREATE_ALIAS, STACK_CREATE_PACKAGE } from "./constants.js";
3
+ export const STACK_SCHEMA_VERSION = 1;
4
+ export const STACK_SCHEMA_ID = "https://cronus.dev/schema/stack-1.json";
5
+ export const STACK_GENERATOR_PACKAGE = STACK_CREATE_PACKAGE;
6
+ export const STACK_BUILDER_METADATA = {
7
+ name: "Cronus Stack Builder",
8
+ statusLabel: "Stable",
9
+ route: "/stack",
10
+ docsRoute: "/docs/stack-builder",
11
+ schemaId: STACK_SCHEMA_ID,
12
+ schemaVersion: STACK_SCHEMA_VERSION,
13
+ generatorPackage: STACK_GENERATOR_PACKAGE,
14
+ generatorCreateAlias: STACK_CREATE_ALIAS,
15
+ generatorPackageExistsInRepo: true,
16
+ generatorTruth: "This repository ships create-cronus-stack; bun create cronus-stack@latest resolves to that generator package after publish.",
17
+ artifacts: ["Scaffolding command", "KICKOFF.md", "stack.json"],
18
+ };
19
+ function categorySchema(category) {
20
+ if (category.kind === "toggle") {
21
+ return {
22
+ type: "boolean",
23
+ description: category.description ?? category.title,
24
+ };
25
+ }
26
+ const optionIds = category.options.map((option) => option.id);
27
+ if (category.kind === "multi") {
28
+ return {
29
+ type: "array",
30
+ description: category.description ?? category.title,
31
+ uniqueItems: true,
32
+ items: {
33
+ type: "string",
34
+ enum: optionIds,
35
+ },
36
+ };
37
+ }
38
+ return {
39
+ type: "string",
40
+ description: category.description ?? category.title,
41
+ enum: optionIds,
42
+ };
43
+ }
44
+ const stackProperties = Object.fromEntries(catalog.map((category) => [category.id, categorySchema(category)]));
45
+ export const STACK_SCHEMA = {
46
+ $schema: "https://json-schema.org/draft/2020-12/schema",
47
+ $id: STACK_SCHEMA_ID,
48
+ title: "Cronus Stack Builder snapshot",
49
+ description: "A machine-readable snapshot emitted by the Cronus Stack Builder.",
50
+ type: "object",
51
+ additionalProperties: false,
52
+ required: ["$schema", "version", "name", "generator", "stack"],
53
+ properties: {
54
+ $schema: {
55
+ const: STACK_SCHEMA_ID,
56
+ description: "Schema identifier for this Stack Builder snapshot.",
57
+ },
58
+ version: {
59
+ const: STACK_SCHEMA_VERSION,
60
+ description: "Schema version for the emitted stack.json file.",
61
+ },
62
+ name: {
63
+ type: "string",
64
+ pattern: "^[a-z0-9]([a-z0-9-]{0,62}[a-z0-9])?$",
65
+ description: "Sanitized project slug.",
66
+ },
67
+ generator: {
68
+ const: STACK_BUILDER_GENERATOR,
69
+ description: "The product surface that emitted this snapshot.",
70
+ },
71
+ stack: {
72
+ type: "object",
73
+ additionalProperties: false,
74
+ required: catalog.map((category) => category.id),
75
+ properties: stackProperties,
76
+ },
77
+ },
78
+ };
79
+ export const STACK_SCHEMA_EXAMPLE = {
80
+ $schema: STACK_SCHEMA_ID,
81
+ version: STACK_SCHEMA_VERSION,
82
+ name: "my-cronus-app",
83
+ generator: STACK_BUILDER_GENERATOR,
84
+ stack: {
85
+ web: "web-next",
86
+ backend: "backend-none",
87
+ runtime: "runtime-bun",
88
+ api: "api-none",
89
+ database: "db-none",
90
+ orm: "orm-none",
91
+ dbSetup: "dbsetup-basic",
92
+ auth: "auth-none",
93
+ payments: "pay-none",
94
+ ui: "ui-cronus",
95
+ assistants: ["ai-claude-code"],
96
+ mcp: [],
97
+ skills: [],
98
+ vibe: false,
99
+ deploy: "deploy-none",
100
+ packageManager: "pm-bun",
101
+ addons: [],
102
+ naming: "naming-kebab",
103
+ structure: "structure-src",
104
+ importAlias: "import-alias",
105
+ commitStyle: "commit-conventional",
106
+ tsStrict: "ts-strict",
107
+ git: true,
108
+ install: true,
109
+ },
110
+ };
111
+ export const STACK_SCHEMA_FIELD_SUMMARY = [
112
+ {
113
+ field: "$schema",
114
+ description: "Pins the snapshot to the current Stack Builder schema.",
115
+ },
116
+ {
117
+ field: "version",
118
+ description: "Version number for migrations when the snapshot contract changes.",
119
+ },
120
+ {
121
+ field: "name",
122
+ description: "Sanitized project slug used by the preview command and kickoff docs.",
123
+ },
124
+ {
125
+ field: "generator",
126
+ description: `Always ${STACK_BUILDER_GENERATOR} for artifacts emitted by this builder.`,
127
+ },
128
+ {
129
+ field: "stack",
130
+ description: "Resolved category selections after all requires, conflicts, and defaults apply.",
131
+ },
132
+ ];
133
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1,128 @@
1
+ /**
2
+ * The Cronus Stack Builder model — a Better-T-Stack-class stack configurator.
3
+ *
4
+ * The whole builder is driven by a single declarative {@link Catalog}: a list of
5
+ * {@link Category}, each holding {@link Option}s that wire up to each other via
6
+ * `requires` / `conflicts` / `implies` / `recommends`. The pure resolver in
7
+ * `engine.ts` turns a {@link Selection} (what the user picked) into a fully
8
+ * resolved, valid {@link StackConfig} plus per-option availability.
9
+ *
10
+ * Option ids are GLOBALLY UNIQUE (e.g. "db-none", "orm-drizzle", "web-next") so
11
+ * cross-category constraints can reference them directly.
12
+ */
13
+ /** A short status flag rendered as a pill on an option. */
14
+ export type Badge = "beta" | "new" | "experimental" | "gated";
15
+ /**
16
+ * How a category is selected:
17
+ * - "single": exactly one option id (radio).
18
+ * - "multi": zero or more option ids (checkboxes).
19
+ * - "toggle": a boolean (on/off switch).
20
+ */
21
+ export type CategoryKind = "single" | "multi" | "toggle";
22
+ /** A single choice inside a category. */
23
+ export interface Option {
24
+ /** Globally unique id, e.g. "orm-drizzle". */
25
+ id: string;
26
+ /** Human label, e.g. "Drizzle". */
27
+ name: string;
28
+ /** One-line description shown under the label. */
29
+ description: string;
30
+ /** Optional lucide-react icon name, e.g. "database". */
31
+ icon?: string;
32
+ /** Optional status pill. */
33
+ badge?: Badge;
34
+ /** Option ids that must ALL be selected for this option to be available. */
35
+ requires?: string[];
36
+ /** Option ids that, if any is selected, make this option unavailable. */
37
+ conflicts?: string[];
38
+ /** Option ids auto-selected when this option is selected. */
39
+ implies?: string[];
40
+ /** Option ids surfaced as soft suggestions (no hard effect on validity). */
41
+ recommends?: string[];
42
+ }
43
+ /** A group of related options (one builder row / column). */
44
+ export interface Category {
45
+ /** Stable category id, e.g. "orm". Also the {@link Selection} key. */
46
+ id: string;
47
+ /** Human title, e.g. "ORM". */
48
+ title: string;
49
+ /** One-line description of what the category controls. */
50
+ description?: string;
51
+ /** Selection semantics. */
52
+ kind: CategoryKind;
53
+ /** The options (for "toggle" categories this is empty / ignored). */
54
+ options: Option[];
55
+ /**
56
+ * When true a "single" category may resolve to no selection (rare). Most
57
+ * single categories always hold a value (their default).
58
+ */
59
+ optional?: boolean;
60
+ /**
61
+ * The builder section this category is displayed under, e.g. "Framework",
62
+ * "Data", "Conventions". Categories with the same group render together beneath
63
+ * one section header, in catalog order.
64
+ */
65
+ group?: string;
66
+ /**
67
+ * Render style for a "single" category:
68
+ * - "cards" (default): the icon-card grid — for choices that benefit from an
69
+ * icon + description (frameworks, databases, …).
70
+ * - "segmented": a compact inline pill row — for simple, self-evident choices
71
+ * (naming convention, directory layout, …) where a big card would be noise.
72
+ */
73
+ layout?: "cards" | "segmented";
74
+ }
75
+ /** The full, ordered taxonomy. */
76
+ export type Catalog = Category[];
77
+ /**
78
+ * Raw user selection keyed by category id.
79
+ * - "single" -> option id string.
80
+ * - "multi" -> array of option ids.
81
+ * - "toggle" -> boolean.
82
+ */
83
+ export type Selection = Record<string, string | string[] | boolean>;
84
+ /**
85
+ * A fully resolved stack — the canonical config consumed by `kickoff.ts`.
86
+ * Same shape as {@link Selection} but guaranteed valid and complete (every
87
+ * single/toggle category present, every value available).
88
+ */
89
+ export type StackConfig = Selection;
90
+ /** Resolution metadata for one option in one category. */
91
+ export interface ResolvedOption {
92
+ /** The underlying option definition. */
93
+ option: Option;
94
+ /** Whether the option may currently be selected. */
95
+ available: boolean;
96
+ /** Short, human reason it is unavailable (only set when `available` is false). */
97
+ reason?: string;
98
+ /** Whether this option is currently selected. */
99
+ selected: boolean;
100
+ }
101
+ /** Resolved state for one category. */
102
+ export interface ResolvedCategory {
103
+ category: Category;
104
+ options: ResolvedOption[];
105
+ /** The resolved value (string | string[] | boolean) for this category. */
106
+ value: string | string[] | boolean;
107
+ }
108
+ /** A validation note attached to the resolved stack. */
109
+ export interface ResolutionIssue {
110
+ /** Category the issue belongs to. */
111
+ categoryId: string;
112
+ /** Severity: "error" blocks validity; "info" is advisory. */
113
+ level: "error" | "info";
114
+ /** Human message. */
115
+ message: string;
116
+ }
117
+ /** The complete output of `resolve()`. */
118
+ export interface Resolution {
119
+ /** The (auto-corrected) selection used to produce this resolution. */
120
+ selection: Selection;
121
+ /** Per-category resolved state, keyed by category id. */
122
+ categories: Record<string, ResolvedCategory>;
123
+ /** True when there are no "error"-level issues. */
124
+ valid: boolean;
125
+ /** All issues found during resolution. */
126
+ issues: ResolutionIssue[];
127
+ }
128
+ //# sourceMappingURL=types.d.ts.map
package/dist/types.js ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * The Cronus Stack Builder model — a Better-T-Stack-class stack configurator.
3
+ *
4
+ * The whole builder is driven by a single declarative {@link Catalog}: a list of
5
+ * {@link Category}, each holding {@link Option}s that wire up to each other via
6
+ * `requires` / `conflicts` / `implies` / `recommends`. The pure resolver in
7
+ * `engine.ts` turns a {@link Selection} (what the user picked) into a fully
8
+ * resolved, valid {@link StackConfig} plus per-option availability.
9
+ *
10
+ * Option ids are GLOBALLY UNIQUE (e.g. "db-none", "orm-drizzle", "web-next") so
11
+ * cross-category constraints can reference them directly.
12
+ */
13
+ export {};
14
+ //# sourceMappingURL=types.js.map
package/package.json ADDED
@@ -0,0 +1,84 @@
1
+ {
2
+ "name": "@cronus-ui/stack",
3
+ "version": "0.6.0",
4
+ "description": "Cronus Stack Builder core — catalog, resolver, CLI flags, KICKOFF.md and stack.json artifacts.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "Cronus",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/pedrogbraz/cronus-ui.git",
11
+ "directory": "packages/stack"
12
+ },
13
+ "homepage": "https://aicronus.com",
14
+ "bugs": {
15
+ "url": "https://github.com/pedrogbraz/cronus-ui/issues"
16
+ },
17
+ "keywords": [
18
+ "cronus",
19
+ "stack",
20
+ "scaffold",
21
+ "kickoff",
22
+ "design-system",
23
+ "typescript"
24
+ ],
25
+ "exports": {
26
+ ".": {
27
+ "types": "./dist/index.d.ts",
28
+ "import": "./dist/index.js"
29
+ },
30
+ "./catalog": {
31
+ "types": "./dist/catalog.d.ts",
32
+ "import": "./dist/catalog.js"
33
+ },
34
+ "./cli": {
35
+ "types": "./dist/cli.d.ts",
36
+ "import": "./dist/cli.js"
37
+ },
38
+ "./constants": {
39
+ "types": "./dist/constants.d.ts",
40
+ "import": "./dist/constants.js"
41
+ },
42
+ "./engine": {
43
+ "types": "./dist/engine.d.ts",
44
+ "import": "./dist/engine.js"
45
+ },
46
+ "./kickoff": {
47
+ "types": "./dist/kickoff.d.ts",
48
+ "import": "./dist/kickoff.js"
49
+ },
50
+ "./schema": {
51
+ "types": "./dist/schema.d.ts",
52
+ "import": "./dist/schema.js"
53
+ },
54
+ "./types": {
55
+ "types": "./dist/types.d.ts",
56
+ "import": "./dist/types.js"
57
+ }
58
+ },
59
+ "main": "./dist/index.js",
60
+ "types": "./dist/index.d.ts",
61
+ "files": [
62
+ "dist",
63
+ "LICENSE",
64
+ "README.md",
65
+ "!dist/**/*.map"
66
+ ],
67
+ "publishConfig": {
68
+ "access": "public"
69
+ },
70
+ "scripts": {
71
+ "build": "tsc -p tsconfig.json",
72
+ "typecheck": "tsc -p tsconfig.json --noEmit",
73
+ "test": "vitest run --config vitest.config.ts",
74
+ "test:watch": "vitest --config vitest.config.ts",
75
+ "prepublishOnly": "tsc -p tsconfig.json"
76
+ },
77
+ "devDependencies": {
78
+ "typescript": "^6.0.3",
79
+ "vitest": "^4.1.9"
80
+ },
81
+ "engines": {
82
+ "node": ">=20"
83
+ }
84
+ }