mirror of
https://github.com/Dvorinka/Bookra.git
synced 2026-06-04 04:22:59 +00:00
first commit
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "@bookra/api-client",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./generated/types": "./src/generated/types.ts"
|
||||
},
|
||||
"scripts": {
|
||||
"generate": "node ./scripts/generate.mjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"openapi-fetch": "^0.13.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"openapi-typescript": "^7.8.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { pathToFileURL } from "node:url";
|
||||
import openapiTS, { astToString } from "openapi-typescript";
|
||||
|
||||
const rootDir = path.resolve(import.meta.dirname, "../../..");
|
||||
const specPath = path.resolve(rootDir, "apps/backend/openapi/bookra.openapi.yaml");
|
||||
const outputPath = path.resolve(import.meta.dirname, "../src/generated/types.ts");
|
||||
|
||||
const ast = await openapiTS(pathToFileURL(specPath), {
|
||||
alphabetize: true,
|
||||
});
|
||||
const schema = astToString(ast);
|
||||
|
||||
await fs.mkdir(path.dirname(outputPath), { recursive: true });
|
||||
await fs.writeFile(outputPath, `${schema}\n`, "utf8");
|
||||
console.log(`Generated API types to ${outputPath}`);
|
||||
@@ -0,0 +1,683 @@
|
||||
export interface paths {
|
||||
"/healthz": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get: operations["getHealth"];
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/v1/billing/checkout": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
post: operations["createBillingCheckout"];
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/v1/billing/refresh": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
post: operations["refreshSubscriptionSnapshot"];
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/v1/billing/subscription": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get: operations["getSubscriptionSnapshot"];
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/v1/dashboard/summary": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get: operations["getDashboardSummary"];
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/v1/internal/jobs/reminders/dispatch": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
post: operations["dispatchReminderJobs"];
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/v1/meta/config": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get: operations["getPublicConfig"];
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/v1/public/bookings": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
post: operations["createBooking"];
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/v1/public/tenants/{tenantSlug}/availability": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get: operations["getPublicAvailability"];
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/v1/tenants/bootstrap": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get: operations["getTenantBootstrap"];
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/v1/tenants/onboard": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
post: operations["onboardTenant"];
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/v1/webhooks/stripe": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
post: operations["handleStripeWebhook"];
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
}
|
||||
export type webhooks = Record<string, never>;
|
||||
export interface components {
|
||||
schemas: {
|
||||
CheckoutSessionRequest: {
|
||||
/** @enum {string} */
|
||||
planCode: "starter" | "growth" | "multi-location";
|
||||
};
|
||||
CheckoutSessionResponse: {
|
||||
/** Format: uri */
|
||||
url: string;
|
||||
};
|
||||
CreateBookingRequest: {
|
||||
/** @enum {string} */
|
||||
bookingMode: "appointment" | "class";
|
||||
/** Format: uuid */
|
||||
classSessionId?: string;
|
||||
/** Format: email */
|
||||
customerEmail: string;
|
||||
customerName: string;
|
||||
/** Format: date-time */
|
||||
endsAt: string;
|
||||
/** Format: uuid */
|
||||
locationId?: string;
|
||||
notes?: string;
|
||||
/** Format: uuid */
|
||||
serviceId?: string;
|
||||
/** Format: uuid */
|
||||
staffId?: string;
|
||||
/** Format: date-time */
|
||||
startsAt: string;
|
||||
tenantSlug: string;
|
||||
};
|
||||
CreateBookingResponse: {
|
||||
/** Format: uuid */
|
||||
bookingId: string;
|
||||
reference: string;
|
||||
/** @enum {string} */
|
||||
status: "confirmed" | "waitlisted";
|
||||
};
|
||||
DashboardKPI: {
|
||||
code: string;
|
||||
label: string;
|
||||
value: string;
|
||||
};
|
||||
DashboardSummary: {
|
||||
kpis: components["schemas"]["DashboardKPI"][];
|
||||
locale: string;
|
||||
planCode: string;
|
||||
tenantName: string;
|
||||
timezone: string;
|
||||
};
|
||||
DispatchReminderJobsRequest: {
|
||||
limit?: number;
|
||||
};
|
||||
DispatchReminderJobsResponse: {
|
||||
failedCount: number;
|
||||
processedCount: number;
|
||||
sentCount: number;
|
||||
};
|
||||
HealthResponse: {
|
||||
databaseConfigured?: boolean;
|
||||
/** @example staging */
|
||||
environment: string;
|
||||
/** @example ok */
|
||||
status: string;
|
||||
};
|
||||
OnboardTenantRequest: {
|
||||
/** @enum {string} */
|
||||
locale: "cs" | "en";
|
||||
name: string;
|
||||
/** @enum {string} */
|
||||
preset: "salon" | "clinic" | "massage" | "repair" | "studio";
|
||||
slug: string;
|
||||
timezone: string;
|
||||
};
|
||||
PlanEntitlements: {
|
||||
advancedReporting: boolean;
|
||||
maxLocations: number;
|
||||
maxStaff: number;
|
||||
smsAddonAvailable: boolean;
|
||||
};
|
||||
PublicAvailabilityResponse: {
|
||||
/** @enum {string} */
|
||||
locale: "cs" | "en";
|
||||
slots: components["schemas"]["TimeSlot"][];
|
||||
tenantSlug: string;
|
||||
timezone: string;
|
||||
};
|
||||
PublicConfig: {
|
||||
/** Format: uri */
|
||||
apiUrl?: string;
|
||||
environment: string;
|
||||
neonAuthEnabled: boolean;
|
||||
};
|
||||
SubscriptionSnapshot: {
|
||||
cancelAtPeriodEnd: boolean;
|
||||
checkoutUrlAvailable?: boolean;
|
||||
/** Format: date-time */
|
||||
currentPeriodEnd?: string | null;
|
||||
/** Format: date-time */
|
||||
currentPeriodStart?: string | null;
|
||||
customerId: string;
|
||||
entitlements: components["schemas"]["PlanEntitlements"];
|
||||
/** Format: date-time */
|
||||
lastSyncedAt?: string | null;
|
||||
paymentMethodBrand?: string;
|
||||
paymentMethodLast4?: string;
|
||||
planCode: string;
|
||||
priceId: string;
|
||||
status: string;
|
||||
subscriptionId: string;
|
||||
/** Format: uuid */
|
||||
tenantId: string;
|
||||
};
|
||||
TenantBootstrap: {
|
||||
currentUser: {
|
||||
/** Format: email */
|
||||
email?: string;
|
||||
name?: string;
|
||||
role: string;
|
||||
subject: string;
|
||||
};
|
||||
locale: string;
|
||||
planCode?: string;
|
||||
preset: string;
|
||||
/** Format: uuid */
|
||||
tenantId: string;
|
||||
tenantName: string;
|
||||
timezone: string;
|
||||
};
|
||||
TimeSlot: {
|
||||
/** Format: uuid */
|
||||
classSessionId?: string | null;
|
||||
/** Format: date-time */
|
||||
endsAt: string;
|
||||
label?: string;
|
||||
/** Format: uuid */
|
||||
locationId?: string | null;
|
||||
/** @enum {string} */
|
||||
mode: "appointment" | "class";
|
||||
remainingCapacity?: number | null;
|
||||
/** Format: uuid */
|
||||
serviceId?: string | null;
|
||||
/** Format: uuid */
|
||||
staffId?: string | null;
|
||||
/** Format: date-time */
|
||||
startsAt: string;
|
||||
};
|
||||
};
|
||||
responses: never;
|
||||
parameters: never;
|
||||
requestBodies: never;
|
||||
headers: never;
|
||||
pathItems: never;
|
||||
}
|
||||
export type $defs = Record<string, never>;
|
||||
export interface operations {
|
||||
getHealth: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description Service health */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["HealthResponse"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
createBillingCheckout: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["CheckoutSessionRequest"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Hosted Stripe checkout session */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["CheckoutSessionResponse"];
|
||||
};
|
||||
};
|
||||
/** @description Invalid request */
|
||||
400: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
/** @description Unauthorized */
|
||||
401: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
};
|
||||
};
|
||||
refreshSubscriptionSnapshot: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description Refreshed snapshot */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["SubscriptionSnapshot"];
|
||||
};
|
||||
};
|
||||
/** @description Unauthorized */
|
||||
401: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
};
|
||||
};
|
||||
getSubscriptionSnapshot: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description Current subscription snapshot and entitlements */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["SubscriptionSnapshot"];
|
||||
};
|
||||
};
|
||||
/** @description Unauthorized */
|
||||
401: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
};
|
||||
};
|
||||
getDashboardSummary: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description Tenant dashboard summary */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["DashboardSummary"];
|
||||
};
|
||||
};
|
||||
/** @description Unauthorized */
|
||||
401: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
};
|
||||
};
|
||||
dispatchReminderJobs: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["DispatchReminderJobsRequest"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Reminder jobs dispatched */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["DispatchReminderJobsResponse"];
|
||||
};
|
||||
};
|
||||
/** @description Unauthorized */
|
||||
401: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
};
|
||||
};
|
||||
getPublicConfig: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description Public runtime configuration */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["PublicConfig"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
createBooking: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["CreateBookingRequest"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Booking created */
|
||||
201: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["CreateBookingResponse"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
getPublicAvailability: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
tenantSlug: string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description Availability for a tenant booking page */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["PublicAvailabilityResponse"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
getTenantBootstrap: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description Tenant bootstrap payload for the authenticated user */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["TenantBootstrap"];
|
||||
};
|
||||
};
|
||||
/** @description Unauthorized */
|
||||
401: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
};
|
||||
};
|
||||
onboardTenant: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["OnboardTenantRequest"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Tenant created for authenticated user */
|
||||
201: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["TenantBootstrap"];
|
||||
};
|
||||
};
|
||||
/** @description Invalid request */
|
||||
400: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
/** @description Unauthorized */
|
||||
401: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
/** @description Conflict */
|
||||
409: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
};
|
||||
};
|
||||
handleStripeWebhook: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": Record<string, never>;
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Webhook accepted */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from "./generated/types";
|
||||
|
||||
Reference in New Issue
Block a user