@rejot-dev/thalo 0.1.0 → 0.2.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.
@@ -0,0 +1,66 @@
1
+ import { FileType, GenericTree, ParseOptions, ParsedBlock as ParsedBlock$1, ParsedDocument as ParsedDocument$1, ThaloParser } from "./parser.shared.js";
2
+ import { Workspace } from "./model/workspace.js";
3
+
4
+ //#region src/parser.node.d.ts
5
+
6
+ type ParsedBlock = ParsedBlock$1<GenericTree>;
7
+ type ParsedDocument = ParsedDocument$1<GenericTree>;
8
+ /**
9
+ * Check if the parser has been initialized.
10
+ */
11
+ declare function isInitialized(): boolean;
12
+ /**
13
+ * Check if using native bindings (vs WASM fallback).
14
+ * Only valid after `initParser()` has been called.
15
+ */
16
+ declare function isUsingNative(): boolean;
17
+ /**
18
+ * Initialize the parser, trying native first then falling back to WASM.
19
+ *
20
+ * This must be called (and awaited) once before using `createParser()` or
21
+ * `createWorkspace()`. Multiple calls are safe and will return immediately
22
+ * if already initialized.
23
+ *
24
+ * @returns Promise that resolves when parser is ready
25
+ * @throws Error if both native and WASM initialization fail
26
+ */
27
+ declare function initParser(): Promise<void>;
28
+ /**
29
+ * Create a ThaloParser instance.
30
+ *
31
+ * Note: `initParser()` must be called first.
32
+ *
33
+ * @throws Error if `initParser()` has not been called
34
+ */
35
+ declare function createParser(): ThaloParser<GenericTree>;
36
+ /**
37
+ * Create a Workspace with the initialized parser.
38
+ *
39
+ * Note: `initParser()` must be called first.
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * import { initParser, createWorkspace } from "@rejot-dev/thalo/node";
44
+ *
45
+ * await initParser();
46
+ * const workspace = createWorkspace();
47
+ * workspace.addDocument(source, { filename: "test.thalo" });
48
+ * ```
49
+ *
50
+ * @throws Error if `initParser()` has not been called
51
+ */
52
+ declare function createWorkspace(): Workspace;
53
+ /**
54
+ * Parse a document using the initialized parser.
55
+ *
56
+ * Note: `initParser()` must be called first.
57
+ *
58
+ * @param source - The source code to parse
59
+ * @param options - Parse options
60
+ * @returns A parsed document
61
+ * @throws Error if `initParser()` has not been called
62
+ */
63
+ declare function parseDocument(source: string, options?: ParseOptions): ParsedDocument$1<GenericTree>;
64
+ //#endregion
65
+ export { type FileType, type ParseOptions, ParsedBlock, ParsedDocument, type ThaloParser, Workspace, createParser, createWorkspace, initParser, isInitialized, isUsingNative, parseDocument };
66
+ //# sourceMappingURL=parser.node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.node.d.ts","names":[],"sources":["../src/parser.node.ts"],"sourcesContent":[],"mappings":";;;;;KAuCY,WAAA,GAAc,cAAmB;KACjC,cAAA,GAAiB,iBAAsB;;;;iBAiBnC,aAAA,CAAA;;;;;iBAQA,aAAA,CAAA;;;;;;;;;;;iBAcM,UAAA,CAAA,GAAc;;;;;;;;iBA6EpB,YAAA,CAAA,GAAgB,YAAY;;;;;;;;;;;;;;;;;iBAyB5B,eAAA,CAAA,GAAmB;;;;;;;;;;;iBAsBnB,aAAA,2BAEJ,eACT,iBAAsB"}
@@ -0,0 +1,118 @@
1
+ import { createThaloParser } from "./parser.shared.js";
2
+ import { Workspace } from "./model/workspace.js";
3
+ import { createRequire } from "node:module";
4
+ import { readFileSync } from "node:fs";
5
+
6
+ //#region src/parser.node.ts
7
+ const require = createRequire(import.meta.url);
8
+ let parserFactory = null;
9
+ let usingNative = false;
10
+ /**
11
+ * Check if the parser has been initialized.
12
+ */
13
+ function isInitialized() {
14
+ return parserFactory !== null;
15
+ }
16
+ /**
17
+ * Check if using native bindings (vs WASM fallback).
18
+ * Only valid after `initParser()` has been called.
19
+ */
20
+ function isUsingNative() {
21
+ return usingNative;
22
+ }
23
+ /**
24
+ * Initialize the parser, trying native first then falling back to WASM.
25
+ *
26
+ * This must be called (and awaited) once before using `createParser()` or
27
+ * `createWorkspace()`. Multiple calls are safe and will return immediately
28
+ * if already initialized.
29
+ *
30
+ * @returns Promise that resolves when parser is ready
31
+ * @throws Error if both native and WASM initialization fail
32
+ */
33
+ async function initParser() {
34
+ if (parserFactory) return;
35
+ try {
36
+ const { default: Parser } = await import("tree-sitter");
37
+ const { default: thalo } = await import("@rejot-dev/tree-sitter-thalo");
38
+ thalo.nodeTypeInfo ??= [];
39
+ new Parser().setLanguage(thalo);
40
+ parserFactory = () => {
41
+ const parser = new Parser();
42
+ parser.setLanguage(thalo);
43
+ return createThaloParser(parser);
44
+ };
45
+ usingNative = true;
46
+ return;
47
+ } catch {}
48
+ try {
49
+ const { Parser, Language } = await import("web-tree-sitter");
50
+ const treeSitterWasmPath = require.resolve("web-tree-sitter/tree-sitter.wasm");
51
+ const languageWasmPath = require.resolve("@rejot-dev/tree-sitter-thalo/tree-sitter-thalo.wasm");
52
+ const treeSitterWasm = readFileSync(treeSitterWasmPath);
53
+ const languageWasm = readFileSync(languageWasmPath);
54
+ await Parser.init({ wasmBinary: treeSitterWasm });
55
+ const language = await Language.load(languageWasm);
56
+ parserFactory = () => {
57
+ const parser = new Parser();
58
+ parser.setLanguage(language);
59
+ return createThaloParser(parser);
60
+ };
61
+ usingNative = false;
62
+ return;
63
+ } catch (wasmError) {
64
+ throw new Error(`Failed to initialize thalo parser. Native tree-sitter bindings are not available for your platform, and WASM fallback also failed: ${wasmError instanceof Error ? wasmError.message : wasmError}`);
65
+ }
66
+ }
67
+ let cachedParser = null;
68
+ /**
69
+ * Create a ThaloParser instance.
70
+ *
71
+ * Note: `initParser()` must be called first.
72
+ *
73
+ * @throws Error if `initParser()` has not been called
74
+ */
75
+ function createParser() {
76
+ if (!parserFactory) throw new Error("Parser not initialized. Call `await initParser()` before using createParser().");
77
+ return parserFactory();
78
+ }
79
+ /**
80
+ * Create a Workspace with the initialized parser.
81
+ *
82
+ * Note: `initParser()` must be called first.
83
+ *
84
+ * @example
85
+ * ```typescript
86
+ * import { initParser, createWorkspace } from "@rejot-dev/thalo/node";
87
+ *
88
+ * await initParser();
89
+ * const workspace = createWorkspace();
90
+ * workspace.addDocument(source, { filename: "test.thalo" });
91
+ * ```
92
+ *
93
+ * @throws Error if `initParser()` has not been called
94
+ */
95
+ function createWorkspace() {
96
+ if (!parserFactory) throw new Error("Parser not initialized. Call `await initParser()` before using createWorkspace().");
97
+ if (!cachedParser) cachedParser = parserFactory();
98
+ return new Workspace(cachedParser);
99
+ }
100
+ /**
101
+ * Parse a document using the initialized parser.
102
+ *
103
+ * Note: `initParser()` must be called first.
104
+ *
105
+ * @param source - The source code to parse
106
+ * @param options - Parse options
107
+ * @returns A parsed document
108
+ * @throws Error if `initParser()` has not been called
109
+ */
110
+ function parseDocument(source, options) {
111
+ if (!parserFactory) throw new Error("Parser not initialized. Call `await initParser()` before using parseDocument().");
112
+ if (!cachedParser) cachedParser = parserFactory();
113
+ return cachedParser.parseDocument(source, options);
114
+ }
115
+
116
+ //#endregion
117
+ export { Workspace, createParser, createWorkspace, initParser, isInitialized, isUsingNative, parseDocument };
118
+ //# sourceMappingURL=parser.node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.node.js","names":["parserFactory: (() => ThaloParser<GenericTree>) | null","cachedParser: ThaloParser<GenericTree> | null"],"sources":["../src/parser.node.ts"],"sourcesContent":["/**\n * Node.js parser with automatic fallback from native to WASM.\n *\n * This module provides a unified API for Node.js environments that:\n * 1. Tries to use native tree-sitter bindings (fastest)\n * 2. Falls back to web-tree-sitter WASM if native bindings aren't available\n *\n * The fallback is transparent - callers don't need to know which implementation\n * is being used. The only requirement is that `initParser()` must be called\n * (and awaited) before using `createParser()` or `createWorkspace()`.\n *\n * @example\n * ```typescript\n * import { initParser, createWorkspace } from \"@rejot-dev/thalo/node\";\n *\n * // Initialize once at startup (required)\n * await initParser();\n *\n * // Then use synchronously\n * const workspace = createWorkspace();\n * workspace.addDocument(source, { filename: \"test.thalo\" });\n * ```\n */\n\nimport { readFileSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport {\n createThaloParser,\n type ThaloParser,\n type ParsedBlock as GenericParsedBlock,\n type ParsedDocument as GenericParsedDocument,\n type FileType,\n type ParseOptions,\n type GenericTree,\n} from \"./parser.shared.js\";\nimport type { Language as NativeLanguage } from \"tree-sitter\";\nimport { Workspace } from \"./model/workspace.js\";\n\n// Re-export shared types\nexport type ParsedBlock = GenericParsedBlock<GenericTree>;\nexport type ParsedDocument = GenericParsedDocument<GenericTree>;\nexport type { FileType, ParseOptions, ThaloParser };\n\n// Re-export Workspace for convenience\nexport { Workspace } from \"./model/workspace.js\";\n\nconst require = createRequire(import.meta.url);\n\n// Parser factory function - set after initialization\nlet parserFactory: (() => ThaloParser<GenericTree>) | null = null;\n\n// Track which implementation is being used\nlet usingNative = false;\n\n/**\n * Check if the parser has been initialized.\n */\nexport function isInitialized(): boolean {\n return parserFactory !== null;\n}\n\n/**\n * Check if using native bindings (vs WASM fallback).\n * Only valid after `initParser()` has been called.\n */\nexport function isUsingNative(): boolean {\n return usingNative;\n}\n\n/**\n * Initialize the parser, trying native first then falling back to WASM.\n *\n * This must be called (and awaited) once before using `createParser()` or\n * `createWorkspace()`. Multiple calls are safe and will return immediately\n * if already initialized.\n *\n * @returns Promise that resolves when parser is ready\n * @throws Error if both native and WASM initialization fail\n */\nexport async function initParser(): Promise<void> {\n // Already initialized\n if (parserFactory) {\n return;\n }\n\n // Try native first\n try {\n const { default: Parser } = await import(\"tree-sitter\");\n const { default: thalo } = await import(\"@rejot-dev/tree-sitter-thalo\");\n\n // Ensure nodeTypeInfo is an array\n thalo.nodeTypeInfo ??= [];\n\n // Test that we can actually create a parser (this will fail if native bindings are broken)\n const testParser = new Parser();\n testParser.setLanguage(thalo as unknown as NativeLanguage);\n\n // Native works! Set up the factory\n parserFactory = () => {\n const parser = new Parser();\n parser.setLanguage(thalo as unknown as NativeLanguage);\n return createThaloParser(parser);\n };\n usingNative = true;\n return;\n } catch {\n // Native failed, try WASM fallback\n }\n\n // Fall back to WASM\n try {\n const { Parser, Language } = await import(\"web-tree-sitter\");\n\n // Resolve WASM file paths from installed dependencies\n const treeSitterWasmPath = require.resolve(\"web-tree-sitter/tree-sitter.wasm\");\n const languageWasmPath = require.resolve(\"@rejot-dev/tree-sitter-thalo/tree-sitter-thalo.wasm\");\n\n // Load WASM files\n const treeSitterWasm = readFileSync(treeSitterWasmPath);\n const languageWasm = readFileSync(languageWasmPath);\n\n // Initialize web-tree-sitter\n await Parser.init({\n wasmBinary: treeSitterWasm,\n });\n\n // Load the thalo language\n const language = await Language.load(languageWasm);\n\n // WASM works! Set up the factory\n parserFactory = () => {\n const parser = new Parser();\n parser.setLanguage(language);\n return createThaloParser(parser);\n };\n usingNative = false;\n return;\n } catch (wasmError) {\n throw new Error(\n `Failed to initialize thalo parser. ` +\n `Native tree-sitter bindings are not available for your platform, ` +\n `and WASM fallback also failed: ${wasmError instanceof Error ? wasmError.message : wasmError}`,\n );\n }\n}\n\n// Cached parser instance for createWorkspace\nlet cachedParser: ThaloParser<GenericTree> | null = null;\n\n/**\n * Create a ThaloParser instance.\n *\n * Note: `initParser()` must be called first.\n *\n * @throws Error if `initParser()` has not been called\n */\nexport function createParser(): ThaloParser<GenericTree> {\n if (!parserFactory) {\n throw new Error(\n \"Parser not initialized. Call `await initParser()` before using createParser().\",\n );\n }\n return parserFactory();\n}\n\n/**\n * Create a Workspace with the initialized parser.\n *\n * Note: `initParser()` must be called first.\n *\n * @example\n * ```typescript\n * import { initParser, createWorkspace } from \"@rejot-dev/thalo/node\";\n *\n * await initParser();\n * const workspace = createWorkspace();\n * workspace.addDocument(source, { filename: \"test.thalo\" });\n * ```\n *\n * @throws Error if `initParser()` has not been called\n */\nexport function createWorkspace(): Workspace {\n if (!parserFactory) {\n throw new Error(\n \"Parser not initialized. Call `await initParser()` before using createWorkspace().\",\n );\n }\n if (!cachedParser) {\n cachedParser = parserFactory();\n }\n return new Workspace(cachedParser);\n}\n\n/**\n * Parse a document using the initialized parser.\n *\n * Note: `initParser()` must be called first.\n *\n * @param source - The source code to parse\n * @param options - Parse options\n * @returns A parsed document\n * @throws Error if `initParser()` has not been called\n */\nexport function parseDocument(\n source: string,\n options?: ParseOptions,\n): GenericParsedDocument<GenericTree> {\n if (!parserFactory) {\n throw new Error(\n \"Parser not initialized. Call `await initParser()` before using parseDocument().\",\n );\n }\n if (!cachedParser) {\n cachedParser = parserFactory();\n }\n return cachedParser.parseDocument(source, options);\n}\n"],"mappings":";;;;;;AA8CA,MAAM,UAAU,cAAc,OAAO,KAAK,IAAI;AAG9C,IAAIA,gBAAyD;AAG7D,IAAI,cAAc;;;;AAKlB,SAAgB,gBAAyB;AACvC,QAAO,kBAAkB;;;;;;AAO3B,SAAgB,gBAAyB;AACvC,QAAO;;;;;;;;;;;;AAaT,eAAsB,aAA4B;AAEhD,KAAI,cACF;AAIF,KAAI;EACF,MAAM,EAAE,SAAS,WAAW,MAAM,OAAO;EACzC,MAAM,EAAE,SAAS,UAAU,MAAM,OAAO;AAGxC,QAAM,iBAAiB,EAAE;AAIzB,EADmB,IAAI,QAAQ,CACpB,YAAY,MAAmC;AAG1D,wBAAsB;GACpB,MAAM,SAAS,IAAI,QAAQ;AAC3B,UAAO,YAAY,MAAmC;AACtD,UAAO,kBAAkB,OAAO;;AAElC,gBAAc;AACd;SACM;AAKR,KAAI;EACF,MAAM,EAAE,QAAQ,aAAa,MAAM,OAAO;EAG1C,MAAM,qBAAqB,QAAQ,QAAQ,mCAAmC;EAC9E,MAAM,mBAAmB,QAAQ,QAAQ,sDAAsD;EAG/F,MAAM,iBAAiB,aAAa,mBAAmB;EACvD,MAAM,eAAe,aAAa,iBAAiB;AAGnD,QAAM,OAAO,KAAK,EAChB,YAAY,gBACb,CAAC;EAGF,MAAM,WAAW,MAAM,SAAS,KAAK,aAAa;AAGlD,wBAAsB;GACpB,MAAM,SAAS,IAAI,QAAQ;AAC3B,UAAO,YAAY,SAAS;AAC5B,UAAO,kBAAkB,OAAO;;AAElC,gBAAc;AACd;UACO,WAAW;AAClB,QAAM,IAAI,MACR,sIAEoC,qBAAqB,QAAQ,UAAU,UAAU,YACtF;;;AAKL,IAAIC,eAAgD;;;;;;;;AASpD,SAAgB,eAAyC;AACvD,KAAI,CAAC,cACH,OAAM,IAAI,MACR,iFACD;AAEH,QAAO,eAAe;;;;;;;;;;;;;;;;;;AAmBxB,SAAgB,kBAA6B;AAC3C,KAAI,CAAC,cACH,OAAM,IAAI,MACR,oFACD;AAEH,KAAI,CAAC,aACH,gBAAe,eAAe;AAEhC,QAAO,IAAI,UAAU,aAAa;;;;;;;;;;;;AAapC,SAAgB,cACd,QACA,SACoC;AACpC,KAAI,CAAC,cACH,OAAM,IAAI,MACR,kFACD;AAEH,KAAI,CAAC,aACH,gBAAe,eAAe;AAEhC,QAAO,aAAa,cAAc,QAAQ,QAAQ"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rejot-dev/thalo",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
@@ -29,6 +29,11 @@
29
29
  "types": "./dist/parser.web.d.ts",
30
30
  "default": "./dist/parser.web.js"
31
31
  },
32
+ "./node": {
33
+ "development": "./src/parser.node.ts",
34
+ "types": "./dist/parser.node.d.ts",
35
+ "default": "./dist/parser.node.js"
36
+ },
32
37
  "./services/semantic-tokens": {
33
38
  "development": "./src/services/semantic-tokens.ts",
34
39
  "types": "./dist/services/semantic-tokens.d.ts",
@@ -88,12 +93,17 @@
88
93
  "development": "./src/files.ts",
89
94
  "types": "./dist/files.d.ts",
90
95
  "default": "./dist/files.js"
96
+ },
97
+ "./api": {
98
+ "development": "./src/api.ts",
99
+ "types": "./dist/api.d.ts",
100
+ "default": "./dist/api.js"
91
101
  }
92
102
  },
93
103
  "main": "./dist/mod.js",
94
104
  "types": "./dist/mod.d.ts",
95
105
  "dependencies": {
96
- "@rejot-dev/tree-sitter-thalo": "0.1.0"
106
+ "@rejot-dev/tree-sitter-thalo": "0.2.0"
97
107
  },
98
108
  "peerDependencies": {
99
109
  "tree-sitter": "^0.25.0",