syntaqlite 0.6.0 → 0.7.1
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 +78 -15
- package/dist/engine.d.ts +62 -26
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +184 -113
- package/dist/engine.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lsp.d.ts +22 -0
- package/dist/lsp.d.ts.map +1 -0
- package/dist/lsp.js +21 -0
- package/dist/lsp.js.map +1 -0
- package/dist/types.d.ts +53 -17
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/wasm/syntaqlite-runtime.js +101 -41
- package/wasm/syntaqlite-runtime.wasm +0 -0
- package/wasm/syntaqlite-sqlite.wasm +0 -0
package/README.md
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
# syntaqlite
|
|
2
2
|
|
|
3
|
-
SQLite SQL parser, formatter, and
|
|
3
|
+
SQLite SQL parser, formatter, and language server for the browser — powered
|
|
4
|
+
by WebAssembly.
|
|
4
5
|
|
|
5
6
|
Built from SQLite's own grammar for 100% syntax compatibility.
|
|
6
7
|
|
|
7
8
|
- **Format** SQL with configurable line width, keyword casing, and semicolons
|
|
8
|
-
- **Parse** SQL into a full
|
|
9
|
-
- **
|
|
10
|
-
|
|
9
|
+
- **Parse** SQL into a full syntax tree
|
|
10
|
+
- **Language server**: diagnostics, completions, hover, and semantic tokens
|
|
11
|
+
over standard LSP JSON-RPC, schema-aware via your DDL
|
|
12
|
+
- **Analyze** SQL in one shot: schema-aware diagnostics without an
|
|
13
|
+
editor session
|
|
11
14
|
|
|
12
15
|
## Install
|
|
13
16
|
|
|
@@ -18,23 +21,83 @@ npm install syntaqlite
|
|
|
18
21
|
## Usage
|
|
19
22
|
|
|
20
23
|
```ts
|
|
21
|
-
import { Engine } from "syntaqlite";
|
|
24
|
+
import { Engine, DialectManager } from "syntaqlite";
|
|
22
25
|
|
|
23
26
|
const engine = new Engine();
|
|
24
27
|
await engine.load();
|
|
28
|
+
await new DialectManager().loadDefault(engine);
|
|
25
29
|
|
|
26
|
-
// Format SQL
|
|
27
|
-
|
|
28
|
-
console.log(
|
|
29
|
-
|
|
30
|
+
// Format SQL. Options mirror the Rust FormatConfig; omitted fields use
|
|
31
|
+
// the formatter defaults.
|
|
32
|
+
console.log(engine.format("select id,name from users where id=1", {
|
|
33
|
+
lineWidth: 80,
|
|
34
|
+
indentWidth: 2,
|
|
35
|
+
keywordCase: "upper",
|
|
36
|
+
semicolons: true,
|
|
37
|
+
}));
|
|
38
|
+
// SELECT id, name FROM users WHERE id = 1;
|
|
30
39
|
|
|
31
|
-
// Parse SQL to AST (JSON)
|
|
32
|
-
const
|
|
33
|
-
console.log(ast);
|
|
40
|
+
// Parse SQL to AST (JSON); parse errors are data, not exceptions
|
|
41
|
+
const {statements, errors} = engine.parse("SELECT 1");
|
|
34
42
|
|
|
35
|
-
//
|
|
36
|
-
const
|
|
37
|
-
|
|
43
|
+
// Tokenize SQL
|
|
44
|
+
const tokens = engine.tokenize("SELECT 1");
|
|
45
|
+
|
|
46
|
+
// Give the analyzer your schema
|
|
47
|
+
engine.setSessionContextDdl("CREATE TABLE users(id INTEGER, name TEXT);");
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Language server
|
|
51
|
+
|
|
52
|
+
Editor features are served by an in-process LSP server. Drive it with
|
|
53
|
+
JSON-RPC messages:
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
engine.lspMessage({ jsonrpc: "2.0", id: 1, method: "initialize", params: { capabilities: {} } });
|
|
57
|
+
engine.lspMessage({ jsonrpc: "2.0", method: "initialized", params: {} });
|
|
58
|
+
|
|
59
|
+
const out = engine.lspMessage({
|
|
60
|
+
jsonrpc: "2.0",
|
|
61
|
+
method: "textDocument/didOpen",
|
|
62
|
+
params: {
|
|
63
|
+
textDocument: { uri: "file:///q.sql", languageId: "sql", version: 1, text: "SELECT * FROM missing" },
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
// out includes a textDocument/publishDiagnostics notification.
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Or run it in a Web Worker and connect a standard LSP client
|
|
70
|
+
(CodeMirror, Monaco, ...):
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
// worker.ts
|
|
74
|
+
import { Engine, DialectManager, attachLspPort, type LspPortLike } from "syntaqlite";
|
|
75
|
+
|
|
76
|
+
const engine = new Engine();
|
|
77
|
+
await engine.load();
|
|
78
|
+
await new DialectManager().loadDefault(engine);
|
|
79
|
+
attachLspPort(engine, self as unknown as LspPortLike);
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Beyond standard LSP, the server accepts a `syntaqlite/setSessionContext`
|
|
83
|
+
extension request to set or clear the schema catalog
|
|
84
|
+
(`Engine.setSessionContextDdl` wraps it).
|
|
85
|
+
|
|
86
|
+
## One-shot analysis
|
|
87
|
+
|
|
88
|
+
For programmatic validation without an editor session. The catalog can
|
|
89
|
+
come from DDL, from structured `tables` and `views`, or both:
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
const analysis = engine.analyze("SELECT c FROM users", {
|
|
93
|
+
schemaDdl: "CREATE TABLE users(id INTEGER, name TEXT);",
|
|
94
|
+
});
|
|
95
|
+
console.log(analysis.diagnostics);
|
|
96
|
+
// [{ message: "unknown column 'c'", severity: "error", ... }]
|
|
97
|
+
|
|
98
|
+
engine.analyze("SELECT id FROM logs", {
|
|
99
|
+
tables: [{name: "logs", columns: ["id", "ts"]}],
|
|
100
|
+
});
|
|
38
101
|
```
|
|
39
102
|
|
|
40
103
|
## Documentation
|
package/dist/engine.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { AnalyzeOptions, AnalyzeResult, DiagnosticsResult, DialectBinding, EmbeddedExtractResult, EmbeddedLanguage, EmscriptenModule, FormatOptions, ParseResult, TokenEntry } from "./types.js";
|
|
2
2
|
export interface CflagEntry {
|
|
3
3
|
name: string;
|
|
4
4
|
minVersion: number;
|
|
@@ -7,6 +7,10 @@ export interface CflagEntry {
|
|
|
7
7
|
export interface EngineConfig {
|
|
8
8
|
runtimeJsPath?: string;
|
|
9
9
|
runtimeWasmPath?: string;
|
|
10
|
+
/** Reuse an already-loaded runtime module instead of loading a new one.
|
|
11
|
+
* The engines share linear memory and loaded dialect modules but get
|
|
12
|
+
* independent WASM sessions (dialect, schema context, analysis state). */
|
|
13
|
+
runtime?: EmscriptenModule;
|
|
10
14
|
}
|
|
11
15
|
export declare class Engine {
|
|
12
16
|
status: string;
|
|
@@ -15,16 +19,12 @@ export declare class Engine {
|
|
|
15
19
|
private module;
|
|
16
20
|
private encoder;
|
|
17
21
|
private decoder;
|
|
22
|
+
private sessionNewRaw;
|
|
23
|
+
private sessionFreeRaw;
|
|
18
24
|
private setDialectRaw;
|
|
19
25
|
private clearDialectRaw;
|
|
20
26
|
private allocRaw;
|
|
21
27
|
private freeRaw;
|
|
22
|
-
private astRaw;
|
|
23
|
-
private astJsonRaw;
|
|
24
|
-
private fmtRaw;
|
|
25
|
-
private diagnosticsRaw;
|
|
26
|
-
private semanticTokensRaw;
|
|
27
|
-
private completionsRaw;
|
|
28
28
|
private resultPtrRaw;
|
|
29
29
|
private resultLenRaw;
|
|
30
30
|
private resultFreeRaw;
|
|
@@ -33,16 +33,25 @@ export declare class Engine {
|
|
|
33
33
|
private clearCflagRaw;
|
|
34
34
|
private clearAllCflagsRaw;
|
|
35
35
|
private getCflagListRaw;
|
|
36
|
-
private
|
|
37
|
-
private
|
|
38
|
-
private
|
|
39
|
-
private
|
|
40
|
-
private
|
|
36
|
+
private embeddedExtractRaw;
|
|
37
|
+
private embeddedDiagnosticsRaw;
|
|
38
|
+
private embeddedSemanticTokensRaw;
|
|
39
|
+
private lspMessageRaw;
|
|
40
|
+
private rpcRaw;
|
|
41
41
|
private currentLangMode;
|
|
42
|
+
/** Handle for the WASM session all calls run against. 0 = not created yet. */
|
|
43
|
+
private session;
|
|
44
|
+
/** Sequence for `syntaqlite/setSessionContext` request ids. */
|
|
45
|
+
private contextSeq;
|
|
42
46
|
/** Last session context applied, so it can be re-applied after dialect switches. */
|
|
43
47
|
private sessionContext;
|
|
44
48
|
constructor(config?: EngineConfig);
|
|
45
49
|
get ready(): boolean;
|
|
50
|
+
/** The underlying Emscripten module, e.g. to share with another Engine
|
|
51
|
+
* via `EngineConfig.runtime`. Undefined until load() completes. */
|
|
52
|
+
get runtimeModule(): EmscriptenModule | undefined;
|
|
53
|
+
/** Free the WASM session. The engine must not be used after this. */
|
|
54
|
+
dispose(): void;
|
|
46
55
|
updateStatus(text: string, isError?: boolean): void;
|
|
47
56
|
load(): Promise<void>;
|
|
48
57
|
private resolveRuntimeFn;
|
|
@@ -56,31 +65,54 @@ export declare class Engine {
|
|
|
56
65
|
setDialectPointer(ptr: number): void;
|
|
57
66
|
private reapplySessionContext;
|
|
58
67
|
clearDialectPointer(): void;
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
/** Parse SQL into AST JSON. Parse errors are data, not exceptions. */
|
|
69
|
+
parse(sql: string): ParseResult;
|
|
70
|
+
/** Format SQL. Throws when the input cannot be formatted. */
|
|
71
|
+
format(sql: string, opts?: FormatOptions): string;
|
|
72
|
+
/** Tokenize SQL. Throws on malformed input. */
|
|
73
|
+
tokenize(sql: string): TokenEntry[];
|
|
74
|
+
/** Semantic tokens for an embedded-language document (see setLanguageMode).
|
|
75
|
+
* Returns a pre-encoded Uint32Array (5 u32s per token) or undefined on
|
|
76
|
+
* failure. SQL documents are served over LSP (`textDocument/semanticTokens`).
|
|
77
|
+
* @experimental Embedded language support is experimental and may change. */
|
|
78
|
+
embeddedSemanticTokens(source: string): Uint32Array | undefined;
|
|
79
|
+
/** Diagnostics for an embedded-language document (see setLanguageMode).
|
|
80
|
+
* SQL documents are served over LSP (`textDocument/publishDiagnostics`).
|
|
81
|
+
* @experimental Embedded language support is experimental and may change. */
|
|
82
|
+
embeddedDiagnostics(source: string): DiagnosticsResult;
|
|
83
|
+
/** Whether this runtime exposes the LSP JSON-RPC entry point. */
|
|
84
|
+
get lspSupported(): boolean;
|
|
85
|
+
/** Handle one LSP JSON-RPC message against this engine's in-process
|
|
86
|
+
* language server. Returns the outgoing messages as parsed objects
|
|
87
|
+
* (response plus server notifications). Drive it exactly like a
|
|
88
|
+
* standalone LSP server, lifecycle included. */
|
|
89
|
+
lspMessage(message: string | object): unknown[];
|
|
90
|
+
/** Validate SQL in one shot without an editor session. Schema-aware when
|
|
91
|
+
* a catalog is provided via `schemaDdl`, `tables`, or `views`. Throws on
|
|
92
|
+
* malformed input. */
|
|
93
|
+
analyze(sql: string, opts?: AnalyzeOptions): AnalyzeResult;
|
|
94
|
+
/** One-shot JSON-RPC op — the CLI `serve json` protocol. Returns the
|
|
95
|
+
* op's result value; throws on error. */
|
|
96
|
+
private rpc;
|
|
97
|
+
/** Set the active language mode. Diagnostics, semantic tokens, and extraction
|
|
98
|
+
* dispatch to the SQL or embedded implementation based on this mode.
|
|
71
99
|
* @experimental Embedded language support is experimental and may change. */
|
|
72
100
|
setLanguageMode(lang: "sql" | EmbeddedLanguage): void;
|
|
73
101
|
/** Extract SQL fragments from `source`. Returns empty in SQL mode (O(1) fast path).
|
|
74
|
-
* In embedded mode the WASM extractor runs
|
|
102
|
+
* In embedded mode the WASM extractor runs for the language set by setLanguageMode.
|
|
75
103
|
* @experimental Embedded language support is experimental and may change. */
|
|
76
|
-
|
|
104
|
+
extract(source: string): EmbeddedExtractResult;
|
|
77
105
|
setSqliteVersion(version: string): void;
|
|
78
106
|
setCflag(name: string): void;
|
|
79
107
|
clearCflag(name: string): void;
|
|
80
108
|
clearAllCflags(): void;
|
|
81
109
|
getCflagList(): CflagEntry[];
|
|
110
|
+
/** Set the schema session context from structured catalog JSON, via the
|
|
111
|
+
* `syntaqlite/setSessionContext` extension request. Throws on rejection. */
|
|
82
112
|
setSessionContext(json: string): void;
|
|
83
113
|
clearSessionContext(): void;
|
|
114
|
+
/** Set the schema session context from DDL. DDL that fails to parse is
|
|
115
|
+
* reported in `error`; statements that did parse are still applied. */
|
|
84
116
|
setSessionContextDdl(sql: string): {
|
|
85
117
|
ok: true;
|
|
86
118
|
} | {
|
|
@@ -89,5 +121,9 @@ export declare class Engine {
|
|
|
89
121
|
};
|
|
90
122
|
private applySessionContextJson;
|
|
91
123
|
private applySessionContextDdl;
|
|
124
|
+
/** Send a `syntaqlite/setSessionContext` extension request to the
|
|
125
|
+
* language server. Returns the (possibly empty) DDL parse errors;
|
|
126
|
+
* throws if the server rejects the request. */
|
|
127
|
+
private applySessionContext;
|
|
92
128
|
}
|
|
93
129
|
//# sourceMappingURL=engine.d.ts.map
|
package/dist/engine.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
|