@naisys/erp 3.0.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of @naisys/erp might be problematic. Click here for more details.
- package/bin/naisys-erp +2 -0
- package/client-dist/android-chrome-192x192.png +0 -0
- package/client-dist/android-chrome-512x512.png +0 -0
- package/client-dist/apple-touch-icon.png +0 -0
- package/client-dist/assets/index-45dVo30p.css +1 -0
- package/client-dist/assets/index-Dffms7F_.js +168 -0
- package/client-dist/assets/naisys-logo-CzoPnn5I.webp +0 -0
- package/client-dist/favicon.ico +0 -0
- package/client-dist/index.html +42 -0
- package/client-dist/site.webmanifest +22 -0
- package/dist/api-reference.d.ts +10 -0
- package/dist/api-reference.js +101 -0
- package/dist/audit.d.ts +5 -0
- package/dist/audit.js +14 -0
- package/dist/auth-middleware.d.ts +18 -0
- package/dist/auth-middleware.js +203 -0
- package/dist/dbConfig.d.ts +5 -0
- package/dist/dbConfig.js +10 -0
- package/dist/erpDb.d.ts +10 -0
- package/dist/erpDb.js +34 -0
- package/dist/erpServer.d.ts +10 -0
- package/dist/erpServer.js +321 -0
- package/dist/error-handler.d.ts +7 -0
- package/dist/error-handler.js +17 -0
- package/dist/generated/prisma/client.d.ts +154 -0
- package/dist/generated/prisma/client.js +35 -0
- package/dist/generated/prisma/commonInputTypes.d.ts +637 -0
- package/dist/generated/prisma/commonInputTypes.js +11 -0
- package/dist/generated/prisma/enums.d.ts +59 -0
- package/dist/generated/prisma/enums.js +60 -0
- package/dist/generated/prisma/internal/class.d.ts +406 -0
- package/dist/generated/prisma/internal/class.js +50 -0
- package/dist/generated/prisma/internal/prismaNamespace.d.ts +2722 -0
- package/dist/generated/prisma/internal/prismaNamespace.js +366 -0
- package/dist/generated/prisma/models/Attachment.d.ts +1455 -0
- package/dist/generated/prisma/models/Attachment.js +2 -0
- package/dist/generated/prisma/models/AuditLog.d.ts +1359 -0
- package/dist/generated/prisma/models/AuditLog.js +2 -0
- package/dist/generated/prisma/models/Field.d.ts +1880 -0
- package/dist/generated/prisma/models/Field.js +2 -0
- package/dist/generated/prisma/models/FieldAttachment.d.ts +1245 -0
- package/dist/generated/prisma/models/FieldAttachment.js +2 -0
- package/dist/generated/prisma/models/FieldRecord.d.ts +1625 -0
- package/dist/generated/prisma/models/FieldRecord.js +2 -0
- package/dist/generated/prisma/models/FieldSet.d.ts +1577 -0
- package/dist/generated/prisma/models/FieldSet.js +2 -0
- package/dist/generated/prisma/models/FieldValue.d.ts +1908 -0
- package/dist/generated/prisma/models/FieldValue.js +2 -0
- package/dist/generated/prisma/models/Item.d.ts +1858 -0
- package/dist/generated/prisma/models/Item.js +2 -0
- package/dist/generated/prisma/models/ItemInstance.d.ts +1987 -0
- package/dist/generated/prisma/models/ItemInstance.js +2 -0
- package/dist/generated/prisma/models/LaborTicket.d.ts +1867 -0
- package/dist/generated/prisma/models/LaborTicket.js +2 -0
- package/dist/generated/prisma/models/Operation.d.ts +2578 -0
- package/dist/generated/prisma/models/Operation.js +2 -0
- package/dist/generated/prisma/models/OperationDependency.d.ts +1434 -0
- package/dist/generated/prisma/models/OperationDependency.js +2 -0
- package/dist/generated/prisma/models/OperationFieldRef.d.ts +1539 -0
- package/dist/generated/prisma/models/OperationFieldRef.js +2 -0
- package/dist/generated/prisma/models/OperationRun.d.ts +2563 -0
- package/dist/generated/prisma/models/OperationRun.js +2 -0
- package/dist/generated/prisma/models/OperationRunComment.d.ts +1366 -0
- package/dist/generated/prisma/models/OperationRunComment.js +2 -0
- package/dist/generated/prisma/models/Order.d.ts +1931 -0
- package/dist/generated/prisma/models/Order.js +2 -0
- package/dist/generated/prisma/models/OrderRevision.d.ts +1962 -0
- package/dist/generated/prisma/models/OrderRevision.js +2 -0
- package/dist/generated/prisma/models/OrderRun.d.ts +2310 -0
- package/dist/generated/prisma/models/OrderRun.js +2 -0
- package/dist/generated/prisma/models/SchemaVersion.d.ts +985 -0
- package/dist/generated/prisma/models/SchemaVersion.js +2 -0
- package/dist/generated/prisma/models/Session.d.ts +1213 -0
- package/dist/generated/prisma/models/Session.js +2 -0
- package/dist/generated/prisma/models/Step.d.ts +2180 -0
- package/dist/generated/prisma/models/Step.js +2 -0
- package/dist/generated/prisma/models/StepRun.d.ts +1963 -0
- package/dist/generated/prisma/models/StepRun.js +2 -0
- package/dist/generated/prisma/models/User.d.ts +11819 -0
- package/dist/generated/prisma/models/User.js +2 -0
- package/dist/generated/prisma/models/UserPermission.d.ts +1348 -0
- package/dist/generated/prisma/models/UserPermission.js +2 -0
- package/dist/generated/prisma/models/WorkCenter.d.ts +1657 -0
- package/dist/generated/prisma/models/WorkCenter.js +2 -0
- package/dist/generated/prisma/models/WorkCenterUser.d.ts +1390 -0
- package/dist/generated/prisma/models/WorkCenterUser.js +2 -0
- package/dist/generated/prisma/models.d.ts +28 -0
- package/dist/generated/prisma/models.js +2 -0
- package/dist/hateoas.d.ts +7 -0
- package/dist/hateoas.js +61 -0
- package/dist/route-helpers.d.ts +318 -0
- package/dist/route-helpers.js +220 -0
- package/dist/routes/admin.d.ts +3 -0
- package/dist/routes/admin.js +147 -0
- package/dist/routes/audit.d.ts +3 -0
- package/dist/routes/audit.js +36 -0
- package/dist/routes/auth.d.ts +3 -0
- package/dist/routes/auth.js +112 -0
- package/dist/routes/dispatch.d.ts +3 -0
- package/dist/routes/dispatch.js +174 -0
- package/dist/routes/inventory.d.ts +3 -0
- package/dist/routes/inventory.js +70 -0
- package/dist/routes/item-fields.d.ts +3 -0
- package/dist/routes/item-fields.js +220 -0
- package/dist/routes/item-instances.d.ts +3 -0
- package/dist/routes/item-instances.js +426 -0
- package/dist/routes/items.d.ts +3 -0
- package/dist/routes/items.js +252 -0
- package/dist/routes/labor-tickets.d.ts +3 -0
- package/dist/routes/labor-tickets.js +268 -0
- package/dist/routes/operation-dependencies.d.ts +3 -0
- package/dist/routes/operation-dependencies.js +170 -0
- package/dist/routes/operation-field-refs.d.ts +3 -0
- package/dist/routes/operation-field-refs.js +263 -0
- package/dist/routes/operation-run-comments.d.ts +3 -0
- package/dist/routes/operation-run-comments.js +108 -0
- package/dist/routes/operation-run-transitions.d.ts +3 -0
- package/dist/routes/operation-run-transitions.js +249 -0
- package/dist/routes/operation-runs.d.ts +112 -0
- package/dist/routes/operation-runs.js +299 -0
- package/dist/routes/operations.d.ts +3 -0
- package/dist/routes/operations.js +283 -0
- package/dist/routes/order-revision-transitions.d.ts +3 -0
- package/dist/routes/order-revision-transitions.js +86 -0
- package/dist/routes/order-revisions.d.ts +51 -0
- package/dist/routes/order-revisions.js +327 -0
- package/dist/routes/order-run-transitions.d.ts +3 -0
- package/dist/routes/order-run-transitions.js +215 -0
- package/dist/routes/order-runs.d.ts +58 -0
- package/dist/routes/order-runs.js +335 -0
- package/dist/routes/orders.d.ts +3 -0
- package/dist/routes/orders.js +262 -0
- package/dist/routes/root.d.ts +3 -0
- package/dist/routes/root.js +123 -0
- package/dist/routes/schemas.d.ts +3 -0
- package/dist/routes/schemas.js +31 -0
- package/dist/routes/step-field-attachments.d.ts +3 -0
- package/dist/routes/step-field-attachments.js +231 -0
- package/dist/routes/step-fields.d.ts +100 -0
- package/dist/routes/step-fields.js +315 -0
- package/dist/routes/step-run-fields.d.ts +3 -0
- package/dist/routes/step-run-fields.js +438 -0
- package/dist/routes/step-run-transitions.d.ts +3 -0
- package/dist/routes/step-run-transitions.js +113 -0
- package/dist/routes/step-runs.d.ts +332 -0
- package/dist/routes/step-runs.js +324 -0
- package/dist/routes/steps.d.ts +3 -0
- package/dist/routes/steps.js +283 -0
- package/dist/routes/user-permissions.d.ts +3 -0
- package/dist/routes/user-permissions.js +100 -0
- package/dist/routes/users.d.ts +57 -0
- package/dist/routes/users.js +381 -0
- package/dist/routes/work-centers.d.ts +3 -0
- package/dist/routes/work-centers.js +280 -0
- package/dist/schema-registry.d.ts +3 -0
- package/dist/schema-registry.js +45 -0
- package/dist/services/attachment-service.d.ts +33 -0
- package/dist/services/attachment-service.js +118 -0
- package/dist/services/field-ref-service.d.ts +96 -0
- package/dist/services/field-ref-service.js +74 -0
- package/dist/services/field-service.d.ts +49 -0
- package/dist/services/field-service.js +114 -0
- package/dist/services/field-value-service.d.ts +61 -0
- package/dist/services/field-value-service.js +256 -0
- package/dist/services/item-instance-service.d.ts +152 -0
- package/dist/services/item-instance-service.js +155 -0
- package/dist/services/item-service.d.ts +47 -0
- package/dist/services/item-service.js +56 -0
- package/dist/services/labor-ticket-service.d.ts +40 -0
- package/dist/services/labor-ticket-service.js +148 -0
- package/dist/services/log-file-service.d.ts +4 -0
- package/dist/services/log-file-service.js +11 -0
- package/dist/services/operation-dependency-service.d.ts +33 -0
- package/dist/services/operation-dependency-service.js +30 -0
- package/dist/services/operation-run-comment-service.d.ts +17 -0
- package/dist/services/operation-run-comment-service.js +26 -0
- package/dist/services/operation-run-service.d.ts +126 -0
- package/dist/services/operation-run-service.js +347 -0
- package/dist/services/operation-service.d.ts +47 -0
- package/dist/services/operation-service.js +132 -0
- package/dist/services/order-revision-service.d.ts +53 -0
- package/dist/services/order-revision-service.js +264 -0
- package/dist/services/order-run-service.d.ts +138 -0
- package/dist/services/order-run-service.js +356 -0
- package/dist/services/order-service.d.ts +15 -0
- package/dist/services/order-service.js +68 -0
- package/dist/services/revision-diff-service.d.ts +3 -0
- package/dist/services/revision-diff-service.js +194 -0
- package/dist/services/step-run-service.d.ts +172 -0
- package/dist/services/step-run-service.js +106 -0
- package/dist/services/step-service.d.ts +104 -0
- package/dist/services/step-service.js +89 -0
- package/dist/services/user-service.d.ts +185 -0
- package/dist/services/user-service.js +132 -0
- package/dist/services/work-center-service.d.ts +29 -0
- package/dist/services/work-center-service.js +106 -0
- package/dist/supervisorAuth.d.ts +3 -0
- package/dist/supervisorAuth.js +16 -0
- package/dist/userService.d.ts +20 -0
- package/dist/userService.js +118 -0
- package/package.json +69 -0
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
import "dotenv/config";
|
|
2
|
+
import "./schema-registry.js";
|
|
3
|
+
import { expandNaisysFolder } from "@naisys/common-node";
|
|
4
|
+
expandNaisysFolder();
|
|
5
|
+
// Important to load dotenv before any other imports, to ensure environment variables are available
|
|
6
|
+
import cookie from "@fastify/cookie";
|
|
7
|
+
import cors from "@fastify/cors";
|
|
8
|
+
import multipart from "@fastify/multipart";
|
|
9
|
+
import { fastifyRateLimit as rateLimit } from "@fastify/rate-limit";
|
|
10
|
+
import staticFiles from "@fastify/static";
|
|
11
|
+
import swagger from "@fastify/swagger";
|
|
12
|
+
import { commonErrorHandler, registerLenientJsonParser, registerSecurityHeaders, } from "@naisys/common";
|
|
13
|
+
import { createHubDatabaseClient, deployPrismaMigrations, } from "@naisys/hub-database";
|
|
14
|
+
import { createSupervisorDatabaseClient, handleResetPassword, } from "@naisys/supervisor-database";
|
|
15
|
+
import Fastify from "fastify";
|
|
16
|
+
import { jsonSchemaTransform, jsonSchemaTransformObject, serializerCompiler, validatorCompiler, } from "fastify-type-provider-zod";
|
|
17
|
+
import path from "path";
|
|
18
|
+
import pino from "pino";
|
|
19
|
+
import { fileURLToPath } from "url";
|
|
20
|
+
import { registerApiReference } from "./api-reference.js";
|
|
21
|
+
import { registerAuthMiddleware } from "./auth-middleware.js";
|
|
22
|
+
import { ERP_DB_VERSION, erpDbPath } from "./dbConfig.js";
|
|
23
|
+
import { initErpDb } from "./erpDb.js";
|
|
24
|
+
import adminRoutes from "./routes/admin.js";
|
|
25
|
+
import auditRoutes from "./routes/audit.js";
|
|
26
|
+
import authRoutes from "./routes/auth.js";
|
|
27
|
+
import dispatchRoutes from "./routes/dispatch.js";
|
|
28
|
+
import inventoryRoutes from "./routes/inventory.js";
|
|
29
|
+
import itemFieldRoutes from "./routes/item-fields.js";
|
|
30
|
+
import itemInstanceRoutes from "./routes/item-instances.js";
|
|
31
|
+
import itemRoutes from "./routes/items.js";
|
|
32
|
+
import laborTicketRoutes from "./routes/labor-tickets.js";
|
|
33
|
+
import operationDependencyRoutes from "./routes/operation-dependencies.js";
|
|
34
|
+
import operationFieldRefRoutes from "./routes/operation-field-refs.js";
|
|
35
|
+
import operationRunCommentRoutes from "./routes/operation-run-comments.js";
|
|
36
|
+
import operationRunTransitionRoutes from "./routes/operation-run-transitions.js";
|
|
37
|
+
import operationRunRoutes from "./routes/operation-runs.js";
|
|
38
|
+
import operationRoutes from "./routes/operations.js";
|
|
39
|
+
import orderRevisionTransitionRoutes from "./routes/order-revision-transitions.js";
|
|
40
|
+
import orderRevisionRoutes from "./routes/order-revisions.js";
|
|
41
|
+
import orderRunTransitionRoutes from "./routes/order-run-transitions.js";
|
|
42
|
+
import orderRunRoutes from "./routes/order-runs.js";
|
|
43
|
+
import orderRoutes from "./routes/orders.js";
|
|
44
|
+
import rootRoute from "./routes/root.js";
|
|
45
|
+
import schemaRoutes from "./routes/schemas.js";
|
|
46
|
+
import stepFieldAttachmentRoutes from "./routes/step-field-attachments.js";
|
|
47
|
+
import stepFieldRoutes from "./routes/step-fields.js";
|
|
48
|
+
import stepRunFieldRoutes from "./routes/step-run-fields.js";
|
|
49
|
+
import stepRunTransitionRoutes from "./routes/step-run-transitions.js";
|
|
50
|
+
import stepRunRoutes from "./routes/step-runs.js";
|
|
51
|
+
import stepRoutes from "./routes/steps.js";
|
|
52
|
+
import userPermissionRoutes from "./routes/user-permissions.js";
|
|
53
|
+
import userRoutes from "./routes/users.js";
|
|
54
|
+
import workCenterRoutes from "./routes/work-centers.js";
|
|
55
|
+
import { isSupervisorAuth } from "./supervisorAuth.js";
|
|
56
|
+
import { ensureLocalSuperAdmin, ensureSupervisorSuperAdmin, resetLocalPassword, } from "./userService.js";
|
|
57
|
+
export { enableSupervisorAuth } from "./supervisorAuth.js";
|
|
58
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
59
|
+
const __dirname = path.dirname(__filename);
|
|
60
|
+
/**
|
|
61
|
+
* Fastify plugin that registers ERP routes and static files.
|
|
62
|
+
* Can be used standalone or registered inside another Fastify app (e.g. supervisor).
|
|
63
|
+
*/
|
|
64
|
+
export const erpPlugin = async (fastify) => {
|
|
65
|
+
const isProd = process.env.NODE_ENV === "production";
|
|
66
|
+
// Cookie plugin (guard for supervisor embedding)
|
|
67
|
+
if (!fastify.hasDecorator("parseCookie")) {
|
|
68
|
+
await fastify.register(cookie);
|
|
69
|
+
}
|
|
70
|
+
// Multipart file upload support
|
|
71
|
+
if (!fastify.hasContentTypeParser("multipart/form-data")) {
|
|
72
|
+
await fastify.register(multipart, { limits: { fileSize: 10_000_000 } });
|
|
73
|
+
}
|
|
74
|
+
// Rate limiting — moderate global default, strict overrides on sensitive routes
|
|
75
|
+
await fastify.register(rateLimit, {
|
|
76
|
+
max: 500,
|
|
77
|
+
timeWindow: "1 minute",
|
|
78
|
+
allowList: (request) => !request.url.startsWith("/api/"),
|
|
79
|
+
});
|
|
80
|
+
// Auto-migrate ERP database
|
|
81
|
+
const erpServerDir = path.join(__dirname, "..");
|
|
82
|
+
await deployPrismaMigrations({
|
|
83
|
+
packageDir: erpServerDir,
|
|
84
|
+
databasePath: erpDbPath(),
|
|
85
|
+
expectedVersion: ERP_DB_VERSION,
|
|
86
|
+
});
|
|
87
|
+
// Initialize SQLite pragmas now that the database exists
|
|
88
|
+
await initErpDb();
|
|
89
|
+
if (isSupervisorAuth()) {
|
|
90
|
+
if (!(await createHubDatabaseClient())) {
|
|
91
|
+
throw new Error("[ERP] Hub database not available. Required for supervisor auth.");
|
|
92
|
+
}
|
|
93
|
+
if (!(await createSupervisorDatabaseClient())) {
|
|
94
|
+
throw new Error("[ERP] Supervisor database not available. Required for supervisor auth.");
|
|
95
|
+
}
|
|
96
|
+
await ensureSupervisorSuperAdmin();
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
await ensureLocalSuperAdmin();
|
|
100
|
+
}
|
|
101
|
+
fastify.setErrorHandler(commonErrorHandler);
|
|
102
|
+
registerAuthMiddleware(fastify);
|
|
103
|
+
// ERP-specific file logger (works in both standalone and hosted mode)
|
|
104
|
+
const naisysFolder = process.env.NAISYS_FOLDER;
|
|
105
|
+
if (naisysFolder) {
|
|
106
|
+
const erpLogDest = path.join(naisysFolder, "logs", "erp.log");
|
|
107
|
+
const erpFileLogger = pino({ level: "info" }, pino.destination({ dest: erpLogDest, mkdir: true }));
|
|
108
|
+
erpFileLogger.info("ERP plugin initialized");
|
|
109
|
+
fastify.addHook("onResponse", async (request, reply) => {
|
|
110
|
+
if (!request.url.startsWith("/api/erp"))
|
|
111
|
+
return;
|
|
112
|
+
const logFn = reply.statusCode >= 400 ? erpFileLogger.error : erpFileLogger.info;
|
|
113
|
+
logFn.call(erpFileLogger, {
|
|
114
|
+
responseTime: reply.elapsedTime,
|
|
115
|
+
statusCode: reply.statusCode,
|
|
116
|
+
}, `${request.method} ${request.url}`);
|
|
117
|
+
});
|
|
118
|
+
fastify.addHook("onError", async (request, _reply, error) => {
|
|
119
|
+
if (!request.url.startsWith("/api/erp"))
|
|
120
|
+
return;
|
|
121
|
+
erpFileLogger.error({
|
|
122
|
+
err: { message: error.message, stack: error.stack },
|
|
123
|
+
}, `${request.method} ${request.url} error`);
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
// API routes under /api/erp prefix
|
|
127
|
+
fastify.register(adminRoutes, { prefix: "/api/erp/admin" });
|
|
128
|
+
fastify.register(auditRoutes, { prefix: "/api/erp/audit" });
|
|
129
|
+
fastify.register(authRoutes, { prefix: "/api/erp/auth" });
|
|
130
|
+
fastify.register(dispatchRoutes, { prefix: "/api/erp/dispatch" });
|
|
131
|
+
fastify.register(inventoryRoutes, { prefix: "/api/erp/inventory" });
|
|
132
|
+
fastify.register(rootRoute, { prefix: "/api/erp" });
|
|
133
|
+
fastify.register(itemRoutes, { prefix: "/api/erp/items" });
|
|
134
|
+
fastify.register(itemFieldRoutes, {
|
|
135
|
+
prefix: "/api/erp/items/:key/fields",
|
|
136
|
+
});
|
|
137
|
+
fastify.register(itemInstanceRoutes, {
|
|
138
|
+
prefix: "/api/erp/items/:key/instances",
|
|
139
|
+
});
|
|
140
|
+
fastify.register(orderRoutes, {
|
|
141
|
+
prefix: "/api/erp/orders",
|
|
142
|
+
});
|
|
143
|
+
fastify.register(orderRevisionRoutes, {
|
|
144
|
+
prefix: "/api/erp/orders/:orderKey/revs",
|
|
145
|
+
});
|
|
146
|
+
fastify.register(orderRevisionTransitionRoutes, {
|
|
147
|
+
prefix: "/api/erp/orders/:orderKey/revs",
|
|
148
|
+
});
|
|
149
|
+
fastify.register(orderRunRoutes, {
|
|
150
|
+
prefix: "/api/erp/orders/:orderKey/runs",
|
|
151
|
+
});
|
|
152
|
+
fastify.register(orderRunTransitionRoutes, {
|
|
153
|
+
prefix: "/api/erp/orders/:orderKey/runs",
|
|
154
|
+
});
|
|
155
|
+
fastify.register(operationRoutes, {
|
|
156
|
+
prefix: "/api/erp/orders/:orderKey/revs/:revNo/ops",
|
|
157
|
+
});
|
|
158
|
+
fastify.register(operationDependencyRoutes, {
|
|
159
|
+
prefix: "/api/erp/orders/:orderKey/revs/:revNo/ops/:seqNo/deps",
|
|
160
|
+
});
|
|
161
|
+
fastify.register(operationFieldRefRoutes, {
|
|
162
|
+
prefix: "/api/erp/orders/:orderKey/revs/:revNo/ops/:seqNo/field-refs",
|
|
163
|
+
});
|
|
164
|
+
fastify.register(operationRunRoutes, {
|
|
165
|
+
prefix: "/api/erp/orders/:orderKey/runs/:runNo/ops",
|
|
166
|
+
});
|
|
167
|
+
fastify.register(operationRunTransitionRoutes, {
|
|
168
|
+
prefix: "/api/erp/orders/:orderKey/runs/:runNo/ops",
|
|
169
|
+
});
|
|
170
|
+
fastify.register(laborTicketRoutes, {
|
|
171
|
+
prefix: "/api/erp/orders/:orderKey/runs/:runNo/ops/:seqNo/labor",
|
|
172
|
+
});
|
|
173
|
+
fastify.register(operationRunCommentRoutes, {
|
|
174
|
+
prefix: "/api/erp/orders/:orderKey/runs/:runNo/ops/:seqNo/comments",
|
|
175
|
+
});
|
|
176
|
+
fastify.register(stepRunRoutes, {
|
|
177
|
+
prefix: "/api/erp/orders/:orderKey/runs/:runNo/ops/:seqNo/steps",
|
|
178
|
+
});
|
|
179
|
+
fastify.register(stepRunTransitionRoutes, {
|
|
180
|
+
prefix: "/api/erp/orders/:orderKey/runs/:runNo/ops/:seqNo/steps",
|
|
181
|
+
});
|
|
182
|
+
fastify.register(stepRunFieldRoutes, {
|
|
183
|
+
prefix: "/api/erp/orders/:orderKey/runs/:runNo/ops/:seqNo/steps",
|
|
184
|
+
});
|
|
185
|
+
fastify.register(stepFieldAttachmentRoutes, {
|
|
186
|
+
prefix: "/api/erp/orders/:orderKey/runs/:runNo/ops/:seqNo/steps/:stepSeqNo/fields/:fieldSeqNo/attachments",
|
|
187
|
+
});
|
|
188
|
+
fastify.register(stepFieldAttachmentRoutes, {
|
|
189
|
+
prefix: "/api/erp/orders/:orderKey/runs/:runNo/ops/:seqNo/steps/:stepSeqNo/sets/:setIndex/fields/:fieldSeqNo/attachments",
|
|
190
|
+
});
|
|
191
|
+
fastify.register(stepRoutes, {
|
|
192
|
+
prefix: "/api/erp/orders/:orderKey/revs/:revNo/ops/:seqNo/steps",
|
|
193
|
+
});
|
|
194
|
+
fastify.register(stepFieldRoutes, {
|
|
195
|
+
prefix: "/api/erp/orders/:orderKey/revs/:revNo/ops/:seqNo/steps/:stepSeqNo/fields",
|
|
196
|
+
});
|
|
197
|
+
fastify.register(schemaRoutes, { prefix: "/api/erp/schemas" });
|
|
198
|
+
fastify.register(userRoutes, { prefix: "/api/erp/users" });
|
|
199
|
+
fastify.register(userPermissionRoutes, { prefix: "/api/erp/users" });
|
|
200
|
+
fastify.register(workCenterRoutes, { prefix: "/api/erp/work-centers" });
|
|
201
|
+
// Public endpoint to expose client configuration (publicRead, etc.)
|
|
202
|
+
fastify.get("/api/erp/client-config", { schema: { hide: true } }, () => ({
|
|
203
|
+
publicRead: process.env.PUBLIC_READ === "true",
|
|
204
|
+
supervisorAuth: isSupervisorAuth(),
|
|
205
|
+
}));
|
|
206
|
+
registerApiReference(fastify);
|
|
207
|
+
// In production, serve the client build
|
|
208
|
+
if (isProd) {
|
|
209
|
+
const clientDistPath = path.join(__dirname, "../client-dist");
|
|
210
|
+
// Serve static assets and SPA fallback in an encapsulated context
|
|
211
|
+
// to avoid decorator conflicts with the supervisor's @fastify/static
|
|
212
|
+
fastify.register(async (scope) => {
|
|
213
|
+
await scope.register(staticFiles, {
|
|
214
|
+
root: clientDistPath,
|
|
215
|
+
prefix: "/erp/",
|
|
216
|
+
wildcard: false,
|
|
217
|
+
});
|
|
218
|
+
// SPA fallback for /erp/* routes (but not /erp/api-reference)
|
|
219
|
+
scope.get("/erp/*", (_request, reply) => {
|
|
220
|
+
const url = _request.url;
|
|
221
|
+
if (url.startsWith("/erp/api-reference"))
|
|
222
|
+
return reply.callNotFound();
|
|
223
|
+
// If the URL has a file extension, it's a static asset that wasn't matched
|
|
224
|
+
// by the registered routes — likely because the client was rebuilt while
|
|
225
|
+
// the server was running. Return 404 instead of silently serving index.html.
|
|
226
|
+
if (/\.\w+$/.test(url)) {
|
|
227
|
+
reply.code(404).send({
|
|
228
|
+
error: `Static file not found: ${url} — server restart may be needed after a client rebuild`,
|
|
229
|
+
});
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
reply.sendFile("index.html", clientDistPath);
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
async function startServer() {
|
|
238
|
+
const isProd = process.env.NODE_ENV === "production";
|
|
239
|
+
const fastify = Fastify({
|
|
240
|
+
pluginTimeout: 60_000,
|
|
241
|
+
logger: {
|
|
242
|
+
transport: {
|
|
243
|
+
target: "pino-pretty",
|
|
244
|
+
options: { colorize: true },
|
|
245
|
+
},
|
|
246
|
+
},
|
|
247
|
+
}).withTypeProvider();
|
|
248
|
+
fastify.setValidatorCompiler(validatorCompiler);
|
|
249
|
+
fastify.setSerializerCompiler(serializerCompiler);
|
|
250
|
+
registerLenientJsonParser(fastify);
|
|
251
|
+
await fastify.register(cors, {
|
|
252
|
+
origin: isProd ? false : ["http://localhost:3202"],
|
|
253
|
+
credentials: true,
|
|
254
|
+
});
|
|
255
|
+
registerSecurityHeaders(fastify, { enforceHsts: isProd });
|
|
256
|
+
// Swagger (schema collection); Scalar API reference is served by erpPlugin
|
|
257
|
+
await fastify.register(swagger, {
|
|
258
|
+
openapi: {
|
|
259
|
+
info: {
|
|
260
|
+
title: "NAISYS ERP API",
|
|
261
|
+
description: "AI-first ERP system - Order management and definitions",
|
|
262
|
+
version: "1.0.0",
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
transform: jsonSchemaTransform,
|
|
266
|
+
transformObject: jsonSchemaTransformObject,
|
|
267
|
+
});
|
|
268
|
+
fastify.get("/", { schema: { hide: true } }, async (_request, reply) => {
|
|
269
|
+
return reply.redirect("/erp/");
|
|
270
|
+
});
|
|
271
|
+
await fastify.register(erpPlugin);
|
|
272
|
+
const port = Number(process.env.ERP_PORT) || 3201;
|
|
273
|
+
const host = isProd ? "0.0.0.0" : "localhost";
|
|
274
|
+
try {
|
|
275
|
+
await fastify.listen({ port, host });
|
|
276
|
+
console.log(`[ERP] Running on http://${host}:${port}/erp`);
|
|
277
|
+
console.log(`[ERP] API Reference: http://${host}:${port}/erp/api-reference`);
|
|
278
|
+
console.log(`[ERP] Auth mode: ${isSupervisorAuth() ? "supervisor" : "standalone"}`);
|
|
279
|
+
}
|
|
280
|
+
catch (err) {
|
|
281
|
+
console.error("[ERP] Failed to start:", err);
|
|
282
|
+
process.exit(1);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
// Start server if this file is run directly
|
|
286
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
287
|
+
if (process.argv.includes("--reset-password")) {
|
|
288
|
+
const usernameIdx = process.argv.indexOf("--username");
|
|
289
|
+
const passwordIdx = process.argv.indexOf("--password");
|
|
290
|
+
const username = usernameIdx !== -1 ? process.argv[usernameIdx + 1] : undefined;
|
|
291
|
+
const password = passwordIdx !== -1 ? process.argv[passwordIdx + 1] : undefined;
|
|
292
|
+
await initErpDb();
|
|
293
|
+
if (isSupervisorAuth()) {
|
|
294
|
+
void handleResetPassword({
|
|
295
|
+
findLocalUser: async (username) => {
|
|
296
|
+
const prisma = (await import("./erpDb.js")).default;
|
|
297
|
+
const user = await prisma.user.findUnique({ where: { username } });
|
|
298
|
+
return user
|
|
299
|
+
? { id: user.id, username: user.username, uuid: user.uuid }
|
|
300
|
+
: null;
|
|
301
|
+
},
|
|
302
|
+
updateLocalPassword: async (userId, passwordHash) => {
|
|
303
|
+
const prisma = (await import("./erpDb.js")).default;
|
|
304
|
+
await prisma.user.update({
|
|
305
|
+
where: { id: userId },
|
|
306
|
+
data: { passwordHash },
|
|
307
|
+
});
|
|
308
|
+
},
|
|
309
|
+
username,
|
|
310
|
+
password,
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
void resetLocalPassword();
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
void startServer();
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
//# sourceMappingURL=erpServer.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ErrorResponse } from "@naisys/erp-shared";
|
|
2
|
+
import type { FastifyReply } from "fastify";
|
|
3
|
+
export declare function notFound(reply: FastifyReply, message: string): ErrorResponse;
|
|
4
|
+
export declare function conflict(reply: FastifyReply, message: string): ErrorResponse;
|
|
5
|
+
export declare function unauthorized(reply: FastifyReply, message: string): ErrorResponse;
|
|
6
|
+
export declare function unprocessable(reply: FastifyReply, message: string): ErrorResponse;
|
|
7
|
+
//# sourceMappingURL=error-handler.d.ts.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
function send(reply, statusCode, error, message) {
|
|
2
|
+
reply.status(statusCode);
|
|
3
|
+
return { statusCode, error, message };
|
|
4
|
+
}
|
|
5
|
+
export function notFound(reply, message) {
|
|
6
|
+
return send(reply, 404, "Not Found", message);
|
|
7
|
+
}
|
|
8
|
+
export function conflict(reply, message) {
|
|
9
|
+
return send(reply, 409, "Conflict", message);
|
|
10
|
+
}
|
|
11
|
+
export function unauthorized(reply, message) {
|
|
12
|
+
return send(reply, 401, "Unauthorized", message);
|
|
13
|
+
}
|
|
14
|
+
export function unprocessable(reply, message) {
|
|
15
|
+
return send(reply, 422, "Unprocessable Entity", message);
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=error-handler.js.map
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import * as runtime from "@prisma/client/runtime/client";
|
|
2
|
+
import * as $Class from "./internal/class.js";
|
|
3
|
+
import * as Prisma from "./internal/prismaNamespace.js";
|
|
4
|
+
export * as $Enums from './enums.js';
|
|
5
|
+
export * from "./enums.js";
|
|
6
|
+
/**
|
|
7
|
+
* ## Prisma Client
|
|
8
|
+
*
|
|
9
|
+
* Type-safe database client for TypeScript
|
|
10
|
+
* @example
|
|
11
|
+
* ```
|
|
12
|
+
* const prisma = new PrismaClient({
|
|
13
|
+
* adapter: new PrismaPg({ connectionString: process.env.DATABASE_URL })
|
|
14
|
+
* })
|
|
15
|
+
* // Fetch zero or more Orders
|
|
16
|
+
* const orders = await prisma.order.findMany()
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* Read more in our [docs](https://pris.ly/d/client).
|
|
20
|
+
*/
|
|
21
|
+
export declare const PrismaClient: $Class.PrismaClientConstructor;
|
|
22
|
+
export type PrismaClient<LogOpts extends Prisma.LogLevel = never, OmitOpts extends Prisma.PrismaClientOptions["omit"] = Prisma.PrismaClientOptions["omit"], ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = $Class.PrismaClient<LogOpts, OmitOpts, ExtArgs>;
|
|
23
|
+
export { Prisma };
|
|
24
|
+
/**
|
|
25
|
+
* Model Order
|
|
26
|
+
*
|
|
27
|
+
*/
|
|
28
|
+
export type Order = Prisma.OrderModel;
|
|
29
|
+
/**
|
|
30
|
+
* Model OrderRevision
|
|
31
|
+
*
|
|
32
|
+
*/
|
|
33
|
+
export type OrderRevision = Prisma.OrderRevisionModel;
|
|
34
|
+
/**
|
|
35
|
+
* Model Operation
|
|
36
|
+
*
|
|
37
|
+
*/
|
|
38
|
+
export type Operation = Prisma.OperationModel;
|
|
39
|
+
/**
|
|
40
|
+
* Model OperationFieldRef
|
|
41
|
+
*
|
|
42
|
+
*/
|
|
43
|
+
export type OperationFieldRef = Prisma.OperationFieldRefModel;
|
|
44
|
+
/**
|
|
45
|
+
* Model OperationDependency
|
|
46
|
+
*
|
|
47
|
+
*/
|
|
48
|
+
export type OperationDependency = Prisma.OperationDependencyModel;
|
|
49
|
+
/**
|
|
50
|
+
* Model WorkCenter
|
|
51
|
+
*
|
|
52
|
+
*/
|
|
53
|
+
export type WorkCenter = Prisma.WorkCenterModel;
|
|
54
|
+
/**
|
|
55
|
+
* Model WorkCenterUser
|
|
56
|
+
*
|
|
57
|
+
*/
|
|
58
|
+
export type WorkCenterUser = Prisma.WorkCenterUserModel;
|
|
59
|
+
/**
|
|
60
|
+
* Model FieldSet
|
|
61
|
+
*
|
|
62
|
+
*/
|
|
63
|
+
export type FieldSet = Prisma.FieldSetModel;
|
|
64
|
+
/**
|
|
65
|
+
* Model FieldRecord
|
|
66
|
+
*
|
|
67
|
+
*/
|
|
68
|
+
export type FieldRecord = Prisma.FieldRecordModel;
|
|
69
|
+
/**
|
|
70
|
+
* Model Field
|
|
71
|
+
*
|
|
72
|
+
*/
|
|
73
|
+
export type Field = Prisma.FieldModel;
|
|
74
|
+
/**
|
|
75
|
+
* Model Step
|
|
76
|
+
*
|
|
77
|
+
*/
|
|
78
|
+
export type Step = Prisma.StepModel;
|
|
79
|
+
/**
|
|
80
|
+
* Model OrderRun
|
|
81
|
+
*
|
|
82
|
+
*/
|
|
83
|
+
export type OrderRun = Prisma.OrderRunModel;
|
|
84
|
+
/**
|
|
85
|
+
* Model OperationRun
|
|
86
|
+
*
|
|
87
|
+
*/
|
|
88
|
+
export type OperationRun = Prisma.OperationRunModel;
|
|
89
|
+
/**
|
|
90
|
+
* Model StepRun
|
|
91
|
+
*
|
|
92
|
+
*/
|
|
93
|
+
export type StepRun = Prisma.StepRunModel;
|
|
94
|
+
/**
|
|
95
|
+
* Model FieldValue
|
|
96
|
+
*
|
|
97
|
+
*/
|
|
98
|
+
export type FieldValue = Prisma.FieldValueModel;
|
|
99
|
+
/**
|
|
100
|
+
* Model Item
|
|
101
|
+
*
|
|
102
|
+
*/
|
|
103
|
+
export type Item = Prisma.ItemModel;
|
|
104
|
+
/**
|
|
105
|
+
* Model ItemInstance
|
|
106
|
+
*
|
|
107
|
+
*/
|
|
108
|
+
export type ItemInstance = Prisma.ItemInstanceModel;
|
|
109
|
+
/**
|
|
110
|
+
* Model User
|
|
111
|
+
*
|
|
112
|
+
*/
|
|
113
|
+
export type User = Prisma.UserModel;
|
|
114
|
+
/**
|
|
115
|
+
* Model UserPermission
|
|
116
|
+
*
|
|
117
|
+
*/
|
|
118
|
+
export type UserPermission = Prisma.UserPermissionModel;
|
|
119
|
+
/**
|
|
120
|
+
* Model Session
|
|
121
|
+
*
|
|
122
|
+
*/
|
|
123
|
+
export type Session = Prisma.SessionModel;
|
|
124
|
+
/**
|
|
125
|
+
* Model SchemaVersion
|
|
126
|
+
*
|
|
127
|
+
*/
|
|
128
|
+
export type SchemaVersion = Prisma.SchemaVersionModel;
|
|
129
|
+
/**
|
|
130
|
+
* Model LaborTicket
|
|
131
|
+
*
|
|
132
|
+
*/
|
|
133
|
+
export type LaborTicket = Prisma.LaborTicketModel;
|
|
134
|
+
/**
|
|
135
|
+
* Model AuditLog
|
|
136
|
+
*
|
|
137
|
+
*/
|
|
138
|
+
export type AuditLog = Prisma.AuditLogModel;
|
|
139
|
+
/**
|
|
140
|
+
* Model Attachment
|
|
141
|
+
*
|
|
142
|
+
*/
|
|
143
|
+
export type Attachment = Prisma.AttachmentModel;
|
|
144
|
+
/**
|
|
145
|
+
* Model FieldAttachment
|
|
146
|
+
*
|
|
147
|
+
*/
|
|
148
|
+
export type FieldAttachment = Prisma.FieldAttachmentModel;
|
|
149
|
+
/**
|
|
150
|
+
* Model OperationRunComment
|
|
151
|
+
*
|
|
152
|
+
*/
|
|
153
|
+
export type OperationRunComment = Prisma.OperationRunCommentModel;
|
|
154
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/* !!! This is code generated by Prisma. Do not edit directly. !!! */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
// biome-ignore-all lint: generated file
|
|
4
|
+
// @ts-nocheck
|
|
5
|
+
/*
|
|
6
|
+
* This file should be your main import to use Prisma. Through it you get access to all the models, enums, and input types.
|
|
7
|
+
* If you're looking for something you can import in the client-side of your application, please refer to the `browser.ts` file instead.
|
|
8
|
+
*
|
|
9
|
+
* 🟢 You can import this file directly.
|
|
10
|
+
*/
|
|
11
|
+
import * as path from 'node:path';
|
|
12
|
+
import { fileURLToPath } from 'node:url';
|
|
13
|
+
globalThis['__dirname'] = path.dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
import * as $Class from "./internal/class.js";
|
|
15
|
+
import * as Prisma from "./internal/prismaNamespace.js";
|
|
16
|
+
export * as $Enums from './enums.js';
|
|
17
|
+
export * from "./enums.js";
|
|
18
|
+
/**
|
|
19
|
+
* ## Prisma Client
|
|
20
|
+
*
|
|
21
|
+
* Type-safe database client for TypeScript
|
|
22
|
+
* @example
|
|
23
|
+
* ```
|
|
24
|
+
* const prisma = new PrismaClient({
|
|
25
|
+
* adapter: new PrismaPg({ connectionString: process.env.DATABASE_URL })
|
|
26
|
+
* })
|
|
27
|
+
* // Fetch zero or more Orders
|
|
28
|
+
* const orders = await prisma.order.findMany()
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* Read more in our [docs](https://pris.ly/d/client).
|
|
32
|
+
*/
|
|
33
|
+
export const PrismaClient = $Class.getPrismaClientClass();
|
|
34
|
+
export { Prisma };
|
|
35
|
+
//# sourceMappingURL=client.js.map
|