feat: sqlc, nix formatting
This commit is contained in:
parent
32f85fd0be
commit
967e2650ad
@ -12,4 +12,5 @@
|
||||
|
||||
# Server
|
||||
/server/client/
|
||||
/server/tmp/
|
||||
/server/tmp/
|
||||
/server/build/
|
12
.github/workflows/lint.yaml
vendored
12
.github/workflows/lint.yaml
vendored
@ -9,7 +9,7 @@ on:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
release:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
@ -20,9 +20,11 @@ jobs:
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
|
||||
- name: Install NPM Packages
|
||||
working-directory: ./client
|
||||
run: npm ci --legacy-peer-deps
|
||||
- name: Use Cachix
|
||||
uses: cachix/cachix-action@v16
|
||||
with:
|
||||
name: treli
|
||||
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
|
||||
|
||||
- name: Lint
|
||||
run: nix develop --command ts-lint
|
||||
run: nix develop --command trevstack-lint
|
8
.github/workflows/release.yaml
vendored
8
.github/workflows/release.yaml
vendored
@ -19,9 +19,15 @@ jobs:
|
||||
uses: cachix/install-nix-action@v31
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
|
||||
- name: Use Cachix
|
||||
uses: cachix/cachix-action@v16
|
||||
with:
|
||||
name: treli
|
||||
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
|
||||
|
||||
- name: Build
|
||||
run: nix develop --command ts-build
|
||||
run: nix develop --command trevstack-build
|
||||
|
||||
- name: Create Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
|
6
.gitignore
vendored
6
.gitignore
vendored
@ -1,7 +1,5 @@
|
||||
.env
|
||||
|
||||
/docker-compose.*
|
||||
|
||||
/result
|
||||
/.direnv/
|
||||
/build/
|
||||
/result/
|
||||
/build/
|
24
.scripts/build.sh
Executable file
24
.scripts/build.sh
Executable file
@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
git_root=$(git rev-parse --show-toplevel)
|
||||
url=$(git config --get remote.origin.url)
|
||||
name=$(basename -s .git "${url}")
|
||||
git_version=$(git describe --tags --abbrev=0)
|
||||
version=${git_version#v}
|
||||
|
||||
echo "building client"
|
||||
cd "${git_root}"
|
||||
nix build .#trevstack-client
|
||||
cp -a result/. server/client
|
||||
chmod -R u+w server/client
|
||||
|
||||
echo "building server"
|
||||
cd "${git_root}/server"
|
||||
echo "Building ${name}-windows-amd64-${version}.exe"
|
||||
GOOS=windows GOARCH=amd64 go build -o "./build/${name}-windows-amd64-${version}.exe" .
|
||||
echo "Building ${name}-linux-amd64-${version}"
|
||||
GOOS=linux GOARCH=amd64 go build -o "./build/${name}-linux-amd64-${version}" .
|
||||
echo "Building ${name}-linux-amd64-${version}"
|
||||
GOOS=linux GOARCH=arm64 go build -o "./build/${name}-linux-arm64-${version}" .
|
||||
echo "Building ${name}-linux-arm-${version}"
|
||||
GOOS=linux GOARCH=arm go build -o "./build/${name}-linux-arm-${version}" .
|
22
.scripts/bump.sh
Executable file
22
.scripts/bump.sh
Executable file
@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
git_root=$(git rev-parse --show-toplevel)
|
||||
git_version=$(git describe --tags --abbrev=0)
|
||||
version=${git_version#v}
|
||||
next_version=$(echo "${version}" | awk -F. -v OFS=. '{$NF += 1 ; print}')
|
||||
|
||||
echo "bumping client"
|
||||
cd "${git_root}/client"
|
||||
npm version "${next_version}"
|
||||
git add package-lock.json
|
||||
git add package.json
|
||||
|
||||
echo "bumping nix"
|
||||
cd "${git_root}"
|
||||
nix-update --flake --version "${next_version}" default
|
||||
git add flake.nix
|
||||
|
||||
git commit -m "bump: v${version} -> v${next_version}"
|
||||
git push origin main
|
||||
git tag -a "v${next_version}" -m "bump: v${version} -> v${next_version}"
|
||||
git push origin "v${next_version}"
|
23
.scripts/lint.sh
Executable file
23
.scripts/lint.sh
Executable file
@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
git_root=$(git rev-parse --show-toplevel)
|
||||
|
||||
echo "linting client"
|
||||
cd "${git_root}/client"
|
||||
npx prettier --check .
|
||||
npx eslint .
|
||||
npx svelte-check
|
||||
|
||||
echo "linting server"
|
||||
cd "${git_root}/server"
|
||||
revive -config revive.toml -set_exit_status ./...
|
||||
sqlfluff lint
|
||||
|
||||
echo "linting protobuf"
|
||||
cd "${git_root}"
|
||||
buf lint
|
||||
|
||||
echo "linting nix"
|
||||
cd "${git_root}"
|
||||
nix fmt -- flake.nix --check
|
||||
nix flake check --all-systems
|
30
.scripts/update.sh
Executable file
30
.scripts/update.sh
Executable file
@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
git_root=$(git rev-parse --show-toplevel)
|
||||
|
||||
echo "updating client"
|
||||
cd "${git_root}/client"
|
||||
npm update --save
|
||||
if ! git diff --exit-code package.json package-lock.json; then
|
||||
git add package-lock.json
|
||||
git add package.json
|
||||
git commit -m "build(client): updated npm dependencies"
|
||||
fi
|
||||
|
||||
echo "updating server"
|
||||
cd "${git_root}/server"
|
||||
go get -u
|
||||
go mod tidy
|
||||
if ! git diff --exit-code go.mod go.sum; then
|
||||
git add go.mod
|
||||
git add go.sum
|
||||
git commit -m "build(go): updated go dependencies"
|
||||
fi
|
||||
|
||||
echo "updating nix"
|
||||
cd "${git_root}"
|
||||
nix-update --flake --version=skip default
|
||||
if ! git diff --exit-code flake.nix; then
|
||||
git add flake.nix
|
||||
git commit -m "build(nix): updated nix hashes"
|
||||
fi
|
72
.treli.yaml
Normal file
72
.treli.yaml
Normal file
@ -0,0 +1,72 @@
|
||||
apps:
|
||||
buf:
|
||||
color: "#cba6f7"
|
||||
exts:
|
||||
- proto
|
||||
onstart: buf lint
|
||||
onchange: buf lint && buf generate
|
||||
|
||||
eslint:
|
||||
color: "#fab387"
|
||||
dir: client
|
||||
exts:
|
||||
- js
|
||||
- ts
|
||||
- svelte
|
||||
onstart: npx eslint .
|
||||
onchange: npx eslint .
|
||||
|
||||
golang:
|
||||
color: "#89dceb"
|
||||
dir: server
|
||||
exts:
|
||||
- go
|
||||
onstart: go build -o ./tmp/app -tags dev && ./tmp/app
|
||||
onchange: go build -o ./tmp/app -tags dev && ./tmp/app
|
||||
|
||||
prettier:
|
||||
color: "#fab387"
|
||||
dir: client
|
||||
exts:
|
||||
- js
|
||||
- ts
|
||||
- svelte
|
||||
onstart: npx prettier --check .
|
||||
onchange: npx prettier --check . || npx prettier --write .
|
||||
|
||||
revive:
|
||||
color: "#89dceb"
|
||||
dir: server
|
||||
exts:
|
||||
- go
|
||||
onstart: revive -config revive.toml -set_exit_status ./...
|
||||
onchange: revive -config revive.toml -set_exit_status ./...
|
||||
|
||||
sqlc:
|
||||
color: "#a6e3a1"
|
||||
dir: server
|
||||
exts:
|
||||
- sql
|
||||
onstart: sqlc vet
|
||||
onchange: sqlc vet && sqlc generate
|
||||
|
||||
sqlfluff:
|
||||
color: "#a6e3a1"
|
||||
dir: server/db
|
||||
exts:
|
||||
- sql
|
||||
onstart: sqlfluff lint
|
||||
onchange: sqlfluff lint
|
||||
|
||||
svelte:
|
||||
color: "#fab387"
|
||||
dir: client
|
||||
exts:
|
||||
- svelte
|
||||
onstart: npx svelte-check
|
||||
onchange: npx svelte-check
|
||||
|
||||
vite:
|
||||
color: "#fab387"
|
||||
dir: client
|
||||
onstart: npx vite dev
|
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@ -3,4 +3,5 @@
|
||||
"go.lintFlags": [
|
||||
"--config=server/revive.toml"
|
||||
],
|
||||
"sqlfluff.config": "server/db/.sqlfluff",
|
||||
}
|
10
buf.gen.yaml
10
buf.gen.yaml
@ -4,24 +4,24 @@ managed:
|
||||
enabled: true
|
||||
override:
|
||||
- file_option: go_package_prefix
|
||||
value: github.com/spotdemo4/trevstack/server/internal/services
|
||||
value: github.com/spotdemo4/trevstack/server/internal/connect
|
||||
|
||||
plugins:
|
||||
- local: protoc-gen-go
|
||||
out: server/internal/services
|
||||
out: server/internal/connect
|
||||
opt: paths=source_relative
|
||||
|
||||
- local: protoc-gen-connect-go
|
||||
out: server/internal/services
|
||||
out: server/internal/connect
|
||||
opt: paths=source_relative
|
||||
|
||||
- local: protoc-gen-es
|
||||
out: client/src/lib/services
|
||||
out: client/src/lib/connect
|
||||
opt: target=ts
|
||||
|
||||
- local: protoc-gen-connect-openapi
|
||||
out: client/static/openapi
|
||||
strategy: all
|
||||
opt:
|
||||
- base=base.openapi.yaml
|
||||
- base=openapi.base.yaml
|
||||
- path=openapi.yaml
|
||||
|
@ -12,4 +12,4 @@ node_modules
|
||||
static
|
||||
|
||||
# Generated
|
||||
src/lib/services
|
||||
src/lib/connect
|
585
client/package-lock.json
generated
585
client/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -19,12 +19,12 @@
|
||||
"@eslint/compat": "^1.2.8",
|
||||
"@eslint/js": "^9.18.0",
|
||||
"@lucide/svelte": "^0.479.0",
|
||||
"@scalar/api-reference": "^1.28.17",
|
||||
"@scalar/api-reference": "^1.28.19",
|
||||
"@simplewebauthn/browser": "^13.1.0",
|
||||
"@sveltejs/adapter-static": "^3.0.8",
|
||||
"@sveltejs/kit": "^2.20.5",
|
||||
"@sveltejs/kit": "^2.20.7",
|
||||
"@sveltejs/vite-plugin-svelte": "^5.0.3",
|
||||
"@tailwindcss/vite": "^4.1.3",
|
||||
"@tailwindcss/vite": "^4.1.4",
|
||||
"bits-ui": "^1.3.19",
|
||||
"cbor2": "^1.12.0",
|
||||
"clsx": "^2.1.1",
|
||||
@ -35,14 +35,14 @@
|
||||
"prettier": "^3.5.3",
|
||||
"prettier-plugin-svelte": "^3.3.3",
|
||||
"prettier-plugin-tailwindcss": "^0.6.11",
|
||||
"svelte": "^5.25.12",
|
||||
"svelte-check": "^4.1.5",
|
||||
"svelte": "^5.27.0",
|
||||
"svelte-check": "^4.1.6",
|
||||
"svelte-sonner": "^0.3.28",
|
||||
"tailwind-merge": "^3.2.0",
|
||||
"tailwindcss": "^4.0.13",
|
||||
"tw-animate-css": "^1.2.5",
|
||||
"typescript": "^5.8.3",
|
||||
"typescript-eslint": "^8.29.1",
|
||||
"typescript-eslint": "^8.30.1",
|
||||
"vite": "^6.2.6"
|
||||
}
|
||||
}
|
||||
|
@ -12,16 +12,16 @@ import type { Message } from "@bufbuild/protobuf";
|
||||
* Describes the file item/v1/item.proto.
|
||||
*/
|
||||
export const file_item_v1_item: GenFile = /*@__PURE__*/
|
||||
fileDesc("ChJpdGVtL3YxL2l0ZW0ucHJvdG8SB2l0ZW0udjEinAEKBEl0ZW0SDwoCaWQYASABKANIAIgBARIMCgRuYW1lGAIgASgJEhMKC2Rlc2NyaXB0aW9uGAMgASgJEg0KBXByaWNlGAQgASgCEhAKCHF1YW50aXR5GAUgASgFEi4KBWFkZGVkGAYgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcEgBiAEBQgUKA19pZEIICgZfYWRkZWQiHAoOR2V0SXRlbVJlcXVlc3QSCgoCaWQYASABKAMiLgoPR2V0SXRlbVJlc3BvbnNlEhsKBGl0ZW0YASABKAsyDS5pdGVtLnYxLkl0ZW0i3wEKD0dldEl0ZW1zUmVxdWVzdBIuCgVzdGFydBgBIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBIAIgBARIsCgNlbmQYAiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wSAGIAQESEwoGZmlsdGVyGAMgASgJSAKIAQESEgoFbGltaXQYBCABKAVIA4gBARITCgZvZmZzZXQYBSABKAVIBIgBAUIICgZfc3RhcnRCBgoEX2VuZEIJCgdfZmlsdGVyQggKBl9saW1pdEIJCgdfb2Zmc2V0Ij8KEEdldEl0ZW1zUmVzcG9uc2USHAoFaXRlbXMYASADKAsyDS5pdGVtLnYxLkl0ZW0SDQoFY291bnQYAiABKAMiMAoRQ3JlYXRlSXRlbVJlcXVlc3QSGwoEaXRlbRgBIAEoCzINLml0ZW0udjEuSXRlbSIxChJDcmVhdGVJdGVtUmVzcG9uc2USGwoEaXRlbRgBIAEoCzINLml0ZW0udjEuSXRlbSIwChFVcGRhdGVJdGVtUmVxdWVzdBIbCgRpdGVtGAEgASgLMg0uaXRlbS52MS5JdGVtIjEKElVwZGF0ZUl0ZW1SZXNwb25zZRIbCgRpdGVtGAEgASgLMg0uaXRlbS52MS5JdGVtIh8KEURlbGV0ZUl0ZW1SZXF1ZXN0EgoKAmlkGAEgASgDIhQKEkRlbGV0ZUl0ZW1SZXNwb25zZTLrAgoLSXRlbVNlcnZpY2USPgoHR2V0SXRlbRIXLml0ZW0udjEuR2V0SXRlbVJlcXVlc3QaGC5pdGVtLnYxLkdldEl0ZW1SZXNwb25zZSIAEkEKCEdldEl0ZW1zEhguaXRlbS52MS5HZXRJdGVtc1JlcXVlc3QaGS5pdGVtLnYxLkdldEl0ZW1zUmVzcG9uc2UiABJHCgpDcmVhdGVJdGVtEhouaXRlbS52MS5DcmVhdGVJdGVtUmVxdWVzdBobLml0ZW0udjEuQ3JlYXRlSXRlbVJlc3BvbnNlIgASRwoKVXBkYXRlSXRlbRIaLml0ZW0udjEuVXBkYXRlSXRlbVJlcXVlc3QaGy5pdGVtLnYxLlVwZGF0ZUl0ZW1SZXNwb25zZSIAEkcKCkRlbGV0ZUl0ZW0SGi5pdGVtLnYxLkRlbGV0ZUl0ZW1SZXF1ZXN0GhsuaXRlbS52MS5EZWxldGVJdGVtUmVzcG9uc2UiAEKdAQoLY29tLml0ZW0udjFCCUl0ZW1Qcm90b1ABWkZnaXRodWIuY29tL3Nwb3RkZW1vNC90cmV2c3RhY2svc2VydmVyL2ludGVybmFsL3NlcnZpY2VzL2l0ZW0vdjE7aXRlbXYxogIDSVhYqgIHSXRlbS5WMcoCB0l0ZW1cVjHiAhNJdGVtXFYxXEdQQk1ldGFkYXRh6gIISXRlbTo6VjFiBnByb3RvMw", [file_google_protobuf_timestamp]);
|
||||
fileDesc("ChJpdGVtL3YxL2l0ZW0ucHJvdG8SB2l0ZW0udjEigQEKBEl0ZW0SCgoCaWQYASABKAMSDAoEbmFtZRgCIAEoCRIpCgVhZGRlZBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASEwoLZGVzY3JpcHRpb24YBCABKAkSDQoFcHJpY2UYBSABKAISEAoIcXVhbnRpdHkYBiABKAUiHAoOR2V0SXRlbVJlcXVlc3QSCgoCaWQYASABKAMiLgoPR2V0SXRlbVJlc3BvbnNlEhsKBGl0ZW0YASABKAsyDS5pdGVtLnYxLkl0ZW0i3wEKD0dldEl0ZW1zUmVxdWVzdBIuCgVzdGFydBgBIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBIAIgBARIsCgNlbmQYAiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wSAGIAQESEwoGZmlsdGVyGAMgASgJSAKIAQESEgoFbGltaXQYBCABKAVIA4gBARITCgZvZmZzZXQYBSABKAVIBIgBAUIICgZfc3RhcnRCBgoEX2VuZEIJCgdfZmlsdGVyQggKBl9saW1pdEIJCgdfb2Zmc2V0Ij8KEEdldEl0ZW1zUmVzcG9uc2USHAoFaXRlbXMYASADKAsyDS5pdGVtLnYxLkl0ZW0SDQoFY291bnQYAiABKAMiVwoRQ3JlYXRlSXRlbVJlcXVlc3QSDAoEbmFtZRgBIAEoCRITCgtkZXNjcmlwdGlvbhgCIAEoCRINCgVwcmljZRgDIAEoAhIQCghxdWFudGl0eRgEIAEoBSJLChJDcmVhdGVJdGVtUmVzcG9uc2USCgoCaWQYASABKAMSKQoFYWRkZWQYAiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wIqcBChFVcGRhdGVJdGVtUmVxdWVzdBIKCgJpZBgBIAEoAxIRCgRuYW1lGAIgASgJSACIAQESGAoLZGVzY3JpcHRpb24YAyABKAlIAYgBARISCgVwcmljZRgEIAEoAkgCiAEBEhUKCHF1YW50aXR5GAUgASgFSAOIAQFCBwoFX25hbWVCDgoMX2Rlc2NyaXB0aW9uQggKBl9wcmljZUILCglfcXVhbnRpdHkiFAoSVXBkYXRlSXRlbVJlc3BvbnNlIh8KEURlbGV0ZUl0ZW1SZXF1ZXN0EgoKAmlkGAEgASgDIhQKEkRlbGV0ZUl0ZW1SZXNwb25zZTLrAgoLSXRlbVNlcnZpY2USPgoHR2V0SXRlbRIXLml0ZW0udjEuR2V0SXRlbVJlcXVlc3QaGC5pdGVtLnYxLkdldEl0ZW1SZXNwb25zZSIAEkEKCEdldEl0ZW1zEhguaXRlbS52MS5HZXRJdGVtc1JlcXVlc3QaGS5pdGVtLnYxLkdldEl0ZW1zUmVzcG9uc2UiABJHCgpDcmVhdGVJdGVtEhouaXRlbS52MS5DcmVhdGVJdGVtUmVxdWVzdBobLml0ZW0udjEuQ3JlYXRlSXRlbVJlc3BvbnNlIgASRwoKVXBkYXRlSXRlbRIaLml0ZW0udjEuVXBkYXRlSXRlbVJlcXVlc3QaGy5pdGVtLnYxLlVwZGF0ZUl0ZW1SZXNwb25zZSIAEkcKCkRlbGV0ZUl0ZW0SGi5pdGVtLnYxLkRlbGV0ZUl0ZW1SZXF1ZXN0GhsuaXRlbS52MS5EZWxldGVJdGVtUmVzcG9uc2UiAEKcAQoLY29tLml0ZW0udjFCCUl0ZW1Qcm90b1ABWkVnaXRodWIuY29tL3Nwb3RkZW1vNC90cmV2c3RhY2svc2VydmVyL2ludGVybmFsL2Nvbm5lY3QvaXRlbS92MTtpdGVtdjGiAgNJWFiqAgdJdGVtLlYxygIHSXRlbVxWMeICE0l0ZW1cVjFcR1BCTWV0YWRhdGHqAghJdGVtOjpWMWIGcHJvdG8z", [file_google_protobuf_timestamp]);
|
||||
|
||||
/**
|
||||
* @generated from message item.v1.Item
|
||||
*/
|
||||
export type Item = Message<"item.v1.Item"> & {
|
||||
/**
|
||||
* @generated from field: optional int64 id = 1;
|
||||
* @generated from field: int64 id = 1;
|
||||
*/
|
||||
id?: bigint;
|
||||
id: bigint;
|
||||
|
||||
/**
|
||||
* @generated from field: string name = 2;
|
||||
@ -29,24 +29,24 @@ export type Item = Message<"item.v1.Item"> & {
|
||||
name: string;
|
||||
|
||||
/**
|
||||
* @generated from field: string description = 3;
|
||||
* @generated from field: google.protobuf.Timestamp added = 3;
|
||||
*/
|
||||
added?: Timestamp;
|
||||
|
||||
/**
|
||||
* @generated from field: string description = 4;
|
||||
*/
|
||||
description: string;
|
||||
|
||||
/**
|
||||
* @generated from field: float price = 4;
|
||||
* @generated from field: float price = 5;
|
||||
*/
|
||||
price: number;
|
||||
|
||||
/**
|
||||
* @generated from field: int32 quantity = 5;
|
||||
* @generated from field: int32 quantity = 6;
|
||||
*/
|
||||
quantity: number;
|
||||
|
||||
/**
|
||||
* @generated from field: optional google.protobuf.Timestamp added = 6;
|
||||
*/
|
||||
added?: Timestamp;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -154,9 +154,24 @@ export const GetItemsResponseSchema: GenMessage<GetItemsResponse> = /*@__PURE__*
|
||||
*/
|
||||
export type CreateItemRequest = Message<"item.v1.CreateItemRequest"> & {
|
||||
/**
|
||||
* @generated from field: item.v1.Item item = 1;
|
||||
* @generated from field: string name = 1;
|
||||
*/
|
||||
item?: Item;
|
||||
name: string;
|
||||
|
||||
/**
|
||||
* @generated from field: string description = 2;
|
||||
*/
|
||||
description: string;
|
||||
|
||||
/**
|
||||
* @generated from field: float price = 3;
|
||||
*/
|
||||
price: number;
|
||||
|
||||
/**
|
||||
* @generated from field: int32 quantity = 4;
|
||||
*/
|
||||
quantity: number;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -171,9 +186,14 @@ export const CreateItemRequestSchema: GenMessage<CreateItemRequest> = /*@__PURE_
|
||||
*/
|
||||
export type CreateItemResponse = Message<"item.v1.CreateItemResponse"> & {
|
||||
/**
|
||||
* @generated from field: item.v1.Item item = 1;
|
||||
* @generated from field: int64 id = 1;
|
||||
*/
|
||||
item?: Item;
|
||||
id: bigint;
|
||||
|
||||
/**
|
||||
* @generated from field: google.protobuf.Timestamp added = 2;
|
||||
*/
|
||||
added?: Timestamp;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -188,9 +208,29 @@ export const CreateItemResponseSchema: GenMessage<CreateItemResponse> = /*@__PUR
|
||||
*/
|
||||
export type UpdateItemRequest = Message<"item.v1.UpdateItemRequest"> & {
|
||||
/**
|
||||
* @generated from field: item.v1.Item item = 1;
|
||||
* @generated from field: int64 id = 1;
|
||||
*/
|
||||
item?: Item;
|
||||
id: bigint;
|
||||
|
||||
/**
|
||||
* @generated from field: optional string name = 2;
|
||||
*/
|
||||
name?: string;
|
||||
|
||||
/**
|
||||
* @generated from field: optional string description = 3;
|
||||
*/
|
||||
description?: string;
|
||||
|
||||
/**
|
||||
* @generated from field: optional float price = 4;
|
||||
*/
|
||||
price?: number;
|
||||
|
||||
/**
|
||||
* @generated from field: optional int32 quantity = 5;
|
||||
*/
|
||||
quantity?: number;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -204,10 +244,6 @@ export const UpdateItemRequestSchema: GenMessage<UpdateItemRequest> = /*@__PURE_
|
||||
* @generated from message item.v1.UpdateItemResponse
|
||||
*/
|
||||
export type UpdateItemResponse = Message<"item.v1.UpdateItemResponse"> & {
|
||||
/**
|
||||
* @generated from field: item.v1.Item item = 1;
|
||||
*/
|
||||
item?: Item;
|
||||
};
|
||||
|
||||
/**
|
@ -10,7 +10,7 @@ import type { Message } from "@bufbuild/protobuf";
|
||||
* Describes the file user/v1/auth.proto.
|
||||
*/
|
||||
export const file_user_v1_auth: GenFile = /*@__PURE__*/
|
||||
fileDesc("ChJ1c2VyL3YxL2F1dGgucHJvdG8SB3VzZXIudjEiMgoMTG9naW5SZXF1ZXN0EhAKCHVzZXJuYW1lGAEgASgJEhAKCHBhc3N3b3JkGAIgASgJIh4KDUxvZ2luUmVzcG9uc2USDQoFdG9rZW4YASABKAkiTQoNU2lnblVwUmVxdWVzdBIQCgh1c2VybmFtZRgBIAEoCRIQCghwYXNzd29yZBgCIAEoCRIYChBjb25maXJtX3Bhc3N3b3JkGAMgASgJIhAKDlNpZ25VcFJlc3BvbnNlIg8KDUxvZ291dFJlcXVlc3QiEAoOTG9nb3V0UmVzcG9uc2UywQEKC0F1dGhTZXJ2aWNlEjgKBUxvZ2luEhUudXNlci52MS5Mb2dpblJlcXVlc3QaFi51c2VyLnYxLkxvZ2luUmVzcG9uc2UiABI7CgZTaWduVXASFi51c2VyLnYxLlNpZ25VcFJlcXVlc3QaFy51c2VyLnYxLlNpZ25VcFJlc3BvbnNlIgASOwoGTG9nb3V0EhYudXNlci52MS5Mb2dvdXRSZXF1ZXN0GhcudXNlci52MS5Mb2dvdXRSZXNwb25zZSIAQp0BCgtjb20udXNlci52MUIJQXV0aFByb3RvUAFaRmdpdGh1Yi5jb20vc3BvdGRlbW80L3RyZXZzdGFjay9zZXJ2ZXIvaW50ZXJuYWwvc2VydmljZXMvdXNlci92MTt1c2VydjGiAgNVWFiqAgdVc2VyLlYxygIHVXNlclxWMeICE1VzZXJcVjFcR1BCTWV0YWRhdGHqAghVc2VyOjpWMWIGcHJvdG8z");
|
||||
fileDesc("ChJ1c2VyL3YxL2F1dGgucHJvdG8SB3VzZXIudjEiMgoMTG9naW5SZXF1ZXN0EhAKCHVzZXJuYW1lGAEgASgJEhAKCHBhc3N3b3JkGAIgASgJIh4KDUxvZ2luUmVzcG9uc2USDQoFdG9rZW4YASABKAkiTQoNU2lnblVwUmVxdWVzdBIQCgh1c2VybmFtZRgBIAEoCRIQCghwYXNzd29yZBgCIAEoCRIYChBjb25maXJtX3Bhc3N3b3JkGAMgASgJIhAKDlNpZ25VcFJlc3BvbnNlIg8KDUxvZ291dFJlcXVlc3QiEAoOTG9nb3V0UmVzcG9uc2UywQEKC0F1dGhTZXJ2aWNlEjgKBUxvZ2luEhUudXNlci52MS5Mb2dpblJlcXVlc3QaFi51c2VyLnYxLkxvZ2luUmVzcG9uc2UiABI7CgZTaWduVXASFi51c2VyLnYxLlNpZ25VcFJlcXVlc3QaFy51c2VyLnYxLlNpZ25VcFJlc3BvbnNlIgASOwoGTG9nb3V0EhYudXNlci52MS5Mb2dvdXRSZXF1ZXN0GhcudXNlci52MS5Mb2dvdXRSZXNwb25zZSIAQpwBCgtjb20udXNlci52MUIJQXV0aFByb3RvUAFaRWdpdGh1Yi5jb20vc3BvdGRlbW80L3RyZXZzdGFjay9zZXJ2ZXIvaW50ZXJuYWwvY29ubmVjdC91c2VyL3YxO3VzZXJ2MaICA1VYWKoCB1VzZXIuVjHKAgdVc2VyXFYx4gITVXNlclxWMVxHUEJNZXRhZGF0YeoCCFVzZXI6OlYxYgZwcm90bzM");
|
||||
|
||||
/**
|
||||
* @generated from message user.v1.LoginRequest
|
@ -10,7 +10,7 @@ import type { Message } from "@bufbuild/protobuf";
|
||||
* Describes the file user/v1/user.proto.
|
||||
*/
|
||||
export const file_user_v1_user: GenFile = /*@__PURE__*/
|
||||
fileDesc("ChJ1c2VyL3YxL3VzZXIucHJvdG8SB3VzZXIudjEiXAoEVXNlchIKCgJpZBgBIAEoAxIQCgh1c2VybmFtZRgCIAEoCRIfChJwcm9maWxlX3BpY3R1cmVfaWQYAyABKANIAIgBAUIVChNfcHJvZmlsZV9waWN0dXJlX2lkIhAKDkdldFVzZXJSZXF1ZXN0Ii4KD0dldFVzZXJSZXNwb25zZRIbCgR1c2VyGAEgASgLMg0udXNlci52MS5Vc2VyIl0KFVVwZGF0ZVBhc3N3b3JkUmVxdWVzdBIUCgxvbGRfcGFzc3dvcmQYASABKAkSFAoMbmV3X3Bhc3N3b3JkGAIgASgJEhgKEGNvbmZpcm1fcGFzc3dvcmQYAyABKAkiNQoWVXBkYXRlUGFzc3dvcmRSZXNwb25zZRIbCgR1c2VyGAEgASgLMg0udXNlci52MS5Vc2VyIj4KEEdldEFQSUtleVJlcXVlc3QSEAoIcGFzc3dvcmQYASABKAkSGAoQY29uZmlybV9wYXNzd29yZBgCIAEoCSIgChFHZXRBUElLZXlSZXNwb25zZRILCgNrZXkYASABKAkiPgobVXBkYXRlUHJvZmlsZVBpY3R1cmVSZXF1ZXN0EhEKCWZpbGVfbmFtZRgBIAEoCRIMCgRkYXRhGAIgASgMIjsKHFVwZGF0ZVByb2ZpbGVQaWN0dXJlUmVzcG9uc2USGwoEdXNlchgBIAEoCzINLnVzZXIudjEuVXNlcjLPAgoLVXNlclNlcnZpY2USPgoHR2V0VXNlchIXLnVzZXIudjEuR2V0VXNlclJlcXVlc3QaGC51c2VyLnYxLkdldFVzZXJSZXNwb25zZSIAElMKDlVwZGF0ZVBhc3N3b3JkEh4udXNlci52MS5VcGRhdGVQYXNzd29yZFJlcXVlc3QaHy51c2VyLnYxLlVwZGF0ZVBhc3N3b3JkUmVzcG9uc2UiABJECglHZXRBUElLZXkSGS51c2VyLnYxLkdldEFQSUtleVJlcXVlc3QaGi51c2VyLnYxLkdldEFQSUtleVJlc3BvbnNlIgASZQoUVXBkYXRlUHJvZmlsZVBpY3R1cmUSJC51c2VyLnYxLlVwZGF0ZVByb2ZpbGVQaWN0dXJlUmVxdWVzdBolLnVzZXIudjEuVXBkYXRlUHJvZmlsZVBpY3R1cmVSZXNwb25zZSIAQp0BCgtjb20udXNlci52MUIJVXNlclByb3RvUAFaRmdpdGh1Yi5jb20vc3BvdGRlbW80L3RyZXZzdGFjay9zZXJ2ZXIvaW50ZXJuYWwvc2VydmljZXMvdXNlci92MTt1c2VydjGiAgNVWFiqAgdVc2VyLlYxygIHVXNlclxWMeICE1VzZXJcVjFcR1BCTWV0YWRhdGHqAghVc2VyOjpWMWIGcHJvdG8z");
|
||||
fileDesc("ChJ1c2VyL3YxL3VzZXIucHJvdG8SB3VzZXIudjEiXAoEVXNlchIKCgJpZBgBIAEoAxIQCgh1c2VybmFtZRgCIAEoCRIfChJwcm9maWxlX3BpY3R1cmVfaWQYAyABKANIAIgBAUIVChNfcHJvZmlsZV9waWN0dXJlX2lkIhAKDkdldFVzZXJSZXF1ZXN0Ii4KD0dldFVzZXJSZXNwb25zZRIbCgR1c2VyGAEgASgLMg0udXNlci52MS5Vc2VyIl0KFVVwZGF0ZVBhc3N3b3JkUmVxdWVzdBIUCgxvbGRfcGFzc3dvcmQYASABKAkSFAoMbmV3X3Bhc3N3b3JkGAIgASgJEhgKEGNvbmZpcm1fcGFzc3dvcmQYAyABKAkiNQoWVXBkYXRlUGFzc3dvcmRSZXNwb25zZRIbCgR1c2VyGAEgASgLMg0udXNlci52MS5Vc2VyIj4KEEdldEFQSUtleVJlcXVlc3QSEAoIcGFzc3dvcmQYASABKAkSGAoQY29uZmlybV9wYXNzd29yZBgCIAEoCSIgChFHZXRBUElLZXlSZXNwb25zZRILCgNrZXkYASABKAkiPgobVXBkYXRlUHJvZmlsZVBpY3R1cmVSZXF1ZXN0EhEKCWZpbGVfbmFtZRgBIAEoCRIMCgRkYXRhGAIgASgMIjsKHFVwZGF0ZVByb2ZpbGVQaWN0dXJlUmVzcG9uc2USGwoEdXNlchgBIAEoCzINLnVzZXIudjEuVXNlcjLPAgoLVXNlclNlcnZpY2USPgoHR2V0VXNlchIXLnVzZXIudjEuR2V0VXNlclJlcXVlc3QaGC51c2VyLnYxLkdldFVzZXJSZXNwb25zZSIAElMKDlVwZGF0ZVBhc3N3b3JkEh4udXNlci52MS5VcGRhdGVQYXNzd29yZFJlcXVlc3QaHy51c2VyLnYxLlVwZGF0ZVBhc3N3b3JkUmVzcG9uc2UiABJECglHZXRBUElLZXkSGS51c2VyLnYxLkdldEFQSUtleVJlcXVlc3QaGi51c2VyLnYxLkdldEFQSUtleVJlc3BvbnNlIgASZQoUVXBkYXRlUHJvZmlsZVBpY3R1cmUSJC51c2VyLnYxLlVwZGF0ZVByb2ZpbGVQaWN0dXJlUmVxdWVzdBolLnVzZXIudjEuVXBkYXRlUHJvZmlsZVBpY3R1cmVSZXNwb25zZSIAQpwBCgtjb20udXNlci52MUIJVXNlclByb3RvUAFaRWdpdGh1Yi5jb20vc3BvdGRlbW80L3RyZXZzdGFjay9zZXJ2ZXIvaW50ZXJuYWwvY29ubmVjdC91c2VyL3YxO3VzZXJ2MaICA1VYWKoCB1VzZXIuVjHKAgdVc2VyXFYx4gITVXNlclxWMVxHUEJNZXRhZGF0YeoCCFVzZXI6OlYxYgZwcm90bzM");
|
||||
|
||||
/**
|
||||
* @generated from message user.v1.User
|
@ -1,4 +1,4 @@
|
||||
import type { User } from './services/user/v1/user_pb';
|
||||
import type { User } from './connect/user/v1/user_pb';
|
||||
|
||||
export const userState: { user: User | undefined } = $state({
|
||||
user: undefined
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { createConnectTransport } from '@connectrpc/connect-web';
|
||||
import { Code, ConnectError, createClient, type Interceptor } from '@connectrpc/connect';
|
||||
import { AuthService } from '$lib/services/user/v1/auth_pb';
|
||||
import { UserService } from '$lib/services/user/v1/user_pb';
|
||||
import { ItemService } from '$lib/services/item/v1/item_pb';
|
||||
import { AuthService } from '$lib/connect/user/v1/auth_pb';
|
||||
import { UserService } from '$lib/connect/user/v1/user_pb';
|
||||
import { ItemService } from '$lib/connect/item/v1/item_pb';
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
const redirector: Interceptor = (next) => async (req) => {
|
||||
|
@ -10,7 +10,7 @@
|
||||
import Input from '$lib/ui/Input.svelte';
|
||||
import Select from '$lib/ui/Select.svelte';
|
||||
import { SvelteMap } from 'svelte/reactivity';
|
||||
import type { Item } from '$lib/services/item/v1/item_pb';
|
||||
import type { Item } from '$lib/connect/item/v1/item_pb';
|
||||
import Pagination from '$lib/ui/Pagination.svelte';
|
||||
|
||||
// Config
|
||||
@ -113,21 +113,17 @@
|
||||
const quantity = formData.get('quantity')?.toString();
|
||||
|
||||
try {
|
||||
const response = await ItemClient.updateItem({
|
||||
item: {
|
||||
id: item.id,
|
||||
name: name,
|
||||
description: description,
|
||||
price: parseFloat(price ?? '0'),
|
||||
quantity: parseInt(quantity ?? '0')
|
||||
}
|
||||
await ItemClient.updateItem({
|
||||
id: item.id,
|
||||
name: name,
|
||||
description: description,
|
||||
price: price ? parseFloat(price) : undefined,
|
||||
quantity: quantity ? parseInt(quantity) : undefined
|
||||
});
|
||||
|
||||
if (response.item && item.id) {
|
||||
toast.success(`item "${name}" saved`);
|
||||
editsOpen.set(item.id, false);
|
||||
await updateItems();
|
||||
}
|
||||
toast.success(`item "${name}" saved`);
|
||||
editsOpen.set(item.id, false);
|
||||
await updateItems();
|
||||
} catch (err) {
|
||||
const error = ConnectError.from(err);
|
||||
toast.error(error.rawMessage);
|
||||
@ -341,21 +337,17 @@
|
||||
const quantity = formData.get('quantity')?.toString();
|
||||
|
||||
try {
|
||||
const response = await ItemClient.createItem({
|
||||
item: {
|
||||
name: name,
|
||||
description: description,
|
||||
price: parseFloat(price ?? '0'),
|
||||
quantity: parseInt(quantity ?? '0')
|
||||
}
|
||||
await ItemClient.createItem({
|
||||
name: name,
|
||||
description: description,
|
||||
price: parseFloat(price ?? '0'),
|
||||
quantity: parseInt(quantity ?? '0')
|
||||
});
|
||||
|
||||
if (response.item) {
|
||||
form.reset();
|
||||
toast.success(`item "${name}" added`);
|
||||
addedOpen = false;
|
||||
await updateItems();
|
||||
}
|
||||
form.reset();
|
||||
toast.success(`item "${name}" added`);
|
||||
addedOpen = false;
|
||||
await updateItems();
|
||||
} catch (err) {
|
||||
const error = ConnectError.from(err);
|
||||
toast.error(error.rawMessage);
|
||||
|
@ -105,11 +105,11 @@
|
||||
</div>
|
||||
<div class="flex flex-col gap-1">
|
||||
<label for="signup-password" class="text-sm">Password</label>
|
||||
<Input name="signup-password" />
|
||||
<Input name="signup-password" type="password" />
|
||||
</div>
|
||||
<div class="flex flex-col gap-1">
|
||||
<label for="signup-confirm-password" class="text-sm">Confirm Password</label>
|
||||
<Input name="signup-confirm-password" />
|
||||
<Input name="signup-confirm-password" type="password" />
|
||||
</div>
|
||||
<Button type="submit">Submit</Button>
|
||||
</div>
|
||||
|
@ -111,17 +111,34 @@ components:
|
||||
item.v1.CreateItemRequest:
|
||||
type: object
|
||||
properties:
|
||||
item:
|
||||
title: item
|
||||
$ref: '#/components/schemas/item.v1.Item'
|
||||
name:
|
||||
type: string
|
||||
title: name
|
||||
description:
|
||||
type: string
|
||||
title: description
|
||||
price:
|
||||
type: number
|
||||
title: price
|
||||
format: float
|
||||
quantity:
|
||||
type: integer
|
||||
title: quantity
|
||||
format: int32
|
||||
title: CreateItemRequest
|
||||
additionalProperties: false
|
||||
item.v1.CreateItemResponse:
|
||||
type: object
|
||||
properties:
|
||||
item:
|
||||
title: item
|
||||
$ref: '#/components/schemas/item.v1.Item'
|
||||
id:
|
||||
type:
|
||||
- integer
|
||||
- string
|
||||
title: id
|
||||
format: int64
|
||||
added:
|
||||
title: added
|
||||
$ref: '#/components/schemas/google.protobuf.Timestamp'
|
||||
title: CreateItemResponse
|
||||
additionalProperties: false
|
||||
item.v1.DeleteItemRequest:
|
||||
@ -210,10 +227,12 @@ components:
|
||||
- string
|
||||
title: id
|
||||
format: int64
|
||||
nullable: true
|
||||
name:
|
||||
type: string
|
||||
title: name
|
||||
added:
|
||||
title: added
|
||||
$ref: '#/components/schemas/google.protobuf.Timestamp'
|
||||
description:
|
||||
type: string
|
||||
title: description
|
||||
@ -225,26 +244,39 @@ components:
|
||||
type: integer
|
||||
title: quantity
|
||||
format: int32
|
||||
added:
|
||||
title: added
|
||||
nullable: true
|
||||
$ref: '#/components/schemas/google.protobuf.Timestamp'
|
||||
title: Item
|
||||
additionalProperties: false
|
||||
item.v1.UpdateItemRequest:
|
||||
type: object
|
||||
properties:
|
||||
item:
|
||||
title: item
|
||||
$ref: '#/components/schemas/item.v1.Item'
|
||||
id:
|
||||
type:
|
||||
- integer
|
||||
- string
|
||||
title: id
|
||||
format: int64
|
||||
name:
|
||||
type: string
|
||||
title: name
|
||||
nullable: true
|
||||
description:
|
||||
type: string
|
||||
title: description
|
||||
nullable: true
|
||||
price:
|
||||
type: number
|
||||
title: price
|
||||
format: float
|
||||
nullable: true
|
||||
quantity:
|
||||
type: integer
|
||||
title: quantity
|
||||
format: int32
|
||||
nullable: true
|
||||
title: UpdateItemRequest
|
||||
additionalProperties: false
|
||||
item.v1.UpdateItemResponse:
|
||||
type: object
|
||||
properties:
|
||||
item:
|
||||
title: item
|
||||
$ref: '#/components/schemas/item.v1.Item'
|
||||
title: UpdateItemResponse
|
||||
additionalProperties: false
|
||||
connect-protocol-version:
|
||||
|
@ -1,43 +0,0 @@
|
||||
services:
|
||||
trevstack:
|
||||
container_name: trevstack
|
||||
build:
|
||||
context: .
|
||||
ports:
|
||||
- "${PORT}:${PORT}"
|
||||
environment:
|
||||
- DB_TYPE=postgres
|
||||
- DB_USER=${DB_USER}
|
||||
- DB_PASS=${DB_PASS}
|
||||
- DB_HOST=trevstack-db
|
||||
- DB_PORT=5432
|
||||
- DB_NAME=${DB_NAME}
|
||||
- PORT=${PORT}
|
||||
- KEY=${KEY}
|
||||
depends_on:
|
||||
trevstack-db:
|
||||
condition: service_healthy
|
||||
links:
|
||||
- trevstack-db
|
||||
restart: unless-stopped
|
||||
|
||||
trevstack-db:
|
||||
container_name: trevstack-db
|
||||
image: postgres
|
||||
environment:
|
||||
- POSTGRES_USER=${DB_USER}
|
||||
- POSTGRES_PASSWORD=${DB_PASS}
|
||||
- POSTGRES_DB=${DB_NAME}
|
||||
volumes:
|
||||
- trevstackdata:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: "pg_isready -U postgres"
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
trevstackdata:
|
||||
name: trevstackdata
|
||||
external: true
|
123
flake.lock
generated
123
flake.lock
generated
@ -1,89 +1,12 @@
|
||||
{
|
||||
"nodes": {
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1731533236,
|
||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils_2": {
|
||||
"inputs": {
|
||||
"systems": "systems_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1731533236,
|
||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"gitignore": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1709087332,
|
||||
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"gitignore_2": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"treli",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1709087332,
|
||||
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1744098102,
|
||||
"narHash": "sha256-tzCdyIJj9AjysC3OuKA+tMD/kDEDAF9mICPDU7ix0JA=",
|
||||
"lastModified": 1744463964,
|
||||
"narHash": "sha256-LWqduOgLHCFxiTNYi3Uj5Lgz0SR+Xhw3kr/3Xd0GPTM=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "c8cd81426f45942bb2906d5ed2fe21d2f19d95b7",
|
||||
"rev": "2631b0b7abcea6e640ce31cd78ea58910d31e650",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@ -111,54 +34,20 @@
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"gitignore": "gitignore",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"treli": "treli"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems_2": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"treli": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils_2",
|
||||
"gitignore": "gitignore_2",
|
||||
"nixpkgs": "nixpkgs_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1744262571,
|
||||
"narHash": "sha256-zYYx5DCQuyGsEKGStakQW1eSXPofRA3LeufIEVhE/4Q=",
|
||||
"lastModified": 1744776944,
|
||||
"narHash": "sha256-wdmVDDyz6aZpFai2P0PBb2sMRBTgnaURylJw8wis6ks=",
|
||||
"owner": "spotdemo4",
|
||||
"repo": "treli",
|
||||
"rev": "00b55f3cdc82e61a6c4f46c6cb745c71203ccde3",
|
||||
"rev": "eefe10c1ba62a577592ff25e6e5b274215c1d8db",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
280
flake.nix
280
flake.nix
@ -3,224 +3,114 @@
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
treli.url = "github:spotdemo4/treli";
|
||||
gitignore = {
|
||||
url = "github:hercules-ci/gitignore.nix";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, flake-utils, gitignore, treli }:
|
||||
flake-utils.lib.eachDefaultSystem (system:
|
||||
outputs = {
|
||||
nixpkgs,
|
||||
treli,
|
||||
...
|
||||
}: let
|
||||
pname = "trevstack";
|
||||
version = "0.0.11";
|
||||
|
||||
let
|
||||
pname = "trevstack";
|
||||
version = "0.0.11";
|
||||
|
||||
pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
config.allowUnfree = true;
|
||||
};
|
||||
|
||||
protoc-gen-connect-openapi = pkgs.buildGoModule {
|
||||
name = "protoc-gen-connect-openapi";
|
||||
src = pkgs.fetchFromGitHub {
|
||||
owner = "sudorandom";
|
||||
repo = "protoc-gen-connect-openapi";
|
||||
rev = "v0.16.1";
|
||||
sha256 = "sha256-3XBQCc9H9N/AZm/8J5bJRgBhVtoZKFvbdTB+glHxYdA=";
|
||||
};
|
||||
vendorHash = "sha256-CIiG/XhV8xxjYY0sZcSvIFcJ1Wh8LyDDwqem2cSSwBA=";
|
||||
nativeCheckInputs = with pkgs; [ less ];
|
||||
};
|
||||
|
||||
bobgen = pkgs.buildGoModule {
|
||||
name = "bobgen";
|
||||
src = pkgs.fetchFromGitHub {
|
||||
owner = "stephenafamo";
|
||||
repo = "bob";
|
||||
rev = "v0.31.0";
|
||||
sha256 = "sha256-APAckQ+EDAu459NTPXUISLIrcAcX3aQ5B/jrMUEW0EY=";
|
||||
};
|
||||
vendorHash = "sha256-3blGiSxlKpWH8k0acAXXks8nCdnoWmXLmzPStJmmGcM=";
|
||||
subPackages = [
|
||||
"gen/bobgen-sql"
|
||||
];
|
||||
};
|
||||
|
||||
client = pkgs.buildNpmPackage {
|
||||
pname = "${pname}-client";
|
||||
inherit version;
|
||||
src = gitignore.lib.gitignoreSource ./client;
|
||||
npmDepsHash = "sha256-Mu04whysDA1U5wvECJJ+KopGfSzTPR/OhWz9cjTRIfU=";
|
||||
nodejs = pkgs.nodejs_22;
|
||||
npmFlags = [ "--legacy-peer-deps" ];
|
||||
|
||||
installPhase = ''
|
||||
cp -r build "$out"
|
||||
chmod -R u+w "$out"
|
||||
'';
|
||||
};
|
||||
|
||||
server = pkgs.buildGoModule {
|
||||
inherit client pname version;
|
||||
src = gitignore.lib.gitignoreSource ./server;
|
||||
vendorHash = "sha256-YmMKl9X1kVz6dk/JOSi2jghCUKObUKdm2O+JpO9PDCA=";
|
||||
env.CGO_ENABLED = 0;
|
||||
|
||||
preBuild = ''
|
||||
cp -r ${client} client
|
||||
'';
|
||||
};
|
||||
|
||||
in
|
||||
{
|
||||
devShells.default = pkgs.mkShell {
|
||||
packages = with pkgs; [
|
||||
supportedSystems = [
|
||||
"x86_64-linux"
|
||||
"aarch64-linux"
|
||||
"x86_64-darwin"
|
||||
"aarch64-darwin"
|
||||
];
|
||||
forSystem = f:
|
||||
nixpkgs.lib.genAttrs supportedSystems (
|
||||
system:
|
||||
f {
|
||||
inherit system;
|
||||
pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
};
|
||||
}
|
||||
);
|
||||
in {
|
||||
devShells = forSystem ({pkgs, ...}: {
|
||||
default = pkgs.mkShell {
|
||||
packages = with pkgs;
|
||||
[
|
||||
git
|
||||
nix-update
|
||||
treli.packages."${system}".default
|
||||
sqlite
|
||||
|
||||
# Go backend
|
||||
# Server
|
||||
go
|
||||
gotools
|
||||
gopls
|
||||
revive
|
||||
bobgen
|
||||
sqlc
|
||||
|
||||
# database
|
||||
sqlite
|
||||
dbmate
|
||||
|
||||
# Protobuf middleware
|
||||
sqlfluff
|
||||
|
||||
# Protobuf
|
||||
buf
|
||||
protoc-gen-go
|
||||
protoc-gen-connect-go
|
||||
protoc-gen-es
|
||||
protoc-gen-connect-openapi
|
||||
(buildGoModule {
|
||||
name = "protoc-gen-connect-openapi";
|
||||
src = pkgs.fetchFromGitHub {
|
||||
owner = "sudorandom";
|
||||
repo = "protoc-gen-connect-openapi";
|
||||
rev = "v0.16.1";
|
||||
sha256 = "sha256-3XBQCc9H9N/AZm/8J5bJRgBhVtoZKFvbdTB+glHxYdA=";
|
||||
};
|
||||
vendorHash = "sha256-CIiG/XhV8xxjYY0sZcSvIFcJ1Wh8LyDDwqem2cSSwBA=";
|
||||
nativeCheckInputs = with pkgs; [less];
|
||||
})
|
||||
|
||||
# Svelte frontend
|
||||
# Client
|
||||
nodejs_22
|
||||
]
|
||||
# Use .scripts
|
||||
++ map (
|
||||
x: (
|
||||
pkgs.writeShellApplication {
|
||||
name = "${pname}-${(lib.nameFromURL (baseNameOf x) ".")}";
|
||||
text = builtins.readFile x;
|
||||
}
|
||||
)
|
||||
) (pkgs.lib.filesystem.listFilesRecursive ./.scripts);
|
||||
};
|
||||
});
|
||||
|
||||
# Update
|
||||
(writeShellApplication {
|
||||
name = "ts-update";
|
||||
formatter = forSystem ({pkgs, ...}: pkgs.alejandra);
|
||||
|
||||
text = ''
|
||||
git_root=$(git rev-parse --show-toplevel)
|
||||
packages = forSystem ({pkgs, ...}: rec {
|
||||
default = trevstack;
|
||||
|
||||
cd "''${git_root}/client"
|
||||
npm update --save
|
||||
if ! git diff --exit-code package.json package-lock.json; then
|
||||
git add package-lock.json
|
||||
git add package.json
|
||||
git commit -m "build(client): updated npm dependencies"
|
||||
fi
|
||||
trevstack-client = pkgs.buildNpmPackage {
|
||||
pname = "${pname}-client";
|
||||
inherit version;
|
||||
src = ./client;
|
||||
npmDepsHash = "sha256-Mu04whysDA1U5wvECJJ+KopGfSzTPR/OhWz9cjTRIfU=";
|
||||
nodejs = pkgs.nodejs_22;
|
||||
npmFlags = ["--legacy-peer-deps"];
|
||||
|
||||
cd "''${git_root}/server"
|
||||
go get -u
|
||||
go mod tidy
|
||||
if ! git diff --exit-code go.mod go.sum; then
|
||||
git add go.mod
|
||||
git add go.sum
|
||||
git commit -m "build(server): updated go dependencies"
|
||||
fi
|
||||
installPhase = ''
|
||||
cp -r build "$out"
|
||||
chmod -R u+w "$out"
|
||||
'';
|
||||
};
|
||||
|
||||
cd "''${git_root}"
|
||||
nix-update --flake --version=skip --subpackage client default
|
||||
if ! git diff --exit-code flake.nix; then
|
||||
git add flake.nix
|
||||
git commit -m "build(nix): updated nix hashes"
|
||||
fi
|
||||
'';
|
||||
})
|
||||
trevstack = pkgs.buildGoModule {
|
||||
inherit trevstack-client pname version;
|
||||
src = ./server;
|
||||
vendorHash = "sha256-YmMKl9X1kVz6dk/JOSi2jghCUKObUKdm2O+JpO9PDCA=";
|
||||
|
||||
# Bump version
|
||||
(writeShellApplication {
|
||||
name = "ts-bump";
|
||||
|
||||
text = ''
|
||||
git_root=$(git rev-parse --show-toplevel)
|
||||
next_version=$(echo "${version}" | awk -F. -v OFS=. '{$NF += 1 ; print}')
|
||||
|
||||
cd "''${git_root}/client"
|
||||
npm version "''${next_version}"
|
||||
git add package-lock.json
|
||||
git add package.json
|
||||
|
||||
cd "''${git_root}"
|
||||
nix-update --flake --version "''${next_version}" --subpackage client default
|
||||
git add flake.nix
|
||||
git commit -m "bump: v${version} -> v''${next_version}"
|
||||
git push origin main
|
||||
|
||||
git tag -a "v''${next_version}" -m "bump: v${version} -> v''${next_version}"
|
||||
git push origin "v''${next_version}"
|
||||
'';
|
||||
})
|
||||
|
||||
# Lint
|
||||
(writeShellApplication {
|
||||
name = "ts-lint";
|
||||
|
||||
text = ''
|
||||
git_root=$(git rev-parse --show-toplevel)
|
||||
|
||||
if [ -n "''${1:-}" ]; then
|
||||
cd "''${git_root}/client"
|
||||
npm run format
|
||||
fi
|
||||
|
||||
cd "''${git_root}"
|
||||
echo "Linting protobuf"
|
||||
buf lint
|
||||
|
||||
cd "''${git_root}/client"
|
||||
echo "Linting client"
|
||||
npm run check
|
||||
npm run lint
|
||||
|
||||
cd "''${git_root}/server"
|
||||
echo "Linting server"
|
||||
revive -config revive.toml -set_exit_status ./...
|
||||
'';
|
||||
})
|
||||
|
||||
# Build
|
||||
(writeShellApplication {
|
||||
name = "ts-build";
|
||||
|
||||
text = ''
|
||||
git_root=$(git rev-parse --show-toplevel)
|
||||
|
||||
cd "''${git_root}"
|
||||
echo "Building client"
|
||||
nix build .#trevstack-client
|
||||
cp -a result/. server/client
|
||||
chmod -R u+w server/client
|
||||
|
||||
cd "''${git_root}/server"
|
||||
echo "Building ${pname}-windows-amd64-${version}.exe"
|
||||
GOOS=windows GOARCH=amd64 go build -o "../build/${pname}-windows-amd64-${version}.exe" .
|
||||
|
||||
echo "Building ${pname}-linux-amd64-${version}"
|
||||
GOOS=linux GOARCH=amd64 go build -o "../build/${pname}-linux-amd64-${version}" .
|
||||
|
||||
echo "Building ${pname}-linux-amd64-${version}"
|
||||
GOOS=linux GOARCH=arm64 go build -o "../build/${pname}-linux-arm64-${version}" .
|
||||
|
||||
echo "Building ${pname}-linux-arm-${version}"
|
||||
GOOS=linux GOARCH=arm go build -o "../build/${pname}-linux-arm-${version}" .
|
||||
'';
|
||||
})
|
||||
];
|
||||
};
|
||||
|
||||
packages = rec {
|
||||
default = trevstack;
|
||||
|
||||
trevstack = server;
|
||||
trevstack-client = client;
|
||||
};
|
||||
}
|
||||
);
|
||||
preBuild = ''
|
||||
cp -r ${trevstack-client} client
|
||||
'';
|
||||
};
|
||||
});
|
||||
};
|
||||
}
|
||||
|
@ -5,12 +5,12 @@ package item.v1;
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
message Item {
|
||||
optional int64 id = 1;
|
||||
int64 id = 1;
|
||||
string name = 2;
|
||||
string description = 3;
|
||||
float price = 4;
|
||||
int32 quantity = 5;
|
||||
optional google.protobuf.Timestamp added = 6;
|
||||
google.protobuf.Timestamp added = 3;
|
||||
string description = 4;
|
||||
float price = 5;
|
||||
int32 quantity = 6;
|
||||
}
|
||||
|
||||
service ItemService {
|
||||
@ -40,19 +40,25 @@ message GetItemsResponse {
|
||||
int64 count = 2;
|
||||
}
|
||||
|
||||
message CreateItemRequest {
|
||||
Item item = 1;
|
||||
message CreateItemRequest {
|
||||
string name = 1;
|
||||
string description = 2;
|
||||
float price = 3;
|
||||
int32 quantity = 4;
|
||||
}
|
||||
message CreateItemResponse {
|
||||
Item item = 1;
|
||||
int64 id = 1;
|
||||
google.protobuf.Timestamp added = 2;
|
||||
}
|
||||
|
||||
message UpdateItemRequest {
|
||||
Item item = 1;
|
||||
}
|
||||
message UpdateItemResponse {
|
||||
Item item = 1;
|
||||
int64 id = 1;
|
||||
optional string name = 2;
|
||||
optional string description = 3;
|
||||
optional float price = 4;
|
||||
optional int32 quantity = 5;
|
||||
}
|
||||
message UpdateItemResponse {}
|
||||
|
||||
message DeleteItemRequest {
|
||||
int64 id = 1;
|
||||
|
3
server/.gitignore
vendored
3
server/.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
/client/
|
||||
/tmp/
|
||||
/tmp/
|
||||
/build/
|
2
server/db/.sqlfluff
Normal file
2
server/db/.sqlfluff
Normal file
@ -0,0 +1,2 @@
|
||||
[sqlfluff]
|
||||
dialect = sqlite
|
1
server/db/.sqlfluffignore
Normal file
1
server/db/.sqlfluffignore
Normal file
@ -0,0 +1 @@
|
||||
/schema.sql
|
@ -1,23 +1,23 @@
|
||||
-- migrate:up
|
||||
CREATE TABLE user(
|
||||
CREATE TABLE user (
|
||||
id INTEGER PRIMARY KEY NOT NULL,
|
||||
username TEXT NOT NULL,
|
||||
password TEXT NOT NULL,
|
||||
profile_picture_id INTEGER,
|
||||
|
||||
FOREIGN KEY(profile_picture_id) REFERENCES file(id)
|
||||
FOREIGN KEY (profile_picture_id) REFERENCES file (id)
|
||||
);
|
||||
|
||||
CREATE TABLE file(
|
||||
CREATE TABLE file (
|
||||
id INTEGER PRIMARY KEY NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
data BLOB NOT NULL,
|
||||
user_id INTEGER NOT NULL,
|
||||
|
||||
FOREIGN KEY(user_id) REFERENCES user(id)
|
||||
FOREIGN KEY (user_id) REFERENCES user (id)
|
||||
);
|
||||
|
||||
CREATE TABLE item(
|
||||
CREATE TABLE item (
|
||||
id INTEGER PRIMARY KEY NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
added DATETIME NOT NULL,
|
||||
@ -26,10 +26,10 @@ CREATE TABLE item(
|
||||
quantity INTEGER NOT NULL,
|
||||
user_id INTEGER NOT NULL,
|
||||
|
||||
FOREIGN KEY(user_id) REFERENCES user(id)
|
||||
FOREIGN KEY (user_id) REFERENCES user (id)
|
||||
);
|
||||
|
||||
-- migrate:down
|
||||
drop table user;
|
||||
drop table file;
|
||||
drop table item;
|
||||
DROP TABLE user;
|
||||
DROP TABLE file;
|
||||
DROP TABLE item;
|
||||
|
41
server/db/queries/file.sql
Normal file
41
server/db/queries/file.sql
Normal file
@ -0,0 +1,41 @@
|
||||
-- name: GetFile :one
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
data,
|
||||
user_id
|
||||
FROM file
|
||||
WHERE
|
||||
id = @id
|
||||
AND
|
||||
user_id = @user_id
|
||||
LIMIT 1;
|
||||
|
||||
-- name: InsertFile :one
|
||||
INSERT INTO file (
|
||||
name,
|
||||
data,
|
||||
user_id
|
||||
) VALUES (
|
||||
@name,
|
||||
@data,
|
||||
@user_id
|
||||
)
|
||||
RETURNING id;
|
||||
|
||||
-- name: UpdateFile :exec
|
||||
UPDATE file
|
||||
SET
|
||||
name = COALESCE(sqlc.narg('name'), name),
|
||||
data = COALESCE(sqlc.narg('data'), data)
|
||||
WHERE
|
||||
id = @id
|
||||
AND
|
||||
user_id = @user_id;
|
||||
|
||||
-- name: DeleteFile :exec
|
||||
DELETE FROM file
|
||||
WHERE
|
||||
id = @id
|
||||
AND
|
||||
user_id = @user_id;
|
92
server/db/queries/item.sql
Normal file
92
server/db/queries/item.sql
Normal file
@ -0,0 +1,92 @@
|
||||
-- name: GetItem :one
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
added,
|
||||
description,
|
||||
price,
|
||||
quantity,
|
||||
user_id
|
||||
FROM item
|
||||
WHERE
|
||||
id = @id
|
||||
AND
|
||||
user_id = @user_id
|
||||
LIMIT 1;
|
||||
|
||||
-- name: GetItems :many
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
added,
|
||||
description,
|
||||
price,
|
||||
quantity,
|
||||
user_id
|
||||
FROM item
|
||||
WHERE
|
||||
user_id = @user_id
|
||||
AND
|
||||
(
|
||||
(name LIKE sqlc.narg('name') OR sqlc.narg('name') IS NULL)
|
||||
AND
|
||||
(added >= sqlc.narg('start') OR sqlc.narg('start') IS NULL)
|
||||
AND
|
||||
(added <= sqlc.narg('end') OR sqlc.narg('end') IS NULL)
|
||||
)
|
||||
LIMIT
|
||||
@limit
|
||||
OFFSET
|
||||
@offset;
|
||||
|
||||
-- name: GetItemsCount :one
|
||||
SELECT COUNT(id)
|
||||
FROM item
|
||||
WHERE
|
||||
user_id = @user_id
|
||||
AND
|
||||
(
|
||||
(name LIKE sqlc.narg('name') OR sqlc.narg('name') IS NULL)
|
||||
AND
|
||||
(added >= sqlc.narg('start') OR sqlc.narg('start') IS NULL)
|
||||
AND
|
||||
(added <= sqlc.narg('end') OR sqlc.narg('end') IS NULL)
|
||||
)
|
||||
LIMIT 1;
|
||||
|
||||
-- name: InsertItem :one
|
||||
INSERT INTO item (
|
||||
name,
|
||||
added,
|
||||
description,
|
||||
price,
|
||||
quantity,
|
||||
user_id
|
||||
) VALUES (
|
||||
@name,
|
||||
@added,
|
||||
@description,
|
||||
@price,
|
||||
@quantity,
|
||||
@user_id
|
||||
)
|
||||
RETURNING id;
|
||||
|
||||
-- name: UpdateItem :exec
|
||||
UPDATE item
|
||||
SET
|
||||
name = COALESCE(sqlc.narg('name'), name),
|
||||
description = COALESCE(sqlc.narg('description'), description),
|
||||
price = COALESCE(sqlc.narg('price'), price),
|
||||
quantity = COALESCE(sqlc.narg('quantity'), quantity)
|
||||
WHERE
|
||||
id = @id
|
||||
AND
|
||||
user_id = @user_id;
|
||||
|
||||
-- name: DeleteItem :exec
|
||||
DELETE FROM item
|
||||
WHERE
|
||||
id = @id
|
||||
AND
|
||||
user_id = @user_id;
|
46
server/db/queries/user.sql
Normal file
46
server/db/queries/user.sql
Normal file
@ -0,0 +1,46 @@
|
||||
-- name: GetUser :one
|
||||
SELECT
|
||||
id,
|
||||
username,
|
||||
password,
|
||||
profile_picture_id
|
||||
FROM user
|
||||
WHERE
|
||||
id = @id
|
||||
LIMIT 1;
|
||||
|
||||
-- name: GetUserbyUsername :one
|
||||
SELECT
|
||||
id,
|
||||
username,
|
||||
password,
|
||||
profile_picture_id
|
||||
FROM user
|
||||
WHERE
|
||||
username = @username
|
||||
LIMIT 1;
|
||||
|
||||
-- name: InsertUser :one
|
||||
INSERT INTO user (
|
||||
username,
|
||||
password
|
||||
) VALUES (
|
||||
@username,
|
||||
@password
|
||||
)
|
||||
RETURNING id;
|
||||
|
||||
-- name: UpdateUser :exec
|
||||
UPDATE user
|
||||
SET
|
||||
username = COALESCE(sqlc.narg('username'), username),
|
||||
password = COALESCE(sqlc.narg('password'), password),
|
||||
profile_picture_id = COALESCE(
|
||||
sqlc.narg('profile_picture_id'),
|
||||
profile_picture_id
|
||||
)
|
||||
WHERE id = @id;
|
||||
|
||||
-- name: DeleteUser :exec
|
||||
DELETE FROM user
|
||||
WHERE id = @id;
|
@ -1,21 +1,21 @@
|
||||
CREATE TABLE IF NOT EXISTS "schema_migrations" (version varchar(128) primary key);
|
||||
CREATE TABLE user(
|
||||
CREATE TABLE user (
|
||||
id INTEGER PRIMARY KEY NOT NULL,
|
||||
username TEXT NOT NULL,
|
||||
password TEXT NOT NULL,
|
||||
profile_picture_id INTEGER,
|
||||
|
||||
FOREIGN KEY(profile_picture_id) REFERENCES file(id)
|
||||
FOREIGN KEY (profile_picture_id) REFERENCES file (id)
|
||||
);
|
||||
CREATE TABLE file(
|
||||
CREATE TABLE file (
|
||||
id INTEGER PRIMARY KEY NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
data BLOB NOT NULL,
|
||||
user_id INTEGER NOT NULL,
|
||||
|
||||
FOREIGN KEY(user_id) REFERENCES user(id)
|
||||
FOREIGN KEY (user_id) REFERENCES user (id)
|
||||
);
|
||||
CREATE TABLE item(
|
||||
CREATE TABLE item (
|
||||
id INTEGER PRIMARY KEY NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
added DATETIME NOT NULL,
|
||||
@ -24,7 +24,7 @@ CREATE TABLE item(
|
||||
quantity INTEGER NOT NULL,
|
||||
user_id INTEGER NOT NULL,
|
||||
|
||||
FOREIGN KEY(user_id) REFERENCES user(id)
|
||||
FOREIGN KEY (user_id) REFERENCES user (id)
|
||||
);
|
||||
-- Dbmate schema migrations
|
||||
INSERT INTO "schema_migrations" (version) VALUES
|
||||
|
@ -5,15 +5,11 @@ go 1.24.1
|
||||
require (
|
||||
connectrpc.com/connect v1.18.1
|
||||
connectrpc.com/cors v0.1.0
|
||||
github.com/aarondl/opt v0.0.0-20240623220848-083f18ab9536
|
||||
github.com/amacneil/dbmate/v2 v2.26.0
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2
|
||||
github.com/jaswdr/faker/v2 v2.3.3
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/lib/pq v1.10.9
|
||||
github.com/rs/cors v1.11.1
|
||||
github.com/spotdemo4/dbmate-sqlite-modernc v0.0.2
|
||||
github.com/stephenafamo/bob v0.31.0
|
||||
golang.org/x/crypto v0.37.0
|
||||
golang.org/x/net v0.39.0
|
||||
golang.org/x/time v0.11.0
|
||||
@ -22,14 +18,12 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/aarondl/json v0.0.0-20221020222930-8b0db17ef1bf // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/lib/pq v1.10.9 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||
github.com/qdm12/reprint v0.0.0-20200326205758-722754a53494 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/stephenafamo/scan v0.6.2 // indirect
|
||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect
|
||||
golang.org/x/sys v0.32.0 // indirect
|
||||
golang.org/x/text v0.24.0 // indirect
|
||||
|
@ -4,15 +4,8 @@ connectrpc.com/cors v0.1.0 h1:f3gTXJyDZPrDIZCQ567jxfD9PAIpopHiRDnJRt3QuOQ=
|
||||
connectrpc.com/cors v0.1.0/go.mod h1:v8SJZCPfHtGH1zsm+Ttajpozd4cYIUryl4dFB6QEpfg=
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
github.com/aarondl/json v0.0.0-20221020222930-8b0db17ef1bf h1:+edM69bH/X6JpYPmJYBRLanAMe1V5yRXYU3hHUovGcE=
|
||||
github.com/aarondl/json v0.0.0-20221020222930-8b0db17ef1bf/go.mod h1:FZqLhJSj2tg0ZN48GB1zvj00+ZYcHPqgsC7yzcgCq6k=
|
||||
github.com/aarondl/opt v0.0.0-20240623220848-083f18ab9536 h1:vhpjulzH5Tr4S3uJ3Y/9pNL481kPq5ERj13ceAW0/uE=
|
||||
github.com/aarondl/opt v0.0.0-20240623220848-083f18ab9536/go.mod h1:l4/5NZtYd/SIohsFhaJQQe+sPOTG22furpZ5FvcYOzk=
|
||||
github.com/amacneil/dbmate/v2 v2.26.0 h1:74ykEWh0V41BU3wesgmTowMn/2x9rUfIxIG+Q+vuUm0=
|
||||
github.com/amacneil/dbmate/v2 v2.26.0/go.mod h1:cnjZKm5x/gKMLPfExXbEDUUQi1Sv5UqY3AIgbnxql84=
|
||||
github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ=
|
||||
github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
@ -27,8 +20,6 @@ github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17k
|
||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/jaswdr/faker/v2 v2.3.3 h1:0mA+B5YGjqgpOPdDY/72d6pDv7Z/5t6F1XzIfkUfgC4=
|
||||
github.com/jaswdr/faker/v2 v2.3.3/go.mod h1:ROK8xwQV0hYOLDUtxCQgHGcl10jbVzIvqHxcIDdwY2Q=
|
||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
@ -41,24 +32,12 @@ github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdh
|
||||
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/qdm12/reprint v0.0.0-20200326205758-722754a53494 h1:wSmWgpuccqS2IOfmYrbRiUgv+g37W5suLLLxwwniTSc=
|
||||
github.com/qdm12/reprint v0.0.0-20200326205758-722754a53494/go.mod h1:yipyliwI08eQ6XwDm1fEwKPdF/xdbkiHtrU+1Hg+vc4=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA=
|
||||
github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
|
||||
github.com/spotdemo4/dbmate-sqlite-modernc v0.0.2 h1:537TA0HvjoWJxPzAhP+t2Gt82NpxGhCdmDsJpta7sdc=
|
||||
github.com/spotdemo4/dbmate-sqlite-modernc v0.0.2/go.mod h1:JwuvDDgb1VLGyHgSsQN3I+dx6QkEGk86o6Yc8vxzG/4=
|
||||
github.com/stephenafamo/bob v0.31.0 h1:Nx80wK0N+gTZEdRCkmAzoYTJ3L3DPIF7Zt+Br3wwRJA=
|
||||
github.com/stephenafamo/bob v0.31.0/go.mod h1:CU2OifyJmHdGvNPEGhZE2p92KirNfFiQm9g2hr9f/cY=
|
||||
github.com/stephenafamo/fakedb v0.0.0-20221230081958-0b86f816ed97 h1:XItoZNmhOih06TC02jK7l3wlpZ0XT/sPQYutDcGOQjg=
|
||||
github.com/stephenafamo/fakedb v0.0.0-20221230081958-0b86f816ed97/go.mod h1:bM3Vmw1IakoaXocHmMIGgJFYob0vuK+CFWiJHQvz0jQ=
|
||||
github.com/stephenafamo/scan v0.6.2 h1:mEjx1P1MuimqALCXfZEV8+KAiVcByrgngqKatgHag9I=
|
||||
github.com/stephenafamo/scan v0.6.2/go.mod h1:FhIUJ8pLNyex36xGFiazDJJ5Xry0UkAi+RkWRrEcRMg=
|
||||
github.com/stephenafamo/sqlparser v0.0.0-20241111104950-b04fa8a26c9c h1:JFga++XBnZG2xlnvQyHJkeBWZ9G9mGdtgvLeSRbp/BA=
|
||||
github.com/stephenafamo/sqlparser v0.0.0-20241111104950-b04fa8a26c9c/go.mod h1:4iveRk8mkzQZxDuK/W0MGLrGmu/igyDYWNDD4a6v0r0=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/zenizh/go-capturer v0.0.0-20211219060012-52ea6c8fed04 h1:qXafrlZL1WsJW5OokjraLLRURHiw0OzKHD/RNdspp4w=
|
||||
@ -84,8 +63,6 @@ golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU=
|
||||
golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s=
|
||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
modernc.org/cc/v4 v4.25.2 h1:T2oH7sZdGvTaie0BRNFbIYsabzCxUQg8nLqCdQ2i0ic=
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.36.5
|
||||
// protoc-gen-go v1.36.6
|
||||
// protoc (unknown)
|
||||
// source: item/v1/item.proto
|
||||
|
||||
@ -24,12 +24,12 @@ const (
|
||||
|
||||
type Item struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Id *int64 `protobuf:"varint,1,opt,name=id,proto3,oneof" json:"id,omitempty"`
|
||||
Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"`
|
||||
Price float32 `protobuf:"fixed32,4,opt,name=price,proto3" json:"price,omitempty"`
|
||||
Quantity int32 `protobuf:"varint,5,opt,name=quantity,proto3" json:"quantity,omitempty"`
|
||||
Added *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=added,proto3,oneof" json:"added,omitempty"`
|
||||
Added *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=added,proto3" json:"added,omitempty"`
|
||||
Description string `protobuf:"bytes,4,opt,name=description,proto3" json:"description,omitempty"`
|
||||
Price float32 `protobuf:"fixed32,5,opt,name=price,proto3" json:"price,omitempty"`
|
||||
Quantity int32 `protobuf:"varint,6,opt,name=quantity,proto3" json:"quantity,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
@ -65,8 +65,8 @@ func (*Item) Descriptor() ([]byte, []int) {
|
||||
}
|
||||
|
||||
func (x *Item) GetId() int64 {
|
||||
if x != nil && x.Id != nil {
|
||||
return *x.Id
|
||||
if x != nil {
|
||||
return x.Id
|
||||
}
|
||||
return 0
|
||||
}
|
||||
@ -78,6 +78,13 @@ func (x *Item) GetName() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Item) GetAdded() *timestamppb.Timestamp {
|
||||
if x != nil {
|
||||
return x.Added
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Item) GetDescription() string {
|
||||
if x != nil {
|
||||
return x.Description
|
||||
@ -99,13 +106,6 @@ func (x *Item) GetQuantity() int32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Item) GetAdded() *timestamppb.Timestamp {
|
||||
if x != nil {
|
||||
return x.Added
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type GetItemRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
@ -324,7 +324,10 @@ func (x *GetItemsResponse) GetCount() int64 {
|
||||
|
||||
type CreateItemRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Item *Item `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"`
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"`
|
||||
Price float32 `protobuf:"fixed32,3,opt,name=price,proto3" json:"price,omitempty"`
|
||||
Quantity int32 `protobuf:"varint,4,opt,name=quantity,proto3" json:"quantity,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
@ -359,16 +362,38 @@ func (*CreateItemRequest) Descriptor() ([]byte, []int) {
|
||||
return file_item_v1_item_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
func (x *CreateItemRequest) GetItem() *Item {
|
||||
func (x *CreateItemRequest) GetName() string {
|
||||
if x != nil {
|
||||
return x.Item
|
||||
return x.Name
|
||||
}
|
||||
return nil
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *CreateItemRequest) GetDescription() string {
|
||||
if x != nil {
|
||||
return x.Description
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *CreateItemRequest) GetPrice() float32 {
|
||||
if x != nil {
|
||||
return x.Price
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *CreateItemRequest) GetQuantity() int32 {
|
||||
if x != nil {
|
||||
return x.Quantity
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type CreateItemResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Item *Item `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"`
|
||||
Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
Added *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=added,proto3" json:"added,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
@ -403,16 +428,27 @@ func (*CreateItemResponse) Descriptor() ([]byte, []int) {
|
||||
return file_item_v1_item_proto_rawDescGZIP(), []int{6}
|
||||
}
|
||||
|
||||
func (x *CreateItemResponse) GetItem() *Item {
|
||||
func (x *CreateItemResponse) GetId() int64 {
|
||||
if x != nil {
|
||||
return x.Item
|
||||
return x.Id
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *CreateItemResponse) GetAdded() *timestamppb.Timestamp {
|
||||
if x != nil {
|
||||
return x.Added
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type UpdateItemRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Item *Item `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"`
|
||||
Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
Name *string `protobuf:"bytes,2,opt,name=name,proto3,oneof" json:"name,omitempty"`
|
||||
Description *string `protobuf:"bytes,3,opt,name=description,proto3,oneof" json:"description,omitempty"`
|
||||
Price *float32 `protobuf:"fixed32,4,opt,name=price,proto3,oneof" json:"price,omitempty"`
|
||||
Quantity *int32 `protobuf:"varint,5,opt,name=quantity,proto3,oneof" json:"quantity,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
@ -447,16 +483,43 @@ func (*UpdateItemRequest) Descriptor() ([]byte, []int) {
|
||||
return file_item_v1_item_proto_rawDescGZIP(), []int{7}
|
||||
}
|
||||
|
||||
func (x *UpdateItemRequest) GetItem() *Item {
|
||||
func (x *UpdateItemRequest) GetId() int64 {
|
||||
if x != nil {
|
||||
return x.Item
|
||||
return x.Id
|
||||
}
|
||||
return nil
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *UpdateItemRequest) GetName() string {
|
||||
if x != nil && x.Name != nil {
|
||||
return *x.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *UpdateItemRequest) GetDescription() string {
|
||||
if x != nil && x.Description != nil {
|
||||
return *x.Description
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *UpdateItemRequest) GetPrice() float32 {
|
||||
if x != nil && x.Price != nil {
|
||||
return *x.Price
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *UpdateItemRequest) GetQuantity() int32 {
|
||||
if x != nil && x.Quantity != nil {
|
||||
return *x.Quantity
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type UpdateItemResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Item *Item `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
@ -491,13 +554,6 @@ func (*UpdateItemResponse) Descriptor() ([]byte, []int) {
|
||||
return file_item_v1_item_proto_rawDescGZIP(), []int{8}
|
||||
}
|
||||
|
||||
func (x *UpdateItemResponse) GetItem() *Item {
|
||||
if x != nil {
|
||||
return x.Item
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type DeleteItemRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
@ -580,103 +636,66 @@ func (*DeleteItemResponse) Descriptor() ([]byte, []int) {
|
||||
|
||||
var File_item_v1_item_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_item_v1_item_proto_rawDesc = string([]byte{
|
||||
0x0a, 0x12, 0x69, 0x74, 0x65, 0x6d, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x74, 0x65, 0x6d, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x69, 0x74, 0x65, 0x6d, 0x2e, 0x76, 0x31, 0x1a, 0x1f, 0x67,
|
||||
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74,
|
||||
0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xcb,
|
||||
0x01, 0x0a, 0x04, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x13, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x02, 0x69, 0x64, 0x88, 0x01, 0x01, 0x12, 0x12, 0x0a, 0x04,
|
||||
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
|
||||
0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18,
|
||||
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28,
|
||||
0x02, 0x52, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x71, 0x75, 0x61, 0x6e,
|
||||
0x74, 0x69, 0x74, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x71, 0x75, 0x61, 0x6e,
|
||||
0x74, 0x69, 0x74, 0x79, 0x12, 0x35, 0x0a, 0x05, 0x61, 0x64, 0x64, 0x65, 0x64, 0x18, 0x06, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x48,
|
||||
0x01, 0x52, 0x05, 0x61, 0x64, 0x64, 0x65, 0x64, 0x88, 0x01, 0x01, 0x42, 0x05, 0x0a, 0x03, 0x5f,
|
||||
0x69, 0x64, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x61, 0x64, 0x64, 0x65, 0x64, 0x22, 0x20, 0x0a, 0x0e,
|
||||
0x47, 0x65, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e,
|
||||
0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x22, 0x34,
|
||||
0x0a, 0x0f, 0x47, 0x65, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x12, 0x21, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||
0x0d, 0x2e, 0x69, 0x74, 0x65, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x04,
|
||||
0x69, 0x74, 0x65, 0x6d, 0x22, 0x82, 0x02, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x49, 0x74, 0x65, 0x6d,
|
||||
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72,
|
||||
0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
|
||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74,
|
||||
0x61, 0x6d, 0x70, 0x48, 0x00, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x88, 0x01, 0x01, 0x12,
|
||||
0x31, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67,
|
||||
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54,
|
||||
0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x48, 0x01, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x88,
|
||||
0x01, 0x01, 0x12, 0x1b, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01,
|
||||
0x28, 0x09, 0x48, 0x02, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x88, 0x01, 0x01, 0x12,
|
||||
0x19, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x48, 0x03,
|
||||
0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x88, 0x01, 0x01, 0x12, 0x1b, 0x0a, 0x06, 0x6f, 0x66,
|
||||
0x66, 0x73, 0x65, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x48, 0x04, 0x52, 0x06, 0x6f, 0x66,
|
||||
0x66, 0x73, 0x65, 0x74, 0x88, 0x01, 0x01, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x73, 0x74, 0x61, 0x72,
|
||||
0x74, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x65, 0x6e, 0x64, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x66, 0x69,
|
||||
0x6c, 0x74, 0x65, 0x72, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x42, 0x09,
|
||||
0x0a, 0x07, 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x4d, 0x0a, 0x10, 0x47, 0x65, 0x74,
|
||||
0x49, 0x74, 0x65, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a,
|
||||
0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x69,
|
||||
0x74, 0x65, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x05, 0x69, 0x74, 0x65,
|
||||
0x6d, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x03, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x36, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61,
|
||||
0x74, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a,
|
||||
0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x69, 0x74,
|
||||
0x65, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d,
|
||||
0x22, 0x37, 0x0a, 0x12, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x69, 0x74, 0x65, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x49,
|
||||
0x74, 0x65, 0x6d, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x36, 0x0a, 0x11, 0x55, 0x70, 0x64,
|
||||
0x61, 0x74, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21,
|
||||
0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x69,
|
||||
0x74, 0x65, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x04, 0x69, 0x74, 0x65,
|
||||
0x6d, 0x22, 0x37, 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x69, 0x74, 0x65, 0x6d, 0x2e, 0x76, 0x31, 0x2e,
|
||||
0x49, 0x74, 0x65, 0x6d, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x23, 0x0a, 0x11, 0x44, 0x65,
|
||||
0x6c, 0x65, 0x74, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
|
||||
0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x22,
|
||||
0x14, 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xeb, 0x02, 0x0a, 0x0b, 0x49, 0x74, 0x65, 0x6d, 0x53, 0x65,
|
||||
0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x3e, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, 0x74, 0x65, 0x6d,
|
||||
0x12, 0x17, 0x2e, 0x69, 0x74, 0x65, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x74,
|
||||
0x65, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x69, 0x74, 0x65, 0x6d,
|
||||
0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x41, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x49, 0x74, 0x65, 0x6d,
|
||||
0x73, 0x12, 0x18, 0x2e, 0x69, 0x74, 0x65, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49,
|
||||
0x74, 0x65, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x69, 0x74,
|
||||
0x65, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x47, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61,
|
||||
0x74, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x1a, 0x2e, 0x69, 0x74, 0x65, 0x6d, 0x2e, 0x76, 0x31,
|
||||
0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x69, 0x74, 0x65, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65,
|
||||
0x61, 0x74, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
|
||||
0x00, 0x12, 0x47, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x12,
|
||||
0x1a, 0x2e, 0x69, 0x74, 0x65, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
|
||||
0x49, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x69, 0x74,
|
||||
0x65, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x49, 0x74, 0x65, 0x6d,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x47, 0x0a, 0x0a, 0x44, 0x65,
|
||||
0x6c, 0x65, 0x74, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x1a, 0x2e, 0x69, 0x74, 0x65, 0x6d, 0x2e,
|
||||
0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x69, 0x74, 0x65, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x44,
|
||||
0x65, 0x6c, 0x65, 0x74, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x22, 0x00, 0x42, 0x9d, 0x01, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x2e, 0x69, 0x74, 0x65, 0x6d,
|
||||
0x2e, 0x76, 0x31, 0x42, 0x09, 0x49, 0x74, 0x65, 0x6d, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01,
|
||||
0x5a, 0x46, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x70, 0x6f,
|
||||
0x74, 0x64, 0x65, 0x6d, 0x6f, 0x34, 0x2f, 0x74, 0x72, 0x65, 0x76, 0x73, 0x74, 0x61, 0x63, 0x6b,
|
||||
0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c,
|
||||
0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x69, 0x74, 0x65, 0x6d, 0x2f, 0x76,
|
||||
0x31, 0x3b, 0x69, 0x74, 0x65, 0x6d, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x49, 0x58, 0x58, 0xaa, 0x02,
|
||||
0x07, 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x07, 0x49, 0x74, 0x65, 0x6d, 0x5c,
|
||||
0x56, 0x31, 0xe2, 0x02, 0x13, 0x49, 0x74, 0x65, 0x6d, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42,
|
||||
0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x08, 0x49, 0x74, 0x65, 0x6d, 0x3a,
|
||||
0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
})
|
||||
const file_item_v1_item_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\x12item/v1/item.proto\x12\aitem.v1\x1a\x1fgoogle/protobuf/timestamp.proto\"\xb0\x01\n" +
|
||||
"\x04Item\x12\x0e\n" +
|
||||
"\x02id\x18\x01 \x01(\x03R\x02id\x12\x12\n" +
|
||||
"\x04name\x18\x02 \x01(\tR\x04name\x120\n" +
|
||||
"\x05added\x18\x03 \x01(\v2\x1a.google.protobuf.TimestampR\x05added\x12 \n" +
|
||||
"\vdescription\x18\x04 \x01(\tR\vdescription\x12\x14\n" +
|
||||
"\x05price\x18\x05 \x01(\x02R\x05price\x12\x1a\n" +
|
||||
"\bquantity\x18\x06 \x01(\x05R\bquantity\" \n" +
|
||||
"\x0eGetItemRequest\x12\x0e\n" +
|
||||
"\x02id\x18\x01 \x01(\x03R\x02id\"4\n" +
|
||||
"\x0fGetItemResponse\x12!\n" +
|
||||
"\x04item\x18\x01 \x01(\v2\r.item.v1.ItemR\x04item\"\x82\x02\n" +
|
||||
"\x0fGetItemsRequest\x125\n" +
|
||||
"\x05start\x18\x01 \x01(\v2\x1a.google.protobuf.TimestampH\x00R\x05start\x88\x01\x01\x121\n" +
|
||||
"\x03end\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampH\x01R\x03end\x88\x01\x01\x12\x1b\n" +
|
||||
"\x06filter\x18\x03 \x01(\tH\x02R\x06filter\x88\x01\x01\x12\x19\n" +
|
||||
"\x05limit\x18\x04 \x01(\x05H\x03R\x05limit\x88\x01\x01\x12\x1b\n" +
|
||||
"\x06offset\x18\x05 \x01(\x05H\x04R\x06offset\x88\x01\x01B\b\n" +
|
||||
"\x06_startB\x06\n" +
|
||||
"\x04_endB\t\n" +
|
||||
"\a_filterB\b\n" +
|
||||
"\x06_limitB\t\n" +
|
||||
"\a_offset\"M\n" +
|
||||
"\x10GetItemsResponse\x12#\n" +
|
||||
"\x05items\x18\x01 \x03(\v2\r.item.v1.ItemR\x05items\x12\x14\n" +
|
||||
"\x05count\x18\x02 \x01(\x03R\x05count\"{\n" +
|
||||
"\x11CreateItemRequest\x12\x12\n" +
|
||||
"\x04name\x18\x01 \x01(\tR\x04name\x12 \n" +
|
||||
"\vdescription\x18\x02 \x01(\tR\vdescription\x12\x14\n" +
|
||||
"\x05price\x18\x03 \x01(\x02R\x05price\x12\x1a\n" +
|
||||
"\bquantity\x18\x04 \x01(\x05R\bquantity\"V\n" +
|
||||
"\x12CreateItemResponse\x12\x0e\n" +
|
||||
"\x02id\x18\x01 \x01(\x03R\x02id\x120\n" +
|
||||
"\x05added\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\x05added\"\xcf\x01\n" +
|
||||
"\x11UpdateItemRequest\x12\x0e\n" +
|
||||
"\x02id\x18\x01 \x01(\x03R\x02id\x12\x17\n" +
|
||||
"\x04name\x18\x02 \x01(\tH\x00R\x04name\x88\x01\x01\x12%\n" +
|
||||
"\vdescription\x18\x03 \x01(\tH\x01R\vdescription\x88\x01\x01\x12\x19\n" +
|
||||
"\x05price\x18\x04 \x01(\x02H\x02R\x05price\x88\x01\x01\x12\x1f\n" +
|
||||
"\bquantity\x18\x05 \x01(\x05H\x03R\bquantity\x88\x01\x01B\a\n" +
|
||||
"\x05_nameB\x0e\n" +
|
||||
"\f_descriptionB\b\n" +
|
||||
"\x06_priceB\v\n" +
|
||||
"\t_quantity\"\x14\n" +
|
||||
"\x12UpdateItemResponse\"#\n" +
|
||||
"\x11DeleteItemRequest\x12\x0e\n" +
|
||||
"\x02id\x18\x01 \x01(\x03R\x02id\"\x14\n" +
|
||||
"\x12DeleteItemResponse2\xeb\x02\n" +
|
||||
"\vItemService\x12>\n" +
|
||||
"\aGetItem\x12\x17.item.v1.GetItemRequest\x1a\x18.item.v1.GetItemResponse\"\x00\x12A\n" +
|
||||
"\bGetItems\x12\x18.item.v1.GetItemsRequest\x1a\x19.item.v1.GetItemsResponse\"\x00\x12G\n" +
|
||||
"\n" +
|
||||
"CreateItem\x12\x1a.item.v1.CreateItemRequest\x1a\x1b.item.v1.CreateItemResponse\"\x00\x12G\n" +
|
||||
"\n" +
|
||||
"UpdateItem\x12\x1a.item.v1.UpdateItemRequest\x1a\x1b.item.v1.UpdateItemResponse\"\x00\x12G\n" +
|
||||
"\n" +
|
||||
"DeleteItem\x12\x1a.item.v1.DeleteItemRequest\x1a\x1b.item.v1.DeleteItemResponse\"\x00B\x9c\x01\n" +
|
||||
"\vcom.item.v1B\tItemProtoP\x01ZEgithub.com/spotdemo4/trevstack/server/internal/connect/item/v1;itemv1\xa2\x02\x03IXX\xaa\x02\aItem.V1\xca\x02\aItem\\V1\xe2\x02\x13Item\\V1\\GPBMetadata\xea\x02\bItem::V1b\x06proto3"
|
||||
|
||||
var (
|
||||
file_item_v1_item_proto_rawDescOnce sync.Once
|
||||
@ -711,25 +730,22 @@ var file_item_v1_item_proto_depIdxs = []int32{
|
||||
11, // 2: item.v1.GetItemsRequest.start:type_name -> google.protobuf.Timestamp
|
||||
11, // 3: item.v1.GetItemsRequest.end:type_name -> google.protobuf.Timestamp
|
||||
0, // 4: item.v1.GetItemsResponse.items:type_name -> item.v1.Item
|
||||
0, // 5: item.v1.CreateItemRequest.item:type_name -> item.v1.Item
|
||||
0, // 6: item.v1.CreateItemResponse.item:type_name -> item.v1.Item
|
||||
0, // 7: item.v1.UpdateItemRequest.item:type_name -> item.v1.Item
|
||||
0, // 8: item.v1.UpdateItemResponse.item:type_name -> item.v1.Item
|
||||
1, // 9: item.v1.ItemService.GetItem:input_type -> item.v1.GetItemRequest
|
||||
3, // 10: item.v1.ItemService.GetItems:input_type -> item.v1.GetItemsRequest
|
||||
5, // 11: item.v1.ItemService.CreateItem:input_type -> item.v1.CreateItemRequest
|
||||
7, // 12: item.v1.ItemService.UpdateItem:input_type -> item.v1.UpdateItemRequest
|
||||
9, // 13: item.v1.ItemService.DeleteItem:input_type -> item.v1.DeleteItemRequest
|
||||
2, // 14: item.v1.ItemService.GetItem:output_type -> item.v1.GetItemResponse
|
||||
4, // 15: item.v1.ItemService.GetItems:output_type -> item.v1.GetItemsResponse
|
||||
6, // 16: item.v1.ItemService.CreateItem:output_type -> item.v1.CreateItemResponse
|
||||
8, // 17: item.v1.ItemService.UpdateItem:output_type -> item.v1.UpdateItemResponse
|
||||
10, // 18: item.v1.ItemService.DeleteItem:output_type -> item.v1.DeleteItemResponse
|
||||
14, // [14:19] is the sub-list for method output_type
|
||||
9, // [9:14] is the sub-list for method input_type
|
||||
9, // [9:9] is the sub-list for extension type_name
|
||||
9, // [9:9] is the sub-list for extension extendee
|
||||
0, // [0:9] is the sub-list for field type_name
|
||||
11, // 5: item.v1.CreateItemResponse.added:type_name -> google.protobuf.Timestamp
|
||||
1, // 6: item.v1.ItemService.GetItem:input_type -> item.v1.GetItemRequest
|
||||
3, // 7: item.v1.ItemService.GetItems:input_type -> item.v1.GetItemsRequest
|
||||
5, // 8: item.v1.ItemService.CreateItem:input_type -> item.v1.CreateItemRequest
|
||||
7, // 9: item.v1.ItemService.UpdateItem:input_type -> item.v1.UpdateItemRequest
|
||||
9, // 10: item.v1.ItemService.DeleteItem:input_type -> item.v1.DeleteItemRequest
|
||||
2, // 11: item.v1.ItemService.GetItem:output_type -> item.v1.GetItemResponse
|
||||
4, // 12: item.v1.ItemService.GetItems:output_type -> item.v1.GetItemsResponse
|
||||
6, // 13: item.v1.ItemService.CreateItem:output_type -> item.v1.CreateItemResponse
|
||||
8, // 14: item.v1.ItemService.UpdateItem:output_type -> item.v1.UpdateItemResponse
|
||||
10, // 15: item.v1.ItemService.DeleteItem:output_type -> item.v1.DeleteItemResponse
|
||||
11, // [11:16] is the sub-list for method output_type
|
||||
6, // [6:11] is the sub-list for method input_type
|
||||
6, // [6:6] is the sub-list for extension type_name
|
||||
6, // [6:6] is the sub-list for extension extendee
|
||||
0, // [0:6] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_item_v1_item_proto_init() }
|
||||
@ -737,8 +753,8 @@ func file_item_v1_item_proto_init() {
|
||||
if File_item_v1_item_proto != nil {
|
||||
return
|
||||
}
|
||||
file_item_v1_item_proto_msgTypes[0].OneofWrappers = []any{}
|
||||
file_item_v1_item_proto_msgTypes[3].OneofWrappers = []any{}
|
||||
file_item_v1_item_proto_msgTypes[7].OneofWrappers = []any{}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
@ -8,7 +8,7 @@ import (
|
||||
connect "connectrpc.com/connect"
|
||||
context "context"
|
||||
errors "errors"
|
||||
v1 "github.com/spotdemo4/trevstack/server/internal/services/item/v1"
|
||||
v1 "github.com/spotdemo4/trevstack/server/internal/connect/item/v1"
|
||||
http "net/http"
|
||||
strings "strings"
|
||||
)
|
@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.36.5
|
||||
// protoc-gen-go v1.36.6
|
||||
// protoc (unknown)
|
||||
// source: user/v1/auth.proto
|
||||
|
||||
@ -287,51 +287,26 @@ func (*LogoutResponse) Descriptor() ([]byte, []int) {
|
||||
|
||||
var File_user_v1_auth_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_user_v1_auth_proto_rawDesc = string([]byte{
|
||||
0x0a, 0x12, 0x75, 0x73, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x22, 0x46, 0x0a,
|
||||
0x0c, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a,
|
||||
0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73,
|
||||
0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73,
|
||||
0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x25, 0x0a, 0x0d, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x72, 0x0a, 0x0d,
|
||||
0x53, 0x69, 0x67, 0x6e, 0x55, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a,
|
||||
0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73,
|
||||
0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73,
|
||||
0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d,
|
||||
0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x0f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64,
|
||||
0x22, 0x10, 0x0a, 0x0e, 0x53, 0x69, 0x67, 0x6e, 0x55, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x22, 0x0f, 0x0a, 0x0d, 0x4c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x22, 0x10, 0x0a, 0x0e, 0x4c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xc1, 0x01, 0x0a, 0x0b, 0x41, 0x75, 0x74, 0x68, 0x53, 0x65,
|
||||
0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x38, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x15,
|
||||
0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e,
|
||||
0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12,
|
||||
0x3b, 0x0a, 0x06, 0x53, 0x69, 0x67, 0x6e, 0x55, 0x70, 0x12, 0x16, 0x2e, 0x75, 0x73, 0x65, 0x72,
|
||||
0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x55, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x1a, 0x17, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e,
|
||||
0x55, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3b, 0x0a, 0x06,
|
||||
0x4c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x12, 0x16, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31,
|
||||
0x2e, 0x4c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17,
|
||||
0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x9d, 0x01, 0x0a, 0x0b, 0x63, 0x6f,
|
||||
0x6d, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x42, 0x09, 0x41, 0x75, 0x74, 0x68, 0x50,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x46, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
|
||||
0x6f, 0x6d, 0x2f, 0x73, 0x70, 0x6f, 0x74, 0x64, 0x65, 0x6d, 0x6f, 0x34, 0x2f, 0x74, 0x72, 0x65,
|
||||
0x76, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x69, 0x6e,
|
||||
0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f,
|
||||
0x75, 0x73, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x3b, 0x75, 0x73, 0x65, 0x72, 0x76, 0x31, 0xa2, 0x02,
|
||||
0x03, 0x55, 0x58, 0x58, 0xaa, 0x02, 0x07, 0x55, 0x73, 0x65, 0x72, 0x2e, 0x56, 0x31, 0xca, 0x02,
|
||||
0x07, 0x55, 0x73, 0x65, 0x72, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x13, 0x55, 0x73, 0x65, 0x72, 0x5c,
|
||||
0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02,
|
||||
0x08, 0x55, 0x73, 0x65, 0x72, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x33,
|
||||
})
|
||||
const file_user_v1_auth_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\x12user/v1/auth.proto\x12\auser.v1\"F\n" +
|
||||
"\fLoginRequest\x12\x1a\n" +
|
||||
"\busername\x18\x01 \x01(\tR\busername\x12\x1a\n" +
|
||||
"\bpassword\x18\x02 \x01(\tR\bpassword\"%\n" +
|
||||
"\rLoginResponse\x12\x14\n" +
|
||||
"\x05token\x18\x01 \x01(\tR\x05token\"r\n" +
|
||||
"\rSignUpRequest\x12\x1a\n" +
|
||||
"\busername\x18\x01 \x01(\tR\busername\x12\x1a\n" +
|
||||
"\bpassword\x18\x02 \x01(\tR\bpassword\x12)\n" +
|
||||
"\x10confirm_password\x18\x03 \x01(\tR\x0fconfirmPassword\"\x10\n" +
|
||||
"\x0eSignUpResponse\"\x0f\n" +
|
||||
"\rLogoutRequest\"\x10\n" +
|
||||
"\x0eLogoutResponse2\xc1\x01\n" +
|
||||
"\vAuthService\x128\n" +
|
||||
"\x05Login\x12\x15.user.v1.LoginRequest\x1a\x16.user.v1.LoginResponse\"\x00\x12;\n" +
|
||||
"\x06SignUp\x12\x16.user.v1.SignUpRequest\x1a\x17.user.v1.SignUpResponse\"\x00\x12;\n" +
|
||||
"\x06Logout\x12\x16.user.v1.LogoutRequest\x1a\x17.user.v1.LogoutResponse\"\x00B\x9c\x01\n" +
|
||||
"\vcom.user.v1B\tAuthProtoP\x01ZEgithub.com/spotdemo4/trevstack/server/internal/connect/user/v1;userv1\xa2\x02\x03UXX\xaa\x02\aUser.V1\xca\x02\aUser\\V1\xe2\x02\x13User\\V1\\GPBMetadata\xea\x02\bUser::V1b\x06proto3"
|
||||
|
||||
var (
|
||||
file_user_v1_auth_proto_rawDescOnce sync.Once
|
@ -1,6 +1,6 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.36.5
|
||||
// protoc-gen-go v1.36.6
|
||||
// protoc (unknown)
|
||||
// source: user/v1/user.proto
|
||||
|
||||
@ -459,84 +459,39 @@ func (x *UpdateProfilePictureResponse) GetUser() *User {
|
||||
|
||||
var File_user_v1_user_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_user_v1_user_proto_rawDesc = string([]byte{
|
||||
0x0a, 0x12, 0x75, 0x73, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x22, 0x7c, 0x0a,
|
||||
0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d,
|
||||
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d,
|
||||
0x65, 0x12, 0x31, 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x70, 0x69, 0x63,
|
||||
0x74, 0x75, 0x72, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52,
|
||||
0x10, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x50, 0x69, 0x63, 0x74, 0x75, 0x72, 0x65, 0x49,
|
||||
0x64, 0x88, 0x01, 0x01, 0x42, 0x15, 0x0a, 0x13, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65,
|
||||
0x5f, 0x70, 0x69, 0x63, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x69, 0x64, 0x22, 0x10, 0x0a, 0x0e, 0x47,
|
||||
0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x34, 0x0a,
|
||||
0x0f, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x12, 0x21, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d,
|
||||
0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75,
|
||||
0x73, 0x65, 0x72, 0x22, 0x88, 0x01, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61,
|
||||
0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a,
|
||||
0x0c, 0x6f, 0x6c, 0x64, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x6c, 0x64, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64,
|
||||
0x12, 0x21, 0x0a, 0x0c, 0x6e, 0x65, 0x77, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6e, 0x65, 0x77, 0x50, 0x61, 0x73, 0x73, 0x77,
|
||||
0x6f, 0x72, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x5f, 0x70,
|
||||
0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63,
|
||||
0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x3b,
|
||||
0x0a, 0x16, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31,
|
||||
0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x59, 0x0a, 0x10, 0x47,
|
||||
0x65, 0x74, 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
|
||||
0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x63,
|
||||
0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18,
|
||||
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x50, 0x61,
|
||||
0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x25, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x41, 0x50, 0x49,
|
||||
0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b,
|
||||
0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0x4e, 0x0a,
|
||||
0x1b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x50, 0x69,
|
||||
0x63, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09,
|
||||
0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x08, 0x66, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74,
|
||||
0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x41, 0x0a,
|
||||
0x1c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x50, 0x69,
|
||||
0x63, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a,
|
||||
0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x75, 0x73,
|
||||
0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72,
|
||||
0x32, 0xcf, 0x02, 0x0a, 0x0b, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
|
||||
0x12, 0x3e, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x17, 0x2e, 0x75, 0x73,
|
||||
0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47,
|
||||
0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00,
|
||||
0x12, 0x53, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f,
|
||||
0x72, 0x64, 0x12, 0x1e, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64,
|
||||
0x61, 0x74, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64,
|
||||
0x61, 0x74, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x44, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x41, 0x50, 0x49, 0x4b,
|
||||
0x65, 0x79, 0x12, 0x19, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74,
|
||||
0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e,
|
||||
0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x50, 0x49, 0x4b, 0x65,
|
||||
0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x65, 0x0a, 0x14, 0x55,
|
||||
0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x50, 0x69, 0x63, 0x74,
|
||||
0x75, 0x72, 0x65, 0x12, 0x24, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70,
|
||||
0x64, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x50, 0x69, 0x63, 0x74, 0x75,
|
||||
0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x75, 0x73, 0x65, 0x72,
|
||||
0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c,
|
||||
0x65, 0x50, 0x69, 0x63, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x22, 0x00, 0x42, 0x9d, 0x01, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e,
|
||||
0x76, 0x31, 0x42, 0x09, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a,
|
||||
0x46, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x70, 0x6f, 0x74,
|
||||
0x64, 0x65, 0x6d, 0x6f, 0x34, 0x2f, 0x74, 0x72, 0x65, 0x76, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x2f,
|
||||
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f,
|
||||
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x2f, 0x76, 0x31,
|
||||
0x3b, 0x75, 0x73, 0x65, 0x72, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x55, 0x58, 0x58, 0xaa, 0x02, 0x07,
|
||||
0x55, 0x73, 0x65, 0x72, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x07, 0x55, 0x73, 0x65, 0x72, 0x5c, 0x56,
|
||||
0x31, 0xe2, 0x02, 0x13, 0x55, 0x73, 0x65, 0x72, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d,
|
||||
0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x08, 0x55, 0x73, 0x65, 0x72, 0x3a, 0x3a,
|
||||
0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
})
|
||||
const file_user_v1_user_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\x12user/v1/user.proto\x12\auser.v1\"|\n" +
|
||||
"\x04User\x12\x0e\n" +
|
||||
"\x02id\x18\x01 \x01(\x03R\x02id\x12\x1a\n" +
|
||||
"\busername\x18\x02 \x01(\tR\busername\x121\n" +
|
||||
"\x12profile_picture_id\x18\x03 \x01(\x03H\x00R\x10profilePictureId\x88\x01\x01B\x15\n" +
|
||||
"\x13_profile_picture_id\"\x10\n" +
|
||||
"\x0eGetUserRequest\"4\n" +
|
||||
"\x0fGetUserResponse\x12!\n" +
|
||||
"\x04user\x18\x01 \x01(\v2\r.user.v1.UserR\x04user\"\x88\x01\n" +
|
||||
"\x15UpdatePasswordRequest\x12!\n" +
|
||||
"\fold_password\x18\x01 \x01(\tR\voldPassword\x12!\n" +
|
||||
"\fnew_password\x18\x02 \x01(\tR\vnewPassword\x12)\n" +
|
||||
"\x10confirm_password\x18\x03 \x01(\tR\x0fconfirmPassword\";\n" +
|
||||
"\x16UpdatePasswordResponse\x12!\n" +
|
||||
"\x04user\x18\x01 \x01(\v2\r.user.v1.UserR\x04user\"Y\n" +
|
||||
"\x10GetAPIKeyRequest\x12\x1a\n" +
|
||||
"\bpassword\x18\x01 \x01(\tR\bpassword\x12)\n" +
|
||||
"\x10confirm_password\x18\x02 \x01(\tR\x0fconfirmPassword\"%\n" +
|
||||
"\x11GetAPIKeyResponse\x12\x10\n" +
|
||||
"\x03key\x18\x01 \x01(\tR\x03key\"N\n" +
|
||||
"\x1bUpdateProfilePictureRequest\x12\x1b\n" +
|
||||
"\tfile_name\x18\x01 \x01(\tR\bfileName\x12\x12\n" +
|
||||
"\x04data\x18\x02 \x01(\fR\x04data\"A\n" +
|
||||
"\x1cUpdateProfilePictureResponse\x12!\n" +
|
||||
"\x04user\x18\x01 \x01(\v2\r.user.v1.UserR\x04user2\xcf\x02\n" +
|
||||
"\vUserService\x12>\n" +
|
||||
"\aGetUser\x12\x17.user.v1.GetUserRequest\x1a\x18.user.v1.GetUserResponse\"\x00\x12S\n" +
|
||||
"\x0eUpdatePassword\x12\x1e.user.v1.UpdatePasswordRequest\x1a\x1f.user.v1.UpdatePasswordResponse\"\x00\x12D\n" +
|
||||
"\tGetAPIKey\x12\x19.user.v1.GetAPIKeyRequest\x1a\x1a.user.v1.GetAPIKeyResponse\"\x00\x12e\n" +
|
||||
"\x14UpdateProfilePicture\x12$.user.v1.UpdateProfilePictureRequest\x1a%.user.v1.UpdateProfilePictureResponse\"\x00B\x9c\x01\n" +
|
||||
"\vcom.user.v1B\tUserProtoP\x01ZEgithub.com/spotdemo4/trevstack/server/internal/connect/user/v1;userv1\xa2\x02\x03UXX\xaa\x02\aUser.V1\xca\x02\aUser\\V1\xe2\x02\x13User\\V1\\GPBMetadata\xea\x02\bUser::V1b\x06proto3"
|
||||
|
||||
var (
|
||||
file_user_v1_user_proto_rawDescOnce sync.Once
|
@ -8,7 +8,7 @@ import (
|
||||
connect "connectrpc.com/connect"
|
||||
context "context"
|
||||
errors "errors"
|
||||
v1 "github.com/spotdemo4/trevstack/server/internal/services/user/v1"
|
||||
v1 "github.com/spotdemo4/trevstack/server/internal/connect/user/v1"
|
||||
http "net/http"
|
||||
strings "strings"
|
||||
)
|
@ -8,7 +8,7 @@ import (
|
||||
connect "connectrpc.com/connect"
|
||||
context "context"
|
||||
errors "errors"
|
||||
v1 "github.com/spotdemo4/trevstack/server/internal/services/user/v1"
|
||||
v1 "github.com/spotdemo4/trevstack/server/internal/connect/user/v1"
|
||||
http "net/http"
|
||||
strings "strings"
|
||||
)
|
@ -9,12 +9,17 @@ import (
|
||||
_ "github.com/spotdemo4/dbmate-sqlite-modernc/pkg/driver/sqlite" // Modernc sqlite
|
||||
)
|
||||
|
||||
func Migrate(url *url.URL, dbFS *embed.FS) error {
|
||||
func Migrate(dsn string, dbFS *embed.FS) error {
|
||||
if dbFS == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
db := dbmate.New(url)
|
||||
dburl, err := url.Parse(dsn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
db := dbmate.New(dburl)
|
||||
db.Driver()
|
||||
db.FS = dbFS
|
||||
|
||||
|
@ -1,74 +0,0 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"runtime"
|
||||
|
||||
_ "github.com/lib/pq" // Postgres
|
||||
"github.com/stephenafamo/bob"
|
||||
)
|
||||
|
||||
func NewPostgresConnection(url *url.URL) (*bob.DB, error) {
|
||||
db, err := sql.Open("postgres", postgresConnectionString(url))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bobdb := bob.NewDB(db)
|
||||
|
||||
return &bobdb, nil
|
||||
}
|
||||
|
||||
func postgresConnectionString(u *url.URL) string {
|
||||
hostname := u.Hostname()
|
||||
port := u.Port()
|
||||
query := u.Query()
|
||||
|
||||
// support socket parameter for consistency with mysql
|
||||
if query.Get("socket") != "" {
|
||||
query.Set("host", query.Get("socket"))
|
||||
query.Del("socket")
|
||||
}
|
||||
|
||||
// default hostname
|
||||
if hostname == "" && query.Get("host") == "" {
|
||||
switch runtime.GOOS {
|
||||
case "linux":
|
||||
query.Set("host", "/var/run/postgresql")
|
||||
case "darwin", "freebsd", "dragonfly", "openbsd", "netbsd":
|
||||
query.Set("host", "/tmp")
|
||||
default:
|
||||
hostname = "localhost"
|
||||
}
|
||||
}
|
||||
|
||||
// host param overrides url hostname
|
||||
if query.Get("host") != "" {
|
||||
hostname = ""
|
||||
}
|
||||
|
||||
// always specify a port
|
||||
if query.Get("port") != "" {
|
||||
port = query.Get("port")
|
||||
query.Del("port")
|
||||
}
|
||||
if port == "" {
|
||||
switch u.Scheme {
|
||||
case "redshift":
|
||||
port = "5439"
|
||||
default:
|
||||
port = "5432"
|
||||
}
|
||||
}
|
||||
|
||||
// generate output URL
|
||||
out, _ := url.Parse(u.String())
|
||||
// force scheme back to postgres if there was another postgres-compatible scheme
|
||||
out.Scheme = "postgres"
|
||||
out.Host = fmt.Sprintf("%s:%s", hostname, port)
|
||||
out.RawQuery = query.Encode()
|
||||
|
||||
return out.String()
|
||||
}
|
@ -2,65 +2,28 @@ package database
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/stephenafamo/bob"
|
||||
"github.com/spotdemo4/trevstack/server/internal/sqlc"
|
||||
_ "modernc.org/sqlite" // Sqlite
|
||||
)
|
||||
|
||||
func NewSQLiteConnection(url *url.URL) (*bob.DB, error) {
|
||||
db, err := sql.Open("sqlite", sqliteConnectionString(url))
|
||||
func New(dsn string) (*sqlc.Queries, *sql.DB, error) {
|
||||
// Validate dsn
|
||||
sp := strings.Split(dsn, ":")
|
||||
if len(sp) != 2 {
|
||||
return nil, nil, errors.New("invalid dsn")
|
||||
}
|
||||
|
||||
// Open db
|
||||
db, err := sql.Open("sqlite", sp[1])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Create new bob db
|
||||
bobdb := bob.NewDB(db)
|
||||
// Create new sqlc connection
|
||||
sqlc := sqlc.New(db)
|
||||
|
||||
return &bobdb, nil
|
||||
}
|
||||
|
||||
// ConnectionString converts a URL into a valid connection string
|
||||
func sqliteConnectionString(u *url.URL) string {
|
||||
// duplicate URL and remove scheme
|
||||
newURL := *u
|
||||
newURL.Scheme = ""
|
||||
|
||||
if newURL.Opaque == "" && newURL.Path != "" {
|
||||
// When the DSN is in the form "scheme:/absolute/path" or
|
||||
// "scheme://absolute/path" or "scheme:///absolute/path", url.Parse
|
||||
// will consider the file path as :
|
||||
// - "absolute" as the hostname
|
||||
// - "path" (and the rest until "?") as the URL path.
|
||||
// Instead, when the DSN is in the form "scheme:", the (relative) file
|
||||
// path is stored in the "Opaque" field.
|
||||
// See: https://pkg.go.dev/net/url#URL
|
||||
//
|
||||
// While Opaque is not escaped, the URL Path is. So, if .Path contains
|
||||
// the file path, we need to un-escape it, and rebuild the full path.
|
||||
|
||||
newURL.Opaque = "//" + newURL.Host + mustUnescapePath(newURL.Path)
|
||||
newURL.Path = ""
|
||||
}
|
||||
|
||||
// trim duplicate leading slashes
|
||||
str := regexp.MustCompile("^//+").ReplaceAllString(newURL.String(), "/")
|
||||
|
||||
return str
|
||||
}
|
||||
|
||||
// MustUnescapePath unescapes a URL path, and panics if it fails.
|
||||
// It is used during in cases where we are parsing a generated path.
|
||||
func mustUnescapePath(s string) string {
|
||||
if s == "" {
|
||||
panic("missing path")
|
||||
}
|
||||
|
||||
path, err := url.PathUnescape(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return path
|
||||
return sqlc, db, nil
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package file
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"net/http"
|
||||
@ -9,13 +8,11 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/spotdemo4/trevstack/server/internal/interceptors"
|
||||
"github.com/spotdemo4/trevstack/server/internal/models"
|
||||
"github.com/stephenafamo/bob"
|
||||
"github.com/stephenafamo/bob/dialect/sqlite"
|
||||
"github.com/spotdemo4/trevstack/server/internal/sqlc"
|
||||
)
|
||||
|
||||
type FileHandler struct {
|
||||
db *bob.DB
|
||||
db *sqlc.Queries
|
||||
key []byte
|
||||
}
|
||||
|
||||
@ -45,12 +42,10 @@ func (h *FileHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// Get the file from the database
|
||||
file, err := models.Files.Query(
|
||||
sqlite.WhereAnd(
|
||||
models.SelectWhere.Files.ID.EQ(int64(id)),
|
||||
models.SelectWhere.Files.UserID.EQ(userid),
|
||||
),
|
||||
).One(context.Background(), h.db)
|
||||
file, err := h.db.GetFile(r.Context(), sqlc.GetFileParams{
|
||||
ID: int64(id),
|
||||
UserID: userid,
|
||||
})
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
http.Error(w, "Not Found", http.StatusNotFound)
|
||||
@ -64,7 +59,7 @@ func (h *FileHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write(file.Data)
|
||||
}
|
||||
|
||||
func NewFileHandler(db *bob.DB, key string) http.Handler {
|
||||
func NewFileHandler(db *sqlc.Queries, key string) http.Handler {
|
||||
return interceptors.WithAuthRedirect(
|
||||
&FileHandler{
|
||||
db: db,
|
||||
|
@ -8,32 +8,29 @@ import (
|
||||
"time"
|
||||
|
||||
"connectrpc.com/connect"
|
||||
"github.com/aarondl/opt/omit"
|
||||
itemv1 "github.com/spotdemo4/trevstack/server/internal/connect/item/v1"
|
||||
"github.com/spotdemo4/trevstack/server/internal/connect/item/v1/itemv1connect"
|
||||
"github.com/spotdemo4/trevstack/server/internal/interceptors"
|
||||
"github.com/spotdemo4/trevstack/server/internal/models"
|
||||
itemv1 "github.com/spotdemo4/trevstack/server/internal/services/item/v1"
|
||||
"github.com/spotdemo4/trevstack/server/internal/services/item/v1/itemv1connect"
|
||||
"github.com/stephenafamo/bob"
|
||||
"github.com/stephenafamo/bob/dialect/sqlite"
|
||||
"github.com/stephenafamo/bob/dialect/sqlite/sm"
|
||||
"github.com/spotdemo4/trevstack/server/internal/sqlc"
|
||||
"github.com/spotdemo4/trevstack/server/internal/util"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
func itemToConnect(item *models.Item) *itemv1.Item {
|
||||
func itemToConnect(item sqlc.Item) *itemv1.Item {
|
||||
timestamp := timestamppb.New(item.Added)
|
||||
|
||||
return &itemv1.Item{
|
||||
Id: &item.ID,
|
||||
Id: item.ID,
|
||||
Name: item.Name,
|
||||
Description: item.Description,
|
||||
Price: item.Price,
|
||||
Price: float32(item.Price),
|
||||
Quantity: int32(item.Quantity),
|
||||
Added: timestamp,
|
||||
}
|
||||
}
|
||||
|
||||
type Handler struct {
|
||||
db *bob.DB
|
||||
db *sqlc.Queries
|
||||
key []byte
|
||||
}
|
||||
|
||||
@ -44,12 +41,10 @@ func (h *Handler) GetItem(ctx context.Context, req *connect.Request[itemv1.GetIt
|
||||
}
|
||||
|
||||
// Get item
|
||||
item, err := models.Items.Query(
|
||||
sqlite.WhereAnd(
|
||||
models.SelectWhere.Items.ID.EQ(req.Msg.Id),
|
||||
models.SelectWhere.Items.UserID.EQ(userid),
|
||||
),
|
||||
).One(ctx, h.db)
|
||||
item, err := h.db.GetItem(ctx, sqlc.GetItemParams{
|
||||
ID: req.Msg.Id,
|
||||
UserID: userid,
|
||||
})
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, connect.NewError(connect.CodeNotFound, err)
|
||||
@ -70,34 +65,26 @@ func (h *Handler) GetItems(ctx context.Context, req *connect.Request[itemv1.GetI
|
||||
return nil, connect.NewError(connect.CodeUnauthenticated, errors.New("unauthenticated"))
|
||||
}
|
||||
|
||||
// Filters
|
||||
query := models.Items.Query(models.SelectWhere.Items.UserID.EQ(userid))
|
||||
countQuery := models.Items.Query(models.SelectWhere.Items.UserID.EQ(userid))
|
||||
|
||||
// Counted filters
|
||||
if req.Msg.Start != nil {
|
||||
query.Apply(models.SelectWhere.Items.Added.GTE(req.Msg.Start.AsTime()))
|
||||
countQuery.Apply(models.SelectWhere.Items.Added.GTE(req.Msg.Start.AsTime()))
|
||||
}
|
||||
if req.Msg.End != nil {
|
||||
query.Apply(models.SelectWhere.Items.Added.LTE(req.Msg.End.AsTime()))
|
||||
countQuery.Apply(models.SelectWhere.Items.Added.LTE(req.Msg.End.AsTime()))
|
||||
}
|
||||
if req.Msg.Filter != nil && *req.Msg.Filter != "" {
|
||||
query.Apply(models.SelectWhere.Items.Name.Like("%" + *req.Msg.Filter + "%"))
|
||||
countQuery.Apply(models.SelectWhere.Items.Name.Like(*req.Msg.Filter))
|
||||
}
|
||||
|
||||
// Uncounted filters
|
||||
if req.Msg.Limit != nil {
|
||||
query.Apply(sm.Limit(*req.Msg.Limit))
|
||||
}
|
||||
// Verify
|
||||
offset := 0
|
||||
if req.Msg.Offset != nil {
|
||||
query.Apply(sm.Offset(*req.Msg.Offset))
|
||||
offset = int(*req.Msg.Offset)
|
||||
}
|
||||
|
||||
// Get items & count
|
||||
items, err := query.All(ctx, h.db)
|
||||
limit := 10
|
||||
if req.Msg.Limit != nil {
|
||||
limit = int(*req.Msg.Limit)
|
||||
}
|
||||
|
||||
// Get items
|
||||
items, err := h.db.GetItems(ctx, sqlc.GetItemsParams{
|
||||
UserID: userid,
|
||||
Name: util.NullLike(req.Msg.Filter),
|
||||
Start: util.NullTimestamp(req.Msg.Start),
|
||||
End: util.NullTimestamp(req.Msg.End),
|
||||
Offset: int64(offset),
|
||||
Limit: int64(limit),
|
||||
})
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, connect.NewError(connect.CodeNotFound, err)
|
||||
@ -106,12 +93,18 @@ func (h *Handler) GetItems(ctx context.Context, req *connect.Request[itemv1.GetI
|
||||
return nil, connect.NewError(connect.CodeInternal, err)
|
||||
}
|
||||
|
||||
count, err := query.Count(ctx, h.db)
|
||||
// Get items count
|
||||
count, err := h.db.GetItemsCount(ctx, sqlc.GetItemsCountParams{
|
||||
UserID: userid,
|
||||
Name: util.NullLike(req.Msg.Filter),
|
||||
Start: util.NullTimestamp(req.Msg.Start),
|
||||
End: util.NullTimestamp(req.Msg.End),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, connect.NewError(connect.CodeInternal, err)
|
||||
}
|
||||
|
||||
// Convert to connect v1 items
|
||||
// Convert to connect items
|
||||
resItems := []*itemv1.Item{}
|
||||
for _, item := range items {
|
||||
resItems = append(resItems, itemToConnect(item))
|
||||
@ -130,20 +123,24 @@ func (h *Handler) CreateItem(ctx context.Context, req *connect.Request[itemv1.Cr
|
||||
return nil, connect.NewError(connect.CodeUnauthenticated, errors.New("unauthenticated"))
|
||||
}
|
||||
|
||||
item, err := models.Items.Insert(&models.ItemSetter{
|
||||
Name: omit.From(req.Msg.Item.Name),
|
||||
Description: omit.From(req.Msg.Item.Description),
|
||||
Price: omit.From(req.Msg.Item.Price),
|
||||
Quantity: omit.From(int64(req.Msg.Item.Quantity)),
|
||||
Added: omit.From(time.Now()),
|
||||
UserID: omit.From(userid),
|
||||
}).One(ctx, h.db)
|
||||
time := time.Now()
|
||||
|
||||
// Insert item
|
||||
id, err := h.db.InsertItem(ctx, sqlc.InsertItemParams{
|
||||
Name: req.Msg.Name,
|
||||
Added: time,
|
||||
Description: req.Msg.Description,
|
||||
Price: float64(req.Msg.Price),
|
||||
Quantity: int64(req.Msg.Quantity),
|
||||
UserID: userid,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, connect.NewError(connect.CodeInternal, err)
|
||||
}
|
||||
|
||||
res := connect.NewResponse(&itemv1.CreateItemResponse{
|
||||
Item: itemToConnect(item),
|
||||
Id: id,
|
||||
Added: timestamppb.New(time),
|
||||
})
|
||||
return res, nil
|
||||
}
|
||||
@ -154,34 +151,23 @@ func (h *Handler) UpdateItem(ctx context.Context, req *connect.Request[itemv1.Up
|
||||
return nil, connect.NewError(connect.CodeUnauthenticated, errors.New("unauthenticated"))
|
||||
}
|
||||
|
||||
// Validate
|
||||
if req.Msg.Item.Id == nil {
|
||||
return nil, connect.NewError(connect.CodeInvalidArgument, errors.New("id is required"))
|
||||
}
|
||||
|
||||
// Update item
|
||||
item, err := models.Items.Update(
|
||||
// Set col
|
||||
models.ItemSetter{
|
||||
Name: omit.From(req.Msg.Item.Name),
|
||||
Description: omit.From(req.Msg.Item.Description),
|
||||
Price: omit.From(req.Msg.Item.Price),
|
||||
Quantity: omit.From(int64(req.Msg.Item.Quantity)),
|
||||
}.UpdateMod(),
|
||||
err := h.db.UpdateItem(ctx, sqlc.UpdateItemParams{
|
||||
// set
|
||||
Name: req.Msg.Name,
|
||||
Description: req.Msg.Description,
|
||||
Price: util.NullFloat64(req.Msg.Price),
|
||||
Quantity: util.NullInt64(req.Msg.Quantity),
|
||||
|
||||
// Where
|
||||
sqlite.WhereAnd(
|
||||
models.UpdateWhere.Items.ID.EQ(*req.Msg.Item.Id),
|
||||
models.UpdateWhere.Items.UserID.EQ(userid),
|
||||
),
|
||||
).One(ctx, h.db)
|
||||
// where
|
||||
ID: req.Msg.Id,
|
||||
UserID: userid,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, connect.NewError(connect.CodeInternal, err)
|
||||
}
|
||||
|
||||
res := connect.NewResponse(&itemv1.UpdateItemResponse{
|
||||
Item: itemToConnect(item),
|
||||
})
|
||||
res := connect.NewResponse(&itemv1.UpdateItemResponse{})
|
||||
return res, nil
|
||||
}
|
||||
|
||||
@ -192,12 +178,10 @@ func (h *Handler) DeleteItem(ctx context.Context, req *connect.Request[itemv1.De
|
||||
}
|
||||
|
||||
// Delete item
|
||||
_, err := models.Items.Delete(
|
||||
sqlite.WhereAnd(
|
||||
models.DeleteWhere.Items.ID.EQ(req.Msg.Id),
|
||||
models.DeleteWhere.Items.UserID.EQ(userid),
|
||||
),
|
||||
).Exec(ctx, h.db)
|
||||
err := h.db.DeleteItem(ctx, sqlc.DeleteItemParams{
|
||||
ID: req.Msg.Id,
|
||||
UserID: userid,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, connect.NewError(connect.CodeInternal, err)
|
||||
}
|
||||
@ -206,7 +190,7 @@ func (h *Handler) DeleteItem(ctx context.Context, req *connect.Request[itemv1.De
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func NewHandler(db *bob.DB, key string) (string, http.Handler) {
|
||||
func NewHandler(db *sqlc.Queries, key string) (string, http.Handler) {
|
||||
interceptors := connect.WithInterceptors(interceptors.NewAuthInterceptor(key))
|
||||
|
||||
return itemv1connect.NewItemServiceHandler(
|
||||
|
@ -11,26 +11,22 @@ import (
|
||||
_ "crypto/sha256" // Crypto
|
||||
|
||||
"connectrpc.com/connect"
|
||||
"github.com/aarondl/opt/omit"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
userv1 "github.com/spotdemo4/trevstack/server/internal/connect/user/v1"
|
||||
"github.com/spotdemo4/trevstack/server/internal/connect/user/v1/userv1connect"
|
||||
"github.com/spotdemo4/trevstack/server/internal/interceptors"
|
||||
"github.com/spotdemo4/trevstack/server/internal/models"
|
||||
userv1 "github.com/spotdemo4/trevstack/server/internal/services/user/v1"
|
||||
"github.com/spotdemo4/trevstack/server/internal/services/user/v1/userv1connect"
|
||||
"github.com/stephenafamo/bob"
|
||||
"github.com/spotdemo4/trevstack/server/internal/sqlc"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
type AuthHandler struct {
|
||||
db *bob.DB
|
||||
db *sqlc.Queries
|
||||
key []byte
|
||||
}
|
||||
|
||||
func (h *AuthHandler) Login(ctx context.Context, req *connect.Request[userv1.LoginRequest]) (*connect.Response[userv1.LoginResponse], error) {
|
||||
// Get user
|
||||
user, err := models.Users.Query(
|
||||
models.SelectWhere.Users.Username.EQ(req.Msg.Username),
|
||||
).One(ctx, h.db)
|
||||
user, err := h.db.GetUserbyUsername(ctx, req.Msg.Username)
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, connect.NewError(connect.CodePermissionDenied, err)
|
||||
@ -47,7 +43,7 @@ func (h *AuthHandler) Login(ctx context.Context, req *connect.Request[userv1.Log
|
||||
// Generate JWT
|
||||
t := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.RegisteredClaims{
|
||||
Issuer: "trevstack",
|
||||
Subject: strconv.FormatUint(uint64(user.ID), 10),
|
||||
Subject: strconv.FormatInt(user.ID, 10),
|
||||
IssuedAt: &jwt.NumericDate{
|
||||
Time: time.Now(),
|
||||
},
|
||||
@ -80,16 +76,13 @@ func (h *AuthHandler) Login(ctx context.Context, req *connect.Request[userv1.Log
|
||||
|
||||
func (h *AuthHandler) SignUp(ctx context.Context, req *connect.Request[userv1.SignUpRequest]) (*connect.Response[userv1.SignUpResponse], error) {
|
||||
// Get user
|
||||
user, err := models.Users.Query(
|
||||
models.SelectWhere.Users.Username.EQ(req.Msg.Username),
|
||||
).One(ctx, h.db)
|
||||
_, err := h.db.GetUserbyUsername(ctx, req.Msg.Username)
|
||||
if err != nil {
|
||||
if !errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, connect.NewError(connect.CodeInternal, err)
|
||||
}
|
||||
}
|
||||
if user != nil {
|
||||
return nil, connect.NewError(connect.CodeAlreadyExists, errors.New("username already exists"))
|
||||
} else {
|
||||
return nil, connect.NewError(connect.CodeAlreadyExists, err)
|
||||
}
|
||||
|
||||
// Check if confirmation passwords match
|
||||
@ -104,10 +97,10 @@ func (h *AuthHandler) SignUp(ctx context.Context, req *connect.Request[userv1.Si
|
||||
}
|
||||
|
||||
// Create user
|
||||
_, err = models.Users.Insert(&models.UserSetter{
|
||||
Username: omit.From(req.Msg.Username),
|
||||
Password: omit.From(string(hash)),
|
||||
}).One(ctx, h.db)
|
||||
_, err = h.db.InsertUser(ctx, sqlc.InsertUserParams{
|
||||
Username: req.Msg.Username,
|
||||
Password: string(hash),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, connect.NewError(connect.CodeInternal, err)
|
||||
}
|
||||
@ -221,7 +214,7 @@ func (h *AuthHandler) Logout(_ context.Context, _ *connect.Request[userv1.Logout
|
||||
// return res, nil
|
||||
// }
|
||||
|
||||
func NewAuthHandler(db *bob.DB, key string) (string, http.Handler) {
|
||||
func NewAuthHandler(db *sqlc.Queries, key string) (string, http.Handler) {
|
||||
interceptors := connect.WithInterceptors(interceptors.NewRateLimitInterceptor(key))
|
||||
|
||||
return userv1connect.NewAuthServiceHandler(
|
||||
|
@ -9,27 +9,25 @@ import (
|
||||
"time"
|
||||
|
||||
"connectrpc.com/connect"
|
||||
"github.com/aarondl/opt/omit"
|
||||
"github.com/aarondl/opt/omitnull"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
userv1 "github.com/spotdemo4/trevstack/server/internal/connect/user/v1"
|
||||
"github.com/spotdemo4/trevstack/server/internal/connect/user/v1/userv1connect"
|
||||
"github.com/spotdemo4/trevstack/server/internal/interceptors"
|
||||
"github.com/spotdemo4/trevstack/server/internal/models"
|
||||
userv1 "github.com/spotdemo4/trevstack/server/internal/services/user/v1"
|
||||
"github.com/spotdemo4/trevstack/server/internal/services/user/v1/userv1connect"
|
||||
"github.com/stephenafamo/bob"
|
||||
"github.com/spotdemo4/trevstack/server/internal/sqlc"
|
||||
"github.com/spotdemo4/trevstack/server/internal/util"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
func userToConnect(item *models.User) *userv1.User {
|
||||
func userToConnect(item sqlc.User) *userv1.User {
|
||||
return &userv1.User{
|
||||
Id: item.ID,
|
||||
Username: item.Username,
|
||||
ProfilePictureId: item.ProfilePictureID.Ptr(),
|
||||
ProfilePictureId: item.ProfilePictureID,
|
||||
}
|
||||
}
|
||||
|
||||
type Handler struct {
|
||||
db *bob.DB
|
||||
db *sqlc.Queries
|
||||
key []byte
|
||||
}
|
||||
|
||||
@ -40,9 +38,7 @@ func (h *Handler) GetUser(ctx context.Context, _ *connect.Request[userv1.GetUser
|
||||
}
|
||||
|
||||
// Get user
|
||||
user, err := models.Users.Query(
|
||||
models.SelectWhere.Users.ID.EQ(userid),
|
||||
).One(ctx, h.db)
|
||||
user, err := h.db.GetUser(ctx, userid)
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, connect.NewError(connect.CodeNotFound, err)
|
||||
@ -64,9 +60,7 @@ func (h *Handler) UpdatePassword(ctx context.Context, req *connect.Request[userv
|
||||
}
|
||||
|
||||
// Get user
|
||||
user, err := models.Users.Query(
|
||||
models.SelectWhere.Users.ID.EQ(userid),
|
||||
).One(ctx, h.db)
|
||||
user, err := h.db.GetUser(ctx, userid)
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, connect.NewError(connect.CodeNotFound, err)
|
||||
@ -90,8 +84,9 @@ func (h *Handler) UpdatePassword(ctx context.Context, req *connect.Request[userv
|
||||
}
|
||||
|
||||
// Update password
|
||||
err = user.Update(ctx, h.db, &models.UserSetter{
|
||||
Password: omit.From(string(hash)),
|
||||
err = h.db.UpdateUser(ctx, sqlc.UpdateUserParams{
|
||||
Password: util.ToPointer(string(hash)),
|
||||
ID: userid,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, connect.NewError(connect.CodeInternal, err)
|
||||
@ -108,9 +103,7 @@ func (h *Handler) GetAPIKey(ctx context.Context, req *connect.Request[userv1.Get
|
||||
}
|
||||
|
||||
// Get user
|
||||
user, err := models.Users.Query(
|
||||
models.SelectWhere.Users.ID.EQ(userid),
|
||||
).One(ctx, h.db)
|
||||
user, err := h.db.GetUser(ctx, userid)
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, connect.NewError(connect.CodeNotFound, err)
|
||||
@ -159,19 +152,17 @@ func (h *Handler) UpdateProfilePicture(ctx context.Context, req *connect.Request
|
||||
}
|
||||
|
||||
// Save bytes into file
|
||||
file, err := models.Files.Insert(&models.FileSetter{
|
||||
Name: omit.From(req.Msg.FileName),
|
||||
Data: omit.From(req.Msg.Data),
|
||||
UserID: omit.From(userid),
|
||||
}).One(ctx, h.db)
|
||||
fileID, err := h.db.InsertFile(ctx, sqlc.InsertFileParams{
|
||||
Name: req.Msg.FileName,
|
||||
Data: req.Msg.Data,
|
||||
UserID: userid,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, connect.NewError(connect.CodeInternal, err)
|
||||
}
|
||||
|
||||
// Get user
|
||||
user, err := models.Users.Query(
|
||||
models.SelectWhere.Users.ID.EQ(userid),
|
||||
).One(ctx, h.db)
|
||||
user, err := h.db.GetUser(ctx, userid)
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, connect.NewError(connect.CodeNotFound, err)
|
||||
@ -180,25 +171,24 @@ func (h *Handler) UpdateProfilePicture(ctx context.Context, req *connect.Request
|
||||
return nil, connect.NewError(connect.CodeInternal, err)
|
||||
}
|
||||
|
||||
// Get old profile picture ID
|
||||
var ppid *int64
|
||||
if user.ProfilePictureID.Ptr() != nil {
|
||||
ppid = user.ProfilePictureID.Ptr()
|
||||
}
|
||||
|
||||
// Update user profile picture
|
||||
err = user.Update(ctx, h.db, &models.UserSetter{
|
||||
ProfilePictureID: omitnull.From(file.ID),
|
||||
err = h.db.UpdateUser(ctx, sqlc.UpdateUserParams{
|
||||
// set
|
||||
ProfilePictureID: &fileID,
|
||||
|
||||
// where
|
||||
ID: userid,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, connect.NewError(connect.CodeInternal, err)
|
||||
}
|
||||
|
||||
// Delete old profile picture if exists
|
||||
if ppid != nil {
|
||||
_, err = models.Files.Delete(
|
||||
models.DeleteWhere.Files.ID.EQ(*ppid),
|
||||
).Exec(ctx, h.db)
|
||||
if user.ProfilePictureID != nil {
|
||||
err = h.db.DeleteFile(ctx, sqlc.DeleteFileParams{
|
||||
ID: *user.ProfilePictureID,
|
||||
UserID: userid,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, connect.NewError(connect.CodeInternal, err)
|
||||
}
|
||||
@ -272,7 +262,7 @@ func (h *Handler) UpdateProfilePicture(ctx context.Context, req *connect.Request
|
||||
// return nil
|
||||
// }
|
||||
|
||||
func NewHandler(db *bob.DB, key string) (string, http.Handler) {
|
||||
func NewHandler(db *sqlc.Queries, key string) (string, http.Handler) {
|
||||
interceptors := connect.WithInterceptors(interceptors.NewAuthInterceptor(key))
|
||||
|
||||
return userv1connect.NewUserServiceHandler(
|
||||
|
@ -1,170 +0,0 @@
|
||||
// Code generated by BobGen sql (devel). DO NOT EDIT.
|
||||
// This file is meant to be re-generated in place and/or deleted at any time.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"hash/maphash"
|
||||
"strings"
|
||||
|
||||
"github.com/stephenafamo/bob"
|
||||
"github.com/stephenafamo/bob/clause"
|
||||
"github.com/stephenafamo/bob/dialect/sqlite"
|
||||
"github.com/stephenafamo/bob/dialect/sqlite/dialect"
|
||||
sqliteDriver "modernc.org/sqlite"
|
||||
)
|
||||
|
||||
var TableNames = struct {
|
||||
Files string
|
||||
Items string
|
||||
SchemaMigrations string
|
||||
Users string
|
||||
}{
|
||||
Files: "file",
|
||||
Items: "item",
|
||||
SchemaMigrations: "schema_migrations",
|
||||
Users: "user",
|
||||
}
|
||||
|
||||
var ColumnNames = struct {
|
||||
Files fileColumnNames
|
||||
Items itemColumnNames
|
||||
SchemaMigrations schemaMigrationColumnNames
|
||||
Users userColumnNames
|
||||
}{
|
||||
Files: fileColumnNames{
|
||||
ID: "id",
|
||||
Name: "name",
|
||||
Data: "data",
|
||||
UserID: "user_id",
|
||||
},
|
||||
Items: itemColumnNames{
|
||||
ID: "id",
|
||||
Name: "name",
|
||||
Added: "added",
|
||||
Description: "description",
|
||||
Price: "price",
|
||||
Quantity: "quantity",
|
||||
UserID: "user_id",
|
||||
},
|
||||
SchemaMigrations: schemaMigrationColumnNames{
|
||||
Version: "version",
|
||||
},
|
||||
Users: userColumnNames{
|
||||
ID: "id",
|
||||
Username: "username",
|
||||
Password: "password",
|
||||
ProfilePictureID: "profile_picture_id",
|
||||
},
|
||||
}
|
||||
|
||||
var (
|
||||
SelectWhere = Where[*dialect.SelectQuery]()
|
||||
InsertWhere = Where[*dialect.InsertQuery]()
|
||||
UpdateWhere = Where[*dialect.UpdateQuery]()
|
||||
DeleteWhere = Where[*dialect.DeleteQuery]()
|
||||
)
|
||||
|
||||
func Where[Q sqlite.Filterable]() struct {
|
||||
Files fileWhere[Q]
|
||||
Items itemWhere[Q]
|
||||
SchemaMigrations schemaMigrationWhere[Q]
|
||||
Users userWhere[Q]
|
||||
} {
|
||||
return struct {
|
||||
Files fileWhere[Q]
|
||||
Items itemWhere[Q]
|
||||
SchemaMigrations schemaMigrationWhere[Q]
|
||||
Users userWhere[Q]
|
||||
}{
|
||||
Files: buildFileWhere[Q](FileColumns),
|
||||
Items: buildItemWhere[Q](ItemColumns),
|
||||
SchemaMigrations: buildSchemaMigrationWhere[Q](SchemaMigrationColumns),
|
||||
Users: buildUserWhere[Q](UserColumns),
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
SelectJoins = getJoins[*dialect.SelectQuery]
|
||||
UpdateJoins = getJoins[*dialect.UpdateQuery]
|
||||
)
|
||||
|
||||
type joinSet[Q interface{ aliasedAs(string) Q }] struct {
|
||||
InnerJoin Q
|
||||
LeftJoin Q
|
||||
RightJoin Q
|
||||
}
|
||||
|
||||
func (j joinSet[Q]) AliasedAs(alias string) joinSet[Q] {
|
||||
return joinSet[Q]{
|
||||
InnerJoin: j.InnerJoin.aliasedAs(alias),
|
||||
LeftJoin: j.LeftJoin.aliasedAs(alias),
|
||||
RightJoin: j.RightJoin.aliasedAs(alias),
|
||||
}
|
||||
}
|
||||
|
||||
type joins[Q dialect.Joinable] struct {
|
||||
Files joinSet[fileJoins[Q]]
|
||||
Items joinSet[itemJoins[Q]]
|
||||
Users joinSet[userJoins[Q]]
|
||||
}
|
||||
|
||||
func buildJoinSet[Q interface{ aliasedAs(string) Q }, C any, F func(C, string) Q](c C, f F) joinSet[Q] {
|
||||
return joinSet[Q]{
|
||||
InnerJoin: f(c, clause.InnerJoin),
|
||||
LeftJoin: f(c, clause.LeftJoin),
|
||||
RightJoin: f(c, clause.RightJoin),
|
||||
}
|
||||
}
|
||||
|
||||
func getJoins[Q dialect.Joinable]() joins[Q] {
|
||||
return joins[Q]{
|
||||
Files: buildJoinSet[fileJoins[Q]](FileColumns, buildFileJoins),
|
||||
Items: buildJoinSet[itemJoins[Q]](ItemColumns, buildItemJoins),
|
||||
Users: buildJoinSet[userJoins[Q]](UserColumns, buildUserJoins),
|
||||
}
|
||||
}
|
||||
|
||||
type modAs[Q any, C interface{ AliasedAs(string) C }] struct {
|
||||
c C
|
||||
f func(C) bob.Mod[Q]
|
||||
}
|
||||
|
||||
func (m modAs[Q, C]) Apply(q Q) {
|
||||
m.f(m.c).Apply(q)
|
||||
}
|
||||
|
||||
func (m modAs[Q, C]) AliasedAs(alias string) bob.Mod[Q] {
|
||||
m.c = m.c.AliasedAs(alias)
|
||||
return m
|
||||
}
|
||||
|
||||
func randInt() int64 {
|
||||
out := int64(new(maphash.Hash).Sum64())
|
||||
|
||||
if out < 0 {
|
||||
return -out % 10000
|
||||
}
|
||||
|
||||
return out % 10000
|
||||
}
|
||||
|
||||
// ErrUniqueConstraint captures all unique constraint errors by explicitly leaving `s` empty.
|
||||
var ErrUniqueConstraint = &UniqueConstraintError{s: ""}
|
||||
|
||||
type UniqueConstraintError struct {
|
||||
// s is a string uniquely identifying the constraint in the raw error message returned from the database.
|
||||
s string
|
||||
}
|
||||
|
||||
func (e *UniqueConstraintError) Error() string {
|
||||
return e.s
|
||||
}
|
||||
|
||||
func (e *UniqueConstraintError) Is(target error) bool {
|
||||
err, ok := target.(*sqliteDriver.Error)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return err.Code() == 2067 && strings.Contains(err.Error(), e.s)
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
// Code generated by BobGen sql (devel). DO NOT EDIT.
|
||||
// This file is meant to be re-generated in place and/or deleted at any time.
|
||||
|
||||
package models
|
||||
|
||||
import "github.com/stephenafamo/bob"
|
||||
|
||||
// Make sure the type File runs hooks after queries
|
||||
var _ bob.HookableType = &File{}
|
||||
|
||||
// Make sure the type Item runs hooks after queries
|
||||
var _ bob.HookableType = &Item{}
|
||||
|
||||
// Make sure the type SchemaMigration runs hooks after queries
|
||||
var _ bob.HookableType = &SchemaMigration{}
|
||||
|
||||
// Make sure the type User runs hooks after queries
|
||||
var _ bob.HookableType = &User{}
|
@ -1,37 +0,0 @@
|
||||
// Code generated by BobGen sql (devel). DO NOT EDIT.
|
||||
// This file is meant to be re-generated in place and/or deleted at any time.
|
||||
|
||||
package factory
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
models "github.com/spotdemo4/trevstack/server/internal/models"
|
||||
)
|
||||
|
||||
type contextKey string
|
||||
|
||||
var (
|
||||
fileCtx = newContextual[*models.File]("file")
|
||||
itemCtx = newContextual[*models.Item]("item")
|
||||
schemaMigrationCtx = newContextual[*models.SchemaMigration]("schemaMigration")
|
||||
userCtx = newContextual[*models.User]("user")
|
||||
)
|
||||
|
||||
// Contextual is a convienience wrapper around context.WithValue and context.Value
|
||||
type contextual[V any] struct {
|
||||
key contextKey
|
||||
}
|
||||
|
||||
func newContextual[V any](key string) contextual[V] {
|
||||
return contextual[V]{key: contextKey(key)}
|
||||
}
|
||||
|
||||
func (k contextual[V]) WithValue(ctx context.Context, val V) context.Context {
|
||||
return context.WithValue(ctx, k.key, val)
|
||||
}
|
||||
|
||||
func (k contextual[V]) Value(ctx context.Context) (V, bool) {
|
||||
v, ok := ctx.Value(k.key).(V)
|
||||
return v, ok
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
// Code generated by BobGen sql (devel). DO NOT EDIT.
|
||||
// This file is meant to be re-generated in place and/or deleted at any time.
|
||||
|
||||
package factory
|
||||
|
||||
type Factory struct {
|
||||
baseFileMods FileModSlice
|
||||
baseItemMods ItemModSlice
|
||||
baseSchemaMigrationMods SchemaMigrationModSlice
|
||||
baseUserMods UserModSlice
|
||||
}
|
||||
|
||||
func New() *Factory {
|
||||
return &Factory{}
|
||||
}
|
||||
|
||||
func (f *Factory) NewFile(mods ...FileMod) *FileTemplate {
|
||||
o := &FileTemplate{f: f}
|
||||
|
||||
if f != nil {
|
||||
f.baseFileMods.Apply(o)
|
||||
}
|
||||
|
||||
FileModSlice(mods).Apply(o)
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (f *Factory) NewItem(mods ...ItemMod) *ItemTemplate {
|
||||
o := &ItemTemplate{f: f}
|
||||
|
||||
if f != nil {
|
||||
f.baseItemMods.Apply(o)
|
||||
}
|
||||
|
||||
ItemModSlice(mods).Apply(o)
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (f *Factory) NewSchemaMigration(mods ...SchemaMigrationMod) *SchemaMigrationTemplate {
|
||||
o := &SchemaMigrationTemplate{f: f}
|
||||
|
||||
if f != nil {
|
||||
f.baseSchemaMigrationMods.Apply(o)
|
||||
}
|
||||
|
||||
SchemaMigrationModSlice(mods).Apply(o)
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (f *Factory) NewUser(mods ...UserMod) *UserTemplate {
|
||||
o := &UserTemplate{f: f}
|
||||
|
||||
if f != nil {
|
||||
f.baseUserMods.Apply(o)
|
||||
}
|
||||
|
||||
UserModSlice(mods).Apply(o)
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (f *Factory) ClearBaseFileMods() {
|
||||
f.baseFileMods = nil
|
||||
}
|
||||
|
||||
func (f *Factory) AddBaseFileMod(mods ...FileMod) {
|
||||
f.baseFileMods = append(f.baseFileMods, mods...)
|
||||
}
|
||||
|
||||
func (f *Factory) ClearBaseItemMods() {
|
||||
f.baseItemMods = nil
|
||||
}
|
||||
|
||||
func (f *Factory) AddBaseItemMod(mods ...ItemMod) {
|
||||
f.baseItemMods = append(f.baseItemMods, mods...)
|
||||
}
|
||||
|
||||
func (f *Factory) ClearBaseSchemaMigrationMods() {
|
||||
f.baseSchemaMigrationMods = nil
|
||||
}
|
||||
|
||||
func (f *Factory) AddBaseSchemaMigrationMod(mods ...SchemaMigrationMod) {
|
||||
f.baseSchemaMigrationMods = append(f.baseSchemaMigrationMods, mods...)
|
||||
}
|
||||
|
||||
func (f *Factory) ClearBaseUserMods() {
|
||||
f.baseUserMods = nil
|
||||
}
|
||||
|
||||
func (f *Factory) AddBaseUserMod(mods ...UserMod) {
|
||||
f.baseUserMods = append(f.baseUserMods, mods...)
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
// Code generated by BobGen sql (devel). DO NOT EDIT.
|
||||
// This file is meant to be re-generated in place and/or deleted at any time.
|
||||
|
||||
package factory
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/jaswdr/faker/v2"
|
||||
)
|
||||
|
||||
var defaultFaker = faker.New()
|
||||
|
||||
func random___byte(f *faker.Faker) []byte {
|
||||
if f == nil {
|
||||
f = &defaultFaker
|
||||
}
|
||||
|
||||
return []byte(random_string(f))
|
||||
}
|
||||
|
||||
func random_float32(f *faker.Faker) float32 {
|
||||
if f == nil {
|
||||
f = &defaultFaker
|
||||
}
|
||||
|
||||
return f.Float32(10, -1_000_000, 1_000_000)
|
||||
}
|
||||
|
||||
func random_int64(f *faker.Faker) int64 {
|
||||
if f == nil {
|
||||
f = &defaultFaker
|
||||
}
|
||||
|
||||
return f.Int64()
|
||||
}
|
||||
|
||||
func random_string(f *faker.Faker) string {
|
||||
if f == nil {
|
||||
f = &defaultFaker
|
||||
}
|
||||
|
||||
return strings.Join(f.Lorem().Words(f.IntBetween(1, 5)), " ")
|
||||
}
|
||||
|
||||
func random_time_Time(f *faker.Faker) time.Time {
|
||||
if f == nil {
|
||||
f = &defaultFaker
|
||||
}
|
||||
|
||||
year := time.Hour * 24 * 365
|
||||
min := time.Now().Add(-year)
|
||||
max := time.Now().Add(year)
|
||||
return f.Time().TimeBetween(min, max)
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
// Code generated by BobGen sql (devel). DO NOT EDIT.
|
||||
// This file is meant to be re-generated in place and/or deleted at any time.
|
||||
|
||||
package factory
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRandom_int64(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
val1 := random_int64(nil)
|
||||
val2 := random_int64(nil)
|
||||
|
||||
if val1 == val2 {
|
||||
t.Fatalf("random_int64() returned the same value twice: %v", val1)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRandom_string(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
val1 := random_string(nil)
|
||||
val2 := random_string(nil)
|
||||
|
||||
if val1 == val2 {
|
||||
t.Fatalf("random_string() returned the same value twice: %v", val1)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRandom___byte(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
val1 := random___byte(nil)
|
||||
val2 := random___byte(nil)
|
||||
|
||||
if bytes.Equal(val1, val2) {
|
||||
t.Fatalf("random___byte() returned the same value twice: %v", val1)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRandom_time_Time(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
val1 := random_time_Time(nil)
|
||||
val2 := random_time_Time(nil)
|
||||
|
||||
if val1.Equal(val2) {
|
||||
t.Fatalf("random_time_Time() returned the same value twice: %v", val1)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRandom_float32(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
val1 := random_float32(nil)
|
||||
val2 := random_float32(nil)
|
||||
|
||||
if val1 == val2 {
|
||||
t.Fatalf("random_float32() returned the same value twice: %v", val1)
|
||||
}
|
||||
}
|
@ -1,527 +0,0 @@
|
||||
// Code generated by BobGen sql (devel). DO NOT EDIT.
|
||||
// This file is meant to be re-generated in place and/or deleted at any time.
|
||||
|
||||
package factory
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/aarondl/opt/null"
|
||||
"github.com/aarondl/opt/omit"
|
||||
"github.com/jaswdr/faker/v2"
|
||||
models "github.com/spotdemo4/trevstack/server/internal/models"
|
||||
"github.com/stephenafamo/bob"
|
||||
)
|
||||
|
||||
type FileMod interface {
|
||||
Apply(*FileTemplate)
|
||||
}
|
||||
|
||||
type FileModFunc func(*FileTemplate)
|
||||
|
||||
func (f FileModFunc) Apply(n *FileTemplate) {
|
||||
f(n)
|
||||
}
|
||||
|
||||
type FileModSlice []FileMod
|
||||
|
||||
func (mods FileModSlice) Apply(n *FileTemplate) {
|
||||
for _, f := range mods {
|
||||
f.Apply(n)
|
||||
}
|
||||
}
|
||||
|
||||
// FileTemplate is an object representing the database table.
|
||||
// all columns are optional and should be set by mods
|
||||
type FileTemplate struct {
|
||||
ID func() int64
|
||||
Name func() string
|
||||
Data func() []byte
|
||||
UserID func() int64
|
||||
|
||||
r fileR
|
||||
f *Factory
|
||||
}
|
||||
|
||||
type fileR struct {
|
||||
User *fileRUserR
|
||||
ProfilePictureUsers []*fileRProfilePictureUsersR
|
||||
}
|
||||
|
||||
type fileRUserR struct {
|
||||
o *UserTemplate
|
||||
}
|
||||
type fileRProfilePictureUsersR struct {
|
||||
number int
|
||||
o *UserTemplate
|
||||
}
|
||||
|
||||
// Apply mods to the FileTemplate
|
||||
func (o *FileTemplate) Apply(mods ...FileMod) {
|
||||
for _, mod := range mods {
|
||||
mod.Apply(o)
|
||||
}
|
||||
}
|
||||
|
||||
// toModel returns an *models.File
|
||||
// this does nothing with the relationship templates
|
||||
func (o FileTemplate) toModel() *models.File {
|
||||
m := &models.File{}
|
||||
|
||||
if o.ID != nil {
|
||||
m.ID = o.ID()
|
||||
}
|
||||
if o.Name != nil {
|
||||
m.Name = o.Name()
|
||||
}
|
||||
if o.Data != nil {
|
||||
m.Data = o.Data()
|
||||
}
|
||||
if o.UserID != nil {
|
||||
m.UserID = o.UserID()
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// toModels returns an models.FileSlice
|
||||
// this does nothing with the relationship templates
|
||||
func (o FileTemplate) toModels(number int) models.FileSlice {
|
||||
m := make(models.FileSlice, number)
|
||||
|
||||
for i := range m {
|
||||
m[i] = o.toModel()
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// setModelRels creates and sets the relationships on *models.File
|
||||
// according to the relationships in the template. Nothing is inserted into the db
|
||||
func (t FileTemplate) setModelRels(o *models.File) {
|
||||
if t.r.User != nil {
|
||||
rel := t.r.User.o.toModel()
|
||||
rel.R.Files = append(rel.R.Files, o)
|
||||
o.UserID = rel.ID
|
||||
o.R.User = rel
|
||||
}
|
||||
|
||||
if t.r.ProfilePictureUsers != nil {
|
||||
rel := models.UserSlice{}
|
||||
for _, r := range t.r.ProfilePictureUsers {
|
||||
related := r.o.toModels(r.number)
|
||||
for _, rel := range related {
|
||||
rel.ProfilePictureID = null.From(o.ID)
|
||||
rel.R.ProfilePictureFile = o
|
||||
}
|
||||
rel = append(rel, related...)
|
||||
}
|
||||
o.R.ProfilePictureUsers = rel
|
||||
}
|
||||
}
|
||||
|
||||
// BuildSetter returns an *models.FileSetter
|
||||
// this does nothing with the relationship templates
|
||||
func (o FileTemplate) BuildSetter() *models.FileSetter {
|
||||
m := &models.FileSetter{}
|
||||
|
||||
if o.ID != nil {
|
||||
m.ID = omit.From(o.ID())
|
||||
}
|
||||
if o.Name != nil {
|
||||
m.Name = omit.From(o.Name())
|
||||
}
|
||||
if o.Data != nil {
|
||||
m.Data = omit.From(o.Data())
|
||||
}
|
||||
if o.UserID != nil {
|
||||
m.UserID = omit.From(o.UserID())
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// BuildManySetter returns an []*models.FileSetter
|
||||
// this does nothing with the relationship templates
|
||||
func (o FileTemplate) BuildManySetter(number int) []*models.FileSetter {
|
||||
m := make([]*models.FileSetter, number)
|
||||
|
||||
for i := range m {
|
||||
m[i] = o.BuildSetter()
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// Build returns an *models.File
|
||||
// Related objects are also created and placed in the .R field
|
||||
// NOTE: Objects are not inserted into the database. Use FileTemplate.Create
|
||||
func (o FileTemplate) Build() *models.File {
|
||||
m := o.toModel()
|
||||
o.setModelRels(m)
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// BuildMany returns an models.FileSlice
|
||||
// Related objects are also created and placed in the .R field
|
||||
// NOTE: Objects are not inserted into the database. Use FileTemplate.CreateMany
|
||||
func (o FileTemplate) BuildMany(number int) models.FileSlice {
|
||||
m := make(models.FileSlice, number)
|
||||
|
||||
for i := range m {
|
||||
m[i] = o.Build()
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func ensureCreatableFile(m *models.FileSetter) {
|
||||
if m.Name.IsUnset() {
|
||||
m.Name = omit.From(random_string(nil))
|
||||
}
|
||||
if m.Data.IsUnset() {
|
||||
m.Data = omit.From(random___byte(nil))
|
||||
}
|
||||
if m.UserID.IsUnset() {
|
||||
m.UserID = omit.From(random_int64(nil))
|
||||
}
|
||||
}
|
||||
|
||||
// insertOptRels creates and inserts any optional the relationships on *models.File
|
||||
// according to the relationships in the template.
|
||||
// any required relationship should have already exist on the model
|
||||
func (o *FileTemplate) insertOptRels(ctx context.Context, exec bob.Executor, m *models.File) (context.Context, error) {
|
||||
var err error
|
||||
|
||||
if o.r.ProfilePictureUsers != nil {
|
||||
for _, r := range o.r.ProfilePictureUsers {
|
||||
var rel1 models.UserSlice
|
||||
ctx, rel1, err = r.o.createMany(ctx, exec, r.number)
|
||||
if err != nil {
|
||||
return ctx, err
|
||||
}
|
||||
|
||||
err = m.AttachProfilePictureUsers(ctx, exec, rel1...)
|
||||
if err != nil {
|
||||
return ctx, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ctx, err
|
||||
}
|
||||
|
||||
// Create builds a file and inserts it into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
func (o *FileTemplate) Create(ctx context.Context, exec bob.Executor) (*models.File, error) {
|
||||
_, m, err := o.create(ctx, exec)
|
||||
return m, err
|
||||
}
|
||||
|
||||
// MustCreate builds a file and inserts it into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
// panics if an error occurs
|
||||
func (o *FileTemplate) MustCreate(ctx context.Context, exec bob.Executor) *models.File {
|
||||
_, m, err := o.create(ctx, exec)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// CreateOrFail builds a file and inserts it into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
// It calls `tb.Fatal(err)` on the test/benchmark if an error occurs
|
||||
func (o *FileTemplate) CreateOrFail(ctx context.Context, tb testing.TB, exec bob.Executor) *models.File {
|
||||
tb.Helper()
|
||||
_, m, err := o.create(ctx, exec)
|
||||
if err != nil {
|
||||
tb.Fatal(err)
|
||||
return nil
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// create builds a file and inserts it into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
// this returns a context that includes the newly inserted model
|
||||
func (o *FileTemplate) create(ctx context.Context, exec bob.Executor) (context.Context, *models.File, error) {
|
||||
var err error
|
||||
opt := o.BuildSetter()
|
||||
ensureCreatableFile(opt)
|
||||
|
||||
var rel0 *models.User
|
||||
if o.r.User == nil {
|
||||
var ok bool
|
||||
rel0, ok = userCtx.Value(ctx)
|
||||
if !ok {
|
||||
FileMods.WithNewUser().Apply(o)
|
||||
}
|
||||
}
|
||||
if o.r.User != nil {
|
||||
ctx, rel0, err = o.r.User.o.create(ctx, exec)
|
||||
if err != nil {
|
||||
return ctx, nil, err
|
||||
}
|
||||
}
|
||||
opt.UserID = omit.From(rel0.ID)
|
||||
|
||||
m, err := models.Files.Insert(opt).One(ctx, exec)
|
||||
if err != nil {
|
||||
return ctx, nil, err
|
||||
}
|
||||
ctx = fileCtx.WithValue(ctx, m)
|
||||
|
||||
m.R.User = rel0
|
||||
|
||||
ctx, err = o.insertOptRels(ctx, exec, m)
|
||||
return ctx, m, err
|
||||
}
|
||||
|
||||
// CreateMany builds multiple files and inserts them into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
func (o FileTemplate) CreateMany(ctx context.Context, exec bob.Executor, number int) (models.FileSlice, error) {
|
||||
_, m, err := o.createMany(ctx, exec, number)
|
||||
return m, err
|
||||
}
|
||||
|
||||
// MustCreateMany builds multiple files and inserts them into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
// panics if an error occurs
|
||||
func (o FileTemplate) MustCreateMany(ctx context.Context, exec bob.Executor, number int) models.FileSlice {
|
||||
_, m, err := o.createMany(ctx, exec, number)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// CreateManyOrFail builds multiple files and inserts them into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
// It calls `tb.Fatal(err)` on the test/benchmark if an error occurs
|
||||
func (o FileTemplate) CreateManyOrFail(ctx context.Context, tb testing.TB, exec bob.Executor, number int) models.FileSlice {
|
||||
tb.Helper()
|
||||
_, m, err := o.createMany(ctx, exec, number)
|
||||
if err != nil {
|
||||
tb.Fatal(err)
|
||||
return nil
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// createMany builds multiple files and inserts them into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
// this returns a context that includes the newly inserted models
|
||||
func (o FileTemplate) createMany(ctx context.Context, exec bob.Executor, number int) (context.Context, models.FileSlice, error) {
|
||||
var err error
|
||||
m := make(models.FileSlice, number)
|
||||
|
||||
for i := range m {
|
||||
ctx, m[i], err = o.create(ctx, exec)
|
||||
if err != nil {
|
||||
return ctx, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return ctx, m, nil
|
||||
}
|
||||
|
||||
// File has methods that act as mods for the FileTemplate
|
||||
var FileMods fileMods
|
||||
|
||||
type fileMods struct{}
|
||||
|
||||
func (m fileMods) RandomizeAllColumns(f *faker.Faker) FileMod {
|
||||
return FileModSlice{
|
||||
FileMods.RandomID(f),
|
||||
FileMods.RandomName(f),
|
||||
FileMods.RandomData(f),
|
||||
FileMods.RandomUserID(f),
|
||||
}
|
||||
}
|
||||
|
||||
// Set the model columns to this value
|
||||
func (m fileMods) ID(val int64) FileMod {
|
||||
return FileModFunc(func(o *FileTemplate) {
|
||||
o.ID = func() int64 { return val }
|
||||
})
|
||||
}
|
||||
|
||||
// Set the Column from the function
|
||||
func (m fileMods) IDFunc(f func() int64) FileMod {
|
||||
return FileModFunc(func(o *FileTemplate) {
|
||||
o.ID = f
|
||||
})
|
||||
}
|
||||
|
||||
// Clear any values for the column
|
||||
func (m fileMods) UnsetID() FileMod {
|
||||
return FileModFunc(func(o *FileTemplate) {
|
||||
o.ID = nil
|
||||
})
|
||||
}
|
||||
|
||||
// Generates a random value for the column using the given faker
|
||||
// if faker is nil, a default faker is used
|
||||
func (m fileMods) RandomID(f *faker.Faker) FileMod {
|
||||
return FileModFunc(func(o *FileTemplate) {
|
||||
o.ID = func() int64 {
|
||||
return random_int64(f)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Set the model columns to this value
|
||||
func (m fileMods) Name(val string) FileMod {
|
||||
return FileModFunc(func(o *FileTemplate) {
|
||||
o.Name = func() string { return val }
|
||||
})
|
||||
}
|
||||
|
||||
// Set the Column from the function
|
||||
func (m fileMods) NameFunc(f func() string) FileMod {
|
||||
return FileModFunc(func(o *FileTemplate) {
|
||||
o.Name = f
|
||||
})
|
||||
}
|
||||
|
||||
// Clear any values for the column
|
||||
func (m fileMods) UnsetName() FileMod {
|
||||
return FileModFunc(func(o *FileTemplate) {
|
||||
o.Name = nil
|
||||
})
|
||||
}
|
||||
|
||||
// Generates a random value for the column using the given faker
|
||||
// if faker is nil, a default faker is used
|
||||
func (m fileMods) RandomName(f *faker.Faker) FileMod {
|
||||
return FileModFunc(func(o *FileTemplate) {
|
||||
o.Name = func() string {
|
||||
return random_string(f)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Set the model columns to this value
|
||||
func (m fileMods) Data(val []byte) FileMod {
|
||||
return FileModFunc(func(o *FileTemplate) {
|
||||
o.Data = func() []byte { return val }
|
||||
})
|
||||
}
|
||||
|
||||
// Set the Column from the function
|
||||
func (m fileMods) DataFunc(f func() []byte) FileMod {
|
||||
return FileModFunc(func(o *FileTemplate) {
|
||||
o.Data = f
|
||||
})
|
||||
}
|
||||
|
||||
// Clear any values for the column
|
||||
func (m fileMods) UnsetData() FileMod {
|
||||
return FileModFunc(func(o *FileTemplate) {
|
||||
o.Data = nil
|
||||
})
|
||||
}
|
||||
|
||||
// Generates a random value for the column using the given faker
|
||||
// if faker is nil, a default faker is used
|
||||
func (m fileMods) RandomData(f *faker.Faker) FileMod {
|
||||
return FileModFunc(func(o *FileTemplate) {
|
||||
o.Data = func() []byte {
|
||||
return random___byte(f)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Set the model columns to this value
|
||||
func (m fileMods) UserID(val int64) FileMod {
|
||||
return FileModFunc(func(o *FileTemplate) {
|
||||
o.UserID = func() int64 { return val }
|
||||
})
|
||||
}
|
||||
|
||||
// Set the Column from the function
|
||||
func (m fileMods) UserIDFunc(f func() int64) FileMod {
|
||||
return FileModFunc(func(o *FileTemplate) {
|
||||
o.UserID = f
|
||||
})
|
||||
}
|
||||
|
||||
// Clear any values for the column
|
||||
func (m fileMods) UnsetUserID() FileMod {
|
||||
return FileModFunc(func(o *FileTemplate) {
|
||||
o.UserID = nil
|
||||
})
|
||||
}
|
||||
|
||||
// Generates a random value for the column using the given faker
|
||||
// if faker is nil, a default faker is used
|
||||
func (m fileMods) RandomUserID(f *faker.Faker) FileMod {
|
||||
return FileModFunc(func(o *FileTemplate) {
|
||||
o.UserID = func() int64 {
|
||||
return random_int64(f)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (m fileMods) WithUser(rel *UserTemplate) FileMod {
|
||||
return FileModFunc(func(o *FileTemplate) {
|
||||
o.r.User = &fileRUserR{
|
||||
o: rel,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (m fileMods) WithNewUser(mods ...UserMod) FileMod {
|
||||
return FileModFunc(func(o *FileTemplate) {
|
||||
related := o.f.NewUser(mods...)
|
||||
|
||||
m.WithUser(related).Apply(o)
|
||||
})
|
||||
}
|
||||
|
||||
func (m fileMods) WithoutUser() FileMod {
|
||||
return FileModFunc(func(o *FileTemplate) {
|
||||
o.r.User = nil
|
||||
})
|
||||
}
|
||||
|
||||
func (m fileMods) WithProfilePictureUsers(number int, related *UserTemplate) FileMod {
|
||||
return FileModFunc(func(o *FileTemplate) {
|
||||
o.r.ProfilePictureUsers = []*fileRProfilePictureUsersR{{
|
||||
number: number,
|
||||
o: related,
|
||||
}}
|
||||
})
|
||||
}
|
||||
|
||||
func (m fileMods) WithNewProfilePictureUsers(number int, mods ...UserMod) FileMod {
|
||||
return FileModFunc(func(o *FileTemplate) {
|
||||
related := o.f.NewUser(mods...)
|
||||
m.WithProfilePictureUsers(number, related).Apply(o)
|
||||
})
|
||||
}
|
||||
|
||||
func (m fileMods) AddProfilePictureUsers(number int, related *UserTemplate) FileMod {
|
||||
return FileModFunc(func(o *FileTemplate) {
|
||||
o.r.ProfilePictureUsers = append(o.r.ProfilePictureUsers, &fileRProfilePictureUsersR{
|
||||
number: number,
|
||||
o: related,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func (m fileMods) AddNewProfilePictureUsers(number int, mods ...UserMod) FileMod {
|
||||
return FileModFunc(func(o *FileTemplate) {
|
||||
related := o.f.NewUser(mods...)
|
||||
m.AddProfilePictureUsers(number, related).Apply(o)
|
||||
})
|
||||
}
|
||||
|
||||
func (m fileMods) WithoutProfilePictureUsers() FileMod {
|
||||
return FileModFunc(func(o *FileTemplate) {
|
||||
o.r.ProfilePictureUsers = nil
|
||||
})
|
||||
}
|
@ -1,582 +0,0 @@
|
||||
// Code generated by BobGen sql (devel). DO NOT EDIT.
|
||||
// This file is meant to be re-generated in place and/or deleted at any time.
|
||||
|
||||
package factory
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/aarondl/opt/omit"
|
||||
"github.com/jaswdr/faker/v2"
|
||||
models "github.com/spotdemo4/trevstack/server/internal/models"
|
||||
"github.com/stephenafamo/bob"
|
||||
)
|
||||
|
||||
type ItemMod interface {
|
||||
Apply(*ItemTemplate)
|
||||
}
|
||||
|
||||
type ItemModFunc func(*ItemTemplate)
|
||||
|
||||
func (f ItemModFunc) Apply(n *ItemTemplate) {
|
||||
f(n)
|
||||
}
|
||||
|
||||
type ItemModSlice []ItemMod
|
||||
|
||||
func (mods ItemModSlice) Apply(n *ItemTemplate) {
|
||||
for _, f := range mods {
|
||||
f.Apply(n)
|
||||
}
|
||||
}
|
||||
|
||||
// ItemTemplate is an object representing the database table.
|
||||
// all columns are optional and should be set by mods
|
||||
type ItemTemplate struct {
|
||||
ID func() int64
|
||||
Name func() string
|
||||
Added func() time.Time
|
||||
Description func() string
|
||||
Price func() float32
|
||||
Quantity func() int64
|
||||
UserID func() int64
|
||||
|
||||
r itemR
|
||||
f *Factory
|
||||
}
|
||||
|
||||
type itemR struct {
|
||||
User *itemRUserR
|
||||
}
|
||||
|
||||
type itemRUserR struct {
|
||||
o *UserTemplate
|
||||
}
|
||||
|
||||
// Apply mods to the ItemTemplate
|
||||
func (o *ItemTemplate) Apply(mods ...ItemMod) {
|
||||
for _, mod := range mods {
|
||||
mod.Apply(o)
|
||||
}
|
||||
}
|
||||
|
||||
// toModel returns an *models.Item
|
||||
// this does nothing with the relationship templates
|
||||
func (o ItemTemplate) toModel() *models.Item {
|
||||
m := &models.Item{}
|
||||
|
||||
if o.ID != nil {
|
||||
m.ID = o.ID()
|
||||
}
|
||||
if o.Name != nil {
|
||||
m.Name = o.Name()
|
||||
}
|
||||
if o.Added != nil {
|
||||
m.Added = o.Added()
|
||||
}
|
||||
if o.Description != nil {
|
||||
m.Description = o.Description()
|
||||
}
|
||||
if o.Price != nil {
|
||||
m.Price = o.Price()
|
||||
}
|
||||
if o.Quantity != nil {
|
||||
m.Quantity = o.Quantity()
|
||||
}
|
||||
if o.UserID != nil {
|
||||
m.UserID = o.UserID()
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// toModels returns an models.ItemSlice
|
||||
// this does nothing with the relationship templates
|
||||
func (o ItemTemplate) toModels(number int) models.ItemSlice {
|
||||
m := make(models.ItemSlice, number)
|
||||
|
||||
for i := range m {
|
||||
m[i] = o.toModel()
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// setModelRels creates and sets the relationships on *models.Item
|
||||
// according to the relationships in the template. Nothing is inserted into the db
|
||||
func (t ItemTemplate) setModelRels(o *models.Item) {
|
||||
if t.r.User != nil {
|
||||
rel := t.r.User.o.toModel()
|
||||
rel.R.Items = append(rel.R.Items, o)
|
||||
o.UserID = rel.ID
|
||||
o.R.User = rel
|
||||
}
|
||||
}
|
||||
|
||||
// BuildSetter returns an *models.ItemSetter
|
||||
// this does nothing with the relationship templates
|
||||
func (o ItemTemplate) BuildSetter() *models.ItemSetter {
|
||||
m := &models.ItemSetter{}
|
||||
|
||||
if o.ID != nil {
|
||||
m.ID = omit.From(o.ID())
|
||||
}
|
||||
if o.Name != nil {
|
||||
m.Name = omit.From(o.Name())
|
||||
}
|
||||
if o.Added != nil {
|
||||
m.Added = omit.From(o.Added())
|
||||
}
|
||||
if o.Description != nil {
|
||||
m.Description = omit.From(o.Description())
|
||||
}
|
||||
if o.Price != nil {
|
||||
m.Price = omit.From(o.Price())
|
||||
}
|
||||
if o.Quantity != nil {
|
||||
m.Quantity = omit.From(o.Quantity())
|
||||
}
|
||||
if o.UserID != nil {
|
||||
m.UserID = omit.From(o.UserID())
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// BuildManySetter returns an []*models.ItemSetter
|
||||
// this does nothing with the relationship templates
|
||||
func (o ItemTemplate) BuildManySetter(number int) []*models.ItemSetter {
|
||||
m := make([]*models.ItemSetter, number)
|
||||
|
||||
for i := range m {
|
||||
m[i] = o.BuildSetter()
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// Build returns an *models.Item
|
||||
// Related objects are also created and placed in the .R field
|
||||
// NOTE: Objects are not inserted into the database. Use ItemTemplate.Create
|
||||
func (o ItemTemplate) Build() *models.Item {
|
||||
m := o.toModel()
|
||||
o.setModelRels(m)
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// BuildMany returns an models.ItemSlice
|
||||
// Related objects are also created and placed in the .R field
|
||||
// NOTE: Objects are not inserted into the database. Use ItemTemplate.CreateMany
|
||||
func (o ItemTemplate) BuildMany(number int) models.ItemSlice {
|
||||
m := make(models.ItemSlice, number)
|
||||
|
||||
for i := range m {
|
||||
m[i] = o.Build()
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func ensureCreatableItem(m *models.ItemSetter) {
|
||||
if m.Name.IsUnset() {
|
||||
m.Name = omit.From(random_string(nil))
|
||||
}
|
||||
if m.Added.IsUnset() {
|
||||
m.Added = omit.From(random_time_Time(nil))
|
||||
}
|
||||
if m.Description.IsUnset() {
|
||||
m.Description = omit.From(random_string(nil))
|
||||
}
|
||||
if m.Price.IsUnset() {
|
||||
m.Price = omit.From(random_float32(nil))
|
||||
}
|
||||
if m.Quantity.IsUnset() {
|
||||
m.Quantity = omit.From(random_int64(nil))
|
||||
}
|
||||
if m.UserID.IsUnset() {
|
||||
m.UserID = omit.From(random_int64(nil))
|
||||
}
|
||||
}
|
||||
|
||||
// insertOptRels creates and inserts any optional the relationships on *models.Item
|
||||
// according to the relationships in the template.
|
||||
// any required relationship should have already exist on the model
|
||||
func (o *ItemTemplate) insertOptRels(ctx context.Context, exec bob.Executor, m *models.Item) (context.Context, error) {
|
||||
var err error
|
||||
|
||||
return ctx, err
|
||||
}
|
||||
|
||||
// Create builds a item and inserts it into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
func (o *ItemTemplate) Create(ctx context.Context, exec bob.Executor) (*models.Item, error) {
|
||||
_, m, err := o.create(ctx, exec)
|
||||
return m, err
|
||||
}
|
||||
|
||||
// MustCreate builds a item and inserts it into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
// panics if an error occurs
|
||||
func (o *ItemTemplate) MustCreate(ctx context.Context, exec bob.Executor) *models.Item {
|
||||
_, m, err := o.create(ctx, exec)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// CreateOrFail builds a item and inserts it into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
// It calls `tb.Fatal(err)` on the test/benchmark if an error occurs
|
||||
func (o *ItemTemplate) CreateOrFail(ctx context.Context, tb testing.TB, exec bob.Executor) *models.Item {
|
||||
tb.Helper()
|
||||
_, m, err := o.create(ctx, exec)
|
||||
if err != nil {
|
||||
tb.Fatal(err)
|
||||
return nil
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// create builds a item and inserts it into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
// this returns a context that includes the newly inserted model
|
||||
func (o *ItemTemplate) create(ctx context.Context, exec bob.Executor) (context.Context, *models.Item, error) {
|
||||
var err error
|
||||
opt := o.BuildSetter()
|
||||
ensureCreatableItem(opt)
|
||||
|
||||
var rel0 *models.User
|
||||
if o.r.User == nil {
|
||||
var ok bool
|
||||
rel0, ok = userCtx.Value(ctx)
|
||||
if !ok {
|
||||
ItemMods.WithNewUser().Apply(o)
|
||||
}
|
||||
}
|
||||
if o.r.User != nil {
|
||||
ctx, rel0, err = o.r.User.o.create(ctx, exec)
|
||||
if err != nil {
|
||||
return ctx, nil, err
|
||||
}
|
||||
}
|
||||
opt.UserID = omit.From(rel0.ID)
|
||||
|
||||
m, err := models.Items.Insert(opt).One(ctx, exec)
|
||||
if err != nil {
|
||||
return ctx, nil, err
|
||||
}
|
||||
ctx = itemCtx.WithValue(ctx, m)
|
||||
|
||||
m.R.User = rel0
|
||||
|
||||
ctx, err = o.insertOptRels(ctx, exec, m)
|
||||
return ctx, m, err
|
||||
}
|
||||
|
||||
// CreateMany builds multiple items and inserts them into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
func (o ItemTemplate) CreateMany(ctx context.Context, exec bob.Executor, number int) (models.ItemSlice, error) {
|
||||
_, m, err := o.createMany(ctx, exec, number)
|
||||
return m, err
|
||||
}
|
||||
|
||||
// MustCreateMany builds multiple items and inserts them into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
// panics if an error occurs
|
||||
func (o ItemTemplate) MustCreateMany(ctx context.Context, exec bob.Executor, number int) models.ItemSlice {
|
||||
_, m, err := o.createMany(ctx, exec, number)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// CreateManyOrFail builds multiple items and inserts them into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
// It calls `tb.Fatal(err)` on the test/benchmark if an error occurs
|
||||
func (o ItemTemplate) CreateManyOrFail(ctx context.Context, tb testing.TB, exec bob.Executor, number int) models.ItemSlice {
|
||||
tb.Helper()
|
||||
_, m, err := o.createMany(ctx, exec, number)
|
||||
if err != nil {
|
||||
tb.Fatal(err)
|
||||
return nil
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// createMany builds multiple items and inserts them into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
// this returns a context that includes the newly inserted models
|
||||
func (o ItemTemplate) createMany(ctx context.Context, exec bob.Executor, number int) (context.Context, models.ItemSlice, error) {
|
||||
var err error
|
||||
m := make(models.ItemSlice, number)
|
||||
|
||||
for i := range m {
|
||||
ctx, m[i], err = o.create(ctx, exec)
|
||||
if err != nil {
|
||||
return ctx, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return ctx, m, nil
|
||||
}
|
||||
|
||||
// Item has methods that act as mods for the ItemTemplate
|
||||
var ItemMods itemMods
|
||||
|
||||
type itemMods struct{}
|
||||
|
||||
func (m itemMods) RandomizeAllColumns(f *faker.Faker) ItemMod {
|
||||
return ItemModSlice{
|
||||
ItemMods.RandomID(f),
|
||||
ItemMods.RandomName(f),
|
||||
ItemMods.RandomAdded(f),
|
||||
ItemMods.RandomDescription(f),
|
||||
ItemMods.RandomPrice(f),
|
||||
ItemMods.RandomQuantity(f),
|
||||
ItemMods.RandomUserID(f),
|
||||
}
|
||||
}
|
||||
|
||||
// Set the model columns to this value
|
||||
func (m itemMods) ID(val int64) ItemMod {
|
||||
return ItemModFunc(func(o *ItemTemplate) {
|
||||
o.ID = func() int64 { return val }
|
||||
})
|
||||
}
|
||||
|
||||
// Set the Column from the function
|
||||
func (m itemMods) IDFunc(f func() int64) ItemMod {
|
||||
return ItemModFunc(func(o *ItemTemplate) {
|
||||
o.ID = f
|
||||
})
|
||||
}
|
||||
|
||||
// Clear any values for the column
|
||||
func (m itemMods) UnsetID() ItemMod {
|
||||
return ItemModFunc(func(o *ItemTemplate) {
|
||||
o.ID = nil
|
||||
})
|
||||
}
|
||||
|
||||
// Generates a random value for the column using the given faker
|
||||
// if faker is nil, a default faker is used
|
||||
func (m itemMods) RandomID(f *faker.Faker) ItemMod {
|
||||
return ItemModFunc(func(o *ItemTemplate) {
|
||||
o.ID = func() int64 {
|
||||
return random_int64(f)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Set the model columns to this value
|
||||
func (m itemMods) Name(val string) ItemMod {
|
||||
return ItemModFunc(func(o *ItemTemplate) {
|
||||
o.Name = func() string { return val }
|
||||
})
|
||||
}
|
||||
|
||||
// Set the Column from the function
|
||||
func (m itemMods) NameFunc(f func() string) ItemMod {
|
||||
return ItemModFunc(func(o *ItemTemplate) {
|
||||
o.Name = f
|
||||
})
|
||||
}
|
||||
|
||||
// Clear any values for the column
|
||||
func (m itemMods) UnsetName() ItemMod {
|
||||
return ItemModFunc(func(o *ItemTemplate) {
|
||||
o.Name = nil
|
||||
})
|
||||
}
|
||||
|
||||
// Generates a random value for the column using the given faker
|
||||
// if faker is nil, a default faker is used
|
||||
func (m itemMods) RandomName(f *faker.Faker) ItemMod {
|
||||
return ItemModFunc(func(o *ItemTemplate) {
|
||||
o.Name = func() string {
|
||||
return random_string(f)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Set the model columns to this value
|
||||
func (m itemMods) Added(val time.Time) ItemMod {
|
||||
return ItemModFunc(func(o *ItemTemplate) {
|
||||
o.Added = func() time.Time { return val }
|
||||
})
|
||||
}
|
||||
|
||||
// Set the Column from the function
|
||||
func (m itemMods) AddedFunc(f func() time.Time) ItemMod {
|
||||
return ItemModFunc(func(o *ItemTemplate) {
|
||||
o.Added = f
|
||||
})
|
||||
}
|
||||
|
||||
// Clear any values for the column
|
||||
func (m itemMods) UnsetAdded() ItemMod {
|
||||
return ItemModFunc(func(o *ItemTemplate) {
|
||||
o.Added = nil
|
||||
})
|
||||
}
|
||||
|
||||
// Generates a random value for the column using the given faker
|
||||
// if faker is nil, a default faker is used
|
||||
func (m itemMods) RandomAdded(f *faker.Faker) ItemMod {
|
||||
return ItemModFunc(func(o *ItemTemplate) {
|
||||
o.Added = func() time.Time {
|
||||
return random_time_Time(f)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Set the model columns to this value
|
||||
func (m itemMods) Description(val string) ItemMod {
|
||||
return ItemModFunc(func(o *ItemTemplate) {
|
||||
o.Description = func() string { return val }
|
||||
})
|
||||
}
|
||||
|
||||
// Set the Column from the function
|
||||
func (m itemMods) DescriptionFunc(f func() string) ItemMod {
|
||||
return ItemModFunc(func(o *ItemTemplate) {
|
||||
o.Description = f
|
||||
})
|
||||
}
|
||||
|
||||
// Clear any values for the column
|
||||
func (m itemMods) UnsetDescription() ItemMod {
|
||||
return ItemModFunc(func(o *ItemTemplate) {
|
||||
o.Description = nil
|
||||
})
|
||||
}
|
||||
|
||||
// Generates a random value for the column using the given faker
|
||||
// if faker is nil, a default faker is used
|
||||
func (m itemMods) RandomDescription(f *faker.Faker) ItemMod {
|
||||
return ItemModFunc(func(o *ItemTemplate) {
|
||||
o.Description = func() string {
|
||||
return random_string(f)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Set the model columns to this value
|
||||
func (m itemMods) Price(val float32) ItemMod {
|
||||
return ItemModFunc(func(o *ItemTemplate) {
|
||||
o.Price = func() float32 { return val }
|
||||
})
|
||||
}
|
||||
|
||||
// Set the Column from the function
|
||||
func (m itemMods) PriceFunc(f func() float32) ItemMod {
|
||||
return ItemModFunc(func(o *ItemTemplate) {
|
||||
o.Price = f
|
||||
})
|
||||
}
|
||||
|
||||
// Clear any values for the column
|
||||
func (m itemMods) UnsetPrice() ItemMod {
|
||||
return ItemModFunc(func(o *ItemTemplate) {
|
||||
o.Price = nil
|
||||
})
|
||||
}
|
||||
|
||||
// Generates a random value for the column using the given faker
|
||||
// if faker is nil, a default faker is used
|
||||
func (m itemMods) RandomPrice(f *faker.Faker) ItemMod {
|
||||
return ItemModFunc(func(o *ItemTemplate) {
|
||||
o.Price = func() float32 {
|
||||
return random_float32(f)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Set the model columns to this value
|
||||
func (m itemMods) Quantity(val int64) ItemMod {
|
||||
return ItemModFunc(func(o *ItemTemplate) {
|
||||
o.Quantity = func() int64 { return val }
|
||||
})
|
||||
}
|
||||
|
||||
// Set the Column from the function
|
||||
func (m itemMods) QuantityFunc(f func() int64) ItemMod {
|
||||
return ItemModFunc(func(o *ItemTemplate) {
|
||||
o.Quantity = f
|
||||
})
|
||||
}
|
||||
|
||||
// Clear any values for the column
|
||||
func (m itemMods) UnsetQuantity() ItemMod {
|
||||
return ItemModFunc(func(o *ItemTemplate) {
|
||||
o.Quantity = nil
|
||||
})
|
||||
}
|
||||
|
||||
// Generates a random value for the column using the given faker
|
||||
// if faker is nil, a default faker is used
|
||||
func (m itemMods) RandomQuantity(f *faker.Faker) ItemMod {
|
||||
return ItemModFunc(func(o *ItemTemplate) {
|
||||
o.Quantity = func() int64 {
|
||||
return random_int64(f)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Set the model columns to this value
|
||||
func (m itemMods) UserID(val int64) ItemMod {
|
||||
return ItemModFunc(func(o *ItemTemplate) {
|
||||
o.UserID = func() int64 { return val }
|
||||
})
|
||||
}
|
||||
|
||||
// Set the Column from the function
|
||||
func (m itemMods) UserIDFunc(f func() int64) ItemMod {
|
||||
return ItemModFunc(func(o *ItemTemplate) {
|
||||
o.UserID = f
|
||||
})
|
||||
}
|
||||
|
||||
// Clear any values for the column
|
||||
func (m itemMods) UnsetUserID() ItemMod {
|
||||
return ItemModFunc(func(o *ItemTemplate) {
|
||||
o.UserID = nil
|
||||
})
|
||||
}
|
||||
|
||||
// Generates a random value for the column using the given faker
|
||||
// if faker is nil, a default faker is used
|
||||
func (m itemMods) RandomUserID(f *faker.Faker) ItemMod {
|
||||
return ItemModFunc(func(o *ItemTemplate) {
|
||||
o.UserID = func() int64 {
|
||||
return random_int64(f)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (m itemMods) WithUser(rel *UserTemplate) ItemMod {
|
||||
return ItemModFunc(func(o *ItemTemplate) {
|
||||
o.r.User = &itemRUserR{
|
||||
o: rel,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (m itemMods) WithNewUser(mods ...UserMod) ItemMod {
|
||||
return ItemModFunc(func(o *ItemTemplate) {
|
||||
related := o.f.NewUser(mods...)
|
||||
|
||||
m.WithUser(related).Apply(o)
|
||||
})
|
||||
}
|
||||
|
||||
func (m itemMods) WithoutUser() ItemMod {
|
||||
return ItemModFunc(func(o *ItemTemplate) {
|
||||
o.r.User = nil
|
||||
})
|
||||
}
|
@ -1,276 +0,0 @@
|
||||
// Code generated by BobGen sql (devel). DO NOT EDIT.
|
||||
// This file is meant to be re-generated in place and/or deleted at any time.
|
||||
|
||||
package factory
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/aarondl/opt/omit"
|
||||
"github.com/jaswdr/faker/v2"
|
||||
models "github.com/spotdemo4/trevstack/server/internal/models"
|
||||
"github.com/stephenafamo/bob"
|
||||
)
|
||||
|
||||
type SchemaMigrationMod interface {
|
||||
Apply(*SchemaMigrationTemplate)
|
||||
}
|
||||
|
||||
type SchemaMigrationModFunc func(*SchemaMigrationTemplate)
|
||||
|
||||
func (f SchemaMigrationModFunc) Apply(n *SchemaMigrationTemplate) {
|
||||
f(n)
|
||||
}
|
||||
|
||||
type SchemaMigrationModSlice []SchemaMigrationMod
|
||||
|
||||
func (mods SchemaMigrationModSlice) Apply(n *SchemaMigrationTemplate) {
|
||||
for _, f := range mods {
|
||||
f.Apply(n)
|
||||
}
|
||||
}
|
||||
|
||||
// SchemaMigrationTemplate is an object representing the database table.
|
||||
// all columns are optional and should be set by mods
|
||||
type SchemaMigrationTemplate struct {
|
||||
Version func() string
|
||||
|
||||
f *Factory
|
||||
}
|
||||
|
||||
// Apply mods to the SchemaMigrationTemplate
|
||||
func (o *SchemaMigrationTemplate) Apply(mods ...SchemaMigrationMod) {
|
||||
for _, mod := range mods {
|
||||
mod.Apply(o)
|
||||
}
|
||||
}
|
||||
|
||||
// toModel returns an *models.SchemaMigration
|
||||
// this does nothing with the relationship templates
|
||||
func (o SchemaMigrationTemplate) toModel() *models.SchemaMigration {
|
||||
m := &models.SchemaMigration{}
|
||||
|
||||
if o.Version != nil {
|
||||
m.Version = o.Version()
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// toModels returns an models.SchemaMigrationSlice
|
||||
// this does nothing with the relationship templates
|
||||
func (o SchemaMigrationTemplate) toModels(number int) models.SchemaMigrationSlice {
|
||||
m := make(models.SchemaMigrationSlice, number)
|
||||
|
||||
for i := range m {
|
||||
m[i] = o.toModel()
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// setModelRels creates and sets the relationships on *models.SchemaMigration
|
||||
// according to the relationships in the template. Nothing is inserted into the db
|
||||
func (t SchemaMigrationTemplate) setModelRels(o *models.SchemaMigration) {}
|
||||
|
||||
// BuildSetter returns an *models.SchemaMigrationSetter
|
||||
// this does nothing with the relationship templates
|
||||
func (o SchemaMigrationTemplate) BuildSetter() *models.SchemaMigrationSetter {
|
||||
m := &models.SchemaMigrationSetter{}
|
||||
|
||||
if o.Version != nil {
|
||||
m.Version = omit.From(o.Version())
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// BuildManySetter returns an []*models.SchemaMigrationSetter
|
||||
// this does nothing with the relationship templates
|
||||
func (o SchemaMigrationTemplate) BuildManySetter(number int) []*models.SchemaMigrationSetter {
|
||||
m := make([]*models.SchemaMigrationSetter, number)
|
||||
|
||||
for i := range m {
|
||||
m[i] = o.BuildSetter()
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// Build returns an *models.SchemaMigration
|
||||
// Related objects are also created and placed in the .R field
|
||||
// NOTE: Objects are not inserted into the database. Use SchemaMigrationTemplate.Create
|
||||
func (o SchemaMigrationTemplate) Build() *models.SchemaMigration {
|
||||
m := o.toModel()
|
||||
o.setModelRels(m)
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// BuildMany returns an models.SchemaMigrationSlice
|
||||
// Related objects are also created and placed in the .R field
|
||||
// NOTE: Objects are not inserted into the database. Use SchemaMigrationTemplate.CreateMany
|
||||
func (o SchemaMigrationTemplate) BuildMany(number int) models.SchemaMigrationSlice {
|
||||
m := make(models.SchemaMigrationSlice, number)
|
||||
|
||||
for i := range m {
|
||||
m[i] = o.Build()
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func ensureCreatableSchemaMigration(m *models.SchemaMigrationSetter) {
|
||||
if m.Version.IsUnset() {
|
||||
m.Version = omit.From(random_string(nil))
|
||||
}
|
||||
}
|
||||
|
||||
// insertOptRels creates and inserts any optional the relationships on *models.SchemaMigration
|
||||
// according to the relationships in the template.
|
||||
// any required relationship should have already exist on the model
|
||||
func (o *SchemaMigrationTemplate) insertOptRels(ctx context.Context, exec bob.Executor, m *models.SchemaMigration) (context.Context, error) {
|
||||
var err error
|
||||
|
||||
return ctx, err
|
||||
}
|
||||
|
||||
// Create builds a schemaMigration and inserts it into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
func (o *SchemaMigrationTemplate) Create(ctx context.Context, exec bob.Executor) (*models.SchemaMigration, error) {
|
||||
_, m, err := o.create(ctx, exec)
|
||||
return m, err
|
||||
}
|
||||
|
||||
// MustCreate builds a schemaMigration and inserts it into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
// panics if an error occurs
|
||||
func (o *SchemaMigrationTemplate) MustCreate(ctx context.Context, exec bob.Executor) *models.SchemaMigration {
|
||||
_, m, err := o.create(ctx, exec)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// CreateOrFail builds a schemaMigration and inserts it into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
// It calls `tb.Fatal(err)` on the test/benchmark if an error occurs
|
||||
func (o *SchemaMigrationTemplate) CreateOrFail(ctx context.Context, tb testing.TB, exec bob.Executor) *models.SchemaMigration {
|
||||
tb.Helper()
|
||||
_, m, err := o.create(ctx, exec)
|
||||
if err != nil {
|
||||
tb.Fatal(err)
|
||||
return nil
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// create builds a schemaMigration and inserts it into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
// this returns a context that includes the newly inserted model
|
||||
func (o *SchemaMigrationTemplate) create(ctx context.Context, exec bob.Executor) (context.Context, *models.SchemaMigration, error) {
|
||||
var err error
|
||||
opt := o.BuildSetter()
|
||||
ensureCreatableSchemaMigration(opt)
|
||||
|
||||
m, err := models.SchemaMigrations.Insert(opt).One(ctx, exec)
|
||||
if err != nil {
|
||||
return ctx, nil, err
|
||||
}
|
||||
ctx = schemaMigrationCtx.WithValue(ctx, m)
|
||||
|
||||
ctx, err = o.insertOptRels(ctx, exec, m)
|
||||
return ctx, m, err
|
||||
}
|
||||
|
||||
// CreateMany builds multiple schemaMigrations and inserts them into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
func (o SchemaMigrationTemplate) CreateMany(ctx context.Context, exec bob.Executor, number int) (models.SchemaMigrationSlice, error) {
|
||||
_, m, err := o.createMany(ctx, exec, number)
|
||||
return m, err
|
||||
}
|
||||
|
||||
// MustCreateMany builds multiple schemaMigrations and inserts them into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
// panics if an error occurs
|
||||
func (o SchemaMigrationTemplate) MustCreateMany(ctx context.Context, exec bob.Executor, number int) models.SchemaMigrationSlice {
|
||||
_, m, err := o.createMany(ctx, exec, number)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// CreateManyOrFail builds multiple schemaMigrations and inserts them into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
// It calls `tb.Fatal(err)` on the test/benchmark if an error occurs
|
||||
func (o SchemaMigrationTemplate) CreateManyOrFail(ctx context.Context, tb testing.TB, exec bob.Executor, number int) models.SchemaMigrationSlice {
|
||||
tb.Helper()
|
||||
_, m, err := o.createMany(ctx, exec, number)
|
||||
if err != nil {
|
||||
tb.Fatal(err)
|
||||
return nil
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// createMany builds multiple schemaMigrations and inserts them into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
// this returns a context that includes the newly inserted models
|
||||
func (o SchemaMigrationTemplate) createMany(ctx context.Context, exec bob.Executor, number int) (context.Context, models.SchemaMigrationSlice, error) {
|
||||
var err error
|
||||
m := make(models.SchemaMigrationSlice, number)
|
||||
|
||||
for i := range m {
|
||||
ctx, m[i], err = o.create(ctx, exec)
|
||||
if err != nil {
|
||||
return ctx, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return ctx, m, nil
|
||||
}
|
||||
|
||||
// SchemaMigration has methods that act as mods for the SchemaMigrationTemplate
|
||||
var SchemaMigrationMods schemaMigrationMods
|
||||
|
||||
type schemaMigrationMods struct{}
|
||||
|
||||
func (m schemaMigrationMods) RandomizeAllColumns(f *faker.Faker) SchemaMigrationMod {
|
||||
return SchemaMigrationModSlice{
|
||||
SchemaMigrationMods.RandomVersion(f),
|
||||
}
|
||||
}
|
||||
|
||||
// Set the model columns to this value
|
||||
func (m schemaMigrationMods) Version(val string) SchemaMigrationMod {
|
||||
return SchemaMigrationModFunc(func(o *SchemaMigrationTemplate) {
|
||||
o.Version = func() string { return val }
|
||||
})
|
||||
}
|
||||
|
||||
// Set the Column from the function
|
||||
func (m schemaMigrationMods) VersionFunc(f func() string) SchemaMigrationMod {
|
||||
return SchemaMigrationModFunc(func(o *SchemaMigrationTemplate) {
|
||||
o.Version = f
|
||||
})
|
||||
}
|
||||
|
||||
// Clear any values for the column
|
||||
func (m schemaMigrationMods) UnsetVersion() SchemaMigrationMod {
|
||||
return SchemaMigrationModFunc(func(o *SchemaMigrationTemplate) {
|
||||
o.Version = nil
|
||||
})
|
||||
}
|
||||
|
||||
// Generates a random value for the column using the given faker
|
||||
// if faker is nil, a default faker is used
|
||||
func (m schemaMigrationMods) RandomVersion(f *faker.Faker) SchemaMigrationMod {
|
||||
return SchemaMigrationModFunc(func(o *SchemaMigrationTemplate) {
|
||||
o.Version = func() string {
|
||||
return random_string(f)
|
||||
}
|
||||
})
|
||||
}
|
@ -1,598 +0,0 @@
|
||||
// Code generated by BobGen sql (devel). DO NOT EDIT.
|
||||
// This file is meant to be re-generated in place and/or deleted at any time.
|
||||
|
||||
package factory
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/aarondl/opt/null"
|
||||
"github.com/aarondl/opt/omit"
|
||||
"github.com/aarondl/opt/omitnull"
|
||||
"github.com/jaswdr/faker/v2"
|
||||
models "github.com/spotdemo4/trevstack/server/internal/models"
|
||||
"github.com/stephenafamo/bob"
|
||||
)
|
||||
|
||||
type UserMod interface {
|
||||
Apply(*UserTemplate)
|
||||
}
|
||||
|
||||
type UserModFunc func(*UserTemplate)
|
||||
|
||||
func (f UserModFunc) Apply(n *UserTemplate) {
|
||||
f(n)
|
||||
}
|
||||
|
||||
type UserModSlice []UserMod
|
||||
|
||||
func (mods UserModSlice) Apply(n *UserTemplate) {
|
||||
for _, f := range mods {
|
||||
f.Apply(n)
|
||||
}
|
||||
}
|
||||
|
||||
// UserTemplate is an object representing the database table.
|
||||
// all columns are optional and should be set by mods
|
||||
type UserTemplate struct {
|
||||
ID func() int64
|
||||
Username func() string
|
||||
Password func() string
|
||||
ProfilePictureID func() null.Val[int64]
|
||||
|
||||
r userR
|
||||
f *Factory
|
||||
}
|
||||
|
||||
type userR struct {
|
||||
Files []*userRFilesR
|
||||
Items []*userRItemsR
|
||||
ProfilePictureFile *userRProfilePictureFileR
|
||||
}
|
||||
|
||||
type userRFilesR struct {
|
||||
number int
|
||||
o *FileTemplate
|
||||
}
|
||||
type userRItemsR struct {
|
||||
number int
|
||||
o *ItemTemplate
|
||||
}
|
||||
type userRProfilePictureFileR struct {
|
||||
o *FileTemplate
|
||||
}
|
||||
|
||||
// Apply mods to the UserTemplate
|
||||
func (o *UserTemplate) Apply(mods ...UserMod) {
|
||||
for _, mod := range mods {
|
||||
mod.Apply(o)
|
||||
}
|
||||
}
|
||||
|
||||
// toModel returns an *models.User
|
||||
// this does nothing with the relationship templates
|
||||
func (o UserTemplate) toModel() *models.User {
|
||||
m := &models.User{}
|
||||
|
||||
if o.ID != nil {
|
||||
m.ID = o.ID()
|
||||
}
|
||||
if o.Username != nil {
|
||||
m.Username = o.Username()
|
||||
}
|
||||
if o.Password != nil {
|
||||
m.Password = o.Password()
|
||||
}
|
||||
if o.ProfilePictureID != nil {
|
||||
m.ProfilePictureID = o.ProfilePictureID()
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// toModels returns an models.UserSlice
|
||||
// this does nothing with the relationship templates
|
||||
func (o UserTemplate) toModels(number int) models.UserSlice {
|
||||
m := make(models.UserSlice, number)
|
||||
|
||||
for i := range m {
|
||||
m[i] = o.toModel()
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// setModelRels creates and sets the relationships on *models.User
|
||||
// according to the relationships in the template. Nothing is inserted into the db
|
||||
func (t UserTemplate) setModelRels(o *models.User) {
|
||||
if t.r.Files != nil {
|
||||
rel := models.FileSlice{}
|
||||
for _, r := range t.r.Files {
|
||||
related := r.o.toModels(r.number)
|
||||
for _, rel := range related {
|
||||
rel.UserID = o.ID
|
||||
rel.R.User = o
|
||||
}
|
||||
rel = append(rel, related...)
|
||||
}
|
||||
o.R.Files = rel
|
||||
}
|
||||
|
||||
if t.r.Items != nil {
|
||||
rel := models.ItemSlice{}
|
||||
for _, r := range t.r.Items {
|
||||
related := r.o.toModels(r.number)
|
||||
for _, rel := range related {
|
||||
rel.UserID = o.ID
|
||||
rel.R.User = o
|
||||
}
|
||||
rel = append(rel, related...)
|
||||
}
|
||||
o.R.Items = rel
|
||||
}
|
||||
|
||||
if t.r.ProfilePictureFile != nil {
|
||||
rel := t.r.ProfilePictureFile.o.toModel()
|
||||
rel.R.ProfilePictureUsers = append(rel.R.ProfilePictureUsers, o)
|
||||
o.ProfilePictureID = null.From(rel.ID)
|
||||
o.R.ProfilePictureFile = rel
|
||||
}
|
||||
}
|
||||
|
||||
// BuildSetter returns an *models.UserSetter
|
||||
// this does nothing with the relationship templates
|
||||
func (o UserTemplate) BuildSetter() *models.UserSetter {
|
||||
m := &models.UserSetter{}
|
||||
|
||||
if o.ID != nil {
|
||||
m.ID = omit.From(o.ID())
|
||||
}
|
||||
if o.Username != nil {
|
||||
m.Username = omit.From(o.Username())
|
||||
}
|
||||
if o.Password != nil {
|
||||
m.Password = omit.From(o.Password())
|
||||
}
|
||||
if o.ProfilePictureID != nil {
|
||||
m.ProfilePictureID = omitnull.FromNull(o.ProfilePictureID())
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// BuildManySetter returns an []*models.UserSetter
|
||||
// this does nothing with the relationship templates
|
||||
func (o UserTemplate) BuildManySetter(number int) []*models.UserSetter {
|
||||
m := make([]*models.UserSetter, number)
|
||||
|
||||
for i := range m {
|
||||
m[i] = o.BuildSetter()
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// Build returns an *models.User
|
||||
// Related objects are also created and placed in the .R field
|
||||
// NOTE: Objects are not inserted into the database. Use UserTemplate.Create
|
||||
func (o UserTemplate) Build() *models.User {
|
||||
m := o.toModel()
|
||||
o.setModelRels(m)
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// BuildMany returns an models.UserSlice
|
||||
// Related objects are also created and placed in the .R field
|
||||
// NOTE: Objects are not inserted into the database. Use UserTemplate.CreateMany
|
||||
func (o UserTemplate) BuildMany(number int) models.UserSlice {
|
||||
m := make(models.UserSlice, number)
|
||||
|
||||
for i := range m {
|
||||
m[i] = o.Build()
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func ensureCreatableUser(m *models.UserSetter) {
|
||||
if m.Username.IsUnset() {
|
||||
m.Username = omit.From(random_string(nil))
|
||||
}
|
||||
if m.Password.IsUnset() {
|
||||
m.Password = omit.From(random_string(nil))
|
||||
}
|
||||
}
|
||||
|
||||
// insertOptRels creates and inserts any optional the relationships on *models.User
|
||||
// according to the relationships in the template.
|
||||
// any required relationship should have already exist on the model
|
||||
func (o *UserTemplate) insertOptRels(ctx context.Context, exec bob.Executor, m *models.User) (context.Context, error) {
|
||||
var err error
|
||||
|
||||
if o.r.Files != nil {
|
||||
for _, r := range o.r.Files {
|
||||
var rel0 models.FileSlice
|
||||
ctx, rel0, err = r.o.createMany(ctx, exec, r.number)
|
||||
if err != nil {
|
||||
return ctx, err
|
||||
}
|
||||
|
||||
err = m.AttachFiles(ctx, exec, rel0...)
|
||||
if err != nil {
|
||||
return ctx, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if o.r.Items != nil {
|
||||
for _, r := range o.r.Items {
|
||||
var rel1 models.ItemSlice
|
||||
ctx, rel1, err = r.o.createMany(ctx, exec, r.number)
|
||||
if err != nil {
|
||||
return ctx, err
|
||||
}
|
||||
|
||||
err = m.AttachItems(ctx, exec, rel1...)
|
||||
if err != nil {
|
||||
return ctx, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if o.r.ProfilePictureFile != nil {
|
||||
var rel2 *models.File
|
||||
ctx, rel2, err = o.r.ProfilePictureFile.o.create(ctx, exec)
|
||||
if err != nil {
|
||||
return ctx, err
|
||||
}
|
||||
err = m.AttachProfilePictureFile(ctx, exec, rel2)
|
||||
if err != nil {
|
||||
return ctx, err
|
||||
}
|
||||
}
|
||||
|
||||
return ctx, err
|
||||
}
|
||||
|
||||
// Create builds a user and inserts it into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
func (o *UserTemplate) Create(ctx context.Context, exec bob.Executor) (*models.User, error) {
|
||||
_, m, err := o.create(ctx, exec)
|
||||
return m, err
|
||||
}
|
||||
|
||||
// MustCreate builds a user and inserts it into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
// panics if an error occurs
|
||||
func (o *UserTemplate) MustCreate(ctx context.Context, exec bob.Executor) *models.User {
|
||||
_, m, err := o.create(ctx, exec)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// CreateOrFail builds a user and inserts it into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
// It calls `tb.Fatal(err)` on the test/benchmark if an error occurs
|
||||
func (o *UserTemplate) CreateOrFail(ctx context.Context, tb testing.TB, exec bob.Executor) *models.User {
|
||||
tb.Helper()
|
||||
_, m, err := o.create(ctx, exec)
|
||||
if err != nil {
|
||||
tb.Fatal(err)
|
||||
return nil
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// create builds a user and inserts it into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
// this returns a context that includes the newly inserted model
|
||||
func (o *UserTemplate) create(ctx context.Context, exec bob.Executor) (context.Context, *models.User, error) {
|
||||
var err error
|
||||
opt := o.BuildSetter()
|
||||
ensureCreatableUser(opt)
|
||||
|
||||
m, err := models.Users.Insert(opt).One(ctx, exec)
|
||||
if err != nil {
|
||||
return ctx, nil, err
|
||||
}
|
||||
ctx = userCtx.WithValue(ctx, m)
|
||||
|
||||
ctx, err = o.insertOptRels(ctx, exec, m)
|
||||
return ctx, m, err
|
||||
}
|
||||
|
||||
// CreateMany builds multiple users and inserts them into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
func (o UserTemplate) CreateMany(ctx context.Context, exec bob.Executor, number int) (models.UserSlice, error) {
|
||||
_, m, err := o.createMany(ctx, exec, number)
|
||||
return m, err
|
||||
}
|
||||
|
||||
// MustCreateMany builds multiple users and inserts them into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
// panics if an error occurs
|
||||
func (o UserTemplate) MustCreateMany(ctx context.Context, exec bob.Executor, number int) models.UserSlice {
|
||||
_, m, err := o.createMany(ctx, exec, number)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// CreateManyOrFail builds multiple users and inserts them into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
// It calls `tb.Fatal(err)` on the test/benchmark if an error occurs
|
||||
func (o UserTemplate) CreateManyOrFail(ctx context.Context, tb testing.TB, exec bob.Executor, number int) models.UserSlice {
|
||||
tb.Helper()
|
||||
_, m, err := o.createMany(ctx, exec, number)
|
||||
if err != nil {
|
||||
tb.Fatal(err)
|
||||
return nil
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// createMany builds multiple users and inserts them into the database
|
||||
// Relations objects are also inserted and placed in the .R field
|
||||
// this returns a context that includes the newly inserted models
|
||||
func (o UserTemplate) createMany(ctx context.Context, exec bob.Executor, number int) (context.Context, models.UserSlice, error) {
|
||||
var err error
|
||||
m := make(models.UserSlice, number)
|
||||
|
||||
for i := range m {
|
||||
ctx, m[i], err = o.create(ctx, exec)
|
||||
if err != nil {
|
||||
return ctx, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return ctx, m, nil
|
||||
}
|
||||
|
||||
// User has methods that act as mods for the UserTemplate
|
||||
var UserMods userMods
|
||||
|
||||
type userMods struct{}
|
||||
|
||||
func (m userMods) RandomizeAllColumns(f *faker.Faker) UserMod {
|
||||
return UserModSlice{
|
||||
UserMods.RandomID(f),
|
||||
UserMods.RandomUsername(f),
|
||||
UserMods.RandomPassword(f),
|
||||
UserMods.RandomProfilePictureID(f),
|
||||
}
|
||||
}
|
||||
|
||||
// Set the model columns to this value
|
||||
func (m userMods) ID(val int64) UserMod {
|
||||
return UserModFunc(func(o *UserTemplate) {
|
||||
o.ID = func() int64 { return val }
|
||||
})
|
||||
}
|
||||
|
||||
// Set the Column from the function
|
||||
func (m userMods) IDFunc(f func() int64) UserMod {
|
||||
return UserModFunc(func(o *UserTemplate) {
|
||||
o.ID = f
|
||||
})
|
||||
}
|
||||
|
||||
// Clear any values for the column
|
||||
func (m userMods) UnsetID() UserMod {
|
||||
return UserModFunc(func(o *UserTemplate) {
|
||||
o.ID = nil
|
||||
})
|
||||
}
|
||||
|
||||
// Generates a random value for the column using the given faker
|
||||
// if faker is nil, a default faker is used
|
||||
func (m userMods) RandomID(f *faker.Faker) UserMod {
|
||||
return UserModFunc(func(o *UserTemplate) {
|
||||
o.ID = func() int64 {
|
||||
return random_int64(f)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Set the model columns to this value
|
||||
func (m userMods) Username(val string) UserMod {
|
||||
return UserModFunc(func(o *UserTemplate) {
|
||||
o.Username = func() string { return val }
|
||||
})
|
||||
}
|
||||
|
||||
// Set the Column from the function
|
||||
func (m userMods) UsernameFunc(f func() string) UserMod {
|
||||
return UserModFunc(func(o *UserTemplate) {
|
||||
o.Username = f
|
||||
})
|
||||
}
|
||||
|
||||
// Clear any values for the column
|
||||
func (m userMods) UnsetUsername() UserMod {
|
||||
return UserModFunc(func(o *UserTemplate) {
|
||||
o.Username = nil
|
||||
})
|
||||
}
|
||||
|
||||
// Generates a random value for the column using the given faker
|
||||
// if faker is nil, a default faker is used
|
||||
func (m userMods) RandomUsername(f *faker.Faker) UserMod {
|
||||
return UserModFunc(func(o *UserTemplate) {
|
||||
o.Username = func() string {
|
||||
return random_string(f)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Set the model columns to this value
|
||||
func (m userMods) Password(val string) UserMod {
|
||||
return UserModFunc(func(o *UserTemplate) {
|
||||
o.Password = func() string { return val }
|
||||
})
|
||||
}
|
||||
|
||||
// Set the Column from the function
|
||||
func (m userMods) PasswordFunc(f func() string) UserMod {
|
||||
return UserModFunc(func(o *UserTemplate) {
|
||||
o.Password = f
|
||||
})
|
||||
}
|
||||
|
||||
// Clear any values for the column
|
||||
func (m userMods) UnsetPassword() UserMod {
|
||||
return UserModFunc(func(o *UserTemplate) {
|
||||
o.Password = nil
|
||||
})
|
||||
}
|
||||
|
||||
// Generates a random value for the column using the given faker
|
||||
// if faker is nil, a default faker is used
|
||||
func (m userMods) RandomPassword(f *faker.Faker) UserMod {
|
||||
return UserModFunc(func(o *UserTemplate) {
|
||||
o.Password = func() string {
|
||||
return random_string(f)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Set the model columns to this value
|
||||
func (m userMods) ProfilePictureID(val null.Val[int64]) UserMod {
|
||||
return UserModFunc(func(o *UserTemplate) {
|
||||
o.ProfilePictureID = func() null.Val[int64] { return val }
|
||||
})
|
||||
}
|
||||
|
||||
// Set the Column from the function
|
||||
func (m userMods) ProfilePictureIDFunc(f func() null.Val[int64]) UserMod {
|
||||
return UserModFunc(func(o *UserTemplate) {
|
||||
o.ProfilePictureID = f
|
||||
})
|
||||
}
|
||||
|
||||
// Clear any values for the column
|
||||
func (m userMods) UnsetProfilePictureID() UserMod {
|
||||
return UserModFunc(func(o *UserTemplate) {
|
||||
o.ProfilePictureID = nil
|
||||
})
|
||||
}
|
||||
|
||||
// Generates a random value for the column using the given faker
|
||||
// if faker is nil, a default faker is used
|
||||
func (m userMods) RandomProfilePictureID(f *faker.Faker) UserMod {
|
||||
return UserModFunc(func(o *UserTemplate) {
|
||||
o.ProfilePictureID = func() null.Val[int64] {
|
||||
if f == nil {
|
||||
f = &defaultFaker
|
||||
}
|
||||
|
||||
if f.Bool() {
|
||||
return null.FromPtr[int64](nil)
|
||||
}
|
||||
|
||||
return null.From(random_int64(f))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (m userMods) WithProfilePictureFile(rel *FileTemplate) UserMod {
|
||||
return UserModFunc(func(o *UserTemplate) {
|
||||
o.r.ProfilePictureFile = &userRProfilePictureFileR{
|
||||
o: rel,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (m userMods) WithNewProfilePictureFile(mods ...FileMod) UserMod {
|
||||
return UserModFunc(func(o *UserTemplate) {
|
||||
related := o.f.NewFile(mods...)
|
||||
|
||||
m.WithProfilePictureFile(related).Apply(o)
|
||||
})
|
||||
}
|
||||
|
||||
func (m userMods) WithoutProfilePictureFile() UserMod {
|
||||
return UserModFunc(func(o *UserTemplate) {
|
||||
o.r.ProfilePictureFile = nil
|
||||
})
|
||||
}
|
||||
|
||||
func (m userMods) WithFiles(number int, related *FileTemplate) UserMod {
|
||||
return UserModFunc(func(o *UserTemplate) {
|
||||
o.r.Files = []*userRFilesR{{
|
||||
number: number,
|
||||
o: related,
|
||||
}}
|
||||
})
|
||||
}
|
||||
|
||||
func (m userMods) WithNewFiles(number int, mods ...FileMod) UserMod {
|
||||
return UserModFunc(func(o *UserTemplate) {
|
||||
related := o.f.NewFile(mods...)
|
||||
m.WithFiles(number, related).Apply(o)
|
||||
})
|
||||
}
|
||||
|
||||
func (m userMods) AddFiles(number int, related *FileTemplate) UserMod {
|
||||
return UserModFunc(func(o *UserTemplate) {
|
||||
o.r.Files = append(o.r.Files, &userRFilesR{
|
||||
number: number,
|
||||
o: related,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func (m userMods) AddNewFiles(number int, mods ...FileMod) UserMod {
|
||||
return UserModFunc(func(o *UserTemplate) {
|
||||
related := o.f.NewFile(mods...)
|
||||
m.AddFiles(number, related).Apply(o)
|
||||
})
|
||||
}
|
||||
|
||||
func (m userMods) WithoutFiles() UserMod {
|
||||
return UserModFunc(func(o *UserTemplate) {
|
||||
o.r.Files = nil
|
||||
})
|
||||
}
|
||||
|
||||
func (m userMods) WithItems(number int, related *ItemTemplate) UserMod {
|
||||
return UserModFunc(func(o *UserTemplate) {
|
||||
o.r.Items = []*userRItemsR{{
|
||||
number: number,
|
||||
o: related,
|
||||
}}
|
||||
})
|
||||
}
|
||||
|
||||
func (m userMods) WithNewItems(number int, mods ...ItemMod) UserMod {
|
||||
return UserModFunc(func(o *UserTemplate) {
|
||||
related := o.f.NewItem(mods...)
|
||||
m.WithItems(number, related).Apply(o)
|
||||
})
|
||||
}
|
||||
|
||||
func (m userMods) AddItems(number int, related *ItemTemplate) UserMod {
|
||||
return UserModFunc(func(o *UserTemplate) {
|
||||
o.r.Items = append(o.r.Items, &userRItemsR{
|
||||
number: number,
|
||||
o: related,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func (m userMods) AddNewItems(number int, mods ...ItemMod) UserMod {
|
||||
return UserModFunc(func(o *UserTemplate) {
|
||||
related := o.f.NewItem(mods...)
|
||||
m.AddItems(number, related).Apply(o)
|
||||
})
|
||||
}
|
||||
|
||||
func (m userMods) WithoutItems() UserMod {
|
||||
return UserModFunc(func(o *UserTemplate) {
|
||||
o.r.Items = nil
|
||||
})
|
||||
}
|
@ -1,851 +0,0 @@
|
||||
// Code generated by BobGen sql (devel). DO NOT EDIT.
|
||||
// This file is meant to be re-generated in place and/or deleted at any time.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/aarondl/opt/omit"
|
||||
"github.com/aarondl/opt/omitnull"
|
||||
"github.com/stephenafamo/bob"
|
||||
"github.com/stephenafamo/bob/dialect/sqlite"
|
||||
"github.com/stephenafamo/bob/dialect/sqlite/dialect"
|
||||
"github.com/stephenafamo/bob/dialect/sqlite/dm"
|
||||
"github.com/stephenafamo/bob/dialect/sqlite/sm"
|
||||
"github.com/stephenafamo/bob/dialect/sqlite/um"
|
||||
"github.com/stephenafamo/bob/expr"
|
||||
"github.com/stephenafamo/bob/mods"
|
||||
"github.com/stephenafamo/bob/orm"
|
||||
)
|
||||
|
||||
// File is an object representing the database table.
|
||||
type File struct {
|
||||
ID int64 `db:"id,pk" `
|
||||
Name string `db:"name" `
|
||||
Data []byte `db:"data" `
|
||||
UserID int64 `db:"user_id" `
|
||||
|
||||
R fileR `db:"-" `
|
||||
}
|
||||
|
||||
// FileSlice is an alias for a slice of pointers to File.
|
||||
// This should almost always be used instead of []*File.
|
||||
type FileSlice []*File
|
||||
|
||||
// Files contains methods to work with the file table
|
||||
var Files = sqlite.NewTablex[*File, FileSlice, *FileSetter]("", "file")
|
||||
|
||||
// FilesQuery is a query on the file table
|
||||
type FilesQuery = *sqlite.ViewQuery[*File, FileSlice]
|
||||
|
||||
// fileR is where relationships are stored.
|
||||
type fileR struct {
|
||||
User *User // fk_file_0
|
||||
ProfilePictureUsers UserSlice // fk_user_0
|
||||
}
|
||||
|
||||
type fileColumnNames struct {
|
||||
ID string
|
||||
Name string
|
||||
Data string
|
||||
UserID string
|
||||
}
|
||||
|
||||
var FileColumns = buildFileColumns("file")
|
||||
|
||||
type fileColumns struct {
|
||||
tableAlias string
|
||||
ID sqlite.Expression
|
||||
Name sqlite.Expression
|
||||
Data sqlite.Expression
|
||||
UserID sqlite.Expression
|
||||
}
|
||||
|
||||
func (c fileColumns) Alias() string {
|
||||
return c.tableAlias
|
||||
}
|
||||
|
||||
func (fileColumns) AliasedAs(alias string) fileColumns {
|
||||
return buildFileColumns(alias)
|
||||
}
|
||||
|
||||
func buildFileColumns(alias string) fileColumns {
|
||||
return fileColumns{
|
||||
tableAlias: alias,
|
||||
ID: sqlite.Quote(alias, "id"),
|
||||
Name: sqlite.Quote(alias, "name"),
|
||||
Data: sqlite.Quote(alias, "data"),
|
||||
UserID: sqlite.Quote(alias, "user_id"),
|
||||
}
|
||||
}
|
||||
|
||||
type fileWhere[Q sqlite.Filterable] struct {
|
||||
ID sqlite.WhereMod[Q, int64]
|
||||
Name sqlite.WhereMod[Q, string]
|
||||
Data sqlite.WhereMod[Q, []byte]
|
||||
UserID sqlite.WhereMod[Q, int64]
|
||||
}
|
||||
|
||||
func (fileWhere[Q]) AliasedAs(alias string) fileWhere[Q] {
|
||||
return buildFileWhere[Q](buildFileColumns(alias))
|
||||
}
|
||||
|
||||
func buildFileWhere[Q sqlite.Filterable](cols fileColumns) fileWhere[Q] {
|
||||
return fileWhere[Q]{
|
||||
ID: sqlite.Where[Q, int64](cols.ID),
|
||||
Name: sqlite.Where[Q, string](cols.Name),
|
||||
Data: sqlite.Where[Q, []byte](cols.Data),
|
||||
UserID: sqlite.Where[Q, int64](cols.UserID),
|
||||
}
|
||||
}
|
||||
|
||||
var FileErrors = &fileErrors{
|
||||
ErrUniquePkMainFile: &UniqueConstraintError{s: "pk_main_file"},
|
||||
}
|
||||
|
||||
type fileErrors struct {
|
||||
ErrUniquePkMainFile *UniqueConstraintError
|
||||
}
|
||||
|
||||
// FileSetter is used for insert/upsert/update operations
|
||||
// All values are optional, and do not have to be set
|
||||
// Generated columns are not included
|
||||
type FileSetter struct {
|
||||
ID omit.Val[int64] `db:"id,pk" `
|
||||
Name omit.Val[string] `db:"name" `
|
||||
Data omit.Val[[]byte] `db:"data" `
|
||||
UserID omit.Val[int64] `db:"user_id" `
|
||||
}
|
||||
|
||||
func (s FileSetter) SetColumns() []string {
|
||||
vals := make([]string, 0, 4)
|
||||
if !s.ID.IsUnset() {
|
||||
vals = append(vals, "id")
|
||||
}
|
||||
|
||||
if !s.Name.IsUnset() {
|
||||
vals = append(vals, "name")
|
||||
}
|
||||
|
||||
if !s.Data.IsUnset() {
|
||||
vals = append(vals, "data")
|
||||
}
|
||||
|
||||
if !s.UserID.IsUnset() {
|
||||
vals = append(vals, "user_id")
|
||||
}
|
||||
|
||||
return vals
|
||||
}
|
||||
|
||||
func (s FileSetter) Overwrite(t *File) {
|
||||
if !s.ID.IsUnset() {
|
||||
t.ID, _ = s.ID.Get()
|
||||
}
|
||||
if !s.Name.IsUnset() {
|
||||
t.Name, _ = s.Name.Get()
|
||||
}
|
||||
if !s.Data.IsUnset() {
|
||||
t.Data, _ = s.Data.Get()
|
||||
}
|
||||
if !s.UserID.IsUnset() {
|
||||
t.UserID, _ = s.UserID.Get()
|
||||
}
|
||||
}
|
||||
|
||||
func (s *FileSetter) Apply(q *dialect.InsertQuery) {
|
||||
q.AppendHooks(func(ctx context.Context, exec bob.Executor) (context.Context, error) {
|
||||
return Files.BeforeInsertHooks.RunHooks(ctx, exec, s)
|
||||
})
|
||||
|
||||
if len(q.Table.Columns) == 0 {
|
||||
q.Table.Columns = s.SetColumns()
|
||||
}
|
||||
|
||||
q.AppendValues(bob.ExpressionFunc(func(ctx context.Context, w io.Writer, d bob.Dialect, start int) ([]any, error) {
|
||||
vals := make([]bob.Expression, 0, 4)
|
||||
if !s.ID.IsUnset() {
|
||||
vals = append(vals, sqlite.Arg(s.ID))
|
||||
}
|
||||
|
||||
if !s.Name.IsUnset() {
|
||||
vals = append(vals, sqlite.Arg(s.Name))
|
||||
}
|
||||
|
||||
if !s.Data.IsUnset() {
|
||||
vals = append(vals, sqlite.Arg(s.Data))
|
||||
}
|
||||
|
||||
if !s.UserID.IsUnset() {
|
||||
vals = append(vals, sqlite.Arg(s.UserID))
|
||||
}
|
||||
|
||||
return bob.ExpressSlice(ctx, w, d, start, vals, "", ", ", "")
|
||||
}))
|
||||
}
|
||||
|
||||
func (s FileSetter) UpdateMod() bob.Mod[*dialect.UpdateQuery] {
|
||||
return um.Set(s.Expressions()...)
|
||||
}
|
||||
|
||||
func (s FileSetter) Expressions(prefix ...string) []bob.Expression {
|
||||
exprs := make([]bob.Expression, 0, 4)
|
||||
|
||||
if !s.ID.IsUnset() {
|
||||
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
|
||||
sqlite.Quote(append(prefix, "id")...),
|
||||
sqlite.Arg(s.ID),
|
||||
}})
|
||||
}
|
||||
|
||||
if !s.Name.IsUnset() {
|
||||
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
|
||||
sqlite.Quote(append(prefix, "name")...),
|
||||
sqlite.Arg(s.Name),
|
||||
}})
|
||||
}
|
||||
|
||||
if !s.Data.IsUnset() {
|
||||
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
|
||||
sqlite.Quote(append(prefix, "data")...),
|
||||
sqlite.Arg(s.Data),
|
||||
}})
|
||||
}
|
||||
|
||||
if !s.UserID.IsUnset() {
|
||||
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
|
||||
sqlite.Quote(append(prefix, "user_id")...),
|
||||
sqlite.Arg(s.UserID),
|
||||
}})
|
||||
}
|
||||
|
||||
return exprs
|
||||
}
|
||||
|
||||
// FindFile retrieves a single record by primary key
|
||||
// If cols is empty Find will return all columns.
|
||||
func FindFile(ctx context.Context, exec bob.Executor, IDPK int64, cols ...string) (*File, error) {
|
||||
if len(cols) == 0 {
|
||||
return Files.Query(
|
||||
SelectWhere.Files.ID.EQ(IDPK),
|
||||
).One(ctx, exec)
|
||||
}
|
||||
|
||||
return Files.Query(
|
||||
SelectWhere.Files.ID.EQ(IDPK),
|
||||
sm.Columns(Files.Columns().Only(cols...)),
|
||||
).One(ctx, exec)
|
||||
}
|
||||
|
||||
// FileExists checks the presence of a single record by primary key
|
||||
func FileExists(ctx context.Context, exec bob.Executor, IDPK int64) (bool, error) {
|
||||
return Files.Query(
|
||||
SelectWhere.Files.ID.EQ(IDPK),
|
||||
).Exists(ctx, exec)
|
||||
}
|
||||
|
||||
// AfterQueryHook is called after File is retrieved from the database
|
||||
func (o *File) AfterQueryHook(ctx context.Context, exec bob.Executor, queryType bob.QueryType) error {
|
||||
var err error
|
||||
|
||||
switch queryType {
|
||||
case bob.QueryTypeSelect:
|
||||
ctx, err = Files.AfterSelectHooks.RunHooks(ctx, exec, FileSlice{o})
|
||||
case bob.QueryTypeInsert:
|
||||
ctx, err = Files.AfterInsertHooks.RunHooks(ctx, exec, FileSlice{o})
|
||||
case bob.QueryTypeUpdate:
|
||||
ctx, err = Files.AfterUpdateHooks.RunHooks(ctx, exec, FileSlice{o})
|
||||
case bob.QueryTypeDelete:
|
||||
ctx, err = Files.AfterDeleteHooks.RunHooks(ctx, exec, FileSlice{o})
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// PrimaryKeyVals returns the primary key values of the File
|
||||
func (o *File) PrimaryKeyVals() bob.Expression {
|
||||
return sqlite.Arg(o.ID)
|
||||
}
|
||||
|
||||
func (o *File) pkEQ() dialect.Expression {
|
||||
return sqlite.Quote("file", "id").EQ(bob.ExpressionFunc(func(ctx context.Context, w io.Writer, d bob.Dialect, start int) ([]any, error) {
|
||||
return o.PrimaryKeyVals().WriteSQL(ctx, w, d, start)
|
||||
}))
|
||||
}
|
||||
|
||||
// Update uses an executor to update the File
|
||||
func (o *File) Update(ctx context.Context, exec bob.Executor, s *FileSetter) error {
|
||||
v, err := Files.Update(s.UpdateMod(), um.Where(o.pkEQ())).One(ctx, exec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
o.R = v.R
|
||||
*o = *v
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Delete deletes a single File record with an executor
|
||||
func (o *File) Delete(ctx context.Context, exec bob.Executor) error {
|
||||
_, err := Files.Delete(dm.Where(o.pkEQ())).Exec(ctx, exec)
|
||||
return err
|
||||
}
|
||||
|
||||
// Reload refreshes the File using the executor
|
||||
func (o *File) Reload(ctx context.Context, exec bob.Executor) error {
|
||||
o2, err := Files.Query(
|
||||
SelectWhere.Files.ID.EQ(o.ID),
|
||||
).One(ctx, exec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o2.R = o.R
|
||||
*o = *o2
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AfterQueryHook is called after FileSlice is retrieved from the database
|
||||
func (o FileSlice) AfterQueryHook(ctx context.Context, exec bob.Executor, queryType bob.QueryType) error {
|
||||
var err error
|
||||
|
||||
switch queryType {
|
||||
case bob.QueryTypeSelect:
|
||||
ctx, err = Files.AfterSelectHooks.RunHooks(ctx, exec, o)
|
||||
case bob.QueryTypeInsert:
|
||||
ctx, err = Files.AfterInsertHooks.RunHooks(ctx, exec, o)
|
||||
case bob.QueryTypeUpdate:
|
||||
ctx, err = Files.AfterUpdateHooks.RunHooks(ctx, exec, o)
|
||||
case bob.QueryTypeDelete:
|
||||
ctx, err = Files.AfterDeleteHooks.RunHooks(ctx, exec, o)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (o FileSlice) pkIN() dialect.Expression {
|
||||
if len(o) == 0 {
|
||||
return sqlite.Raw("NULL")
|
||||
}
|
||||
|
||||
return sqlite.Quote("file", "id").In(bob.ExpressionFunc(func(ctx context.Context, w io.Writer, d bob.Dialect, start int) ([]any, error) {
|
||||
pkPairs := make([]bob.Expression, len(o))
|
||||
for i, row := range o {
|
||||
pkPairs[i] = row.PrimaryKeyVals()
|
||||
}
|
||||
return bob.ExpressSlice(ctx, w, d, start, pkPairs, "", ", ", "")
|
||||
}))
|
||||
}
|
||||
|
||||
// copyMatchingRows finds models in the given slice that have the same primary key
|
||||
// then it first copies the existing relationships from the old model to the new model
|
||||
// and then replaces the old model in the slice with the new model
|
||||
func (o FileSlice) copyMatchingRows(from ...*File) {
|
||||
for i, old := range o {
|
||||
for _, new := range from {
|
||||
if new.ID != old.ID {
|
||||
continue
|
||||
}
|
||||
new.R = old.R
|
||||
o[i] = new
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateMod modifies an update query with "WHERE primary_key IN (o...)"
|
||||
func (o FileSlice) UpdateMod() bob.Mod[*dialect.UpdateQuery] {
|
||||
return bob.ModFunc[*dialect.UpdateQuery](func(q *dialect.UpdateQuery) {
|
||||
q.AppendHooks(func(ctx context.Context, exec bob.Executor) (context.Context, error) {
|
||||
return Files.BeforeUpdateHooks.RunHooks(ctx, exec, o)
|
||||
})
|
||||
|
||||
q.AppendLoader(bob.LoaderFunc(func(ctx context.Context, exec bob.Executor, retrieved any) error {
|
||||
var err error
|
||||
switch retrieved := retrieved.(type) {
|
||||
case *File:
|
||||
o.copyMatchingRows(retrieved)
|
||||
case []*File:
|
||||
o.copyMatchingRows(retrieved...)
|
||||
case FileSlice:
|
||||
o.copyMatchingRows(retrieved...)
|
||||
default:
|
||||
// If the retrieved value is not a File or a slice of File
|
||||
// then run the AfterUpdateHooks on the slice
|
||||
_, err = Files.AfterUpdateHooks.RunHooks(ctx, exec, o)
|
||||
}
|
||||
|
||||
return err
|
||||
}))
|
||||
|
||||
q.AppendWhere(o.pkIN())
|
||||
})
|
||||
}
|
||||
|
||||
// DeleteMod modifies an delete query with "WHERE primary_key IN (o...)"
|
||||
func (o FileSlice) DeleteMod() bob.Mod[*dialect.DeleteQuery] {
|
||||
return bob.ModFunc[*dialect.DeleteQuery](func(q *dialect.DeleteQuery) {
|
||||
q.AppendHooks(func(ctx context.Context, exec bob.Executor) (context.Context, error) {
|
||||
return Files.BeforeDeleteHooks.RunHooks(ctx, exec, o)
|
||||
})
|
||||
|
||||
q.AppendLoader(bob.LoaderFunc(func(ctx context.Context, exec bob.Executor, retrieved any) error {
|
||||
var err error
|
||||
switch retrieved := retrieved.(type) {
|
||||
case *File:
|
||||
o.copyMatchingRows(retrieved)
|
||||
case []*File:
|
||||
o.copyMatchingRows(retrieved...)
|
||||
case FileSlice:
|
||||
o.copyMatchingRows(retrieved...)
|
||||
default:
|
||||
// If the retrieved value is not a File or a slice of File
|
||||
// then run the AfterDeleteHooks on the slice
|
||||
_, err = Files.AfterDeleteHooks.RunHooks(ctx, exec, o)
|
||||
}
|
||||
|
||||
return err
|
||||
}))
|
||||
|
||||
q.AppendWhere(o.pkIN())
|
||||
})
|
||||
}
|
||||
|
||||
func (o FileSlice) UpdateAll(ctx context.Context, exec bob.Executor, vals FileSetter) error {
|
||||
if len(o) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err := Files.Update(vals.UpdateMod(), o.UpdateMod()).All(ctx, exec)
|
||||
return err
|
||||
}
|
||||
|
||||
func (o FileSlice) DeleteAll(ctx context.Context, exec bob.Executor) error {
|
||||
if len(o) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err := Files.Delete(o.DeleteMod()).Exec(ctx, exec)
|
||||
return err
|
||||
}
|
||||
|
||||
func (o FileSlice) ReloadAll(ctx context.Context, exec bob.Executor) error {
|
||||
if len(o) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
o2, err := Files.Query(sm.Where(o.pkIN())).All(ctx, exec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
o.copyMatchingRows(o2...)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type fileJoins[Q dialect.Joinable] struct {
|
||||
typ string
|
||||
User func(context.Context) modAs[Q, userColumns]
|
||||
ProfilePictureUsers func(context.Context) modAs[Q, userColumns]
|
||||
}
|
||||
|
||||
func (j fileJoins[Q]) aliasedAs(alias string) fileJoins[Q] {
|
||||
return buildFileJoins[Q](buildFileColumns(alias), j.typ)
|
||||
}
|
||||
|
||||
func buildFileJoins[Q dialect.Joinable](cols fileColumns, typ string) fileJoins[Q] {
|
||||
return fileJoins[Q]{
|
||||
typ: typ,
|
||||
User: filesJoinUser[Q](cols, typ),
|
||||
ProfilePictureUsers: filesJoinProfilePictureUsers[Q](cols, typ),
|
||||
}
|
||||
}
|
||||
|
||||
func filesJoinUser[Q dialect.Joinable](from fileColumns, typ string) func(context.Context) modAs[Q, userColumns] {
|
||||
return func(ctx context.Context) modAs[Q, userColumns] {
|
||||
return modAs[Q, userColumns]{
|
||||
c: UserColumns,
|
||||
f: func(to userColumns) bob.Mod[Q] {
|
||||
mods := make(mods.QueryMods[Q], 0, 1)
|
||||
|
||||
{
|
||||
mods = append(mods, dialect.Join[Q](typ, Users.Name().As(to.Alias())).On(
|
||||
to.ID.EQ(from.UserID),
|
||||
))
|
||||
}
|
||||
|
||||
return mods
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func filesJoinProfilePictureUsers[Q dialect.Joinable](from fileColumns, typ string) func(context.Context) modAs[Q, userColumns] {
|
||||
return func(ctx context.Context) modAs[Q, userColumns] {
|
||||
return modAs[Q, userColumns]{
|
||||
c: UserColumns,
|
||||
f: func(to userColumns) bob.Mod[Q] {
|
||||
mods := make(mods.QueryMods[Q], 0, 1)
|
||||
|
||||
{
|
||||
mods = append(mods, dialect.Join[Q](typ, Users.Name().As(to.Alias())).On(
|
||||
to.ProfilePictureID.EQ(from.ID),
|
||||
))
|
||||
}
|
||||
|
||||
return mods
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// User starts a query for related objects on user
|
||||
func (o *File) User(mods ...bob.Mod[*dialect.SelectQuery]) UsersQuery {
|
||||
return Users.Query(append(mods,
|
||||
sm.Where(UserColumns.ID.EQ(sqlite.Arg(o.UserID))),
|
||||
)...)
|
||||
}
|
||||
|
||||
func (os FileSlice) User(mods ...bob.Mod[*dialect.SelectQuery]) UsersQuery {
|
||||
PKArgs := make([]bob.Expression, len(os))
|
||||
for i, o := range os {
|
||||
PKArgs[i] = sqlite.ArgGroup(o.UserID)
|
||||
}
|
||||
|
||||
return Users.Query(append(mods,
|
||||
sm.Where(sqlite.Group(UserColumns.ID).In(PKArgs...)),
|
||||
)...)
|
||||
}
|
||||
|
||||
// ProfilePictureUsers starts a query for related objects on user
|
||||
func (o *File) ProfilePictureUsers(mods ...bob.Mod[*dialect.SelectQuery]) UsersQuery {
|
||||
return Users.Query(append(mods,
|
||||
sm.Where(UserColumns.ProfilePictureID.EQ(sqlite.Arg(o.ID))),
|
||||
)...)
|
||||
}
|
||||
|
||||
func (os FileSlice) ProfilePictureUsers(mods ...bob.Mod[*dialect.SelectQuery]) UsersQuery {
|
||||
PKArgs := make([]bob.Expression, len(os))
|
||||
for i, o := range os {
|
||||
PKArgs[i] = sqlite.ArgGroup(o.ID)
|
||||
}
|
||||
|
||||
return Users.Query(append(mods,
|
||||
sm.Where(sqlite.Group(UserColumns.ProfilePictureID).In(PKArgs...)),
|
||||
)...)
|
||||
}
|
||||
|
||||
func (o *File) Preload(name string, retrieved any) error {
|
||||
if o == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch name {
|
||||
case "User":
|
||||
rel, ok := retrieved.(*User)
|
||||
if !ok {
|
||||
return fmt.Errorf("file cannot load %T as %q", retrieved, name)
|
||||
}
|
||||
|
||||
o.R.User = rel
|
||||
|
||||
if rel != nil {
|
||||
rel.R.Files = FileSlice{o}
|
||||
}
|
||||
return nil
|
||||
case "ProfilePictureUsers":
|
||||
rels, ok := retrieved.(UserSlice)
|
||||
if !ok {
|
||||
return fmt.Errorf("file cannot load %T as %q", retrieved, name)
|
||||
}
|
||||
|
||||
o.R.ProfilePictureUsers = rels
|
||||
|
||||
for _, rel := range rels {
|
||||
if rel != nil {
|
||||
rel.R.ProfilePictureFile = o
|
||||
}
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("file has no relationship %q", name)
|
||||
}
|
||||
}
|
||||
|
||||
func PreloadFileUser(opts ...sqlite.PreloadOption) sqlite.Preloader {
|
||||
return sqlite.Preload[*User, UserSlice](orm.Relationship{
|
||||
Name: "User",
|
||||
Sides: []orm.RelSide{
|
||||
{
|
||||
From: TableNames.Files,
|
||||
To: TableNames.Users,
|
||||
FromColumns: []string{
|
||||
ColumnNames.Files.UserID,
|
||||
},
|
||||
ToColumns: []string{
|
||||
ColumnNames.Users.ID,
|
||||
},
|
||||
},
|
||||
},
|
||||
}, Users.Columns().Names(), opts...)
|
||||
}
|
||||
|
||||
func ThenLoadFileUser(queryMods ...bob.Mod[*dialect.SelectQuery]) sqlite.Loader {
|
||||
return sqlite.Loader(func(ctx context.Context, exec bob.Executor, retrieved any) error {
|
||||
loader, isLoader := retrieved.(interface {
|
||||
LoadFileUser(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error
|
||||
})
|
||||
if !isLoader {
|
||||
return fmt.Errorf("object %T cannot load FileUser", retrieved)
|
||||
}
|
||||
|
||||
err := loader.LoadFileUser(ctx, exec, queryMods...)
|
||||
|
||||
// Don't cause an issue due to missing relationships
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
// LoadFileUser loads the file's User into the .R struct
|
||||
func (o *File) LoadFileUser(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
|
||||
if o == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Reset the relationship
|
||||
o.R.User = nil
|
||||
|
||||
related, err := o.User(mods...).One(ctx, exec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
related.R.Files = FileSlice{o}
|
||||
|
||||
o.R.User = related
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadFileUser loads the file's User into the .R struct
|
||||
func (os FileSlice) LoadFileUser(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
|
||||
if len(os) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
users, err := os.User(mods...).All(ctx, exec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, o := range os {
|
||||
for _, rel := range users {
|
||||
if o.UserID != rel.ID {
|
||||
continue
|
||||
}
|
||||
|
||||
rel.R.Files = append(rel.R.Files, o)
|
||||
|
||||
o.R.User = rel
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func ThenLoadFileProfilePictureUsers(queryMods ...bob.Mod[*dialect.SelectQuery]) sqlite.Loader {
|
||||
return sqlite.Loader(func(ctx context.Context, exec bob.Executor, retrieved any) error {
|
||||
loader, isLoader := retrieved.(interface {
|
||||
LoadFileProfilePictureUsers(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error
|
||||
})
|
||||
if !isLoader {
|
||||
return fmt.Errorf("object %T cannot load FileProfilePictureUsers", retrieved)
|
||||
}
|
||||
|
||||
err := loader.LoadFileProfilePictureUsers(ctx, exec, queryMods...)
|
||||
|
||||
// Don't cause an issue due to missing relationships
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
// LoadFileProfilePictureUsers loads the file's ProfilePictureUsers into the .R struct
|
||||
func (o *File) LoadFileProfilePictureUsers(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
|
||||
if o == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Reset the relationship
|
||||
o.R.ProfilePictureUsers = nil
|
||||
|
||||
related, err := o.ProfilePictureUsers(mods...).All(ctx, exec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, rel := range related {
|
||||
rel.R.ProfilePictureFile = o
|
||||
}
|
||||
|
||||
o.R.ProfilePictureUsers = related
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadFileProfilePictureUsers loads the file's ProfilePictureUsers into the .R struct
|
||||
func (os FileSlice) LoadFileProfilePictureUsers(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
|
||||
if len(os) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
users, err := os.ProfilePictureUsers(mods...).All(ctx, exec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, o := range os {
|
||||
o.R.ProfilePictureUsers = nil
|
||||
}
|
||||
|
||||
for _, o := range os {
|
||||
for _, rel := range users {
|
||||
if o.ID != rel.ProfilePictureID.GetOrZero() {
|
||||
continue
|
||||
}
|
||||
|
||||
rel.R.ProfilePictureFile = o
|
||||
|
||||
o.R.ProfilePictureUsers = append(o.R.ProfilePictureUsers, rel)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func attachFileUser0(ctx context.Context, exec bob.Executor, count int, file0 *File, user1 *User) (*File, error) {
|
||||
setter := &FileSetter{
|
||||
UserID: omit.From(user1.ID),
|
||||
}
|
||||
|
||||
err := file0.Update(ctx, exec, setter)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("attachFileUser0: %w", err)
|
||||
}
|
||||
|
||||
return file0, nil
|
||||
}
|
||||
|
||||
func (file0 *File) InsertUser(ctx context.Context, exec bob.Executor, related *UserSetter) error {
|
||||
user1, err := Users.Insert(related).One(ctx, exec)
|
||||
if err != nil {
|
||||
return fmt.Errorf("inserting related objects: %w", err)
|
||||
}
|
||||
|
||||
_, err = attachFileUser0(ctx, exec, 1, file0, user1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
file0.R.User = user1
|
||||
|
||||
user1.R.Files = append(user1.R.Files, file0)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (file0 *File) AttachUser(ctx context.Context, exec bob.Executor, user1 *User) error {
|
||||
var err error
|
||||
|
||||
_, err = attachFileUser0(ctx, exec, 1, file0, user1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
file0.R.User = user1
|
||||
|
||||
user1.R.Files = append(user1.R.Files, file0)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func insertFileProfilePictureUsers0(ctx context.Context, exec bob.Executor, users1 []*UserSetter, file0 *File) (UserSlice, error) {
|
||||
for i := range users1 {
|
||||
users1[i].ProfilePictureID = omitnull.From(file0.ID)
|
||||
}
|
||||
|
||||
ret, err := Users.Insert(bob.ToMods(users1...)).All(ctx, exec)
|
||||
if err != nil {
|
||||
return ret, fmt.Errorf("insertFileProfilePictureUsers0: %w", err)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func attachFileProfilePictureUsers0(ctx context.Context, exec bob.Executor, count int, users1 UserSlice, file0 *File) (UserSlice, error) {
|
||||
setter := &UserSetter{
|
||||
ProfilePictureID: omitnull.From(file0.ID),
|
||||
}
|
||||
|
||||
err := users1.UpdateAll(ctx, exec, *setter)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("attachFileProfilePictureUsers0: %w", err)
|
||||
}
|
||||
|
||||
return users1, nil
|
||||
}
|
||||
|
||||
func (file0 *File) InsertProfilePictureUsers(ctx context.Context, exec bob.Executor, related ...*UserSetter) error {
|
||||
if len(related) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
users1, err := insertFileProfilePictureUsers0(ctx, exec, related, file0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
file0.R.ProfilePictureUsers = append(file0.R.ProfilePictureUsers, users1...)
|
||||
|
||||
for _, rel := range users1 {
|
||||
rel.R.ProfilePictureFile = file0
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (file0 *File) AttachProfilePictureUsers(ctx context.Context, exec bob.Executor, related ...*User) error {
|
||||
if len(related) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var err error
|
||||
users1 := UserSlice(related)
|
||||
|
||||
_, err = attachFileProfilePictureUsers0(ctx, exec, len(related), users1, file0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
file0.R.ProfilePictureUsers = append(file0.R.ProfilePictureUsers, users1...)
|
||||
|
||||
for _, rel := range related {
|
||||
rel.R.ProfilePictureFile = file0
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -1,732 +0,0 @@
|
||||
// Code generated by BobGen sql (devel). DO NOT EDIT.
|
||||
// This file is meant to be re-generated in place and/or deleted at any time.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/aarondl/opt/omit"
|
||||
"github.com/stephenafamo/bob"
|
||||
"github.com/stephenafamo/bob/dialect/sqlite"
|
||||
"github.com/stephenafamo/bob/dialect/sqlite/dialect"
|
||||
"github.com/stephenafamo/bob/dialect/sqlite/dm"
|
||||
"github.com/stephenafamo/bob/dialect/sqlite/sm"
|
||||
"github.com/stephenafamo/bob/dialect/sqlite/um"
|
||||
"github.com/stephenafamo/bob/expr"
|
||||
"github.com/stephenafamo/bob/mods"
|
||||
"github.com/stephenafamo/bob/orm"
|
||||
)
|
||||
|
||||
// Item is an object representing the database table.
|
||||
type Item struct {
|
||||
ID int64 `db:"id,pk" `
|
||||
Name string `db:"name" `
|
||||
Added time.Time `db:"added" `
|
||||
Description string `db:"description" `
|
||||
Price float32 `db:"price" `
|
||||
Quantity int64 `db:"quantity" `
|
||||
UserID int64 `db:"user_id" `
|
||||
|
||||
R itemR `db:"-" `
|
||||
}
|
||||
|
||||
// ItemSlice is an alias for a slice of pointers to Item.
|
||||
// This should almost always be used instead of []*Item.
|
||||
type ItemSlice []*Item
|
||||
|
||||
// Items contains methods to work with the item table
|
||||
var Items = sqlite.NewTablex[*Item, ItemSlice, *ItemSetter]("", "item")
|
||||
|
||||
// ItemsQuery is a query on the item table
|
||||
type ItemsQuery = *sqlite.ViewQuery[*Item, ItemSlice]
|
||||
|
||||
// itemR is where relationships are stored.
|
||||
type itemR struct {
|
||||
User *User // fk_item_0
|
||||
}
|
||||
|
||||
type itemColumnNames struct {
|
||||
ID string
|
||||
Name string
|
||||
Added string
|
||||
Description string
|
||||
Price string
|
||||
Quantity string
|
||||
UserID string
|
||||
}
|
||||
|
||||
var ItemColumns = buildItemColumns("item")
|
||||
|
||||
type itemColumns struct {
|
||||
tableAlias string
|
||||
ID sqlite.Expression
|
||||
Name sqlite.Expression
|
||||
Added sqlite.Expression
|
||||
Description sqlite.Expression
|
||||
Price sqlite.Expression
|
||||
Quantity sqlite.Expression
|
||||
UserID sqlite.Expression
|
||||
}
|
||||
|
||||
func (c itemColumns) Alias() string {
|
||||
return c.tableAlias
|
||||
}
|
||||
|
||||
func (itemColumns) AliasedAs(alias string) itemColumns {
|
||||
return buildItemColumns(alias)
|
||||
}
|
||||
|
||||
func buildItemColumns(alias string) itemColumns {
|
||||
return itemColumns{
|
||||
tableAlias: alias,
|
||||
ID: sqlite.Quote(alias, "id"),
|
||||
Name: sqlite.Quote(alias, "name"),
|
||||
Added: sqlite.Quote(alias, "added"),
|
||||
Description: sqlite.Quote(alias, "description"),
|
||||
Price: sqlite.Quote(alias, "price"),
|
||||
Quantity: sqlite.Quote(alias, "quantity"),
|
||||
UserID: sqlite.Quote(alias, "user_id"),
|
||||
}
|
||||
}
|
||||
|
||||
type itemWhere[Q sqlite.Filterable] struct {
|
||||
ID sqlite.WhereMod[Q, int64]
|
||||
Name sqlite.WhereMod[Q, string]
|
||||
Added sqlite.WhereMod[Q, time.Time]
|
||||
Description sqlite.WhereMod[Q, string]
|
||||
Price sqlite.WhereMod[Q, float32]
|
||||
Quantity sqlite.WhereMod[Q, int64]
|
||||
UserID sqlite.WhereMod[Q, int64]
|
||||
}
|
||||
|
||||
func (itemWhere[Q]) AliasedAs(alias string) itemWhere[Q] {
|
||||
return buildItemWhere[Q](buildItemColumns(alias))
|
||||
}
|
||||
|
||||
func buildItemWhere[Q sqlite.Filterable](cols itemColumns) itemWhere[Q] {
|
||||
return itemWhere[Q]{
|
||||
ID: sqlite.Where[Q, int64](cols.ID),
|
||||
Name: sqlite.Where[Q, string](cols.Name),
|
||||
Added: sqlite.Where[Q, time.Time](cols.Added),
|
||||
Description: sqlite.Where[Q, string](cols.Description),
|
||||
Price: sqlite.Where[Q, float32](cols.Price),
|
||||
Quantity: sqlite.Where[Q, int64](cols.Quantity),
|
||||
UserID: sqlite.Where[Q, int64](cols.UserID),
|
||||
}
|
||||
}
|
||||
|
||||
var ItemErrors = &itemErrors{
|
||||
ErrUniquePkMainItem: &UniqueConstraintError{s: "pk_main_item"},
|
||||
}
|
||||
|
||||
type itemErrors struct {
|
||||
ErrUniquePkMainItem *UniqueConstraintError
|
||||
}
|
||||
|
||||
// ItemSetter is used for insert/upsert/update operations
|
||||
// All values are optional, and do not have to be set
|
||||
// Generated columns are not included
|
||||
type ItemSetter struct {
|
||||
ID omit.Val[int64] `db:"id,pk" `
|
||||
Name omit.Val[string] `db:"name" `
|
||||
Added omit.Val[time.Time] `db:"added" `
|
||||
Description omit.Val[string] `db:"description" `
|
||||
Price omit.Val[float32] `db:"price" `
|
||||
Quantity omit.Val[int64] `db:"quantity" `
|
||||
UserID omit.Val[int64] `db:"user_id" `
|
||||
}
|
||||
|
||||
func (s ItemSetter) SetColumns() []string {
|
||||
vals := make([]string, 0, 7)
|
||||
if !s.ID.IsUnset() {
|
||||
vals = append(vals, "id")
|
||||
}
|
||||
|
||||
if !s.Name.IsUnset() {
|
||||
vals = append(vals, "name")
|
||||
}
|
||||
|
||||
if !s.Added.IsUnset() {
|
||||
vals = append(vals, "added")
|
||||
}
|
||||
|
||||
if !s.Description.IsUnset() {
|
||||
vals = append(vals, "description")
|
||||
}
|
||||
|
||||
if !s.Price.IsUnset() {
|
||||
vals = append(vals, "price")
|
||||
}
|
||||
|
||||
if !s.Quantity.IsUnset() {
|
||||
vals = append(vals, "quantity")
|
||||
}
|
||||
|
||||
if !s.UserID.IsUnset() {
|
||||
vals = append(vals, "user_id")
|
||||
}
|
||||
|
||||
return vals
|
||||
}
|
||||
|
||||
func (s ItemSetter) Overwrite(t *Item) {
|
||||
if !s.ID.IsUnset() {
|
||||
t.ID, _ = s.ID.Get()
|
||||
}
|
||||
if !s.Name.IsUnset() {
|
||||
t.Name, _ = s.Name.Get()
|
||||
}
|
||||
if !s.Added.IsUnset() {
|
||||
t.Added, _ = s.Added.Get()
|
||||
}
|
||||
if !s.Description.IsUnset() {
|
||||
t.Description, _ = s.Description.Get()
|
||||
}
|
||||
if !s.Price.IsUnset() {
|
||||
t.Price, _ = s.Price.Get()
|
||||
}
|
||||
if !s.Quantity.IsUnset() {
|
||||
t.Quantity, _ = s.Quantity.Get()
|
||||
}
|
||||
if !s.UserID.IsUnset() {
|
||||
t.UserID, _ = s.UserID.Get()
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ItemSetter) Apply(q *dialect.InsertQuery) {
|
||||
q.AppendHooks(func(ctx context.Context, exec bob.Executor) (context.Context, error) {
|
||||
return Items.BeforeInsertHooks.RunHooks(ctx, exec, s)
|
||||
})
|
||||
|
||||
if len(q.Table.Columns) == 0 {
|
||||
q.Table.Columns = s.SetColumns()
|
||||
}
|
||||
|
||||
q.AppendValues(bob.ExpressionFunc(func(ctx context.Context, w io.Writer, d bob.Dialect, start int) ([]any, error) {
|
||||
vals := make([]bob.Expression, 0, 7)
|
||||
if !s.ID.IsUnset() {
|
||||
vals = append(vals, sqlite.Arg(s.ID))
|
||||
}
|
||||
|
||||
if !s.Name.IsUnset() {
|
||||
vals = append(vals, sqlite.Arg(s.Name))
|
||||
}
|
||||
|
||||
if !s.Added.IsUnset() {
|
||||
vals = append(vals, sqlite.Arg(s.Added))
|
||||
}
|
||||
|
||||
if !s.Description.IsUnset() {
|
||||
vals = append(vals, sqlite.Arg(s.Description))
|
||||
}
|
||||
|
||||
if !s.Price.IsUnset() {
|
||||
vals = append(vals, sqlite.Arg(s.Price))
|
||||
}
|
||||
|
||||
if !s.Quantity.IsUnset() {
|
||||
vals = append(vals, sqlite.Arg(s.Quantity))
|
||||
}
|
||||
|
||||
if !s.UserID.IsUnset() {
|
||||
vals = append(vals, sqlite.Arg(s.UserID))
|
||||
}
|
||||
|
||||
return bob.ExpressSlice(ctx, w, d, start, vals, "", ", ", "")
|
||||
}))
|
||||
}
|
||||
|
||||
func (s ItemSetter) UpdateMod() bob.Mod[*dialect.UpdateQuery] {
|
||||
return um.Set(s.Expressions()...)
|
||||
}
|
||||
|
||||
func (s ItemSetter) Expressions(prefix ...string) []bob.Expression {
|
||||
exprs := make([]bob.Expression, 0, 7)
|
||||
|
||||
if !s.ID.IsUnset() {
|
||||
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
|
||||
sqlite.Quote(append(prefix, "id")...),
|
||||
sqlite.Arg(s.ID),
|
||||
}})
|
||||
}
|
||||
|
||||
if !s.Name.IsUnset() {
|
||||
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
|
||||
sqlite.Quote(append(prefix, "name")...),
|
||||
sqlite.Arg(s.Name),
|
||||
}})
|
||||
}
|
||||
|
||||
if !s.Added.IsUnset() {
|
||||
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
|
||||
sqlite.Quote(append(prefix, "added")...),
|
||||
sqlite.Arg(s.Added),
|
||||
}})
|
||||
}
|
||||
|
||||
if !s.Description.IsUnset() {
|
||||
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
|
||||
sqlite.Quote(append(prefix, "description")...),
|
||||
sqlite.Arg(s.Description),
|
||||
}})
|
||||
}
|
||||
|
||||
if !s.Price.IsUnset() {
|
||||
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
|
||||
sqlite.Quote(append(prefix, "price")...),
|
||||
sqlite.Arg(s.Price),
|
||||
}})
|
||||
}
|
||||
|
||||
if !s.Quantity.IsUnset() {
|
||||
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
|
||||
sqlite.Quote(append(prefix, "quantity")...),
|
||||
sqlite.Arg(s.Quantity),
|
||||
}})
|
||||
}
|
||||
|
||||
if !s.UserID.IsUnset() {
|
||||
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
|
||||
sqlite.Quote(append(prefix, "user_id")...),
|
||||
sqlite.Arg(s.UserID),
|
||||
}})
|
||||
}
|
||||
|
||||
return exprs
|
||||
}
|
||||
|
||||
// FindItem retrieves a single record by primary key
|
||||
// If cols is empty Find will return all columns.
|
||||
func FindItem(ctx context.Context, exec bob.Executor, IDPK int64, cols ...string) (*Item, error) {
|
||||
if len(cols) == 0 {
|
||||
return Items.Query(
|
||||
SelectWhere.Items.ID.EQ(IDPK),
|
||||
).One(ctx, exec)
|
||||
}
|
||||
|
||||
return Items.Query(
|
||||
SelectWhere.Items.ID.EQ(IDPK),
|
||||
sm.Columns(Items.Columns().Only(cols...)),
|
||||
).One(ctx, exec)
|
||||
}
|
||||
|
||||
// ItemExists checks the presence of a single record by primary key
|
||||
func ItemExists(ctx context.Context, exec bob.Executor, IDPK int64) (bool, error) {
|
||||
return Items.Query(
|
||||
SelectWhere.Items.ID.EQ(IDPK),
|
||||
).Exists(ctx, exec)
|
||||
}
|
||||
|
||||
// AfterQueryHook is called after Item is retrieved from the database
|
||||
func (o *Item) AfterQueryHook(ctx context.Context, exec bob.Executor, queryType bob.QueryType) error {
|
||||
var err error
|
||||
|
||||
switch queryType {
|
||||
case bob.QueryTypeSelect:
|
||||
ctx, err = Items.AfterSelectHooks.RunHooks(ctx, exec, ItemSlice{o})
|
||||
case bob.QueryTypeInsert:
|
||||
ctx, err = Items.AfterInsertHooks.RunHooks(ctx, exec, ItemSlice{o})
|
||||
case bob.QueryTypeUpdate:
|
||||
ctx, err = Items.AfterUpdateHooks.RunHooks(ctx, exec, ItemSlice{o})
|
||||
case bob.QueryTypeDelete:
|
||||
ctx, err = Items.AfterDeleteHooks.RunHooks(ctx, exec, ItemSlice{o})
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// PrimaryKeyVals returns the primary key values of the Item
|
||||
func (o *Item) PrimaryKeyVals() bob.Expression {
|
||||
return sqlite.Arg(o.ID)
|
||||
}
|
||||
|
||||
func (o *Item) pkEQ() dialect.Expression {
|
||||
return sqlite.Quote("item", "id").EQ(bob.ExpressionFunc(func(ctx context.Context, w io.Writer, d bob.Dialect, start int) ([]any, error) {
|
||||
return o.PrimaryKeyVals().WriteSQL(ctx, w, d, start)
|
||||
}))
|
||||
}
|
||||
|
||||
// Update uses an executor to update the Item
|
||||
func (o *Item) Update(ctx context.Context, exec bob.Executor, s *ItemSetter) error {
|
||||
v, err := Items.Update(s.UpdateMod(), um.Where(o.pkEQ())).One(ctx, exec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
o.R = v.R
|
||||
*o = *v
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Delete deletes a single Item record with an executor
|
||||
func (o *Item) Delete(ctx context.Context, exec bob.Executor) error {
|
||||
_, err := Items.Delete(dm.Where(o.pkEQ())).Exec(ctx, exec)
|
||||
return err
|
||||
}
|
||||
|
||||
// Reload refreshes the Item using the executor
|
||||
func (o *Item) Reload(ctx context.Context, exec bob.Executor) error {
|
||||
o2, err := Items.Query(
|
||||
SelectWhere.Items.ID.EQ(o.ID),
|
||||
).One(ctx, exec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o2.R = o.R
|
||||
*o = *o2
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AfterQueryHook is called after ItemSlice is retrieved from the database
|
||||
func (o ItemSlice) AfterQueryHook(ctx context.Context, exec bob.Executor, queryType bob.QueryType) error {
|
||||
var err error
|
||||
|
||||
switch queryType {
|
||||
case bob.QueryTypeSelect:
|
||||
ctx, err = Items.AfterSelectHooks.RunHooks(ctx, exec, o)
|
||||
case bob.QueryTypeInsert:
|
||||
ctx, err = Items.AfterInsertHooks.RunHooks(ctx, exec, o)
|
||||
case bob.QueryTypeUpdate:
|
||||
ctx, err = Items.AfterUpdateHooks.RunHooks(ctx, exec, o)
|
||||
case bob.QueryTypeDelete:
|
||||
ctx, err = Items.AfterDeleteHooks.RunHooks(ctx, exec, o)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (o ItemSlice) pkIN() dialect.Expression {
|
||||
if len(o) == 0 {
|
||||
return sqlite.Raw("NULL")
|
||||
}
|
||||
|
||||
return sqlite.Quote("item", "id").In(bob.ExpressionFunc(func(ctx context.Context, w io.Writer, d bob.Dialect, start int) ([]any, error) {
|
||||
pkPairs := make([]bob.Expression, len(o))
|
||||
for i, row := range o {
|
||||
pkPairs[i] = row.PrimaryKeyVals()
|
||||
}
|
||||
return bob.ExpressSlice(ctx, w, d, start, pkPairs, "", ", ", "")
|
||||
}))
|
||||
}
|
||||
|
||||
// copyMatchingRows finds models in the given slice that have the same primary key
|
||||
// then it first copies the existing relationships from the old model to the new model
|
||||
// and then replaces the old model in the slice with the new model
|
||||
func (o ItemSlice) copyMatchingRows(from ...*Item) {
|
||||
for i, old := range o {
|
||||
for _, new := range from {
|
||||
if new.ID != old.ID {
|
||||
continue
|
||||
}
|
||||
new.R = old.R
|
||||
o[i] = new
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateMod modifies an update query with "WHERE primary_key IN (o...)"
|
||||
func (o ItemSlice) UpdateMod() bob.Mod[*dialect.UpdateQuery] {
|
||||
return bob.ModFunc[*dialect.UpdateQuery](func(q *dialect.UpdateQuery) {
|
||||
q.AppendHooks(func(ctx context.Context, exec bob.Executor) (context.Context, error) {
|
||||
return Items.BeforeUpdateHooks.RunHooks(ctx, exec, o)
|
||||
})
|
||||
|
||||
q.AppendLoader(bob.LoaderFunc(func(ctx context.Context, exec bob.Executor, retrieved any) error {
|
||||
var err error
|
||||
switch retrieved := retrieved.(type) {
|
||||
case *Item:
|
||||
o.copyMatchingRows(retrieved)
|
||||
case []*Item:
|
||||
o.copyMatchingRows(retrieved...)
|
||||
case ItemSlice:
|
||||
o.copyMatchingRows(retrieved...)
|
||||
default:
|
||||
// If the retrieved value is not a Item or a slice of Item
|
||||
// then run the AfterUpdateHooks on the slice
|
||||
_, err = Items.AfterUpdateHooks.RunHooks(ctx, exec, o)
|
||||
}
|
||||
|
||||
return err
|
||||
}))
|
||||
|
||||
q.AppendWhere(o.pkIN())
|
||||
})
|
||||
}
|
||||
|
||||
// DeleteMod modifies an delete query with "WHERE primary_key IN (o...)"
|
||||
func (o ItemSlice) DeleteMod() bob.Mod[*dialect.DeleteQuery] {
|
||||
return bob.ModFunc[*dialect.DeleteQuery](func(q *dialect.DeleteQuery) {
|
||||
q.AppendHooks(func(ctx context.Context, exec bob.Executor) (context.Context, error) {
|
||||
return Items.BeforeDeleteHooks.RunHooks(ctx, exec, o)
|
||||
})
|
||||
|
||||
q.AppendLoader(bob.LoaderFunc(func(ctx context.Context, exec bob.Executor, retrieved any) error {
|
||||
var err error
|
||||
switch retrieved := retrieved.(type) {
|
||||
case *Item:
|
||||
o.copyMatchingRows(retrieved)
|
||||
case []*Item:
|
||||
o.copyMatchingRows(retrieved...)
|
||||
case ItemSlice:
|
||||
o.copyMatchingRows(retrieved...)
|
||||
default:
|
||||
// If the retrieved value is not a Item or a slice of Item
|
||||
// then run the AfterDeleteHooks on the slice
|
||||
_, err = Items.AfterDeleteHooks.RunHooks(ctx, exec, o)
|
||||
}
|
||||
|
||||
return err
|
||||
}))
|
||||
|
||||
q.AppendWhere(o.pkIN())
|
||||
})
|
||||
}
|
||||
|
||||
func (o ItemSlice) UpdateAll(ctx context.Context, exec bob.Executor, vals ItemSetter) error {
|
||||
if len(o) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err := Items.Update(vals.UpdateMod(), o.UpdateMod()).All(ctx, exec)
|
||||
return err
|
||||
}
|
||||
|
||||
func (o ItemSlice) DeleteAll(ctx context.Context, exec bob.Executor) error {
|
||||
if len(o) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err := Items.Delete(o.DeleteMod()).Exec(ctx, exec)
|
||||
return err
|
||||
}
|
||||
|
||||
func (o ItemSlice) ReloadAll(ctx context.Context, exec bob.Executor) error {
|
||||
if len(o) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
o2, err := Items.Query(sm.Where(o.pkIN())).All(ctx, exec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
o.copyMatchingRows(o2...)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type itemJoins[Q dialect.Joinable] struct {
|
||||
typ string
|
||||
User func(context.Context) modAs[Q, userColumns]
|
||||
}
|
||||
|
||||
func (j itemJoins[Q]) aliasedAs(alias string) itemJoins[Q] {
|
||||
return buildItemJoins[Q](buildItemColumns(alias), j.typ)
|
||||
}
|
||||
|
||||
func buildItemJoins[Q dialect.Joinable](cols itemColumns, typ string) itemJoins[Q] {
|
||||
return itemJoins[Q]{
|
||||
typ: typ,
|
||||
User: itemsJoinUser[Q](cols, typ),
|
||||
}
|
||||
}
|
||||
|
||||
func itemsJoinUser[Q dialect.Joinable](from itemColumns, typ string) func(context.Context) modAs[Q, userColumns] {
|
||||
return func(ctx context.Context) modAs[Q, userColumns] {
|
||||
return modAs[Q, userColumns]{
|
||||
c: UserColumns,
|
||||
f: func(to userColumns) bob.Mod[Q] {
|
||||
mods := make(mods.QueryMods[Q], 0, 1)
|
||||
|
||||
{
|
||||
mods = append(mods, dialect.Join[Q](typ, Users.Name().As(to.Alias())).On(
|
||||
to.ID.EQ(from.UserID),
|
||||
))
|
||||
}
|
||||
|
||||
return mods
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// User starts a query for related objects on user
|
||||
func (o *Item) User(mods ...bob.Mod[*dialect.SelectQuery]) UsersQuery {
|
||||
return Users.Query(append(mods,
|
||||
sm.Where(UserColumns.ID.EQ(sqlite.Arg(o.UserID))),
|
||||
)...)
|
||||
}
|
||||
|
||||
func (os ItemSlice) User(mods ...bob.Mod[*dialect.SelectQuery]) UsersQuery {
|
||||
PKArgs := make([]bob.Expression, len(os))
|
||||
for i, o := range os {
|
||||
PKArgs[i] = sqlite.ArgGroup(o.UserID)
|
||||
}
|
||||
|
||||
return Users.Query(append(mods,
|
||||
sm.Where(sqlite.Group(UserColumns.ID).In(PKArgs...)),
|
||||
)...)
|
||||
}
|
||||
|
||||
func (o *Item) Preload(name string, retrieved any) error {
|
||||
if o == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch name {
|
||||
case "User":
|
||||
rel, ok := retrieved.(*User)
|
||||
if !ok {
|
||||
return fmt.Errorf("item cannot load %T as %q", retrieved, name)
|
||||
}
|
||||
|
||||
o.R.User = rel
|
||||
|
||||
if rel != nil {
|
||||
rel.R.Items = ItemSlice{o}
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("item has no relationship %q", name)
|
||||
}
|
||||
}
|
||||
|
||||
func PreloadItemUser(opts ...sqlite.PreloadOption) sqlite.Preloader {
|
||||
return sqlite.Preload[*User, UserSlice](orm.Relationship{
|
||||
Name: "User",
|
||||
Sides: []orm.RelSide{
|
||||
{
|
||||
From: TableNames.Items,
|
||||
To: TableNames.Users,
|
||||
FromColumns: []string{
|
||||
ColumnNames.Items.UserID,
|
||||
},
|
||||
ToColumns: []string{
|
||||
ColumnNames.Users.ID,
|
||||
},
|
||||
},
|
||||
},
|
||||
}, Users.Columns().Names(), opts...)
|
||||
}
|
||||
|
||||
func ThenLoadItemUser(queryMods ...bob.Mod[*dialect.SelectQuery]) sqlite.Loader {
|
||||
return sqlite.Loader(func(ctx context.Context, exec bob.Executor, retrieved any) error {
|
||||
loader, isLoader := retrieved.(interface {
|
||||
LoadItemUser(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error
|
||||
})
|
||||
if !isLoader {
|
||||
return fmt.Errorf("object %T cannot load ItemUser", retrieved)
|
||||
}
|
||||
|
||||
err := loader.LoadItemUser(ctx, exec, queryMods...)
|
||||
|
||||
// Don't cause an issue due to missing relationships
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
// LoadItemUser loads the item's User into the .R struct
|
||||
func (o *Item) LoadItemUser(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
|
||||
if o == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Reset the relationship
|
||||
o.R.User = nil
|
||||
|
||||
related, err := o.User(mods...).One(ctx, exec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
related.R.Items = ItemSlice{o}
|
||||
|
||||
o.R.User = related
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadItemUser loads the item's User into the .R struct
|
||||
func (os ItemSlice) LoadItemUser(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
|
||||
if len(os) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
users, err := os.User(mods...).All(ctx, exec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, o := range os {
|
||||
for _, rel := range users {
|
||||
if o.UserID != rel.ID {
|
||||
continue
|
||||
}
|
||||
|
||||
rel.R.Items = append(rel.R.Items, o)
|
||||
|
||||
o.R.User = rel
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func attachItemUser0(ctx context.Context, exec bob.Executor, count int, item0 *Item, user1 *User) (*Item, error) {
|
||||
setter := &ItemSetter{
|
||||
UserID: omit.From(user1.ID),
|
||||
}
|
||||
|
||||
err := item0.Update(ctx, exec, setter)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("attachItemUser0: %w", err)
|
||||
}
|
||||
|
||||
return item0, nil
|
||||
}
|
||||
|
||||
func (item0 *Item) InsertUser(ctx context.Context, exec bob.Executor, related *UserSetter) error {
|
||||
user1, err := Users.Insert(related).One(ctx, exec)
|
||||
if err != nil {
|
||||
return fmt.Errorf("inserting related objects: %w", err)
|
||||
}
|
||||
|
||||
_, err = attachItemUser0(ctx, exec, 1, item0, user1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
item0.R.User = user1
|
||||
|
||||
user1.R.Items = append(user1.R.Items, item0)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (item0 *Item) AttachUser(ctx context.Context, exec bob.Executor, user1 *User) error {
|
||||
var err error
|
||||
|
||||
_, err = attachItemUser0(ctx, exec, 1, item0, user1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
item0.R.User = user1
|
||||
|
||||
user1.R.Items = append(user1.R.Items, item0)
|
||||
|
||||
return nil
|
||||
}
|
@ -1,361 +0,0 @@
|
||||
// Code generated by BobGen sql (devel). DO NOT EDIT.
|
||||
// This file is meant to be re-generated in place and/or deleted at any time.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
|
||||
"github.com/aarondl/opt/omit"
|
||||
"github.com/stephenafamo/bob"
|
||||
"github.com/stephenafamo/bob/dialect/sqlite"
|
||||
"github.com/stephenafamo/bob/dialect/sqlite/dialect"
|
||||
"github.com/stephenafamo/bob/dialect/sqlite/dm"
|
||||
"github.com/stephenafamo/bob/dialect/sqlite/sm"
|
||||
"github.com/stephenafamo/bob/dialect/sqlite/um"
|
||||
"github.com/stephenafamo/bob/expr"
|
||||
)
|
||||
|
||||
// SchemaMigration is an object representing the database table.
|
||||
type SchemaMigration struct {
|
||||
Version string `db:"version,pk" `
|
||||
}
|
||||
|
||||
// SchemaMigrationSlice is an alias for a slice of pointers to SchemaMigration.
|
||||
// This should almost always be used instead of []*SchemaMigration.
|
||||
type SchemaMigrationSlice []*SchemaMigration
|
||||
|
||||
// SchemaMigrations contains methods to work with the schema_migrations table
|
||||
var SchemaMigrations = sqlite.NewTablex[*SchemaMigration, SchemaMigrationSlice, *SchemaMigrationSetter]("", "schema_migrations")
|
||||
|
||||
// SchemaMigrationsQuery is a query on the schema_migrations table
|
||||
type SchemaMigrationsQuery = *sqlite.ViewQuery[*SchemaMigration, SchemaMigrationSlice]
|
||||
|
||||
type schemaMigrationColumnNames struct {
|
||||
Version string
|
||||
}
|
||||
|
||||
var SchemaMigrationColumns = buildSchemaMigrationColumns("schema_migrations")
|
||||
|
||||
type schemaMigrationColumns struct {
|
||||
tableAlias string
|
||||
Version sqlite.Expression
|
||||
}
|
||||
|
||||
func (c schemaMigrationColumns) Alias() string {
|
||||
return c.tableAlias
|
||||
}
|
||||
|
||||
func (schemaMigrationColumns) AliasedAs(alias string) schemaMigrationColumns {
|
||||
return buildSchemaMigrationColumns(alias)
|
||||
}
|
||||
|
||||
func buildSchemaMigrationColumns(alias string) schemaMigrationColumns {
|
||||
return schemaMigrationColumns{
|
||||
tableAlias: alias,
|
||||
Version: sqlite.Quote(alias, "version"),
|
||||
}
|
||||
}
|
||||
|
||||
type schemaMigrationWhere[Q sqlite.Filterable] struct {
|
||||
Version sqlite.WhereMod[Q, string]
|
||||
}
|
||||
|
||||
func (schemaMigrationWhere[Q]) AliasedAs(alias string) schemaMigrationWhere[Q] {
|
||||
return buildSchemaMigrationWhere[Q](buildSchemaMigrationColumns(alias))
|
||||
}
|
||||
|
||||
func buildSchemaMigrationWhere[Q sqlite.Filterable](cols schemaMigrationColumns) schemaMigrationWhere[Q] {
|
||||
return schemaMigrationWhere[Q]{
|
||||
Version: sqlite.Where[Q, string](cols.Version),
|
||||
}
|
||||
}
|
||||
|
||||
var SchemaMigrationErrors = &schemaMigrationErrors{
|
||||
ErrUniqueSqliteAutoindexSchemaMigrations1: &UniqueConstraintError{s: "sqlite_autoindex_schema_migrations_1"},
|
||||
}
|
||||
|
||||
type schemaMigrationErrors struct {
|
||||
ErrUniqueSqliteAutoindexSchemaMigrations1 *UniqueConstraintError
|
||||
}
|
||||
|
||||
// SchemaMigrationSetter is used for insert/upsert/update operations
|
||||
// All values are optional, and do not have to be set
|
||||
// Generated columns are not included
|
||||
type SchemaMigrationSetter struct {
|
||||
Version omit.Val[string] `db:"version,pk" `
|
||||
}
|
||||
|
||||
func (s SchemaMigrationSetter) SetColumns() []string {
|
||||
vals := make([]string, 0, 1)
|
||||
if !s.Version.IsUnset() {
|
||||
vals = append(vals, "version")
|
||||
}
|
||||
|
||||
return vals
|
||||
}
|
||||
|
||||
func (s SchemaMigrationSetter) Overwrite(t *SchemaMigration) {
|
||||
if !s.Version.IsUnset() {
|
||||
t.Version, _ = s.Version.Get()
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SchemaMigrationSetter) Apply(q *dialect.InsertQuery) {
|
||||
q.AppendHooks(func(ctx context.Context, exec bob.Executor) (context.Context, error) {
|
||||
return SchemaMigrations.BeforeInsertHooks.RunHooks(ctx, exec, s)
|
||||
})
|
||||
|
||||
if len(q.Table.Columns) == 0 {
|
||||
q.Table.Columns = s.SetColumns()
|
||||
}
|
||||
|
||||
q.AppendValues(bob.ExpressionFunc(func(ctx context.Context, w io.Writer, d bob.Dialect, start int) ([]any, error) {
|
||||
vals := make([]bob.Expression, 0, 1)
|
||||
if !s.Version.IsUnset() {
|
||||
vals = append(vals, sqlite.Arg(s.Version))
|
||||
}
|
||||
|
||||
return bob.ExpressSlice(ctx, w, d, start, vals, "", ", ", "")
|
||||
}))
|
||||
}
|
||||
|
||||
func (s SchemaMigrationSetter) UpdateMod() bob.Mod[*dialect.UpdateQuery] {
|
||||
return um.Set(s.Expressions()...)
|
||||
}
|
||||
|
||||
func (s SchemaMigrationSetter) Expressions(prefix ...string) []bob.Expression {
|
||||
exprs := make([]bob.Expression, 0, 1)
|
||||
|
||||
if !s.Version.IsUnset() {
|
||||
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
|
||||
sqlite.Quote(append(prefix, "version")...),
|
||||
sqlite.Arg(s.Version),
|
||||
}})
|
||||
}
|
||||
|
||||
return exprs
|
||||
}
|
||||
|
||||
// FindSchemaMigration retrieves a single record by primary key
|
||||
// If cols is empty Find will return all columns.
|
||||
func FindSchemaMigration(ctx context.Context, exec bob.Executor, VersionPK string, cols ...string) (*SchemaMigration, error) {
|
||||
if len(cols) == 0 {
|
||||
return SchemaMigrations.Query(
|
||||
SelectWhere.SchemaMigrations.Version.EQ(VersionPK),
|
||||
).One(ctx, exec)
|
||||
}
|
||||
|
||||
return SchemaMigrations.Query(
|
||||
SelectWhere.SchemaMigrations.Version.EQ(VersionPK),
|
||||
sm.Columns(SchemaMigrations.Columns().Only(cols...)),
|
||||
).One(ctx, exec)
|
||||
}
|
||||
|
||||
// SchemaMigrationExists checks the presence of a single record by primary key
|
||||
func SchemaMigrationExists(ctx context.Context, exec bob.Executor, VersionPK string) (bool, error) {
|
||||
return SchemaMigrations.Query(
|
||||
SelectWhere.SchemaMigrations.Version.EQ(VersionPK),
|
||||
).Exists(ctx, exec)
|
||||
}
|
||||
|
||||
// AfterQueryHook is called after SchemaMigration is retrieved from the database
|
||||
func (o *SchemaMigration) AfterQueryHook(ctx context.Context, exec bob.Executor, queryType bob.QueryType) error {
|
||||
var err error
|
||||
|
||||
switch queryType {
|
||||
case bob.QueryTypeSelect:
|
||||
ctx, err = SchemaMigrations.AfterSelectHooks.RunHooks(ctx, exec, SchemaMigrationSlice{o})
|
||||
case bob.QueryTypeInsert:
|
||||
ctx, err = SchemaMigrations.AfterInsertHooks.RunHooks(ctx, exec, SchemaMigrationSlice{o})
|
||||
case bob.QueryTypeUpdate:
|
||||
ctx, err = SchemaMigrations.AfterUpdateHooks.RunHooks(ctx, exec, SchemaMigrationSlice{o})
|
||||
case bob.QueryTypeDelete:
|
||||
ctx, err = SchemaMigrations.AfterDeleteHooks.RunHooks(ctx, exec, SchemaMigrationSlice{o})
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// PrimaryKeyVals returns the primary key values of the SchemaMigration
|
||||
func (o *SchemaMigration) PrimaryKeyVals() bob.Expression {
|
||||
return sqlite.Arg(o.Version)
|
||||
}
|
||||
|
||||
func (o *SchemaMigration) pkEQ() dialect.Expression {
|
||||
return sqlite.Quote("schema_migrations", "version").EQ(bob.ExpressionFunc(func(ctx context.Context, w io.Writer, d bob.Dialect, start int) ([]any, error) {
|
||||
return o.PrimaryKeyVals().WriteSQL(ctx, w, d, start)
|
||||
}))
|
||||
}
|
||||
|
||||
// Update uses an executor to update the SchemaMigration
|
||||
func (o *SchemaMigration) Update(ctx context.Context, exec bob.Executor, s *SchemaMigrationSetter) error {
|
||||
v, err := SchemaMigrations.Update(s.UpdateMod(), um.Where(o.pkEQ())).One(ctx, exec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*o = *v
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Delete deletes a single SchemaMigration record with an executor
|
||||
func (o *SchemaMigration) Delete(ctx context.Context, exec bob.Executor) error {
|
||||
_, err := SchemaMigrations.Delete(dm.Where(o.pkEQ())).Exec(ctx, exec)
|
||||
return err
|
||||
}
|
||||
|
||||
// Reload refreshes the SchemaMigration using the executor
|
||||
func (o *SchemaMigration) Reload(ctx context.Context, exec bob.Executor) error {
|
||||
o2, err := SchemaMigrations.Query(
|
||||
SelectWhere.SchemaMigrations.Version.EQ(o.Version),
|
||||
).One(ctx, exec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*o = *o2
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AfterQueryHook is called after SchemaMigrationSlice is retrieved from the database
|
||||
func (o SchemaMigrationSlice) AfterQueryHook(ctx context.Context, exec bob.Executor, queryType bob.QueryType) error {
|
||||
var err error
|
||||
|
||||
switch queryType {
|
||||
case bob.QueryTypeSelect:
|
||||
ctx, err = SchemaMigrations.AfterSelectHooks.RunHooks(ctx, exec, o)
|
||||
case bob.QueryTypeInsert:
|
||||
ctx, err = SchemaMigrations.AfterInsertHooks.RunHooks(ctx, exec, o)
|
||||
case bob.QueryTypeUpdate:
|
||||
ctx, err = SchemaMigrations.AfterUpdateHooks.RunHooks(ctx, exec, o)
|
||||
case bob.QueryTypeDelete:
|
||||
ctx, err = SchemaMigrations.AfterDeleteHooks.RunHooks(ctx, exec, o)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (o SchemaMigrationSlice) pkIN() dialect.Expression {
|
||||
if len(o) == 0 {
|
||||
return sqlite.Raw("NULL")
|
||||
}
|
||||
|
||||
return sqlite.Quote("schema_migrations", "version").In(bob.ExpressionFunc(func(ctx context.Context, w io.Writer, d bob.Dialect, start int) ([]any, error) {
|
||||
pkPairs := make([]bob.Expression, len(o))
|
||||
for i, row := range o {
|
||||
pkPairs[i] = row.PrimaryKeyVals()
|
||||
}
|
||||
return bob.ExpressSlice(ctx, w, d, start, pkPairs, "", ", ", "")
|
||||
}))
|
||||
}
|
||||
|
||||
// copyMatchingRows finds models in the given slice that have the same primary key
|
||||
// then it first copies the existing relationships from the old model to the new model
|
||||
// and then replaces the old model in the slice with the new model
|
||||
func (o SchemaMigrationSlice) copyMatchingRows(from ...*SchemaMigration) {
|
||||
for i, old := range o {
|
||||
for _, new := range from {
|
||||
if new.Version != old.Version {
|
||||
continue
|
||||
}
|
||||
|
||||
o[i] = new
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateMod modifies an update query with "WHERE primary_key IN (o...)"
|
||||
func (o SchemaMigrationSlice) UpdateMod() bob.Mod[*dialect.UpdateQuery] {
|
||||
return bob.ModFunc[*dialect.UpdateQuery](func(q *dialect.UpdateQuery) {
|
||||
q.AppendHooks(func(ctx context.Context, exec bob.Executor) (context.Context, error) {
|
||||
return SchemaMigrations.BeforeUpdateHooks.RunHooks(ctx, exec, o)
|
||||
})
|
||||
|
||||
q.AppendLoader(bob.LoaderFunc(func(ctx context.Context, exec bob.Executor, retrieved any) error {
|
||||
var err error
|
||||
switch retrieved := retrieved.(type) {
|
||||
case *SchemaMigration:
|
||||
o.copyMatchingRows(retrieved)
|
||||
case []*SchemaMigration:
|
||||
o.copyMatchingRows(retrieved...)
|
||||
case SchemaMigrationSlice:
|
||||
o.copyMatchingRows(retrieved...)
|
||||
default:
|
||||
// If the retrieved value is not a SchemaMigration or a slice of SchemaMigration
|
||||
// then run the AfterUpdateHooks on the slice
|
||||
_, err = SchemaMigrations.AfterUpdateHooks.RunHooks(ctx, exec, o)
|
||||
}
|
||||
|
||||
return err
|
||||
}))
|
||||
|
||||
q.AppendWhere(o.pkIN())
|
||||
})
|
||||
}
|
||||
|
||||
// DeleteMod modifies an delete query with "WHERE primary_key IN (o...)"
|
||||
func (o SchemaMigrationSlice) DeleteMod() bob.Mod[*dialect.DeleteQuery] {
|
||||
return bob.ModFunc[*dialect.DeleteQuery](func(q *dialect.DeleteQuery) {
|
||||
q.AppendHooks(func(ctx context.Context, exec bob.Executor) (context.Context, error) {
|
||||
return SchemaMigrations.BeforeDeleteHooks.RunHooks(ctx, exec, o)
|
||||
})
|
||||
|
||||
q.AppendLoader(bob.LoaderFunc(func(ctx context.Context, exec bob.Executor, retrieved any) error {
|
||||
var err error
|
||||
switch retrieved := retrieved.(type) {
|
||||
case *SchemaMigration:
|
||||
o.copyMatchingRows(retrieved)
|
||||
case []*SchemaMigration:
|
||||
o.copyMatchingRows(retrieved...)
|
||||
case SchemaMigrationSlice:
|
||||
o.copyMatchingRows(retrieved...)
|
||||
default:
|
||||
// If the retrieved value is not a SchemaMigration or a slice of SchemaMigration
|
||||
// then run the AfterDeleteHooks on the slice
|
||||
_, err = SchemaMigrations.AfterDeleteHooks.RunHooks(ctx, exec, o)
|
||||
}
|
||||
|
||||
return err
|
||||
}))
|
||||
|
||||
q.AppendWhere(o.pkIN())
|
||||
})
|
||||
}
|
||||
|
||||
func (o SchemaMigrationSlice) UpdateAll(ctx context.Context, exec bob.Executor, vals SchemaMigrationSetter) error {
|
||||
if len(o) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err := SchemaMigrations.Update(vals.UpdateMod(), o.UpdateMod()).All(ctx, exec)
|
||||
return err
|
||||
}
|
||||
|
||||
func (o SchemaMigrationSlice) DeleteAll(ctx context.Context, exec bob.Executor) error {
|
||||
if len(o) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err := SchemaMigrations.Delete(o.DeleteMod()).Exec(ctx, exec)
|
||||
return err
|
||||
}
|
||||
|
||||
func (o SchemaMigrationSlice) ReloadAll(ctx context.Context, exec bob.Executor) error {
|
||||
if len(o) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
o2, err := SchemaMigrations.Query(sm.Where(o.pkIN())).All(ctx, exec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
o.copyMatchingRows(o2...)
|
||||
|
||||
return nil
|
||||
}
|
File diff suppressed because it is too large
Load Diff
31
server/internal/sqlc/db.go
Normal file
31
server/internal/sqlc/db.go
Normal file
@ -0,0 +1,31 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.28.0
|
||||
|
||||
package sqlc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
)
|
||||
|
||||
type DBTX interface {
|
||||
ExecContext(context.Context, string, ...interface{}) (sql.Result, error)
|
||||
PrepareContext(context.Context, string) (*sql.Stmt, error)
|
||||
QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error)
|
||||
QueryRowContext(context.Context, string, ...interface{}) *sql.Row
|
||||
}
|
||||
|
||||
func New(db DBTX) *Queries {
|
||||
return &Queries{db: db}
|
||||
}
|
||||
|
||||
type Queries struct {
|
||||
db DBTX
|
||||
}
|
||||
|
||||
func (q *Queries) WithTx(tx *sql.Tx) *Queries {
|
||||
return &Queries{
|
||||
db: tx,
|
||||
}
|
||||
}
|
113
server/internal/sqlc/file.sql.go
Normal file
113
server/internal/sqlc/file.sql.go
Normal file
@ -0,0 +1,113 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.28.0
|
||||
// source: file.sql
|
||||
|
||||
package sqlc
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
const deleteFile = `-- name: DeleteFile :exec
|
||||
DELETE FROM file
|
||||
WHERE
|
||||
id = ?1
|
||||
AND
|
||||
user_id = ?2
|
||||
`
|
||||
|
||||
type DeleteFileParams struct {
|
||||
ID int64
|
||||
UserID int64
|
||||
}
|
||||
|
||||
func (q *Queries) DeleteFile(ctx context.Context, arg DeleteFileParams) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteFile, arg.ID, arg.UserID)
|
||||
return err
|
||||
}
|
||||
|
||||
const getFile = `-- name: GetFile :one
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
data,
|
||||
user_id
|
||||
FROM file
|
||||
WHERE
|
||||
id = ?1
|
||||
AND
|
||||
user_id = ?2
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
type GetFileParams struct {
|
||||
ID int64
|
||||
UserID int64
|
||||
}
|
||||
|
||||
func (q *Queries) GetFile(ctx context.Context, arg GetFileParams) (File, error) {
|
||||
row := q.db.QueryRowContext(ctx, getFile, arg.ID, arg.UserID)
|
||||
var i File
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.Data,
|
||||
&i.UserID,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const insertFile = `-- name: InsertFile :one
|
||||
INSERT INTO file (
|
||||
name,
|
||||
data,
|
||||
user_id
|
||||
) VALUES (
|
||||
?1,
|
||||
?2,
|
||||
?3
|
||||
)
|
||||
RETURNING id
|
||||
`
|
||||
|
||||
type InsertFileParams struct {
|
||||
Name string
|
||||
Data []byte
|
||||
UserID int64
|
||||
}
|
||||
|
||||
func (q *Queries) InsertFile(ctx context.Context, arg InsertFileParams) (int64, error) {
|
||||
row := q.db.QueryRowContext(ctx, insertFile, arg.Name, arg.Data, arg.UserID)
|
||||
var id int64
|
||||
err := row.Scan(&id)
|
||||
return id, err
|
||||
}
|
||||
|
||||
const updateFile = `-- name: UpdateFile :exec
|
||||
UPDATE file
|
||||
SET
|
||||
name = COALESCE(?1, name),
|
||||
data = COALESCE(?2, data)
|
||||
WHERE
|
||||
id = ?3
|
||||
AND
|
||||
user_id = ?4
|
||||
`
|
||||
|
||||
type UpdateFileParams struct {
|
||||
Name *string
|
||||
Data []byte
|
||||
ID int64
|
||||
UserID int64
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateFile(ctx context.Context, arg UpdateFileParams) error {
|
||||
_, err := q.db.ExecContext(ctx, updateFile,
|
||||
arg.Name,
|
||||
arg.Data,
|
||||
arg.ID,
|
||||
arg.UserID,
|
||||
)
|
||||
return err
|
||||
}
|
250
server/internal/sqlc/item.sql.go
Normal file
250
server/internal/sqlc/item.sql.go
Normal file
@ -0,0 +1,250 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.28.0
|
||||
// source: item.sql
|
||||
|
||||
package sqlc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
const deleteItem = `-- name: DeleteItem :exec
|
||||
DELETE FROM item
|
||||
WHERE
|
||||
id = ?1
|
||||
AND
|
||||
user_id = ?2
|
||||
`
|
||||
|
||||
type DeleteItemParams struct {
|
||||
ID int64
|
||||
UserID int64
|
||||
}
|
||||
|
||||
func (q *Queries) DeleteItem(ctx context.Context, arg DeleteItemParams) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteItem, arg.ID, arg.UserID)
|
||||
return err
|
||||
}
|
||||
|
||||
const getItem = `-- name: GetItem :one
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
added,
|
||||
description,
|
||||
price,
|
||||
quantity,
|
||||
user_id
|
||||
FROM item
|
||||
WHERE
|
||||
id = ?1
|
||||
AND
|
||||
user_id = ?2
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
type GetItemParams struct {
|
||||
ID int64
|
||||
UserID int64
|
||||
}
|
||||
|
||||
func (q *Queries) GetItem(ctx context.Context, arg GetItemParams) (Item, error) {
|
||||
row := q.db.QueryRowContext(ctx, getItem, arg.ID, arg.UserID)
|
||||
var i Item
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.Added,
|
||||
&i.Description,
|
||||
&i.Price,
|
||||
&i.Quantity,
|
||||
&i.UserID,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getItems = `-- name: GetItems :many
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
added,
|
||||
description,
|
||||
price,
|
||||
quantity,
|
||||
user_id
|
||||
FROM item
|
||||
WHERE
|
||||
user_id = ?1
|
||||
AND
|
||||
(
|
||||
(name LIKE ?2 OR ?2 IS NULL)
|
||||
AND
|
||||
(added >= ?3 OR ?3 IS NULL)
|
||||
AND
|
||||
(added <= ?4 OR ?4 IS NULL)
|
||||
)
|
||||
LIMIT
|
||||
?6
|
||||
OFFSET
|
||||
?5
|
||||
`
|
||||
|
||||
type GetItemsParams struct {
|
||||
UserID int64
|
||||
Name *string
|
||||
Start *time.Time
|
||||
End *time.Time
|
||||
Offset int64
|
||||
Limit int64
|
||||
}
|
||||
|
||||
func (q *Queries) GetItems(ctx context.Context, arg GetItemsParams) ([]Item, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getItems,
|
||||
arg.UserID,
|
||||
arg.Name,
|
||||
arg.Start,
|
||||
arg.End,
|
||||
arg.Offset,
|
||||
arg.Limit,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Item
|
||||
for rows.Next() {
|
||||
var i Item
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.Added,
|
||||
&i.Description,
|
||||
&i.Price,
|
||||
&i.Quantity,
|
||||
&i.UserID,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getItemsCount = `-- name: GetItemsCount :one
|
||||
SELECT COUNT(id)
|
||||
FROM item
|
||||
WHERE
|
||||
user_id = ?1
|
||||
AND
|
||||
(
|
||||
(name LIKE ?2 OR ?2 IS NULL)
|
||||
AND
|
||||
(added >= ?3 OR ?3 IS NULL)
|
||||
AND
|
||||
(added <= ?4 OR ?4 IS NULL)
|
||||
)
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
type GetItemsCountParams struct {
|
||||
UserID int64
|
||||
Name *string
|
||||
Start *time.Time
|
||||
End *time.Time
|
||||
}
|
||||
|
||||
func (q *Queries) GetItemsCount(ctx context.Context, arg GetItemsCountParams) (int64, error) {
|
||||
row := q.db.QueryRowContext(ctx, getItemsCount,
|
||||
arg.UserID,
|
||||
arg.Name,
|
||||
arg.Start,
|
||||
arg.End,
|
||||
)
|
||||
var count int64
|
||||
err := row.Scan(&count)
|
||||
return count, err
|
||||
}
|
||||
|
||||
const insertItem = `-- name: InsertItem :one
|
||||
INSERT INTO item (
|
||||
name,
|
||||
added,
|
||||
description,
|
||||
price,
|
||||
quantity,
|
||||
user_id
|
||||
) VALUES (
|
||||
?1,
|
||||
?2,
|
||||
?3,
|
||||
?4,
|
||||
?5,
|
||||
?6
|
||||
)
|
||||
RETURNING id
|
||||
`
|
||||
|
||||
type InsertItemParams struct {
|
||||
Name string
|
||||
Added time.Time
|
||||
Description string
|
||||
Price float64
|
||||
Quantity int64
|
||||
UserID int64
|
||||
}
|
||||
|
||||
func (q *Queries) InsertItem(ctx context.Context, arg InsertItemParams) (int64, error) {
|
||||
row := q.db.QueryRowContext(ctx, insertItem,
|
||||
arg.Name,
|
||||
arg.Added,
|
||||
arg.Description,
|
||||
arg.Price,
|
||||
arg.Quantity,
|
||||
arg.UserID,
|
||||
)
|
||||
var id int64
|
||||
err := row.Scan(&id)
|
||||
return id, err
|
||||
}
|
||||
|
||||
const updateItem = `-- name: UpdateItem :exec
|
||||
UPDATE item
|
||||
SET
|
||||
name = COALESCE(?1, name),
|
||||
description = COALESCE(?2, description),
|
||||
price = COALESCE(?3, price),
|
||||
quantity = COALESCE(?4, quantity)
|
||||
WHERE
|
||||
id = ?5
|
||||
AND
|
||||
user_id = ?6
|
||||
`
|
||||
|
||||
type UpdateItemParams struct {
|
||||
Name *string
|
||||
Description *string
|
||||
Price *float64
|
||||
Quantity *int64
|
||||
ID int64
|
||||
UserID int64
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateItem(ctx context.Context, arg UpdateItemParams) error {
|
||||
_, err := q.db.ExecContext(ctx, updateItem,
|
||||
arg.Name,
|
||||
arg.Description,
|
||||
arg.Price,
|
||||
arg.Quantity,
|
||||
arg.ID,
|
||||
arg.UserID,
|
||||
)
|
||||
return err
|
||||
}
|
37
server/internal/sqlc/models.go
Normal file
37
server/internal/sqlc/models.go
Normal file
@ -0,0 +1,37 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.28.0
|
||||
|
||||
package sqlc
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type File struct {
|
||||
ID int64
|
||||
Name string
|
||||
Data []byte
|
||||
UserID int64
|
||||
}
|
||||
|
||||
type Item struct {
|
||||
ID int64
|
||||
Name string
|
||||
Added time.Time
|
||||
Description string
|
||||
Price float64
|
||||
Quantity int64
|
||||
UserID int64
|
||||
}
|
||||
|
||||
type SchemaMigration struct {
|
||||
Version string
|
||||
}
|
||||
|
||||
type User struct {
|
||||
ID int64
|
||||
Username string
|
||||
Password string
|
||||
ProfilePictureID *int64
|
||||
}
|
120
server/internal/sqlc/user.sql.go
Normal file
120
server/internal/sqlc/user.sql.go
Normal file
@ -0,0 +1,120 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.28.0
|
||||
// source: user.sql
|
||||
|
||||
package sqlc
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
const deleteUser = `-- name: DeleteUser :exec
|
||||
DELETE FROM user
|
||||
WHERE id = ?1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteUser(ctx context.Context, id int64) error {
|
||||
_, err := q.db.ExecContext(ctx, deleteUser, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const getUser = `-- name: GetUser :one
|
||||
SELECT
|
||||
id,
|
||||
username,
|
||||
password,
|
||||
profile_picture_id
|
||||
FROM user
|
||||
WHERE
|
||||
id = ?1
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
func (q *Queries) GetUser(ctx context.Context, id int64) (User, error) {
|
||||
row := q.db.QueryRowContext(ctx, getUser, id)
|
||||
var i User
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Username,
|
||||
&i.Password,
|
||||
&i.ProfilePictureID,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getUserbyUsername = `-- name: GetUserbyUsername :one
|
||||
SELECT
|
||||
id,
|
||||
username,
|
||||
password,
|
||||
profile_picture_id
|
||||
FROM user
|
||||
WHERE
|
||||
username = ?1
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
func (q *Queries) GetUserbyUsername(ctx context.Context, username string) (User, error) {
|
||||
row := q.db.QueryRowContext(ctx, getUserbyUsername, username)
|
||||
var i User
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Username,
|
||||
&i.Password,
|
||||
&i.ProfilePictureID,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const insertUser = `-- name: InsertUser :one
|
||||
INSERT INTO user (
|
||||
username,
|
||||
password
|
||||
) VALUES (
|
||||
?1,
|
||||
?2
|
||||
)
|
||||
RETURNING id
|
||||
`
|
||||
|
||||
type InsertUserParams struct {
|
||||
Username string
|
||||
Password string
|
||||
}
|
||||
|
||||
func (q *Queries) InsertUser(ctx context.Context, arg InsertUserParams) (int64, error) {
|
||||
row := q.db.QueryRowContext(ctx, insertUser, arg.Username, arg.Password)
|
||||
var id int64
|
||||
err := row.Scan(&id)
|
||||
return id, err
|
||||
}
|
||||
|
||||
const updateUser = `-- name: UpdateUser :exec
|
||||
UPDATE user
|
||||
SET
|
||||
username = COALESCE(?1, username),
|
||||
password = COALESCE(?2, password),
|
||||
profile_picture_id = COALESCE(
|
||||
?3,
|
||||
profile_picture_id
|
||||
)
|
||||
WHERE id = ?4
|
||||
`
|
||||
|
||||
type UpdateUserParams struct {
|
||||
Username *string
|
||||
Password *string
|
||||
ProfilePictureID *int64
|
||||
ID int64
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateUser(ctx context.Context, arg UpdateUserParams) error {
|
||||
_, err := q.db.ExecContext(ctx, updateUser,
|
||||
arg.Username,
|
||||
arg.Password,
|
||||
arg.ProfilePictureID,
|
||||
arg.ID,
|
||||
)
|
||||
return err
|
||||
}
|
17
server/internal/util/pointers.go
Normal file
17
server/internal/util/pointers.go
Normal file
@ -0,0 +1,17 @@
|
||||
package util
|
||||
|
||||
func DerefOrEmpty[T any](val *T) T {
|
||||
if val == nil {
|
||||
var empty T
|
||||
return empty
|
||||
}
|
||||
return *val
|
||||
}
|
||||
|
||||
func IsNotNil[T any](val *T) bool {
|
||||
return val != nil
|
||||
}
|
||||
|
||||
func ToPointer[T any](val T) *T {
|
||||
return &val
|
||||
}
|
44
server/internal/util/sql.go
Normal file
44
server/internal/util/sql.go
Normal file
@ -0,0 +1,44 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
func NullLike(s *string) *string {
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
ts := fmt.Sprintf("%%%s%%", *s)
|
||||
return &ts
|
||||
}
|
||||
|
||||
func NullTimestamp(ts *timestamppb.Timestamp) *time.Time {
|
||||
if ts == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
t := ts.AsTime()
|
||||
return &t
|
||||
}
|
||||
|
||||
func NullFloat64(f *float32) *float64 {
|
||||
if f == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
f64 := float64(*f)
|
||||
return &f64
|
||||
}
|
||||
|
||||
func NullInt64(i *int32) *int64 {
|
||||
if i == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
i64 := int64(*i)
|
||||
return &i64
|
||||
}
|
@ -9,15 +9,12 @@ import (
|
||||
"log"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
"github.com/stephenafamo/bob"
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/http2/h2c"
|
||||
|
||||
@ -33,7 +30,7 @@ var clientFS *embed.FS
|
||||
var dbFS *embed.FS
|
||||
|
||||
func main() {
|
||||
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
||||
logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{}))
|
||||
slog.SetDefault(logger)
|
||||
|
||||
// Get env
|
||||
@ -43,44 +40,27 @@ func main() {
|
||||
}
|
||||
|
||||
// Migrate database
|
||||
err = database.Migrate(env.DatabaseUrl, dbFS)
|
||||
err = database.Migrate(env.DatabaseURL, dbFS)
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
|
||||
// Get database
|
||||
db := &bob.DB{}
|
||||
switch env.DatabaseType {
|
||||
case "postgres":
|
||||
log.Println("Using Postgres")
|
||||
|
||||
db, err = database.NewPostgresConnection(env.DatabaseUrl)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to connect to postgres: %v", err)
|
||||
}
|
||||
|
||||
case "sqlite", "sqlite3":
|
||||
log.Println("Using SQLite")
|
||||
|
||||
db, err = database.NewSQLiteConnection(env.DatabaseUrl)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to connect to sqlite: %v", err)
|
||||
}
|
||||
|
||||
default:
|
||||
log.Fatal("DB_TYPE must be either postgres or sqlite")
|
||||
sqlc, db, err := database.New(env.DatabaseURL)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to connect to database: %s", err.Error())
|
||||
}
|
||||
|
||||
// Serve GRPC Handlers
|
||||
api := http.NewServeMux()
|
||||
api.Handle(interceptors.WithCORS(user.NewAuthHandler(db, env.Key)))
|
||||
api.Handle(interceptors.WithCORS(user.NewHandler(db, env.Key)))
|
||||
api.Handle(interceptors.WithCORS(item.NewHandler(db, env.Key)))
|
||||
api.Handle(interceptors.WithCORS(user.NewAuthHandler(sqlc, env.Key)))
|
||||
api.Handle(interceptors.WithCORS(user.NewHandler(sqlc, env.Key)))
|
||||
api.Handle(interceptors.WithCORS(item.NewHandler(sqlc, env.Key)))
|
||||
|
||||
// Serve web interface
|
||||
mux := http.NewServeMux()
|
||||
mux.Handle("/", client.NewClientHandler(env.Key, clientFS))
|
||||
mux.Handle("/file/", file.NewFileHandler(db, env.Key))
|
||||
mux.Handle("/file/", file.NewFileHandler(sqlc, env.Key))
|
||||
mux.Handle("/grpc/", http.StripPrefix("/grpc", api))
|
||||
|
||||
// Start server
|
||||
@ -114,10 +94,9 @@ func main() {
|
||||
}
|
||||
|
||||
type env struct {
|
||||
Port string
|
||||
Key string
|
||||
DatabaseType string
|
||||
DatabaseUrl *url.URL
|
||||
Port string
|
||||
Key string
|
||||
DatabaseURL string
|
||||
}
|
||||
|
||||
func getEnv() (*env, error) {
|
||||
@ -128,8 +107,9 @@ func getEnv() (*env, error) {
|
||||
|
||||
// Create
|
||||
env := env{
|
||||
Port: os.Getenv("PORT"),
|
||||
Key: os.Getenv("KEY"),
|
||||
Port: os.Getenv("PORT"),
|
||||
Key: os.Getenv("KEY"),
|
||||
DatabaseURL: os.Getenv("DATABASE_URL"),
|
||||
}
|
||||
|
||||
// Validate
|
||||
@ -139,20 +119,9 @@ func getEnv() (*env, error) {
|
||||
if env.Key == "" {
|
||||
return nil, errors.New("env 'key' not found")
|
||||
}
|
||||
|
||||
// Validate DATABASE_URL
|
||||
dbstr := os.Getenv("DATABASE_URL")
|
||||
if dbstr == "" {
|
||||
if env.DatabaseURL == "" {
|
||||
return nil, errors.New("env 'DATABASE_URL' not found")
|
||||
}
|
||||
|
||||
dbsp := strings.Split(dbstr, ":")
|
||||
dburl, err := url.Parse(dbstr)
|
||||
if err != nil || len(dbsp) < 2 {
|
||||
return nil, errors.New("env 'DATABASE_URL' formatted incorrectly")
|
||||
}
|
||||
env.DatabaseType = dbsp[0]
|
||||
env.DatabaseUrl = dburl
|
||||
|
||||
return &env, nil
|
||||
}
|
||||
|
14
server/sqlc.yaml
Normal file
14
server/sqlc.yaml
Normal file
@ -0,0 +1,14 @@
|
||||
version: "2"
|
||||
sql:
|
||||
- engine: "sqlite"
|
||||
queries: "db/queries"
|
||||
schema: "db/schema.sql"
|
||||
gen:
|
||||
go:
|
||||
package: "sqlc"
|
||||
out: "internal/sqlc"
|
||||
emit_pointers_for_null_types: true
|
||||
database:
|
||||
uri: ${DATABASE_URL}
|
||||
rules:
|
||||
- sqlc/db-prepare
|
Loading…
x
Reference in New Issue
Block a user