Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds browser (WASM) support #34

Merged
merged 14 commits into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@ libs/
npm-debug.log
libpg_query/**/*.a
libpg_query/**/*.h
wasm/libpg-query.js
*.wasm
.cache
91 changes: 91 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
WASM_OUT_DIR := wasm
WASM_OUT_NAME := libpg-query
WASM_MODULE_NAME := PgQueryModule
LIBPG_QUERY_REPO := https://github.com/pganalyze/libpg_query.git
LIBPG_QUERY_TAG := 15-4.2.4
CACHE_DIR := .cache

OS ?= $(shell uname -s)
ARCH ?= $(shell uname -m)

ifdef EMSCRIPTEN
PLATFORM := emscripten
else ifeq ($(OS),Darwin)
PLATFORM := darwin
else ifeq ($(OS),Linux)
PLATFORM := linux
else
$(error Unsupported platform: $(OS))
endif

ifdef EMSCRIPTEN
ARCH := wasm
endif

PLATFORM_ARCH := $(PLATFORM)-$(ARCH)
SRC_FILES := $(wildcard src/*.cc)
LIBPG_QUERY_DIR := $(CACHE_DIR)/$(PLATFORM_ARCH)/libpg_query/$(LIBPG_QUERY_TAG)
LIBPG_QUERY_ARCHIVE := $(LIBPG_QUERY_DIR)/libpg_query.a
LIBPG_QUERY_HEADER := $(LIBPG_QUERY_DIR)/pg_query.h
CXXFLAGS := -O3

ifdef EMSCRIPTEN
OUT_FILES := $(foreach EXT,.js .wasm,$(WASM_OUT_DIR)/$(WASM_OUT_NAME)$(EXT))
else
OUT_FILES := build/Release/queryparser.node $(wildcard build/*)
endif

# Clone libpg_query source (lives in CACHE_DIR)
$(LIBPG_QUERY_DIR):
mkdir -p $(CACHE_DIR)
git clone -b $(LIBPG_QUERY_TAG) --single-branch $(LIBPG_QUERY_REPO) $(LIBPG_QUERY_DIR)

$(LIBPG_QUERY_HEADER): $(LIBPG_QUERY_DIR)

# Build libpg_query
$(LIBPG_QUERY_ARCHIVE): $(LIBPG_QUERY_DIR)
cd $(LIBPG_QUERY_DIR); $(MAKE) build

# Build libpg-query-node (based on platform)
$(OUT_FILES): $(LIBPG_QUERY_ARCHIVE) $(LIBPG_QUERY_HEADER) $(SRC_FILES)
ifdef EMSCRIPTEN
@ $(CXX) \
$(CXXFLAGS) \
-DNAPI_HAS_THREADS \
-I$(LIBPG_QUERY_DIR) \
-I./node_modules/emnapi/include \
-I./node_modules/node-addon-api \
-L./node_modules/emnapi/lib/wasm32-emscripten \
-L$(LIBPG_QUERY_DIR) \
--js-library=./node_modules/emnapi/dist/library_napi.js \
-sEXPORTED_FUNCTIONS="['_malloc','_free','_napi_register_wasm_v1','_node_api_module_get_api_version_v1']" \
-sEXPORT_NAME="$(WASM_MODULE_NAME)" \
-sENVIRONMENT="web" \
-sMODULARIZE=1 \
-sEXPORT_ES6=1 \
-fexceptions \
-lpg_query \
-lemnapi-basic \
-o $@ \
$(SRC_FILES)
else
# if not wasm, defer to node-gyp
yarn rebuild
endif

# Commands
build: $(OUT_FILES)

build-cache: $(LIBPG_QUERY_ARCHIVE) $(LIBPG_QUERY_HEADER)

rebuild: clean build

rebuild-cache: clean-cache build-cache

clean:
-@ rm -r $(OUT_FILES) > /dev/null 2>&1

clean-cache:
-@ rm -rf $(LIBPG_QUERY_DIR)

.PHONY: build build-cache rebuild rebuild-cache clean clean-cache
8 changes: 4 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const PgQuery = require('./build/Release/queryparser');
const PgQuery = require('./build/Release/queryparser.node');

module.exports = {
parseQuery(query) {
Expand Down Expand Up @@ -26,14 +26,14 @@ module.exports = {
},

fingerprint(query) {
return new Promise((resolve, reject) =>{
return new Promise((resolve, reject) => {
PgQuery.fingerprintAsync(query, (err, result) => {
err ? reject(err) : resolve(result);
})
});
});
},

fingerprintSync(query) {
return PgQuery.fingerprintSync(query);
}
},
};
32 changes: 30 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,36 @@
"publishConfig": {
"access": "public"
},
"files": [
"binding.gyp",
"index.js",
"index.d.ts",
"libpg_query/*",
"script/*",
"src/*",
"wasm/*"
],
"exports": {
".": {
"types": "./index.d.ts",
"browser": "./wasm/index.js",
"node": "./index.js",
"default": "./index.js"
},
"./wasm": {
"types": "./index.d.ts",
"default": "./wasm/index.js"
}
},
"scripts": {
"configure": "node-pre-gyp configure",
"install": "node-pre-gyp install --fallback-to-build",
"rebuild": "node-pre-gyp configure rebuild",
"make:wasm": "docker run --rm -v $(pwd):/src -u $(id -u):$(id -g) emscripten/emsdk emmake make",
"build:wasm": "yarn make:wasm build",
"rebuild:wasm": "yarn make:wasm rebuild",
"clean:wasm": "yarn make:wasm clean",
"clean-cache:wasm": "yarn make:wasm clean-cache",
"test": "mocha --timeout 5000",
"binary:build": "node-pre-gyp rebuild package",
"binary:publish": "AWS_PROFILE=supabase-dev node-pre-gyp publish"
Expand All @@ -24,12 +50,14 @@
},
"devDependencies": {
"chai": "^3.5.0",
"emnapi": "^0.43.1",
"lodash": "^4.17.15",
"mocha": "^5.2.0"
},
"dependencies": {
"@emnapi/runtime": "^0.43.1",
"@mapbox/node-pre-gyp": "^1.0.8",
"node-addon-api": "^1.6.3",
"node-addon-api": "^7.0.0",
"node-gyp": "^8.0.0"
},
"keywords": [
Expand All @@ -47,4 +75,4 @@
"host": "https://supabase-public-artifacts-bucket.s3.amazonaws.com",
"remote_path": "./libpg-query-node/"
}
}
}
1 change: 1 addition & 0 deletions test/webpack/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dist/*.js
14 changes: 14 additions & 0 deletions test/webpack/dist/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8" />
<title>libpg-query web</title>
</head>

<body>
<script src="main.js"></script>
<h2>Check the console for the parsed SQL.</h2>
</body>

</html>
14 changes: 14 additions & 0 deletions test/webpack/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "webpack-test",
"version": "0.0.0",
"private": true,
"scripts": {
"dev": "webpack serve --open",
"build": "webpack"
},
"devDependencies": {
"webpack": "^5.89.0",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1"
}
}
7 changes: 7 additions & 0 deletions test/webpack/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { parseQuery } from '../../../wasm';

const sql = 'select * from customers;';
const result = await parseQuery(sql);

console.log(sql);
console.log(result);
15 changes: 15 additions & 0 deletions test/webpack/webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const path = require('path');

module.exports = {
entry: './src/index.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
},
devServer: {
static: './dist',
client: {
overlay: false,
},
},
};
Loading