feat: add sqlc

This commit is contained in:
AJ ONeal
2024-09-17 06:18:21 +00:00
parent f4ec7ca640
commit 231b6d12e4
4 changed files with 386 additions and 0 deletions

264
sqlc/README.md Normal file
View File

@@ -0,0 +1,264 @@
---
title: sqlc
homepage: https://github.com/sqlc-dev/sqlc
tagline: |
sqlc: generate code from SQL (not the other way around)
---
To update or switch versions, run `webi sqlc@stable` (or `@v1.27`, `@beta`,
etc).
## Cheat Sheet
1. Create a `sqlc.yaml` (see templates below)
```yaml
version: '2'
sql:
- engine: 'postgresql'
schema: './sql/migrations/'
queries: './sql/queries/'
gen:
json|go|typescript|kotlin|python:
out: './db/'
# ...
# (see language-specific examples below)
```
2. Create the migration, query, and code directories
```sh
mkdir -p ./sql/migrations/
mkdir -p ./sql/queries/
mkdir -p ./db/
```
3. Generate
```sh
sqlc compile # (dry-run)
sqlc generate -f ./sqlc.yaml
ls ./db/
```
## Table of Contents
- Files
- Starter sqlc.yaml
- JSON (language agnostic)
- Go
- TypeScript
- Python
- Kotlin
- Shell Completions
- fish
- zsh
- bash
- powershell
### Files
These are the files / directories that are created and/or modified with this
install:
```text
~/.config/envman/PATH.env
~/.local/bin/sqlc
# shell completions
~/.profile
~/.zshrc
~/.config/fish/config.fsh
```
### Starter sqlc.yaml
#### JSON
```yaml
version: '2'
plugins:
- name: ts
wasm:
url: https://downloads.sqlc.dev/plugin/sqlc-gen-typescript_0.1.3.wasm
sha256: 287df8f6cc06377d67ad5ba02c9e0f00c585509881434d15ea8bd9fc751a9368
sql:
- engine: 'postgresql'
schema: './sql/migrations/'
queries: './sql/queries/'
gen:
json:
out: './db/json/'
filename: 'db.json'
indent: ' '
```
See:
- <https://docs.sqlc.dev/en/latest/reference/config.html#json>
#### Go
```yaml
version: '2'
sql:
- engine: 'postgresql'
schema: './sql/migrations/'
queries: './sql/queries/'
gen:
go:
package: 'db'
out: './db/'
sql_package: 'pgx/v5'
```
See also:
- <https://docs.sqlc.dev/en/latest/tutorials/getting-started-postgresql.html>
#### Node
The query functions will be generated **as TypeScript**, but you can use `tsc`
to transform them **to JavaScript** (shown below).
`sqlc.yaml`:
```yaml
version: '2'
plugins:
- name: ts
wasm:
url: https://downloads.sqlc.dev/plugin/sqlc-gen-typescript_0.1.3.wasm
sha256: 287df8f6cc06377d67ad5ba02c9e0f00c585509881434d15ea8bd9fc751a9368
sql:
- engine: 'postgresql'
schema: './sql/migrations/'
queries: './sql/queries/'
codegen:
- out: './db/ts/'
plugin: ts
options:
runtime: node
driver: pg
```
Use `ts-to-jsdoc` to transpile from TypeScript to readable JavaScript + JSDoc
source code:
```sh
npm install --location=global ts-to-jsdoc
sqlc generate -f ./sqlc.yaml
ts-to-jsdoc -f -o ./db/ ./db/ts/
```
Converting from ESM to Node is also simple:
**with [sd](./sd)**:
```sh
sd '(/.*@import.*/)' '$1\n\nlet Queries = module.exports;' ./db/*.js
sd 'export const (\w+) =' '\nQueries.$1 =' ./db/*.js
sd ' (\w+Query)\b' ' Queries.$1' ./db/*.js
sd 'export async function (\w+)' 'Queries.$1 = async function ' ./db/*.js
sd --flags m '([^\n])\n/\*\*' '$1\n\n/**' ./db/*.js
```
**with js**:
```js
let Fs = require('fs/promises');
let Path = require('path');
async function main() {
// ex: ./db/
let dir = process.argv[2];
// let namespace = process.argv[3]; // 'Queries' for now
let entries = await Fs.readdir(dir);
for (let entry of entries) {
let isJs = entry.endsWith('.js');
if (!isJs) {
continue;
}
console.log(`processing ${entry}`);
let path = Path.join(dir, entry);
let js = await Fs.readFile(path, 'utf8');
js = js.replace(/(.*@import.*)/, '$1\n\nlet Queries = module.exports;');
js = js.replace(/export const (\w+) =/g, '\nQueries.$1 =');
js = js.replace(/ (\w+Query)\b/g, ' Queries.$1');
js = js.replace(
/export async function (\w+)/g,
'Queries.$1 = async function ',
);
js = js.replace(/([^\n])\n\/\*\*/gm, '$1\n\n/**');
await Fs.writeFile(path, js, 'utf8');
}
}
main();
```
**with vim**:
```vim
:%s:export const \(\w\+\) =:\rQueries.\1 =:gc
:%s:export async function \(\w\+\):Queries.\1 = async function :gc
:%s:/\*\*:\r/**:gc
```
See also:
- <https://github.com/sqlc-dev/sqlc-gen-typescript>
#### Kotlin
See:
- <https://docs.sqlc.dev/en/latest/guides/migrating-to-sqlc-gen-kotlin.html>
- <https://github.com/sqlc-dev/sqlc-gen-kotlin>
#### Python
See:
- <https://docs.sqlc.dev/en/latest/guides/migrating-to-sqlc-gen-python.html>
- <https://github.com/sqlc-dev/sqlc-gen-python>
### Completions
Supported shells include:
- [fish](#fish)
- [zsh](#zsh)
- [bash](#bash)
- [powershell](#powershell)
### fish
```sh
sqlc completion fish | source &&
echo 'status is-interactive ; and sqlc completion fish | source' >> ~/.config/fish/config.fish
```
### zsh
```sh
sqlc completion zsh | source &&
echo 'eval "$(sqlc completion zsh)"' >> ~/.zshrc
```
### bash
```sh
sqlc completion bash | source &&
echo 'eval "$(sqlc completion bash)"' >> ~/.bashrc
```
### powershell
```pwsh
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
Add-Content $PROFILE 'sqlc completion powershell | Out-String | Invoke-Expression'
. $PROFILE
```

62
sqlc/install.ps1 Normal file
View File

@@ -0,0 +1,62 @@
#!/usr/bin/env pwsh
################
# Install sqlc #
################
# Every package should define these variables
$pkg_cmd_name = "sqlc"
$pkg_dst_cmd = "$Env:USERPROFILE\.local\bin\sqlc.exe"
$pkg_dst_bin = "$Env:USERPROFILE\.local\bin"
$pkg_dst = "$pkg_dst_cmd"
$pkg_src_cmd = "$Env:USERPROFILE\.local\opt\sqlc-v$Env:WEBI_VERSION\bin\sqlc.exe"
$pkg_src_bin = "$Env:USERPROFILE\.local\opt\sqlc-v$Env:WEBI_VERSION\bin"
$pkg_src_dir = "$Env:USERPROFILE\.local\opt\sqlc-v$Env:WEBI_VERSION"
$pkg_src = "$pkg_src_cmd"
$pkg_download_dir = "$Env:USERPROFILE\Downloads\webi\$pkg_cmd_name\$Env:WEBI_VERSION"
$pkg_download_file = "$pkg_download_dir\$Env:WEBI_PKG_FILE"
# Fetch archive
IF (!(Test-Path -Path "$pkg_download_file")) {
New-Item "$pkg_download_dir" -ItemType Directory -Force | Out-Null
Write-Output " Downloading $pkg_cmd_name v$Env:WEBI_VERSION from $Env:WEBI_PKG_URL to $pkg_download_file"
& curl.exe -A "$Env:WEBI_UA" -fsSL "$Env:WEBI_PKG_URL" -o "$pkg_download_file.part"
& Move-Item "$pkg_download_file.part" "$pkg_download_file"
}
IF (!(Test-Path -Path "$pkg_src_cmd")) {
Write-Output " Installing sqlc v$Env:WEBI_VERSION"
# Remove any leftover tmp cruft and recreate the unpack
Remove-Item -Path ".local\tmp\sqlc-v$Env:WEBI_VERSION" -Recurse -ErrorAction Ignore
New-Item ".local\tmp\sqlc-v$Env:WEBI_VERSION" -ItemType Directory -Force | Out-Null
# Unpack archive file into this temporary directory
Push-Location ".local\tmp\sqlc-v$Env:WEBI_VERSION"
# Windows BSD-tar handles zip. Imagine that.
Write-Output " Unpacking $pkg_download_file"
& tar xf "$pkg_download_file"
Pop-Location
# Settle unpacked archive into place
Write-Output " Install Location: $pkg_src_cmd"
New-Item "$pkg_src_bin" -ItemType Directory -Force | Out-Null
Move-Item -Path ".local\tmp\sqlc-v$Env:WEBI_VERSION.\sqlc.exe" -Destination "$pkg_src_bin"
# Remove any leftover tmp cruft & exit tmp
Remove-Item -Path ".local\tmp\sqlc-v$Env:WEBI_VERSION" -Recurse -ErrorAction Ignore
Pop-Location
}
Write-Output " Copying into '$pkg_dst_cmd' from '$pkg_src_cmd'"
Remove-Item -Path "$pkg_dst_cmd" -Recurse -ErrorAction Ignore | Out-Null
New-Item "$pkg_dst_bin" -ItemType Directory -Force | Out-Null
Copy-Item -Path "$pkg_src" -Destination "$pkg_dst" -Recurse
$version_output = & "$pkg_dst_cmd" version
$version_line = $version_output |
Select-String -Pattern 'v\d+\.\d+'
Write-Output " Installed $version_line"

43
sqlc/install.sh Normal file
View File

@@ -0,0 +1,43 @@
#!/bin/sh
# shellcheck disable=SC2034
__init_sqlc() {
set -e
set -u
################
# Install sqlc #
################
# Every package should define these 6 variables
pkg_cmd_name="sqlc"
pkg_dst_cmd="$HOME/.local/bin/sqlc"
pkg_dst="$pkg_dst_cmd"
pkg_src_cmd="$HOME/.local/opt/sqlc-v$WEBI_VERSION/bin/sqlc"
pkg_src_dir="$HOME/.local/opt/sqlc-v$WEBI_VERSION"
pkg_src="$pkg_src_cmd"
pkg_install() {
# mkdir -p "$HOME/.local/opt/sqlc-v1.27.0/bin"
mkdir -p "$(dirname "$pkg_src_cmd")"
# mv ./sqlc* "$HOME/.local/opt/sqlc-v1.27.0/bin/sqlc"
mv ./"$pkg_cmd_name"* "$pkg_src_cmd"
# chmod a+x "$HOME/.local/opt/sqlc-v1.27.0/bin/sqlc"
chmod a+x "$pkg_src_cmd"
}
pkg_get_current_version() {
# 'sqlc version' has output in this format:
# v1.27.0
# This trims it down to just the version number:
# 1.27.0
sqlc version 2> /dev/null |
head -n 1 |
sed 's:^v::'
}
}
__init_sqlc

17
sqlc/releases.js Normal file
View File

@@ -0,0 +1,17 @@
'use strict';
var github = require('../_common/github.js');
var owner = 'sqlc-dev';
var repo = 'sqlc';
module.exports = async function () {
let all = await github(null, owner, repo);
return all;
};
if (module === require.main) {
module.exports().then(function (all) {
all = require('../_webi/normalize.js')(all);
console.info(JSON.stringify(all));
});
}