feat: items page
This commit is contained in:
parent
f58b3cc18d
commit
50c8d18df9
@ -18,5 +18,7 @@
|
||||
--color-subtext-1: #bac2de;
|
||||
|
||||
--color-text: #cdd6f4;
|
||||
|
||||
--color-sky: #89dceb;
|
||||
--color-red: #f38ba8;
|
||||
}
|
296
client/src/lib/services/item/v1/item_pb.ts
Normal file
296
client/src/lib/services/item/v1/item_pb.ts
Normal file
@ -0,0 +1,296 @@
|
||||
// @generated by protoc-gen-es v2.2.3 with parameter "target=ts"
|
||||
// @generated from file item/v1/item.proto (package item.v1, syntax proto3)
|
||||
/* eslint-disable */
|
||||
|
||||
import type { GenFile, GenMessage, GenService } from "@bufbuild/protobuf/codegenv1";
|
||||
import { fileDesc, messageDesc, serviceDesc } from "@bufbuild/protobuf/codegenv1";
|
||||
import type { Timestamp } from "@bufbuild/protobuf/wkt";
|
||||
import { file_google_protobuf_timestamp } from "@bufbuild/protobuf/wkt";
|
||||
import type { Message } from "@bufbuild/protobuf";
|
||||
|
||||
/**
|
||||
* Describes the file item/v1/item.proto.
|
||||
*/
|
||||
export const file_item_v1_item: GenFile = /*@__PURE__*/
|
||||
fileDesc("ChJpdGVtL3YxL2l0ZW0ucHJvdG8SB2l0ZW0udjEinAEKBEl0ZW0SDwoCaWQYASABKA1IAIgBARIMCgRuYW1lGAIgASgJEhMKC2Rlc2NyaXB0aW9uGAMgASgJEg0KBXByaWNlGAQgASgCEhAKCHF1YW50aXR5GAUgASgNEi4KBWFkZGVkGAYgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcEgBiAEBQgUKA19pZEIICgZfYWRkZWQiHAoOR2V0SXRlbVJlcXVlc3QSCgoCaWQYASABKA0iLgoPR2V0SXRlbVJlc3BvbnNlEhsKBGl0ZW0YASABKAsyDS5pdGVtLnYxLkl0ZW0i3wEKD0dldEl0ZW1zUmVxdWVzdBIuCgVzdGFydBgBIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBIAIgBARIsCgNlbmQYAiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wSAGIAQESEwoGZmlsdGVyGAMgASgJSAKIAQESEgoFbGltaXQYBCABKA1IA4gBARITCgZvZmZzZXQYBSABKA1IBIgBAUIICgZfc3RhcnRCBgoEX2VuZEIJCgdfZmlsdGVyQggKBl9saW1pdEIJCgdfb2Zmc2V0Ij8KEEdldEl0ZW1zUmVzcG9uc2USHAoFaXRlbXMYASADKAsyDS5pdGVtLnYxLkl0ZW0SDQoFY291bnQYAiABKAQiMAoRQ3JlYXRlSXRlbVJlcXVlc3QSGwoEaXRlbRgBIAEoCzINLml0ZW0udjEuSXRlbSIxChJDcmVhdGVJdGVtUmVzcG9uc2USGwoEaXRlbRgBIAEoCzINLml0ZW0udjEuSXRlbSIwChFVcGRhdGVJdGVtUmVxdWVzdBIbCgRpdGVtGAEgASgLMg0uaXRlbS52MS5JdGVtIjEKElVwZGF0ZUl0ZW1SZXNwb25zZRIbCgRpdGVtGAEgASgLMg0uaXRlbS52MS5JdGVtIh8KEURlbGV0ZUl0ZW1SZXF1ZXN0EgoKAmlkGAEgASgNIhQKEkRlbGV0ZUl0ZW1SZXNwb25zZTLrAgoLSXRlbVNlcnZpY2USPgoHR2V0SXRlbRIXLml0ZW0udjEuR2V0SXRlbVJlcXVlc3QaGC5pdGVtLnYxLkdldEl0ZW1SZXNwb25zZSIAEkEKCEdldEl0ZW1zEhguaXRlbS52MS5HZXRJdGVtc1JlcXVlc3QaGS5pdGVtLnYxLkdldEl0ZW1zUmVzcG9uc2UiABJHCgpDcmVhdGVJdGVtEhouaXRlbS52MS5DcmVhdGVJdGVtUmVxdWVzdBobLml0ZW0udjEuQ3JlYXRlSXRlbVJlc3BvbnNlIgASRwoKVXBkYXRlSXRlbRIaLml0ZW0udjEuVXBkYXRlSXRlbVJlcXVlc3QaGy5pdGVtLnYxLlVwZGF0ZUl0ZW1SZXNwb25zZSIAEkcKCkRlbGV0ZUl0ZW0SGi5pdGVtLnYxLkRlbGV0ZUl0ZW1SZXF1ZXN0GhsuaXRlbS52MS5EZWxldGVJdGVtUmVzcG9uc2UiAEKdAQoLY29tLml0ZW0udjFCCUl0ZW1Qcm90b1ABWkZnaXRodWIuY29tL3Nwb3RkZW1vNC90cmV2c3RhY2svc2VydmVyL2ludGVybmFsL3NlcnZpY2VzL2l0ZW0vdjE7aXRlbXYxogIDSVhYqgIHSXRlbS5WMcoCB0l0ZW1cVjHiAhNJdGVtXFYxXEdQQk1ldGFkYXRh6gIISXRlbTo6VjFiBnByb3RvMw", [file_google_protobuf_timestamp]);
|
||||
|
||||
/**
|
||||
* @generated from message item.v1.Item
|
||||
*/
|
||||
export type Item = Message<"item.v1.Item"> & {
|
||||
/**
|
||||
* @generated from field: optional uint32 id = 1;
|
||||
*/
|
||||
id?: number;
|
||||
|
||||
/**
|
||||
* @generated from field: string name = 2;
|
||||
*/
|
||||
name: string;
|
||||
|
||||
/**
|
||||
* @generated from field: string description = 3;
|
||||
*/
|
||||
description: string;
|
||||
|
||||
/**
|
||||
* @generated from field: float price = 4;
|
||||
*/
|
||||
price: number;
|
||||
|
||||
/**
|
||||
* @generated from field: uint32 quantity = 5;
|
||||
*/
|
||||
quantity: number;
|
||||
|
||||
/**
|
||||
* @generated from field: optional google.protobuf.Timestamp added = 6;
|
||||
*/
|
||||
added?: Timestamp;
|
||||
};
|
||||
|
||||
/**
|
||||
* Describes the message item.v1.Item.
|
||||
* Use `create(ItemSchema)` to create a new message.
|
||||
*/
|
||||
export const ItemSchema: GenMessage<Item> = /*@__PURE__*/
|
||||
messageDesc(file_item_v1_item, 0);
|
||||
|
||||
/**
|
||||
* @generated from message item.v1.GetItemRequest
|
||||
*/
|
||||
export type GetItemRequest = Message<"item.v1.GetItemRequest"> & {
|
||||
/**
|
||||
* @generated from field: uint32 id = 1;
|
||||
*/
|
||||
id: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* Describes the message item.v1.GetItemRequest.
|
||||
* Use `create(GetItemRequestSchema)` to create a new message.
|
||||
*/
|
||||
export const GetItemRequestSchema: GenMessage<GetItemRequest> = /*@__PURE__*/
|
||||
messageDesc(file_item_v1_item, 1);
|
||||
|
||||
/**
|
||||
* @generated from message item.v1.GetItemResponse
|
||||
*/
|
||||
export type GetItemResponse = Message<"item.v1.GetItemResponse"> & {
|
||||
/**
|
||||
* @generated from field: item.v1.Item item = 1;
|
||||
*/
|
||||
item?: Item;
|
||||
};
|
||||
|
||||
/**
|
||||
* Describes the message item.v1.GetItemResponse.
|
||||
* Use `create(GetItemResponseSchema)` to create a new message.
|
||||
*/
|
||||
export const GetItemResponseSchema: GenMessage<GetItemResponse> = /*@__PURE__*/
|
||||
messageDesc(file_item_v1_item, 2);
|
||||
|
||||
/**
|
||||
* @generated from message item.v1.GetItemsRequest
|
||||
*/
|
||||
export type GetItemsRequest = Message<"item.v1.GetItemsRequest"> & {
|
||||
/**
|
||||
* @generated from field: optional google.protobuf.Timestamp start = 1;
|
||||
*/
|
||||
start?: Timestamp;
|
||||
|
||||
/**
|
||||
* @generated from field: optional google.protobuf.Timestamp end = 2;
|
||||
*/
|
||||
end?: Timestamp;
|
||||
|
||||
/**
|
||||
* @generated from field: optional string filter = 3;
|
||||
*/
|
||||
filter?: string;
|
||||
|
||||
/**
|
||||
* @generated from field: optional uint32 limit = 4;
|
||||
*/
|
||||
limit?: number;
|
||||
|
||||
/**
|
||||
* @generated from field: optional uint32 offset = 5;
|
||||
*/
|
||||
offset?: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* Describes the message item.v1.GetItemsRequest.
|
||||
* Use `create(GetItemsRequestSchema)` to create a new message.
|
||||
*/
|
||||
export const GetItemsRequestSchema: GenMessage<GetItemsRequest> = /*@__PURE__*/
|
||||
messageDesc(file_item_v1_item, 3);
|
||||
|
||||
/**
|
||||
* @generated from message item.v1.GetItemsResponse
|
||||
*/
|
||||
export type GetItemsResponse = Message<"item.v1.GetItemsResponse"> & {
|
||||
/**
|
||||
* @generated from field: repeated item.v1.Item items = 1;
|
||||
*/
|
||||
items: Item[];
|
||||
|
||||
/**
|
||||
* @generated from field: uint64 count = 2;
|
||||
*/
|
||||
count: bigint;
|
||||
};
|
||||
|
||||
/**
|
||||
* Describes the message item.v1.GetItemsResponse.
|
||||
* Use `create(GetItemsResponseSchema)` to create a new message.
|
||||
*/
|
||||
export const GetItemsResponseSchema: GenMessage<GetItemsResponse> = /*@__PURE__*/
|
||||
messageDesc(file_item_v1_item, 4);
|
||||
|
||||
/**
|
||||
* @generated from message item.v1.CreateItemRequest
|
||||
*/
|
||||
export type CreateItemRequest = Message<"item.v1.CreateItemRequest"> & {
|
||||
/**
|
||||
* @generated from field: item.v1.Item item = 1;
|
||||
*/
|
||||
item?: Item;
|
||||
};
|
||||
|
||||
/**
|
||||
* Describes the message item.v1.CreateItemRequest.
|
||||
* Use `create(CreateItemRequestSchema)` to create a new message.
|
||||
*/
|
||||
export const CreateItemRequestSchema: GenMessage<CreateItemRequest> = /*@__PURE__*/
|
||||
messageDesc(file_item_v1_item, 5);
|
||||
|
||||
/**
|
||||
* @generated from message item.v1.CreateItemResponse
|
||||
*/
|
||||
export type CreateItemResponse = Message<"item.v1.CreateItemResponse"> & {
|
||||
/**
|
||||
* @generated from field: item.v1.Item item = 1;
|
||||
*/
|
||||
item?: Item;
|
||||
};
|
||||
|
||||
/**
|
||||
* Describes the message item.v1.CreateItemResponse.
|
||||
* Use `create(CreateItemResponseSchema)` to create a new message.
|
||||
*/
|
||||
export const CreateItemResponseSchema: GenMessage<CreateItemResponse> = /*@__PURE__*/
|
||||
messageDesc(file_item_v1_item, 6);
|
||||
|
||||
/**
|
||||
* @generated from message item.v1.UpdateItemRequest
|
||||
*/
|
||||
export type UpdateItemRequest = Message<"item.v1.UpdateItemRequest"> & {
|
||||
/**
|
||||
* @generated from field: item.v1.Item item = 1;
|
||||
*/
|
||||
item?: Item;
|
||||
};
|
||||
|
||||
/**
|
||||
* Describes the message item.v1.UpdateItemRequest.
|
||||
* Use `create(UpdateItemRequestSchema)` to create a new message.
|
||||
*/
|
||||
export const UpdateItemRequestSchema: GenMessage<UpdateItemRequest> = /*@__PURE__*/
|
||||
messageDesc(file_item_v1_item, 7);
|
||||
|
||||
/**
|
||||
* @generated from message item.v1.UpdateItemResponse
|
||||
*/
|
||||
export type UpdateItemResponse = Message<"item.v1.UpdateItemResponse"> & {
|
||||
/**
|
||||
* @generated from field: item.v1.Item item = 1;
|
||||
*/
|
||||
item?: Item;
|
||||
};
|
||||
|
||||
/**
|
||||
* Describes the message item.v1.UpdateItemResponse.
|
||||
* Use `create(UpdateItemResponseSchema)` to create a new message.
|
||||
*/
|
||||
export const UpdateItemResponseSchema: GenMessage<UpdateItemResponse> = /*@__PURE__*/
|
||||
messageDesc(file_item_v1_item, 8);
|
||||
|
||||
/**
|
||||
* @generated from message item.v1.DeleteItemRequest
|
||||
*/
|
||||
export type DeleteItemRequest = Message<"item.v1.DeleteItemRequest"> & {
|
||||
/**
|
||||
* @generated from field: uint32 id = 1;
|
||||
*/
|
||||
id: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* Describes the message item.v1.DeleteItemRequest.
|
||||
* Use `create(DeleteItemRequestSchema)` to create a new message.
|
||||
*/
|
||||
export const DeleteItemRequestSchema: GenMessage<DeleteItemRequest> = /*@__PURE__*/
|
||||
messageDesc(file_item_v1_item, 9);
|
||||
|
||||
/**
|
||||
* @generated from message item.v1.DeleteItemResponse
|
||||
*/
|
||||
export type DeleteItemResponse = Message<"item.v1.DeleteItemResponse"> & {
|
||||
};
|
||||
|
||||
/**
|
||||
* Describes the message item.v1.DeleteItemResponse.
|
||||
* Use `create(DeleteItemResponseSchema)` to create a new message.
|
||||
*/
|
||||
export const DeleteItemResponseSchema: GenMessage<DeleteItemResponse> = /*@__PURE__*/
|
||||
messageDesc(file_item_v1_item, 10);
|
||||
|
||||
/**
|
||||
* @generated from service item.v1.ItemService
|
||||
*/
|
||||
export const ItemService: GenService<{
|
||||
/**
|
||||
* @generated from rpc item.v1.ItemService.GetItem
|
||||
*/
|
||||
getItem: {
|
||||
methodKind: "unary";
|
||||
input: typeof GetItemRequestSchema;
|
||||
output: typeof GetItemResponseSchema;
|
||||
},
|
||||
/**
|
||||
* @generated from rpc item.v1.ItemService.GetItems
|
||||
*/
|
||||
getItems: {
|
||||
methodKind: "unary";
|
||||
input: typeof GetItemsRequestSchema;
|
||||
output: typeof GetItemsResponseSchema;
|
||||
},
|
||||
/**
|
||||
* @generated from rpc item.v1.ItemService.CreateItem
|
||||
*/
|
||||
createItem: {
|
||||
methodKind: "unary";
|
||||
input: typeof CreateItemRequestSchema;
|
||||
output: typeof CreateItemResponseSchema;
|
||||
},
|
||||
/**
|
||||
* @generated from rpc item.v1.ItemService.UpdateItem
|
||||
*/
|
||||
updateItem: {
|
||||
methodKind: "unary";
|
||||
input: typeof UpdateItemRequestSchema;
|
||||
output: typeof UpdateItemResponseSchema;
|
||||
},
|
||||
/**
|
||||
* @generated from rpc item.v1.ItemService.DeleteItem
|
||||
*/
|
||||
deleteItem: {
|
||||
methodKind: "unary";
|
||||
input: typeof DeleteItemRequestSchema;
|
||||
output: typeof DeleteItemResponseSchema;
|
||||
},
|
||||
}> = /*@__PURE__*/
|
||||
serviceDesc(file_item_v1_item, 0);
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { createConnectTransport } from "@connectrpc/connect-web"
|
||||
import { Code, ConnectError, createClient } from "@connectrpc/connect"
|
||||
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 type { Interceptor } from "@connectrpc/connect";
|
||||
import { ItemService } from "$lib/services/item/v1/item_pb";
|
||||
import { goto } from "$app/navigation";
|
||||
|
||||
const redirector: Interceptor = (next) => async (req) => {
|
||||
@ -23,4 +23,5 @@ const transport = createConnectTransport({
|
||||
});
|
||||
|
||||
export const AuthClient = createClient(AuthService, transport);
|
||||
export const UserClient = createClient(UserService, transport);
|
||||
export const UserClient = createClient(UserService, transport);
|
||||
export const ItemClient = createClient(ItemService, transport);
|
51
client/src/lib/ui/Modal.svelte
Normal file
51
client/src/lib/ui/Modal.svelte
Normal file
@ -0,0 +1,51 @@
|
||||
<script lang="ts">
|
||||
import { Dialog } from 'bits-ui';
|
||||
import { fade } from 'svelte/transition';
|
||||
import type { Snippet } from 'svelte';
|
||||
|
||||
let {
|
||||
trigger,
|
||||
content,
|
||||
open = $bindable(false)
|
||||
}: { trigger: Snippet; content: Snippet; open: boolean } = $props();
|
||||
</script>
|
||||
|
||||
<Dialog.Root bind:open>
|
||||
<Dialog.Trigger>
|
||||
{@render trigger()}
|
||||
</Dialog.Trigger>
|
||||
<Dialog.Portal>
|
||||
<Dialog.Overlay forceMount>
|
||||
{#snippet child({ props, open })}
|
||||
{#if open}
|
||||
<div
|
||||
{...props}
|
||||
transition:fade={{
|
||||
duration: 100
|
||||
}}
|
||||
>
|
||||
<div class="fixed inset-0 z-50 mt-[50px] bg-black/50 transition-all"></div>
|
||||
</div>
|
||||
{/if}
|
||||
{/snippet}
|
||||
</Dialog.Overlay>
|
||||
<Dialog.Content forceMount>
|
||||
{#snippet child({ props, open })}
|
||||
{#if open}
|
||||
<div
|
||||
{...props}
|
||||
transition:fade={{
|
||||
duration: 100
|
||||
}}
|
||||
>
|
||||
<div
|
||||
class="bg-mantle border-surface-0 fixed inset-0 left-[50%] top-[50%] z-50 size-fit w-96 -translate-x-1/2 -translate-y-1/2 transform overflow-y-auto rounded-xl border pb-1 drop-shadow-md"
|
||||
>
|
||||
{@render content()}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{/snippet}
|
||||
</Dialog.Content>
|
||||
</Dialog.Portal>
|
||||
</Dialog.Root>
|
@ -34,7 +34,7 @@
|
||||
},
|
||||
{
|
||||
name: 'Items',
|
||||
href: '/items',
|
||||
href: '/items/',
|
||||
icon: LayoutList
|
||||
},
|
||||
{
|
||||
|
332
client/src/routes/(app)/items/+page.svelte
Normal file
332
client/src/routes/(app)/items/+page.svelte
Normal file
@ -0,0 +1,332 @@
|
||||
<script lang="ts">
|
||||
import { ItemClient } from '$lib/transport';
|
||||
import { Plus, Trash, Pencil } from '@lucide/svelte';
|
||||
import { timestampFromDate, timestampDate } from '@bufbuild/protobuf/wkt';
|
||||
import { Dialog, Button } from 'bits-ui';
|
||||
import { fade } from 'svelte/transition';
|
||||
import { toast } from 'svelte-sonner';
|
||||
import { ConnectError } from '@connectrpc/connect';
|
||||
import Modal from '$lib/ui/Modal.svelte';
|
||||
import { SvelteMap } from 'svelte/reactivity';
|
||||
|
||||
// Config
|
||||
let limit: number = $state(10);
|
||||
let offset: number = $state(0);
|
||||
let start = $state(new Date(new Date().setDate(new Date().getDate() - 1)));
|
||||
let end = $state(new Date());
|
||||
let filter = $state('');
|
||||
|
||||
// Items
|
||||
let items = $state(getItems());
|
||||
let count: number = $state(0);
|
||||
|
||||
// Open
|
||||
let addedOpen = $state(false);
|
||||
let deletesOpen: SvelteMap<number, boolean> = new SvelteMap();
|
||||
let editsOpen: SvelteMap<number, boolean> = new SvelteMap();
|
||||
|
||||
async function getItems() {
|
||||
return await ItemClient.getItems({
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
start: timestampFromDate(start),
|
||||
end: timestampFromDate(end),
|
||||
filter: filter
|
||||
}).then((resp) => {
|
||||
count = Number(resp.count);
|
||||
return resp.items;
|
||||
});
|
||||
}
|
||||
async function updateItems() {
|
||||
let i = getItems();
|
||||
i.then(() => {
|
||||
items = i;
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="border-surface-0 bg-mantle mx-4 mt-2 overflow-x-auto rounded border-x border-t drop-shadow-md"
|
||||
>
|
||||
<table class="w-full table-auto border-collapse text-left rtl:text-right">
|
||||
<thead>
|
||||
<tr class="border-surface-0 border-b">
|
||||
<th scope="col" class="text-subtext-0 px-6 py-3 font-normal">Added</th>
|
||||
<th scope="col" class="text-subtext-0 px-6 py-3 font-normal">Name</th>
|
||||
<th scope="col" class="text-subtext-0 px-6 py-3 font-normal">Description</th>
|
||||
<th scope="col" class="text-subtext-0 px-6 py-3 font-normal">Price</th>
|
||||
<th scope="col" class="text-subtext-0 px-6 py-3 font-normal">Quantity</th>
|
||||
<th class="w-0"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#await items}
|
||||
<tr class="border-surface-0 border-b">
|
||||
<td class="px-6 py-3"><div class="bg-surface-2 m-2 h-3 animate-pulse rounded"></div></td>
|
||||
<td class="px-6 py-3"><div class="bg-surface-2 m-2 h-3 animate-pulse rounded"></div></td>
|
||||
<td class="px-6 py-3"><div class="bg-surface-2 m-2 h-3 animate-pulse rounded"></div></td>
|
||||
<td class="px-6 py-3"><div class="bg-surface-2 m-2 h-3 animate-pulse rounded"></div></td>
|
||||
<td class="px-6 py-3"><div class="bg-surface-2 m-2 h-3 animate-pulse rounded"></div></td>
|
||||
</tr>
|
||||
{:then items}
|
||||
{#each items as item}
|
||||
<tr class="border-surface-0 border-b">
|
||||
<td class="px-6 py-3">
|
||||
{item.added ? timestampDate(item.added).toLocaleString() : ''}
|
||||
</td>
|
||||
<td class="px-6 py-3">{item.name}</td>
|
||||
<td class="px-6 py-3">{item.description}</td>
|
||||
<td class="px-6 py-3">{item.price}</td>
|
||||
<td class="px-6 py-3">{item.quantity}</td>
|
||||
<td class="pr-2">
|
||||
<div class="flex gap-2">
|
||||
<Modal bind:open={
|
||||
() => editsOpen.has(item.id!) ? editsOpen.get(item.id!)! : editsOpen.set(item.id!, false) && editsOpen.get(item.id!)!,
|
||||
(value) => editsOpen.set(item.id!, value)
|
||||
}>
|
||||
{#snippet trigger()}
|
||||
<button
|
||||
class="bg-text text-crust hover:brightness-120 block cursor-pointer rounded p-2 drop-shadow-md"
|
||||
>
|
||||
<Pencil />
|
||||
</button>
|
||||
{/snippet}
|
||||
|
||||
{#snippet content()}
|
||||
<h1 class="border-surface-0 border-b py-3 text-center text-xl font-bold">
|
||||
Edit {item.name}
|
||||
</h1>
|
||||
<form
|
||||
onsubmit={async (e) => {
|
||||
e.preventDefault();
|
||||
const form = e.target as HTMLFormElement;
|
||||
const formData = new FormData(form);
|
||||
const name = formData.get('name')?.toString();
|
||||
const description = formData.get('description')?.toString();
|
||||
const price = formData.get('price')?.toString();
|
||||
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')
|
||||
}
|
||||
});
|
||||
|
||||
if (response.item && item.id) {
|
||||
toast.success(`item "${name}" saved`);
|
||||
editsOpen.set(item.id, false)
|
||||
await updateItems();
|
||||
}
|
||||
} catch (err) {
|
||||
const error = ConnectError.from(err);
|
||||
toast.error(error.rawMessage);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div class="flex flex-col gap-4 p-3">
|
||||
<div class="flex flex-col gap-1">
|
||||
<label for="name" class="text-sm">Name</label>
|
||||
<input
|
||||
id="name"
|
||||
name="name"
|
||||
type="text"
|
||||
class="border-surface-0 rounded border p-2 text-sm"
|
||||
value={item.name}
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-col gap-1">
|
||||
<label for="description" class="text-sm">Description</label>
|
||||
<input
|
||||
id="description"
|
||||
name="description"
|
||||
type="text"
|
||||
class="border-surface-0 rounded border p-2 text-sm"
|
||||
value={item.description}
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-col gap-1">
|
||||
<label for="price" class="text-sm">Price</label>
|
||||
<input
|
||||
id="price"
|
||||
name="price"
|
||||
type="number"
|
||||
class="border-surface-0 rounded border p-2 text-sm"
|
||||
value={item.price}
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-col gap-1">
|
||||
<label for="quantity" class="text-sm">Quantity</label>
|
||||
<input
|
||||
id="quantity"
|
||||
name="quantity"
|
||||
type="number"
|
||||
class="border-surface-0 rounded border p-2 text-sm"
|
||||
value={item.quantity}
|
||||
/>
|
||||
</div>
|
||||
<Button.Root
|
||||
type="submit"
|
||||
class="bg-sky text-crust hover:brightness-120 w-20 cursor-pointer rounded p-2 px-4 text-sm transition-all"
|
||||
>
|
||||
Submit
|
||||
</Button.Root>
|
||||
</div>
|
||||
</form>
|
||||
{/snippet}
|
||||
</Modal>
|
||||
|
||||
<Modal bind:open={
|
||||
() => deletesOpen.has(item.id!) ? deletesOpen.get(item.id!)! : deletesOpen.set(item.id!, false) && deletesOpen.get(item.id!)!,
|
||||
(value) => deletesOpen.set(item.id!, value)
|
||||
}>
|
||||
{#snippet trigger()}
|
||||
<button
|
||||
class="bg-red text-crust hover:brightness-120 block cursor-pointer rounded p-2 drop-shadow-md"
|
||||
>
|
||||
<Trash />
|
||||
</button>
|
||||
{/snippet}
|
||||
|
||||
{#snippet content()}
|
||||
<h1 class="border-surface-0 border-b py-3 text-center text-xl font-bold">
|
||||
Delete {item.name}
|
||||
</h1>
|
||||
<form
|
||||
onsubmit={async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
try {
|
||||
await ItemClient.deleteItem({
|
||||
id: item.id
|
||||
});
|
||||
|
||||
toast.success(`item "${item.name}" deleted`);
|
||||
deletesOpen.set(item.id!, false);
|
||||
await updateItems();
|
||||
} catch (err) {
|
||||
const error = ConnectError.from(err);
|
||||
toast.error(error.rawMessage);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div class="flex flex-col gap-4 p-3">
|
||||
<span class="text-center">Are you sure you want to delete "{item.name}"?</span
|
||||
>
|
||||
<div class="flex justify-center gap-4">
|
||||
<Button.Root
|
||||
type="submit"
|
||||
class="bg-sky text-crust hover:brightness-120 cursor-pointer rounded p-2 px-4 text-sm transition-all"
|
||||
>
|
||||
Confirm
|
||||
</Button.Root>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{/snippet}
|
||||
</Modal>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
{/await}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="mx-4 mt-1 flex justify-end">
|
||||
<Modal bind:open={addedOpen}>
|
||||
{#snippet trigger()}
|
||||
<button
|
||||
class="bg-sky text-crust hover:brightness-120 cursor-pointer rounded p-2 px-4 drop-shadow-md"
|
||||
>
|
||||
<Plus />
|
||||
</button>
|
||||
{/snippet}
|
||||
|
||||
{#snippet content()}
|
||||
<h1 class="border-surface-0 border-b py-3 text-center text-xl font-bold">Add Item</h1>
|
||||
<form
|
||||
onsubmit={async (e) => {
|
||||
e.preventDefault();
|
||||
const form = e.target as HTMLFormElement;
|
||||
const formData = new FormData(form);
|
||||
const name = formData.get('name')?.toString();
|
||||
const description = formData.get('description')?.toString();
|
||||
const price = formData.get('price')?.toString();
|
||||
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')
|
||||
}
|
||||
});
|
||||
|
||||
if (response.item) {
|
||||
form.reset();
|
||||
toast.success(`item "${name}" added`);
|
||||
addedOpen = false;
|
||||
await updateItems();
|
||||
}
|
||||
} catch (err) {
|
||||
const error = ConnectError.from(err);
|
||||
toast.error(error.rawMessage);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div class="flex flex-col gap-4 p-3">
|
||||
<div class="flex flex-col gap-1">
|
||||
<label for="name" class="text-sm">Name</label>
|
||||
<input
|
||||
id="name"
|
||||
name="name"
|
||||
type="text"
|
||||
class="border-surface-0 rounded border p-2 text-sm"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-col gap-1">
|
||||
<label for="description" class="text-sm">Description</label>
|
||||
<input
|
||||
id="description"
|
||||
name="description"
|
||||
type="text"
|
||||
class="border-surface-0 rounded border p-2 text-sm"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-col gap-1">
|
||||
<label for="price" class="text-sm">Price</label>
|
||||
<input
|
||||
id="price"
|
||||
name="price"
|
||||
type="number"
|
||||
class="border-surface-0 rounded border p-2 text-sm"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-col gap-1">
|
||||
<label for="quantity" class="text-sm">Quantity</label>
|
||||
<input
|
||||
id="quantity"
|
||||
name="quantity"
|
||||
type="number"
|
||||
class="border-surface-0 rounded border p-2 text-sm"
|
||||
/>
|
||||
</div>
|
||||
<Button.Root
|
||||
type="submit"
|
||||
class="bg-sky text-crust hover:brightness-120 w-fit cursor-pointer rounded p-2 px-4 text-sm transition-all"
|
||||
>
|
||||
Submit
|
||||
</Button.Root>
|
||||
</div>
|
||||
</form>
|
||||
{/snippet}
|
||||
</Modal>
|
||||
</div>
|
@ -15,50 +15,225 @@ components:
|
||||
scheme: bearer
|
||||
bearerFormat: JWT
|
||||
schemas:
|
||||
user.v1.LoginRequest:
|
||||
google.protobuf.Timestamp:
|
||||
type: string
|
||||
format: date-time
|
||||
description: |-
|
||||
A Timestamp represents a point in time independent of any time zone or local
|
||||
calendar, encoded as a count of seconds and fractions of seconds at
|
||||
nanosecond resolution. The count is relative to an epoch at UTC midnight on
|
||||
January 1, 1970, in the proleptic Gregorian calendar which extends the
|
||||
Gregorian calendar backwards to year one.
|
||||
|
||||
All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap
|
||||
second table is needed for interpretation, using a [24-hour linear
|
||||
smear](https://developers.google.com/time/smear).
|
||||
|
||||
The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By
|
||||
restricting to that range, we ensure that we can convert to and from [RFC
|
||||
3339](https://www.ietf.org/rfc/rfc3339.txt) date strings.
|
||||
|
||||
# Examples
|
||||
|
||||
Example 1: Compute Timestamp from POSIX `time()`.
|
||||
|
||||
Timestamp timestamp;
|
||||
timestamp.set_seconds(time(NULL));
|
||||
timestamp.set_nanos(0);
|
||||
|
||||
Example 2: Compute Timestamp from POSIX `gettimeofday()`.
|
||||
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
Timestamp timestamp;
|
||||
timestamp.set_seconds(tv.tv_sec);
|
||||
timestamp.set_nanos(tv.tv_usec * 1000);
|
||||
|
||||
Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
|
||||
|
||||
FILETIME ft;
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
|
||||
|
||||
// A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
|
||||
// is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
|
||||
Timestamp timestamp;
|
||||
timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
|
||||
timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
|
||||
|
||||
Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.
|
||||
|
||||
long millis = System.currentTimeMillis();
|
||||
|
||||
Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
|
||||
.setNanos((int) ((millis % 1000) * 1000000)).build();
|
||||
|
||||
Example 5: Compute Timestamp from Java `Instant.now()`.
|
||||
|
||||
Instant now = Instant.now();
|
||||
|
||||
Timestamp timestamp =
|
||||
Timestamp.newBuilder().setSeconds(now.getEpochSecond())
|
||||
.setNanos(now.getNano()).build();
|
||||
|
||||
Example 6: Compute Timestamp from current time in Python.
|
||||
|
||||
timestamp = Timestamp()
|
||||
timestamp.GetCurrentTime()
|
||||
|
||||
# JSON Mapping
|
||||
|
||||
In JSON format, the Timestamp type is encoded as a string in the
|
||||
[RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the
|
||||
format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z"
|
||||
where {year} is always expressed using four digits while {month}, {day},
|
||||
{hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
|
||||
seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
|
||||
are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
|
||||
is required. A proto3 JSON serializer should always use UTC (as indicated by
|
||||
"Z") when printing the Timestamp type and a proto3 JSON parser should be
|
||||
able to accept both UTC and other timezones (as indicated by an offset).
|
||||
|
||||
For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
|
||||
01:30 UTC on January 15, 2017.
|
||||
|
||||
In JavaScript, one can convert a Date object to this format using the
|
||||
standard
|
||||
[toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString)
|
||||
method. In Python, a standard `datetime.datetime` object can be converted
|
||||
to this format using
|
||||
[`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with
|
||||
the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use
|
||||
the Joda Time's [`ISODateTimeFormat.dateTime()`](
|
||||
http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime()
|
||||
) to obtain a formatter capable of generating timestamps in this format.
|
||||
item.v1.CreateItemRequest:
|
||||
type: object
|
||||
properties:
|
||||
username:
|
||||
type: string
|
||||
title: username
|
||||
password:
|
||||
type: string
|
||||
title: password
|
||||
title: LoginRequest
|
||||
item:
|
||||
title: item
|
||||
$ref: '#/components/schemas/item.v1.Item'
|
||||
title: CreateItemRequest
|
||||
additionalProperties: false
|
||||
user.v1.LoginResponse:
|
||||
item.v1.CreateItemResponse:
|
||||
type: object
|
||||
properties:
|
||||
token:
|
||||
type: string
|
||||
title: token
|
||||
title: LoginResponse
|
||||
item:
|
||||
title: item
|
||||
$ref: '#/components/schemas/item.v1.Item'
|
||||
title: CreateItemResponse
|
||||
additionalProperties: false
|
||||
user.v1.LogoutRequest:
|
||||
type: object
|
||||
title: LogoutRequest
|
||||
additionalProperties: false
|
||||
user.v1.LogoutResponse:
|
||||
type: object
|
||||
title: LogoutResponse
|
||||
additionalProperties: false
|
||||
user.v1.SignUpRequest:
|
||||
item.v1.DeleteItemRequest:
|
||||
type: object
|
||||
properties:
|
||||
username:
|
||||
type: string
|
||||
title: username
|
||||
password:
|
||||
type: string
|
||||
title: password
|
||||
confirmPassword:
|
||||
type: string
|
||||
title: confirm_password
|
||||
title: SignUpRequest
|
||||
id:
|
||||
type: integer
|
||||
title: id
|
||||
title: DeleteItemRequest
|
||||
additionalProperties: false
|
||||
user.v1.SignUpResponse:
|
||||
item.v1.DeleteItemResponse:
|
||||
type: object
|
||||
title: SignUpResponse
|
||||
title: DeleteItemResponse
|
||||
additionalProperties: false
|
||||
item.v1.GetItemRequest:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
title: id
|
||||
title: GetItemRequest
|
||||
additionalProperties: false
|
||||
item.v1.GetItemResponse:
|
||||
type: object
|
||||
properties:
|
||||
item:
|
||||
title: item
|
||||
$ref: '#/components/schemas/item.v1.Item'
|
||||
title: GetItemResponse
|
||||
additionalProperties: false
|
||||
item.v1.GetItemsRequest:
|
||||
type: object
|
||||
properties:
|
||||
start:
|
||||
title: start
|
||||
nullable: true
|
||||
$ref: '#/components/schemas/google.protobuf.Timestamp'
|
||||
end:
|
||||
title: end
|
||||
nullable: true
|
||||
$ref: '#/components/schemas/google.protobuf.Timestamp'
|
||||
filter:
|
||||
type: string
|
||||
title: filter
|
||||
nullable: true
|
||||
limit:
|
||||
type: integer
|
||||
title: limit
|
||||
nullable: true
|
||||
offset:
|
||||
type: integer
|
||||
title: offset
|
||||
nullable: true
|
||||
title: GetItemsRequest
|
||||
additionalProperties: false
|
||||
item.v1.GetItemsResponse:
|
||||
type: object
|
||||
properties:
|
||||
items:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/item.v1.Item'
|
||||
title: items
|
||||
count:
|
||||
type:
|
||||
- integer
|
||||
- string
|
||||
title: count
|
||||
format: int64
|
||||
title: GetItemsResponse
|
||||
additionalProperties: false
|
||||
item.v1.Item:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
title: id
|
||||
nullable: true
|
||||
name:
|
||||
type: string
|
||||
title: name
|
||||
description:
|
||||
type: string
|
||||
title: description
|
||||
price:
|
||||
type: number
|
||||
title: price
|
||||
format: float
|
||||
quantity:
|
||||
type: integer
|
||||
title: quantity
|
||||
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'
|
||||
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:
|
||||
type: number
|
||||
@ -117,6 +292,51 @@ components:
|
||||
additionalProperties: true
|
||||
additionalProperties: true
|
||||
description: Contains an arbitrary serialized message along with a @type that describes the type of the serialized message.
|
||||
user.v1.LoginRequest:
|
||||
type: object
|
||||
properties:
|
||||
username:
|
||||
type: string
|
||||
title: username
|
||||
password:
|
||||
type: string
|
||||
title: password
|
||||
title: LoginRequest
|
||||
additionalProperties: false
|
||||
user.v1.LoginResponse:
|
||||
type: object
|
||||
properties:
|
||||
token:
|
||||
type: string
|
||||
title: token
|
||||
title: LoginResponse
|
||||
additionalProperties: false
|
||||
user.v1.LogoutRequest:
|
||||
type: object
|
||||
title: LogoutRequest
|
||||
additionalProperties: false
|
||||
user.v1.LogoutResponse:
|
||||
type: object
|
||||
title: LogoutResponse
|
||||
additionalProperties: false
|
||||
user.v1.SignUpRequest:
|
||||
type: object
|
||||
properties:
|
||||
username:
|
||||
type: string
|
||||
title: username
|
||||
password:
|
||||
type: string
|
||||
title: password
|
||||
confirmPassword:
|
||||
type: string
|
||||
title: confirm_password
|
||||
title: SignUpRequest
|
||||
additionalProperties: false
|
||||
user.v1.SignUpResponse:
|
||||
type: object
|
||||
title: SignUpResponse
|
||||
additionalProperties: false
|
||||
user.v1.APIKeyRequest:
|
||||
type: object
|
||||
properties:
|
||||
@ -157,6 +377,181 @@ components:
|
||||
security:
|
||||
- bearerAuth: []
|
||||
paths:
|
||||
/item.v1.ItemService/GetItem:
|
||||
post:
|
||||
tags:
|
||||
- item.v1.ItemService
|
||||
summary: GetItem
|
||||
operationId: item.v1.ItemService.GetItem
|
||||
parameters:
|
||||
- name: Connect-Protocol-Version
|
||||
in: header
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/components/schemas/connect-protocol-version'
|
||||
- name: Connect-Timeout-Ms
|
||||
in: header
|
||||
schema:
|
||||
$ref: '#/components/schemas/connect-timeout-header'
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/item.v1.GetItemRequest'
|
||||
required: true
|
||||
responses:
|
||||
default:
|
||||
description: Error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/connect.error'
|
||||
"200":
|
||||
description: Success
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/item.v1.GetItemResponse'
|
||||
/item.v1.ItemService/GetItems:
|
||||
post:
|
||||
tags:
|
||||
- item.v1.ItemService
|
||||
summary: GetItems
|
||||
operationId: item.v1.ItemService.GetItems
|
||||
parameters:
|
||||
- name: Connect-Protocol-Version
|
||||
in: header
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/components/schemas/connect-protocol-version'
|
||||
- name: Connect-Timeout-Ms
|
||||
in: header
|
||||
schema:
|
||||
$ref: '#/components/schemas/connect-timeout-header'
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/item.v1.GetItemsRequest'
|
||||
required: true
|
||||
responses:
|
||||
default:
|
||||
description: Error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/connect.error'
|
||||
"200":
|
||||
description: Success
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/item.v1.GetItemsResponse'
|
||||
/item.v1.ItemService/CreateItem:
|
||||
post:
|
||||
tags:
|
||||
- item.v1.ItemService
|
||||
summary: CreateItem
|
||||
operationId: item.v1.ItemService.CreateItem
|
||||
parameters:
|
||||
- name: Connect-Protocol-Version
|
||||
in: header
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/components/schemas/connect-protocol-version'
|
||||
- name: Connect-Timeout-Ms
|
||||
in: header
|
||||
schema:
|
||||
$ref: '#/components/schemas/connect-timeout-header'
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/item.v1.CreateItemRequest'
|
||||
required: true
|
||||
responses:
|
||||
default:
|
||||
description: Error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/connect.error'
|
||||
"200":
|
||||
description: Success
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/item.v1.CreateItemResponse'
|
||||
/item.v1.ItemService/UpdateItem:
|
||||
post:
|
||||
tags:
|
||||
- item.v1.ItemService
|
||||
summary: UpdateItem
|
||||
operationId: item.v1.ItemService.UpdateItem
|
||||
parameters:
|
||||
- name: Connect-Protocol-Version
|
||||
in: header
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/components/schemas/connect-protocol-version'
|
||||
- name: Connect-Timeout-Ms
|
||||
in: header
|
||||
schema:
|
||||
$ref: '#/components/schemas/connect-timeout-header'
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/item.v1.UpdateItemRequest'
|
||||
required: true
|
||||
responses:
|
||||
default:
|
||||
description: Error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/connect.error'
|
||||
"200":
|
||||
description: Success
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/item.v1.UpdateItemResponse'
|
||||
/item.v1.ItemService/DeleteItem:
|
||||
post:
|
||||
tags:
|
||||
- item.v1.ItemService
|
||||
summary: DeleteItem
|
||||
operationId: item.v1.ItemService.DeleteItem
|
||||
parameters:
|
||||
- name: Connect-Protocol-Version
|
||||
in: header
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/components/schemas/connect-protocol-version'
|
||||
- name: Connect-Timeout-Ms
|
||||
in: header
|
||||
schema:
|
||||
$ref: '#/components/schemas/connect-timeout-header'
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/item.v1.DeleteItemRequest'
|
||||
required: true
|
||||
responses:
|
||||
default:
|
||||
description: Error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/connect.error'
|
||||
"200":
|
||||
description: Success
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/item.v1.DeleteItemResponse'
|
||||
/user.v1.AuthService/Login:
|
||||
post:
|
||||
tags:
|
||||
@ -333,5 +728,6 @@ paths:
|
||||
schema:
|
||||
$ref: '#/components/schemas/user.v1.APIKeyResponse'
|
||||
tags:
|
||||
- name: item.v1.ItemService
|
||||
- name: user.v1.AuthService
|
||||
- name: user.v1.UserService
|
||||
|
@ -68,9 +68,6 @@
|
||||
# Svelte frontend
|
||||
nodejs_22
|
||||
|
||||
# Openapi gen
|
||||
openapi-generator-cli
|
||||
|
||||
# Helper scripts
|
||||
(writeShellApplication {
|
||||
name = "run";
|
||||
@ -91,6 +88,8 @@
|
||||
wait $P1
|
||||
wait $P2
|
||||
wait $P3
|
||||
|
||||
kill $P1 $P2 $P3
|
||||
'';
|
||||
})
|
||||
|
||||
|
60
proto/item/v1/item.proto
Normal file
60
proto/item/v1/item.proto
Normal file
@ -0,0 +1,60 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package item.v1;
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
message Item {
|
||||
optional uint32 id = 1;
|
||||
string name = 2;
|
||||
string description = 3;
|
||||
float price = 4;
|
||||
uint32 quantity = 5;
|
||||
optional google.protobuf.Timestamp added = 6;
|
||||
}
|
||||
|
||||
service ItemService {
|
||||
rpc GetItem (GetItemRequest) returns (GetItemResponse) {}
|
||||
rpc GetItems (GetItemsRequest) returns (GetItemsResponse) {}
|
||||
rpc CreateItem (CreateItemRequest) returns (CreateItemResponse) {}
|
||||
rpc UpdateItem (UpdateItemRequest) returns (UpdateItemResponse) {}
|
||||
rpc DeleteItem (DeleteItemRequest) returns (DeleteItemResponse) {}
|
||||
}
|
||||
|
||||
message GetItemRequest {
|
||||
uint32 id = 1;
|
||||
}
|
||||
message GetItemResponse {
|
||||
Item item = 1;
|
||||
}
|
||||
|
||||
message GetItemsRequest {
|
||||
optional google.protobuf.Timestamp start = 1;
|
||||
optional google.protobuf.Timestamp end = 2;
|
||||
optional string filter = 3;
|
||||
optional uint32 limit = 4;
|
||||
optional uint32 offset = 5;
|
||||
}
|
||||
message GetItemsResponse {
|
||||
repeated Item items = 1;
|
||||
uint64 count = 2;
|
||||
}
|
||||
|
||||
message CreateItemRequest {
|
||||
Item item = 1;
|
||||
}
|
||||
message CreateItemResponse {
|
||||
Item item = 1;
|
||||
}
|
||||
|
||||
message UpdateItemRequest {
|
||||
Item item = 1;
|
||||
}
|
||||
message UpdateItemResponse {
|
||||
Item item = 1;
|
||||
}
|
||||
|
||||
message DeleteItemRequest {
|
||||
uint32 id = 1;
|
||||
}
|
||||
message DeleteItemResponse {}
|
@ -6,7 +6,7 @@ import (
|
||||
)
|
||||
|
||||
func Migrate(db *gorm.DB) error {
|
||||
err := db.AutoMigrate(&models.User{})
|
||||
err := db.AutoMigrate(&models.User{}, &models.Item{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
171
server/internal/handlers/item.go
Normal file
171
server/internal/handlers/item.go
Normal file
@ -0,0 +1,171 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"connectrpc.com/connect"
|
||||
"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"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type ItemHandler struct {
|
||||
db *gorm.DB
|
||||
key []byte
|
||||
}
|
||||
|
||||
func (h *ItemHandler) GetItem(ctx context.Context, req *connect.Request[itemv1.GetItemRequest]) (*connect.Response[itemv1.GetItemResponse], error) {
|
||||
userid, ok := interceptors.UserFromContext(ctx)
|
||||
if !ok {
|
||||
return nil, connect.NewError(connect.CodeUnauthenticated, errors.New("unauthenticated"))
|
||||
}
|
||||
|
||||
// Get item
|
||||
item := models.Item{}
|
||||
if err := h.db.First(&item, "id = ? AND user_id = ?", req.Msg.Id, userid).Error; err != nil {
|
||||
return nil, connect.NewError(connect.CodeNotFound, err)
|
||||
}
|
||||
|
||||
res := connect.NewResponse(&itemv1.GetItemResponse{
|
||||
Item: item.ToConnectV1(),
|
||||
})
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *ItemHandler) GetItems(ctx context.Context, req *connect.Request[itemv1.GetItemsRequest]) (*connect.Response[itemv1.GetItemsResponse], error) {
|
||||
userid, ok := interceptors.UserFromContext(ctx)
|
||||
if !ok {
|
||||
return nil, connect.NewError(connect.CodeUnauthenticated, errors.New("unauthenticated"))
|
||||
}
|
||||
|
||||
// Filters
|
||||
sql := h.db.Where("user_id = ?", userid)
|
||||
if req.Msg.Start != nil {
|
||||
sql = sql.Where("added >= ?", req.Msg.Start.AsTime())
|
||||
}
|
||||
if req.Msg.End != nil {
|
||||
sql = sql.Where("added <= ?", req.Msg.End.AsTime())
|
||||
}
|
||||
if req.Msg.Filter != nil {
|
||||
sql = sql.Where("name LIKE ?", fmt.Sprintf("%%%s%%", *req.Msg.Filter))
|
||||
}
|
||||
|
||||
// Uncounted filters
|
||||
sqlu := sql.Session(&gorm.Session{})
|
||||
if req.Msg.Limit != nil {
|
||||
sqlu = sqlu.Limit(int(*req.Msg.Limit))
|
||||
}
|
||||
if req.Msg.Offset != nil {
|
||||
sqlu = sqlu.Offset(int(*req.Msg.Offset))
|
||||
}
|
||||
|
||||
// Get items & count
|
||||
items := []models.Item{}
|
||||
var count int64
|
||||
if err := sqlu.Order("added desc").Find(&items).Error; err != nil {
|
||||
return nil, connect.NewError(connect.CodeNotFound, err)
|
||||
}
|
||||
if err := sql.Model(&items).Count(&count).Error; err != nil {
|
||||
return nil, connect.NewError(connect.CodeInternal, err)
|
||||
}
|
||||
|
||||
// Convert to connect v1 items
|
||||
resItems := []*itemv1.Item{}
|
||||
for _, item := range items {
|
||||
resItems = append(resItems, item.ToConnectV1())
|
||||
}
|
||||
|
||||
res := connect.NewResponse(&itemv1.GetItemsResponse{
|
||||
Items: resItems,
|
||||
Count: uint64(count),
|
||||
})
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *ItemHandler) CreateItem(ctx context.Context, req *connect.Request[itemv1.CreateItemRequest]) (*connect.Response[itemv1.CreateItemResponse], error) {
|
||||
userid, ok := interceptors.UserFromContext(ctx)
|
||||
if !ok {
|
||||
return nil, connect.NewError(connect.CodeUnauthenticated, errors.New("unauthenticated"))
|
||||
}
|
||||
|
||||
// Create item
|
||||
item := models.Item{
|
||||
Name: req.Msg.Item.Name,
|
||||
Description: req.Msg.Item.Description,
|
||||
Price: req.Msg.Item.Price,
|
||||
Quantity: int(req.Msg.Item.Quantity),
|
||||
Added: time.Now(),
|
||||
UserID: uint(userid),
|
||||
}
|
||||
if err := h.db.Create(&item).Error; err != nil {
|
||||
return nil, connect.NewError(connect.CodeInternal, err)
|
||||
}
|
||||
|
||||
res := connect.NewResponse(&itemv1.CreateItemResponse{
|
||||
Item: item.ToConnectV1(),
|
||||
})
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *ItemHandler) UpdateItem(ctx context.Context, req *connect.Request[itemv1.UpdateItemRequest]) (*connect.Response[itemv1.UpdateItemResponse], error) {
|
||||
userid, ok := interceptors.UserFromContext(ctx)
|
||||
if !ok {
|
||||
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 := models.Item{
|
||||
ID: *req.Msg.Item.Id,
|
||||
Name: req.Msg.Item.Name,
|
||||
Description: req.Msg.Item.Description,
|
||||
Price: req.Msg.Item.Price,
|
||||
Quantity: int(req.Msg.Item.Quantity),
|
||||
UserID: uint(userid),
|
||||
}
|
||||
if err := h.db.Where("id = ? AND user_id = ?", req.Msg.Item.Id, userid).Updates(&item).Error; err != nil {
|
||||
return nil, connect.NewError(connect.CodeInternal, err)
|
||||
}
|
||||
|
||||
res := connect.NewResponse(&itemv1.UpdateItemResponse{
|
||||
Item: item.ToConnectV1(),
|
||||
})
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (h *ItemHandler) DeleteItem(ctx context.Context, req *connect.Request[itemv1.DeleteItemRequest]) (*connect.Response[itemv1.DeleteItemResponse], error) {
|
||||
userid, ok := interceptors.UserFromContext(ctx)
|
||||
if !ok {
|
||||
return nil, connect.NewError(connect.CodeUnauthenticated, errors.New("unauthenticated"))
|
||||
}
|
||||
|
||||
// Delete item
|
||||
if err := h.db.Delete(&models.Item{}, "id = ? AND user_id = ?", req.Msg.Id, userid).Error; err != nil {
|
||||
return nil, connect.NewError(connect.CodeInternal, err)
|
||||
}
|
||||
|
||||
res := connect.NewResponse(&itemv1.DeleteItemResponse{})
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func NewItemHandler(db *gorm.DB, key string) (string, http.Handler) {
|
||||
interceptors := connect.WithInterceptors(interceptors.NewAuthInterceptor(key))
|
||||
|
||||
return itemv1connect.NewItemServiceHandler(
|
||||
&ItemHandler{
|
||||
db: db,
|
||||
key: []byte(key),
|
||||
},
|
||||
interceptors,
|
||||
)
|
||||
}
|
@ -24,11 +24,12 @@ func WithAuthRedirect(next http.Handler, key string) http.Handler {
|
||||
}
|
||||
|
||||
switch pathItems[1] {
|
||||
case "auth":
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
|
||||
case "auth":
|
||||
fallthrough
|
||||
case "_app":
|
||||
fallthrough
|
||||
case "favicon.png":
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
|
||||
|
@ -2,7 +2,7 @@ package interceptors
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"errors"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@ -44,8 +44,11 @@ func (i *ratelimitInterceptor) WrapUnary(next connect.UnaryFunc) connect.UnaryFu
|
||||
return next(ctx, req)
|
||||
}
|
||||
|
||||
// Get ip
|
||||
log.Println(req.Peer().Addr)
|
||||
// Get user agent
|
||||
limiter := i.getVisitor(req.Header().Get("User-Agent"))
|
||||
if limiter.Allow() == false {
|
||||
return nil, connect.NewError(connect.CodeResourceExhausted, errors.New("rate limit exceeded"))
|
||||
}
|
||||
|
||||
return next(ctx, req)
|
||||
})
|
||||
@ -65,22 +68,25 @@ func (i *ratelimitInterceptor) WrapStreamingHandler(next connect.StreamingHandle
|
||||
ctx context.Context,
|
||||
conn connect.StreamingHandlerConn,
|
||||
) error {
|
||||
// Get ip
|
||||
log.Println(conn.Peer().Query)
|
||||
// Get user agent
|
||||
limiter := i.getVisitor(conn.RequestHeader().Get("User-Agent"))
|
||||
if limiter.Allow() == false {
|
||||
return connect.NewError(connect.CodeResourceExhausted, errors.New("rate limit exceeded"))
|
||||
}
|
||||
|
||||
return next(ctx, conn)
|
||||
})
|
||||
}
|
||||
|
||||
func (i *ratelimitInterceptor) getVisitor(ip string) *rate.Limiter {
|
||||
func (i *ratelimitInterceptor) getVisitor(userAgent string) *rate.Limiter {
|
||||
i.mu.Lock()
|
||||
defer i.mu.Unlock()
|
||||
|
||||
v, exists := i.visitors[ip]
|
||||
v, exists := i.visitors[userAgent]
|
||||
if !exists {
|
||||
limiter := rate.NewLimiter(1, 3)
|
||||
// Include the current time when creating a new visitor.
|
||||
i.visitors[ip] = &visitor{limiter, time.Now()}
|
||||
i.visitors[userAgent] = &visitor{limiter, time.Now()}
|
||||
return limiter
|
||||
}
|
||||
|
||||
|
33
server/internal/models/item.go
Normal file
33
server/internal/models/item.go
Normal file
@ -0,0 +1,33 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
itemv1 "github.com/spotdemo4/trevstack/server/internal/services/item/v1"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
type Item struct {
|
||||
ID uint32 `gorm:"primaryKey"`
|
||||
|
||||
Name string
|
||||
Description string
|
||||
Price float32
|
||||
Quantity int
|
||||
Added time.Time
|
||||
|
||||
// User
|
||||
UserID uint
|
||||
User User
|
||||
}
|
||||
|
||||
func (i Item) ToConnectV1() *itemv1.Item {
|
||||
return &itemv1.Item{
|
||||
Id: &i.ID,
|
||||
Name: i.Name,
|
||||
Description: i.Description,
|
||||
Price: i.Price,
|
||||
Quantity: uint32(i.Quantity),
|
||||
Added: timestamppb.New(i.Added),
|
||||
}
|
||||
}
|
759
server/internal/services/item/v1/item.pb.go
Normal file
759
server/internal/services/item/v1/item.pb.go
Normal file
@ -0,0 +1,759 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.36.5
|
||||
// protoc (unknown)
|
||||
// source: item/v1/item.proto
|
||||
|
||||
package itemv1
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
unsafe "unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type Item struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Id *uint32 `protobuf:"varint,1,opt,name=id,proto3,oneof" 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 uint32 `protobuf:"varint,5,opt,name=quantity,proto3" json:"quantity,omitempty"`
|
||||
Added *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=added,proto3,oneof" json:"added,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *Item) Reset() {
|
||||
*x = Item{}
|
||||
mi := &file_item_v1_item_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *Item) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Item) ProtoMessage() {}
|
||||
|
||||
func (x *Item) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_item_v1_item_proto_msgTypes[0]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Item.ProtoReflect.Descriptor instead.
|
||||
func (*Item) Descriptor() ([]byte, []int) {
|
||||
return file_item_v1_item_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *Item) GetId() uint32 {
|
||||
if x != nil && x.Id != nil {
|
||||
return *x.Id
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Item) GetName() string {
|
||||
if x != nil {
|
||||
return x.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Item) GetDescription() string {
|
||||
if x != nil {
|
||||
return x.Description
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Item) GetPrice() float32 {
|
||||
if x != nil {
|
||||
return x.Price
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Item) GetQuantity() uint32 {
|
||||
if x != nil {
|
||||
return x.Quantity
|
||||
}
|
||||
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 uint32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GetItemRequest) Reset() {
|
||||
*x = GetItemRequest{}
|
||||
mi := &file_item_v1_item_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GetItemRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetItemRequest) ProtoMessage() {}
|
||||
|
||||
func (x *GetItemRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_item_v1_item_proto_msgTypes[1]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use GetItemRequest.ProtoReflect.Descriptor instead.
|
||||
func (*GetItemRequest) Descriptor() ([]byte, []int) {
|
||||
return file_item_v1_item_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *GetItemRequest) GetId() uint32 {
|
||||
if x != nil {
|
||||
return x.Id
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type GetItemResponse 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
|
||||
}
|
||||
|
||||
func (x *GetItemResponse) Reset() {
|
||||
*x = GetItemResponse{}
|
||||
mi := &file_item_v1_item_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GetItemResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetItemResponse) ProtoMessage() {}
|
||||
|
||||
func (x *GetItemResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_item_v1_item_proto_msgTypes[2]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use GetItemResponse.ProtoReflect.Descriptor instead.
|
||||
func (*GetItemResponse) Descriptor() ([]byte, []int) {
|
||||
return file_item_v1_item_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *GetItemResponse) GetItem() *Item {
|
||||
if x != nil {
|
||||
return x.Item
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type GetItemsRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Start *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=start,proto3,oneof" json:"start,omitempty"`
|
||||
End *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=end,proto3,oneof" json:"end,omitempty"`
|
||||
Filter *string `protobuf:"bytes,3,opt,name=filter,proto3,oneof" json:"filter,omitempty"`
|
||||
Limit *uint32 `protobuf:"varint,4,opt,name=limit,proto3,oneof" json:"limit,omitempty"`
|
||||
Offset *uint32 `protobuf:"varint,5,opt,name=offset,proto3,oneof" json:"offset,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GetItemsRequest) Reset() {
|
||||
*x = GetItemsRequest{}
|
||||
mi := &file_item_v1_item_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GetItemsRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetItemsRequest) ProtoMessage() {}
|
||||
|
||||
func (x *GetItemsRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_item_v1_item_proto_msgTypes[3]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use GetItemsRequest.ProtoReflect.Descriptor instead.
|
||||
func (*GetItemsRequest) Descriptor() ([]byte, []int) {
|
||||
return file_item_v1_item_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *GetItemsRequest) GetStart() *timestamppb.Timestamp {
|
||||
if x != nil {
|
||||
return x.Start
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *GetItemsRequest) GetEnd() *timestamppb.Timestamp {
|
||||
if x != nil {
|
||||
return x.End
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *GetItemsRequest) GetFilter() string {
|
||||
if x != nil && x.Filter != nil {
|
||||
return *x.Filter
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *GetItemsRequest) GetLimit() uint32 {
|
||||
if x != nil && x.Limit != nil {
|
||||
return *x.Limit
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *GetItemsRequest) GetOffset() uint32 {
|
||||
if x != nil && x.Offset != nil {
|
||||
return *x.Offset
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type GetItemsResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Items []*Item `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"`
|
||||
Count uint64 `protobuf:"varint,2,opt,name=count,proto3" json:"count,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GetItemsResponse) Reset() {
|
||||
*x = GetItemsResponse{}
|
||||
mi := &file_item_v1_item_proto_msgTypes[4]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GetItemsResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetItemsResponse) ProtoMessage() {}
|
||||
|
||||
func (x *GetItemsResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_item_v1_item_proto_msgTypes[4]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use GetItemsResponse.ProtoReflect.Descriptor instead.
|
||||
func (*GetItemsResponse) Descriptor() ([]byte, []int) {
|
||||
return file_item_v1_item_proto_rawDescGZIP(), []int{4}
|
||||
}
|
||||
|
||||
func (x *GetItemsResponse) GetItems() []*Item {
|
||||
if x != nil {
|
||||
return x.Items
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *GetItemsResponse) GetCount() uint64 {
|
||||
if x != nil {
|
||||
return x.Count
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type CreateItemRequest 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
|
||||
}
|
||||
|
||||
func (x *CreateItemRequest) Reset() {
|
||||
*x = CreateItemRequest{}
|
||||
mi := &file_item_v1_item_proto_msgTypes[5]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *CreateItemRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*CreateItemRequest) ProtoMessage() {}
|
||||
|
||||
func (x *CreateItemRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_item_v1_item_proto_msgTypes[5]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use CreateItemRequest.ProtoReflect.Descriptor instead.
|
||||
func (*CreateItemRequest) Descriptor() ([]byte, []int) {
|
||||
return file_item_v1_item_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
func (x *CreateItemRequest) GetItem() *Item {
|
||||
if x != nil {
|
||||
return x.Item
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type CreateItemResponse 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
|
||||
}
|
||||
|
||||
func (x *CreateItemResponse) Reset() {
|
||||
*x = CreateItemResponse{}
|
||||
mi := &file_item_v1_item_proto_msgTypes[6]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *CreateItemResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*CreateItemResponse) ProtoMessage() {}
|
||||
|
||||
func (x *CreateItemResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_item_v1_item_proto_msgTypes[6]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use CreateItemResponse.ProtoReflect.Descriptor instead.
|
||||
func (*CreateItemResponse) Descriptor() ([]byte, []int) {
|
||||
return file_item_v1_item_proto_rawDescGZIP(), []int{6}
|
||||
}
|
||||
|
||||
func (x *CreateItemResponse) GetItem() *Item {
|
||||
if x != nil {
|
||||
return x.Item
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type UpdateItemRequest 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
|
||||
}
|
||||
|
||||
func (x *UpdateItemRequest) Reset() {
|
||||
*x = UpdateItemRequest{}
|
||||
mi := &file_item_v1_item_proto_msgTypes[7]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *UpdateItemRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*UpdateItemRequest) ProtoMessage() {}
|
||||
|
||||
func (x *UpdateItemRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_item_v1_item_proto_msgTypes[7]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use UpdateItemRequest.ProtoReflect.Descriptor instead.
|
||||
func (*UpdateItemRequest) Descriptor() ([]byte, []int) {
|
||||
return file_item_v1_item_proto_rawDescGZIP(), []int{7}
|
||||
}
|
||||
|
||||
func (x *UpdateItemRequest) GetItem() *Item {
|
||||
if x != nil {
|
||||
return x.Item
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
func (x *UpdateItemResponse) Reset() {
|
||||
*x = UpdateItemResponse{}
|
||||
mi := &file_item_v1_item_proto_msgTypes[8]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *UpdateItemResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*UpdateItemResponse) ProtoMessage() {}
|
||||
|
||||
func (x *UpdateItemResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_item_v1_item_proto_msgTypes[8]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use UpdateItemResponse.ProtoReflect.Descriptor instead.
|
||||
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 uint32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *DeleteItemRequest) Reset() {
|
||||
*x = DeleteItemRequest{}
|
||||
mi := &file_item_v1_item_proto_msgTypes[9]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *DeleteItemRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*DeleteItemRequest) ProtoMessage() {}
|
||||
|
||||
func (x *DeleteItemRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_item_v1_item_proto_msgTypes[9]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use DeleteItemRequest.ProtoReflect.Descriptor instead.
|
||||
func (*DeleteItemRequest) Descriptor() ([]byte, []int) {
|
||||
return file_item_v1_item_proto_rawDescGZIP(), []int{9}
|
||||
}
|
||||
|
||||
func (x *DeleteItemRequest) GetId() uint32 {
|
||||
if x != nil {
|
||||
return x.Id
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type DeleteItemResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *DeleteItemResponse) Reset() {
|
||||
*x = DeleteItemResponse{}
|
||||
mi := &file_item_v1_item_proto_msgTypes[10]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *DeleteItemResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*DeleteItemResponse) ProtoMessage() {}
|
||||
|
||||
func (x *DeleteItemResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_item_v1_item_proto_msgTypes[10]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use DeleteItemResponse.ProtoReflect.Descriptor instead.
|
||||
func (*DeleteItemResponse) Descriptor() ([]byte, []int) {
|
||||
return file_item_v1_item_proto_rawDescGZIP(), []int{10}
|
||||
}
|
||||
|
||||
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, 0x0d, 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, 0x0d, 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, 0x0d, 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, 0x0d, 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, 0x0d, 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,
|
||||
0x04, 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, 0x0d, 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,
|
||||
})
|
||||
|
||||
var (
|
||||
file_item_v1_item_proto_rawDescOnce sync.Once
|
||||
file_item_v1_item_proto_rawDescData []byte
|
||||
)
|
||||
|
||||
func file_item_v1_item_proto_rawDescGZIP() []byte {
|
||||
file_item_v1_item_proto_rawDescOnce.Do(func() {
|
||||
file_item_v1_item_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_item_v1_item_proto_rawDesc), len(file_item_v1_item_proto_rawDesc)))
|
||||
})
|
||||
return file_item_v1_item_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_item_v1_item_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
|
||||
var file_item_v1_item_proto_goTypes = []any{
|
||||
(*Item)(nil), // 0: item.v1.Item
|
||||
(*GetItemRequest)(nil), // 1: item.v1.GetItemRequest
|
||||
(*GetItemResponse)(nil), // 2: item.v1.GetItemResponse
|
||||
(*GetItemsRequest)(nil), // 3: item.v1.GetItemsRequest
|
||||
(*GetItemsResponse)(nil), // 4: item.v1.GetItemsResponse
|
||||
(*CreateItemRequest)(nil), // 5: item.v1.CreateItemRequest
|
||||
(*CreateItemResponse)(nil), // 6: item.v1.CreateItemResponse
|
||||
(*UpdateItemRequest)(nil), // 7: item.v1.UpdateItemRequest
|
||||
(*UpdateItemResponse)(nil), // 8: item.v1.UpdateItemResponse
|
||||
(*DeleteItemRequest)(nil), // 9: item.v1.DeleteItemRequest
|
||||
(*DeleteItemResponse)(nil), // 10: item.v1.DeleteItemResponse
|
||||
(*timestamppb.Timestamp)(nil), // 11: google.protobuf.Timestamp
|
||||
}
|
||||
var file_item_v1_item_proto_depIdxs = []int32{
|
||||
11, // 0: item.v1.Item.added:type_name -> google.protobuf.Timestamp
|
||||
0, // 1: item.v1.GetItemResponse.item:type_name -> item.v1.Item
|
||||
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
|
||||
}
|
||||
|
||||
func init() { file_item_v1_item_proto_init() }
|
||||
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{}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_item_v1_item_proto_rawDesc), len(file_item_v1_item_proto_rawDesc)),
|
||||
NumEnums: 0,
|
||||
NumMessages: 11,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
GoTypes: file_item_v1_item_proto_goTypes,
|
||||
DependencyIndexes: file_item_v1_item_proto_depIdxs,
|
||||
MessageInfos: file_item_v1_item_proto_msgTypes,
|
||||
}.Build()
|
||||
File_item_v1_item_proto = out.File
|
||||
file_item_v1_item_proto_goTypes = nil
|
||||
file_item_v1_item_proto_depIdxs = nil
|
||||
}
|
220
server/internal/services/item/v1/itemv1connect/item.connect.go
Normal file
220
server/internal/services/item/v1/itemv1connect/item.connect.go
Normal file
@ -0,0 +1,220 @@
|
||||
// Code generated by protoc-gen-connect-go. DO NOT EDIT.
|
||||
//
|
||||
// Source: item/v1/item.proto
|
||||
|
||||
package itemv1connect
|
||||
|
||||
import (
|
||||
connect "connectrpc.com/connect"
|
||||
context "context"
|
||||
errors "errors"
|
||||
v1 "github.com/spotdemo4/trevstack/server/internal/services/item/v1"
|
||||
http "net/http"
|
||||
strings "strings"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file and the connect package are
|
||||
// compatible. If you get a compiler error that this constant is not defined, this code was
|
||||
// generated with a version of connect newer than the one compiled into your binary. You can fix the
|
||||
// problem by either regenerating this code with an older version of connect or updating the connect
|
||||
// version compiled into your binary.
|
||||
const _ = connect.IsAtLeastVersion1_13_0
|
||||
|
||||
const (
|
||||
// ItemServiceName is the fully-qualified name of the ItemService service.
|
||||
ItemServiceName = "item.v1.ItemService"
|
||||
)
|
||||
|
||||
// These constants are the fully-qualified names of the RPCs defined in this package. They're
|
||||
// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route.
|
||||
//
|
||||
// Note that these are different from the fully-qualified method names used by
|
||||
// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to
|
||||
// reflection-formatted method names, remove the leading slash and convert the remaining slash to a
|
||||
// period.
|
||||
const (
|
||||
// ItemServiceGetItemProcedure is the fully-qualified name of the ItemService's GetItem RPC.
|
||||
ItemServiceGetItemProcedure = "/item.v1.ItemService/GetItem"
|
||||
// ItemServiceGetItemsProcedure is the fully-qualified name of the ItemService's GetItems RPC.
|
||||
ItemServiceGetItemsProcedure = "/item.v1.ItemService/GetItems"
|
||||
// ItemServiceCreateItemProcedure is the fully-qualified name of the ItemService's CreateItem RPC.
|
||||
ItemServiceCreateItemProcedure = "/item.v1.ItemService/CreateItem"
|
||||
// ItemServiceUpdateItemProcedure is the fully-qualified name of the ItemService's UpdateItem RPC.
|
||||
ItemServiceUpdateItemProcedure = "/item.v1.ItemService/UpdateItem"
|
||||
// ItemServiceDeleteItemProcedure is the fully-qualified name of the ItemService's DeleteItem RPC.
|
||||
ItemServiceDeleteItemProcedure = "/item.v1.ItemService/DeleteItem"
|
||||
)
|
||||
|
||||
// ItemServiceClient is a client for the item.v1.ItemService service.
|
||||
type ItemServiceClient interface {
|
||||
GetItem(context.Context, *connect.Request[v1.GetItemRequest]) (*connect.Response[v1.GetItemResponse], error)
|
||||
GetItems(context.Context, *connect.Request[v1.GetItemsRequest]) (*connect.Response[v1.GetItemsResponse], error)
|
||||
CreateItem(context.Context, *connect.Request[v1.CreateItemRequest]) (*connect.Response[v1.CreateItemResponse], error)
|
||||
UpdateItem(context.Context, *connect.Request[v1.UpdateItemRequest]) (*connect.Response[v1.UpdateItemResponse], error)
|
||||
DeleteItem(context.Context, *connect.Request[v1.DeleteItemRequest]) (*connect.Response[v1.DeleteItemResponse], error)
|
||||
}
|
||||
|
||||
// NewItemServiceClient constructs a client for the item.v1.ItemService service. By default, it uses
|
||||
// the Connect protocol with the binary Protobuf Codec, asks for gzipped responses, and sends
|
||||
// uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the connect.WithGRPC() or
|
||||
// connect.WithGRPCWeb() options.
|
||||
//
|
||||
// The URL supplied here should be the base URL for the Connect or gRPC server (for example,
|
||||
// http://api.acme.com or https://acme.com/grpc).
|
||||
func NewItemServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) ItemServiceClient {
|
||||
baseURL = strings.TrimRight(baseURL, "/")
|
||||
itemServiceMethods := v1.File_item_v1_item_proto.Services().ByName("ItemService").Methods()
|
||||
return &itemServiceClient{
|
||||
getItem: connect.NewClient[v1.GetItemRequest, v1.GetItemResponse](
|
||||
httpClient,
|
||||
baseURL+ItemServiceGetItemProcedure,
|
||||
connect.WithSchema(itemServiceMethods.ByName("GetItem")),
|
||||
connect.WithClientOptions(opts...),
|
||||
),
|
||||
getItems: connect.NewClient[v1.GetItemsRequest, v1.GetItemsResponse](
|
||||
httpClient,
|
||||
baseURL+ItemServiceGetItemsProcedure,
|
||||
connect.WithSchema(itemServiceMethods.ByName("GetItems")),
|
||||
connect.WithClientOptions(opts...),
|
||||
),
|
||||
createItem: connect.NewClient[v1.CreateItemRequest, v1.CreateItemResponse](
|
||||
httpClient,
|
||||
baseURL+ItemServiceCreateItemProcedure,
|
||||
connect.WithSchema(itemServiceMethods.ByName("CreateItem")),
|
||||
connect.WithClientOptions(opts...),
|
||||
),
|
||||
updateItem: connect.NewClient[v1.UpdateItemRequest, v1.UpdateItemResponse](
|
||||
httpClient,
|
||||
baseURL+ItemServiceUpdateItemProcedure,
|
||||
connect.WithSchema(itemServiceMethods.ByName("UpdateItem")),
|
||||
connect.WithClientOptions(opts...),
|
||||
),
|
||||
deleteItem: connect.NewClient[v1.DeleteItemRequest, v1.DeleteItemResponse](
|
||||
httpClient,
|
||||
baseURL+ItemServiceDeleteItemProcedure,
|
||||
connect.WithSchema(itemServiceMethods.ByName("DeleteItem")),
|
||||
connect.WithClientOptions(opts...),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
// itemServiceClient implements ItemServiceClient.
|
||||
type itemServiceClient struct {
|
||||
getItem *connect.Client[v1.GetItemRequest, v1.GetItemResponse]
|
||||
getItems *connect.Client[v1.GetItemsRequest, v1.GetItemsResponse]
|
||||
createItem *connect.Client[v1.CreateItemRequest, v1.CreateItemResponse]
|
||||
updateItem *connect.Client[v1.UpdateItemRequest, v1.UpdateItemResponse]
|
||||
deleteItem *connect.Client[v1.DeleteItemRequest, v1.DeleteItemResponse]
|
||||
}
|
||||
|
||||
// GetItem calls item.v1.ItemService.GetItem.
|
||||
func (c *itemServiceClient) GetItem(ctx context.Context, req *connect.Request[v1.GetItemRequest]) (*connect.Response[v1.GetItemResponse], error) {
|
||||
return c.getItem.CallUnary(ctx, req)
|
||||
}
|
||||
|
||||
// GetItems calls item.v1.ItemService.GetItems.
|
||||
func (c *itemServiceClient) GetItems(ctx context.Context, req *connect.Request[v1.GetItemsRequest]) (*connect.Response[v1.GetItemsResponse], error) {
|
||||
return c.getItems.CallUnary(ctx, req)
|
||||
}
|
||||
|
||||
// CreateItem calls item.v1.ItemService.CreateItem.
|
||||
func (c *itemServiceClient) CreateItem(ctx context.Context, req *connect.Request[v1.CreateItemRequest]) (*connect.Response[v1.CreateItemResponse], error) {
|
||||
return c.createItem.CallUnary(ctx, req)
|
||||
}
|
||||
|
||||
// UpdateItem calls item.v1.ItemService.UpdateItem.
|
||||
func (c *itemServiceClient) UpdateItem(ctx context.Context, req *connect.Request[v1.UpdateItemRequest]) (*connect.Response[v1.UpdateItemResponse], error) {
|
||||
return c.updateItem.CallUnary(ctx, req)
|
||||
}
|
||||
|
||||
// DeleteItem calls item.v1.ItemService.DeleteItem.
|
||||
func (c *itemServiceClient) DeleteItem(ctx context.Context, req *connect.Request[v1.DeleteItemRequest]) (*connect.Response[v1.DeleteItemResponse], error) {
|
||||
return c.deleteItem.CallUnary(ctx, req)
|
||||
}
|
||||
|
||||
// ItemServiceHandler is an implementation of the item.v1.ItemService service.
|
||||
type ItemServiceHandler interface {
|
||||
GetItem(context.Context, *connect.Request[v1.GetItemRequest]) (*connect.Response[v1.GetItemResponse], error)
|
||||
GetItems(context.Context, *connect.Request[v1.GetItemsRequest]) (*connect.Response[v1.GetItemsResponse], error)
|
||||
CreateItem(context.Context, *connect.Request[v1.CreateItemRequest]) (*connect.Response[v1.CreateItemResponse], error)
|
||||
UpdateItem(context.Context, *connect.Request[v1.UpdateItemRequest]) (*connect.Response[v1.UpdateItemResponse], error)
|
||||
DeleteItem(context.Context, *connect.Request[v1.DeleteItemRequest]) (*connect.Response[v1.DeleteItemResponse], error)
|
||||
}
|
||||
|
||||
// NewItemServiceHandler builds an HTTP handler from the service implementation. It returns the path
|
||||
// on which to mount the handler and the handler itself.
|
||||
//
|
||||
// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf
|
||||
// and JSON codecs. They also support gzip compression.
|
||||
func NewItemServiceHandler(svc ItemServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) {
|
||||
itemServiceMethods := v1.File_item_v1_item_proto.Services().ByName("ItemService").Methods()
|
||||
itemServiceGetItemHandler := connect.NewUnaryHandler(
|
||||
ItemServiceGetItemProcedure,
|
||||
svc.GetItem,
|
||||
connect.WithSchema(itemServiceMethods.ByName("GetItem")),
|
||||
connect.WithHandlerOptions(opts...),
|
||||
)
|
||||
itemServiceGetItemsHandler := connect.NewUnaryHandler(
|
||||
ItemServiceGetItemsProcedure,
|
||||
svc.GetItems,
|
||||
connect.WithSchema(itemServiceMethods.ByName("GetItems")),
|
||||
connect.WithHandlerOptions(opts...),
|
||||
)
|
||||
itemServiceCreateItemHandler := connect.NewUnaryHandler(
|
||||
ItemServiceCreateItemProcedure,
|
||||
svc.CreateItem,
|
||||
connect.WithSchema(itemServiceMethods.ByName("CreateItem")),
|
||||
connect.WithHandlerOptions(opts...),
|
||||
)
|
||||
itemServiceUpdateItemHandler := connect.NewUnaryHandler(
|
||||
ItemServiceUpdateItemProcedure,
|
||||
svc.UpdateItem,
|
||||
connect.WithSchema(itemServiceMethods.ByName("UpdateItem")),
|
||||
connect.WithHandlerOptions(opts...),
|
||||
)
|
||||
itemServiceDeleteItemHandler := connect.NewUnaryHandler(
|
||||
ItemServiceDeleteItemProcedure,
|
||||
svc.DeleteItem,
|
||||
connect.WithSchema(itemServiceMethods.ByName("DeleteItem")),
|
||||
connect.WithHandlerOptions(opts...),
|
||||
)
|
||||
return "/item.v1.ItemService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.URL.Path {
|
||||
case ItemServiceGetItemProcedure:
|
||||
itemServiceGetItemHandler.ServeHTTP(w, r)
|
||||
case ItemServiceGetItemsProcedure:
|
||||
itemServiceGetItemsHandler.ServeHTTP(w, r)
|
||||
case ItemServiceCreateItemProcedure:
|
||||
itemServiceCreateItemHandler.ServeHTTP(w, r)
|
||||
case ItemServiceUpdateItemProcedure:
|
||||
itemServiceUpdateItemHandler.ServeHTTP(w, r)
|
||||
case ItemServiceDeleteItemProcedure:
|
||||
itemServiceDeleteItemHandler.ServeHTTP(w, r)
|
||||
default:
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// UnimplementedItemServiceHandler returns CodeUnimplemented from all methods.
|
||||
type UnimplementedItemServiceHandler struct{}
|
||||
|
||||
func (UnimplementedItemServiceHandler) GetItem(context.Context, *connect.Request[v1.GetItemRequest]) (*connect.Response[v1.GetItemResponse], error) {
|
||||
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("item.v1.ItemService.GetItem is not implemented"))
|
||||
}
|
||||
|
||||
func (UnimplementedItemServiceHandler) GetItems(context.Context, *connect.Request[v1.GetItemsRequest]) (*connect.Response[v1.GetItemsResponse], error) {
|
||||
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("item.v1.ItemService.GetItems is not implemented"))
|
||||
}
|
||||
|
||||
func (UnimplementedItemServiceHandler) CreateItem(context.Context, *connect.Request[v1.CreateItemRequest]) (*connect.Response[v1.CreateItemResponse], error) {
|
||||
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("item.v1.ItemService.CreateItem is not implemented"))
|
||||
}
|
||||
|
||||
func (UnimplementedItemServiceHandler) UpdateItem(context.Context, *connect.Request[v1.UpdateItemRequest]) (*connect.Response[v1.UpdateItemResponse], error) {
|
||||
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("item.v1.ItemService.UpdateItem is not implemented"))
|
||||
}
|
||||
|
||||
func (UnimplementedItemServiceHandler) DeleteItem(context.Context, *connect.Request[v1.DeleteItemRequest]) (*connect.Response[v1.DeleteItemResponse], error) {
|
||||
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("item.v1.ItemService.DeleteItem is not implemented"))
|
||||
}
|
@ -114,6 +114,7 @@ func main() {
|
||||
api := http.NewServeMux()
|
||||
api.Handle(withCORS(handlers.NewAuthHandler(db, env.Key)))
|
||||
api.Handle(withCORS(handlers.NewUserHandler(db, env.Key)))
|
||||
api.Handle(withCORS(handlers.NewItemHandler(db, env.Key)))
|
||||
|
||||
// Serve web interface
|
||||
mux := http.NewServeMux()
|
||||
@ -153,7 +154,9 @@ func main() {
|
||||
}
|
||||
}()
|
||||
|
||||
server.ListenAndServe()
|
||||
if err := server.ListenAndServe(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// withCORS adds CORS support to a Connect HTTP handler.
|
||||
|
Loading…
x
Reference in New Issue
Block a user