express-file-cluster 0.3.4 → 0.3.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.
package/dist/index.d.cts CHANGED
@@ -1,13 +1,33 @@
1
1
  import http from 'node:http';
2
- import { M as ModelSchema, b as ModelCRUD, R as RouteEntry, E as EFCConfig } from './types-CFU2IhRW.cjs';
3
- export { A as AuthStrategy, C as CorsConfig, D as DatabaseEngine, c as RouteMeta, d as RouteMethodMeta, T as TaskDefinition, a as TaskOptions } from './types-CFU2IhRW.cjs';
2
+ import { M as ModelSchema, b as ModelCRUD, R as RouteEntry, E as EFCConfig } from './types-Df0jLGwr.cjs';
3
+ export { A as AuthStrategy, C as CorsConfig, D as DatabaseEngine, F as FieldDefinition, c as ModelQueryOptions, d as RouteMeta, e as RouteMethodMeta, T as TaskDefinition, a as TaskOptions } from './types-Df0jLGwr.cjs';
4
4
  import { RequestHandler } from 'express';
5
5
 
6
+ /**
7
+ * Represents an HTTP error with a status code and message.
8
+ * Throw this inside any route handler to send a structured error response.
9
+ *
10
+ * @example
11
+ * throw new HttpError(404, 'User not found');
12
+ */
6
13
  declare class HttpError extends Error {
7
14
  readonly statusCode: number;
8
15
  constructor(statusCode: number, message: string);
16
+ /** Returns a plain object representation suitable for JSON serialization. */
17
+ toJSON(): {
18
+ statusCode: number;
19
+ error: string;
20
+ message: string;
21
+ };
9
22
  }
10
23
 
24
+ /**
25
+ * Chains multiple Express request handlers into a single handler.
26
+ * Each handler calls the next one via its `next` callback.
27
+ *
28
+ * @example
29
+ * export const GET = compose(requireAuth, rateLimiter, myHandler);
30
+ */
11
31
  declare function compose(...handlers: RequestHandler[]): RequestHandler;
12
32
 
13
33
  declare function defineModel<T extends Record<string, any>>(name: string, schema: ModelSchema): ModelCRUD<T>;
package/dist/index.d.ts CHANGED
@@ -1,13 +1,33 @@
1
1
  import http from 'node:http';
2
- import { M as ModelSchema, b as ModelCRUD, R as RouteEntry, E as EFCConfig } from './types-CFU2IhRW.js';
3
- export { A as AuthStrategy, C as CorsConfig, D as DatabaseEngine, c as RouteMeta, d as RouteMethodMeta, T as TaskDefinition, a as TaskOptions } from './types-CFU2IhRW.js';
2
+ import { M as ModelSchema, b as ModelCRUD, R as RouteEntry, E as EFCConfig } from './types-Df0jLGwr.js';
3
+ export { A as AuthStrategy, C as CorsConfig, D as DatabaseEngine, F as FieldDefinition, c as ModelQueryOptions, d as RouteMeta, e as RouteMethodMeta, T as TaskDefinition, a as TaskOptions } from './types-Df0jLGwr.js';
4
4
  import { RequestHandler } from 'express';
5
5
 
6
+ /**
7
+ * Represents an HTTP error with a status code and message.
8
+ * Throw this inside any route handler to send a structured error response.
9
+ *
10
+ * @example
11
+ * throw new HttpError(404, 'User not found');
12
+ */
6
13
  declare class HttpError extends Error {
7
14
  readonly statusCode: number;
8
15
  constructor(statusCode: number, message: string);
16
+ /** Returns a plain object representation suitable for JSON serialization. */
17
+ toJSON(): {
18
+ statusCode: number;
19
+ error: string;
20
+ message: string;
21
+ };
9
22
  }
10
23
 
24
+ /**
25
+ * Chains multiple Express request handlers into a single handler.
26
+ * Each handler calls the next one via its `next` callback.
27
+ *
28
+ * @example
29
+ * export const GET = compose(requireAuth, rateLimiter, myHandler);
30
+ */
11
31
  declare function compose(...handlers: RequestHandler[]): RequestHandler;
12
32
 
13
33
  declare function defineModel<T extends Record<string, any>>(name: string, schema: ModelSchema): ModelCRUD<T>;
package/dist/index.js CHANGED
@@ -118,7 +118,61 @@ function normalise(doc) {
118
118
  const id = doc["_id"] ? String(doc["_id"]) : "";
119
119
  return { ...doc, id };
120
120
  }
121
- async function getModel(name, schemaObj) {
121
+ function isNestedArraySchema(def) {
122
+ return Array.isArray(def);
123
+ }
124
+ function primitiveCtor(type, mg) {
125
+ switch (type) {
126
+ case "string":
127
+ return String;
128
+ case "number":
129
+ return Number;
130
+ case "boolean":
131
+ return Boolean;
132
+ case "date":
133
+ return Date;
134
+ case "object":
135
+ return Object;
136
+ case "objectId":
137
+ return mg.Schema.Types.ObjectId;
138
+ case "array":
139
+ return Array;
140
+ }
141
+ }
142
+ function buildFieldEntry(def, mg) {
143
+ const entry = {};
144
+ if (def.type === "array") {
145
+ if (def.of === "objectId") {
146
+ const item = { type: mg.Schema.Types.ObjectId };
147
+ if (def.ref !== void 0) item["ref"] = def.ref;
148
+ entry["type"] = [item];
149
+ } else if (def.of) {
150
+ entry["type"] = [primitiveCtor(def.of, mg)];
151
+ } else {
152
+ entry["type"] = Array;
153
+ }
154
+ } else {
155
+ entry["type"] = primitiveCtor(def.type, mg);
156
+ if (def.type === "objectId" && def.ref !== void 0) entry["ref"] = def.ref;
157
+ }
158
+ if (def.required !== void 0) entry["required"] = def.required;
159
+ if (def.unique !== void 0) entry["unique"] = def.unique;
160
+ if (def.default !== void 0) entry["default"] = def.default;
161
+ if (def.enum !== void 0) entry["enum"] = def.enum;
162
+ return entry;
163
+ }
164
+ function buildMongooseSchema(schema, mg) {
165
+ const out = {};
166
+ for (const [key, def] of Object.entries(schema)) {
167
+ if (isNestedArraySchema(def)) {
168
+ out[key] = def[0] ? [buildMongooseSchema(def[0], mg)] : [];
169
+ } else {
170
+ out[key] = buildFieldEntry(def, mg);
171
+ }
172
+ }
173
+ return out;
174
+ }
175
+ async function getModel(name, schema) {
122
176
  let mg;
123
177
  try {
124
178
  const mod = await import("mongoose");
@@ -127,77 +181,52 @@ async function getModel(name, schemaObj) {
127
181
  throw new Error("[EFC] mongoose is not installed. Run: npm install mongoose");
128
182
  }
129
183
  if (mg.models[name]) return mg.models[name];
130
- const schema = new mg.Schema(schemaObj, { timestamps: true });
131
- return mg.model(name, schema);
132
- }
133
- function buildMongooseSchema(schema) {
134
- const out = {};
135
- for (const [key, def] of Object.entries(schema)) {
136
- const entry = {};
137
- switch (def.type) {
138
- case "string":
139
- entry["type"] = String;
140
- break;
141
- case "number":
142
- entry["type"] = Number;
143
- break;
144
- case "boolean":
145
- entry["type"] = Boolean;
146
- break;
147
- case "date":
148
- entry["type"] = Date;
149
- break;
150
- case "object":
151
- entry["type"] = Object;
152
- break;
153
- case "array":
154
- entry["type"] = Array;
155
- break;
156
- }
157
- if (def.required !== void 0) entry["required"] = def.required;
158
- if (def.unique !== void 0) entry["unique"] = def.unique;
159
- if (def.default !== void 0) entry["default"] = def.default;
160
- out[key] = entry;
161
- }
162
- return out;
184
+ const schemaObj = buildMongooseSchema(schema, mg);
185
+ const mongooseSchema = new mg.Schema(schemaObj, { timestamps: true });
186
+ return mg.model(name, mongooseSchema);
163
187
  }
164
188
  function defineModel(name, schema) {
165
- const mongooseSchema = buildMongooseSchema(schema);
166
189
  return {
167
- async find(filter = {}) {
168
- const M = await getModel(name, mongooseSchema);
169
- const docs = await M.find(filter).lean();
190
+ async find(filter = {}, options) {
191
+ const M = await getModel(name, schema);
192
+ const query = M.find(filter);
193
+ if (options?.populate) query.populate(options.populate);
194
+ const docs = await query.lean();
170
195
  return docs.map(normalise);
171
196
  },
172
- async findById(id) {
173
- const M = await getModel(name, mongooseSchema);
174
- const doc = await M.findById(id).lean();
197
+ async findById(id, options) {
198
+ const M = await getModel(name, schema);
199
+ const query = M.findById(id);
200
+ if (options?.populate) query.populate(options.populate);
201
+ const doc = await query.lean();
175
202
  if (!doc) return null;
176
203
  return normalise(doc);
177
204
  },
178
- async findOne(filter) {
179
- const M = await getModel(name, mongooseSchema);
180
- const doc = await M.findOne(filter).lean();
205
+ async findOne(filter, options) {
206
+ const M = await getModel(name, schema);
207
+ const query = M.findOne(filter);
208
+ if (options?.populate) query.populate(options.populate);
209
+ const doc = await query.lean();
181
210
  if (!doc) return null;
182
211
  return normalise(doc);
183
212
  },
184
213
  async create(data) {
185
- const M = await getModel(name, mongooseSchema);
214
+ const M = await getModel(name, schema);
186
215
  const doc = await M.create(data);
187
216
  return normalise(doc.toObject());
188
217
  },
189
218
  async update(id, data) {
190
- const M = await getModel(name, mongooseSchema);
219
+ const M = await getModel(name, schema);
191
220
  const doc = await M.findByIdAndUpdate(id, data, { new: true }).lean();
192
221
  if (!doc) return null;
193
222
  return normalise(doc);
194
223
  },
195
224
  async delete(id) {
196
- const M = await getModel(name, mongooseSchema);
225
+ const M = await getModel(name, schema);
197
226
  await M.findByIdAndDelete(id);
198
227
  },
199
228
  async count(filter = {}) {
200
- const M = await getModel(name, mongooseSchema);
229
+ const M = await getModel(name, schema);
201
230
  return M.countDocuments(filter);
202
231
  }
203
232
  };
@@ -951,12 +980,19 @@ var HttpError = class _HttpError extends Error {
951
980
  this.statusCode = statusCode;
952
981
  Error.captureStackTrace(this, _HttpError);
953
982
  }
983
+ /** Returns a plain object representation suitable for JSON serialization. */
984
+ toJSON() {
985
+ return {
986
+ statusCode: this.statusCode,
987
+ error: this.name,
988
+ message: this.message
989
+ };
990
+ }
954
991
  };
955
992
 
956
993
  // src/compose.ts
957
994
  function compose(...handlers) {
958
995
  return (req, res, next) => {
959
- const index = 0;
960
996
  function dispatch(i) {
961
997
  if (i >= handlers.length) {
962
998
  next();
@@ -973,7 +1009,7 @@ function compose(...handlers) {
973
1009
  next(err);
974
1010
  }
975
1011
  }
976
- dispatch(index);
1012
+ dispatch(0);
977
1013
  };
978
1014
  }
979
1015
 
@@ -1014,11 +1050,10 @@ async function ignite(config) {
1014
1050
  return { name: "API", version: "" };
1015
1051
  }
1016
1052
  }
1017
- const envPort = process.env["PORT"] != null ? Number(process.env["PORT"]) : NaN;
1018
- const port = _port != null && !Number.isNaN(_port) ? _port : !Number.isNaN(envPort) ? envPort : 3e3;
1019
- const databaseUrl = config.databaseUrl ?? process.env["DATABASE_URL"];
1053
+ const port = _port != null && !Number.isNaN(_port) ? _port : 3e3;
1054
+ const databaseUrl = config.databaseUrl;
1020
1055
  const database = config.database ?? detectDatabase(databaseUrl);
1021
- const jwtSecret = config.jwtSecret ?? process.env["JWT_SECRET"];
1056
+ const jwtSecret = config.jwtSecret;
1022
1057
  const authStrategy = config.authStrategy ?? "http-only";
1023
1058
  const clusterEnabled = config.cluster ?? process.env["NODE_ENV"] === "production";
1024
1059
  if (clusterEnabled && cluster2.isPrimary) {
@@ -1032,16 +1067,7 @@ async function ignite(config) {
1032
1067
  const app = express();
1033
1068
  const corsOption = config.cors ?? true;
1034
1069
  if (corsOption !== false) {
1035
- const envOrigins = process.env["CORS_ORIGINS"];
1036
- let origin;
1037
- if (envOrigins) {
1038
- const list = envOrigins.split(",").map((o) => o.trim()).filter(Boolean);
1039
- origin = list;
1040
- } else if (typeof corsOption === "object" && corsOption.origin !== void 0) {
1041
- origin = corsOption.origin;
1042
- } else {
1043
- origin = true;
1044
- }
1070
+ const origin = typeof corsOption === "object" && corsOption.origin !== void 0 ? corsOption.origin : true;
1045
1071
  const corsOpts = typeof corsOption === "object" ? { ...corsOption, origin } : { origin };
1046
1072
  app.use(cors(corsOpts));
1047
1073
  }
@@ -1056,12 +1082,11 @@ async function ignite(config) {
1056
1082
  setDbClient(conn);
1057
1083
  }
1058
1084
  if (jwtSecret) {
1059
- const cookieDomain = process.env["COOKIE_DOMAIN"];
1060
1085
  configureAuth({
1061
1086
  secret: jwtSecret,
1062
1087
  strategy: authStrategy,
1063
- expiresIn: process.env["JWT_EXPIRES_IN"] ?? "7d",
1064
- ...cookieDomain !== void 0 && { cookieDomain }
1088
+ expiresIn: config.jwtExpiresIn ?? "7d",
1089
+ ...config.cookieDomain !== void 0 && { cookieDomain: config.cookieDomain }
1065
1090
  });
1066
1091
  }
1067
1092
  if (tasksDir) {