@famgia/omnify-laravel 0.0.83 → 0.0.85

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.
@@ -2609,6 +2609,129 @@ var SKIP_FIELDS = /* @__PURE__ */ new Set([
2609
2609
  "remember_token",
2610
2610
  "email_verified_at"
2611
2611
  ]);
2612
+ function getExampleValue(fieldName, type) {
2613
+ if (fieldName.endsWith("_lastname") && !fieldName.includes("kana")) {
2614
+ return "\u7530\u4E2D";
2615
+ }
2616
+ if (fieldName.endsWith("_firstname") && !fieldName.includes("kana")) {
2617
+ return "\u592A\u90CE";
2618
+ }
2619
+ if (fieldName.includes("kana_lastname") || fieldName.endsWith("_kana_lastname")) {
2620
+ return "\u30BF\u30CA\u30AB";
2621
+ }
2622
+ if (fieldName.includes("kana_firstname") || fieldName.endsWith("_kana_firstname")) {
2623
+ return "\u30BF\u30ED\u30A6";
2624
+ }
2625
+ if (fieldName.includes("email")) {
2626
+ return "user@example.com";
2627
+ }
2628
+ if (fieldName.includes("password")) {
2629
+ return "password123";
2630
+ }
2631
+ if (fieldName.includes("url") || fieldName.includes("website")) {
2632
+ return "https://example.com";
2633
+ }
2634
+ if (fieldName.endsWith("_id")) {
2635
+ return 1;
2636
+ }
2637
+ if (fieldName.endsWith("_at")) {
2638
+ return "2024-01-01T00:00:00Z";
2639
+ }
2640
+ if (type === "boolean") {
2641
+ return true;
2642
+ }
2643
+ if (type === "integer") {
2644
+ return 1;
2645
+ }
2646
+ return void 0;
2647
+ }
2648
+ function mapValidationToOpenApiType(rules, fieldName) {
2649
+ if (fieldName.includes("email")) {
2650
+ return { type: "string", format: "email" };
2651
+ }
2652
+ if (fieldName.includes("password")) {
2653
+ return { type: "string", format: "password" };
2654
+ }
2655
+ if (fieldName.includes("url") || fieldName.includes("website")) {
2656
+ return { type: "string", format: "uri" };
2657
+ }
2658
+ for (const rule of rules) {
2659
+ if (rule === "'integer'") {
2660
+ return { type: "integer" };
2661
+ }
2662
+ if (rule === "'boolean'") {
2663
+ return { type: "boolean" };
2664
+ }
2665
+ if (rule === "'numeric'") {
2666
+ return { type: "number" };
2667
+ }
2668
+ if (rule === "'array'") {
2669
+ return { type: "array" };
2670
+ }
2671
+ if (rule === "'email'") {
2672
+ return { type: "string", format: "email" };
2673
+ }
2674
+ if (rule === "'url'") {
2675
+ return { type: "string", format: "uri" };
2676
+ }
2677
+ if (rule === "'date'") {
2678
+ if (fieldName.endsWith("_at")) {
2679
+ return { type: "string", format: "date-time" };
2680
+ }
2681
+ return { type: "string", format: "date" };
2682
+ }
2683
+ }
2684
+ return { type: "string" };
2685
+ }
2686
+ function extractConstraints(rules) {
2687
+ const constraints = {};
2688
+ for (const rule of rules) {
2689
+ const maxMatch = rule.match(/'max:(\d+)'/);
2690
+ if (maxMatch) {
2691
+ constraints.maxLength = parseInt(maxMatch[1], 10);
2692
+ }
2693
+ const minMatch = rule.match(/'min:(\d+)'/);
2694
+ if (minMatch) {
2695
+ constraints.minLength = parseInt(minMatch[1], 10);
2696
+ }
2697
+ if (rule === "'nullable'") {
2698
+ constraints.nullable = true;
2699
+ }
2700
+ const inMatch = rule.match(/Rule::in\(\[([^\]]+)\]\)/);
2701
+ if (inMatch) {
2702
+ const values = inMatch[1].split(",").map((v) => v.trim().replace(/^'|'$/g, ""));
2703
+ constraints.enum = values;
2704
+ }
2705
+ }
2706
+ return constraints;
2707
+ }
2708
+ function formatRequestOpenApiProperty(prop, indent) {
2709
+ const parts = [`property: '${prop.property}'`, `type: '${prop.type}'`];
2710
+ if (prop.format) {
2711
+ parts.push(`format: '${prop.format}'`);
2712
+ }
2713
+ if (prop.maxLength) {
2714
+ parts.push(`maxLength: ${prop.maxLength}`);
2715
+ }
2716
+ if (prop.minLength) {
2717
+ parts.push(`minLength: ${prop.minLength}`);
2718
+ }
2719
+ if (prop.nullable) {
2720
+ parts.push(`nullable: true`);
2721
+ }
2722
+ if (prop.enum) {
2723
+ const enumStr = prop.enum.map((v) => `'${v}'`).join(", ");
2724
+ parts.push(`enum: [${enumStr}]`);
2725
+ }
2726
+ if (prop.example !== void 0) {
2727
+ if (typeof prop.example === "string") {
2728
+ parts.push(`example: '${escapePhpString2(prop.example)}'`);
2729
+ } else {
2730
+ parts.push(`example: ${prop.example}`);
2731
+ }
2732
+ }
2733
+ return `${indent}new OA\\Property(${parts.join(", ")})`;
2734
+ }
2612
2735
  function resolveOptions3(options) {
2613
2736
  return {
2614
2737
  baseRequestNamespace: options?.baseRequestNamespace ?? DEFAULT_OPTIONS2.baseRequestNamespace,
@@ -3142,12 +3265,82 @@ ${attributeLines.join("\n")}
3142
3265
  module
3143
3266
  };
3144
3267
  }
3145
- function generateStoreRequest(schema, options) {
3268
+ function generateRequestOpenApiProperties(schema, schemas, options, isStore) {
3269
+ const properties = [];
3270
+ const requiredFields = [];
3271
+ const schemaProps = schema.properties ?? {};
3272
+ for (const [propName, propDef] of Object.entries(schemaProps)) {
3273
+ const snakeName = toSnakeCase(propName);
3274
+ if (SKIP_FIELDS.has(snakeName)) continue;
3275
+ if (propDef.type === "Association") {
3276
+ const assoc = propDef;
3277
+ if (assoc.relation !== "ManyToOne" && assoc.relation !== "OneToOne") {
3278
+ continue;
3279
+ }
3280
+ const fkName = `${snakeName}_id`;
3281
+ const rules2 = isStore ? generateStoreRules(propName, propDef, schema, schemas, options) : generateUpdateRules(propName, propDef, schema, schemas, options);
3282
+ const openApiType2 = mapValidationToOpenApiType(rules2, fkName);
3283
+ const constraints2 = extractConstraints(rules2);
3284
+ const example2 = getExampleValue(fkName, openApiType2.type);
3285
+ const prop2 = {
3286
+ property: fkName,
3287
+ ...openApiType2,
3288
+ ...constraints2
3289
+ };
3290
+ if (example2 !== void 0) prop2.example = example2;
3291
+ properties.push(prop2);
3292
+ if (isStore && !propDef.nullable) {
3293
+ requiredFields.push(fkName);
3294
+ }
3295
+ continue;
3296
+ }
3297
+ const expandedFields = expandCompoundTypeFields(propName, propDef, options);
3298
+ if (expandedFields.length > 0) {
3299
+ for (const field of expandedFields) {
3300
+ const openApiType2 = mapValidationToOpenApiType(field.rules, field.fieldName);
3301
+ const constraints2 = extractConstraints(field.rules);
3302
+ const example2 = getExampleValue(field.fieldName, openApiType2.type);
3303
+ const prop2 = {
3304
+ property: field.fieldName,
3305
+ ...openApiType2,
3306
+ ...constraints2
3307
+ };
3308
+ if (example2 !== void 0) prop2.example = example2;
3309
+ properties.push(prop2);
3310
+ if (isStore && field.rules.includes("'required'")) {
3311
+ requiredFields.push(field.fieldName);
3312
+ }
3313
+ }
3314
+ continue;
3315
+ }
3316
+ const rules = isStore ? generateStoreRules(propName, propDef, schema, schemas, options) : generateUpdateRules(propName, propDef, schema, schemas, options);
3317
+ const openApiType = mapValidationToOpenApiType(rules, snakeName);
3318
+ const constraints = extractConstraints(rules);
3319
+ const example = getExampleValue(snakeName, openApiType.type);
3320
+ const prop = {
3321
+ property: snakeName,
3322
+ ...openApiType,
3323
+ ...constraints
3324
+ };
3325
+ if (example !== void 0) prop.example = example;
3326
+ properties.push(prop);
3327
+ if (isStore && rules.includes("'required'")) {
3328
+ requiredFields.push(snakeName);
3329
+ }
3330
+ }
3331
+ return { properties, requiredFields };
3332
+ }
3333
+ function generateStoreRequest(schema, schemas, options) {
3146
3334
  const className = toPascalCase(schema.name);
3147
3335
  const module = getModuleName(schema);
3148
3336
  const namespaceModule = module ? `\\${module}` : "";
3149
3337
  const namespace = `${options.requestNamespace}${namespaceModule}`;
3150
3338
  const baseNamespace = `${options.baseRequestNamespace}${namespaceModule}`;
3339
+ const { properties, requiredFields } = generateRequestOpenApiProperties(schema, schemas, options, true);
3340
+ const propsIndent = " ";
3341
+ const openApiPropsFormatted = properties.map((prop) => formatRequestOpenApiProperty(prop, propsIndent)).join(",\n");
3342
+ const requiredArray = requiredFields.length > 0 ? `
3343
+ required: [${requiredFields.map((f) => `'${f}'`).join(", ")}],` : "";
3151
3344
  const content = `<?php
3152
3345
 
3153
3346
  /**
@@ -3158,8 +3351,15 @@ function generateStoreRequest(schema, options) {
3158
3351
 
3159
3352
  namespace ${namespace};
3160
3353
 
3354
+ use OpenApi\\Attributes as OA;
3161
3355
  use ${baseNamespace}\\${className}StoreRequestBase;
3162
3356
 
3357
+ #[OA\\Schema(
3358
+ schema: '${schema.name}StoreRequest',${requiredArray}
3359
+ properties: [
3360
+ ${openApiPropsFormatted},
3361
+ ]
3362
+ )]
3163
3363
  class ${className}StoreRequest extends ${className}StoreRequestBase
3164
3364
  {
3165
3365
  /**
@@ -3217,12 +3417,15 @@ class ${className}StoreRequest extends ${className}StoreRequestBase
3217
3417
  module
3218
3418
  };
3219
3419
  }
3220
- function generateUpdateRequest(schema, options) {
3420
+ function generateUpdateRequest(schema, schemas, options) {
3221
3421
  const className = toPascalCase(schema.name);
3222
3422
  const module = getModuleName(schema);
3223
3423
  const namespaceModule = module ? `\\${module}` : "";
3224
3424
  const namespace = `${options.requestNamespace}${namespaceModule}`;
3225
3425
  const baseNamespace = `${options.baseRequestNamespace}${namespaceModule}`;
3426
+ const { properties } = generateRequestOpenApiProperties(schema, schemas, options, false);
3427
+ const propsIndent = " ";
3428
+ const openApiPropsFormatted = properties.map((prop) => formatRequestOpenApiProperty(prop, propsIndent)).join(",\n");
3226
3429
  const content = `<?php
3227
3430
 
3228
3431
  /**
@@ -3233,8 +3436,15 @@ function generateUpdateRequest(schema, options) {
3233
3436
 
3234
3437
  namespace ${namespace};
3235
3438
 
3439
+ use OpenApi\\Attributes as OA;
3236
3440
  use ${baseNamespace}\\${className}UpdateRequestBase;
3237
3441
 
3442
+ #[OA\\Schema(
3443
+ schema: '${schema.name}UpdateRequest',
3444
+ properties: [
3445
+ ${openApiPropsFormatted},
3446
+ ]
3447
+ )]
3238
3448
  class ${className}UpdateRequest extends ${className}UpdateRequestBase
3239
3449
  {
3240
3450
  /**
@@ -3300,8 +3510,8 @@ function generateRequests(schemas, options) {
3300
3510
  if (schema.options?.hidden === true) continue;
3301
3511
  requests.push(generateStoreRequestBase(schema, schemas, resolved));
3302
3512
  requests.push(generateUpdateRequestBase(schema, schemas, resolved));
3303
- requests.push(generateStoreRequest(schema, resolved));
3304
- requests.push(generateUpdateRequest(schema, resolved));
3513
+ requests.push(generateStoreRequest(schema, schemas, resolved));
3514
+ requests.push(generateUpdateRequest(schema, schemas, resolved));
3305
3515
  }
3306
3516
  return requests;
3307
3517
  }
@@ -3323,6 +3533,155 @@ var SKIP_FIELDS2 = /* @__PURE__ */ new Set([
3323
3533
  "password",
3324
3534
  "remember_token"
3325
3535
  ]);
3536
+ function mapTsTypeToOpenApi(tsType, fieldName) {
3537
+ if (fieldName.includes("email")) {
3538
+ return { type: "string", format: "email" };
3539
+ }
3540
+ switch (tsType) {
3541
+ case "string":
3542
+ return { type: "string" };
3543
+ case "number":
3544
+ return { type: "number" };
3545
+ case "boolean":
3546
+ return { type: "boolean" };
3547
+ default:
3548
+ return { type: "string" };
3549
+ }
3550
+ }
3551
+ function getOpenApiType(propDef, fieldName) {
3552
+ if (fieldName.includes("email")) {
3553
+ return { type: "string", format: "email" };
3554
+ }
3555
+ if (fieldName.includes("password")) {
3556
+ return { type: "string", format: "password" };
3557
+ }
3558
+ switch (propDef.type) {
3559
+ case "String":
3560
+ case "Text":
3561
+ case "LongText":
3562
+ return { type: "string" };
3563
+ case "Int":
3564
+ case "BigInt":
3565
+ return { type: "integer" };
3566
+ case "Float":
3567
+ case "Decimal":
3568
+ return { type: "number" };
3569
+ case "Boolean":
3570
+ return { type: "boolean" };
3571
+ case "Date":
3572
+ return { type: "string", format: "date" };
3573
+ case "DateTime":
3574
+ case "Timestamp":
3575
+ return { type: "string", format: "date-time" };
3576
+ case "Email":
3577
+ return { type: "string", format: "email" };
3578
+ case "UUID":
3579
+ return { type: "string", format: "uuid" };
3580
+ case "JSON":
3581
+ return { type: "object" };
3582
+ default:
3583
+ return { type: "string" };
3584
+ }
3585
+ }
3586
+ function generateOpenApiProperties(schema, options) {
3587
+ const properties = [];
3588
+ const schemaProps = schema.properties ?? {};
3589
+ if (schema.options?.id !== false) {
3590
+ properties.push({
3591
+ property: "id",
3592
+ type: "integer",
3593
+ example: 1
3594
+ });
3595
+ }
3596
+ for (const [propName, propDef] of Object.entries(schemaProps)) {
3597
+ const snakeName = toSnakeCase(propName);
3598
+ if (SKIP_FIELDS2.has(snakeName)) continue;
3599
+ if (propDef.hidden === true) continue;
3600
+ if (propDef.type === "Association") continue;
3601
+ const typeDef = options.customTypes.get(propDef.type);
3602
+ if (typeDef?.compound && typeDef.expand) {
3603
+ for (const field of typeDef.expand) {
3604
+ const suffixSnake = toSnakeCase(field.suffix);
3605
+ const fieldName = `${snakeName}_${suffixSnake}`;
3606
+ const tsType = field.typescript?.type ?? "string";
3607
+ const openApiType2 = mapTsTypeToOpenApi(tsType, fieldName);
3608
+ const prop2 = {
3609
+ property: fieldName,
3610
+ ...openApiType2
3611
+ };
3612
+ const sqlDef = field.sql;
3613
+ if (sqlDef?.length) {
3614
+ prop2.maxLength = sqlDef.length;
3615
+ }
3616
+ properties.push(prop2);
3617
+ }
3618
+ if (typeDef.accessors) {
3619
+ for (const accessor of typeDef.accessors) {
3620
+ const accessorName = `${snakeName}_${toSnakeCase(accessor.name)}`;
3621
+ properties.push({
3622
+ property: accessorName,
3623
+ type: "string"
3624
+ });
3625
+ }
3626
+ }
3627
+ continue;
3628
+ }
3629
+ const openApiType = getOpenApiType(propDef, snakeName);
3630
+ const prop = {
3631
+ property: snakeName,
3632
+ ...openApiType
3633
+ };
3634
+ const length = propDef.length;
3635
+ if (length) {
3636
+ prop.maxLength = length;
3637
+ }
3638
+ if (propDef.nullable) {
3639
+ prop.nullable = true;
3640
+ }
3641
+ properties.push(prop);
3642
+ }
3643
+ if (schema.options?.timestamps !== false) {
3644
+ properties.push({
3645
+ property: "created_at",
3646
+ type: "string",
3647
+ format: "date-time"
3648
+ });
3649
+ properties.push({
3650
+ property: "updated_at",
3651
+ type: "string",
3652
+ format: "date-time"
3653
+ });
3654
+ }
3655
+ if (schema.options?.softDelete) {
3656
+ properties.push({
3657
+ property: "deleted_at",
3658
+ type: "string",
3659
+ format: "date-time",
3660
+ nullable: true
3661
+ });
3662
+ }
3663
+ return properties;
3664
+ }
3665
+ function formatOpenApiProperty(prop, indent) {
3666
+ const parts = [`property: '${prop.property}'`, `type: '${prop.type}'`];
3667
+ if (prop.format) {
3668
+ parts.push(`format: '${prop.format}'`);
3669
+ }
3670
+ if (prop.maxLength) {
3671
+ parts.push(`maxLength: ${prop.maxLength}`);
3672
+ }
3673
+ if (prop.nullable) {
3674
+ parts.push(`nullable: true`);
3675
+ }
3676
+ if (prop.example !== void 0) {
3677
+ if (typeof prop.example === "string") {
3678
+ parts.push(`example: '${prop.example}'`);
3679
+ } else {
3680
+ parts.push(`example: ${prop.example}`);
3681
+ }
3682
+ }
3683
+ return `${indent}new OA\\Property(${parts.join(", ")})`;
3684
+ }
3326
3685
  function resolveOptions4(options) {
3327
3686
  return {
3328
3687
  baseResourceNamespace: options?.baseResourceNamespace ?? DEFAULT_OPTIONS3.baseResourceNamespace,
@@ -3333,6 +3692,9 @@ function resolveOptions4(options) {
3333
3692
  locale: options?.locale ?? DEFAULT_OPTIONS3.locale
3334
3693
  };
3335
3694
  }
3695
+ function escapePhpString3(str) {
3696
+ return str.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
3697
+ }
3336
3698
  function getModuleName2(schema) {
3337
3699
  if (schema.module) {
3338
3700
  return schema.module;
@@ -3480,6 +3842,10 @@ function generateResource(schema, options) {
3480
3842
  const namespaceModule = module ? `\\${module}` : "";
3481
3843
  const namespace = `${options.resourceNamespace}${namespaceModule}`;
3482
3844
  const baseNamespace = `${options.baseResourceNamespace}${namespaceModule}`;
3845
+ const openApiProps = generateOpenApiProperties(schema, options);
3846
+ const propsIndent = " ";
3847
+ const openApiPropsFormatted = openApiProps.map((prop) => formatOpenApiProperty(prop, propsIndent)).join(",\n");
3848
+ const description = schema.displayName ? typeof schema.displayName === "string" ? schema.displayName : schema.displayName["en"] ?? schema.name : `${schema.name} resource`;
3483
3849
  const content = `<?php
3484
3850
 
3485
3851
  /**
@@ -3491,8 +3857,16 @@ function generateResource(schema, options) {
3491
3857
  namespace ${namespace};
3492
3858
 
3493
3859
  use Illuminate\\Http\\Request;
3860
+ use OpenApi\\Attributes as OA;
3494
3861
  use ${baseNamespace}\\${className}ResourceBase;
3495
3862
 
3863
+ #[OA\\Schema(
3864
+ schema: '${schema.name}',
3865
+ description: '${escapePhpString3(description)}',
3866
+ properties: [
3867
+ ${openApiPropsFormatted},
3868
+ ]
3869
+ )]
3496
3870
  class ${className}Resource extends ${className}ResourceBase
3497
3871
  {
3498
3872
  /**
@@ -3842,14 +4216,22 @@ function laravelPlugin(options) {
3842
4216
  existingContent = null;
3843
4217
  }
3844
4218
  } else if (existsSync(configAppPath)) {
3845
- laravelVersion = "laravel10-";
3846
4219
  try {
3847
- existingContent = readFileSync(configAppPath, "utf-8");
4220
+ const configContent = readFileSync(configAppPath, "utf-8");
4221
+ if (/'providers'\s*=>\s*\[/.test(configContent)) {
4222
+ laravelVersion = "laravel10-";
4223
+ existingContent = configContent;
4224
+ } else {
4225
+ laravelVersion = "laravel11+";
4226
+ existingContent = null;
4227
+ }
3848
4228
  } catch {
4229
+ laravelVersion = "laravel11+";
3849
4230
  existingContent = null;
3850
4231
  }
3851
4232
  } else {
3852
4233
  laravelVersion = "laravel11+";
4234
+ existingContent = null;
3853
4235
  }
3854
4236
  const registration = generateProviderRegistration(existingContent, laravelVersion, laravelRoot);
3855
4237
  if (registration && !registration.alreadyRegistered) {
@@ -3996,4 +4378,4 @@ export {
3996
4378
  getFactoryPath,
3997
4379
  laravelPlugin
3998
4380
  };
3999
- //# sourceMappingURL=chunk-TBXCIKK7.js.map
4381
+ //# sourceMappingURL=chunk-PCQM7JIA.js.map