@naisys/erp 3.0.0-beta.6

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.
Files changed (150) 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.js +101 -0
  12. package/dist/audit.js +14 -0
  13. package/dist/auth-middleware.js +203 -0
  14. package/dist/dbConfig.js +10 -0
  15. package/dist/erpDb.js +34 -0
  16. package/dist/erpServer.js +321 -0
  17. package/dist/error-handler.js +17 -0
  18. package/dist/generated/prisma/client.js +35 -0
  19. package/dist/generated/prisma/commonInputTypes.js +11 -0
  20. package/dist/generated/prisma/enums.js +60 -0
  21. package/dist/generated/prisma/internal/class.js +50 -0
  22. package/dist/generated/prisma/internal/prismaNamespace.js +366 -0
  23. package/dist/generated/prisma/models/Attachment.js +2 -0
  24. package/dist/generated/prisma/models/AuditLog.js +2 -0
  25. package/dist/generated/prisma/models/Field.js +2 -0
  26. package/dist/generated/prisma/models/FieldAttachment.js +2 -0
  27. package/dist/generated/prisma/models/FieldRecord.js +2 -0
  28. package/dist/generated/prisma/models/FieldSet.js +2 -0
  29. package/dist/generated/prisma/models/FieldValue.js +2 -0
  30. package/dist/generated/prisma/models/Item.js +2 -0
  31. package/dist/generated/prisma/models/ItemInstance.js +2 -0
  32. package/dist/generated/prisma/models/LaborTicket.js +2 -0
  33. package/dist/generated/prisma/models/Operation.js +2 -0
  34. package/dist/generated/prisma/models/OperationDependency.js +2 -0
  35. package/dist/generated/prisma/models/OperationFieldRef.js +2 -0
  36. package/dist/generated/prisma/models/OperationRun.js +2 -0
  37. package/dist/generated/prisma/models/OperationRunComment.js +2 -0
  38. package/dist/generated/prisma/models/Order.js +2 -0
  39. package/dist/generated/prisma/models/OrderRevision.js +2 -0
  40. package/dist/generated/prisma/models/OrderRun.js +2 -0
  41. package/dist/generated/prisma/models/SchemaVersion.js +2 -0
  42. package/dist/generated/prisma/models/Session.js +2 -0
  43. package/dist/generated/prisma/models/Step.js +2 -0
  44. package/dist/generated/prisma/models/StepRun.js +2 -0
  45. package/dist/generated/prisma/models/User.js +2 -0
  46. package/dist/generated/prisma/models/UserPermission.js +2 -0
  47. package/dist/generated/prisma/models/WorkCenter.js +2 -0
  48. package/dist/generated/prisma/models/WorkCenterUser.js +2 -0
  49. package/dist/generated/prisma/models.js +2 -0
  50. package/dist/hateoas.js +61 -0
  51. package/dist/route-helpers.js +220 -0
  52. package/dist/routes/admin.js +147 -0
  53. package/dist/routes/audit.js +36 -0
  54. package/dist/routes/auth.js +112 -0
  55. package/dist/routes/dispatch.js +174 -0
  56. package/dist/routes/inventory.js +70 -0
  57. package/dist/routes/item-fields.js +220 -0
  58. package/dist/routes/item-instances.js +426 -0
  59. package/dist/routes/items.js +252 -0
  60. package/dist/routes/labor-tickets.js +268 -0
  61. package/dist/routes/operation-dependencies.js +170 -0
  62. package/dist/routes/operation-field-refs.js +263 -0
  63. package/dist/routes/operation-run-comments.js +108 -0
  64. package/dist/routes/operation-run-transitions.js +249 -0
  65. package/dist/routes/operation-runs.js +299 -0
  66. package/dist/routes/operations.js +283 -0
  67. package/dist/routes/order-revision-transitions.js +86 -0
  68. package/dist/routes/order-revisions.js +327 -0
  69. package/dist/routes/order-run-transitions.js +215 -0
  70. package/dist/routes/order-runs.js +335 -0
  71. package/dist/routes/orders.js +262 -0
  72. package/dist/routes/root.js +123 -0
  73. package/dist/routes/schemas.js +31 -0
  74. package/dist/routes/step-field-attachments.js +231 -0
  75. package/dist/routes/step-fields.js +315 -0
  76. package/dist/routes/step-run-fields.js +438 -0
  77. package/dist/routes/step-run-transitions.js +113 -0
  78. package/dist/routes/step-runs.js +324 -0
  79. package/dist/routes/steps.js +283 -0
  80. package/dist/routes/user-permissions.js +100 -0
  81. package/dist/routes/users.js +381 -0
  82. package/dist/routes/work-centers.js +280 -0
  83. package/dist/schema-registry.js +45 -0
  84. package/dist/services/attachment-service.js +118 -0
  85. package/dist/services/field-ref-service.js +74 -0
  86. package/dist/services/field-service.js +114 -0
  87. package/dist/services/field-value-service.js +256 -0
  88. package/dist/services/item-instance-service.js +155 -0
  89. package/dist/services/item-service.js +56 -0
  90. package/dist/services/labor-ticket-service.js +148 -0
  91. package/dist/services/log-file-service.js +11 -0
  92. package/dist/services/operation-dependency-service.js +30 -0
  93. package/dist/services/operation-run-comment-service.js +26 -0
  94. package/dist/services/operation-run-service.js +347 -0
  95. package/dist/services/operation-service.js +132 -0
  96. package/dist/services/order-revision-service.js +264 -0
  97. package/dist/services/order-run-service.js +356 -0
  98. package/dist/services/order-service.js +68 -0
  99. package/dist/services/revision-diff-service.js +194 -0
  100. package/dist/services/step-run-service.js +106 -0
  101. package/dist/services/step-service.js +89 -0
  102. package/dist/services/user-service.js +132 -0
  103. package/dist/services/work-center-service.js +106 -0
  104. package/dist/supervisorAuth.js +16 -0
  105. package/dist/userService.js +118 -0
  106. package/package.json +75 -0
  107. package/prisma/migrations/20260212170352_init/migration.sql +125 -0
  108. package/prisma/migrations/20260308000000_multi_session/migration.sql +23 -0
  109. package/prisma/migrations/20260309000000_add_user_api_key/migration.sql +5 -0
  110. package/prisma/migrations/20260309010000_add_plan_operations/migration.sql +21 -0
  111. package/prisma/migrations/20260309020000_rename_exec_orders_to_order_runs/migration.sql +13 -0
  112. package/prisma/migrations/20260310000000_rename_plan_order_revs_to_order_revisions/migration.sql +22 -0
  113. package/prisma/migrations/20260310100000_rename_plan_orders_to_orders/migration.sql +23 -0
  114. package/prisma/migrations/20260310200000_rename_order_no_to_run_no/migration.sql +3 -0
  115. package/prisma/migrations/20260312000000_add_user_permissions/migration.sql +16 -0
  116. package/prisma/migrations/20260313000000_rename_plan_operations_to_operations/migration.sql +2 -0
  117. package/prisma/migrations/20260313100000_add_steps/migration.sql +20 -0
  118. package/prisma/migrations/20260314000000_add_step_fields/migration.sql +22 -0
  119. package/prisma/migrations/20260315000000_add_operation_runs/migration.sql +24 -0
  120. package/prisma/migrations/20260315100000_add_step_runs/migration.sql +40 -0
  121. package/prisma/migrations/20260316000000_drop_order_name/migration.sql +12 -0
  122. package/prisma/migrations/20260317000000_add_attachments/migration.sql +28 -0
  123. package/prisma/migrations/20260317000000_add_items/migration.sql +21 -0
  124. package/prisma/migrations/20260317100000_add_order_item_id/migration.sql +8 -0
  125. package/prisma/migrations/20260318000000_add_labor_tickets/migration.sql +27 -0
  126. package/prisma/migrations/20260319000000_add_operation_dependencies/migration.sql +17 -0
  127. package/prisma/migrations/20260320000000_step_field_is_array/migration.sql +5 -0
  128. package/prisma/migrations/20260320100000_rename_is_array_to_multi_value/migration.sql +2 -0
  129. package/prisma/migrations/20260320200000_add_field_types/migration.sql +2 -0
  130. package/prisma/migrations/20260321000000_add_multi_set/migration.sql +13 -0
  131. package/prisma/migrations/20260322000000_add_field_sets/migration.sql +90 -0
  132. package/prisma/migrations/20260323000000_add_item_instances/migration.sql +18 -0
  133. package/prisma/migrations/20260324000000_add_field_records/migration.sql +77 -0
  134. package/prisma/migrations/20260325000000_add_run_costs/migration.sql +3 -0
  135. package/prisma/migrations/20260326000000_add_comments/migration.sql +16 -0
  136. package/prisma/migrations/20260327000000_move_assigned_to_op_run/migration.sql +3 -0
  137. package/prisma/migrations/20260328000000_add_step_completion_note/migration.sql +2 -0
  138. package/prisma/migrations/20260328000000_add_step_title/migration.sql +2 -0
  139. package/prisma/migrations/20260329000000_rename_notes_to_release_note/migration.sql +2 -0
  140. package/prisma/migrations/20260329000000_simplify_order_run_dates/migration.sql +5 -0
  141. package/prisma/migrations/20260330000000_add_operation_run_completion_note/migration.sql +2 -0
  142. package/prisma/migrations/20260331000000_add_work_centers/migration.sql +30 -0
  143. package/prisma/migrations/20260401000000_fix_field_values_column_shift/migration.sql +26 -0
  144. package/prisma/migrations/20260402000000_rename_completion_note_to_status_note/migration.sql +5 -0
  145. package/prisma/migrations/20260403000000_add_operation_field_refs/migration.sql +16 -0
  146. package/prisma/migrations/20260404000000_rename_multi_value_to_is_array/migration.sql +2 -0
  147. package/prisma/migrations/20260404100000_add_attachment_public_id/migration.sql +8 -0
  148. package/prisma/migrations/migration_lock.toml +3 -0
  149. package/prisma/schema.prisma +595 -0
  150. package/prisma.config.ts +18 -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,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,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
@@ -0,0 +1,11 @@
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 exports various common sort, input & filter types that are not directly linked to a particular model.
7
+ *
8
+ * 🟢 You can import this file directly.
9
+ */
10
+ export {};
11
+ //# sourceMappingURL=commonInputTypes.js.map
@@ -0,0 +1,60 @@
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 exports all enum related types from the schema.
7
+ *
8
+ * 🟢 You can import this file directly.
9
+ */
10
+ export const OrderStatus = {
11
+ active: 'active',
12
+ archived: 'archived'
13
+ };
14
+ export const RevisionStatus = {
15
+ draft: 'draft',
16
+ approved: 'approved',
17
+ obsolete: 'obsolete'
18
+ };
19
+ export const OrderRunStatus = {
20
+ released: 'released',
21
+ started: 'started',
22
+ closed: 'closed',
23
+ cancelled: 'cancelled'
24
+ };
25
+ export const OrderRunPriority = {
26
+ low: 'low',
27
+ medium: 'medium',
28
+ high: 'high',
29
+ critical: 'critical'
30
+ };
31
+ export const OperationRunStatus = {
32
+ blocked: 'blocked',
33
+ pending: 'pending',
34
+ in_progress: 'in_progress',
35
+ completed: 'completed',
36
+ skipped: 'skipped',
37
+ failed: 'failed'
38
+ };
39
+ export const OperationRunCommentType = {
40
+ note: 'note',
41
+ issue: 'issue',
42
+ feedback: 'feedback'
43
+ };
44
+ export const FieldType = {
45
+ string: 'string',
46
+ number: 'number',
47
+ date: 'date',
48
+ datetime: 'datetime',
49
+ yesNo: 'yesNo',
50
+ checkbox: 'checkbox',
51
+ attachment: 'attachment'
52
+ };
53
+ export const ErpPermission = {
54
+ erp_admin: 'erp_admin',
55
+ order_planner: 'order_planner',
56
+ order_executor: 'order_executor',
57
+ order_manager: 'order_manager',
58
+ item_manager: 'item_manager'
59
+ };
60
+ //# sourceMappingURL=enums.js.map