@famgia/omnify-laravel 0.0.84 → 0.0.86

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,157 @@ 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
+ switch (propDef.type) {
3553
+ case "Date":
3554
+ return { type: "string", format: "date" };
3555
+ case "DateTime":
3556
+ case "Timestamp":
3557
+ return { type: "string", format: "date-time" };
3558
+ }
3559
+ if (fieldName.includes("email") && !fieldName.endsWith("_at")) {
3560
+ return { type: "string", format: "email" };
3561
+ }
3562
+ if (fieldName.includes("password")) {
3563
+ return { type: "string", format: "password" };
3564
+ }
3565
+ switch (propDef.type) {
3566
+ case "String":
3567
+ case "Text":
3568
+ case "LongText":
3569
+ return { type: "string" };
3570
+ case "Int":
3571
+ case "BigInt":
3572
+ return { type: "integer" };
3573
+ case "Float":
3574
+ case "Decimal":
3575
+ return { type: "number" };
3576
+ case "Boolean":
3577
+ return { type: "boolean" };
3578
+ case "Email":
3579
+ return { type: "string", format: "email" };
3580
+ case "UUID":
3581
+ return { type: "string", format: "uuid" };
3582
+ case "JSON":
3583
+ return { type: "object" };
3584
+ default:
3585
+ return { type: "string" };
3586
+ }
3587
+ }
3588
+ function generateOpenApiProperties(schema, options) {
3589
+ const properties = [];
3590
+ const schemaProps = schema.properties ?? {};
3591
+ if (schema.options?.id !== false) {
3592
+ properties.push({
3593
+ property: "id",
3594
+ type: "integer",
3595
+ example: 1
3596
+ });
3597
+ }
3598
+ for (const [propName, propDef] of Object.entries(schemaProps)) {
3599
+ const snakeName = toSnakeCase(propName);
3600
+ if (SKIP_FIELDS2.has(snakeName)) continue;
3601
+ if (propDef.hidden === true) continue;
3602
+ if (propDef.type === "Association") continue;
3603
+ const typeDef = options.customTypes.get(propDef.type);
3604
+ if (typeDef?.compound && typeDef.expand) {
3605
+ for (const field of typeDef.expand) {
3606
+ const suffixSnake = toSnakeCase(field.suffix);
3607
+ const fieldName = `${snakeName}_${suffixSnake}`;
3608
+ const tsType = field.typescript?.type ?? "string";
3609
+ const openApiType2 = mapTsTypeToOpenApi(tsType, fieldName);
3610
+ const prop2 = {
3611
+ property: fieldName,
3612
+ ...openApiType2
3613
+ };
3614
+ const sqlDef = field.sql;
3615
+ if (sqlDef?.length) {
3616
+ prop2.maxLength = sqlDef.length;
3617
+ }
3618
+ properties.push(prop2);
3619
+ }
3620
+ if (typeDef.accessors) {
3621
+ for (const accessor of typeDef.accessors) {
3622
+ const accessorName = `${snakeName}_${toSnakeCase(accessor.name)}`;
3623
+ properties.push({
3624
+ property: accessorName,
3625
+ type: "string"
3626
+ });
3627
+ }
3628
+ }
3629
+ continue;
3630
+ }
3631
+ const openApiType = getOpenApiType(propDef, snakeName);
3632
+ const prop = {
3633
+ property: snakeName,
3634
+ ...openApiType
3635
+ };
3636
+ const length = propDef.length;
3637
+ if (length) {
3638
+ prop.maxLength = length;
3639
+ }
3640
+ if (propDef.nullable) {
3641
+ prop.nullable = true;
3642
+ }
3643
+ properties.push(prop);
3644
+ }
3645
+ if (schema.options?.timestamps !== false) {
3646
+ properties.push({
3647
+ property: "created_at",
3648
+ type: "string",
3649
+ format: "date-time"
3650
+ });
3651
+ properties.push({
3652
+ property: "updated_at",
3653
+ type: "string",
3654
+ format: "date-time"
3655
+ });
3656
+ }
3657
+ if (schema.options?.softDelete) {
3658
+ properties.push({
3659
+ property: "deleted_at",
3660
+ type: "string",
3661
+ format: "date-time",
3662
+ nullable: true
3663
+ });
3664
+ }
3665
+ return properties;
3666
+ }
3667
+ function formatOpenApiProperty(prop, indent) {
3668
+ const parts = [`property: '${prop.property}'`, `type: '${prop.type}'`];
3669
+ if (prop.format) {
3670
+ parts.push(`format: '${prop.format}'`);
3671
+ }
3672
+ if (prop.maxLength) {
3673
+ parts.push(`maxLength: ${prop.maxLength}`);
3674
+ }
3675
+ if (prop.nullable) {
3676
+ parts.push(`nullable: true`);
3677
+ }
3678
+ if (prop.example !== void 0) {
3679
+ if (typeof prop.example === "string") {
3680
+ parts.push(`example: '${prop.example}'`);
3681
+ } else {
3682
+ parts.push(`example: ${prop.example}`);
3683
+ }
3684
+ }
3685
+ return `${indent}new OA\\Property(${parts.join(", ")})`;
3686
+ }
3326
3687
  function resolveOptions4(options) {
3327
3688
  return {
3328
3689
  baseResourceNamespace: options?.baseResourceNamespace ?? DEFAULT_OPTIONS3.baseResourceNamespace,
@@ -3333,6 +3694,9 @@ function resolveOptions4(options) {
3333
3694
  locale: options?.locale ?? DEFAULT_OPTIONS3.locale
3334
3695
  };
3335
3696
  }
3697
+ function escapePhpString3(str) {
3698
+ return str.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
3699
+ }
3336
3700
  function getModuleName2(schema) {
3337
3701
  if (schema.module) {
3338
3702
  return schema.module;
@@ -3480,6 +3844,10 @@ function generateResource(schema, options) {
3480
3844
  const namespaceModule = module ? `\\${module}` : "";
3481
3845
  const namespace = `${options.resourceNamespace}${namespaceModule}`;
3482
3846
  const baseNamespace = `${options.baseResourceNamespace}${namespaceModule}`;
3847
+ const openApiProps = generateOpenApiProperties(schema, options);
3848
+ const propsIndent = " ";
3849
+ const openApiPropsFormatted = openApiProps.map((prop) => formatOpenApiProperty(prop, propsIndent)).join(",\n");
3850
+ const description = schema.displayName ? typeof schema.displayName === "string" ? schema.displayName : schema.displayName["en"] ?? schema.name : `${schema.name} resource`;
3483
3851
  const content = `<?php
3484
3852
 
3485
3853
  /**
@@ -3491,8 +3859,16 @@ function generateResource(schema, options) {
3491
3859
  namespace ${namespace};
3492
3860
 
3493
3861
  use Illuminate\\Http\\Request;
3862
+ use OpenApi\\Attributes as OA;
3494
3863
  use ${baseNamespace}\\${className}ResourceBase;
3495
3864
 
3865
+ #[OA\\Schema(
3866
+ schema: '${schema.name}',
3867
+ description: '${escapePhpString3(description)}',
3868
+ properties: [
3869
+ ${openApiPropsFormatted},
3870
+ ]
3871
+ )]
3496
3872
  class ${className}Resource extends ${className}ResourceBase
3497
3873
  {
3498
3874
  /**
@@ -4004,4 +4380,4 @@ export {
4004
4380
  getFactoryPath,
4005
4381
  laravelPlugin
4006
4382
  };
4007
- //# sourceMappingURL=chunk-KKNVSIBX.js.map
4383
+ //# sourceMappingURL=chunk-YVVAJA3T.js.map