@webbycrown/webbycommerce 1.1.2 → 1.2.1

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.
@@ -157,6 +157,38 @@ var require_routes = __commonJS({
157
157
  auth: false
158
158
  }
159
159
  },
160
+ {
161
+ method: "GET",
162
+ path: "/auth/method",
163
+ handler: "auth.getAuthMethod",
164
+ config: {
165
+ auth: false,
166
+ policies: []
167
+ },
168
+ info: {
169
+ type: "content-api",
170
+ pluginName: PLUGIN_ID,
171
+ description: "Get current authentication method (default or otp)",
172
+ summary: "Get auth method",
173
+ tags: ["Authentication"]
174
+ }
175
+ },
176
+ {
177
+ method: "POST",
178
+ path: "/auth/unified",
179
+ handler: "auth.unifiedAuth",
180
+ config: {
181
+ auth: false,
182
+ policies: []
183
+ },
184
+ info: {
185
+ type: "content-api",
186
+ pluginName: PLUGIN_ID,
187
+ description: "Unified authentication endpoint supporting both OTP and default (email/password) methods",
188
+ summary: "Unified auth",
189
+ tags: ["Authentication"]
190
+ }
191
+ },
160
192
  {
161
193
  method: "GET",
162
194
  path: "/auth/profile",
@@ -1242,7 +1274,8 @@ var require_register = __commonJS({
1242
1274
  uid: shippingZoneUid,
1243
1275
  modelType: "component",
1244
1276
  modelName: "shipping-zone-location",
1245
- globalId: "ComponentPluginWebbycommerceShippingZoneLocation"
1277
+ globalId: "ComponentPluginWebbycommerceShippingZoneLocation",
1278
+ category: shippingZoneSchema.category || "WebbyCommerce Shared"
1246
1279
  });
1247
1280
  strapi2.log.info(`[webbycommerce] Component registered: ${shippingZoneUid}`);
1248
1281
  } else {
@@ -1257,7 +1290,8 @@ var require_register = __commonJS({
1257
1290
  uid: contentBlockUid,
1258
1291
  modelType: "component",
1259
1292
  modelName: "content-block",
1260
- globalId: "ComponentPluginWebbycommerceContentBlock"
1293
+ globalId: "ComponentPluginWebbycommerceContentBlock",
1294
+ category: contentBlockSchema.category || "WebbyCommerce Shared"
1261
1295
  });
1262
1296
  strapi2.log.info(`[webbycommerce] Component registered: ${contentBlockUid}`);
1263
1297
  } else {
@@ -3157,6 +3191,8 @@ var require_content_types = __commonJS({
3157
3191
  var require_bootstrap = __commonJS({
3158
3192
  "server/src/bootstrap.js"(exports2, module2) {
3159
3193
  "use strict";
3194
+ var fs = require("fs");
3195
+ var path = require("path");
3160
3196
  var { registerEcommerceActions, ensureEcommercePermission } = require_check_ecommerce_permission();
3161
3197
  var { extendUserSchemaWithOtpFields } = require_extend_user_schema();
3162
3198
  module2.exports = async ({ strapi: strapi2 }) => {
@@ -3212,8 +3248,8 @@ var require_bootstrap = __commonJS({
3212
3248
  return "webbycommerce";
3213
3249
  }
3214
3250
  };
3215
- const isAdminRoute = (path) => {
3216
- if (!path) return false;
3251
+ const isAdminRoute = (path2) => {
3252
+ if (!path2) return false;
3217
3253
  const adminRoutePatterns = [
3218
3254
  "/admin/",
3219
3255
  "/content-type-builder/",
@@ -3224,8 +3260,343 @@ var require_bootstrap = __commonJS({
3224
3260
  "/documentation/",
3225
3261
  "/graphql"
3226
3262
  ];
3227
- return adminRoutePatterns.some((pattern) => path.startsWith(pattern));
3263
+ return adminRoutePatterns.some((pattern) => path2.startsWith(pattern));
3228
3264
  };
3265
+ strapi2.server.use(async (ctx, next) => {
3266
+ if (ctx.path === "/content-type-builder/update-schema" && ctx.method === "POST") {
3267
+ try {
3268
+ let body = ctx.request.body;
3269
+ let bodyWasParsed = false;
3270
+ if (!body || typeof body === "object" && Object.keys(body).length === 0) {
3271
+ try {
3272
+ const contentType = ctx.request.header["content-type"] || "";
3273
+ if (contentType.includes("application/json") && ctx.req && typeof ctx.req[Symbol.asyncIterator] === "function") {
3274
+ const chunks = [];
3275
+ for await (const chunk of ctx.req) {
3276
+ chunks.push(chunk);
3277
+ }
3278
+ const rawBody = Buffer.concat(chunks).toString("utf8");
3279
+ if (rawBody && rawBody.trim()) {
3280
+ body = JSON.parse(rawBody);
3281
+ ctx.request.body = body;
3282
+ bodyWasParsed = true;
3283
+ const { Readable } = require("stream");
3284
+ ctx.req = Readable.from([Buffer.from(rawBody)]);
3285
+ strapi2.log.info("[webbycommerce] EARLY: Manually parsed request body");
3286
+ }
3287
+ }
3288
+ } catch (parseError) {
3289
+ strapi2.log.warn("[webbycommerce] EARLY: Could not parse body:", parseError.message);
3290
+ }
3291
+ }
3292
+ body = body || {};
3293
+ const data = body.data || body;
3294
+ const contentTypes3 = data.contentTypes || [];
3295
+ const components = data.components || [];
3296
+ strapi2.log.info("[webbycommerce] ===== EARLY: Processing content-type-builder update-schema request =====");
3297
+ strapi2.log.info("[webbycommerce] EARLY: Body type:", typeof body);
3298
+ strapi2.log.info("[webbycommerce] EARLY: Body keys:", Object.keys(body));
3299
+ strapi2.log.info("[webbycommerce] EARLY: Content types found:", contentTypes3.length);
3300
+ strapi2.log.info("[webbycommerce] EARLY: Components found:", components.length);
3301
+ let appDir;
3302
+ if (strapi2.dirs && strapi2.dirs.app && strapi2.dirs.app.root) {
3303
+ appDir = strapi2.dirs.app.root;
3304
+ } else if (strapi2.dirs && strapi2.dirs.root) {
3305
+ appDir = strapi2.dirs.root;
3306
+ } else {
3307
+ appDir = path.resolve(__dirname, "../..");
3308
+ }
3309
+ if (!strapi2.dirs) {
3310
+ strapi2.dirs = {};
3311
+ }
3312
+ if (!strapi2.dirs.app) {
3313
+ strapi2.dirs.app = {};
3314
+ }
3315
+ if (!strapi2.dirs.app.root) {
3316
+ strapi2.dirs.app.root = appDir;
3317
+ }
3318
+ for (const contentType of contentTypes3) {
3319
+ if (contentType.uid && contentType.uid.startsWith("api::")) {
3320
+ const uidParts = contentType.uid.split("::");
3321
+ if (uidParts.length === 2) {
3322
+ const apiAndType = uidParts[1].split(".");
3323
+ if (apiAndType.length >= 2) {
3324
+ const apiName = apiAndType[0];
3325
+ const contentTypeName = apiAndType[1];
3326
+ const apiDir = path.join(appDir, "src", "api", apiName);
3327
+ const contentTypeDir = path.join(apiDir, "content-types", contentTypeName);
3328
+ const schemaPath = path.join(contentTypeDir, "schema.json");
3329
+ if (contentType.action === "delete") {
3330
+ strapi2.log.info(`[webbycommerce] EARLY: Deleting collection: ${contentType.uid}`);
3331
+ if (fs.existsSync(schemaPath)) {
3332
+ fs.unlinkSync(schemaPath);
3333
+ strapi2.log.info(`[webbycommerce] EARLY: \u2713 Deleted schema file: ${schemaPath}`);
3334
+ }
3335
+ if (fs.existsSync(contentTypeDir)) {
3336
+ try {
3337
+ fs.rmSync(contentTypeDir, { recursive: true, force: true });
3338
+ strapi2.log.info(`[webbycommerce] EARLY: \u2713 Deleted content type directory: ${contentTypeDir}`);
3339
+ } catch (error) {
3340
+ strapi2.log.warn(`[webbycommerce] EARLY: Could not delete directory: ${error.message}`);
3341
+ }
3342
+ }
3343
+ ctx.state.schemaFileCreated = true;
3344
+ ctx.state.schemaDeleted = true;
3345
+ continue;
3346
+ }
3347
+ fs.mkdirSync(contentTypeDir, { recursive: true });
3348
+ let existingSchema = {};
3349
+ if (fs.existsSync(schemaPath)) {
3350
+ try {
3351
+ existingSchema = JSON.parse(fs.readFileSync(schemaPath, "utf8"));
3352
+ } catch (e) {
3353
+ existingSchema = {};
3354
+ }
3355
+ }
3356
+ const attributes = { ...existingSchema.attributes || {} };
3357
+ if (contentType.attributes && Array.isArray(contentType.attributes)) {
3358
+ for (const attr of contentType.attributes) {
3359
+ const action = attr.action || "update";
3360
+ if (action === "delete" && attr.name) {
3361
+ if (attributes[attr.name]) {
3362
+ delete attributes[attr.name];
3363
+ strapi2.log.info(`[webbycommerce] EARLY: \u2713 Deleted attribute: ${attr.name}`);
3364
+ } else {
3365
+ strapi2.log.warn(`[webbycommerce] EARLY: Attribute not found for deletion: ${attr.name}`);
3366
+ }
3367
+ continue;
3368
+ }
3369
+ if (attr.name && attr.properties) {
3370
+ const attributeDef = { ...attr.properties };
3371
+ if (attributeDef.type === "component") {
3372
+ if (attributeDef.component) {
3373
+ strapi2.log.info(`[webbycommerce] EARLY: Processing component attribute: ${attr.name} -> ${attributeDef.component}`);
3374
+ }
3375
+ if (!attributeDef.repeatable) {
3376
+ attributeDef.repeatable = false;
3377
+ }
3378
+ }
3379
+ if (attributeDef.type === "dynamiczone") {
3380
+ if (Array.isArray(attributeDef.components)) {
3381
+ strapi2.log.info(`[webbycommerce] EARLY: Processing dynamiczone: ${attr.name} with ${attributeDef.components.length} components`);
3382
+ }
3383
+ }
3384
+ if (attributeDef.type === "relation") {
3385
+ if (attributeDef.target) {
3386
+ strapi2.log.info(`[webbycommerce] EARLY: Processing relation: ${attr.name} -> ${attributeDef.target}`);
3387
+ }
3388
+ }
3389
+ attributes[attr.name] = attributeDef;
3390
+ strapi2.log.info(`[webbycommerce] EARLY: ${action === "create" ? "Added" : "Updated"} attribute: ${attr.name} (type: ${attributeDef.type || "unknown"})`);
3391
+ }
3392
+ }
3393
+ }
3394
+ const schema = {
3395
+ kind: contentType.kind || existingSchema.kind || "collectionType",
3396
+ collectionName: contentType.collectionName || existingSchema.collectionName || (contentType.kind === "singleType" ? contentTypeName : `${contentTypeName}s`),
3397
+ info: {
3398
+ singularName: contentType.singularName || existingSchema.info?.singularName || contentTypeName,
3399
+ pluralName: contentType.pluralName || existingSchema.info?.pluralName || (contentType.kind === "singleType" ? contentTypeName : `${contentTypeName}s`),
3400
+ displayName: contentType.displayName || contentType.modelName || existingSchema.info?.displayName || contentTypeName,
3401
+ description: contentType.description || existingSchema.info?.description || ""
3402
+ },
3403
+ options: {
3404
+ draftAndPublish: contentType.draftAndPublish !== void 0 ? contentType.draftAndPublish : existingSchema.options?.draftAndPublish !== void 0 ? existingSchema.options.draftAndPublish : false
3405
+ },
3406
+ pluginOptions: contentType.pluginOptions || existingSchema.pluginOptions || {
3407
+ "content-manager": {
3408
+ visible: true
3409
+ },
3410
+ "content-api": {
3411
+ visible: true
3412
+ }
3413
+ },
3414
+ attributes
3415
+ };
3416
+ const schemaJson = JSON.stringify(schema, null, 2);
3417
+ fs.writeFileSync(schemaPath, schemaJson, "utf8");
3418
+ if (fs.existsSync(schemaPath)) {
3419
+ try {
3420
+ const verifySchema = JSON.parse(fs.readFileSync(schemaPath, "utf8"));
3421
+ const fileStats = fs.statSync(schemaPath);
3422
+ strapi2.log.info(`[webbycommerce] ========================================`);
3423
+ strapi2.log.info(`[webbycommerce] \u2713 COLLECTION SCHEMA CREATED/UPDATED`);
3424
+ strapi2.log.info(`[webbycommerce] ========================================`);
3425
+ strapi2.log.info(`[webbycommerce] \u2713 File: ${schemaPath}`);
3426
+ strapi2.log.info(`[webbycommerce] \u2713 File size: ${fileStats.size} bytes`);
3427
+ strapi2.log.info(`[webbycommerce] \u2713 Schema is valid JSON`);
3428
+ strapi2.log.info(`[webbycommerce] \u2713 Schema kind: ${verifySchema.kind}`);
3429
+ strapi2.log.info(`[webbycommerce] \u2713 Collection name: ${verifySchema.collectionName}`);
3430
+ strapi2.log.info(`[webbycommerce] \u2713 Display name: ${verifySchema.info?.displayName || "N/A"}`);
3431
+ strapi2.log.info(`[webbycommerce] \u2713 Total attributes: ${Object.keys(verifySchema.attributes || {}).length}`);
3432
+ const attrNames = Object.keys(verifySchema.attributes || {});
3433
+ if (attrNames.length > 0) {
3434
+ strapi2.log.info(`[webbycommerce] \u2713 Attributes list:`);
3435
+ attrNames.forEach((attrName) => {
3436
+ const attr = verifySchema.attributes[attrName];
3437
+ const attrType = attr.type || "unknown";
3438
+ const attrInfo = attrType === "component" ? `component: ${attr.component}` : attrType === "dynamiczone" ? `dynamiczone: ${(attr.components || []).join(", ")}` : attrType === "relation" ? `relation: ${attr.target}` : attrType;
3439
+ strapi2.log.info(`[webbycommerce] - ${attrName}: ${attrInfo}`);
3440
+ });
3441
+ } else {
3442
+ strapi2.log.warn(`[webbycommerce] \u26A0 No attributes found - this is a new empty collection`);
3443
+ }
3444
+ strapi2.log.info(`[webbycommerce] \u2713 File will trigger auto-restart`);
3445
+ strapi2.log.info(`[webbycommerce] \u2713 After restart, collection will be registered with all fields/components`);
3446
+ strapi2.log.info(`[webbycommerce] ========================================`);
3447
+ fs.chmodSync(schemaPath, 420);
3448
+ const now = /* @__PURE__ */ new Date();
3449
+ fs.utimesSync(schemaPath, now, now);
3450
+ ctx.state.schemaFileCreated = true;
3451
+ ctx.state.schemaPath = schemaPath;
3452
+ ctx.state.contentTypeUid = contentType.uid;
3453
+ } catch (verifyError) {
3454
+ strapi2.log.error(`[webbycommerce] \u2717 Schema file verification failed: ${verifyError.message}`);
3455
+ strapi2.log.error(`[webbycommerce] \u2717 Stack: ${verifyError.stack}`);
3456
+ }
3457
+ } else {
3458
+ strapi2.log.error(`[webbycommerce] \u2717 Schema file was not created: ${schemaPath}`);
3459
+ }
3460
+ const controllersDir = path.join(apiDir, "controllers", contentTypeName);
3461
+ const servicesDir = path.join(apiDir, "services", contentTypeName);
3462
+ const routesDir = path.join(apiDir, "routes", contentTypeName);
3463
+ [controllersDir, servicesDir, routesDir].forEach((dir) => {
3464
+ if (!fs.existsSync(dir)) {
3465
+ fs.mkdirSync(dir, { recursive: true });
3466
+ strapi2.log.info(`[webbycommerce] EARLY: \u2713 Created directory: ${dir}`);
3467
+ }
3468
+ });
3469
+ }
3470
+ }
3471
+ }
3472
+ }
3473
+ const hasContentTypes = (ctx.state.schemaFileCreated || ctx.state.schemaDeleted) && contentTypes3.length > 0;
3474
+ const hasComponents = ctx.state.componentsCreated === true || ctx.state.componentsDeleted === true;
3475
+ strapi2.log.info(`[webbycommerce] EARLY: Checking early return conditions...`);
3476
+ strapi2.log.info(`[webbycommerce] EARLY: hasContentTypes=${hasContentTypes}, hasComponents=${hasComponents}`);
3477
+ strapi2.log.info(`[webbycommerce] EARLY: ctx.state.schemaFileCreated=${ctx.state.schemaFileCreated}, ctx.state.componentsCreated=${ctx.state.componentsCreated}`);
3478
+ strapi2.log.info(`[webbycommerce] EARLY: contentTypes.length=${contentTypes3.length}, components.length=${components.length}`);
3479
+ if (hasContentTypes || hasComponents) {
3480
+ strapi2.log.info(`[webbycommerce] EARLY: \u2713 Schema file(s) created successfully`);
3481
+ if (hasContentTypes) {
3482
+ strapi2.log.info(`[webbycommerce] EARLY: \u2713 Created ${contentTypes3.length} content type(s)`);
3483
+ }
3484
+ if (hasComponents) {
3485
+ strapi2.log.info(`[webbycommerce] EARLY: \u2713 Created ${components.length} component(s)`);
3486
+ }
3487
+ strapi2.log.info(`[webbycommerce] EARLY: \u2713 File watcher will detect change and trigger auto-restart`);
3488
+ strapi2.log.info(`[webbycommerce] EARLY: \u2713 After restart, collections and components will be automatically registered with all fields`);
3489
+ ctx.status = 200;
3490
+ ctx.set("Content-Type", "application/json");
3491
+ ctx.body = {
3492
+ data: {
3493
+ contentTypes: contentTypes3.map((ct) => {
3494
+ const uidParts = ct.uid.split("::");
3495
+ const apiAndType = uidParts.length === 2 ? uidParts[1].split(".") : [];
3496
+ return {
3497
+ uid: ct.uid,
3498
+ apiID: ct.uid,
3499
+ schema: {
3500
+ kind: ct.kind || "collectionType",
3501
+ collectionName: ct.collectionName || (ct.kind === "singleType" ? apiAndType[1] : `${apiAndType[1]}s`),
3502
+ info: {
3503
+ singularName: ct.singularName || apiAndType[1],
3504
+ pluralName: ct.pluralName || (ct.kind === "singleType" ? apiAndType[1] : `${apiAndType[1]}s`),
3505
+ displayName: ct.displayName || ct.modelName || apiAndType[1],
3506
+ description: ct.description || ""
3507
+ },
3508
+ options: {
3509
+ draftAndPublish: ct.draftAndPublish !== void 0 ? ct.draftAndPublish : false
3510
+ }
3511
+ }
3512
+ };
3513
+ }),
3514
+ components: (components || []).map((comp) => {
3515
+ const uidParts = comp.uid ? comp.uid.split(".") : [];
3516
+ return {
3517
+ uid: comp.uid,
3518
+ category: uidParts[0] || "",
3519
+ apiID: comp.uid,
3520
+ schema: {
3521
+ collectionName: comp.collectionName || "components_" + comp.uid.replace(/\./g, "_"),
3522
+ info: {
3523
+ displayName: comp.displayName || comp.modelName || uidParts[1] || "New Component",
3524
+ description: comp.description || ""
3525
+ }
3526
+ }
3527
+ };
3528
+ })
3529
+ }
3530
+ };
3531
+ strapi2.log.info(`[webbycommerce] EARLY: \u2713 Success response sent - request handled`);
3532
+ strapi2.log.info(`[webbycommerce] EARLY: \u2713 Returning early to prevent Strapi from processing request again`);
3533
+ return;
3534
+ } else {
3535
+ strapi2.log.warn(`[webbycommerce] EARLY: \u26A0 Not returning early - conditions not met`);
3536
+ strapi2.log.warn(`[webbycommerce] EARLY: \u26A0 schemaFileCreated=${ctx.state.schemaFileCreated}, componentsCreated=${ctx.state.componentsCreated}`);
3537
+ strapi2.log.warn(`[webbycommerce] EARLY: \u26A0 contentTypes.length=${contentTypes3.length}, components.length=${components.length}`);
3538
+ }
3539
+ } catch (error) {
3540
+ strapi2.log.error("[webbycommerce] EARLY: Error in content-type-builder fix:", error.message);
3541
+ strapi2.log.error("[webbycommerce] EARLY: Stack:", error.stack);
3542
+ }
3543
+ }
3544
+ return next();
3545
+ });
3546
+ strapi2.server.use(async (ctx, next) => {
3547
+ if (ctx.path.includes("/content-manager/collection-types/") && (ctx.method === "POST" || ctx.method === "PUT") && ctx.request.body) {
3548
+ try {
3549
+ const match = ctx.path.match(/collection-types\/([^\/\?]+)/);
3550
+ const contentTypeUid = match?.[1];
3551
+ if (contentTypeUid && contentTypeUid.startsWith("api::")) {
3552
+ const contentType = strapi2.contentTypes[contentTypeUid];
3553
+ if (contentType && contentType.attributes) {
3554
+ const body = ctx.request.body;
3555
+ let modified = false;
3556
+ const sanitizeJsonValue = (value, fieldName) => {
3557
+ if (value === "" || value === '""') {
3558
+ return null;
3559
+ }
3560
+ if (typeof value === "string" && value.trim() === "") {
3561
+ return null;
3562
+ }
3563
+ if (typeof value === "string" && (value.startsWith("{") || value.startsWith("["))) {
3564
+ try {
3565
+ return JSON.parse(value);
3566
+ } catch (e) {
3567
+ strapi2.log.warn(`[webbycommerce] Failed to parse JSON string for field "${fieldName}", using null`);
3568
+ return null;
3569
+ }
3570
+ }
3571
+ return value;
3572
+ };
3573
+ for (const [fieldName, fieldValue] of Object.entries(body)) {
3574
+ if (fieldName === "id" || fieldName === "documentId" || fieldName.startsWith("_") || fieldName === "createdAt" || fieldName === "updatedAt" || fieldName === "publishedAt" || fieldName === "createdBy" || fieldName === "updatedBy") {
3575
+ continue;
3576
+ }
3577
+ const attribute = contentType.attributes[fieldName];
3578
+ if (attribute && attribute.type === "json") {
3579
+ const sanitizedValue = sanitizeJsonValue(fieldValue, fieldName);
3580
+ if (sanitizedValue !== fieldValue) {
3581
+ body[fieldName] = sanitizedValue;
3582
+ modified = true;
3583
+ strapi2.log.info(`[webbycommerce] Sanitized JSON field "${fieldName}": "${fieldValue}" -> ${sanitizedValue === null ? "null" : "parsed JSON"}`);
3584
+ }
3585
+ }
3586
+ }
3587
+ if (modified) {
3588
+ strapi2.log.info(`[webbycommerce] \u2713 Sanitized JSON fields in content-manager request for ${contentTypeUid}`);
3589
+ }
3590
+ } else {
3591
+ strapi2.log.debug(`[webbycommerce] Content type ${contentTypeUid} not found or has no attributes`);
3592
+ }
3593
+ }
3594
+ } catch (error) {
3595
+ strapi2.log.warn(`[webbycommerce] Error sanitizing JSON fields:`, error.message);
3596
+ }
3597
+ }
3598
+ return next();
3599
+ });
3229
3600
  strapi2.server.use(async (ctx, next) => {
3230
3601
  if (isAdminRoute(ctx.path)) {
3231
3602
  return next();
@@ -3302,10 +3673,12 @@ var require_bootstrap = __commonJS({
3302
3673
  const method = value.loginRegisterMethod || "default";
3303
3674
  if (method === "otp") {
3304
3675
  ctx.badRequest(
3305
- "Authentication method is set to OTP. Please use the OTP login/register endpoints."
3676
+ "Authentication method is set to OTP. Please use the OTP login/register endpoints or the unified /auth/unified endpoint."
3306
3677
  );
3307
3678
  return;
3308
3679
  }
3680
+ if (method === "both") {
3681
+ }
3309
3682
  if (ctx.path === "/api/auth/local/register") {
3310
3683
  return next();
3311
3684
  }
@@ -3342,6 +3715,18 @@ var require_bootstrap = __commonJS({
3342
3715
  "/webbycommerce/auth/verify-otp",
3343
3716
  `/${routePrefix}/auth/verify-otp`
3344
3717
  ]);
3718
+ const methodPaths = /* @__PURE__ */ new Set([
3719
+ "/api/webbycommerce/auth/method",
3720
+ `/api/${routePrefix}/auth/method`,
3721
+ "/webbycommerce/auth/method",
3722
+ `/${routePrefix}/auth/method`
3723
+ ]);
3724
+ const unifiedAuthPaths = /* @__PURE__ */ new Set([
3725
+ "/api/webbycommerce/auth/unified",
3726
+ `/api/${routePrefix}/auth/unified`,
3727
+ "/webbycommerce/auth/unified",
3728
+ `/${routePrefix}/auth/unified`
3729
+ ]);
3345
3730
  const profilePaths = /* @__PURE__ */ new Set([
3346
3731
  "/api/webbycommerce/auth/profile",
3347
3732
  `/api/${routePrefix}/auth/profile`,
@@ -3374,6 +3759,50 @@ var require_bootstrap = __commonJS({
3374
3759
  return;
3375
3760
  }
3376
3761
  }
3762
+ if (ctx.method === "GET" && methodPaths.has(ctx.path)) {
3763
+ ctx.state.route = {
3764
+ info: {
3765
+ type: "content-api",
3766
+ pluginName: "webbycommerce"
3767
+ }
3768
+ };
3769
+ const authController = strapi2.plugin("webbycommerce").controller("auth");
3770
+ if (authController && typeof authController.getAuthMethod === "function") {
3771
+ await authController.getAuthMethod(ctx);
3772
+ return;
3773
+ }
3774
+ }
3775
+ if (ctx.method === "POST" && unifiedAuthPaths.has(ctx.path)) {
3776
+ ctx.state.route = {
3777
+ info: {
3778
+ type: "content-api",
3779
+ pluginName: "webbycommerce"
3780
+ }
3781
+ };
3782
+ if (!ctx.request.body || typeof ctx.request.body === "object" && Object.keys(ctx.request.body || {}).length === 0) {
3783
+ try {
3784
+ const contentType = ctx.request.header["content-type"] || "";
3785
+ if (contentType.includes("application/json")) {
3786
+ const chunks = [];
3787
+ for await (const chunk of ctx.req) {
3788
+ chunks.push(chunk);
3789
+ }
3790
+ const rawBody = Buffer.concat(chunks).toString("utf8");
3791
+ if (rawBody && rawBody.trim()) {
3792
+ ctx.request.body = JSON.parse(rawBody);
3793
+ strapi2.log.debug(`[webbycommerce] Parsed request body for unified auth:`, ctx.request.body);
3794
+ }
3795
+ }
3796
+ } catch (error) {
3797
+ strapi2.log.error(`[webbycommerce] Failed to parse request body for unified auth:`, error.message);
3798
+ }
3799
+ }
3800
+ const authController = strapi2.plugin("webbycommerce").controller("auth");
3801
+ if (authController && typeof authController.unifiedAuth === "function") {
3802
+ await authController.unifiedAuth(ctx);
3803
+ return;
3804
+ }
3805
+ }
3377
3806
  if ((ctx.method === "GET" || ctx.method === "PUT") && profilePaths.has(ctx.path)) {
3378
3807
  ctx.state.route = {
3379
3808
  info: {
@@ -4894,6 +5323,575 @@ var require_bootstrap = __commonJS({
4894
5323
  }
4895
5324
  return next();
4896
5325
  });
5326
+ strapi2.server.use(async (ctx, next) => {
5327
+ if (ctx.path === "/content-type-builder/update-schema" && ctx.method === "POST") {
5328
+ try {
5329
+ let body = ctx.request.body;
5330
+ if (!body || typeof body === "object" && Object.keys(body).length === 0) {
5331
+ try {
5332
+ const contentType = ctx.request.header["content-type"] || "";
5333
+ if (contentType.includes("application/json")) {
5334
+ const chunks = [];
5335
+ const originalReq = ctx.req;
5336
+ for await (const chunk of originalReq) {
5337
+ chunks.push(chunk);
5338
+ }
5339
+ const rawBody = Buffer.concat(chunks).toString("utf8");
5340
+ if (rawBody && rawBody.trim()) {
5341
+ body = JSON.parse(rawBody);
5342
+ ctx.request.body = body;
5343
+ ctx.req = require("stream").Readable.from([Buffer.from(rawBody)]);
5344
+ }
5345
+ }
5346
+ } catch (parseError) {
5347
+ strapi2.log.warn("[webbycommerce] Could not parse request body:", parseError.message);
5348
+ }
5349
+ }
5350
+ body = body || {};
5351
+ const data = body.data || body;
5352
+ const contentTypes3 = data.contentTypes || [];
5353
+ const components = data.components || [];
5354
+ strapi2.log.info("[webbycommerce] ===== Processing content-type-builder update-schema request =====");
5355
+ strapi2.log.info("[webbycommerce] Request body keys:", Object.keys(body));
5356
+ strapi2.log.info("[webbycommerce] Data keys:", Object.keys(data));
5357
+ strapi2.log.info("[webbycommerce] Content types to process:", contentTypes3.length);
5358
+ strapi2.log.info("[webbycommerce] Components to process:", components.length);
5359
+ if (contentTypes3.length === 0 && components.length === 0) {
5360
+ strapi2.log.warn("[webbycommerce] No content types or components found in request body");
5361
+ strapi2.log.warn("[webbycommerce] Body type:", typeof body);
5362
+ strapi2.log.warn("[webbycommerce] Body stringified (first 500 chars):", JSON.stringify(body, null, 2).substring(0, 500));
5363
+ }
5364
+ let appDir;
5365
+ if (strapi2.dirs && strapi2.dirs.app && strapi2.dirs.app.root) {
5366
+ appDir = strapi2.dirs.app.root;
5367
+ strapi2.log.info("[webbycommerce] Using strapi.dirs.app.root:", appDir);
5368
+ } else if (strapi2.dirs && strapi2.dirs.root) {
5369
+ appDir = strapi2.dirs.root;
5370
+ strapi2.log.info("[webbycommerce] Using strapi.dirs.root:", appDir);
5371
+ } else {
5372
+ appDir = path.resolve(__dirname, "../..");
5373
+ strapi2.log.info("[webbycommerce] Using fallback appDir (from __dirname):", appDir);
5374
+ strapi2.log.info("[webbycommerce] __dirname is:", __dirname);
5375
+ }
5376
+ if (!strapi2.dirs) {
5377
+ strapi2.dirs = {};
5378
+ }
5379
+ if (!strapi2.dirs.app) {
5380
+ strapi2.dirs.app = {};
5381
+ }
5382
+ if (!strapi2.dirs.app.root) {
5383
+ strapi2.dirs.app.root = appDir;
5384
+ strapi2.log.info("[webbycommerce] Set strapi.dirs.app.root to:", appDir);
5385
+ }
5386
+ let componentsCreated = false;
5387
+ for (const component of components) {
5388
+ if (component.uid && component.uid.includes(".")) {
5389
+ const uidParts = component.uid.split(".");
5390
+ if (uidParts.length >= 2) {
5391
+ const category = uidParts[0];
5392
+ const componentName = uidParts[1];
5393
+ strapi2.log.info(`[webbycommerce] EARLY: Processing component: ${component.uid}`);
5394
+ const componentsDir = path.join(appDir, "src", "components", category);
5395
+ fs.mkdirSync(componentsDir, { recursive: true });
5396
+ const componentSchemaPath = path.join(componentsDir, `${componentName}.json`);
5397
+ let existingComponentSchema = {};
5398
+ if (fs.existsSync(componentSchemaPath)) {
5399
+ try {
5400
+ existingComponentSchema = JSON.parse(fs.readFileSync(componentSchemaPath, "utf8"));
5401
+ } catch (error) {
5402
+ strapi2.log.warn(`[webbycommerce] EARLY: Could not parse existing component schema: ${error.message}`);
5403
+ existingComponentSchema = {};
5404
+ }
5405
+ }
5406
+ if (component.action === "delete") {
5407
+ strapi2.log.info(`[webbycommerce] EARLY: Deleting component: ${component.uid}`);
5408
+ if (fs.existsSync(componentSchemaPath)) {
5409
+ fs.unlinkSync(componentSchemaPath);
5410
+ strapi2.log.info(`[webbycommerce] EARLY: \u2713 Deleted component file: ${componentSchemaPath}`);
5411
+ }
5412
+ ctx.state.componentsCreated = true;
5413
+ ctx.state.componentsDeleted = true;
5414
+ continue;
5415
+ }
5416
+ const componentAttributes = { ...existingComponentSchema.attributes || {} };
5417
+ if (component.attributes && Array.isArray(component.attributes)) {
5418
+ for (const attr of component.attributes) {
5419
+ const action = attr.action || "update";
5420
+ if (action === "delete" && attr.name) {
5421
+ if (componentAttributes[attr.name]) {
5422
+ delete componentAttributes[attr.name];
5423
+ strapi2.log.info(`[webbycommerce] EARLY: \u2713 Deleted component attribute: ${attr.name}`);
5424
+ } else {
5425
+ strapi2.log.warn(`[webbycommerce] EARLY: Component attribute not found for deletion: ${attr.name}`);
5426
+ }
5427
+ continue;
5428
+ }
5429
+ if (attr.name && attr.properties) {
5430
+ const attributeDef = { ...attr.properties };
5431
+ componentAttributes[attr.name] = attributeDef;
5432
+ strapi2.log.info(`[webbycommerce] EARLY: ${action === "create" ? "Added" : "Updated"} component attribute: ${attr.name} (type: ${attributeDef.type || "unknown"})`);
5433
+ }
5434
+ }
5435
+ }
5436
+ const componentSchema = {
5437
+ collectionName: component.collectionName || existingComponentSchema.collectionName || "components_" + component.uid.replace(/\./g, "_"),
5438
+ info: {
5439
+ displayName: component.displayName || component.modelName || existingComponentSchema.info?.displayName || componentName || "New Component",
5440
+ description: component.description || existingComponentSchema.info?.description || "",
5441
+ icon: component.icon || existingComponentSchema.info?.icon || ""
5442
+ },
5443
+ options: component.options || existingComponentSchema.options || {},
5444
+ attributes: componentAttributes
5445
+ };
5446
+ const componentSchemaJson = JSON.stringify(componentSchema, null, 2);
5447
+ fs.writeFileSync(componentSchemaPath, componentSchemaJson, "utf8");
5448
+ if (fs.existsSync(componentSchemaPath)) {
5449
+ try {
5450
+ const verifyComponentSchema = JSON.parse(fs.readFileSync(componentSchemaPath, "utf8"));
5451
+ const fileStats = fs.statSync(componentSchemaPath);
5452
+ strapi2.log.info(`[webbycommerce] ========================================`);
5453
+ strapi2.log.info(`[webbycommerce] \u2713 COMPONENT SCHEMA CREATED/UPDATED`);
5454
+ strapi2.log.info(`[webbycommerce] ========================================`);
5455
+ strapi2.log.info(`[webbycommerce] \u2713 Component: ${component.uid}`);
5456
+ strapi2.log.info(`[webbycommerce] \u2713 File: ${componentSchemaPath}`);
5457
+ strapi2.log.info(`[webbycommerce] \u2713 File size: ${fileStats.size} bytes`);
5458
+ strapi2.log.info(`[webbycommerce] \u2713 Schema is valid JSON`);
5459
+ strapi2.log.info(`[webbycommerce] \u2713 Display name: ${verifyComponentSchema.info?.displayName || "N/A"}`);
5460
+ strapi2.log.info(`[webbycommerce] \u2713 Total attributes: ${Object.keys(verifyComponentSchema.attributes || {}).length}`);
5461
+ const attrNames = Object.keys(verifyComponentSchema.attributes || {});
5462
+ if (attrNames.length > 0) {
5463
+ strapi2.log.info(`[webbycommerce] \u2713 Component attributes:`);
5464
+ attrNames.forEach((attrName) => {
5465
+ const attr = verifyComponentSchema.attributes[attrName];
5466
+ const attrType = attr.type || "unknown";
5467
+ strapi2.log.info(`[webbycommerce] - ${attrName}: ${attrType}`);
5468
+ });
5469
+ }
5470
+ strapi2.log.info(`[webbycommerce] \u2713 File will trigger auto-restart`);
5471
+ strapi2.log.info(`[webbycommerce] \u2713 After restart, component will be registered with all fields`);
5472
+ strapi2.log.info(`[webbycommerce] ========================================`);
5473
+ fs.chmodSync(componentSchemaPath, 420);
5474
+ const now = /* @__PURE__ */ new Date();
5475
+ fs.utimesSync(componentSchemaPath, now, now);
5476
+ fs.fsyncSync(fs.openSync(componentSchemaPath, "r+"));
5477
+ componentsCreated = true;
5478
+ ctx.state.componentsCreated = true;
5479
+ strapi2.log.info(`[webbycommerce] EARLY: \u2713 Set ctx.state.componentsCreated = true for component ${component.uid}`);
5480
+ strapi2.log.info(`[webbycommerce] EARLY: \u2713 Component file synced to disk - file watcher will detect change`);
5481
+ } catch (verifyError) {
5482
+ strapi2.log.error(`[webbycommerce] \u2717 Component schema verification failed: ${verifyError.message}`);
5483
+ }
5484
+ } else {
5485
+ strapi2.log.error(`[webbycommerce] \u2717 Component schema file was not created: ${componentSchemaPath}`);
5486
+ }
5487
+ }
5488
+ }
5489
+ }
5490
+ for (const contentType of contentTypes3) {
5491
+ if (contentType.uid && contentType.uid.startsWith("api::")) {
5492
+ const uidParts = contentType.uid.split("::");
5493
+ if (uidParts.length === 2) {
5494
+ const apiAndType = uidParts[1].split(".");
5495
+ if (apiAndType.length >= 2) {
5496
+ const apiName = apiAndType[0];
5497
+ const contentTypeName = apiAndType[1];
5498
+ const apiDir = path.join(appDir, "src", "api", apiName);
5499
+ const contentTypeDir = path.join(apiDir, "content-types", contentTypeName);
5500
+ const schemaPath = path.join(contentTypeDir, "schema.json");
5501
+ strapi2.log.info(`[webbycommerce] Processing content type: ${contentType.uid}`);
5502
+ strapi2.log.info(`[webbycommerce] API Name: ${apiName}, Content Type Name: ${contentTypeName}`);
5503
+ if (contentType.action === "delete") {
5504
+ strapi2.log.info(`[webbycommerce] Deleting collection: ${contentType.uid}`);
5505
+ if (fs.existsSync(schemaPath)) {
5506
+ fs.unlinkSync(schemaPath);
5507
+ strapi2.log.info(`[webbycommerce] \u2713 Deleted schema file: ${schemaPath}`);
5508
+ }
5509
+ if (fs.existsSync(contentTypeDir)) {
5510
+ try {
5511
+ fs.rmSync(contentTypeDir, { recursive: true, force: true });
5512
+ strapi2.log.info(`[webbycommerce] \u2713 Deleted content type directory: ${contentTypeDir}`);
5513
+ } catch (error) {
5514
+ strapi2.log.warn(`[webbycommerce] Could not delete directory: ${error.message}`);
5515
+ }
5516
+ }
5517
+ ctx.state.schemaFileCreated = true;
5518
+ ctx.state.schemaDeleted = true;
5519
+ continue;
5520
+ }
5521
+ if (!fs.existsSync(apiDir)) {
5522
+ fs.mkdirSync(apiDir, { recursive: true });
5523
+ strapi2.log.info(`[webbycommerce] \u2713 Created API directory: ${apiDir}`);
5524
+ } else {
5525
+ strapi2.log.info(`[webbycommerce] \u2713 API directory already exists: ${apiDir}`);
5526
+ }
5527
+ if (!fs.existsSync(contentTypeDir)) {
5528
+ fs.mkdirSync(contentTypeDir, { recursive: true });
5529
+ strapi2.log.info(`[webbycommerce] \u2713 Created content type directory: ${contentTypeDir}`);
5530
+ } else {
5531
+ strapi2.log.info(`[webbycommerce] \u2713 Content type directory already exists: ${contentTypeDir}`);
5532
+ }
5533
+ strapi2.log.info(`[webbycommerce] Schema path: ${schemaPath}`);
5534
+ let schemaNeedsUpdate = false;
5535
+ let currentSchema = {};
5536
+ if (fs.existsSync(schemaPath)) {
5537
+ try {
5538
+ currentSchema = JSON.parse(fs.readFileSync(schemaPath, "utf8"));
5539
+ if (!currentSchema || typeof currentSchema !== "object") {
5540
+ throw new Error("Invalid schema file");
5541
+ }
5542
+ strapi2.log.info(`[webbycommerce] \u2713 Schema file already exists and is valid`);
5543
+ const now = /* @__PURE__ */ new Date();
5544
+ fs.utimesSync(schemaPath, now, now);
5545
+ } catch (parseError) {
5546
+ strapi2.log.warn(`[webbycommerce] \u26A0 Schema file exists but is invalid, will be overwritten`);
5547
+ schemaNeedsUpdate = true;
5548
+ }
5549
+ } else {
5550
+ schemaNeedsUpdate = true;
5551
+ }
5552
+ if (schemaNeedsUpdate) {
5553
+ const attributes = { ...currentSchema.attributes || {} };
5554
+ if (contentType.attributes && Array.isArray(contentType.attributes)) {
5555
+ for (const attr of contentType.attributes) {
5556
+ const action = attr.action || "update";
5557
+ if (action === "delete" && attr.name) {
5558
+ if (attributes[attr.name]) {
5559
+ delete attributes[attr.name];
5560
+ strapi2.log.info(`[webbycommerce] \u2713 Deleted attribute: ${attr.name}`);
5561
+ }
5562
+ continue;
5563
+ }
5564
+ if (attr.name && attr.properties) {
5565
+ attributes[attr.name] = { ...attr.properties };
5566
+ strapi2.log.info(`[webbycommerce] ${action === "create" ? "Added" : "Updated"} attribute: ${attr.name}`);
5567
+ }
5568
+ }
5569
+ }
5570
+ const schema = {
5571
+ kind: contentType.kind || currentSchema.kind || "collectionType",
5572
+ collectionName: contentType.collectionName || currentSchema.collectionName || (contentType.kind === "singleType" ? contentTypeName : `${contentTypeName}s`),
5573
+ info: {
5574
+ singularName: contentType.singularName || currentSchema.info?.singularName || contentTypeName,
5575
+ pluralName: contentType.pluralName || currentSchema.info?.pluralName || (contentType.kind === "singleType" ? contentTypeName : `${contentTypeName}s`),
5576
+ displayName: contentType.displayName || contentType.modelName || currentSchema.info?.displayName || contentTypeName,
5577
+ description: contentType.description || currentSchema.info?.description || ""
5578
+ },
5579
+ options: {
5580
+ draftAndPublish: contentType.draftAndPublish !== void 0 ? contentType.draftAndPublish : currentSchema.options?.draftAndPublish !== void 0 ? currentSchema.options.draftAndPublish : false
5581
+ },
5582
+ pluginOptions: contentType.pluginOptions || currentSchema.pluginOptions || {
5583
+ "content-manager": {
5584
+ visible: true
5585
+ },
5586
+ "content-api": {
5587
+ visible: true
5588
+ }
5589
+ },
5590
+ attributes
5591
+ };
5592
+ fs.writeFileSync(schemaPath, JSON.stringify(schema, null, 2));
5593
+ strapi2.log.info(`[webbycommerce] \u2713 Created/Updated schema file: ${schemaPath}`);
5594
+ strapi2.log.info(`[webbycommerce] \u2713 File watcher will detect change and trigger auto-restart`);
5595
+ ctx.state.schemaFileCreated = true;
5596
+ }
5597
+ const controllersDir = path.join(apiDir, "controllers", contentTypeName);
5598
+ const servicesDir = path.join(apiDir, "services", contentTypeName);
5599
+ const routesDir = path.join(apiDir, "routes", contentTypeName);
5600
+ [controllersDir, servicesDir, routesDir].forEach((dir) => {
5601
+ if (!fs.existsSync(dir)) {
5602
+ fs.mkdirSync(dir, { recursive: true });
5603
+ strapi2.log.info(`[webbycommerce] \u2713 Created directory: ${dir}`);
5604
+ }
5605
+ });
5606
+ if (!fs.existsSync(schemaPath)) {
5607
+ strapi2.log.error(`[webbycommerce] \u2717 CRITICAL: Schema path does not exist after creation attempt: ${schemaPath}`);
5608
+ } else {
5609
+ strapi2.log.info(`[webbycommerce] \u2713 Final verification: Schema path exists: ${schemaPath}`);
5610
+ }
5611
+ } else {
5612
+ strapi2.log.warn(`[webbycommerce] \u26A0 Could not parse UID parts for: ${contentType.uid}`);
5613
+ }
5614
+ } else {
5615
+ strapi2.log.warn(`[webbycommerce] \u26A0 Invalid UID format: ${contentType.uid}`);
5616
+ }
5617
+ } else {
5618
+ strapi2.log.warn(`[webbycommerce] \u26A0 Content type does not have UID or is not an API content type`);
5619
+ }
5620
+ }
5621
+ strapi2.log.info("[webbycommerce] ===== Finished processing content-type-builder request =====");
5622
+ const hasContentTypes = (ctx.state.schemaFileCreated || ctx.state.schemaDeleted) && contentTypes3.length > 0;
5623
+ const hasComponents = ctx.state.componentsCreated === true || ctx.state.componentsDeleted === true;
5624
+ strapi2.log.info(`[webbycommerce] EARLY (SECOND): Checking early return conditions...`);
5625
+ strapi2.log.info(`[webbycommerce] EARLY (SECOND): hasContentTypes=${hasContentTypes}, hasComponents=${hasComponents}`);
5626
+ strapi2.log.info(`[webbycommerce] EARLY (SECOND): ctx.state.schemaFileCreated=${ctx.state.schemaFileCreated}, ctx.state.componentsCreated=${ctx.state.componentsCreated}`);
5627
+ if (hasContentTypes || hasComponents) {
5628
+ strapi2.log.info(`[webbycommerce] EARLY (SECOND): \u2713 Schema file(s) created successfully`);
5629
+ if (hasContentTypes) {
5630
+ strapi2.log.info(`[webbycommerce] EARLY (SECOND): \u2713 Created ${contentTypes3.length} content type(s)`);
5631
+ }
5632
+ if (hasComponents) {
5633
+ strapi2.log.info(`[webbycommerce] EARLY (SECOND): \u2713 Created ${components.length} component(s)`);
5634
+ }
5635
+ strapi2.log.info(`[webbycommerce] EARLY (SECOND): \u2713 File watcher will detect change and trigger auto-restart`);
5636
+ strapi2.log.info(`[webbycommerce] EARLY (SECOND): \u2713 After restart, collections and components will be automatically registered with all fields`);
5637
+ ctx.status = 200;
5638
+ ctx.set("Content-Type", "application/json");
5639
+ ctx.body = {
5640
+ data: {
5641
+ contentTypes: contentTypes3.map((ct) => {
5642
+ const uidParts = ct.uid.split("::");
5643
+ const apiAndType = uidParts.length === 2 ? uidParts[1].split(".") : [];
5644
+ return {
5645
+ uid: ct.uid,
5646
+ apiID: ct.uid,
5647
+ schema: {
5648
+ kind: ct.kind || "collectionType",
5649
+ collectionName: ct.collectionName || (ct.kind === "singleType" ? apiAndType[1] : `${apiAndType[1]}s`),
5650
+ info: {
5651
+ singularName: ct.singularName || apiAndType[1],
5652
+ pluralName: ct.pluralName || (ct.kind === "singleType" ? apiAndType[1] : `${apiAndType[1]}s`),
5653
+ displayName: ct.displayName || ct.modelName || apiAndType[1],
5654
+ description: ct.description || ""
5655
+ },
5656
+ options: {
5657
+ draftAndPublish: ct.draftAndPublish !== void 0 ? ct.draftAndPublish : false
5658
+ }
5659
+ }
5660
+ };
5661
+ }),
5662
+ components: (components || []).map((comp) => {
5663
+ const uidParts = comp.uid ? comp.uid.split(".") : [];
5664
+ return {
5665
+ uid: comp.uid,
5666
+ category: uidParts[0] || "",
5667
+ apiID: comp.uid,
5668
+ schema: {
5669
+ collectionName: comp.collectionName || "components_" + comp.uid.replace(/\./g, "_"),
5670
+ info: {
5671
+ displayName: comp.displayName || comp.modelName || uidParts[1] || "New Component",
5672
+ description: comp.description || ""
5673
+ }
5674
+ }
5675
+ };
5676
+ })
5677
+ }
5678
+ };
5679
+ strapi2.log.info(`[webbycommerce] EARLY (SECOND): \u2713 Success response sent - request handled`);
5680
+ strapi2.log.info(`[webbycommerce] EARLY (SECOND): \u2713 Returning early to prevent Strapi from processing request again`);
5681
+ return;
5682
+ }
5683
+ } catch (error) {
5684
+ strapi2.log.error("[webbycommerce] \u2717 Error ensuring API directory structure:", error.message);
5685
+ strapi2.log.error("[webbycommerce] Error stack:", error.stack);
5686
+ }
5687
+ }
5688
+ return next();
5689
+ });
5690
+ strapi2.server.use(async (ctx, next) => {
5691
+ try {
5692
+ await next();
5693
+ } catch (error) {
5694
+ if (ctx.path === "/content-type-builder/update-schema" && error.message && error.message.includes("path") && error.message.includes("undefined")) {
5695
+ strapi2.log.error("[webbycommerce] Caught path undefined error, attempting to fix...");
5696
+ try {
5697
+ const body = ctx.request.body || {};
5698
+ const data = body.data || body;
5699
+ const contentTypes3 = data.contentTypes || [];
5700
+ let appDir;
5701
+ if (strapi2.dirs && strapi2.dirs.app && strapi2.dirs.app.root) {
5702
+ appDir = strapi2.dirs.app.root;
5703
+ } else if (strapi2.dirs && strapi2.dirs.root) {
5704
+ appDir = strapi2.dirs.root;
5705
+ } else {
5706
+ appDir = path.resolve(__dirname, "../..");
5707
+ }
5708
+ for (const contentType of contentTypes3) {
5709
+ if (contentType.uid && contentType.uid.startsWith("api::")) {
5710
+ const uidParts = contentType.uid.split("::");
5711
+ if (uidParts.length === 2) {
5712
+ const apiAndType = uidParts[1].split(".");
5713
+ if (apiAndType.length >= 2) {
5714
+ const apiName = apiAndType[0];
5715
+ const contentTypeName = apiAndType[1];
5716
+ const apiDir = path.join(appDir, "src", "api", apiName);
5717
+ const contentTypeDir = path.join(apiDir, "content-types", contentTypeName);
5718
+ const schemaPath = path.join(contentTypeDir, "schema.json");
5719
+ if (!fs.existsSync(contentTypeDir)) {
5720
+ fs.mkdirSync(contentTypeDir, { recursive: true });
5721
+ strapi2.log.info(`[webbycommerce] Created content type directory: ${contentTypeDir}`);
5722
+ }
5723
+ if (!fs.existsSync(schemaPath)) {
5724
+ const minimalSchema = {
5725
+ kind: contentType.kind || "collectionType",
5726
+ collectionName: contentType.collectionName || (contentType.kind === "singleType" ? contentTypeName : `${contentTypeName}s`),
5727
+ info: {
5728
+ singularName: contentType.singularName || contentTypeName,
5729
+ pluralName: contentType.pluralName || (contentType.kind === "singleType" ? contentTypeName : `${contentTypeName}s`),
5730
+ displayName: contentType.displayName || contentType.modelName || contentTypeName,
5731
+ description: contentType.description || ""
5732
+ },
5733
+ options: {
5734
+ draftAndPublish: contentType.draftAndPublish !== void 0 ? contentType.draftAndPublish : false
5735
+ },
5736
+ attributes: {}
5737
+ };
5738
+ fs.writeFileSync(schemaPath, JSON.stringify(minimalSchema, null, 2));
5739
+ strapi2.log.info(`[webbycommerce] Created schema file: ${schemaPath}`);
5740
+ }
5741
+ }
5742
+ }
5743
+ }
5744
+ }
5745
+ strapi2.log.info("[webbycommerce] Retrying content-type-builder request after fixing directories...");
5746
+ } catch (fixError) {
5747
+ strapi2.log.error("[webbycommerce] Failed to fix path error:", fixError.message);
5748
+ }
5749
+ }
5750
+ throw error;
5751
+ }
5752
+ });
5753
+ try {
5754
+ const contentTypeBuilderPlugin = strapi2.plugin("content-type-builder");
5755
+ if (contentTypeBuilderPlugin) {
5756
+ const ctbController = contentTypeBuilderPlugin.controller("content-types");
5757
+ if (ctbController && typeof ctbController.updateSchema === "function") {
5758
+ const originalUpdateSchema = ctbController.updateSchema;
5759
+ ctbController.updateSchema = async function(ctx) {
5760
+ try {
5761
+ return await originalUpdateSchema.call(this, ctx);
5762
+ } catch (error) {
5763
+ if (error.message && error.message.includes("path") && error.message.includes("undefined")) {
5764
+ strapi2.log.error("[webbycommerce] CONTROLLER: Caught path undefined error in updateSchema");
5765
+ const body = ctx.request.body || {};
5766
+ const data = body.data || body;
5767
+ const contentTypes3 = data.contentTypes || [];
5768
+ let appDir = strapi2.dirs?.app?.root || path.resolve(__dirname, "../..");
5769
+ for (const contentType of contentTypes3) {
5770
+ if (contentType.uid && contentType.uid.startsWith("api::")) {
5771
+ const uidParts = contentType.uid.split("::");
5772
+ if (uidParts.length === 2) {
5773
+ const apiAndType = uidParts[1].split(".");
5774
+ if (apiAndType.length >= 2) {
5775
+ const apiName = apiAndType[0];
5776
+ const contentTypeName = apiAndType[1];
5777
+ const contentTypeDir = path.join(appDir, "src", "api", apiName, "content-types", contentTypeName);
5778
+ const schemaPath = path.join(contentTypeDir, "schema.json");
5779
+ fs.mkdirSync(contentTypeDir, { recursive: true });
5780
+ if (!fs.existsSync(schemaPath)) {
5781
+ const minimalSchema = {
5782
+ kind: contentType.kind || "collectionType",
5783
+ collectionName: contentType.collectionName || (contentType.kind === "singleType" ? contentTypeName : `${contentTypeName}s`),
5784
+ info: {
5785
+ singularName: contentType.singularName || contentTypeName,
5786
+ pluralName: contentType.pluralName || (contentType.kind === "singleType" ? contentTypeName : `${contentTypeName}s`),
5787
+ displayName: contentType.displayName || contentType.modelName || contentTypeName
5788
+ },
5789
+ options: {
5790
+ draftAndPublish: contentType.draftAndPublish !== void 0 ? contentType.draftAndPublish : false
5791
+ },
5792
+ attributes: {}
5793
+ };
5794
+ fs.writeFileSync(schemaPath, JSON.stringify(minimalSchema, null, 2));
5795
+ }
5796
+ }
5797
+ }
5798
+ }
5799
+ }
5800
+ strapi2.log.info("[webbycommerce] CONTROLLER: Retrying updateSchema after fixing paths");
5801
+ return await originalUpdateSchema.call(this, ctx);
5802
+ }
5803
+ throw error;
5804
+ }
5805
+ };
5806
+ strapi2.log.info("[webbycommerce] Patched content-type-builder updateSchema controller");
5807
+ }
5808
+ const ctbService = contentTypeBuilderPlugin.service("builder");
5809
+ if (ctbService) {
5810
+ if (ctbService.writeContentTypeSchema && typeof ctbService.writeContentTypeSchema === "function") {
5811
+ const originalWriteContentTypeSchema = ctbService.writeContentTypeSchema;
5812
+ ctbService.writeContentTypeSchema = function(uid, schema) {
5813
+ try {
5814
+ return originalWriteContentTypeSchema.call(this, uid, schema);
5815
+ } catch (error) {
5816
+ if (error.message && error.message.includes("path") && error.message.includes("undefined")) {
5817
+ strapi2.log.error("[webbycommerce] SERVICE: Caught path undefined error in writeContentTypeSchema");
5818
+ if (uid && uid.startsWith("api::")) {
5819
+ const uidParts = uid.split("::");
5820
+ if (uidParts.length === 2) {
5821
+ const apiAndType = uidParts[1].split(".");
5822
+ if (apiAndType.length >= 2) {
5823
+ const apiName = apiAndType[0];
5824
+ const contentTypeName = apiAndType[1];
5825
+ const appDir = strapi2.dirs?.app?.root || path.resolve(__dirname, "../..");
5826
+ const contentTypeDir = path.join(appDir, "src", "api", apiName, "content-types", contentTypeName);
5827
+ const schemaPath = path.join(contentTypeDir, "schema.json");
5828
+ fs.mkdirSync(contentTypeDir, { recursive: true });
5829
+ if (!fs.existsSync(schemaPath)) {
5830
+ fs.writeFileSync(schemaPath, JSON.stringify(schema || {}, null, 2));
5831
+ }
5832
+ return originalWriteContentTypeSchema.call(this, uid, schema);
5833
+ }
5834
+ }
5835
+ }
5836
+ }
5837
+ throw error;
5838
+ }
5839
+ };
5840
+ strapi2.log.info("[webbycommerce] Patched content-type-builder writeContentTypeSchema service");
5841
+ }
5842
+ }
5843
+ }
5844
+ } catch (patchError) {
5845
+ strapi2.log.warn("[webbycommerce] Could not patch content-type-builder:", patchError.message);
5846
+ strapi2.log.warn("[webbycommerce] Patch error stack:", patchError.stack);
5847
+ }
5848
+ const originalWriteFileSync = fs.writeFileSync;
5849
+ fs.writeFileSync = function(filePath, data, options) {
5850
+ if (filePath === void 0 || filePath === null) {
5851
+ const error = new Error('The "path" argument must be of type string. Received undefined');
5852
+ strapi2.log.error("[webbycommerce] FS PATCH: Caught undefined path in writeFileSync");
5853
+ strapi2.log.error("[webbycommerce] FS PATCH: Stack trace:", new Error().stack);
5854
+ throw error;
5855
+ }
5856
+ if (typeof filePath === "string" && !path.isAbsolute(filePath)) {
5857
+ const appDir = strapi2.dirs?.app?.root || path.resolve(__dirname, "../..");
5858
+ const absolutePath = path.resolve(appDir, filePath);
5859
+ if (absolutePath.includes("content-types") && absolutePath.endsWith("schema.json")) {
5860
+ const dir = path.dirname(absolutePath);
5861
+ if (!fs.existsSync(dir)) {
5862
+ fs.mkdirSync(dir, { recursive: true });
5863
+ strapi2.log.info(`[webbycommerce] FS PATCH: Created directory for relative path: ${dir}`);
5864
+ }
5865
+ filePath = absolutePath;
5866
+ }
5867
+ }
5868
+ return originalWriteFileSync.call(this, filePath, data, options);
5869
+ };
5870
+ const originalWriteFile = fs.writeFile;
5871
+ fs.writeFile = function(filePath, data, options, callback) {
5872
+ if (filePath === void 0 || filePath === null) {
5873
+ const error = new Error('The "path" argument must be of type string. Received undefined');
5874
+ strapi2.log.error("[webbycommerce] FS PATCH: Caught undefined path in writeFile");
5875
+ if (callback && typeof callback === "function") {
5876
+ return callback(error);
5877
+ }
5878
+ throw error;
5879
+ }
5880
+ if (typeof filePath === "string" && !path.isAbsolute(filePath)) {
5881
+ const appDir = strapi2.dirs?.app?.root || path.resolve(__dirname, "../..");
5882
+ const absolutePath = path.resolve(appDir, filePath);
5883
+ if (absolutePath.includes("content-types") && absolutePath.endsWith("schema.json")) {
5884
+ const dir = path.dirname(absolutePath);
5885
+ if (!fs.existsSync(dir)) {
5886
+ fs.mkdirSync(dir, { recursive: true });
5887
+ strapi2.log.info(`[webbycommerce] FS PATCH: Created directory for relative path: ${dir}`);
5888
+ }
5889
+ filePath = absolutePath;
5890
+ }
5891
+ }
5892
+ return originalWriteFile.call(this, filePath, data, options, callback);
5893
+ };
5894
+ strapi2.log.info("[webbycommerce] Patched fs.writeFileSync and fs.writeFile to catch undefined paths");
4897
5895
  let retryCount = 0;
4898
5896
  const maxRetries = 3;
4899
5897
  const retryDelay = 1e3;
@@ -4916,10 +5914,107 @@ var require_bootstrap = __commonJS({
4916
5914
  }
4917
5915
  };
4918
5916
  await registerWithRetry();
5917
+ strapi2.db.lifecycles.subscribe({
5918
+ models: ["*"],
5919
+ // Listen to all models
5920
+ async afterCreate(event) {
5921
+ }
5922
+ });
5923
+ strapi2.server.use(async (ctx, next) => {
5924
+ if (ctx.path === "/content-type-builder/update-schema" && ctx.method === "POST") {
5925
+ await next();
5926
+ if (ctx.status === 200 || ctx.status === 201) {
5927
+ const body = ctx.request.body || {};
5928
+ const data = body.data || body;
5929
+ const contentTypes3 = data.contentTypes || [];
5930
+ for (const contentType of contentTypes3) {
5931
+ if (contentType.uid && contentType.uid.startsWith("api::")) {
5932
+ const uidParts = contentType.uid.split("::");
5933
+ if (uidParts.length === 2) {
5934
+ const apiAndType = uidParts[1].split(".");
5935
+ if (apiAndType.length >= 2) {
5936
+ const apiName = apiAndType[0];
5937
+ const contentTypeName = apiAndType[1];
5938
+ strapi2.log.info(`[webbycommerce] \u2713 New collection created: ${contentType.uid}`);
5939
+ strapi2.log.info(`[webbycommerce] \u2713 Collection will be auto-registered on next restart`);
5940
+ strapi2.log.info(`[webbycommerce] \u2713 Strapi will auto-restart in develop mode to register the new collection`);
5941
+ const appDir = strapi2.dirs?.app?.root || path.resolve(__dirname, "../..");
5942
+ const schemaPath = path.join(appDir, "src", "api", apiName, "content-types", contentTypeName, "schema.json");
5943
+ if (fs.existsSync(schemaPath)) {
5944
+ strapi2.log.info(`[webbycommerce] \u2713 Schema file confirmed: ${schemaPath}`);
5945
+ strapi2.log.info(`[webbycommerce] \u2713 Auto-restart should occur automatically in develop mode`);
5946
+ }
5947
+ }
5948
+ }
5949
+ }
5950
+ }
5951
+ }
5952
+ } else {
5953
+ await next();
5954
+ }
5955
+ });
5956
+ try {
5957
+ const allContentTypes = strapi2.contentTypes;
5958
+ const apiContentTypes = Object.keys(allContentTypes).filter((uid) => uid.startsWith("api::"));
5959
+ strapi2.log.info(`[webbycommerce] Currently registered API content types: ${apiContentTypes.length}`);
5960
+ if (apiContentTypes.length > 0) {
5961
+ strapi2.log.info(`[webbycommerce] Registered collections: ${apiContentTypes.join(", ")}`);
5962
+ }
5963
+ try {
5964
+ let componentKeys = [];
5965
+ if (strapi2.components && strapi2.components instanceof Map) {
5966
+ componentKeys = Array.from(strapi2.components.keys());
5967
+ } else if (strapi2.get && typeof strapi2.get === "function") {
5968
+ const components = strapi2.get("components");
5969
+ if (components instanceof Map) {
5970
+ componentKeys = Array.from(components.keys());
5971
+ } else if (components && typeof components === "object") {
5972
+ componentKeys = Object.keys(components);
5973
+ }
5974
+ } else if (strapi2.components && typeof strapi2.components === "object") {
5975
+ componentKeys = Object.keys(strapi2.components);
5976
+ }
5977
+ const userComponents = componentKeys.filter(
5978
+ (uid) => (uid.startsWith("shared.") || uid.includes(".")) && !uid.startsWith("plugin::")
5979
+ );
5980
+ strapi2.log.info(`[webbycommerce] Currently registered user components: ${userComponents.length}`);
5981
+ if (userComponents.length > 0) {
5982
+ strapi2.log.info(`[webbycommerce] Registered components: ${userComponents.join(", ")}`);
5983
+ } else {
5984
+ strapi2.log.warn(`[webbycommerce] \u26A0 No user components found - checking component files...`);
5985
+ const appDir = strapi2.dirs?.app?.root || path.resolve(__dirname, "../..");
5986
+ const componentsDir = path.join(appDir, "src", "components");
5987
+ if (fs.existsSync(componentsDir)) {
5988
+ const categoryDirs = fs.readdirSync(componentsDir, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
5989
+ let totalComponentFiles = 0;
5990
+ for (const category of categoryDirs) {
5991
+ const categoryPath = path.join(componentsDir, category);
5992
+ const files = fs.readdirSync(categoryPath, { withFileTypes: true }).filter((dirent) => dirent.isFile() && dirent.name.endsWith(".json")).map((dirent) => dirent.name);
5993
+ for (const jsonFile of files) {
5994
+ const componentName = jsonFile.replace(".json", "");
5995
+ const componentPath = path.join(categoryPath, jsonFile);
5996
+ if (fs.existsSync(componentPath)) {
5997
+ totalComponentFiles++;
5998
+ strapi2.log.info(`[webbycommerce] - Found component file: ${category}.${componentName} at ${componentPath}`);
5999
+ }
6000
+ }
6001
+ }
6002
+ if (totalComponentFiles > 0) {
6003
+ strapi2.log.warn(`[webbycommerce] \u26A0 Found ${totalComponentFiles} component files but Strapi hasn't loaded them yet`);
6004
+ strapi2.log.warn(`[webbycommerce] \u26A0 Components should appear after Strapi finishes loading - try refreshing the browser`);
6005
+ }
6006
+ }
6007
+ }
6008
+ } catch (compError) {
6009
+ strapi2.log.debug(`[webbycommerce] Could not list components: ${compError.message}`);
6010
+ }
6011
+ } catch (error) {
6012
+ }
4919
6013
  strapi2.log.info("[webbycommerce] Plugin bootstrapped successfully");
4920
6014
  strapi2.log.info(
4921
6015
  "[webbycommerce] Health endpoint is available at: /webbycommerce/health and /api/webbycommerce/health"
4922
6016
  );
6017
+ strapi2.log.info("[webbycommerce] Auto-restart enabled: Strapi will automatically restart when new collections or components are added");
4923
6018
  strapi2.log.info("[webbycommerce] ========================================");
4924
6019
  } catch (error) {
4925
6020
  strapi2.log.error("[webbycommerce] Bootstrap error:", error);
@@ -4998,8 +6093,8 @@ var require_controller = __commonJS({
4998
6093
  const currentValue = await store.get({ key: SETTINGS_KEY }) || {};
4999
6094
  const allowedOrigins = body.allowedOrigins !== void 0 ? sanitizeOrigins(body.allowedOrigins) : sanitizeOrigins(currentValue.allowedOrigins);
5000
6095
  let loginRegisterMethod = body.loginRegisterMethod !== void 0 ? body.loginRegisterMethod : currentValue.loginRegisterMethod || "default";
5001
- if (loginRegisterMethod !== "default" && loginRegisterMethod !== "otp") {
5002
- return ctx.badRequest('Invalid loginRegisterMethod. Must be "default" or "otp".');
6096
+ if (loginRegisterMethod !== "default" && loginRegisterMethod !== "otp" && loginRegisterMethod !== "both") {
6097
+ return ctx.badRequest('Invalid loginRegisterMethod. Must be "default", "otp", or "both".');
5003
6098
  }
5004
6099
  let routePrefix = body.routePrefix !== void 0 ? body.routePrefix : currentValue.routePrefix || "webbycommerce";
5005
6100
  routePrefix = routePrefix.trim().replace(/^\/+|\/+$/g, "").replace(/\/+/g, "/").replace(/[^a-zA-Z0-9\/_-]/g, "") || "webbycommerce";
@@ -5037,32 +6132,1850 @@ var require_controller = __commonJS({
5037
6132
  strapi.log.error(`[${PLUGIN_ID}] Seed demo failed:`, error);
5038
6133
  ctx.badRequest("Failed to seed demo data", { error: error.message });
5039
6134
  }
5040
- },
5041
- async generateDemo(ctx) {
5042
- strapi.log.info(`[${PLUGIN_ID}] Demo data generation requested`);
5043
- try {
5044
- const path = require("path");
5045
- const demoScriptPath = path.join(strapi.dirs.app.root, "scripts", "demo-ecommerce-visual.js");
5046
- strapi.log.info(`[${PLUGIN_ID}] Loading demo script from: ${demoScriptPath}`);
5047
- const { createVisualDemo } = require(demoScriptPath);
5048
- if (typeof createVisualDemo !== "function") {
5049
- throw new Error("createVisualDemo is not a function in the demo script");
6135
+ },
6136
+ async generateDemo(ctx) {
6137
+ strapi.log.info(`[${PLUGIN_ID}] Demo data generation requested`);
6138
+ try {
6139
+ const path = require("path");
6140
+ const demoScriptPath = path.join(strapi.dirs.app.root, "scripts", "demo-ecommerce-visual.js");
6141
+ strapi.log.info(`[${PLUGIN_ID}] Loading demo script from: ${demoScriptPath}`);
6142
+ const { createVisualDemo } = require(demoScriptPath);
6143
+ if (typeof createVisualDemo !== "function") {
6144
+ throw new Error("createVisualDemo is not a function in the demo script");
6145
+ }
6146
+ const result = await createVisualDemo();
6147
+ ctx.body = {
6148
+ success: true,
6149
+ message: "Demo data generated successfully",
6150
+ data: result
6151
+ };
6152
+ } catch (error) {
6153
+ strapi.log.error(`[${PLUGIN_ID}] Demo generation failed:`, error);
6154
+ ctx.badRequest("Failed to generate demo data", {
6155
+ error: error.message,
6156
+ details: error.stack
6157
+ });
6158
+ }
6159
+ }
6160
+ };
6161
+ }
6162
+ });
6163
+
6164
+ // node_modules/bcryptjs/dist/bcrypt.js
6165
+ var require_bcrypt = __commonJS({
6166
+ "node_modules/bcryptjs/dist/bcrypt.js"(exports2, module2) {
6167
+ (function(global, factory) {
6168
+ if (typeof define === "function" && define["amd"])
6169
+ define([], factory);
6170
+ else if (typeof require === "function" && typeof module2 === "object" && module2 && module2["exports"])
6171
+ module2["exports"] = factory();
6172
+ else
6173
+ (global["dcodeIO"] = global["dcodeIO"] || {})["bcrypt"] = factory();
6174
+ })(exports2, function() {
6175
+ "use strict";
6176
+ var bcrypt = {};
6177
+ var randomFallback = null;
6178
+ function random(len) {
6179
+ if (typeof module2 !== "undefined" && module2 && module2["exports"])
6180
+ try {
6181
+ return require("crypto")["randomBytes"](len);
6182
+ } catch (e) {
6183
+ }
6184
+ try {
6185
+ var a;
6186
+ (self["crypto"] || self["msCrypto"])["getRandomValues"](a = new Uint32Array(len));
6187
+ return Array.prototype.slice.call(a);
6188
+ } catch (e) {
6189
+ }
6190
+ if (!randomFallback)
6191
+ throw Error("Neither WebCryptoAPI nor a crypto module is available. Use bcrypt.setRandomFallback to set an alternative");
6192
+ return randomFallback(len);
6193
+ }
6194
+ var randomAvailable = false;
6195
+ try {
6196
+ random(1);
6197
+ randomAvailable = true;
6198
+ } catch (e) {
6199
+ }
6200
+ randomFallback = null;
6201
+ bcrypt.setRandomFallback = function(random2) {
6202
+ randomFallback = random2;
6203
+ };
6204
+ bcrypt.genSaltSync = function(rounds, seed_length) {
6205
+ rounds = rounds || GENSALT_DEFAULT_LOG2_ROUNDS;
6206
+ if (typeof rounds !== "number")
6207
+ throw Error("Illegal arguments: " + typeof rounds + ", " + typeof seed_length);
6208
+ if (rounds < 4)
6209
+ rounds = 4;
6210
+ else if (rounds > 31)
6211
+ rounds = 31;
6212
+ var salt = [];
6213
+ salt.push("$2a$");
6214
+ if (rounds < 10)
6215
+ salt.push("0");
6216
+ salt.push(rounds.toString());
6217
+ salt.push("$");
6218
+ salt.push(base64_encode(random(BCRYPT_SALT_LEN), BCRYPT_SALT_LEN));
6219
+ return salt.join("");
6220
+ };
6221
+ bcrypt.genSalt = function(rounds, seed_length, callback) {
6222
+ if (typeof seed_length === "function")
6223
+ callback = seed_length, seed_length = void 0;
6224
+ if (typeof rounds === "function")
6225
+ callback = rounds, rounds = void 0;
6226
+ if (typeof rounds === "undefined")
6227
+ rounds = GENSALT_DEFAULT_LOG2_ROUNDS;
6228
+ else if (typeof rounds !== "number")
6229
+ throw Error("illegal arguments: " + typeof rounds);
6230
+ function _async(callback2) {
6231
+ nextTick(function() {
6232
+ try {
6233
+ callback2(null, bcrypt.genSaltSync(rounds));
6234
+ } catch (err) {
6235
+ callback2(err);
6236
+ }
6237
+ });
6238
+ }
6239
+ if (callback) {
6240
+ if (typeof callback !== "function")
6241
+ throw Error("Illegal callback: " + typeof callback);
6242
+ _async(callback);
6243
+ } else
6244
+ return new Promise(function(resolve, reject) {
6245
+ _async(function(err, res) {
6246
+ if (err) {
6247
+ reject(err);
6248
+ return;
6249
+ }
6250
+ resolve(res);
6251
+ });
6252
+ });
6253
+ };
6254
+ bcrypt.hashSync = function(s, salt) {
6255
+ if (typeof salt === "undefined")
6256
+ salt = GENSALT_DEFAULT_LOG2_ROUNDS;
6257
+ if (typeof salt === "number")
6258
+ salt = bcrypt.genSaltSync(salt);
6259
+ if (typeof s !== "string" || typeof salt !== "string")
6260
+ throw Error("Illegal arguments: " + typeof s + ", " + typeof salt);
6261
+ return _hash(s, salt);
6262
+ };
6263
+ bcrypt.hash = function(s, salt, callback, progressCallback) {
6264
+ function _async(callback2) {
6265
+ if (typeof s === "string" && typeof salt === "number")
6266
+ bcrypt.genSalt(salt, function(err, salt2) {
6267
+ _hash(s, salt2, callback2, progressCallback);
6268
+ });
6269
+ else if (typeof s === "string" && typeof salt === "string")
6270
+ _hash(s, salt, callback2, progressCallback);
6271
+ else
6272
+ nextTick(callback2.bind(this, Error("Illegal arguments: " + typeof s + ", " + typeof salt)));
6273
+ }
6274
+ if (callback) {
6275
+ if (typeof callback !== "function")
6276
+ throw Error("Illegal callback: " + typeof callback);
6277
+ _async(callback);
6278
+ } else
6279
+ return new Promise(function(resolve, reject) {
6280
+ _async(function(err, res) {
6281
+ if (err) {
6282
+ reject(err);
6283
+ return;
6284
+ }
6285
+ resolve(res);
6286
+ });
6287
+ });
6288
+ };
6289
+ function safeStringCompare(known, unknown) {
6290
+ var right = 0, wrong = 0;
6291
+ for (var i = 0, k = known.length; i < k; ++i) {
6292
+ if (known.charCodeAt(i) === unknown.charCodeAt(i))
6293
+ ++right;
6294
+ else
6295
+ ++wrong;
6296
+ }
6297
+ if (right < 0)
6298
+ return false;
6299
+ return wrong === 0;
6300
+ }
6301
+ bcrypt.compareSync = function(s, hash) {
6302
+ if (typeof s !== "string" || typeof hash !== "string")
6303
+ throw Error("Illegal arguments: " + typeof s + ", " + typeof hash);
6304
+ if (hash.length !== 60)
6305
+ return false;
6306
+ return safeStringCompare(bcrypt.hashSync(s, hash.substr(0, hash.length - 31)), hash);
6307
+ };
6308
+ bcrypt.compare = function(s, hash, callback, progressCallback) {
6309
+ function _async(callback2) {
6310
+ if (typeof s !== "string" || typeof hash !== "string") {
6311
+ nextTick(callback2.bind(this, Error("Illegal arguments: " + typeof s + ", " + typeof hash)));
6312
+ return;
6313
+ }
6314
+ if (hash.length !== 60) {
6315
+ nextTick(callback2.bind(this, null, false));
6316
+ return;
6317
+ }
6318
+ bcrypt.hash(s, hash.substr(0, 29), function(err, comp) {
6319
+ if (err)
6320
+ callback2(err);
6321
+ else
6322
+ callback2(null, safeStringCompare(comp, hash));
6323
+ }, progressCallback);
6324
+ }
6325
+ if (callback) {
6326
+ if (typeof callback !== "function")
6327
+ throw Error("Illegal callback: " + typeof callback);
6328
+ _async(callback);
6329
+ } else
6330
+ return new Promise(function(resolve, reject) {
6331
+ _async(function(err, res) {
6332
+ if (err) {
6333
+ reject(err);
6334
+ return;
6335
+ }
6336
+ resolve(res);
6337
+ });
6338
+ });
6339
+ };
6340
+ bcrypt.getRounds = function(hash) {
6341
+ if (typeof hash !== "string")
6342
+ throw Error("Illegal arguments: " + typeof hash);
6343
+ return parseInt(hash.split("$")[2], 10);
6344
+ };
6345
+ bcrypt.getSalt = function(hash) {
6346
+ if (typeof hash !== "string")
6347
+ throw Error("Illegal arguments: " + typeof hash);
6348
+ if (hash.length !== 60)
6349
+ throw Error("Illegal hash length: " + hash.length + " != 60");
6350
+ return hash.substring(0, 29);
6351
+ };
6352
+ var nextTick = typeof process !== "undefined" && process && typeof process.nextTick === "function" ? typeof setImmediate === "function" ? setImmediate : process.nextTick : setTimeout;
6353
+ function stringToBytes(str) {
6354
+ var out = [], i = 0;
6355
+ utfx.encodeUTF16toUTF8(function() {
6356
+ if (i >= str.length) return null;
6357
+ return str.charCodeAt(i++);
6358
+ }, function(b) {
6359
+ out.push(b);
6360
+ });
6361
+ return out;
6362
+ }
6363
+ var BASE64_CODE = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".split("");
6364
+ var BASE64_INDEX = [
6365
+ -1,
6366
+ -1,
6367
+ -1,
6368
+ -1,
6369
+ -1,
6370
+ -1,
6371
+ -1,
6372
+ -1,
6373
+ -1,
6374
+ -1,
6375
+ -1,
6376
+ -1,
6377
+ -1,
6378
+ -1,
6379
+ -1,
6380
+ -1,
6381
+ -1,
6382
+ -1,
6383
+ -1,
6384
+ -1,
6385
+ -1,
6386
+ -1,
6387
+ -1,
6388
+ -1,
6389
+ -1,
6390
+ -1,
6391
+ -1,
6392
+ -1,
6393
+ -1,
6394
+ -1,
6395
+ -1,
6396
+ -1,
6397
+ -1,
6398
+ -1,
6399
+ -1,
6400
+ -1,
6401
+ -1,
6402
+ -1,
6403
+ -1,
6404
+ -1,
6405
+ -1,
6406
+ -1,
6407
+ -1,
6408
+ -1,
6409
+ -1,
6410
+ -1,
6411
+ 0,
6412
+ 1,
6413
+ 54,
6414
+ 55,
6415
+ 56,
6416
+ 57,
6417
+ 58,
6418
+ 59,
6419
+ 60,
6420
+ 61,
6421
+ 62,
6422
+ 63,
6423
+ -1,
6424
+ -1,
6425
+ -1,
6426
+ -1,
6427
+ -1,
6428
+ -1,
6429
+ -1,
6430
+ 2,
6431
+ 3,
6432
+ 4,
6433
+ 5,
6434
+ 6,
6435
+ 7,
6436
+ 8,
6437
+ 9,
6438
+ 10,
6439
+ 11,
6440
+ 12,
6441
+ 13,
6442
+ 14,
6443
+ 15,
6444
+ 16,
6445
+ 17,
6446
+ 18,
6447
+ 19,
6448
+ 20,
6449
+ 21,
6450
+ 22,
6451
+ 23,
6452
+ 24,
6453
+ 25,
6454
+ 26,
6455
+ 27,
6456
+ -1,
6457
+ -1,
6458
+ -1,
6459
+ -1,
6460
+ -1,
6461
+ -1,
6462
+ 28,
6463
+ 29,
6464
+ 30,
6465
+ 31,
6466
+ 32,
6467
+ 33,
6468
+ 34,
6469
+ 35,
6470
+ 36,
6471
+ 37,
6472
+ 38,
6473
+ 39,
6474
+ 40,
6475
+ 41,
6476
+ 42,
6477
+ 43,
6478
+ 44,
6479
+ 45,
6480
+ 46,
6481
+ 47,
6482
+ 48,
6483
+ 49,
6484
+ 50,
6485
+ 51,
6486
+ 52,
6487
+ 53,
6488
+ -1,
6489
+ -1,
6490
+ -1,
6491
+ -1,
6492
+ -1
6493
+ ];
6494
+ var stringFromCharCode = String.fromCharCode;
6495
+ function base64_encode(b, len) {
6496
+ var off = 0, rs = [], c1, c2;
6497
+ if (len <= 0 || len > b.length)
6498
+ throw Error("Illegal len: " + len);
6499
+ while (off < len) {
6500
+ c1 = b[off++] & 255;
6501
+ rs.push(BASE64_CODE[c1 >> 2 & 63]);
6502
+ c1 = (c1 & 3) << 4;
6503
+ if (off >= len) {
6504
+ rs.push(BASE64_CODE[c1 & 63]);
6505
+ break;
6506
+ }
6507
+ c2 = b[off++] & 255;
6508
+ c1 |= c2 >> 4 & 15;
6509
+ rs.push(BASE64_CODE[c1 & 63]);
6510
+ c1 = (c2 & 15) << 2;
6511
+ if (off >= len) {
6512
+ rs.push(BASE64_CODE[c1 & 63]);
6513
+ break;
6514
+ }
6515
+ c2 = b[off++] & 255;
6516
+ c1 |= c2 >> 6 & 3;
6517
+ rs.push(BASE64_CODE[c1 & 63]);
6518
+ rs.push(BASE64_CODE[c2 & 63]);
6519
+ }
6520
+ return rs.join("");
6521
+ }
6522
+ function base64_decode(s, len) {
6523
+ var off = 0, slen = s.length, olen = 0, rs = [], c1, c2, c3, c4, o, code;
6524
+ if (len <= 0)
6525
+ throw Error("Illegal len: " + len);
6526
+ while (off < slen - 1 && olen < len) {
6527
+ code = s.charCodeAt(off++);
6528
+ c1 = code < BASE64_INDEX.length ? BASE64_INDEX[code] : -1;
6529
+ code = s.charCodeAt(off++);
6530
+ c2 = code < BASE64_INDEX.length ? BASE64_INDEX[code] : -1;
6531
+ if (c1 == -1 || c2 == -1)
6532
+ break;
6533
+ o = c1 << 2 >>> 0;
6534
+ o |= (c2 & 48) >> 4;
6535
+ rs.push(stringFromCharCode(o));
6536
+ if (++olen >= len || off >= slen)
6537
+ break;
6538
+ code = s.charCodeAt(off++);
6539
+ c3 = code < BASE64_INDEX.length ? BASE64_INDEX[code] : -1;
6540
+ if (c3 == -1)
6541
+ break;
6542
+ o = (c2 & 15) << 4 >>> 0;
6543
+ o |= (c3 & 60) >> 2;
6544
+ rs.push(stringFromCharCode(o));
6545
+ if (++olen >= len || off >= slen)
6546
+ break;
6547
+ code = s.charCodeAt(off++);
6548
+ c4 = code < BASE64_INDEX.length ? BASE64_INDEX[code] : -1;
6549
+ o = (c3 & 3) << 6 >>> 0;
6550
+ o |= c4;
6551
+ rs.push(stringFromCharCode(o));
6552
+ ++olen;
6553
+ }
6554
+ var res = [];
6555
+ for (off = 0; off < olen; off++)
6556
+ res.push(rs[off].charCodeAt(0));
6557
+ return res;
6558
+ }
6559
+ var utfx = (function() {
6560
+ "use strict";
6561
+ var utfx2 = {};
6562
+ utfx2.MAX_CODEPOINT = 1114111;
6563
+ utfx2.encodeUTF8 = function(src, dst) {
6564
+ var cp = null;
6565
+ if (typeof src === "number")
6566
+ cp = src, src = function() {
6567
+ return null;
6568
+ };
6569
+ while (cp !== null || (cp = src()) !== null) {
6570
+ if (cp < 128)
6571
+ dst(cp & 127);
6572
+ else if (cp < 2048)
6573
+ dst(cp >> 6 & 31 | 192), dst(cp & 63 | 128);
6574
+ else if (cp < 65536)
6575
+ dst(cp >> 12 & 15 | 224), dst(cp >> 6 & 63 | 128), dst(cp & 63 | 128);
6576
+ else
6577
+ dst(cp >> 18 & 7 | 240), dst(cp >> 12 & 63 | 128), dst(cp >> 6 & 63 | 128), dst(cp & 63 | 128);
6578
+ cp = null;
6579
+ }
6580
+ };
6581
+ utfx2.decodeUTF8 = function(src, dst) {
6582
+ var a, b, c, d, fail = function(b2) {
6583
+ b2 = b2.slice(0, b2.indexOf(null));
6584
+ var err = Error(b2.toString());
6585
+ err.name = "TruncatedError";
6586
+ err["bytes"] = b2;
6587
+ throw err;
6588
+ };
6589
+ while ((a = src()) !== null) {
6590
+ if ((a & 128) === 0)
6591
+ dst(a);
6592
+ else if ((a & 224) === 192)
6593
+ (b = src()) === null && fail([a, b]), dst((a & 31) << 6 | b & 63);
6594
+ else if ((a & 240) === 224)
6595
+ ((b = src()) === null || (c = src()) === null) && fail([a, b, c]), dst((a & 15) << 12 | (b & 63) << 6 | c & 63);
6596
+ else if ((a & 248) === 240)
6597
+ ((b = src()) === null || (c = src()) === null || (d = src()) === null) && fail([a, b, c, d]), dst((a & 7) << 18 | (b & 63) << 12 | (c & 63) << 6 | d & 63);
6598
+ else throw RangeError("Illegal starting byte: " + a);
6599
+ }
6600
+ };
6601
+ utfx2.UTF16toUTF8 = function(src, dst) {
6602
+ var c1, c2 = null;
6603
+ while (true) {
6604
+ if ((c1 = c2 !== null ? c2 : src()) === null)
6605
+ break;
6606
+ if (c1 >= 55296 && c1 <= 57343) {
6607
+ if ((c2 = src()) !== null) {
6608
+ if (c2 >= 56320 && c2 <= 57343) {
6609
+ dst((c1 - 55296) * 1024 + c2 - 56320 + 65536);
6610
+ c2 = null;
6611
+ continue;
6612
+ }
6613
+ }
6614
+ }
6615
+ dst(c1);
6616
+ }
6617
+ if (c2 !== null) dst(c2);
6618
+ };
6619
+ utfx2.UTF8toUTF16 = function(src, dst) {
6620
+ var cp = null;
6621
+ if (typeof src === "number")
6622
+ cp = src, src = function() {
6623
+ return null;
6624
+ };
6625
+ while (cp !== null || (cp = src()) !== null) {
6626
+ if (cp <= 65535)
6627
+ dst(cp);
6628
+ else
6629
+ cp -= 65536, dst((cp >> 10) + 55296), dst(cp % 1024 + 56320);
6630
+ cp = null;
6631
+ }
6632
+ };
6633
+ utfx2.encodeUTF16toUTF8 = function(src, dst) {
6634
+ utfx2.UTF16toUTF8(src, function(cp) {
6635
+ utfx2.encodeUTF8(cp, dst);
6636
+ });
6637
+ };
6638
+ utfx2.decodeUTF8toUTF16 = function(src, dst) {
6639
+ utfx2.decodeUTF8(src, function(cp) {
6640
+ utfx2.UTF8toUTF16(cp, dst);
6641
+ });
6642
+ };
6643
+ utfx2.calculateCodePoint = function(cp) {
6644
+ return cp < 128 ? 1 : cp < 2048 ? 2 : cp < 65536 ? 3 : 4;
6645
+ };
6646
+ utfx2.calculateUTF8 = function(src) {
6647
+ var cp, l = 0;
6648
+ while ((cp = src()) !== null)
6649
+ l += utfx2.calculateCodePoint(cp);
6650
+ return l;
6651
+ };
6652
+ utfx2.calculateUTF16asUTF8 = function(src) {
6653
+ var n = 0, l = 0;
6654
+ utfx2.UTF16toUTF8(src, function(cp) {
6655
+ ++n;
6656
+ l += utfx2.calculateCodePoint(cp);
6657
+ });
6658
+ return [n, l];
6659
+ };
6660
+ return utfx2;
6661
+ })();
6662
+ Date.now = Date.now || function() {
6663
+ return +/* @__PURE__ */ new Date();
6664
+ };
6665
+ var BCRYPT_SALT_LEN = 16;
6666
+ var GENSALT_DEFAULT_LOG2_ROUNDS = 10;
6667
+ var BLOWFISH_NUM_ROUNDS = 16;
6668
+ var MAX_EXECUTION_TIME = 100;
6669
+ var P_ORIG = [
6670
+ 608135816,
6671
+ 2242054355,
6672
+ 320440878,
6673
+ 57701188,
6674
+ 2752067618,
6675
+ 698298832,
6676
+ 137296536,
6677
+ 3964562569,
6678
+ 1160258022,
6679
+ 953160567,
6680
+ 3193202383,
6681
+ 887688300,
6682
+ 3232508343,
6683
+ 3380367581,
6684
+ 1065670069,
6685
+ 3041331479,
6686
+ 2450970073,
6687
+ 2306472731
6688
+ ];
6689
+ var S_ORIG = [
6690
+ 3509652390,
6691
+ 2564797868,
6692
+ 805139163,
6693
+ 3491422135,
6694
+ 3101798381,
6695
+ 1780907670,
6696
+ 3128725573,
6697
+ 4046225305,
6698
+ 614570311,
6699
+ 3012652279,
6700
+ 134345442,
6701
+ 2240740374,
6702
+ 1667834072,
6703
+ 1901547113,
6704
+ 2757295779,
6705
+ 4103290238,
6706
+ 227898511,
6707
+ 1921955416,
6708
+ 1904987480,
6709
+ 2182433518,
6710
+ 2069144605,
6711
+ 3260701109,
6712
+ 2620446009,
6713
+ 720527379,
6714
+ 3318853667,
6715
+ 677414384,
6716
+ 3393288472,
6717
+ 3101374703,
6718
+ 2390351024,
6719
+ 1614419982,
6720
+ 1822297739,
6721
+ 2954791486,
6722
+ 3608508353,
6723
+ 3174124327,
6724
+ 2024746970,
6725
+ 1432378464,
6726
+ 3864339955,
6727
+ 2857741204,
6728
+ 1464375394,
6729
+ 1676153920,
6730
+ 1439316330,
6731
+ 715854006,
6732
+ 3033291828,
6733
+ 289532110,
6734
+ 2706671279,
6735
+ 2087905683,
6736
+ 3018724369,
6737
+ 1668267050,
6738
+ 732546397,
6739
+ 1947742710,
6740
+ 3462151702,
6741
+ 2609353502,
6742
+ 2950085171,
6743
+ 1814351708,
6744
+ 2050118529,
6745
+ 680887927,
6746
+ 999245976,
6747
+ 1800124847,
6748
+ 3300911131,
6749
+ 1713906067,
6750
+ 1641548236,
6751
+ 4213287313,
6752
+ 1216130144,
6753
+ 1575780402,
6754
+ 4018429277,
6755
+ 3917837745,
6756
+ 3693486850,
6757
+ 3949271944,
6758
+ 596196993,
6759
+ 3549867205,
6760
+ 258830323,
6761
+ 2213823033,
6762
+ 772490370,
6763
+ 2760122372,
6764
+ 1774776394,
6765
+ 2652871518,
6766
+ 566650946,
6767
+ 4142492826,
6768
+ 1728879713,
6769
+ 2882767088,
6770
+ 1783734482,
6771
+ 3629395816,
6772
+ 2517608232,
6773
+ 2874225571,
6774
+ 1861159788,
6775
+ 326777828,
6776
+ 3124490320,
6777
+ 2130389656,
6778
+ 2716951837,
6779
+ 967770486,
6780
+ 1724537150,
6781
+ 2185432712,
6782
+ 2364442137,
6783
+ 1164943284,
6784
+ 2105845187,
6785
+ 998989502,
6786
+ 3765401048,
6787
+ 2244026483,
6788
+ 1075463327,
6789
+ 1455516326,
6790
+ 1322494562,
6791
+ 910128902,
6792
+ 469688178,
6793
+ 1117454909,
6794
+ 936433444,
6795
+ 3490320968,
6796
+ 3675253459,
6797
+ 1240580251,
6798
+ 122909385,
6799
+ 2157517691,
6800
+ 634681816,
6801
+ 4142456567,
6802
+ 3825094682,
6803
+ 3061402683,
6804
+ 2540495037,
6805
+ 79693498,
6806
+ 3249098678,
6807
+ 1084186820,
6808
+ 1583128258,
6809
+ 426386531,
6810
+ 1761308591,
6811
+ 1047286709,
6812
+ 322548459,
6813
+ 995290223,
6814
+ 1845252383,
6815
+ 2603652396,
6816
+ 3431023940,
6817
+ 2942221577,
6818
+ 3202600964,
6819
+ 3727903485,
6820
+ 1712269319,
6821
+ 422464435,
6822
+ 3234572375,
6823
+ 1170764815,
6824
+ 3523960633,
6825
+ 3117677531,
6826
+ 1434042557,
6827
+ 442511882,
6828
+ 3600875718,
6829
+ 1076654713,
6830
+ 1738483198,
6831
+ 4213154764,
6832
+ 2393238008,
6833
+ 3677496056,
6834
+ 1014306527,
6835
+ 4251020053,
6836
+ 793779912,
6837
+ 2902807211,
6838
+ 842905082,
6839
+ 4246964064,
6840
+ 1395751752,
6841
+ 1040244610,
6842
+ 2656851899,
6843
+ 3396308128,
6844
+ 445077038,
6845
+ 3742853595,
6846
+ 3577915638,
6847
+ 679411651,
6848
+ 2892444358,
6849
+ 2354009459,
6850
+ 1767581616,
6851
+ 3150600392,
6852
+ 3791627101,
6853
+ 3102740896,
6854
+ 284835224,
6855
+ 4246832056,
6856
+ 1258075500,
6857
+ 768725851,
6858
+ 2589189241,
6859
+ 3069724005,
6860
+ 3532540348,
6861
+ 1274779536,
6862
+ 3789419226,
6863
+ 2764799539,
6864
+ 1660621633,
6865
+ 3471099624,
6866
+ 4011903706,
6867
+ 913787905,
6868
+ 3497959166,
6869
+ 737222580,
6870
+ 2514213453,
6871
+ 2928710040,
6872
+ 3937242737,
6873
+ 1804850592,
6874
+ 3499020752,
6875
+ 2949064160,
6876
+ 2386320175,
6877
+ 2390070455,
6878
+ 2415321851,
6879
+ 4061277028,
6880
+ 2290661394,
6881
+ 2416832540,
6882
+ 1336762016,
6883
+ 1754252060,
6884
+ 3520065937,
6885
+ 3014181293,
6886
+ 791618072,
6887
+ 3188594551,
6888
+ 3933548030,
6889
+ 2332172193,
6890
+ 3852520463,
6891
+ 3043980520,
6892
+ 413987798,
6893
+ 3465142937,
6894
+ 3030929376,
6895
+ 4245938359,
6896
+ 2093235073,
6897
+ 3534596313,
6898
+ 375366246,
6899
+ 2157278981,
6900
+ 2479649556,
6901
+ 555357303,
6902
+ 3870105701,
6903
+ 2008414854,
6904
+ 3344188149,
6905
+ 4221384143,
6906
+ 3956125452,
6907
+ 2067696032,
6908
+ 3594591187,
6909
+ 2921233993,
6910
+ 2428461,
6911
+ 544322398,
6912
+ 577241275,
6913
+ 1471733935,
6914
+ 610547355,
6915
+ 4027169054,
6916
+ 1432588573,
6917
+ 1507829418,
6918
+ 2025931657,
6919
+ 3646575487,
6920
+ 545086370,
6921
+ 48609733,
6922
+ 2200306550,
6923
+ 1653985193,
6924
+ 298326376,
6925
+ 1316178497,
6926
+ 3007786442,
6927
+ 2064951626,
6928
+ 458293330,
6929
+ 2589141269,
6930
+ 3591329599,
6931
+ 3164325604,
6932
+ 727753846,
6933
+ 2179363840,
6934
+ 146436021,
6935
+ 1461446943,
6936
+ 4069977195,
6937
+ 705550613,
6938
+ 3059967265,
6939
+ 3887724982,
6940
+ 4281599278,
6941
+ 3313849956,
6942
+ 1404054877,
6943
+ 2845806497,
6944
+ 146425753,
6945
+ 1854211946,
6946
+ 1266315497,
6947
+ 3048417604,
6948
+ 3681880366,
6949
+ 3289982499,
6950
+ 290971e4,
6951
+ 1235738493,
6952
+ 2632868024,
6953
+ 2414719590,
6954
+ 3970600049,
6955
+ 1771706367,
6956
+ 1449415276,
6957
+ 3266420449,
6958
+ 422970021,
6959
+ 1963543593,
6960
+ 2690192192,
6961
+ 3826793022,
6962
+ 1062508698,
6963
+ 1531092325,
6964
+ 1804592342,
6965
+ 2583117782,
6966
+ 2714934279,
6967
+ 4024971509,
6968
+ 1294809318,
6969
+ 4028980673,
6970
+ 1289560198,
6971
+ 2221992742,
6972
+ 1669523910,
6973
+ 35572830,
6974
+ 157838143,
6975
+ 1052438473,
6976
+ 1016535060,
6977
+ 1802137761,
6978
+ 1753167236,
6979
+ 1386275462,
6980
+ 3080475397,
6981
+ 2857371447,
6982
+ 1040679964,
6983
+ 2145300060,
6984
+ 2390574316,
6985
+ 1461121720,
6986
+ 2956646967,
6987
+ 4031777805,
6988
+ 4028374788,
6989
+ 33600511,
6990
+ 2920084762,
6991
+ 1018524850,
6992
+ 629373528,
6993
+ 3691585981,
6994
+ 3515945977,
6995
+ 2091462646,
6996
+ 2486323059,
6997
+ 586499841,
6998
+ 988145025,
6999
+ 935516892,
7000
+ 3367335476,
7001
+ 2599673255,
7002
+ 2839830854,
7003
+ 265290510,
7004
+ 3972581182,
7005
+ 2759138881,
7006
+ 3795373465,
7007
+ 1005194799,
7008
+ 847297441,
7009
+ 406762289,
7010
+ 1314163512,
7011
+ 1332590856,
7012
+ 1866599683,
7013
+ 4127851711,
7014
+ 750260880,
7015
+ 613907577,
7016
+ 1450815602,
7017
+ 3165620655,
7018
+ 3734664991,
7019
+ 3650291728,
7020
+ 3012275730,
7021
+ 3704569646,
7022
+ 1427272223,
7023
+ 778793252,
7024
+ 1343938022,
7025
+ 2676280711,
7026
+ 2052605720,
7027
+ 1946737175,
7028
+ 3164576444,
7029
+ 3914038668,
7030
+ 3967478842,
7031
+ 3682934266,
7032
+ 1661551462,
7033
+ 3294938066,
7034
+ 4011595847,
7035
+ 840292616,
7036
+ 3712170807,
7037
+ 616741398,
7038
+ 312560963,
7039
+ 711312465,
7040
+ 1351876610,
7041
+ 322626781,
7042
+ 1910503582,
7043
+ 271666773,
7044
+ 2175563734,
7045
+ 1594956187,
7046
+ 70604529,
7047
+ 3617834859,
7048
+ 1007753275,
7049
+ 1495573769,
7050
+ 4069517037,
7051
+ 2549218298,
7052
+ 2663038764,
7053
+ 504708206,
7054
+ 2263041392,
7055
+ 3941167025,
7056
+ 2249088522,
7057
+ 1514023603,
7058
+ 1998579484,
7059
+ 1312622330,
7060
+ 694541497,
7061
+ 2582060303,
7062
+ 2151582166,
7063
+ 1382467621,
7064
+ 776784248,
7065
+ 2618340202,
7066
+ 3323268794,
7067
+ 2497899128,
7068
+ 2784771155,
7069
+ 503983604,
7070
+ 4076293799,
7071
+ 907881277,
7072
+ 423175695,
7073
+ 432175456,
7074
+ 1378068232,
7075
+ 4145222326,
7076
+ 3954048622,
7077
+ 3938656102,
7078
+ 3820766613,
7079
+ 2793130115,
7080
+ 2977904593,
7081
+ 26017576,
7082
+ 3274890735,
7083
+ 3194772133,
7084
+ 1700274565,
7085
+ 1756076034,
7086
+ 4006520079,
7087
+ 3677328699,
7088
+ 720338349,
7089
+ 1533947780,
7090
+ 354530856,
7091
+ 688349552,
7092
+ 3973924725,
7093
+ 1637815568,
7094
+ 332179504,
7095
+ 3949051286,
7096
+ 53804574,
7097
+ 2852348879,
7098
+ 3044236432,
7099
+ 1282449977,
7100
+ 3583942155,
7101
+ 3416972820,
7102
+ 4006381244,
7103
+ 1617046695,
7104
+ 2628476075,
7105
+ 3002303598,
7106
+ 1686838959,
7107
+ 431878346,
7108
+ 2686675385,
7109
+ 1700445008,
7110
+ 1080580658,
7111
+ 1009431731,
7112
+ 832498133,
7113
+ 3223435511,
7114
+ 2605976345,
7115
+ 2271191193,
7116
+ 2516031870,
7117
+ 1648197032,
7118
+ 4164389018,
7119
+ 2548247927,
7120
+ 300782431,
7121
+ 375919233,
7122
+ 238389289,
7123
+ 3353747414,
7124
+ 2531188641,
7125
+ 2019080857,
7126
+ 1475708069,
7127
+ 455242339,
7128
+ 2609103871,
7129
+ 448939670,
7130
+ 3451063019,
7131
+ 1395535956,
7132
+ 2413381860,
7133
+ 1841049896,
7134
+ 1491858159,
7135
+ 885456874,
7136
+ 4264095073,
7137
+ 4001119347,
7138
+ 1565136089,
7139
+ 3898914787,
7140
+ 1108368660,
7141
+ 540939232,
7142
+ 1173283510,
7143
+ 2745871338,
7144
+ 3681308437,
7145
+ 4207628240,
7146
+ 3343053890,
7147
+ 4016749493,
7148
+ 1699691293,
7149
+ 1103962373,
7150
+ 3625875870,
7151
+ 2256883143,
7152
+ 3830138730,
7153
+ 1031889488,
7154
+ 3479347698,
7155
+ 1535977030,
7156
+ 4236805024,
7157
+ 3251091107,
7158
+ 2132092099,
7159
+ 1774941330,
7160
+ 1199868427,
7161
+ 1452454533,
7162
+ 157007616,
7163
+ 2904115357,
7164
+ 342012276,
7165
+ 595725824,
7166
+ 1480756522,
7167
+ 206960106,
7168
+ 497939518,
7169
+ 591360097,
7170
+ 863170706,
7171
+ 2375253569,
7172
+ 3596610801,
7173
+ 1814182875,
7174
+ 2094937945,
7175
+ 3421402208,
7176
+ 1082520231,
7177
+ 3463918190,
7178
+ 2785509508,
7179
+ 435703966,
7180
+ 3908032597,
7181
+ 1641649973,
7182
+ 2842273706,
7183
+ 3305899714,
7184
+ 1510255612,
7185
+ 2148256476,
7186
+ 2655287854,
7187
+ 3276092548,
7188
+ 4258621189,
7189
+ 236887753,
7190
+ 3681803219,
7191
+ 274041037,
7192
+ 1734335097,
7193
+ 3815195456,
7194
+ 3317970021,
7195
+ 1899903192,
7196
+ 1026095262,
7197
+ 4050517792,
7198
+ 356393447,
7199
+ 2410691914,
7200
+ 3873677099,
7201
+ 3682840055,
7202
+ 3913112168,
7203
+ 2491498743,
7204
+ 4132185628,
7205
+ 2489919796,
7206
+ 1091903735,
7207
+ 1979897079,
7208
+ 3170134830,
7209
+ 3567386728,
7210
+ 3557303409,
7211
+ 857797738,
7212
+ 1136121015,
7213
+ 1342202287,
7214
+ 507115054,
7215
+ 2535736646,
7216
+ 337727348,
7217
+ 3213592640,
7218
+ 1301675037,
7219
+ 2528481711,
7220
+ 1895095763,
7221
+ 1721773893,
7222
+ 3216771564,
7223
+ 62756741,
7224
+ 2142006736,
7225
+ 835421444,
7226
+ 2531993523,
7227
+ 1442658625,
7228
+ 3659876326,
7229
+ 2882144922,
7230
+ 676362277,
7231
+ 1392781812,
7232
+ 170690266,
7233
+ 3921047035,
7234
+ 1759253602,
7235
+ 3611846912,
7236
+ 1745797284,
7237
+ 664899054,
7238
+ 1329594018,
7239
+ 3901205900,
7240
+ 3045908486,
7241
+ 2062866102,
7242
+ 2865634940,
7243
+ 3543621612,
7244
+ 3464012697,
7245
+ 1080764994,
7246
+ 553557557,
7247
+ 3656615353,
7248
+ 3996768171,
7249
+ 991055499,
7250
+ 499776247,
7251
+ 1265440854,
7252
+ 648242737,
7253
+ 3940784050,
7254
+ 980351604,
7255
+ 3713745714,
7256
+ 1749149687,
7257
+ 3396870395,
7258
+ 4211799374,
7259
+ 3640570775,
7260
+ 1161844396,
7261
+ 3125318951,
7262
+ 1431517754,
7263
+ 545492359,
7264
+ 4268468663,
7265
+ 3499529547,
7266
+ 1437099964,
7267
+ 2702547544,
7268
+ 3433638243,
7269
+ 2581715763,
7270
+ 2787789398,
7271
+ 1060185593,
7272
+ 1593081372,
7273
+ 2418618748,
7274
+ 4260947970,
7275
+ 69676912,
7276
+ 2159744348,
7277
+ 86519011,
7278
+ 2512459080,
7279
+ 3838209314,
7280
+ 1220612927,
7281
+ 3339683548,
7282
+ 133810670,
7283
+ 1090789135,
7284
+ 1078426020,
7285
+ 1569222167,
7286
+ 845107691,
7287
+ 3583754449,
7288
+ 4072456591,
7289
+ 1091646820,
7290
+ 628848692,
7291
+ 1613405280,
7292
+ 3757631651,
7293
+ 526609435,
7294
+ 236106946,
7295
+ 48312990,
7296
+ 2942717905,
7297
+ 3402727701,
7298
+ 1797494240,
7299
+ 859738849,
7300
+ 992217954,
7301
+ 4005476642,
7302
+ 2243076622,
7303
+ 3870952857,
7304
+ 3732016268,
7305
+ 765654824,
7306
+ 3490871365,
7307
+ 2511836413,
7308
+ 1685915746,
7309
+ 3888969200,
7310
+ 1414112111,
7311
+ 2273134842,
7312
+ 3281911079,
7313
+ 4080962846,
7314
+ 172450625,
7315
+ 2569994100,
7316
+ 980381355,
7317
+ 4109958455,
7318
+ 2819808352,
7319
+ 2716589560,
7320
+ 2568741196,
7321
+ 3681446669,
7322
+ 3329971472,
7323
+ 1835478071,
7324
+ 660984891,
7325
+ 3704678404,
7326
+ 4045999559,
7327
+ 3422617507,
7328
+ 3040415634,
7329
+ 1762651403,
7330
+ 1719377915,
7331
+ 3470491036,
7332
+ 2693910283,
7333
+ 3642056355,
7334
+ 3138596744,
7335
+ 1364962596,
7336
+ 2073328063,
7337
+ 1983633131,
7338
+ 926494387,
7339
+ 3423689081,
7340
+ 2150032023,
7341
+ 4096667949,
7342
+ 1749200295,
7343
+ 3328846651,
7344
+ 309677260,
7345
+ 2016342300,
7346
+ 1779581495,
7347
+ 3079819751,
7348
+ 111262694,
7349
+ 1274766160,
7350
+ 443224088,
7351
+ 298511866,
7352
+ 1025883608,
7353
+ 3806446537,
7354
+ 1145181785,
7355
+ 168956806,
7356
+ 3641502830,
7357
+ 3584813610,
7358
+ 1689216846,
7359
+ 3666258015,
7360
+ 3200248200,
7361
+ 1692713982,
7362
+ 2646376535,
7363
+ 4042768518,
7364
+ 1618508792,
7365
+ 1610833997,
7366
+ 3523052358,
7367
+ 4130873264,
7368
+ 2001055236,
7369
+ 3610705100,
7370
+ 2202168115,
7371
+ 4028541809,
7372
+ 2961195399,
7373
+ 1006657119,
7374
+ 2006996926,
7375
+ 3186142756,
7376
+ 1430667929,
7377
+ 3210227297,
7378
+ 1314452623,
7379
+ 4074634658,
7380
+ 4101304120,
7381
+ 2273951170,
7382
+ 1399257539,
7383
+ 3367210612,
7384
+ 3027628629,
7385
+ 1190975929,
7386
+ 2062231137,
7387
+ 2333990788,
7388
+ 2221543033,
7389
+ 2438960610,
7390
+ 1181637006,
7391
+ 548689776,
7392
+ 2362791313,
7393
+ 3372408396,
7394
+ 3104550113,
7395
+ 3145860560,
7396
+ 296247880,
7397
+ 1970579870,
7398
+ 3078560182,
7399
+ 3769228297,
7400
+ 1714227617,
7401
+ 3291629107,
7402
+ 3898220290,
7403
+ 166772364,
7404
+ 1251581989,
7405
+ 493813264,
7406
+ 448347421,
7407
+ 195405023,
7408
+ 2709975567,
7409
+ 677966185,
7410
+ 3703036547,
7411
+ 1463355134,
7412
+ 2715995803,
7413
+ 1338867538,
7414
+ 1343315457,
7415
+ 2802222074,
7416
+ 2684532164,
7417
+ 233230375,
7418
+ 2599980071,
7419
+ 2000651841,
7420
+ 3277868038,
7421
+ 1638401717,
7422
+ 4028070440,
7423
+ 3237316320,
7424
+ 6314154,
7425
+ 819756386,
7426
+ 300326615,
7427
+ 590932579,
7428
+ 1405279636,
7429
+ 3267499572,
7430
+ 3150704214,
7431
+ 2428286686,
7432
+ 3959192993,
7433
+ 3461946742,
7434
+ 1862657033,
7435
+ 1266418056,
7436
+ 963775037,
7437
+ 2089974820,
7438
+ 2263052895,
7439
+ 1917689273,
7440
+ 448879540,
7441
+ 3550394620,
7442
+ 3981727096,
7443
+ 150775221,
7444
+ 3627908307,
7445
+ 1303187396,
7446
+ 508620638,
7447
+ 2975983352,
7448
+ 2726630617,
7449
+ 1817252668,
7450
+ 1876281319,
7451
+ 1457606340,
7452
+ 908771278,
7453
+ 3720792119,
7454
+ 3617206836,
7455
+ 2455994898,
7456
+ 1729034894,
7457
+ 1080033504,
7458
+ 976866871,
7459
+ 3556439503,
7460
+ 2881648439,
7461
+ 1522871579,
7462
+ 1555064734,
7463
+ 1336096578,
7464
+ 3548522304,
7465
+ 2579274686,
7466
+ 3574697629,
7467
+ 3205460757,
7468
+ 3593280638,
7469
+ 3338716283,
7470
+ 3079412587,
7471
+ 564236357,
7472
+ 2993598910,
7473
+ 1781952180,
7474
+ 1464380207,
7475
+ 3163844217,
7476
+ 3332601554,
7477
+ 1699332808,
7478
+ 1393555694,
7479
+ 1183702653,
7480
+ 3581086237,
7481
+ 1288719814,
7482
+ 691649499,
7483
+ 2847557200,
7484
+ 2895455976,
7485
+ 3193889540,
7486
+ 2717570544,
7487
+ 1781354906,
7488
+ 1676643554,
7489
+ 2592534050,
7490
+ 3230253752,
7491
+ 1126444790,
7492
+ 2770207658,
7493
+ 2633158820,
7494
+ 2210423226,
7495
+ 2615765581,
7496
+ 2414155088,
7497
+ 3127139286,
7498
+ 673620729,
7499
+ 2805611233,
7500
+ 1269405062,
7501
+ 4015350505,
7502
+ 3341807571,
7503
+ 4149409754,
7504
+ 1057255273,
7505
+ 2012875353,
7506
+ 2162469141,
7507
+ 2276492801,
7508
+ 2601117357,
7509
+ 993977747,
7510
+ 3918593370,
7511
+ 2654263191,
7512
+ 753973209,
7513
+ 36408145,
7514
+ 2530585658,
7515
+ 25011837,
7516
+ 3520020182,
7517
+ 2088578344,
7518
+ 530523599,
7519
+ 2918365339,
7520
+ 1524020338,
7521
+ 1518925132,
7522
+ 3760827505,
7523
+ 3759777254,
7524
+ 1202760957,
7525
+ 3985898139,
7526
+ 3906192525,
7527
+ 674977740,
7528
+ 4174734889,
7529
+ 2031300136,
7530
+ 2019492241,
7531
+ 3983892565,
7532
+ 4153806404,
7533
+ 3822280332,
7534
+ 352677332,
7535
+ 2297720250,
7536
+ 60907813,
7537
+ 90501309,
7538
+ 3286998549,
7539
+ 1016092578,
7540
+ 2535922412,
7541
+ 2839152426,
7542
+ 457141659,
7543
+ 509813237,
7544
+ 4120667899,
7545
+ 652014361,
7546
+ 1966332200,
7547
+ 2975202805,
7548
+ 55981186,
7549
+ 2327461051,
7550
+ 676427537,
7551
+ 3255491064,
7552
+ 2882294119,
7553
+ 3433927263,
7554
+ 1307055953,
7555
+ 942726286,
7556
+ 933058658,
7557
+ 2468411793,
7558
+ 3933900994,
7559
+ 4215176142,
7560
+ 1361170020,
7561
+ 2001714738,
7562
+ 2830558078,
7563
+ 3274259782,
7564
+ 1222529897,
7565
+ 1679025792,
7566
+ 2729314320,
7567
+ 3714953764,
7568
+ 1770335741,
7569
+ 151462246,
7570
+ 3013232138,
7571
+ 1682292957,
7572
+ 1483529935,
7573
+ 471910574,
7574
+ 1539241949,
7575
+ 458788160,
7576
+ 3436315007,
7577
+ 1807016891,
7578
+ 3718408830,
7579
+ 978976581,
7580
+ 1043663428,
7581
+ 3165965781,
7582
+ 1927990952,
7583
+ 4200891579,
7584
+ 2372276910,
7585
+ 3208408903,
7586
+ 3533431907,
7587
+ 1412390302,
7588
+ 2931980059,
7589
+ 4132332400,
7590
+ 1947078029,
7591
+ 3881505623,
7592
+ 4168226417,
7593
+ 2941484381,
7594
+ 1077988104,
7595
+ 1320477388,
7596
+ 886195818,
7597
+ 18198404,
7598
+ 3786409e3,
7599
+ 2509781533,
7600
+ 112762804,
7601
+ 3463356488,
7602
+ 1866414978,
7603
+ 891333506,
7604
+ 18488651,
7605
+ 661792760,
7606
+ 1628790961,
7607
+ 3885187036,
7608
+ 3141171499,
7609
+ 876946877,
7610
+ 2693282273,
7611
+ 1372485963,
7612
+ 791857591,
7613
+ 2686433993,
7614
+ 3759982718,
7615
+ 3167212022,
7616
+ 3472953795,
7617
+ 2716379847,
7618
+ 445679433,
7619
+ 3561995674,
7620
+ 3504004811,
7621
+ 3574258232,
7622
+ 54117162,
7623
+ 3331405415,
7624
+ 2381918588,
7625
+ 3769707343,
7626
+ 4154350007,
7627
+ 1140177722,
7628
+ 4074052095,
7629
+ 668550556,
7630
+ 3214352940,
7631
+ 367459370,
7632
+ 261225585,
7633
+ 2610173221,
7634
+ 4209349473,
7635
+ 3468074219,
7636
+ 3265815641,
7637
+ 314222801,
7638
+ 3066103646,
7639
+ 3808782860,
7640
+ 282218597,
7641
+ 3406013506,
7642
+ 3773591054,
7643
+ 379116347,
7644
+ 1285071038,
7645
+ 846784868,
7646
+ 2669647154,
7647
+ 3771962079,
7648
+ 3550491691,
7649
+ 2305946142,
7650
+ 453669953,
7651
+ 1268987020,
7652
+ 3317592352,
7653
+ 3279303384,
7654
+ 3744833421,
7655
+ 2610507566,
7656
+ 3859509063,
7657
+ 266596637,
7658
+ 3847019092,
7659
+ 517658769,
7660
+ 3462560207,
7661
+ 3443424879,
7662
+ 370717030,
7663
+ 4247526661,
7664
+ 2224018117,
7665
+ 4143653529,
7666
+ 4112773975,
7667
+ 2788324899,
7668
+ 2477274417,
7669
+ 1456262402,
7670
+ 2901442914,
7671
+ 1517677493,
7672
+ 1846949527,
7673
+ 2295493580,
7674
+ 3734397586,
7675
+ 2176403920,
7676
+ 1280348187,
7677
+ 1908823572,
7678
+ 3871786941,
7679
+ 846861322,
7680
+ 1172426758,
7681
+ 3287448474,
7682
+ 3383383037,
7683
+ 1655181056,
7684
+ 3139813346,
7685
+ 901632758,
7686
+ 1897031941,
7687
+ 2986607138,
7688
+ 3066810236,
7689
+ 3447102507,
7690
+ 1393639104,
7691
+ 373351379,
7692
+ 950779232,
7693
+ 625454576,
7694
+ 3124240540,
7695
+ 4148612726,
7696
+ 2007998917,
7697
+ 544563296,
7698
+ 2244738638,
7699
+ 2330496472,
7700
+ 2058025392,
7701
+ 1291430526,
7702
+ 424198748,
7703
+ 50039436,
7704
+ 29584100,
7705
+ 3605783033,
7706
+ 2429876329,
7707
+ 2791104160,
7708
+ 1057563949,
7709
+ 3255363231,
7710
+ 3075367218,
7711
+ 3463963227,
7712
+ 1469046755,
7713
+ 985887462
7714
+ ];
7715
+ var C_ORIG = [
7716
+ 1332899944,
7717
+ 1700884034,
7718
+ 1701343084,
7719
+ 1684370003,
7720
+ 1668446532,
7721
+ 1869963892
7722
+ ];
7723
+ function _encipher(lr, off, P, S) {
7724
+ var n, l = lr[off], r = lr[off + 1];
7725
+ l ^= P[0];
7726
+ n = S[l >>> 24];
7727
+ n += S[256 | l >> 16 & 255];
7728
+ n ^= S[512 | l >> 8 & 255];
7729
+ n += S[768 | l & 255];
7730
+ r ^= n ^ P[1];
7731
+ n = S[r >>> 24];
7732
+ n += S[256 | r >> 16 & 255];
7733
+ n ^= S[512 | r >> 8 & 255];
7734
+ n += S[768 | r & 255];
7735
+ l ^= n ^ P[2];
7736
+ n = S[l >>> 24];
7737
+ n += S[256 | l >> 16 & 255];
7738
+ n ^= S[512 | l >> 8 & 255];
7739
+ n += S[768 | l & 255];
7740
+ r ^= n ^ P[3];
7741
+ n = S[r >>> 24];
7742
+ n += S[256 | r >> 16 & 255];
7743
+ n ^= S[512 | r >> 8 & 255];
7744
+ n += S[768 | r & 255];
7745
+ l ^= n ^ P[4];
7746
+ n = S[l >>> 24];
7747
+ n += S[256 | l >> 16 & 255];
7748
+ n ^= S[512 | l >> 8 & 255];
7749
+ n += S[768 | l & 255];
7750
+ r ^= n ^ P[5];
7751
+ n = S[r >>> 24];
7752
+ n += S[256 | r >> 16 & 255];
7753
+ n ^= S[512 | r >> 8 & 255];
7754
+ n += S[768 | r & 255];
7755
+ l ^= n ^ P[6];
7756
+ n = S[l >>> 24];
7757
+ n += S[256 | l >> 16 & 255];
7758
+ n ^= S[512 | l >> 8 & 255];
7759
+ n += S[768 | l & 255];
7760
+ r ^= n ^ P[7];
7761
+ n = S[r >>> 24];
7762
+ n += S[256 | r >> 16 & 255];
7763
+ n ^= S[512 | r >> 8 & 255];
7764
+ n += S[768 | r & 255];
7765
+ l ^= n ^ P[8];
7766
+ n = S[l >>> 24];
7767
+ n += S[256 | l >> 16 & 255];
7768
+ n ^= S[512 | l >> 8 & 255];
7769
+ n += S[768 | l & 255];
7770
+ r ^= n ^ P[9];
7771
+ n = S[r >>> 24];
7772
+ n += S[256 | r >> 16 & 255];
7773
+ n ^= S[512 | r >> 8 & 255];
7774
+ n += S[768 | r & 255];
7775
+ l ^= n ^ P[10];
7776
+ n = S[l >>> 24];
7777
+ n += S[256 | l >> 16 & 255];
7778
+ n ^= S[512 | l >> 8 & 255];
7779
+ n += S[768 | l & 255];
7780
+ r ^= n ^ P[11];
7781
+ n = S[r >>> 24];
7782
+ n += S[256 | r >> 16 & 255];
7783
+ n ^= S[512 | r >> 8 & 255];
7784
+ n += S[768 | r & 255];
7785
+ l ^= n ^ P[12];
7786
+ n = S[l >>> 24];
7787
+ n += S[256 | l >> 16 & 255];
7788
+ n ^= S[512 | l >> 8 & 255];
7789
+ n += S[768 | l & 255];
7790
+ r ^= n ^ P[13];
7791
+ n = S[r >>> 24];
7792
+ n += S[256 | r >> 16 & 255];
7793
+ n ^= S[512 | r >> 8 & 255];
7794
+ n += S[768 | r & 255];
7795
+ l ^= n ^ P[14];
7796
+ n = S[l >>> 24];
7797
+ n += S[256 | l >> 16 & 255];
7798
+ n ^= S[512 | l >> 8 & 255];
7799
+ n += S[768 | l & 255];
7800
+ r ^= n ^ P[15];
7801
+ n = S[r >>> 24];
7802
+ n += S[256 | r >> 16 & 255];
7803
+ n ^= S[512 | r >> 8 & 255];
7804
+ n += S[768 | r & 255];
7805
+ l ^= n ^ P[16];
7806
+ lr[off] = r ^ P[BLOWFISH_NUM_ROUNDS + 1];
7807
+ lr[off + 1] = l;
7808
+ return lr;
7809
+ }
7810
+ function _streamtoword(data, offp) {
7811
+ for (var i = 0, word = 0; i < 4; ++i)
7812
+ word = word << 8 | data[offp] & 255, offp = (offp + 1) % data.length;
7813
+ return { key: word, offp };
7814
+ }
7815
+ function _key(key, P, S) {
7816
+ var offset = 0, lr = [0, 0], plen = P.length, slen = S.length, sw;
7817
+ for (var i = 0; i < plen; i++)
7818
+ sw = _streamtoword(key, offset), offset = sw.offp, P[i] = P[i] ^ sw.key;
7819
+ for (i = 0; i < plen; i += 2)
7820
+ lr = _encipher(lr, 0, P, S), P[i] = lr[0], P[i + 1] = lr[1];
7821
+ for (i = 0; i < slen; i += 2)
7822
+ lr = _encipher(lr, 0, P, S), S[i] = lr[0], S[i + 1] = lr[1];
7823
+ }
7824
+ function _ekskey(data, key, P, S) {
7825
+ var offp = 0, lr = [0, 0], plen = P.length, slen = S.length, sw;
7826
+ for (var i = 0; i < plen; i++)
7827
+ sw = _streamtoword(key, offp), offp = sw.offp, P[i] = P[i] ^ sw.key;
7828
+ offp = 0;
7829
+ for (i = 0; i < plen; i += 2)
7830
+ sw = _streamtoword(data, offp), offp = sw.offp, lr[0] ^= sw.key, sw = _streamtoword(data, offp), offp = sw.offp, lr[1] ^= sw.key, lr = _encipher(lr, 0, P, S), P[i] = lr[0], P[i + 1] = lr[1];
7831
+ for (i = 0; i < slen; i += 2)
7832
+ sw = _streamtoword(data, offp), offp = sw.offp, lr[0] ^= sw.key, sw = _streamtoword(data, offp), offp = sw.offp, lr[1] ^= sw.key, lr = _encipher(lr, 0, P, S), S[i] = lr[0], S[i + 1] = lr[1];
7833
+ }
7834
+ function _crypt(b, salt, rounds, callback, progressCallback) {
7835
+ var cdata = C_ORIG.slice(), clen = cdata.length, err;
7836
+ if (rounds < 4 || rounds > 31) {
7837
+ err = Error("Illegal number of rounds (4-31): " + rounds);
7838
+ if (callback) {
7839
+ nextTick(callback.bind(this, err));
7840
+ return;
7841
+ } else
7842
+ throw err;
7843
+ }
7844
+ if (salt.length !== BCRYPT_SALT_LEN) {
7845
+ err = Error("Illegal salt length: " + salt.length + " != " + BCRYPT_SALT_LEN);
7846
+ if (callback) {
7847
+ nextTick(callback.bind(this, err));
7848
+ return;
7849
+ } else
7850
+ throw err;
7851
+ }
7852
+ rounds = 1 << rounds >>> 0;
7853
+ var P, S, i = 0, j;
7854
+ if (Int32Array) {
7855
+ P = new Int32Array(P_ORIG);
7856
+ S = new Int32Array(S_ORIG);
7857
+ } else {
7858
+ P = P_ORIG.slice();
7859
+ S = S_ORIG.slice();
7860
+ }
7861
+ _ekskey(salt, b, P, S);
7862
+ function next() {
7863
+ if (progressCallback)
7864
+ progressCallback(i / rounds);
7865
+ if (i < rounds) {
7866
+ var start = Date.now();
7867
+ for (; i < rounds; ) {
7868
+ i = i + 1;
7869
+ _key(b, P, S);
7870
+ _key(salt, P, S);
7871
+ if (Date.now() - start > MAX_EXECUTION_TIME)
7872
+ break;
7873
+ }
7874
+ } else {
7875
+ for (i = 0; i < 64; i++)
7876
+ for (j = 0; j < clen >> 1; j++)
7877
+ _encipher(cdata, j << 1, P, S);
7878
+ var ret = [];
7879
+ for (i = 0; i < clen; i++)
7880
+ ret.push((cdata[i] >> 24 & 255) >>> 0), ret.push((cdata[i] >> 16 & 255) >>> 0), ret.push((cdata[i] >> 8 & 255) >>> 0), ret.push((cdata[i] & 255) >>> 0);
7881
+ if (callback) {
7882
+ callback(null, ret);
7883
+ return;
7884
+ } else
7885
+ return ret;
7886
+ }
7887
+ if (callback)
7888
+ nextTick(next);
7889
+ }
7890
+ if (typeof callback !== "undefined") {
7891
+ next();
7892
+ } else {
7893
+ var res;
7894
+ while (true)
7895
+ if (typeof (res = next()) !== "undefined")
7896
+ return res || [];
7897
+ }
7898
+ }
7899
+ function _hash(s, salt, callback, progressCallback) {
7900
+ var err;
7901
+ if (typeof s !== "string" || typeof salt !== "string") {
7902
+ err = Error("Invalid string / salt: Not a string");
7903
+ if (callback) {
7904
+ nextTick(callback.bind(this, err));
7905
+ return;
7906
+ } else
7907
+ throw err;
7908
+ }
7909
+ var minor, offset;
7910
+ if (salt.charAt(0) !== "$" || salt.charAt(1) !== "2") {
7911
+ err = Error("Invalid salt version: " + salt.substring(0, 2));
7912
+ if (callback) {
7913
+ nextTick(callback.bind(this, err));
7914
+ return;
7915
+ } else
7916
+ throw err;
7917
+ }
7918
+ if (salt.charAt(2) === "$")
7919
+ minor = String.fromCharCode(0), offset = 3;
7920
+ else {
7921
+ minor = salt.charAt(2);
7922
+ if (minor !== "a" && minor !== "b" && minor !== "y" || salt.charAt(3) !== "$") {
7923
+ err = Error("Invalid salt revision: " + salt.substring(2, 4));
7924
+ if (callback) {
7925
+ nextTick(callback.bind(this, err));
7926
+ return;
7927
+ } else
7928
+ throw err;
5050
7929
  }
5051
- const result = await createVisualDemo();
5052
- ctx.body = {
5053
- success: true,
5054
- message: "Demo data generated successfully",
5055
- data: result
5056
- };
5057
- } catch (error) {
5058
- strapi.log.error(`[${PLUGIN_ID}] Demo generation failed:`, error);
5059
- ctx.badRequest("Failed to generate demo data", {
5060
- error: error.message,
5061
- details: error.stack
5062
- });
7930
+ offset = 4;
5063
7931
  }
5064
- }
5065
- };
7932
+ if (salt.charAt(offset + 2) > "$") {
7933
+ err = Error("Missing salt rounds");
7934
+ if (callback) {
7935
+ nextTick(callback.bind(this, err));
7936
+ return;
7937
+ } else
7938
+ throw err;
7939
+ }
7940
+ var r1 = parseInt(salt.substring(offset, offset + 1), 10) * 10, r2 = parseInt(salt.substring(offset + 1, offset + 2), 10), rounds = r1 + r2, real_salt = salt.substring(offset + 3, offset + 25);
7941
+ s += minor >= "a" ? "\0" : "";
7942
+ var passwordb = stringToBytes(s), saltb = base64_decode(real_salt, BCRYPT_SALT_LEN);
7943
+ function finish(bytes) {
7944
+ var res = [];
7945
+ res.push("$2");
7946
+ if (minor >= "a")
7947
+ res.push(minor);
7948
+ res.push("$");
7949
+ if (rounds < 10)
7950
+ res.push("0");
7951
+ res.push(rounds.toString());
7952
+ res.push("$");
7953
+ res.push(base64_encode(saltb, saltb.length));
7954
+ res.push(base64_encode(bytes, C_ORIG.length * 4 - 1));
7955
+ return res.join("");
7956
+ }
7957
+ if (typeof callback == "undefined")
7958
+ return finish(_crypt(passwordb, saltb, rounds));
7959
+ else {
7960
+ _crypt(passwordb, saltb, rounds, function(err2, bytes) {
7961
+ if (err2)
7962
+ callback(err2, null);
7963
+ else
7964
+ callback(null, finish(bytes));
7965
+ }, progressCallback);
7966
+ }
7967
+ }
7968
+ bcrypt.encodeBase64 = base64_encode;
7969
+ bcrypt.decodeBase64 = base64_decode;
7970
+ return bcrypt;
7971
+ });
7972
+ }
7973
+ });
7974
+
7975
+ // node_modules/bcryptjs/index.js
7976
+ var require_bcryptjs = __commonJS({
7977
+ "node_modules/bcryptjs/index.js"(exports2, module2) {
7978
+ module2.exports = require_bcrypt();
5066
7979
  }
5067
7980
  });
5068
7981
 
@@ -16855,6 +19768,7 @@ var require_auth = __commonJS({
16855
19768
  "server/src/controllers/auth.js"(exports2, module2) {
16856
19769
  "use strict";
16857
19770
  var PLUGIN_ID = "webbycommerce";
19771
+ var bcrypt = require_bcryptjs();
16858
19772
  var { sendEmail } = require_send_email();
16859
19773
  var { ensureEcommercePermission } = require_check_ecommerce_permission();
16860
19774
  var getStore = () => {
@@ -17245,6 +20159,547 @@ var require_auth = __commonJS({
17245
20159
  ctx.internalServerError("Failed to verify OTP. Please try again.");
17246
20160
  }
17247
20161
  },
20162
+ /**
20163
+ * Get current authentication method
20164
+ * Returns which authentication method is currently enabled (default or otp)
20165
+ * This endpoint is public and can be used by frontend to determine which auth flow to use
20166
+ */
20167
+ async getAuthMethod(ctx) {
20168
+ try {
20169
+ const method = await getLoginMethod();
20170
+ ctx.send({
20171
+ method,
20172
+ message: `Current authentication method: ${method}`
20173
+ });
20174
+ } catch (error) {
20175
+ strapi.log.error(`[${PLUGIN_ID}] Error in getAuthMethod:`, error);
20176
+ ctx.send({
20177
+ method: "default",
20178
+ message: "Current authentication method: default"
20179
+ });
20180
+ }
20181
+ },
20182
+ /**
20183
+ * Unified Login/Register endpoint
20184
+ * Supports both OTP and default (email/password) authentication methods
20185
+ * Automatically detects which method to use based on request body
20186
+ *
20187
+ * For OTP method:
20188
+ * - First call: Send email/mobile to receive OTP (step: 'request')
20189
+ * - Second call: Verify OTP to complete login (step: 'verify')
20190
+ *
20191
+ * For Default method:
20192
+ * - Single call: Send email/username and password to login
20193
+ * - Register: Send username, email, and password to register
20194
+ */
20195
+ async unifiedAuth(ctx) {
20196
+ try {
20197
+ const hasPermission = await ensureEcommercePermission(ctx);
20198
+ if (!hasPermission) {
20199
+ return;
20200
+ }
20201
+ if (!ctx.request.body || typeof ctx.request.body !== "object") {
20202
+ return ctx.badRequest("Request body is required. Please provide authentication credentials.");
20203
+ }
20204
+ const {
20205
+ step,
20206
+ // 'request' or 'verify' for OTP, 'login' or 'register' for default
20207
+ authMethod,
20208
+ // 'otp' or 'default' (optional, auto-detected if not provided)
20209
+ // OTP fields
20210
+ email,
20211
+ mobile,
20212
+ type,
20213
+ // 'email' or 'mobile' for OTP
20214
+ otp,
20215
+ // OTP code for verification
20216
+ // Default fields
20217
+ identifier,
20218
+ // email or username for default login
20219
+ password,
20220
+ // password for default login
20221
+ username
20222
+ // username for default register
20223
+ } = ctx.request.body;
20224
+ strapi.log.debug(`[${PLUGIN_ID}] Unified auth request:`, {
20225
+ step,
20226
+ authMethod,
20227
+ hasEmail: !!email,
20228
+ hasMobile: !!mobile,
20229
+ hasType: !!type,
20230
+ hasOtp: !!otp,
20231
+ hasIdentifier: !!identifier,
20232
+ hasPassword: !!password,
20233
+ hasUsername: !!username
20234
+ });
20235
+ const configuredMethod = await getLoginMethod();
20236
+ let detectedMethod = authMethod;
20237
+ if (!detectedMethod) {
20238
+ if ((email || mobile) && type) {
20239
+ detectedMethod = "otp";
20240
+ } else if (identifier && password || username && email && password) {
20241
+ detectedMethod = "default";
20242
+ } else {
20243
+ detectedMethod = configuredMethod;
20244
+ }
20245
+ }
20246
+ if (configuredMethod !== "both") {
20247
+ if (detectedMethod === "otp" && configuredMethod !== "otp") {
20248
+ return ctx.badRequest("OTP authentication is not enabled. Please enable it in plugin settings or use the unified endpoint.");
20249
+ }
20250
+ if (detectedMethod === "default" && configuredMethod !== "default") {
20251
+ return ctx.badRequest("Default authentication is not enabled. Please enable it in plugin settings or use the unified endpoint.");
20252
+ }
20253
+ }
20254
+ if (detectedMethod === "otp") {
20255
+ if (step === "request" || !step && !otp) {
20256
+ let normalizedEmail = email?.toLowerCase();
20257
+ if (!type || type !== "email" && type !== "mobile") {
20258
+ return ctx.badRequest('Type must be "email" or "mobile" for OTP authentication.');
20259
+ }
20260
+ let identifier2 = type === "email" ? normalizedEmail : mobile;
20261
+ if (!identifier2) {
20262
+ return ctx.badRequest(
20263
+ `${type === "email" ? "Email" : "Mobile number"} is required.`
20264
+ );
20265
+ }
20266
+ let user = await strapi.db.query("plugin::users-permissions.user").findOne({
20267
+ where: type === "email" ? { email: normalizedEmail } : { phone_no: mobile }
20268
+ });
20269
+ let isNewUser = false;
20270
+ if (!user) {
20271
+ let generatedUsername = "";
20272
+ if (type === "email" && email) {
20273
+ let base = email.split("@")[0].replace(/[^a-zA-Z]/g, "").toLowerCase();
20274
+ if (!base) base = "user";
20275
+ base = base.substring(0, 4);
20276
+ const digitsNeeded = 8 - base.length;
20277
+ const min = Math.pow(10, digitsNeeded - 1);
20278
+ const max = Math.pow(10, digitsNeeded) - 1;
20279
+ let randomDigits = String(Math.floor(Math.random() * (max - min + 1)) + min);
20280
+ generatedUsername = (base + randomDigits).substring(0, 8);
20281
+ } else if (type === "mobile" && mobile) {
20282
+ const prefix = "webby";
20283
+ const randomDigits = String(Math.floor(100 + Math.random() * 900));
20284
+ generatedUsername = prefix + randomDigits;
20285
+ } else {
20286
+ generatedUsername = "user" + String(Math.floor(1e3 + Math.random() * 9e3));
20287
+ }
20288
+ const existing = await strapi.db.query("plugin::users-permissions.user").findOne({
20289
+ where: { username: generatedUsername }
20290
+ });
20291
+ if (existing) {
20292
+ if (type === "mobile") {
20293
+ generatedUsername = "webby" + String(Math.floor(100 + Math.random() * 900));
20294
+ } else {
20295
+ generatedUsername = generatedUsername.substring(0, 4) + String(Math.floor(1e3 + Math.random() * 9e3));
20296
+ generatedUsername = generatedUsername.substring(0, 8);
20297
+ }
20298
+ }
20299
+ const defaultRole = await strapi.db.query("plugin::users-permissions.role").findOne({ where: { type: "public" } });
20300
+ user = await strapi.plugin("users-permissions").service("user").add({
20301
+ email: type === "email" ? normalizedEmail : null,
20302
+ phone_no: type === "mobile" ? mobile : null,
20303
+ username: generatedUsername,
20304
+ confirmed: false,
20305
+ role: defaultRole?.id || 2
20306
+ });
20307
+ isNewUser = true;
20308
+ }
20309
+ const otpCode = Math.floor(1e5 + Math.random() * 9e5);
20310
+ const otpDigits = otpCode.toString().split("");
20311
+ try {
20312
+ const db = strapi.db;
20313
+ const knex = db.connection;
20314
+ const tableName = "up_users";
20315
+ const client = db.config.connection.client;
20316
+ if (client === "postgres") {
20317
+ await knex.raw(
20318
+ `UPDATE ${tableName} SET otp = ?, is_otp_verified = ? WHERE id = ?`,
20319
+ [otpCode, false, user.id]
20320
+ );
20321
+ } else if (client === "mysql" || client === "mysql2") {
20322
+ await knex.raw(
20323
+ `UPDATE \`${tableName}\` SET \`otp\` = ?, \`is_otp_verified\` = ? WHERE \`id\` = ?`,
20324
+ [otpCode, false, user.id]
20325
+ );
20326
+ } else {
20327
+ await knex.raw(
20328
+ `UPDATE ${tableName} SET otp = ?, is_otp_verified = ? WHERE id = ?`,
20329
+ [otpCode, false, user.id]
20330
+ );
20331
+ }
20332
+ } catch (err) {
20333
+ const { extendUserSchemaWithOtpFields } = require_extend_user_schema();
20334
+ await extendUserSchemaWithOtpFields(strapi);
20335
+ const db = strapi.db;
20336
+ const knex = db.connection;
20337
+ const tableName = "up_users";
20338
+ const client = db.config.connection.client;
20339
+ if (client === "postgres") {
20340
+ await knex.raw(
20341
+ `UPDATE ${tableName} SET otp = ?, is_otp_verified = ? WHERE id = ?`,
20342
+ [otpCode, false, user.id]
20343
+ );
20344
+ } else if (client === "mysql" || client === "mysql2") {
20345
+ await knex.raw(
20346
+ `UPDATE \`${tableName}\` SET \`otp\` = ?, \`is_otp_verified\` = ? WHERE \`id\` = ?`,
20347
+ [otpCode, false, user.id]
20348
+ );
20349
+ } else {
20350
+ await knex.raw(
20351
+ `UPDATE ${tableName} SET otp = ?, is_otp_verified = ? WHERE id = ?`,
20352
+ [otpCode, false, user.id]
20353
+ );
20354
+ }
20355
+ }
20356
+ let emailSent = false;
20357
+ if (type === "email") {
20358
+ const otpEmailHTML = `
20359
+ <!DOCTYPE html>
20360
+ <html lang="en">
20361
+ <head>
20362
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
20363
+ <meta charset="UTF-8" />
20364
+ <title>OTP Confirmation</title>
20365
+ </head>
20366
+ <body style="margin: 0; padding: 0; background-color: #f4f4f4; font-family: Arial, sans-serif;">
20367
+ <table align="center" width="100%" cellpadding="0" cellspacing="0" border="0" style="max-width: 650px; margin: 0 auto; background-color: #ffffff;">
20368
+ <tr>
20369
+ <td align="center" style="padding: 60px 20px 8px;">
20370
+ <h1 style="font-weight: bold; color: #111; font-size: 32px; margin: 0;">Your OTP Code for Secure Access</h1>
20371
+ </td>
20372
+ </tr>
20373
+ <tr>
20374
+ <td align="center" style="padding: 16px 30px;">
20375
+ <p style="font-size: 16px; color: #333333; line-height: 24px; margin: 0; max-width: 500px;">
20376
+ To complete your account verification, please use the One-Time Password (OTP) provided below. For security reasons, this OTP will expire in 10 minutes and can only be used once.
20377
+ </p>
20378
+ </td>
20379
+ </tr>
20380
+ <tr>
20381
+ <td align="center" style="padding: 30px 0;">
20382
+ <table cellpadding="0" cellspacing="0" border="0" style="margin: 0 auto;">
20383
+ <tr>
20384
+ <td style="padding: 0 6px;">
20385
+ <table cellpadding="0" cellspacing="0" border="0" style="width: 60px; height: 60px; border: 1px solid #0156D559; border-radius: 8px; background-color: #f8f9fa;">
20386
+ <tr>
20387
+ <td align="center" style="font-size: 28px; font-weight: bold; color: #111;">${otpDigits[0]}</td>
20388
+ </tr>
20389
+ </table>
20390
+ </td>
20391
+ <td style="padding: 0 6px;">
20392
+ <table cellpadding="0" cellspacing="0" border="0" style="width: 60px; height: 60px; border: 1px solid #0156D559; border-radius: 8px; background-color: #f8f9fa;">
20393
+ <tr>
20394
+ <td align="center" style="font-size: 28px; font-weight: bold; color: #111;">${otpDigits[1]}</td>
20395
+ </tr>
20396
+ </table>
20397
+ </td>
20398
+ <td style="padding: 0 6px;">
20399
+ <table cellpadding="0" cellspacing="0" border="0" style="width: 60px; height: 60px; border: 1px solid #0156D559; border-radius: 8px; background-color: #f8f9fa;">
20400
+ <tr>
20401
+ <td align="center" style="font-size: 28px; font-weight: bold; color: #111;">${otpDigits[2]}</td>
20402
+ </tr>
20403
+ </table>
20404
+ </td>
20405
+ <td style="padding: 0 6px;">
20406
+ <table cellpadding="0" cellspacing="0" border="0" style="width: 60px; height: 60px; border: 1px solid #0156D559; border-radius: 8px; background-color: #f8f9fa;">
20407
+ <tr>
20408
+ <td align="center" style="font-size: 28px; font-weight: bold; color: #111;">${otpDigits[3]}</td>
20409
+ </tr>
20410
+ </table>
20411
+ </td>
20412
+ <td style="padding: 0 6px;">
20413
+ <table cellpadding="0" cellspacing="0" border="0" style="width: 60px; height: 60px; border: 1px solid #0156D559; border-radius: 8px; background-color: #f8f9fa;">
20414
+ <tr>
20415
+ <td align="center" style="font-size: 28px; font-weight: bold; color: #111;">${otpDigits[4]}</td>
20416
+ </tr>
20417
+ </table>
20418
+ </td>
20419
+ <td style="padding: 0 6px;">
20420
+ <table cellpadding="0" cellspacing="0" border="0" style="width: 60px; height: 60px; border: 1px solid #0156D559; border-radius: 8px; background-color: #f8f9fa;">
20421
+ <tr>
20422
+ <td align="center" style="font-size: 28px; font-weight: bold; color: #111;">${otpDigits[5]}</td>
20423
+ </tr>
20424
+ </table>
20425
+ </td>
20426
+ </tr>
20427
+ </table>
20428
+ </td>
20429
+ </tr>
20430
+ </table>
20431
+ </body>
20432
+ </html>
20433
+ `;
20434
+ try {
20435
+ await sendEmail({
20436
+ to: email,
20437
+ subject: "Your OTP Code - Strapi WebbyCommerce",
20438
+ html: otpEmailHTML
20439
+ });
20440
+ emailSent = true;
20441
+ } catch (emailError) {
20442
+ strapi.log.error(
20443
+ `[${PLUGIN_ID}] Failed to send OTP email (userId: ${user.id}, email: ${email}):`,
20444
+ emailError
20445
+ );
20446
+ }
20447
+ } else if (type === "mobile") {
20448
+ strapi.log.info(`[${PLUGIN_ID}] OTP for mobile ${mobile}: ${otpCode}`);
20449
+ }
20450
+ ctx.send({
20451
+ success: true,
20452
+ step: "request",
20453
+ method: "otp",
20454
+ message: emailSent ? `OTP sent to ${type}.` : type === "email" ? "User created. OTP email could not be sent; please check email configuration on the server." : `OTP sent to ${type}.`,
20455
+ userId: user.id,
20456
+ isNewUser,
20457
+ emailSent,
20458
+ nextStep: "verify"
20459
+ });
20460
+ return;
20461
+ }
20462
+ if (step === "verify" || !step && otp) {
20463
+ if (!otp || !(type === "email" && email || type === "mobile" && mobile)) {
20464
+ return ctx.badRequest(
20465
+ `${type === "email" ? "Email" : "Mobile number"} and OTP are required.`
20466
+ );
20467
+ }
20468
+ const identifier2 = type === "email" ? email.toLowerCase() : mobile;
20469
+ const user = await strapi.db.query("plugin::users-permissions.user").findOne({
20470
+ where: { [type === "email" ? "email" : "phone_no"]: identifier2 }
20471
+ });
20472
+ if (!user) return ctx.badRequest("User not found.");
20473
+ const db = strapi.db;
20474
+ const knex = db.connection;
20475
+ const tableName = "up_users";
20476
+ const client = db.config.connection.client;
20477
+ let userOtpData;
20478
+ let columnsExist = false;
20479
+ try {
20480
+ if (client === "postgres") {
20481
+ const result = await knex.raw(
20482
+ `SELECT otp, is_otp_verified FROM ${tableName} WHERE id = ?`,
20483
+ [user.id]
20484
+ );
20485
+ userOtpData = result.rows[0];
20486
+ columnsExist = userOtpData && userOtpData.hasOwnProperty("otp") && userOtpData.hasOwnProperty("is_otp_verified");
20487
+ } else if (client === "mysql" || client === "mysql2") {
20488
+ const result = await knex.raw(
20489
+ `SELECT \`otp\`, \`is_otp_verified\` FROM \`${tableName}\` WHERE \`id\` = ?`,
20490
+ [user.id]
20491
+ );
20492
+ userOtpData = result[0][0];
20493
+ columnsExist = userOtpData && userOtpData.hasOwnProperty("otp") && userOtpData.hasOwnProperty("is_otp_verified");
20494
+ } else {
20495
+ const result = await knex.raw(
20496
+ `SELECT otp, is_otp_verified FROM ${tableName} WHERE id = ?`,
20497
+ [user.id]
20498
+ );
20499
+ userOtpData = result[0];
20500
+ columnsExist = userOtpData && userOtpData.hasOwnProperty("otp") && userOtpData.hasOwnProperty("is_otp_verified");
20501
+ }
20502
+ } catch (queryErr) {
20503
+ strapi.log.warn(`[${PLUGIN_ID}] OTP columns not found, attempting to add them:`, queryErr.message);
20504
+ columnsExist = false;
20505
+ }
20506
+ if (!columnsExist) {
20507
+ const { extendUserSchemaWithOtpFields } = require_extend_user_schema();
20508
+ await extendUserSchemaWithOtpFields(strapi);
20509
+ await new Promise((resolve) => setTimeout(resolve, 200));
20510
+ try {
20511
+ if (client === "postgres") {
20512
+ const result = await knex.raw(
20513
+ `SELECT otp, is_otp_verified FROM ${tableName} WHERE id = ?`,
20514
+ [user.id]
20515
+ );
20516
+ userOtpData = result.rows[0];
20517
+ columnsExist = userOtpData && userOtpData.hasOwnProperty("otp") && userOtpData.hasOwnProperty("is_otp_verified");
20518
+ } else if (client === "mysql" || client === "mysql2") {
20519
+ const result = await knex.raw(
20520
+ `SELECT \`otp\`, \`is_otp_verified\` FROM \`${tableName}\` WHERE \`id\` = ?`,
20521
+ [user.id]
20522
+ );
20523
+ userOtpData = result[0][0];
20524
+ columnsExist = userOtpData && userOtpData.hasOwnProperty("otp") && userOtpData.hasOwnProperty("is_otp_verified");
20525
+ } else {
20526
+ const result = await knex.raw(
20527
+ `SELECT otp, is_otp_verified FROM ${tableName} WHERE id = ?`,
20528
+ [user.id]
20529
+ );
20530
+ userOtpData = result[0];
20531
+ columnsExist = userOtpData && userOtpData.hasOwnProperty("otp") && userOtpData.hasOwnProperty("is_otp_verified");
20532
+ }
20533
+ } catch (retryErr) {
20534
+ return ctx.badRequest(
20535
+ "OTP fields are not available. Please restart Strapi after extending the user schema."
20536
+ );
20537
+ }
20538
+ }
20539
+ const userOtp = userOtpData?.otp;
20540
+ const isOtpVerified = userOtpData?.is_otp_verified;
20541
+ if (isOtpVerified) return ctx.badRequest("User already verified.");
20542
+ if (userOtp !== parseInt(otp, 10)) return ctx.badRequest("Invalid OTP.");
20543
+ try {
20544
+ if (client === "postgres") {
20545
+ await knex.raw(
20546
+ `UPDATE ${tableName} SET is_otp_verified = ?, confirmed = true, otp = NULL WHERE id = ?`,
20547
+ [true, user.id]
20548
+ );
20549
+ } else if (client === "mysql" || client === "mysql2") {
20550
+ await knex.raw(
20551
+ `UPDATE \`${tableName}\` SET \`is_otp_verified\` = ?, \`confirmed\` = true, \`otp\` = NULL WHERE \`id\` = ?`,
20552
+ [true, user.id]
20553
+ );
20554
+ } else {
20555
+ await knex.raw(
20556
+ `UPDATE ${tableName} SET is_otp_verified = ?, confirmed = 1, otp = NULL WHERE id = ?`,
20557
+ [true, user.id]
20558
+ );
20559
+ }
20560
+ } catch (dbErr) {
20561
+ strapi.log.error(`[${PLUGIN_ID}] Database error during OTP verification:`, dbErr);
20562
+ return ctx.badRequest(
20563
+ "OTP fields are not available in the user schema. Please extend the user schema as described in the plugin README."
20564
+ );
20565
+ }
20566
+ const jwt = strapi.plugins["users-permissions"].services.jwt.issue({
20567
+ id: user.id
20568
+ });
20569
+ ctx.send({
20570
+ success: true,
20571
+ step: "verify",
20572
+ method: "otp",
20573
+ message: "Login successfully!",
20574
+ jwt,
20575
+ user: {
20576
+ id: user.id,
20577
+ username: user.username,
20578
+ email: user.email,
20579
+ phone_no: user.phone_no
20580
+ }
20581
+ });
20582
+ return;
20583
+ }
20584
+ return ctx.badRequest('Invalid step for OTP authentication. Use "request" or "verify".');
20585
+ }
20586
+ if (detectedMethod === "default") {
20587
+ if (step === "login" || !step && identifier && password) {
20588
+ if (!identifier || !password) {
20589
+ return ctx.badRequest("Identifier (email/username) and password are required for login.");
20590
+ }
20591
+ const userService = strapi.plugin("users-permissions").service("user");
20592
+ const jwt = strapi.plugins["users-permissions"].services.jwt;
20593
+ const user = await strapi.db.query("plugin::users-permissions.user").findOne({
20594
+ where: {
20595
+ $or: [
20596
+ { email: identifier.toLowerCase() },
20597
+ { username: identifier }
20598
+ ]
20599
+ },
20600
+ populate: ["role"]
20601
+ });
20602
+ if (!user) {
20603
+ return ctx.badRequest("Invalid identifier or password.");
20604
+ }
20605
+ if (!user.password) {
20606
+ return ctx.badRequest("Invalid identifier or password.");
20607
+ }
20608
+ const validPassword = await bcrypt.compare(password, user.password);
20609
+ if (!validPassword) {
20610
+ return ctx.badRequest("Invalid identifier or password.");
20611
+ }
20612
+ if (user.blocked) {
20613
+ return ctx.badRequest("Your account has been blocked.");
20614
+ }
20615
+ const token = jwt.issue({
20616
+ id: user.id
20617
+ });
20618
+ ctx.send({
20619
+ success: true,
20620
+ step: "login",
20621
+ method: "default",
20622
+ message: "Login successfully!",
20623
+ jwt: token,
20624
+ user: {
20625
+ id: user.id,
20626
+ username: user.username,
20627
+ email: user.email,
20628
+ phone_no: user.phone_no,
20629
+ role: user.role ? {
20630
+ id: user.role.id,
20631
+ name: user.role.name,
20632
+ type: user.role.type
20633
+ } : null
20634
+ }
20635
+ });
20636
+ return;
20637
+ }
20638
+ if (step === "register" || !step && username && email && password) {
20639
+ if (!username || !email || !password) {
20640
+ return ctx.badRequest("Username, email, and password are required for registration.");
20641
+ }
20642
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
20643
+ if (!emailRegex.test(email.trim())) {
20644
+ return ctx.badRequest("Invalid email format.");
20645
+ }
20646
+ const existingUser = await strapi.db.query("plugin::users-permissions.user").findOne({
20647
+ where: {
20648
+ $or: [
20649
+ { email: email.toLowerCase() },
20650
+ { username }
20651
+ ]
20652
+ }
20653
+ });
20654
+ if (existingUser) {
20655
+ return ctx.badRequest("Email or username already exists.");
20656
+ }
20657
+ const defaultRole = await strapi.db.query("plugin::users-permissions.role").findOne({ where: { type: "public" } });
20658
+ const user = await strapi.plugin("users-permissions").service("user").add({
20659
+ username: username.trim(),
20660
+ email: email.trim().toLowerCase(),
20661
+ password,
20662
+ confirmed: true,
20663
+ // Auto-confirm for default method
20664
+ role: defaultRole?.id || 2
20665
+ });
20666
+ const jwt = strapi.plugins["users-permissions"].services.jwt.issue({
20667
+ id: user.id
20668
+ });
20669
+ ctx.send({
20670
+ success: true,
20671
+ step: "register",
20672
+ method: "default",
20673
+ message: "Registration successful!",
20674
+ jwt,
20675
+ user: {
20676
+ id: user.id,
20677
+ username: user.username,
20678
+ email: user.email,
20679
+ role: user.role ? {
20680
+ id: user.role.id,
20681
+ name: user.role.name,
20682
+ type: user.role.type
20683
+ } : null
20684
+ }
20685
+ });
20686
+ return;
20687
+ }
20688
+ return ctx.badRequest('Invalid step for default authentication. Use "login" or "register".');
20689
+ }
20690
+ return ctx.badRequest(
20691
+ 'Invalid request. Please provide valid authentication credentials. For OTP: provide step="request" with email/mobile and type, or step="verify" with OTP code. For default: provide step="login" with identifier and password, or step="register" with username, email, and password.'
20692
+ );
20693
+ } catch (error) {
20694
+ strapi.log.error(`[${PLUGIN_ID}] Error in unifiedAuth:`, error);
20695
+ strapi.log.error(`[${PLUGIN_ID}] Error stack:`, error.stack);
20696
+ strapi.log.error(`[${PLUGIN_ID}] Request body:`, JSON.stringify(ctx.request.body, null, 2));
20697
+ if (error.message) {
20698
+ return ctx.internalServerError(`Authentication failed: ${error.message}`);
20699
+ }
20700
+ ctx.internalServerError("Authentication failed. Please try again.");
20701
+ }
20702
+ },
17248
20703
  /**
17249
20704
  * Get authenticated user profile
17250
20705
  * Returns all user details for the authenticated user
@@ -17382,7 +20837,10 @@ var require_auth = __commonJS({
17382
20837
  if (!currentUser) {
17383
20838
  return ctx.notFound("User not found.");
17384
20839
  }
17385
- const validPassword = await strapi.plugin("users-permissions").service("users-permissions").validatePassword(currentPassword, currentUser.password);
20840
+ if (!currentUser.password) {
20841
+ return ctx.badRequest("Current password is incorrect.");
20842
+ }
20843
+ const validPassword = await bcrypt.compare(currentPassword, currentUser.password);
17386
20844
  if (!validPassword) {
17387
20845
  return ctx.badRequest("Current password is incorrect.");
17388
20846
  }
@@ -21376,7 +24834,7 @@ var require_shipping = __commonJS({
21376
24834
  availableMethods = availableMethods.concat(methods);
21377
24835
  }
21378
24836
  const uniqueMethods = availableMethods.filter(
21379
- (method, index, self) => index === self.findIndex((m) => String(m.id) === String(method.id))
24837
+ (method, index, self2) => index === self2.findIndex((m) => String(m.id) === String(method.id))
21380
24838
  );
21381
24839
  const methodsWithCosts = [];
21382
24840
  for (const method of uniqueMethods) {
@@ -21413,7 +24871,7 @@ var require_shipping = __commonJS({
21413
24871
  }
21414
24872
  const finalMethods = await applyShippingRules(methodsWithCosts, cart_items, shipping_address);
21415
24873
  const uniqueFinalMethods = finalMethods.filter(
21416
- (method, index, self) => index === self.findIndex((m) => String(m.id) === String(method.id))
24874
+ (method, index, self2) => index === self2.findIndex((m) => String(m.id) === String(method.id))
21417
24875
  );
21418
24876
  ctx.send({
21419
24877
  data: uniqueFinalMethods,
@@ -23457,7 +26915,7 @@ var require_shipping2 = __commonJS({
23457
26915
  availableMethods = availableMethods.concat(methods);
23458
26916
  }
23459
26917
  const uniqueMethods = availableMethods.filter(
23460
- (method, index, self) => index === self.findIndex((m) => String(m.id) === String(method.id))
26918
+ (method, index, self2) => index === self2.findIndex((m) => String(m.id) === String(method.id))
23461
26919
  );
23462
26920
  const methodsWithCosts = [];
23463
26921
  for (const method of uniqueMethods) {
@@ -23494,7 +26952,7 @@ var require_shipping2 = __commonJS({
23494
26952
  }
23495
26953
  const finalMethods = await this.applyShippingRules(methodsWithCosts, cartItems, shippingAddress);
23496
26954
  const uniqueFinalMethods = finalMethods.filter(
23497
- (method, index, self) => index === self.findIndex((m) => String(m.id) === String(method.id))
26955
+ (method, index, self2) => index === self2.findIndex((m) => String(m.id) === String(method.id))
23498
26956
  );
23499
26957
  return {
23500
26958
  methods: uniqueFinalMethods,
@@ -23867,3 +27325,12 @@ module.exports = {
23867
27325
  routes,
23868
27326
  services
23869
27327
  };
27328
+ /*! Bundled license information:
27329
+
27330
+ bcryptjs/dist/bcrypt.js:
27331
+ (**
27332
+ * @license bcrypt.js (c) 2013 Daniel Wirtz <dcode@dcode.io>
27333
+ * Released under the Apache License, Version 2.0
27334
+ * see: https://github.com/dcodeIO/bcrypt.js for details
27335
+ *)
27336
+ */