Add Milestones 1 & 2: full-stack POS foundation with admin UI

- Node/Express/TypeScript API under /api/v1 with JWT auth (login, refresh, logout, /me)
- Prisma schema: vendors, users, roles, products, categories, taxes, transactions
- SQLite for local dev; Postgres via docker-compose for production
- Full CRUD routes for vendors, users, categories, taxes, products with Zod validation and RBAC
- Paginated list endpoints scoped per vendor; refresh token rotation
- React/TypeScript admin SPA (Vite): login, protected routing, sidebar layout
- Pages: Dashboard, Catalog (tabbed Products/Categories/Taxes), Users, Vendor Settings
- Shared UI: Table, Modal, FormField, Btn, PageHeader components
- Multi-stage Dockerfile; docker-compose with Postgres healthcheck
- Seed script with demo vendor and owner account
- INSTRUCTIONS.md, ROADMAP.md, .claude/launch.json for dev server config

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-20 23:18:04 -05:00
parent fb62439eab
commit d53c772dd6
4594 changed files with 1876068 additions and 0 deletions

1
server/node_modules/tsx/dist/cjs/api/index.cjs generated vendored Normal file
View File

@@ -0,0 +1 @@
"use strict";require("../../get-pipe-path-BoR10qr8.cjs");var r=require("../../register-D46fvsV_.cjs"),e=require("../../require-D4F1Lv60.cjs");require("module"),require("node:path"),require("../../temporary-directory-B83uKxJF.cjs"),require("node:os"),require("node:module"),require("node:url"),require("get-tsconfig"),require("node:fs"),require("../../index-gckBtVBf.cjs"),require("esbuild"),require("node:crypto"),require("../../client-D6NvIMSC.cjs"),require("node:net"),require("node:util"),require("../../index-BWFBUo6r.cjs"),exports.register=r.register,exports.require=e.tsxRequire;

35
server/node_modules/tsx/dist/cjs/api/index.d.cts generated vendored Normal file
View File

@@ -0,0 +1,35 @@
import { R as RequiredProperty } from '../../types-Cxp8y2TL.js';
type RegisterOptions = {
namespace?: string;
};
type Unregister = () => void;
type ScopedRequire = (id: string, fromFile: string | URL) => any;
type ScopedResolve = (id: string, fromFile: string | URL, resolveOptions?: {
paths?: string[] | undefined;
}) => string;
type NamespacedUnregister = Unregister & {
require: ScopedRequire;
resolve: ScopedResolve;
unregister: Unregister;
};
type Register = {
(options: RequiredProperty<RegisterOptions, 'namespace'>): NamespacedUnregister;
(options?: RegisterOptions): Unregister;
};
declare const register: Register;
declare const tsxRequire: {
(id: string, fromFile: string | URL): any;
resolve: {
(id: string, fromFile: string | URL, options?: {
paths?: string[] | undefined;
}): string;
paths: (request: string) => string[] | null;
};
main: NodeJS.Module | undefined;
extensions: NodeJS.RequireExtensions;
cache: NodeJS.Dict<NodeJS.Module>;
};
export { register, tsxRequire as require };

35
server/node_modules/tsx/dist/cjs/api/index.d.mts generated vendored Normal file
View File

@@ -0,0 +1,35 @@
import { R as RequiredProperty } from '../../types-Cxp8y2TL.js';
type RegisterOptions = {
namespace?: string;
};
type Unregister = () => void;
type ScopedRequire = (id: string, fromFile: string | URL) => any;
type ScopedResolve = (id: string, fromFile: string | URL, resolveOptions?: {
paths?: string[] | undefined;
}) => string;
type NamespacedUnregister = Unregister & {
require: ScopedRequire;
resolve: ScopedResolve;
unregister: Unregister;
};
type Register = {
(options: RequiredProperty<RegisterOptions, 'namespace'>): NamespacedUnregister;
(options?: RegisterOptions): Unregister;
};
declare const register: Register;
declare const tsxRequire: {
(id: string, fromFile: string | URL): any;
resolve: {
(id: string, fromFile: string | URL, options?: {
paths?: string[] | undefined;
}): string;
paths: (request: string) => string[] | null;
};
main: NodeJS.Module | undefined;
extensions: NodeJS.RequireExtensions;
cache: NodeJS.Dict<NodeJS.Module>;
};
export { register, tsxRequire as require };

1
server/node_modules/tsx/dist/cjs/api/index.mjs generated vendored Normal file
View File

@@ -0,0 +1 @@
import"../../get-pipe-path-BHW2eJdv.mjs";import{r as j}from"../../register-CFH5oNdT.mjs";import{t as l}from"../../require-DQxpCAr4.mjs";import"module";import"node:path";import"../../temporary-directory-CwHp0_NW.mjs";import"node:os";import"node:module";import"node:url";import"get-tsconfig";import"node:fs";import"../../index-7AaEi15b.mjs";import"esbuild";import"node:crypto";import"../../client-BQVF1NaW.mjs";import"node:net";import"node:util";import"../../index-gbaejti9.mjs";export{j as register,l as require};

1
server/node_modules/tsx/dist/cjs/index.cjs generated vendored Normal file
View File

@@ -0,0 +1 @@
"use strict";var r=require("../register-D46fvsV_.cjs");require("../get-pipe-path-BoR10qr8.cjs"),require("module"),require("node:path"),require("../temporary-directory-B83uKxJF.cjs"),require("node:os"),require("node:module"),require("node:url"),require("get-tsconfig"),require("node:fs"),require("../index-gckBtVBf.cjs"),require("esbuild"),require("node:crypto"),require("../client-D6NvIMSC.cjs"),require("node:net"),require("node:util"),require("../index-BWFBUo6r.cjs"),r.register();

1
server/node_modules/tsx/dist/cjs/index.mjs generated vendored Normal file
View File

@@ -0,0 +1 @@
import{r}from"../register-CFH5oNdT.mjs";import"../get-pipe-path-BHW2eJdv.mjs";import"module";import"node:path";import"../temporary-directory-CwHp0_NW.mjs";import"node:os";import"node:module";import"node:url";import"get-tsconfig";import"node:fs";import"../index-7AaEi15b.mjs";import"esbuild";import"node:crypto";import"../client-BQVF1NaW.mjs";import"node:net";import"node:util";import"../index-gbaejti9.mjs";r();