Skip to content
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
40 changes: 37 additions & 3 deletions .github/workflows/publish.reusable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,23 @@ jobs:
exit 1
fi

- name: Generate Packages (deprecated)
id: generate-packages-deprecated
run: node packages/@postgrestools/postgrestools/scripts/generate-packages.mjs
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_TAG: ${{ inputs.release-tag }}
PRERELEASE: ${{ inputs.is-prerelease }}

- name: Generate Packages
id: generate-packages
run: node packages/@postgrestools/postgrestools/scripts/generate-packages.mjs
run: node packages/@postgres-language-server/cli/scripts/generate-packages.mjs
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_TAG: ${{ inputs.release-tag }}
PRERELEASE: ${{ inputs.is-prerelease }}

- name: Publish npm packages as nightly
- name: Publish npm packages as nightly (deprecated)
if: inputs.is-prerelease == 'true'
run: |
for package in packages/@postgrestools/*; do
Expand All @@ -50,7 +58,16 @@ jobs:
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} #

- name: Publish npm packages as latest
- name: Publish npm packages as nightly
if: inputs.is-prerelease == 'true'
run: |
for package in packages/@postgres-language-server/*; do
npm publish "$package" --tag nightly --access public --provenance
done
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} #

- name: Publish npm packages as latest (deprecated)
if: inputs.is-prerelease != 'true'
run: |
for package in packages/@postgrestools/*; do
Expand All @@ -66,3 +83,20 @@ jobs:
done
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Publish npm packages as latest
if: inputs.is-prerelease != 'true'
run: |
for package in packages/@postgres-language-server/*; do
version="${{ inputs.release-tag }}"
npm_package_name=$(jq -r ".name" "$package/package.json")

if npm view "$npm_package_name@$version" version 2>/dev/null; then
echo "Package $npm_package_name@$version already exists, skipping..."
else
echo "Publishing $npm_package_name@$version..."
npm publish "$package" --tag latest --access public --provenance
fi
done
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
35 changes: 29 additions & 6 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,6 @@ jobs:

runs-on: ${{ matrix.config.os }}

outputs:
artifact_url: ${{ steps.upload-artifacts.outputs.artifact-url }}

steps:
- uses: actions/checkout@v4
with:
Expand Down Expand Up @@ -96,17 +93,22 @@ jobs:
if: matrix.config.os == 'windows-2022'
run: |
mkdir dist
# deprecated
cp target/${{ matrix.config.target }}/release/postgrestools.exe ./dist/postgrestools_${{ matrix.config.target }}
cp target/${{ matrix.config.target }}/release/postgres-language-server.exe ./dist/postgres-language-server_${{ matrix.config.target }}

- name: 👦 Name the Binary
if: matrix.config.os != 'windows-2022'
run: |
mkdir dist
# deprecated
cp target/${{ matrix.config.target }}/release/postgrestools ./dist/postgrestools_${{ matrix.config.target }}
cp target/${{ matrix.config.target }}/release/postgres-language-server ./dist/postgres-language-server_${{ matrix.config.target }}

# It is not possible to return the artifacts from the matrix jobs individually: Matrix outputs overwrite each other.
# A common workaround is to upload and download the resulting artifacts.
- name: 👆 Upload Artifacts
id: upload-artifacts
- name: 👆 Upload Artifacts (deprecated)
id: upload-artifacts-deprecated
uses: actions/upload-artifact@v4
with:
name: postgrestools_${{ matrix.config.target }}
Expand All @@ -117,6 +119,20 @@ jobs:
compression-level: 2
if-no-files-found: error

# It is not possible to return the artifacts from the matrix jobs individually: Matrix outputs overwrite each other.
# A common workaround is to upload and download the resulting artifacts.
- name: 👆 Upload Artifacts
id: upload-artifacts
uses: actions/upload-artifact@v4
with:
name: postgres-language-server_${{ matrix.config.target }}
path: ./dist/postgres-language-server_*
# The default compression level is 6; this took the binary down from 350 to 330MB.
# It is recommended to use a lower level for binaries, since the compressed result is not much smaller,
# and the higher levels of compression take much longer.
compression-level: 2
if-no-files-found: error

create_changelog_and_release:
runs-on: ubuntu-latest
needs: [extract_version, build_and_test] # make sure that tests & build work correctly
Expand All @@ -142,12 +158,19 @@ jobs:
echo "Tag does not match: ${{ steps.create_changelog.outputs.version }} vs ${{ needs.extract_version.outputs.version }}"
exit 1

- name: 👇 Download Artifacts (deprecated)
uses: actions/download-artifact@v4
id: download-deprecated
with:
merge-multiple: true
pattern: postgrestools_*

- name: 👇 Download Artifacts
uses: actions/download-artifact@v4
id: download
with:
merge-multiple: true
pattern: postgrestools_*
pattern: postgres-language-server_*

- name: 📂 Create Release
uses: softprops/action-gh-release@v2
Expand Down
4 changes: 4 additions & 0 deletions crates/pgt_cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,7 @@ doctest = false
[[bin]]
name = "postgrestools"
path = "src/main.rs"

[[bin]]
name = "postgres-language-server"
path = "src/main.rs"
32 changes: 32 additions & 0 deletions packages/@postgres-language-server/backend-jsonrpc/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "@postgres-language-server/backend-jsonrpc",
"version": "<placeholder>",
"main": "dist/index.js",
"scripts": {
"test": "bun test",
"test:ci": "bun build && bun test",
"build": "bun build ./src/index.ts --outdir ./dist --target node"
},
"files": ["dist/", "README.md"],
"repository": {
"type": "git",
"url": "git+https://github.com/supabase-community/postgres-language-server.git",
"directory": "packages/@postgres-language-server/backend-jsonrpc"
},
"author": "Supabase Community",
"bugs": "ttps://github.com/supabase-community/postgres-language-server/issues",
"description": "Bindings to the JSON-RPC Workspace API of the Postgres Language Tools daemon",
"keywords": ["TypeScript", "Postgres"],
"license": "MIT",
"publishConfig": {
"provenance": true
},
"optionalDependencies": {
"@postgres-language-server/cli-win32-x64": "<placeholder>",
"@postgres-language-server/cli-win32-arm64": "<placeholder>",
"@postgres-language-server/cli-darwin-x64": "<placeholder>",
"@postgres-language-server/cli-darwin-arm64": "<placeholder>",
"@postgres-language-server/cli-linux-x64": "<placeholder>",
"@postgres-language-server/cli-linux-arm64": "<placeholder>"
}
}
74 changes: 74 additions & 0 deletions packages/@postgres-language-server/backend-jsonrpc/src/command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { execSync } from "node:child_process";

/**
* Gets the path of the binary for the current platform
*
* @returns Filesystem path to the binary, or null if no prebuilt distribution exists for the current platform
*/
export function getCommand(): string | null {
const { platform, arch } = process;

const PLATFORMS: Partial<
Record<
NodeJS.Platform | "linux-musl",
Partial<Record<NodeJS.Architecture, string>>
>
> = {
win32: {
x64: "@postgres-language-server/cli-x86_64-windows-msvc/postgres-language-server.exe",
arm64: "@postgres-language-server/cli-aarch64-windows-msvc/postgres-language-server.exe",
},
darwin: {
x64: "@postgres-language-server/cli-x86_64-apple-darwin/postgres-language-server",
arm64: "@postgres-language-server/cli-aarch64-apple-darwin/postgres-language-server",
},
linux: {
x64: "@postgres-language-server/cli-x86_64-linux-gnu/postgres-language-server",
arm64: "@postgres-language-server/cli-aarch64-linux-gnu/postgres-language-server",
},
"linux-musl": {
x64: "@postgres-language-server/cli-x86_64-linux-musl/postgres-language-server",
// no arm64 build for musl
},
};

function isMusl() {
let stderr = "";
try {
stderr = execSync("ldd --version", {
stdio: [
"ignore", // stdin
"pipe", // stdout – glibc systems print here
"pipe", // stderr – musl systems print here
],
}).toString();
} catch (err: unknown) {
if (hasStdErr(err)) {
stderr = err.stderr;
}
}
if (stderr.indexOf("musl") > -1) {
return true;
}
return false;
}

function getPlatform(): NodeJS.Platform | "linux-musl" {
if (platform === "linux") {
return isMusl() ? "linux-musl" : "linux";
}

return platform;
}

const binPath = PLATFORMS?.[getPlatform()]?.[arch];
if (!binPath) {
return null;
}

return require.resolve(binPath);
}

function hasStdErr(err: unknown): err is { stderr: string } {
return !!(err as any)?.stderr;
}
46 changes: 46 additions & 0 deletions packages/@postgres-language-server/backend-jsonrpc/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { getCommand } from "./command";
import { createSocket } from "./socket";
import { Transport } from "./transport";
import { type Workspace, createWorkspace as wrapTransport } from "./workspace";

/**
* Create an instance of the Workspace client connected to a remote daemon
* instance through the JSON-RPC protocol
*
* @returns A Workspace client, or null if the underlying platform is not supported
*/
export async function createWorkspace(): Promise<Workspace | null> {
const command = getCommand();
if (!command) {
return null;
}

return createWorkspaceWithBinary(command);
}

/**
* Create an instance of the Workspace client connected to a remote daemon
* instance through the JSON-RPC protocol, using the provided command to spawn
* the daemon if necessary
*
* @param command Path to the binary
* @returns A Workspace client, or null if the underlying platform is not supported
*/
export async function createWorkspaceWithBinary(
command: string,
): Promise<Workspace> {
const socket = await createSocket(command);
const transport = new Transport(socket);

await transport.request("initialize", {
capabilities: {},
client_info: {
name: "@postgres-language-server/backend-jsonrpc",
version: "0.0.0",
},
});

return wrapTransport(transport);
}

export * from "./workspace";
47 changes: 47 additions & 0 deletions packages/@postgres-language-server/backend-jsonrpc/src/socket.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { spawn } from "node:child_process";
import { type Socket, connect } from "node:net";

function getSocket(command: string): Promise<string> {
return new Promise((resolve, reject) => {
const process = spawn(command, ["__print_socket"], {
stdio: "pipe",
});

process.on("error", reject);

let pipeName = "";
process.stdout.on("data", (data) => {
pipeName += data.toString("utf-8");
});

process.on("exit", (code) => {
if (code === 0) {
resolve(pipeName.trimEnd());
} else {
reject(
new Error(
`Command '${command} __print_socket' exited with code ${code}`,
),
);
}
});
});
}

/**
* Ensure the daemon server is running and create a Socket connected to the RPC channel
*
* @param command Path to the daemon binary
* @returns Socket instance connected to the daemon
*/
export async function createSocket(command: string): Promise<Socket> {
const path = await getSocket(command);
const socket = connect(path);

await new Promise((resolve, reject) => {
socket.once("error", reject);
socket.once("ready", resolve);
});

return socket;
}
Loading