@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.

Files changed (201) hide show
  1. package/bin/naisys-erp +2 -0
  2. package/client-dist/android-chrome-192x192.png +0 -0
  3. package/client-dist/android-chrome-512x512.png +0 -0
  4. package/client-dist/apple-touch-icon.png +0 -0
  5. package/client-dist/assets/index-45dVo30p.css +1 -0
  6. package/client-dist/assets/index-Dffms7F_.js +168 -0
  7. package/client-dist/assets/naisys-logo-CzoPnn5I.webp +0 -0
  8. package/client-dist/favicon.ico +0 -0
  9. package/client-dist/index.html +42 -0
  10. package/client-dist/site.webmanifest +22 -0
  11. package/dist/api-reference.d.ts +10 -0
  12. package/dist/api-reference.js +101 -0
  13. package/dist/audit.d.ts +5 -0
  14. package/dist/audit.js +14 -0
  15. package/dist/auth-middleware.d.ts +18 -0
  16. package/dist/auth-middleware.js +203 -0
  17. package/dist/dbConfig.d.ts +5 -0
  18. package/dist/dbConfig.js +10 -0
  19. package/dist/erpDb.d.ts +10 -0
  20. package/dist/erpDb.js +34 -0
  21. package/dist/erpServer.d.ts +10 -0
  22. package/dist/erpServer.js +321 -0
  23. package/dist/error-handler.d.ts +7 -0
  24. package/dist/error-handler.js +17 -0
  25. package/dist/generated/prisma/client.d.ts +154 -0
  26. package/dist/generated/prisma/client.js +35 -0
  27. package/dist/generated/prisma/commonInputTypes.d.ts +637 -0
  28. package/dist/generated/prisma/commonInputTypes.js +11 -0
  29. package/dist/generated/prisma/enums.d.ts +59 -0
  30. package/dist/generated/prisma/enums.js +60 -0
  31. package/dist/generated/prisma/internal/class.d.ts +406 -0
  32. package/dist/generated/prisma/internal/class.js +50 -0
  33. package/dist/generated/prisma/internal/prismaNamespace.d.ts +2722 -0
  34. package/dist/generated/prisma/internal/prismaNamespace.js +366 -0
  35. package/dist/generated/prisma/models/Attachment.d.ts +1455 -0
  36. package/dist/generated/prisma/models/Attachment.js +2 -0
  37. package/dist/generated/prisma/models/AuditLog.d.ts +1359 -0
  38. package/dist/generated/prisma/models/AuditLog.js +2 -0
  39. package/dist/generated/prisma/models/Field.d.ts +1880 -0
  40. package/dist/generated/prisma/models/Field.js +2 -0
  41. package/dist/generated/prisma/models/FieldAttachment.d.ts +1245 -0
  42. package/dist/generated/prisma/models/FieldAttachment.js +2 -0
  43. package/dist/generated/prisma/models/FieldRecord.d.ts +1625 -0
  44. package/dist/generated/prisma/models/FieldRecord.js +2 -0
  45. package/dist/generated/prisma/models/FieldSet.d.ts +1577 -0
  46. package/dist/generated/prisma/models/FieldSet.js +2 -0
  47. package/dist/generated/prisma/models/FieldValue.d.ts +1908 -0
  48. package/dist/generated/prisma/models/FieldValue.js +2 -0
  49. package/dist/generated/prisma/models/Item.d.ts +1858 -0
  50. package/dist/generated/prisma/models/Item.js +2 -0
  51. package/dist/generated/prisma/models/ItemInstance.d.ts +1987 -0
  52. package/dist/generated/prisma/models/ItemInstance.js +2 -0
  53. package/dist/generated/prisma/models/LaborTicket.d.ts +1867 -0
  54. package/dist/generated/prisma/models/LaborTicket.js +2 -0
  55. package/dist/generated/prisma/models/Operation.d.ts +2578 -0
  56. package/dist/generated/prisma/models/Operation.js +2 -0
  57. package/dist/generated/prisma/models/OperationDependency.d.ts +1434 -0
  58. package/dist/generated/prisma/models/OperationDependency.js +2 -0
  59. package/dist/generated/prisma/models/OperationFieldRef.d.ts +1539 -0
  60. package/dist/generated/prisma/models/OperationFieldRef.js +2 -0
  61. package/dist/generated/prisma/models/OperationRun.d.ts +2563 -0
  62. package/dist/generated/prisma/models/OperationRun.js +2 -0
  63. package/dist/generated/prisma/models/OperationRunComment.d.ts +1366 -0
  64. package/dist/generated/prisma/models/OperationRunComment.js +2 -0
  65. package/dist/generated/prisma/models/Order.d.ts +1931 -0
  66. package/dist/generated/prisma/models/Order.js +2 -0
  67. package/dist/generated/prisma/models/OrderRevision.d.ts +1962 -0
  68. package/dist/generated/prisma/models/OrderRevision.js +2 -0
  69. package/dist/generated/prisma/models/OrderRun.d.ts +2310 -0
  70. package/dist/generated/prisma/models/OrderRun.js +2 -0
  71. package/dist/generated/prisma/models/SchemaVersion.d.ts +985 -0
  72. package/dist/generated/prisma/models/SchemaVersion.js +2 -0
  73. package/dist/generated/prisma/models/Session.d.ts +1213 -0
  74. package/dist/generated/prisma/models/Session.js +2 -0
  75. package/dist/generated/prisma/models/Step.d.ts +2180 -0
  76. package/dist/generated/prisma/models/Step.js +2 -0
  77. package/dist/generated/prisma/models/StepRun.d.ts +1963 -0
  78. package/dist/generated/prisma/models/StepRun.js +2 -0
  79. package/dist/generated/prisma/models/User.d.ts +11819 -0
  80. package/dist/generated/prisma/models/User.js +2 -0
  81. package/dist/generated/prisma/models/UserPermission.d.ts +1348 -0
  82. package/dist/generated/prisma/models/UserPermission.js +2 -0
  83. package/dist/generated/prisma/models/WorkCenter.d.ts +1657 -0
  84. package/dist/generated/prisma/models/WorkCenter.js +2 -0
  85. package/dist/generated/prisma/models/WorkCenterUser.d.ts +1390 -0
  86. package/dist/generated/prisma/models/WorkCenterUser.js +2 -0
  87. package/dist/generated/prisma/models.d.ts +28 -0
  88. package/dist/generated/prisma/models.js +2 -0
  89. package/dist/hateoas.d.ts +7 -0
  90. package/dist/hateoas.js +61 -0
  91. package/dist/route-helpers.d.ts +318 -0
  92. package/dist/route-helpers.js +220 -0
  93. package/dist/routes/admin.d.ts +3 -0
  94. package/dist/routes/admin.js +147 -0
  95. package/dist/routes/audit.d.ts +3 -0
  96. package/dist/routes/audit.js +36 -0
  97. package/dist/routes/auth.d.ts +3 -0
  98. package/dist/routes/auth.js +112 -0
  99. package/dist/routes/dispatch.d.ts +3 -0
  100. package/dist/routes/dispatch.js +174 -0
  101. package/dist/routes/inventory.d.ts +3 -0
  102. package/dist/routes/inventory.js +70 -0
  103. package/dist/routes/item-fields.d.ts +3 -0
  104. package/dist/routes/item-fields.js +220 -0
  105. package/dist/routes/item-instances.d.ts +3 -0
  106. package/dist/routes/item-instances.js +426 -0
  107. package/dist/routes/items.d.ts +3 -0
  108. package/dist/routes/items.js +252 -0
  109. package/dist/routes/labor-tickets.d.ts +3 -0
  110. package/dist/routes/labor-tickets.js +268 -0
  111. package/dist/routes/operation-dependencies.d.ts +3 -0
  112. package/dist/routes/operation-dependencies.js +170 -0
  113. package/dist/routes/operation-field-refs.d.ts +3 -0
  114. package/dist/routes/operation-field-refs.js +263 -0
  115. package/dist/routes/operation-run-comments.d.ts +3 -0
  116. package/dist/routes/operation-run-comments.js +108 -0
  117. package/dist/routes/operation-run-transitions.d.ts +3 -0
  118. package/dist/routes/operation-run-transitions.js +249 -0
  119. package/dist/routes/operation-runs.d.ts +112 -0
  120. package/dist/routes/operation-runs.js +299 -0
  121. package/dist/routes/operations.d.ts +3 -0
  122. package/dist/routes/operations.js +283 -0
  123. package/dist/routes/order-revision-transitions.d.ts +3 -0
  124. package/dist/routes/order-revision-transitions.js +86 -0
  125. package/dist/routes/order-revisions.d.ts +51 -0
  126. package/dist/routes/order-revisions.js +327 -0
  127. package/dist/routes/order-run-transitions.d.ts +3 -0
  128. package/dist/routes/order-run-transitions.js +215 -0
  129. package/dist/routes/order-runs.d.ts +58 -0
  130. package/dist/routes/order-runs.js +335 -0
  131. package/dist/routes/orders.d.ts +3 -0
  132. package/dist/routes/orders.js +262 -0
  133. package/dist/routes/root.d.ts +3 -0
  134. package/dist/routes/root.js +123 -0
  135. package/dist/routes/schemas.d.ts +3 -0
  136. package/dist/routes/schemas.js +31 -0
  137. package/dist/routes/step-field-attachments.d.ts +3 -0
  138. package/dist/routes/step-field-attachments.js +231 -0
  139. package/dist/routes/step-fields.d.ts +100 -0
  140. package/dist/routes/step-fields.js +315 -0
  141. package/dist/routes/step-run-fields.d.ts +3 -0
  142. package/dist/routes/step-run-fields.js +438 -0
  143. package/dist/routes/step-run-transitions.d.ts +3 -0
  144. package/dist/routes/step-run-transitions.js +113 -0
  145. package/dist/routes/step-runs.d.ts +332 -0
  146. package/dist/routes/step-runs.js +324 -0
  147. package/dist/routes/steps.d.ts +3 -0
  148. package/dist/routes/steps.js +283 -0
  149. package/dist/routes/user-permissions.d.ts +3 -0
  150. package/dist/routes/user-permissions.js +100 -0
  151. package/dist/routes/users.d.ts +57 -0
  152. package/dist/routes/users.js +381 -0
  153. package/dist/routes/work-centers.d.ts +3 -0
  154. package/dist/routes/work-centers.js +280 -0
  155. package/dist/schema-registry.d.ts +3 -0
  156. package/dist/schema-registry.js +45 -0
  157. package/dist/services/attachment-service.d.ts +33 -0
  158. package/dist/services/attachment-service.js +118 -0
  159. package/dist/services/field-ref-service.d.ts +96 -0
  160. package/dist/services/field-ref-service.js +74 -0
  161. package/dist/services/field-service.d.ts +49 -0
  162. package/dist/services/field-service.js +114 -0
  163. package/dist/services/field-value-service.d.ts +61 -0
  164. package/dist/services/field-value-service.js +256 -0
  165. package/dist/services/item-instance-service.d.ts +152 -0
  166. package/dist/services/item-instance-service.js +155 -0
  167. package/dist/services/item-service.d.ts +47 -0
  168. package/dist/services/item-service.js +56 -0
  169. package/dist/services/labor-ticket-service.d.ts +40 -0
  170. package/dist/services/labor-ticket-service.js +148 -0
  171. package/dist/services/log-file-service.d.ts +4 -0
  172. package/dist/services/log-file-service.js +11 -0
  173. package/dist/services/operation-dependency-service.d.ts +33 -0
  174. package/dist/services/operation-dependency-service.js +30 -0
  175. package/dist/services/operation-run-comment-service.d.ts +17 -0
  176. package/dist/services/operation-run-comment-service.js +26 -0
  177. package/dist/services/operation-run-service.d.ts +126 -0
  178. package/dist/services/operation-run-service.js +347 -0
  179. package/dist/services/operation-service.d.ts +47 -0
  180. package/dist/services/operation-service.js +132 -0
  181. package/dist/services/order-revision-service.d.ts +53 -0
  182. package/dist/services/order-revision-service.js +264 -0
  183. package/dist/services/order-run-service.d.ts +138 -0
  184. package/dist/services/order-run-service.js +356 -0
  185. package/dist/services/order-service.d.ts +15 -0
  186. package/dist/services/order-service.js +68 -0
  187. package/dist/services/revision-diff-service.d.ts +3 -0
  188. package/dist/services/revision-diff-service.js +194 -0
  189. package/dist/services/step-run-service.d.ts +172 -0
  190. package/dist/services/step-run-service.js +106 -0
  191. package/dist/services/step-service.d.ts +104 -0
  192. package/dist/services/step-service.js +89 -0
  193. package/dist/services/user-service.d.ts +185 -0
  194. package/dist/services/user-service.js +132 -0
  195. package/dist/services/work-center-service.d.ts +29 -0
  196. package/dist/services/work-center-service.js +106 -0
  197. package/dist/supervisorAuth.d.ts +3 -0
  198. package/dist/supervisorAuth.js +16 -0
  199. package/dist/userService.d.ts +20 -0
  200. package/dist/userService.js +118 -0
  201. 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