@sprig-and-prose/sprig 0.1.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/README.md ADDED
@@ -0,0 +1,41 @@
1
+ # sprig-cli
2
+
3
+ Sprig CLI tool for compiling and serving universes.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g @sprig-and-prose/sprig-cli
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Commands
14
+
15
+ - `sprig compile [path?]` - Compile universe files to manifest
16
+ - `sprig validate [path?]` - Validate universe files (no output)
17
+ - `sprig ui [path?]` - Start UI server with watch mode
18
+
19
+ ### Root Discovery
20
+
21
+ The CLI walks upward from the provided path (or current directory) until it finds a directory containing `universe.prose`. That directory is the universe root.
22
+
23
+ ### Compile
24
+
25
+ Compiles all `.prose` files under the universe root (excluding `.sprig/**`, `dist/**`, `node_modules/**`, `.git/**`) and writes `.sprig/manifest.json`.
26
+
27
+ ### Validate
28
+
29
+ Validates the universe without writing output. Exits with a nonzero code if errors are found.
30
+
31
+ ### UI
32
+
33
+ Starts a local HTTP server (default port 5173) that:
34
+ - Serves the UI from `@sprig-and-prose/sprig-ui-csr`
35
+ - Provides `/api/manifest` endpoint for the compiled manifest
36
+ - Provides `/api/events` endpoint for Server-Sent Events (SSE) updates
37
+ - Watches `.prose` files and automatically rebuilds on changes
38
+ - Broadcasts SSE events after each successful rebuild
39
+
40
+ The `.sprig/` directory is a cache and should not be committed.
41
+
package/biome.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
3
+ "vcs": {
4
+ "enabled": true,
5
+ "clientKind": "git",
6
+ "useIgnoreFile": true
7
+ },
8
+ "files": {
9
+ "ignoreUnknown": false,
10
+ "ignore": []
11
+ },
12
+ "formatter": {
13
+ "enabled": true,
14
+ "indentStyle": "space",
15
+ "indentWidth": 2
16
+ },
17
+ "organizeImports": {
18
+ "enabled": true
19
+ },
20
+ "linter": {
21
+ "enabled": true,
22
+ "rules": {
23
+ "recommended": true
24
+ }
25
+ },
26
+ "javascript": {
27
+ "formatter": {
28
+ "quoteStyle": "double"
29
+ }
30
+ }
31
+ }
32
+
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,161 @@
1
+ #!/usr/bin/env node
2
+ import { resolve } from "node:path";
3
+ import { discoverUniverseRoot } from "./root.js";
4
+ import { loadProseFiles } from "./prose.js";
5
+ import { compileUniverse } from "./compiler.js";
6
+ import { startUIServer } from "./ui.js";
7
+ const commands = ["compile", "validate", "ui"];
8
+ function printHelp() {
9
+ console.log("Usage: sprig <command> [path?] [options]");
10
+ console.log("");
11
+ console.log("Commands:");
12
+ console.log(" compile Compile universe files to manifest");
13
+ console.log(" validate Validate universe files (no output)");
14
+ console.log(" ui Start UI server with watch mode");
15
+ console.log("");
16
+ console.log("Options (for ui command):");
17
+ console.log(" -p, --port <number> Port to listen on (default: 6336)");
18
+ console.log("");
19
+ console.log("Root discovery:");
20
+ console.log(" - Walks upward from provided path (or current directory)");
21
+ console.log(" - Finds directory containing universe.prose");
22
+ }
23
+ function parseArgs() {
24
+ const args = process.argv.slice(2);
25
+ if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
26
+ return { command: null, path: process.cwd() };
27
+ }
28
+ const command = args[0];
29
+ if (!commands.includes(command)) {
30
+ console.error(`Error: Unknown command "${command}"`);
31
+ console.error("Run 'sprig --help' for usage information");
32
+ process.exit(1);
33
+ }
34
+ // Parse path and options
35
+ let path = process.cwd();
36
+ let port;
37
+ for (let i = 1; i < args.length; i++) {
38
+ const arg = args[i];
39
+ if (arg === "--port" || arg === "-p") {
40
+ const portValue = args[i + 1];
41
+ if (!portValue) {
42
+ console.error("Error: --port requires a value");
43
+ process.exit(1);
44
+ }
45
+ const parsedPort = parseInt(portValue, 10);
46
+ if (isNaN(parsedPort) || parsedPort < 1 || parsedPort > 65535) {
47
+ console.error("Error: --port must be a number between 1 and 65535");
48
+ process.exit(1);
49
+ }
50
+ port = parsedPort;
51
+ i++; // Skip the port value
52
+ }
53
+ else if (!arg.startsWith("-")) {
54
+ // First non-option argument is the path
55
+ path = resolve(arg);
56
+ }
57
+ else {
58
+ console.error(`Error: Unknown option "${arg}"`);
59
+ console.error("Run 'sprig --help' for usage information");
60
+ process.exit(1);
61
+ }
62
+ }
63
+ return { command, path, port };
64
+ }
65
+ async function handleCompile(path) {
66
+ const root = discoverUniverseRoot(path);
67
+ if (!root) {
68
+ console.error("Couldn't find universe.prose");
69
+ console.error("");
70
+ console.error("Make sure you're inside a universe repository.");
71
+ process.exit(1);
72
+ }
73
+ const files = await loadProseFiles(root);
74
+ const result = await compileUniverse(root, files, true);
75
+ if (!result.success) {
76
+ const errors = result.diagnostics.filter((d) => d.severity === "error");
77
+ if (errors.length > 0) {
78
+ for (const error of errors) {
79
+ console.error(`Error: ${error.message}`);
80
+ }
81
+ }
82
+ process.exit(1);
83
+ }
84
+ const warnings = result.diagnostics.filter((d) => d.severity === "warning");
85
+ if (warnings.length > 0) {
86
+ for (const warning of warnings) {
87
+ const source = warning.source
88
+ ? // @ts-expect-error - source structure may vary
89
+ `${warning.source.file}:${warning.source.start?.line}:${warning.source.start?.col}`
90
+ : "unknown location";
91
+ console.warn(`Warning: ${source}: ${warning.message}`);
92
+ }
93
+ }
94
+ }
95
+ async function handleValidate(path) {
96
+ const root = discoverUniverseRoot(path);
97
+ if (!root) {
98
+ console.error("Couldn't find universe.prose");
99
+ console.error("");
100
+ console.error("Make sure you're inside a universe repository.");
101
+ process.exit(1);
102
+ }
103
+ const files = await loadProseFiles(root);
104
+ const result = await compileUniverse(root, files, false);
105
+ if (!result.success) {
106
+ const errors = result.diagnostics.filter((d) => d.severity === "error");
107
+ if (errors.length > 0) {
108
+ for (const error of errors) {
109
+ console.error(`Error: ${error.message}`);
110
+ }
111
+ }
112
+ process.exit(1);
113
+ }
114
+ const warnings = result.diagnostics.filter((d) => d.severity === "warning");
115
+ if (warnings.length > 0) {
116
+ for (const warning of warnings) {
117
+ const source = warning.source
118
+ ? // @ts-expect-error - source structure may vary
119
+ `${warning.source.file}:${warning.source.start?.line}:${warning.source.start?.col}`
120
+ : "unknown location";
121
+ console.warn(`Warning: ${source}: ${warning.message}`);
122
+ }
123
+ }
124
+ }
125
+ async function handleUI(path, port) {
126
+ const root = discoverUniverseRoot(path);
127
+ if (!root) {
128
+ console.error("Couldn't find universe.prose");
129
+ console.error("");
130
+ console.error("Make sure you're inside a universe repository.");
131
+ process.exit(1);
132
+ }
133
+ await startUIServer(root, port);
134
+ }
135
+ async function main() {
136
+ const { command, path, port } = parseArgs();
137
+ if (!command) {
138
+ printHelp();
139
+ process.exit(0);
140
+ }
141
+ try {
142
+ switch (command) {
143
+ case "compile":
144
+ await handleCompile(path);
145
+ break;
146
+ case "validate":
147
+ await handleValidate(path);
148
+ break;
149
+ case "ui":
150
+ await handleUI(path, port);
151
+ break;
152
+ }
153
+ }
154
+ catch (error) {
155
+ const message = error instanceof Error ? error.message : String(error);
156
+ console.error(`Error: ${message}`);
157
+ process.exit(1);
158
+ }
159
+ }
160
+ main();
161
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ export interface CompileResult {
2
+ success: boolean;
3
+ manifest?: Record<string, unknown> & {
4
+ repositories?: Record<string, unknown>;
5
+ generatedAt: string;
6
+ };
7
+ diagnostics: Array<{
8
+ severity: string;
9
+ message: string;
10
+ source?: unknown;
11
+ }>;
12
+ }
13
+ /**
14
+ * Compiles prose files into a manifest
15
+ * @param universeRoot - Universe root directory
16
+ * @param files - Array of prose file paths
17
+ * @param writeManifest - If true, write manifest to disk
18
+ * @returns Compile result with success status, manifest, and diagnostics
19
+ */
20
+ export declare function compileUniverse(universeRoot: string, files: string[], writeManifest?: boolean): Promise<CompileResult>;
21
+ //# sourceMappingURL=compiler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../src/compiler.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IACrG,WAAW,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CAC7E;AA2CD;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EAAE,EACf,aAAa,UAAO,GACnB,OAAO,CAAC,aAAa,CAAC,CA6ExB"}
@@ -0,0 +1,117 @@
1
+ import { readFileSync, writeFileSync, mkdirSync, renameSync } from "node:fs";
2
+ import { join, dirname } from "node:path";
3
+ // @ts-expect-error - sprig-universe doesn't have TypeScript types
4
+ import { parseFiles } from "@sprig-and-prose/sprig-universe";
5
+ /**
6
+ * Validates that exactly one universe declaration exists in the parsed graph
7
+ */
8
+ function validateUniverseCount(graph) {
9
+ const universes = graph.universes;
10
+ const universeNames = Object.keys(universes || {});
11
+ if (universeNames.length === 0) {
12
+ return {
13
+ valid: false,
14
+ error: "No universe declaration found. At least one universe declaration is required.",
15
+ };
16
+ }
17
+ if (universeNames.length > 1) {
18
+ const nodes = graph.nodes;
19
+ const fileList = Array.from(universeNames)
20
+ .map((name) => {
21
+ const universe = universes?.[name];
22
+ const rootNode = universe?.root && nodes ? nodes[universe.root] : null;
23
+ return rootNode?.source?.file || "unknown";
24
+ })
25
+ .filter((file, index, arr) => arr.indexOf(file) === index) // unique files
26
+ .sort()
27
+ .join(", ");
28
+ return {
29
+ valid: false,
30
+ error: `Multiple distinct universes found: ${universeNames.join(", ")}. Files: ${fileList}. Exactly one universe declaration is required.`,
31
+ };
32
+ }
33
+ return {
34
+ valid: true,
35
+ universeName: universeNames[0],
36
+ };
37
+ }
38
+ /**
39
+ * Compiles prose files into a manifest
40
+ * @param universeRoot - Universe root directory
41
+ * @param files - Array of prose file paths
42
+ * @param writeManifest - If true, write manifest to disk
43
+ * @returns Compile result with success status, manifest, and diagnostics
44
+ */
45
+ export async function compileUniverse(universeRoot, files, writeManifest = true) {
46
+ const manifestPath = join(universeRoot, ".sprig", "manifest.json");
47
+ // Read and parse files
48
+ const fileContents = files.map((file) => ({
49
+ file,
50
+ text: readFileSync(file, "utf-8"),
51
+ }));
52
+ try {
53
+ const graph = parseFiles(fileContents);
54
+ // Validate exactly one universe
55
+ const validation = validateUniverseCount(graph);
56
+ if (!validation.valid) {
57
+ return {
58
+ success: false,
59
+ diagnostics: [
60
+ {
61
+ severity: "error",
62
+ message: validation.error || "Unknown validation error",
63
+ },
64
+ ],
65
+ };
66
+ }
67
+ // Add repositories and metadata to manifest
68
+ const manifest = {
69
+ ...graph,
70
+ repositories: graph.repositories || {},
71
+ generatedAt: new Date().toISOString(),
72
+ };
73
+ // Check for parsing errors
74
+ const hasErrors = graph.diagnostics.some((d) => d.severity === "error");
75
+ if (hasErrors) {
76
+ return {
77
+ success: false,
78
+ manifest,
79
+ diagnostics: graph.diagnostics,
80
+ };
81
+ }
82
+ // Write manifest if requested
83
+ if (writeManifest) {
84
+ // Ensure output directory exists
85
+ const manifestDir = dirname(manifestPath);
86
+ try {
87
+ mkdirSync(manifestDir, { recursive: true });
88
+ }
89
+ catch (error) {
90
+ // Directory might already exist, ignore
91
+ }
92
+ // Write atomically (temp file + rename)
93
+ const tempPath = `${manifestPath}.tmp`;
94
+ const json = JSON.stringify(manifest, null, 2);
95
+ writeFileSync(tempPath, json, "utf-8");
96
+ renameSync(tempPath, manifestPath);
97
+ }
98
+ return {
99
+ success: true,
100
+ manifest,
101
+ diagnostics: graph.diagnostics,
102
+ };
103
+ }
104
+ catch (error) {
105
+ const message = error instanceof Error ? error.message : String(error);
106
+ return {
107
+ success: false,
108
+ diagnostics: [
109
+ {
110
+ severity: "error",
111
+ message: `Compilation error: ${message}`,
112
+ },
113
+ ],
114
+ };
115
+ }
116
+ }
117
+ //# sourceMappingURL=compiler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compiler.js","sourceRoot":"","sources":["../src/compiler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Loads all .prose files under root with default excludes
3
+ * @param root - Universe root directory
4
+ * @returns Array of prose file paths, sorted deterministically
5
+ */
6
+ export declare function loadProseFiles(root: string): Promise<string[]>;
7
+ //# sourceMappingURL=prose.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prose.d.ts","sourceRoot":"","sources":["../src/prose.ts"],"names":[],"mappings":"AAKA;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CASpE"}
package/dist/prose.js ADDED
@@ -0,0 +1,18 @@
1
+ import { join } from "node:path";
2
+ import fastGlob from "fast-glob";
3
+ const DEFAULT_EXCLUDES = [".sprig/**", "dist/**", "node_modules/**", ".git/**"];
4
+ /**
5
+ * Loads all .prose files under root with default excludes
6
+ * @param root - Universe root directory
7
+ * @returns Array of prose file paths, sorted deterministically
8
+ */
9
+ export async function loadProseFiles(root) {
10
+ const pattern = join(root, "**/*.prose");
11
+ const allFiles = await fastGlob(pattern, {
12
+ absolute: true,
13
+ ignore: DEFAULT_EXCLUDES.map((exclude) => join(root, exclude)),
14
+ });
15
+ // Sort for deterministic ordering
16
+ return allFiles.sort();
17
+ }
18
+ //# sourceMappingURL=prose.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prose.js","sourceRoot":"","sources":["../src/prose.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,QAAQ,MAAM,WAAW,CAAC;AAEjC,MAAM,gBAAgB,GAAG,CAAC,WAAW,EAAE,SAAS,EAAE,iBAAiB,EAAE,SAAS,CAAC,CAAC;AAEhF;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAY;IAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,OAAO,EAAE;QACvC,QAAQ,EAAE,IAAI;QACd,MAAM,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;KAC/D,CAAC,CAAC;IAEH,kCAAkC;IAClC,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;AACzB,CAAC"}
package/dist/root.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Walks upward from startPath to find universe.prose marker
3
+ * @param startPath - Starting directory path
4
+ * @returns Path to directory containing universe.prose, or null if not found
5
+ */
6
+ export declare function discoverUniverseRoot(startPath: string): string | null;
7
+ //# sourceMappingURL=root.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"root.d.ts","sourceRoot":"","sources":["../src/root.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAmBrE"}
package/dist/root.js ADDED
@@ -0,0 +1,25 @@
1
+ import { existsSync, statSync } from "node:fs";
2
+ import { resolve, dirname, join } from "node:path";
3
+ /**
4
+ * Walks upward from startPath to find universe.prose marker
5
+ * @param startPath - Starting directory path
6
+ * @returns Path to directory containing universe.prose, or null if not found
7
+ */
8
+ export function discoverUniverseRoot(startPath) {
9
+ let current = resolve(startPath);
10
+ const root = resolve("/");
11
+ while (current !== root) {
12
+ const markerPath = join(current, "universe.prose");
13
+ if (existsSync(markerPath) && statSync(markerPath).isFile()) {
14
+ return current;
15
+ }
16
+ current = dirname(current);
17
+ }
18
+ // Check root directory as well
19
+ const rootMarkerPath = join(root, "universe.prose");
20
+ if (existsSync(rootMarkerPath) && statSync(rootMarkerPath).isFile()) {
21
+ return root;
22
+ }
23
+ return null;
24
+ }
25
+ //# sourceMappingURL=root.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"root.js","sourceRoot":"","sources":["../src/root.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEnD;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,SAAiB;IACpD,IAAI,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IACjC,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAE1B,OAAO,OAAO,KAAK,IAAI,EAAE,CAAC;QACxB,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;QACnD,IAAI,UAAU,CAAC,UAAU,CAAC,IAAI,QAAQ,CAAC,UAAU,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;YAC5D,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAED,+BAA+B;IAC/B,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;IACpD,IAAI,UAAU,CAAC,cAAc,CAAC,IAAI,QAAQ,CAAC,cAAc,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;QACpE,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
package/dist/ui.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Starts the UI server with watch mode
3
+ */
4
+ export declare function startUIServer(universeRoot: string, port?: number): Promise<void>;
5
+ //# sourceMappingURL=ui.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAiNA;;GAEG;AACH,wBAAsB,aAAa,CACjC,YAAY,EAAE,MAAM,EACpB,IAAI,GAAE,MAAa,GAClB,OAAO,CAAC,IAAI,CAAC,CAuHf"}