diff --git a/.githooks/pre-commit b/.githooks/pre-commit index 9e8f865..2f226a8 100755 --- a/.githooks/pre-commit +++ b/.githooks/pre-commit @@ -6,7 +6,7 @@ cargo fmt --check || { exit 1 } -# Lint TypeScript (if ts/node_modules exists) -if [ -d "ts/node_modules" ]; then - cd ts && npm run lint || exit 1 +# Lint TypeScript (if node_modules exists) +if [ -d "node_modules" ]; then + npm run lint || exit 1 fi diff --git a/.github/workflows/check-upstream.yml b/.github/workflows/check-upstream.yml index 54c658d..9340fe7 100644 --- a/.github/workflows/check-upstream.yml +++ b/.github/workflows/check-upstream.yml @@ -83,9 +83,9 @@ jobs: - [ ] Run \`./scripts/upgrade.sh ${latest}\` - [ ] Check for new dialects - [ ] Check for AST changes - - [ ] Update \`ts/src/types/ast.ts\` if needed + - [ ] Update \`src/types/ast.ts\` if needed - [ ] Run \`./scripts/build.sh\` - - [ ] Run tests: \`cd ts && npm test\` + - [ ] Run tests: \`npm test\` - [ ] Update README if needed - [ ] Publish to npm ` diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d720cf8..0ad9ee0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,16 +7,18 @@ on: - 'v*' paths: - 'src/**' - - 'ts/**' + - 'tests/**' - 'Cargo.*' + - 'package*.json' - '.github/workflows/ci.yml' - '.githooks/**' pull_request: branches: [main] paths: - 'src/**' - - 'ts/**' + - 'tests/**' - 'Cargo.*' + - 'package*.json' - '.github/workflows/ci.yml' - '.githooks/**' @@ -40,10 +42,8 @@ jobs: with: node-version: '20' cache: 'npm' - cache-dependency-path: ts/package-lock.json - name: Install npm dependencies - working-directory: ts run: npm ci - name: Run pre-commit checks @@ -53,14 +53,12 @@ jobs: uses: jetli/wasm-pack-action@v0.4.0 - name: Build WASM - run: wasm-pack build --target web --out-dir ts/wasm + run: wasm-pack build --target web --out-dir wasm - name: Build TypeScript - working-directory: ts run: npm run build:ts - name: Run tests - working-directory: ts run: npm test - name: Upload build artifacts @@ -69,11 +67,11 @@ jobs: with: name: build-artifacts path: | - ts/wasm/ - ts/dist/ - ts/package.json - ts/package-lock.json - ts/README.md + wasm/ + dist/ + package.json + package-lock.json + README.md retention-days: 1 publish: @@ -89,7 +87,6 @@ jobs: uses: actions/download-artifact@v4 with: name: build-artifacts - path: ts - name: Setup Node.js uses: actions/setup-node@v4 @@ -98,7 +95,6 @@ jobs: registry-url: 'https://registry.npmjs.org' - name: Publish to npm - working-directory: ts run: | VERSION="${GITHUB_REF#refs/tags/v}" if [[ "$VERSION" == *"rc"* ]]; then @@ -108,4 +104,4 @@ jobs: fi env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - NPM_CONFIG_PROVENANCE: true \ No newline at end of file + NPM_CONFIG_PROVENANCE: true diff --git a/.gitignore b/.gitignore index f195dc0..d741936 100644 --- a/.gitignore +++ b/.gitignore @@ -6,14 +6,13 @@ node_modules/ # WASM build output /pkg -/ts/wasm +/wasm # TypeScript build output -/ts/dist +/dist # Test coverage /coverage -/ts/coverage # npm pack output *.tgz diff --git a/README.md b/README.md deleted file mode 120000 index 339ebe2..0000000 --- a/README.md +++ /dev/null @@ -1 +0,0 @@ -ts/README.md \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..b019771 --- /dev/null +++ b/README.md @@ -0,0 +1,105 @@ +# sqlparser-ts + +[![npm version](https://img.shields.io/npm/v/@guanmingchiu/sqlparser-ts.svg)](https://www.npmjs.com/package/@guanmingchiu/sqlparser-ts) +[![npm downloads](https://img.shields.io/npm/dm/@guanmingchiu/sqlparser-ts.svg)](https://www.npmjs.com/package/@guanmingchiu/sqlparser-ts) +[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE) +[![WebAssembly](https://img.shields.io/badge/WebAssembly-powered-blueviolet.svg)](https://webassembly.org/) +[![sqlparser](https://img.shields.io/badge/sqlparser--rs-v0.61.0-orange.svg)](https://github.com/apache/datafusion-sqlparser-rs) + +SQL parser for JavaScript and TypeScript, powered by [datafusion-sqlparser-rs](https://github.com/apache/datafusion-sqlparser-rs) via WebAssembly. + +## Features + +- Parse SQL into a detailed AST with full TypeScript types +- Support 14 SQL dialects (PostgreSQL, MySQL, SQLite, BigQuery, and more) +- Run in Node.js and browsers +- Stay small (~600KB gzipped) and fast (Rust + WebAssembly) +- Ship zero native dependencies + +## Installation + +```bash +npm install @guanmingchiu/sqlparser-ts +``` + +## Usage + +```typescript +import { init, parse, format, validate } from '@guanmingchiu/sqlparser-ts'; + +// Initialize WASM module (must be called once before using any parser functions) +await init(); + +// Parse SQL into AST +const ast = parse('SELECT * FROM users'); + +// With specific dialect +const ast = parse('SELECT * FROM users WHERE id = $1', 'postgresql'); + +// Format SQL +const sql = format('select * from users'); +// "SELECT * FROM users" + +// Validate SQL (throws on invalid) +validate('SELECT * FROM users'); // ok +``` + +### Vite Configuration + +WASM packages must be excluded from Vite's dev server [dependency pre-bundling](https://github.com/vitejs/vite/discussions/9256). This only affects the dev server. Production builds use Rollup instead of esbuild and handle WASM files correctly. + +```typescript +// vite.config.ts +export default defineConfig({ + optimizeDeps: { + exclude: ['@guanmingchiu/sqlparser-ts'], + }, +}); +``` + +### Working with AST + +```typescript +// Parse and inspect +const ast = parse('SELECT id, name FROM users WHERE active = true'); +console.log(JSON.stringify(ast, null, 2)); + +// Multiple statements +const statements = parse(` + SELECT * FROM users; + SELECT * FROM orders; +`); +console.log(statements.length); // 2 + +// Modify AST and convert back to SQL +const ast = parse('SELECT * FROM users')[0]; +// ... modify ast ... +const sql = format(JSON.stringify([ast])); +``` + +### Error Handling + +```typescript +try { + parse('SELEC * FORM users'); +} catch (e) { + console.error(e.message); // Parse error details +} +``` + +## Supported Dialects + +`generic`, `ansi`, `mysql`, `postgresql`, `sqlite`, `snowflake`, `redshift`, `mssql`, `clickhouse`, `bigquery`, `duckdb`, `databricks`, `hive`, `oracle` + +## Versioning + +Follows [Semantic Versioning](https://semver.org/) with upstream tracking: + +- MAJOR.MINOR: Tracks upstream [datafusion-sqlparser-rs](https://github.com/apache/datafusion-sqlparser-rs) +- PATCH: sqlparser-ts specific releases + +Example: `0.60.4` = upstream 0.60 + 4 sqlparser-ts releases + +## License + +Apache-2.0 diff --git a/benchmark/package.json b/benchmark/package.json index b7381f6..43c94cb 100644 --- a/benchmark/package.json +++ b/benchmark/package.json @@ -13,6 +13,6 @@ }, "dependencies": { "node-sql-parser": "^5.3.8", - "@guanmingchiu/sqlparser-ts": "file:../ts" + "@guanmingchiu/sqlparser-ts": "file:.." } } diff --git a/ts/eslint.config.js b/eslint.config.js similarity index 91% rename from ts/eslint.config.js rename to eslint.config.js index 1ab8523..056d031 100644 --- a/ts/eslint.config.js +++ b/eslint.config.js @@ -3,7 +3,7 @@ import unusedImports from 'eslint-plugin-unused-imports'; export default tseslint.config( { - ignores: ['dist/**', 'wasm/**', 'coverage/**'], + ignores: ['dist/**', 'wasm/**', 'coverage/**', '**/*.rs'], }, ...tseslint.configs.recommended, { diff --git a/ts/package-lock.json b/package-lock.json similarity index 100% rename from ts/package-lock.json rename to package-lock.json diff --git a/ts/package.json b/package.json similarity index 93% rename from ts/package.json rename to package.json index 2a76edd..a81ba15 100644 --- a/ts/package.json +++ b/package.json @@ -20,7 +20,7 @@ ], "scripts": { "build": "npm run build:wasm && npm run build:ts", - "build:wasm": "cd .. && wasm-pack build --target web --out-dir ts/wasm && rm -f ts/wasm/.gitignore", + "build:wasm": "wasm-pack build --target web --out-dir wasm && rm -f wasm/.gitignore", "build:ts": "tsdown", "test": "vitest run", "test:watch": "vitest", diff --git a/scripts/build.sh b/scripts/build.sh index 90c637c..d406194 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -22,11 +22,10 @@ fi echo "Step 1: Building WASM module..." cd "$PROJECT_DIR" -wasm-pack build --target web --out-dir ts/wasm +wasm-pack build --target web --out-dir wasm echo "" echo "Step 2: Installing npm dependencies..." -cd "$PROJECT_DIR/ts" npm install echo "" @@ -39,10 +38,10 @@ echo "Build complete!" echo "==========================================" echo "" echo "Output files:" -echo " - WASM: ts/wasm/" -echo " - ESM: ts/dist/index.mjs" -echo " - CJS: ts/dist/index.cjs" -echo " - Types: ts/dist/index.d.{mts,cts}" +echo " - WASM: wasm/" +echo " - ESM: dist/index.mjs" +echo " - CJS: dist/index.cjs" +echo " - Types: dist/index.d.{mts,cts}" echo "" -echo "To run tests: cd ts && npm test" -echo "To publish: cd ts && npm publish" +echo "To run tests: npm test" +echo "To publish: npm publish" diff --git a/scripts/upgrade.sh b/scripts/upgrade.sh index e11501f..376040f 100755 --- a/scripts/upgrade.sh +++ b/scripts/upgrade.sh @@ -21,12 +21,10 @@ sed -i '' "s/sqlparser = { version = \"[^\"]*\"/sqlparser = { version = \"${VERS sed -i '' "s/^version = \"[^\"]*\"/version = \"${VERSION}\"/" "$PROJECT_DIR/Cargo.toml" # Update package.json -sed -i '' "s/\"version\": \"[^\"]*\"/\"version\": \"${VERSION}\"/" "$PROJECT_DIR/ts/package.json" +sed -i '' "s/\"version\": \"[^\"]*\"/\"version\": \"${VERSION}\"/" "$PROJECT_DIR/package.json" # Update README badge -README=$(readlink -f "$PROJECT_DIR/README.md" 2>/dev/null || readlink "$PROJECT_DIR/README.md") -[[ "$README" != /* ]] && README="$PROJECT_DIR/$README" -sed -i '' "s/sqlparser--rs-v[0-9.]*-orange/sqlparser--rs-v${VERSION}-orange/" "$README" +sed -i '' "s/sqlparser--rs-v[0-9.]*-orange/sqlparser--rs-v${VERSION}-orange/" "$PROJECT_DIR/README.md" echo "" echo "Updated to v${VERSION}. Next steps:" @@ -40,11 +38,11 @@ echo " - Check changed field names" echo "" echo "3. Update dialects if new ones added:" echo " - src/lib.rs (Rust bindings)" -echo " - ts/src/dialects.ts (TypeScript)" +echo " - src/dialects.ts (TypeScript)" echo "" echo "4. Build and test:" echo " ./scripts/build.sh" -echo " cd ts && npm test" +echo " npm test" echo "" echo "5. Commit and tag:" echo " git add -A" diff --git a/ts/src/dialects.ts b/src/dialects.ts similarity index 100% rename from ts/src/dialects.ts rename to src/dialects.ts diff --git a/ts/src/index.ts b/src/index.ts similarity index 100% rename from ts/src/index.ts rename to src/index.ts diff --git a/ts/src/parser.ts b/src/parser.ts similarity index 100% rename from ts/src/parser.ts rename to src/parser.ts diff --git a/ts/src/types/ast.ts b/src/types/ast.ts similarity index 100% rename from ts/src/types/ast.ts rename to src/types/ast.ts diff --git a/ts/src/types/errors.ts b/src/types/errors.ts similarity index 100% rename from ts/src/types/errors.ts rename to src/types/errors.ts diff --git a/ts/src/types/index.ts b/src/types/index.ts similarity index 100% rename from ts/src/types/index.ts rename to src/types/index.ts diff --git a/ts/src/wasm.ts b/src/wasm.ts similarity index 100% rename from ts/src/wasm.ts rename to src/wasm.ts diff --git a/ts/tests/README.md b/tests/README.md similarity index 100% rename from ts/tests/README.md rename to tests/README.md diff --git a/ts/tests/builds.test.ts b/tests/builds.test.ts similarity index 100% rename from ts/tests/builds.test.ts rename to tests/builds.test.ts diff --git a/ts/tests/dialects/bigquery.test.ts b/tests/dialects/bigquery.test.ts similarity index 100% rename from ts/tests/dialects/bigquery.test.ts rename to tests/dialects/bigquery.test.ts diff --git a/ts/tests/dialects/clickhouse.test.ts b/tests/dialects/clickhouse.test.ts similarity index 100% rename from ts/tests/dialects/clickhouse.test.ts rename to tests/dialects/clickhouse.test.ts diff --git a/ts/tests/dialects/common.test.ts b/tests/dialects/common.test.ts similarity index 100% rename from ts/tests/dialects/common.test.ts rename to tests/dialects/common.test.ts diff --git a/ts/tests/dialects/databricks.test.ts b/tests/dialects/databricks.test.ts similarity index 100% rename from ts/tests/dialects/databricks.test.ts rename to tests/dialects/databricks.test.ts diff --git a/ts/tests/dialects/duckdb.test.ts b/tests/dialects/duckdb.test.ts similarity index 100% rename from ts/tests/dialects/duckdb.test.ts rename to tests/dialects/duckdb.test.ts diff --git a/ts/tests/dialects/hive.test.ts b/tests/dialects/hive.test.ts similarity index 100% rename from ts/tests/dialects/hive.test.ts rename to tests/dialects/hive.test.ts diff --git a/ts/tests/dialects/mssql.test.ts b/tests/dialects/mssql.test.ts similarity index 100% rename from ts/tests/dialects/mssql.test.ts rename to tests/dialects/mssql.test.ts diff --git a/ts/tests/dialects/mysql.test.ts b/tests/dialects/mysql.test.ts similarity index 100% rename from ts/tests/dialects/mysql.test.ts rename to tests/dialects/mysql.test.ts diff --git a/ts/tests/dialects/oracle.test.ts b/tests/dialects/oracle.test.ts similarity index 100% rename from ts/tests/dialects/oracle.test.ts rename to tests/dialects/oracle.test.ts diff --git a/ts/tests/dialects/postgresql.test.ts b/tests/dialects/postgresql.test.ts similarity index 100% rename from ts/tests/dialects/postgresql.test.ts rename to tests/dialects/postgresql.test.ts diff --git a/ts/tests/dialects/redshift.test.ts b/tests/dialects/redshift.test.ts similarity index 100% rename from ts/tests/dialects/redshift.test.ts rename to tests/dialects/redshift.test.ts diff --git a/ts/tests/dialects/snowflake.test.ts b/tests/dialects/snowflake.test.ts similarity index 100% rename from ts/tests/dialects/snowflake.test.ts rename to tests/dialects/snowflake.test.ts diff --git a/ts/tests/dialects/sqlite.test.ts b/tests/dialects/sqlite.test.ts similarity index 100% rename from ts/tests/dialects/sqlite.test.ts rename to tests/dialects/sqlite.test.ts diff --git a/ts/tests/errors/parse-errors.test.ts b/tests/errors/parse-errors.test.ts similarity index 100% rename from ts/tests/errors/parse-errors.test.ts rename to tests/errors/parse-errors.test.ts diff --git a/ts/tests/parser.test.ts b/tests/parser.test.ts similarity index 100% rename from ts/tests/parser.test.ts rename to tests/parser.test.ts diff --git a/ts/tests/setup.ts b/tests/setup.ts similarity index 100% rename from ts/tests/setup.ts rename to tests/setup.ts diff --git a/ts/tests/statements/ddl.test.ts b/tests/statements/ddl.test.ts similarity index 100% rename from ts/tests/statements/ddl.test.ts rename to tests/statements/ddl.test.ts diff --git a/ts/tests/statements/dml.test.ts b/tests/statements/dml.test.ts similarity index 100% rename from ts/tests/statements/dml.test.ts rename to tests/statements/dml.test.ts diff --git a/ts/tests/statements/select.test.ts b/tests/statements/select.test.ts similarity index 100% rename from ts/tests/statements/select.test.ts rename to tests/statements/select.test.ts diff --git a/ts/tests/test-utils.ts b/tests/test-utils.ts similarity index 100% rename from ts/tests/test-utils.ts rename to tests/test-utils.ts diff --git a/ts/README.md b/ts/README.md deleted file mode 100644 index b019771..0000000 --- a/ts/README.md +++ /dev/null @@ -1,105 +0,0 @@ -# sqlparser-ts - -[![npm version](https://img.shields.io/npm/v/@guanmingchiu/sqlparser-ts.svg)](https://www.npmjs.com/package/@guanmingchiu/sqlparser-ts) -[![npm downloads](https://img.shields.io/npm/dm/@guanmingchiu/sqlparser-ts.svg)](https://www.npmjs.com/package/@guanmingchiu/sqlparser-ts) -[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE) -[![WebAssembly](https://img.shields.io/badge/WebAssembly-powered-blueviolet.svg)](https://webassembly.org/) -[![sqlparser](https://img.shields.io/badge/sqlparser--rs-v0.61.0-orange.svg)](https://github.com/apache/datafusion-sqlparser-rs) - -SQL parser for JavaScript and TypeScript, powered by [datafusion-sqlparser-rs](https://github.com/apache/datafusion-sqlparser-rs) via WebAssembly. - -## Features - -- Parse SQL into a detailed AST with full TypeScript types -- Support 14 SQL dialects (PostgreSQL, MySQL, SQLite, BigQuery, and more) -- Run in Node.js and browsers -- Stay small (~600KB gzipped) and fast (Rust + WebAssembly) -- Ship zero native dependencies - -## Installation - -```bash -npm install @guanmingchiu/sqlparser-ts -``` - -## Usage - -```typescript -import { init, parse, format, validate } from '@guanmingchiu/sqlparser-ts'; - -// Initialize WASM module (must be called once before using any parser functions) -await init(); - -// Parse SQL into AST -const ast = parse('SELECT * FROM users'); - -// With specific dialect -const ast = parse('SELECT * FROM users WHERE id = $1', 'postgresql'); - -// Format SQL -const sql = format('select * from users'); -// "SELECT * FROM users" - -// Validate SQL (throws on invalid) -validate('SELECT * FROM users'); // ok -``` - -### Vite Configuration - -WASM packages must be excluded from Vite's dev server [dependency pre-bundling](https://github.com/vitejs/vite/discussions/9256). This only affects the dev server. Production builds use Rollup instead of esbuild and handle WASM files correctly. - -```typescript -// vite.config.ts -export default defineConfig({ - optimizeDeps: { - exclude: ['@guanmingchiu/sqlparser-ts'], - }, -}); -``` - -### Working with AST - -```typescript -// Parse and inspect -const ast = parse('SELECT id, name FROM users WHERE active = true'); -console.log(JSON.stringify(ast, null, 2)); - -// Multiple statements -const statements = parse(` - SELECT * FROM users; - SELECT * FROM orders; -`); -console.log(statements.length); // 2 - -// Modify AST and convert back to SQL -const ast = parse('SELECT * FROM users')[0]; -// ... modify ast ... -const sql = format(JSON.stringify([ast])); -``` - -### Error Handling - -```typescript -try { - parse('SELEC * FORM users'); -} catch (e) { - console.error(e.message); // Parse error details -} -``` - -## Supported Dialects - -`generic`, `ansi`, `mysql`, `postgresql`, `sqlite`, `snowflake`, `redshift`, `mssql`, `clickhouse`, `bigquery`, `duckdb`, `databricks`, `hive`, `oracle` - -## Versioning - -Follows [Semantic Versioning](https://semver.org/) with upstream tracking: - -- MAJOR.MINOR: Tracks upstream [datafusion-sqlparser-rs](https://github.com/apache/datafusion-sqlparser-rs) -- PATCH: sqlparser-ts specific releases - -Example: `0.60.4` = upstream 0.60 + 4 sqlparser-ts releases - -## License - -Apache-2.0 diff --git a/ts/tsconfig.json b/tsconfig.json similarity index 100% rename from ts/tsconfig.json rename to tsconfig.json diff --git a/ts/tsdown.config.ts b/tsdown.config.ts similarity index 100% rename from ts/tsdown.config.ts rename to tsdown.config.ts diff --git a/ts/vitest.config.ts b/vitest.config.ts similarity index 100% rename from ts/vitest.config.ts rename to vitest.config.ts