WIP: passkey auth

This commit is contained in:
2025-03-23 14:33:25 -04:00
parent f05e745d05
commit 93bc18022a
22 changed files with 1500 additions and 459 deletions

View File

@ -14,11 +14,13 @@
"@eslint/js": "^9.18.0",
"@lucide/svelte": "^0.479.0",
"@scalar/api-reference": "^1.28.5",
"@simplewebauthn/browser": "^13.1.0",
"@sveltejs/adapter-static": "^3.0.8",
"@sveltejs/kit": "^2.20.1",
"@sveltejs/vite-plugin-svelte": "^5.0.3",
"@tailwindcss/vite": "^4.0.14",
"bits-ui": "^1.3.13",
"cbor2": "^1.12.0",
"clsx": "^2.1.1",
"eslint": "^9.22.0",
"eslint-config-prettier": "^10.1.1",
@ -2069,6 +2071,13 @@
"node": ">=18"
}
},
"node_modules/@simplewebauthn/browser": {
"version": "13.1.0",
"resolved": "https://registry.npmjs.org/@simplewebauthn/browser/-/browser-13.1.0.tgz",
"integrity": "sha512-WuHZ/PYvyPJ9nxSzgHtOEjogBhwJfC8xzYkPC+rR/+8chl/ft4ngjiK8kSU5HtRJfczupyOh33b25TjYbvwAcg==",
"dev": true,
"license": "MIT"
},
"node_modules/@sveltejs/acorn-typescript": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.5.tgz",
@ -3331,6 +3340,16 @@
"node": ">=6"
}
},
"node_modules/cbor2": {
"version": "1.12.0",
"resolved": "https://registry.npmjs.org/cbor2/-/cbor2-1.12.0.tgz",
"integrity": "sha512-3Cco8XQhi27DogSp9Ri6LYNZLi/TBY/JVnDe+mj06NkBjW/ZYOtekaEU4wZ4xcRMNrFkDv8KNtOAqHyDfz3lYg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=18.7"
}
},
"node_modules/ccount": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz",
@ -6118,6 +6137,19 @@
"node": ">=8.6"
}
},
"node_modules/micromatch/node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8.6"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
@ -6336,13 +6368,15 @@
"license": "ISC"
},
"node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
"dev": true,
"license": "MIT",
"optional": true,
"peer": true,
"engines": {
"node": ">=8.6"
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"

View File

@ -20,11 +20,13 @@
"@eslint/js": "^9.18.0",
"@lucide/svelte": "^0.479.0",
"@scalar/api-reference": "^1.28.5",
"@simplewebauthn/browser": "^13.1.0",
"@sveltejs/adapter-static": "^3.0.8",
"@sveltejs/kit": "^2.20.1",
"@sveltejs/vite-plugin-svelte": "^5.0.3",
"@tailwindcss/vite": "^4.0.14",
"bits-ui": "^1.3.13",
"cbor2": "^1.12.0",
"clsx": "^2.1.1",
"eslint": "^9.22.0",
"eslint-config-prettier": "^10.1.1",

View File

@ -2,305 +2,295 @@
// @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';
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]
);
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;
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 name = 2;
*/
name: string;
/**
* @generated from field: string description = 3;
*/
description: string;
/**
* @generated from field: string description = 3;
*/
description: string;
/**
* @generated from field: float price = 4;
*/
price: number;
/**
* @generated from field: float price = 4;
*/
price: number;
/**
* @generated from field: uint32 quantity = 5;
*/
quantity: number;
/**
* @generated from field: uint32 quantity = 5;
*/
quantity: number;
/**
* @generated from field: optional google.protobuf.Timestamp added = 6;
*/
added?: Timestamp;
/**
* @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);
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;
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);
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;
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);
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;
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 google.protobuf.Timestamp end = 2;
*/
end?: Timestamp;
/**
* @generated from field: optional string filter = 3;
*/
filter?: string;
/**
* @generated from field: optional string filter = 3;
*/
filter?: string;
/**
* @generated from field: optional uint32 limit = 4;
*/
limit?: number;
/**
* @generated from field: optional uint32 limit = 4;
*/
limit?: number;
/**
* @generated from field: optional uint32 offset = 5;
*/
offset?: 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);
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[];
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;
/**
* @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);
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;
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);
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;
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);
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;
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);
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;
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);
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;
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);
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'> & {};
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);
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);
/**
* @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);

View File

@ -2,153 +2,243 @@
// @generated from file user/v1/auth.proto (package user.v1, syntax proto3)
/* eslint-disable */
import type { GenFile, GenMessage, GenService } from '@bufbuild/protobuf/codegenv1';
import { fileDesc, messageDesc, serviceDesc } from '@bufbuild/protobuf/codegenv1';
import type { Message } from '@bufbuild/protobuf';
import type { GenFile, GenMessage, GenService } from "@bufbuild/protobuf/codegenv1";
import { fileDesc, messageDesc, serviceDesc } from "@bufbuild/protobuf/codegenv1";
import type { Message } from "@bufbuild/protobuf";
/**
* Describes the file user/v1/auth.proto.
*/
export const file_user_v1_auth: GenFile =
/*@__PURE__*/
fileDesc(
'ChJ1c2VyL3YxL2F1dGgucHJvdG8SB3VzZXIudjEiMgoMTG9naW5SZXF1ZXN0EhAKCHVzZXJuYW1lGAEgASgJEhAKCHBhc3N3b3JkGAIgASgJIh4KDUxvZ2luUmVzcG9uc2USDQoFdG9rZW4YASABKAkiTQoNU2lnblVwUmVxdWVzdBIQCgh1c2VybmFtZRgBIAEoCRIQCghwYXNzd29yZBgCIAEoCRIYChBjb25maXJtX3Bhc3N3b3JkGAMgASgJIhAKDlNpZ25VcFJlc3BvbnNlIg8KDUxvZ291dFJlcXVlc3QiEAoOTG9nb3V0UmVzcG9uc2UywQEKC0F1dGhTZXJ2aWNlEjgKBUxvZ2luEhUudXNlci52MS5Mb2dpblJlcXVlc3QaFi51c2VyLnYxLkxvZ2luUmVzcG9uc2UiABI7CgZTaWduVXASFi51c2VyLnYxLlNpZ25VcFJlcXVlc3QaFy51c2VyLnYxLlNpZ25VcFJlc3BvbnNlIgASOwoGTG9nb3V0EhYudXNlci52MS5Mb2dvdXRSZXF1ZXN0GhcudXNlci52MS5Mb2dvdXRSZXNwb25zZSIAQp0BCgtjb20udXNlci52MUIJQXV0aFByb3RvUAFaRmdpdGh1Yi5jb20vc3BvdGRlbW80L3RyZXZzdGFjay9zZXJ2ZXIvaW50ZXJuYWwvc2VydmljZXMvdXNlci92MTt1c2VydjGiAgNVWFiqAgdVc2VyLlYxygIHVXNlclxWMeICE1VzZXJcVjFcR1BCTWV0YWRhdGHqAghVc2VyOjpWMWIGcHJvdG8z'
);
export const file_user_v1_auth: GenFile = /*@__PURE__*/
fileDesc("ChJ1c2VyL3YxL2F1dGgucHJvdG8SB3VzZXIudjEiMgoMTG9naW5SZXF1ZXN0EhAKCHVzZXJuYW1lGAEgASgJEhAKCHBhc3N3b3JkGAIgASgJIh4KDUxvZ2luUmVzcG9uc2USDQoFdG9rZW4YASABKAkiTQoNU2lnblVwUmVxdWVzdBIQCgh1c2VybmFtZRgBIAEoCRIQCghwYXNzd29yZBgCIAEoCRIYChBjb25maXJtX3Bhc3N3b3JkGAMgASgJIhAKDlNpZ25VcFJlc3BvbnNlIg8KDUxvZ291dFJlcXVlc3QiEAoOTG9nb3V0UmVzcG9uc2UiKAoUR2V0UGFzc2tleUlEc1JlcXVlc3QSEAoIdXNlcm5hbWUYASABKAkiLAoVR2V0UGFzc2tleUlEc1Jlc3BvbnNlEhMKC3Bhc3NrZXlfaWRzGAEgAygJIkcKE1Bhc3NrZXlMb2dpblJlcXVlc3QSCgoCaWQYASABKAkSEQoJc2lnbmF0dXJlGAIgASgMEhEKCWFsZ29yaXRobRgDIAEoBSIlChRQYXNza2V5TG9naW5SZXNwb25zZRINCgV0b2tlbhgBIAEoCTLiAgoLQXV0aFNlcnZpY2USOAoFTG9naW4SFS51c2VyLnYxLkxvZ2luUmVxdWVzdBoWLnVzZXIudjEuTG9naW5SZXNwb25zZSIAEjsKBlNpZ25VcBIWLnVzZXIudjEuU2lnblVwUmVxdWVzdBoXLnVzZXIudjEuU2lnblVwUmVzcG9uc2UiABI7CgZMb2dvdXQSFi51c2VyLnYxLkxvZ291dFJlcXVlc3QaFy51c2VyLnYxLkxvZ291dFJlc3BvbnNlIgASUAoNR2V0UGFzc2tleUlEcxIdLnVzZXIudjEuR2V0UGFzc2tleUlEc1JlcXVlc3QaHi51c2VyLnYxLkdldFBhc3NrZXlJRHNSZXNwb25zZSIAEk0KDFBhc3NrZXlMb2dpbhIcLnVzZXIudjEuUGFzc2tleUxvZ2luUmVxdWVzdBodLnVzZXIudjEuUGFzc2tleUxvZ2luUmVzcG9uc2UiAEKdAQoLY29tLnVzZXIudjFCCUF1dGhQcm90b1ABWkZnaXRodWIuY29tL3Nwb3RkZW1vNC90cmV2c3RhY2svc2VydmVyL2ludGVybmFsL3NlcnZpY2VzL3VzZXIvdjE7dXNlcnYxogIDVVhYqgIHVXNlci5WMcoCB1VzZXJcVjHiAhNVc2VyXFYxXEdQQk1ldGFkYXRh6gIIVXNlcjo6VjFiBnByb3RvMw");
/**
* @generated from message user.v1.LoginRequest
*/
export type LoginRequest = Message<'user.v1.LoginRequest'> & {
/**
* @generated from field: string username = 1;
*/
username: string;
export type LoginRequest = Message<"user.v1.LoginRequest"> & {
/**
* @generated from field: string username = 1;
*/
username: string;
/**
* @generated from field: string password = 2;
*/
password: string;
/**
* @generated from field: string password = 2;
*/
password: string;
};
/**
* Describes the message user.v1.LoginRequest.
* Use `create(LoginRequestSchema)` to create a new message.
*/
export const LoginRequestSchema: GenMessage<LoginRequest> =
/*@__PURE__*/
messageDesc(file_user_v1_auth, 0);
export const LoginRequestSchema: GenMessage<LoginRequest> = /*@__PURE__*/
messageDesc(file_user_v1_auth, 0);
/**
* @generated from message user.v1.LoginResponse
*/
export type LoginResponse = Message<'user.v1.LoginResponse'> & {
/**
* @generated from field: string token = 1;
*/
token: string;
export type LoginResponse = Message<"user.v1.LoginResponse"> & {
/**
* @generated from field: string token = 1;
*/
token: string;
};
/**
* Describes the message user.v1.LoginResponse.
* Use `create(LoginResponseSchema)` to create a new message.
*/
export const LoginResponseSchema: GenMessage<LoginResponse> =
/*@__PURE__*/
messageDesc(file_user_v1_auth, 1);
export const LoginResponseSchema: GenMessage<LoginResponse> = /*@__PURE__*/
messageDesc(file_user_v1_auth, 1);
/**
* @generated from message user.v1.SignUpRequest
*/
export type SignUpRequest = Message<'user.v1.SignUpRequest'> & {
/**
* @generated from field: string username = 1;
*/
username: string;
export type SignUpRequest = Message<"user.v1.SignUpRequest"> & {
/**
* @generated from field: string username = 1;
*/
username: string;
/**
* @generated from field: string password = 2;
*/
password: string;
/**
* @generated from field: string password = 2;
*/
password: string;
/**
* @generated from field: string confirm_password = 3;
*/
confirmPassword: string;
/**
* @generated from field: string confirm_password = 3;
*/
confirmPassword: string;
};
/**
* Describes the message user.v1.SignUpRequest.
* Use `create(SignUpRequestSchema)` to create a new message.
*/
export const SignUpRequestSchema: GenMessage<SignUpRequest> =
/*@__PURE__*/
messageDesc(file_user_v1_auth, 2);
export const SignUpRequestSchema: GenMessage<SignUpRequest> = /*@__PURE__*/
messageDesc(file_user_v1_auth, 2);
/**
* @generated from message user.v1.SignUpResponse
*/
export type SignUpResponse = Message<'user.v1.SignUpResponse'> & {};
export type SignUpResponse = Message<"user.v1.SignUpResponse"> & {
};
/**
* Describes the message user.v1.SignUpResponse.
* Use `create(SignUpResponseSchema)` to create a new message.
*/
export const SignUpResponseSchema: GenMessage<SignUpResponse> =
/*@__PURE__*/
messageDesc(file_user_v1_auth, 3);
export const SignUpResponseSchema: GenMessage<SignUpResponse> = /*@__PURE__*/
messageDesc(file_user_v1_auth, 3);
/**
* @generated from message user.v1.LogoutRequest
*/
export type LogoutRequest = Message<'user.v1.LogoutRequest'> & {};
export type LogoutRequest = Message<"user.v1.LogoutRequest"> & {
};
/**
* Describes the message user.v1.LogoutRequest.
* Use `create(LogoutRequestSchema)` to create a new message.
*/
export const LogoutRequestSchema: GenMessage<LogoutRequest> =
/*@__PURE__*/
messageDesc(file_user_v1_auth, 4);
export const LogoutRequestSchema: GenMessage<LogoutRequest> = /*@__PURE__*/
messageDesc(file_user_v1_auth, 4);
/**
* @generated from message user.v1.LogoutResponse
*/
export type LogoutResponse = Message<'user.v1.LogoutResponse'> & {};
export type LogoutResponse = Message<"user.v1.LogoutResponse"> & {
};
/**
* Describes the message user.v1.LogoutResponse.
* Use `create(LogoutResponseSchema)` to create a new message.
*/
export const LogoutResponseSchema: GenMessage<LogoutResponse> =
/*@__PURE__*/
messageDesc(file_user_v1_auth, 5);
export const LogoutResponseSchema: GenMessage<LogoutResponse> = /*@__PURE__*/
messageDesc(file_user_v1_auth, 5);
/**
* @generated from message user.v1.GetPasskeyIDsRequest
*/
export type GetPasskeyIDsRequest = Message<"user.v1.GetPasskeyIDsRequest"> & {
/**
* @generated from field: string username = 1;
*/
username: string;
};
/**
* Describes the message user.v1.GetPasskeyIDsRequest.
* Use `create(GetPasskeyIDsRequestSchema)` to create a new message.
*/
export const GetPasskeyIDsRequestSchema: GenMessage<GetPasskeyIDsRequest> = /*@__PURE__*/
messageDesc(file_user_v1_auth, 6);
/**
* @generated from message user.v1.GetPasskeyIDsResponse
*/
export type GetPasskeyIDsResponse = Message<"user.v1.GetPasskeyIDsResponse"> & {
/**
* @generated from field: repeated string passkey_ids = 1;
*/
passkeyIds: string[];
};
/**
* Describes the message user.v1.GetPasskeyIDsResponse.
* Use `create(GetPasskeyIDsResponseSchema)` to create a new message.
*/
export const GetPasskeyIDsResponseSchema: GenMessage<GetPasskeyIDsResponse> = /*@__PURE__*/
messageDesc(file_user_v1_auth, 7);
/**
* @generated from message user.v1.PasskeyLoginRequest
*/
export type PasskeyLoginRequest = Message<"user.v1.PasskeyLoginRequest"> & {
/**
* @generated from field: string id = 1;
*/
id: string;
/**
* @generated from field: bytes signature = 2;
*/
signature: Uint8Array;
/**
* @generated from field: int32 algorithm = 3;
*/
algorithm: number;
};
/**
* Describes the message user.v1.PasskeyLoginRequest.
* Use `create(PasskeyLoginRequestSchema)` to create a new message.
*/
export const PasskeyLoginRequestSchema: GenMessage<PasskeyLoginRequest> = /*@__PURE__*/
messageDesc(file_user_v1_auth, 8);
/**
* @generated from message user.v1.PasskeyLoginResponse
*/
export type PasskeyLoginResponse = Message<"user.v1.PasskeyLoginResponse"> & {
/**
* @generated from field: string token = 1;
*/
token: string;
};
/**
* Describes the message user.v1.PasskeyLoginResponse.
* Use `create(PasskeyLoginResponseSchema)` to create a new message.
*/
export const PasskeyLoginResponseSchema: GenMessage<PasskeyLoginResponse> = /*@__PURE__*/
messageDesc(file_user_v1_auth, 9);
/**
* @generated from service user.v1.AuthService
*/
export const AuthService: GenService<{
/**
* @generated from rpc user.v1.AuthService.Login
*/
login: {
methodKind: 'unary';
input: typeof LoginRequestSchema;
output: typeof LoginResponseSchema;
};
/**
* @generated from rpc user.v1.AuthService.SignUp
*/
signUp: {
methodKind: 'unary';
input: typeof SignUpRequestSchema;
output: typeof SignUpResponseSchema;
};
/**
* @generated from rpc user.v1.AuthService.Logout
*/
logout: {
methodKind: 'unary';
input: typeof LogoutRequestSchema;
output: typeof LogoutResponseSchema;
};
}> = /*@__PURE__*/ serviceDesc(file_user_v1_auth, 0);
/**
* @generated from rpc user.v1.AuthService.Login
*/
login: {
methodKind: "unary";
input: typeof LoginRequestSchema;
output: typeof LoginResponseSchema;
},
/**
* @generated from rpc user.v1.AuthService.SignUp
*/
signUp: {
methodKind: "unary";
input: typeof SignUpRequestSchema;
output: typeof SignUpResponseSchema;
},
/**
* @generated from rpc user.v1.AuthService.Logout
*/
logout: {
methodKind: "unary";
input: typeof LogoutRequestSchema;
output: typeof LogoutResponseSchema;
},
/**
* @generated from rpc user.v1.AuthService.GetPasskeyIDs
*/
getPasskeyIDs: {
methodKind: "unary";
input: typeof GetPasskeyIDsRequestSchema;
output: typeof GetPasskeyIDsResponseSchema;
},
/**
* @generated from rpc user.v1.AuthService.PasskeyLogin
*/
passkeyLogin: {
methodKind: "unary";
input: typeof PasskeyLoginRequestSchema;
output: typeof PasskeyLoginResponseSchema;
},
}> = /*@__PURE__*/
serviceDesc(file_user_v1_auth, 0);

View File

@ -2,238 +2,274 @@
// @generated from file user/v1/user.proto (package user.v1, syntax proto3)
/* eslint-disable */
import type { GenFile, GenMessage, GenService } from '@bufbuild/protobuf/codegenv1';
import { fileDesc, messageDesc, serviceDesc } from '@bufbuild/protobuf/codegenv1';
import type { Message } from '@bufbuild/protobuf';
import type { GenFile, GenMessage, GenService } from "@bufbuild/protobuf/codegenv1";
import { fileDesc, messageDesc, serviceDesc } from "@bufbuild/protobuf/codegenv1";
import type { Message } from "@bufbuild/protobuf";
/**
* Describes the file user/v1/user.proto.
*/
export const file_user_v1_user: GenFile =
/*@__PURE__*/
fileDesc(
'ChJ1c2VyL3YxL3VzZXIucHJvdG8SB3VzZXIudjEiVgoEVXNlchIKCgJpZBgBIAEoDRIQCgh1c2VybmFtZRgCIAEoCRIcCg9wcm9maWxlX3BpY3R1cmUYAyABKAlIAIgBAUISChBfcHJvZmlsZV9waWN0dXJlIhAKDkdldFVzZXJSZXF1ZXN0Ii4KD0dldFVzZXJSZXNwb25zZRIbCgR1c2VyGAEgASgLMg0udXNlci52MS5Vc2VyIl0KFVVwZGF0ZVBhc3N3b3JkUmVxdWVzdBIUCgxvbGRfcGFzc3dvcmQYASABKAkSFAoMbmV3X3Bhc3N3b3JkGAIgASgJEhgKEGNvbmZpcm1fcGFzc3dvcmQYAyABKAkiNQoWVXBkYXRlUGFzc3dvcmRSZXNwb25zZRIbCgR1c2VyGAEgASgLMg0udXNlci52MS5Vc2VyIj4KEEdldEFQSUtleVJlcXVlc3QSEAoIcGFzc3dvcmQYASABKAkSGAoQY29uZmlybV9wYXNzd29yZBgCIAEoCSIgChFHZXRBUElLZXlSZXNwb25zZRILCgNrZXkYASABKAkiPgobVXBkYXRlUHJvZmlsZVBpY3R1cmVSZXF1ZXN0EhEKCWZpbGVfbmFtZRgBIAEoCRIMCgRkYXRhGAIgASgMIjsKHFVwZGF0ZVByb2ZpbGVQaWN0dXJlUmVzcG9uc2USGwoEdXNlchgBIAEoCzINLnVzZXIudjEuVXNlcjLPAgoLVXNlclNlcnZpY2USPgoHR2V0VXNlchIXLnVzZXIudjEuR2V0VXNlclJlcXVlc3QaGC51c2VyLnYxLkdldFVzZXJSZXNwb25zZSIAElMKDlVwZGF0ZVBhc3N3b3JkEh4udXNlci52MS5VcGRhdGVQYXNzd29yZFJlcXVlc3QaHy51c2VyLnYxLlVwZGF0ZVBhc3N3b3JkUmVzcG9uc2UiABJECglHZXRBUElLZXkSGS51c2VyLnYxLkdldEFQSUtleVJlcXVlc3QaGi51c2VyLnYxLkdldEFQSUtleVJlc3BvbnNlIgASZQoUVXBkYXRlUHJvZmlsZVBpY3R1cmUSJC51c2VyLnYxLlVwZGF0ZVByb2ZpbGVQaWN0dXJlUmVxdWVzdBolLnVzZXIudjEuVXBkYXRlUHJvZmlsZVBpY3R1cmVSZXNwb25zZSIAQp0BCgtjb20udXNlci52MUIJVXNlclByb3RvUAFaRmdpdGh1Yi5jb20vc3BvdGRlbW80L3RyZXZzdGFjay9zZXJ2ZXIvaW50ZXJuYWwvc2VydmljZXMvdXNlci92MTt1c2VydjGiAgNVWFiqAgdVc2VyLlYxygIHVXNlclxWMeICE1VzZXJcVjFcR1BCTWV0YWRhdGHqAghVc2VyOjpWMWIGcHJvdG8z'
);
export const file_user_v1_user: GenFile = /*@__PURE__*/
fileDesc("ChJ1c2VyL3YxL3VzZXIucHJvdG8SB3VzZXIudjEiVgoEVXNlchIKCgJpZBgBIAEoDRIQCgh1c2VybmFtZRgCIAEoCRIcCg9wcm9maWxlX3BpY3R1cmUYAyABKAlIAIgBAUISChBfcHJvZmlsZV9waWN0dXJlIhAKDkdldFVzZXJSZXF1ZXN0Ii4KD0dldFVzZXJSZXNwb25zZRIbCgR1c2VyGAEgASgLMg0udXNlci52MS5Vc2VyIl0KFVVwZGF0ZVBhc3N3b3JkUmVxdWVzdBIUCgxvbGRfcGFzc3dvcmQYASABKAkSFAoMbmV3X3Bhc3N3b3JkGAIgASgJEhgKEGNvbmZpcm1fcGFzc3dvcmQYAyABKAkiNQoWVXBkYXRlUGFzc3dvcmRSZXNwb25zZRIbCgR1c2VyGAEgASgLMg0udXNlci52MS5Vc2VyIj4KEEdldEFQSUtleVJlcXVlc3QSEAoIcGFzc3dvcmQYASABKAkSGAoQY29uZmlybV9wYXNzd29yZBgCIAEoCSIgChFHZXRBUElLZXlSZXNwb25zZRILCgNrZXkYASABKAkiPgobVXBkYXRlUHJvZmlsZVBpY3R1cmVSZXF1ZXN0EhEKCWZpbGVfbmFtZRgBIAEoCRIMCgRkYXRhGAIgASgMIjsKHFVwZGF0ZVByb2ZpbGVQaWN0dXJlUmVzcG9uc2USGwoEdXNlchgBIAEoCzINLnVzZXIudjEuVXNlciI2ChRDcmVhdGVQYXNza2V5UmVxdWVzdBIKCgJpZBgBIAEoCRISCgpwdWJsaWNfa2V5GAIgASgMIhcKFUNyZWF0ZVBhc3NrZXlSZXNwb25zZTKhAwoLVXNlclNlcnZpY2USPgoHR2V0VXNlchIXLnVzZXIudjEuR2V0VXNlclJlcXVlc3QaGC51c2VyLnYxLkdldFVzZXJSZXNwb25zZSIAElMKDlVwZGF0ZVBhc3N3b3JkEh4udXNlci52MS5VcGRhdGVQYXNzd29yZFJlcXVlc3QaHy51c2VyLnYxLlVwZGF0ZVBhc3N3b3JkUmVzcG9uc2UiABJECglHZXRBUElLZXkSGS51c2VyLnYxLkdldEFQSUtleVJlcXVlc3QaGi51c2VyLnYxLkdldEFQSUtleVJlc3BvbnNlIgASZQoUVXBkYXRlUHJvZmlsZVBpY3R1cmUSJC51c2VyLnYxLlVwZGF0ZVByb2ZpbGVQaWN0dXJlUmVxdWVzdBolLnVzZXIudjEuVXBkYXRlUHJvZmlsZVBpY3R1cmVSZXNwb25zZSIAElAKDUNyZWF0ZVBhc3NrZXkSHS51c2VyLnYxLkNyZWF0ZVBhc3NrZXlSZXF1ZXN0Gh4udXNlci52MS5DcmVhdGVQYXNza2V5UmVzcG9uc2UiAEKdAQoLY29tLnVzZXIudjFCCVVzZXJQcm90b1ABWkZnaXRodWIuY29tL3Nwb3RkZW1vNC90cmV2c3RhY2svc2VydmVyL2ludGVybmFsL3NlcnZpY2VzL3VzZXIvdjE7dXNlcnYxogIDVVhYqgIHVXNlci5WMcoCB1VzZXJcVjHiAhNVc2VyXFYxXEdQQk1ldGFkYXRh6gIIVXNlcjo6VjFiBnByb3RvMw");
/**
* @generated from message user.v1.User
*/
export type User = Message<'user.v1.User'> & {
/**
* @generated from field: uint32 id = 1;
*/
id: number;
export type User = Message<"user.v1.User"> & {
/**
* @generated from field: uint32 id = 1;
*/
id: number;
/**
* @generated from field: string username = 2;
*/
username: string;
/**
* @generated from field: string username = 2;
*/
username: string;
/**
* @generated from field: optional string profile_picture = 3;
*/
profilePicture?: string;
/**
* @generated from field: optional string profile_picture = 3;
*/
profilePicture?: string;
};
/**
* Describes the message user.v1.User.
* Use `create(UserSchema)` to create a new message.
*/
export const UserSchema: GenMessage<User> = /*@__PURE__*/ messageDesc(file_user_v1_user, 0);
export const UserSchema: GenMessage<User> = /*@__PURE__*/
messageDesc(file_user_v1_user, 0);
/**
* @generated from message user.v1.GetUserRequest
*/
export type GetUserRequest = Message<'user.v1.GetUserRequest'> & {};
export type GetUserRequest = Message<"user.v1.GetUserRequest"> & {
};
/**
* Describes the message user.v1.GetUserRequest.
* Use `create(GetUserRequestSchema)` to create a new message.
*/
export const GetUserRequestSchema: GenMessage<GetUserRequest> =
/*@__PURE__*/
messageDesc(file_user_v1_user, 1);
export const GetUserRequestSchema: GenMessage<GetUserRequest> = /*@__PURE__*/
messageDesc(file_user_v1_user, 1);
/**
* @generated from message user.v1.GetUserResponse
*/
export type GetUserResponse = Message<'user.v1.GetUserResponse'> & {
/**
* @generated from field: user.v1.User user = 1;
*/
user?: User;
export type GetUserResponse = Message<"user.v1.GetUserResponse"> & {
/**
* @generated from field: user.v1.User user = 1;
*/
user?: User;
};
/**
* Describes the message user.v1.GetUserResponse.
* Use `create(GetUserResponseSchema)` to create a new message.
*/
export const GetUserResponseSchema: GenMessage<GetUserResponse> =
/*@__PURE__*/
messageDesc(file_user_v1_user, 2);
export const GetUserResponseSchema: GenMessage<GetUserResponse> = /*@__PURE__*/
messageDesc(file_user_v1_user, 2);
/**
* @generated from message user.v1.UpdatePasswordRequest
*/
export type UpdatePasswordRequest = Message<'user.v1.UpdatePasswordRequest'> & {
/**
* @generated from field: string old_password = 1;
*/
oldPassword: string;
export type UpdatePasswordRequest = Message<"user.v1.UpdatePasswordRequest"> & {
/**
* @generated from field: string old_password = 1;
*/
oldPassword: string;
/**
* @generated from field: string new_password = 2;
*/
newPassword: string;
/**
* @generated from field: string new_password = 2;
*/
newPassword: string;
/**
* @generated from field: string confirm_password = 3;
*/
confirmPassword: string;
/**
* @generated from field: string confirm_password = 3;
*/
confirmPassword: string;
};
/**
* Describes the message user.v1.UpdatePasswordRequest.
* Use `create(UpdatePasswordRequestSchema)` to create a new message.
*/
export const UpdatePasswordRequestSchema: GenMessage<UpdatePasswordRequest> =
/*@__PURE__*/
messageDesc(file_user_v1_user, 3);
export const UpdatePasswordRequestSchema: GenMessage<UpdatePasswordRequest> = /*@__PURE__*/
messageDesc(file_user_v1_user, 3);
/**
* @generated from message user.v1.UpdatePasswordResponse
*/
export type UpdatePasswordResponse = Message<'user.v1.UpdatePasswordResponse'> & {
/**
* @generated from field: user.v1.User user = 1;
*/
user?: User;
export type UpdatePasswordResponse = Message<"user.v1.UpdatePasswordResponse"> & {
/**
* @generated from field: user.v1.User user = 1;
*/
user?: User;
};
/**
* Describes the message user.v1.UpdatePasswordResponse.
* Use `create(UpdatePasswordResponseSchema)` to create a new message.
*/
export const UpdatePasswordResponseSchema: GenMessage<UpdatePasswordResponse> =
/*@__PURE__*/
messageDesc(file_user_v1_user, 4);
export const UpdatePasswordResponseSchema: GenMessage<UpdatePasswordResponse> = /*@__PURE__*/
messageDesc(file_user_v1_user, 4);
/**
* @generated from message user.v1.GetAPIKeyRequest
*/
export type GetAPIKeyRequest = Message<'user.v1.GetAPIKeyRequest'> & {
/**
* @generated from field: string password = 1;
*/
password: string;
export type GetAPIKeyRequest = Message<"user.v1.GetAPIKeyRequest"> & {
/**
* @generated from field: string password = 1;
*/
password: string;
/**
* @generated from field: string confirm_password = 2;
*/
confirmPassword: string;
/**
* @generated from field: string confirm_password = 2;
*/
confirmPassword: string;
};
/**
* Describes the message user.v1.GetAPIKeyRequest.
* Use `create(GetAPIKeyRequestSchema)` to create a new message.
*/
export const GetAPIKeyRequestSchema: GenMessage<GetAPIKeyRequest> =
/*@__PURE__*/
messageDesc(file_user_v1_user, 5);
export const GetAPIKeyRequestSchema: GenMessage<GetAPIKeyRequest> = /*@__PURE__*/
messageDesc(file_user_v1_user, 5);
/**
* @generated from message user.v1.GetAPIKeyResponse
*/
export type GetAPIKeyResponse = Message<'user.v1.GetAPIKeyResponse'> & {
/**
* @generated from field: string key = 1;
*/
key: string;
export type GetAPIKeyResponse = Message<"user.v1.GetAPIKeyResponse"> & {
/**
* @generated from field: string key = 1;
*/
key: string;
};
/**
* Describes the message user.v1.GetAPIKeyResponse.
* Use `create(GetAPIKeyResponseSchema)` to create a new message.
*/
export const GetAPIKeyResponseSchema: GenMessage<GetAPIKeyResponse> =
/*@__PURE__*/
messageDesc(file_user_v1_user, 6);
export const GetAPIKeyResponseSchema: GenMessage<GetAPIKeyResponse> = /*@__PURE__*/
messageDesc(file_user_v1_user, 6);
/**
* @generated from message user.v1.UpdateProfilePictureRequest
*/
export type UpdateProfilePictureRequest = Message<'user.v1.UpdateProfilePictureRequest'> & {
/**
* @generated from field: string file_name = 1;
*/
fileName: string;
export type UpdateProfilePictureRequest = Message<"user.v1.UpdateProfilePictureRequest"> & {
/**
* @generated from field: string file_name = 1;
*/
fileName: string;
/**
* @generated from field: bytes data = 2;
*/
data: Uint8Array;
/**
* @generated from field: bytes data = 2;
*/
data: Uint8Array;
};
/**
* Describes the message user.v1.UpdateProfilePictureRequest.
* Use `create(UpdateProfilePictureRequestSchema)` to create a new message.
*/
export const UpdateProfilePictureRequestSchema: GenMessage<UpdateProfilePictureRequest> =
/*@__PURE__*/
messageDesc(file_user_v1_user, 7);
export const UpdateProfilePictureRequestSchema: GenMessage<UpdateProfilePictureRequest> = /*@__PURE__*/
messageDesc(file_user_v1_user, 7);
/**
* @generated from message user.v1.UpdateProfilePictureResponse
*/
export type UpdateProfilePictureResponse = Message<'user.v1.UpdateProfilePictureResponse'> & {
/**
* @generated from field: user.v1.User user = 1;
*/
user?: User;
export type UpdateProfilePictureResponse = Message<"user.v1.UpdateProfilePictureResponse"> & {
/**
* @generated from field: user.v1.User user = 1;
*/
user?: User;
};
/**
* Describes the message user.v1.UpdateProfilePictureResponse.
* Use `create(UpdateProfilePictureResponseSchema)` to create a new message.
*/
export const UpdateProfilePictureResponseSchema: GenMessage<UpdateProfilePictureResponse> =
/*@__PURE__*/
messageDesc(file_user_v1_user, 8);
export const UpdateProfilePictureResponseSchema: GenMessage<UpdateProfilePictureResponse> = /*@__PURE__*/
messageDesc(file_user_v1_user, 8);
/**
* @generated from message user.v1.CreatePasskeyRequest
*/
export type CreatePasskeyRequest = Message<"user.v1.CreatePasskeyRequest"> & {
/**
* @generated from field: string id = 1;
*/
id: string;
/**
* @generated from field: bytes public_key = 2;
*/
publicKey: Uint8Array;
};
/**
* Describes the message user.v1.CreatePasskeyRequest.
* Use `create(CreatePasskeyRequestSchema)` to create a new message.
*/
export const CreatePasskeyRequestSchema: GenMessage<CreatePasskeyRequest> = /*@__PURE__*/
messageDesc(file_user_v1_user, 9);
/**
* @generated from message user.v1.CreatePasskeyResponse
*/
export type CreatePasskeyResponse = Message<"user.v1.CreatePasskeyResponse"> & {
};
/**
* Describes the message user.v1.CreatePasskeyResponse.
* Use `create(CreatePasskeyResponseSchema)` to create a new message.
*/
export const CreatePasskeyResponseSchema: GenMessage<CreatePasskeyResponse> = /*@__PURE__*/
messageDesc(file_user_v1_user, 10);
/**
* @generated from service user.v1.UserService
*/
export const UserService: GenService<{
/**
* @generated from rpc user.v1.UserService.GetUser
*/
getUser: {
methodKind: 'unary';
input: typeof GetUserRequestSchema;
output: typeof GetUserResponseSchema;
};
/**
* @generated from rpc user.v1.UserService.UpdatePassword
*/
updatePassword: {
methodKind: 'unary';
input: typeof UpdatePasswordRequestSchema;
output: typeof UpdatePasswordResponseSchema;
};
/**
* @generated from rpc user.v1.UserService.GetAPIKey
*/
getAPIKey: {
methodKind: 'unary';
input: typeof GetAPIKeyRequestSchema;
output: typeof GetAPIKeyResponseSchema;
};
/**
* @generated from rpc user.v1.UserService.UpdateProfilePicture
*/
updateProfilePicture: {
methodKind: 'unary';
input: typeof UpdateProfilePictureRequestSchema;
output: typeof UpdateProfilePictureResponseSchema;
};
}> = /*@__PURE__*/ serviceDesc(file_user_v1_user, 0);
/**
* @generated from rpc user.v1.UserService.GetUser
*/
getUser: {
methodKind: "unary";
input: typeof GetUserRequestSchema;
output: typeof GetUserResponseSchema;
},
/**
* @generated from rpc user.v1.UserService.UpdatePassword
*/
updatePassword: {
methodKind: "unary";
input: typeof UpdatePasswordRequestSchema;
output: typeof UpdatePasswordResponseSchema;
},
/**
* @generated from rpc user.v1.UserService.GetAPIKey
*/
getAPIKey: {
methodKind: "unary";
input: typeof GetAPIKeyRequestSchema;
output: typeof GetAPIKeyResponseSchema;
},
/**
* @generated from rpc user.v1.UserService.UpdateProfilePicture
*/
updateProfilePicture: {
methodKind: "unary";
input: typeof UpdateProfilePictureRequestSchema;
output: typeof UpdateProfilePictureResponseSchema;
},
/**
* @generated from rpc user.v1.UserService.CreatePasskey
*/
createPasskey: {
methodKind: "unary";
input: typeof CreatePasskeyRequestSchema;
output: typeof CreatePasskeyResponseSchema;
},
}> = /*@__PURE__*/
serviceDesc(file_user_v1_user, 0);

View File

@ -12,7 +12,7 @@
}: {
className?: string;
type?: 'submit' | 'reset' | 'button' | null;
onclick?: () => MouseEventHandler<HTMLButtonElement> | null | undefined;
onclick?: () => void;
children?: Snippet<[]>;
} = $props();
</script>
@ -23,7 +23,9 @@
'bg-sky text-crust focus:outline-sky flex w-fit cursor-pointer items-center justify-center rounded p-2 px-4 text-sm font-medium transition-all hover:brightness-120 focus:outline-2 focus:outline-offset-1',
className
)}
{onclick}
onclick={() => {
onclick?.();
}}
>
{@render children?.()}
</Button.Root>

120
client/src/lib/webauthn.ts Normal file
View File

@ -0,0 +1,120 @@
import { decode } from 'cbor2';
import { page } from '$app/state';
interface CreateCredential extends Credential {
response: AuthenticatorAttestationResponse
}
interface AttestationObject {
authData: Uint8Array,
fmt: string,
attStmt: any
}
interface DecodedPublicKeyObject {
[key: number]: number | Uint8Array
}
export async function createPasskey(username: string, userid: number, challenge: string) {
const challengeBuffer = Uint8Array.from(challenge, c => c.charCodeAt(0));
const idBuffer = Uint8Array.from(userid.toString(), c => c.charCodeAt(0));
const credential = await navigator.credentials.create({
publicKey: {
challenge: challengeBuffer,
rp: { id: page.url.hostname, name: "TrevStack" },
user: {
id: idBuffer,
name: username,
displayName: username
},
pubKeyCredParams: [
{
type: 'public-key',
alg: -7
},
{
type: 'public-key',
alg: -257
}
],
timeout: 60000,
attestation: 'none'
}
}) as CreateCredential | null;
if (!credential) {
throw new Error('Could not create passkey');
}
console.log(credential.id)
//console.log(credential.type);
const utf8Decoder = new TextDecoder('utf-8');
const decodedClientData = utf8Decoder.decode(credential.response.clientDataJSON)
const clientDataObj = JSON.parse(decodedClientData);
console.log(clientDataObj);
const attestationObject = new Uint8Array(credential.response.attestationObject)
const decodedAttestationObject = decode(attestationObject) as AttestationObject;
const { authData } = decodedAttestationObject;
// get the length of the credential ID
const dataView = new DataView(new ArrayBuffer(2));
const idLenBytes = authData.slice(53, 55);
idLenBytes.forEach((value, index) => dataView.setUint8(index, value));
const credentialIdLength = dataView.getUint16(0);
// get the credential ID
const credentialId = authData.slice(55, 55 + credentialIdLength);
// get the public key object
const publicKeyBytes = authData.slice(55 + credentialIdLength);
console.log(publicKeyBytes);
// the publicKeyBytes are encoded again as CBOR
const publicKeyObject = new Uint8Array(publicKeyBytes.buffer)
const decodedPublicKeyObject = decode(publicKeyObject) as DecodedPublicKeyObject;
console.log(decodedPublicKeyObject);
return {
id: credential.id,
publicKey: publicKeyBytes,
algorithm: decodedPublicKeyObject[3]
}
}
interface GetCredential extends Credential {
response: AuthenticatorAssertionResponse
}
export async function getPasskey(passkeyids: string[], challenge: string) {
const challengeBuffer = Uint8Array.from(challenge, c => c.charCodeAt(0));
const credential = await navigator.credentials.get({
publicKey: {
challenge: challengeBuffer,
allowCredentials: passkeyids.map((passkeyid) => {
return {
id: Uint8Array.from(passkeyid, c => c.charCodeAt(0)),
type: 'public-key',
}
}),
timeout: 60000,
}
}) as GetCredential | null;
if (!credential) {
throw new Error('Could not get passkey');
}
const signature = credential.response.signature;
return {
signature
}
}

View File

@ -7,6 +7,8 @@
import { Separator } from 'bits-ui';
import { toast } from 'svelte-sonner';
import { userState } from '$lib/sharedState.svelte';
import { createPasskey } from '$lib/webauthn';
import { page } from '$app/state';
import Avatar from '$lib/ui/Avatar.svelte';
let openChangeProfilePicture = $state(false);
@ -17,7 +19,7 @@
<div class="m-auto flex w-96 flex-col gap-4 p-4">
<div class="flex items-center justify-center gap-4">
<div
class="outline-surface-2 bg-text text-crust h-9 w-9 rounded-full text-sm outline outline-offset-2 select-none"
class="outline-surface-2 bg-text text-crust h-9 w-9 select-none rounded-full text-sm outline outline-offset-2"
>
<Avatar />
</div>
@ -26,7 +28,7 @@
<Separator.Root class="bg-surface-0 h-px" />
<div class="flex justify-around gap-2">
<div class="flex flex-wrap justify-around gap-2">
<Modal>
{#snippet trigger(props)}
<Button {...props} className="bg-text">Generate API Key</Button>
@ -133,6 +135,16 @@
</form>
{/snippet}
</Modal>
<Button
className="bg-text"
onclick={async () => {
if (userState.user) {
await createPasskey(userState.user.username, userState.user.id, "what");
}
}}>Register Device</Button
>
</div>
<form

View File

@ -292,6 +292,24 @@ 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.GetPasskeyIDsRequest:
type: object
properties:
username:
type: string
title: username
title: GetPasskeyIDsRequest
additionalProperties: false
user.v1.GetPasskeyIDsResponse:
type: object
properties:
passkeyIds:
type: array
items:
type: string
title: passkey_ids
title: GetPasskeyIDsResponse
additionalProperties: false
user.v1.LoginRequest:
type: object
properties:
@ -319,6 +337,30 @@ components:
type: object
title: LogoutResponse
additionalProperties: false
user.v1.PasskeyLoginRequest:
type: object
properties:
id:
type: string
title: id
signature:
type: string
title: signature
format: byte
algorithm:
type: integer
title: algorithm
format: int32
title: PasskeyLoginRequest
additionalProperties: false
user.v1.PasskeyLoginResponse:
type: object
properties:
token:
type: string
title: token
title: PasskeyLoginResponse
additionalProperties: false
user.v1.SignUpRequest:
type: object
properties:
@ -337,6 +379,22 @@ components:
type: object
title: SignUpResponse
additionalProperties: false
user.v1.CreatePasskeyRequest:
type: object
properties:
id:
type: string
title: id
publicKey:
type: string
title: public_key
format: byte
title: CreatePasskeyRequest
additionalProperties: false
user.v1.CreatePasskeyResponse:
type: object
title: CreatePasskeyResponse
additionalProperties: false
user.v1.GetAPIKeyRequest:
type: object
properties:
@ -708,6 +766,76 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/user.v1.LogoutResponse'
/user.v1.AuthService/GetPasskeyIDs:
post:
tags:
- user.v1.AuthService
summary: GetPasskeyIDs
operationId: user.v1.AuthService.GetPasskeyIDs
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/user.v1.GetPasskeyIDsRequest'
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/user.v1.GetPasskeyIDsResponse'
/user.v1.AuthService/PasskeyLogin:
post:
tags:
- user.v1.AuthService
summary: PasskeyLogin
operationId: user.v1.AuthService.PasskeyLogin
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/user.v1.PasskeyLoginRequest'
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/user.v1.PasskeyLoginResponse'
/user.v1.UserService/GetUser:
post:
tags:
@ -848,6 +976,41 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/user.v1.UpdateProfilePictureResponse'
/user.v1.UserService/CreatePasskey:
post:
tags:
- user.v1.UserService
summary: CreatePasskey
operationId: user.v1.UserService.CreatePasskey
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/user.v1.CreatePasskeyRequest'
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/user.v1.CreatePasskeyResponse'
tags:
- name: item.v1.ItemService
- name: user.v1.AuthService