@famgia/omnify-laravel 0.0.77 → 0.0.79

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -2571,6 +2571,610 @@ function getFactoryPath(factory) {
2571
2571
  // src/plugin.ts
2572
2572
  var import_node_fs = require("fs");
2573
2573
  var import_node_path = require("path");
2574
+
2575
+ // src/request/generator.ts
2576
+ var import_omnify_types3 = require("@famgia/omnify-types");
2577
+ var DEFAULT_OPTIONS2 = {
2578
+ baseRequestNamespace: "App\\Http\\Requests\\OmnifyBase",
2579
+ requestNamespace: "App\\Http\\Requests",
2580
+ baseRequestPath: "app/Http/Requests/OmnifyBase",
2581
+ requestPath: "app/Http/Requests",
2582
+ modelNamespace: "App\\Models",
2583
+ customTypes: /* @__PURE__ */ new Map(),
2584
+ locale: "en"
2585
+ };
2586
+ var SKIP_FIELDS = /* @__PURE__ */ new Set([
2587
+ "id",
2588
+ "created_at",
2589
+ "updated_at",
2590
+ "deleted_at",
2591
+ "remember_token",
2592
+ "email_verified_at"
2593
+ ]);
2594
+ function resolveOptions3(options) {
2595
+ return {
2596
+ baseRequestNamespace: options?.baseRequestNamespace ?? DEFAULT_OPTIONS2.baseRequestNamespace,
2597
+ requestNamespace: options?.requestNamespace ?? DEFAULT_OPTIONS2.requestNamespace,
2598
+ baseRequestPath: options?.baseRequestPath ?? DEFAULT_OPTIONS2.baseRequestPath,
2599
+ requestPath: options?.requestPath ?? DEFAULT_OPTIONS2.requestPath,
2600
+ modelNamespace: options?.modelNamespace ?? DEFAULT_OPTIONS2.modelNamespace,
2601
+ customTypes: options?.customTypes ?? /* @__PURE__ */ new Map(),
2602
+ locale: options?.locale ?? DEFAULT_OPTIONS2.locale
2603
+ };
2604
+ }
2605
+ function escapePhpString2(str) {
2606
+ return str.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
2607
+ }
2608
+ function getDisplayName(displayName, locale, fallback) {
2609
+ if (!displayName) return fallback;
2610
+ if (typeof displayName === "string") return displayName;
2611
+ if ((0, import_omnify_types3.isLocaleMap)(displayName)) {
2612
+ return displayName[locale] ?? displayName["en"] ?? fallback;
2613
+ }
2614
+ return fallback;
2615
+ }
2616
+ function getModuleName(schema) {
2617
+ if (schema.module) {
2618
+ return schema.module;
2619
+ }
2620
+ return "";
2621
+ }
2622
+ function generateStoreRules(propName, propDef, schema, schemas, options) {
2623
+ const rules = [];
2624
+ const snakeName = toSnakeCase(propName);
2625
+ const prop = propDef;
2626
+ const tableName = schema.options?.tableName ?? pluralize(toSnakeCase(schema.name));
2627
+ const isNullable2 = prop.nullable === true;
2628
+ if (!isNullable2) {
2629
+ rules.push("'required'");
2630
+ } else {
2631
+ rules.push("'nullable'");
2632
+ }
2633
+ switch (propDef.type) {
2634
+ case "String":
2635
+ case "Email":
2636
+ case "Password":
2637
+ rules.push("'string'");
2638
+ const length = prop.length ?? 255;
2639
+ rules.push(`'max:${length}'`);
2640
+ if (propDef.type === "Email") {
2641
+ rules.push("'email'");
2642
+ }
2643
+ break;
2644
+ case "Text":
2645
+ case "MediumText":
2646
+ case "LongText":
2647
+ rules.push("'string'");
2648
+ break;
2649
+ case "TinyInt":
2650
+ case "Int":
2651
+ case "BigInt":
2652
+ rules.push("'integer'");
2653
+ if (prop.min !== void 0) {
2654
+ rules.push(`'min:${prop.min}'`);
2655
+ }
2656
+ if (prop.max !== void 0) {
2657
+ rules.push(`'max:${prop.max}'`);
2658
+ }
2659
+ break;
2660
+ case "Float":
2661
+ case "Decimal":
2662
+ rules.push("'numeric'");
2663
+ if (prop.min !== void 0) {
2664
+ rules.push(`'min:${prop.min}'`);
2665
+ }
2666
+ if (prop.max !== void 0) {
2667
+ rules.push(`'max:${prop.max}'`);
2668
+ }
2669
+ break;
2670
+ case "Boolean":
2671
+ rules.push("'boolean'");
2672
+ break;
2673
+ case "Date":
2674
+ rules.push("'date'");
2675
+ break;
2676
+ case "DateTime":
2677
+ case "Timestamp":
2678
+ rules.push("'date'");
2679
+ break;
2680
+ case "Json":
2681
+ rules.push("'array'");
2682
+ break;
2683
+ case "Enum":
2684
+ case "EnumRef":
2685
+ rules.push("'string'");
2686
+ if (prop.enum && Array.isArray(prop.enum)) {
2687
+ const values = prop.enum.map((v) => `'${v}'`).join(", ");
2688
+ rules.push(`Rule::in([${values}])`);
2689
+ }
2690
+ break;
2691
+ case "Association":
2692
+ const assoc = propDef;
2693
+ if (assoc.relation === "ManyToOne" || assoc.relation === "OneToOne") {
2694
+ if (assoc.target) {
2695
+ const targetSchema = schemas[assoc.target];
2696
+ const targetTable = targetSchema?.options?.tableName ?? pluralize(toSnakeCase(assoc.target));
2697
+ rules.push("'integer'");
2698
+ rules.push(`'exists:${targetTable},id'`);
2699
+ }
2700
+ }
2701
+ break;
2702
+ }
2703
+ if (prop.unique === true) {
2704
+ rules.push(`'unique:${tableName}'`);
2705
+ }
2706
+ return rules;
2707
+ }
2708
+ function generateUpdateRules(propName, propDef, schema, schemas, options) {
2709
+ const rules = [];
2710
+ const snakeName = toSnakeCase(propName);
2711
+ const prop = propDef;
2712
+ const tableName = schema.options?.tableName ?? pluralize(toSnakeCase(schema.name));
2713
+ const modelVar = toSnakeCase(schema.name);
2714
+ rules.push("'sometimes'");
2715
+ switch (propDef.type) {
2716
+ case "String":
2717
+ case "Email":
2718
+ case "Password":
2719
+ rules.push("'string'");
2720
+ const length = prop.length ?? 255;
2721
+ rules.push(`'max:${length}'`);
2722
+ if (propDef.type === "Email") {
2723
+ rules.push("'email'");
2724
+ }
2725
+ break;
2726
+ case "Text":
2727
+ case "MediumText":
2728
+ case "LongText":
2729
+ rules.push("'string'");
2730
+ break;
2731
+ case "TinyInt":
2732
+ case "Int":
2733
+ case "BigInt":
2734
+ rules.push("'integer'");
2735
+ if (prop.min !== void 0) {
2736
+ rules.push(`'min:${prop.min}'`);
2737
+ }
2738
+ if (prop.max !== void 0) {
2739
+ rules.push(`'max:${prop.max}'`);
2740
+ }
2741
+ break;
2742
+ case "Float":
2743
+ case "Decimal":
2744
+ rules.push("'numeric'");
2745
+ if (prop.min !== void 0) {
2746
+ rules.push(`'min:${prop.min}'`);
2747
+ }
2748
+ if (prop.max !== void 0) {
2749
+ rules.push(`'max:${prop.max}'`);
2750
+ }
2751
+ break;
2752
+ case "Boolean":
2753
+ rules.push("'boolean'");
2754
+ break;
2755
+ case "Date":
2756
+ rules.push("'date'");
2757
+ break;
2758
+ case "DateTime":
2759
+ case "Timestamp":
2760
+ rules.push("'date'");
2761
+ break;
2762
+ case "Json":
2763
+ rules.push("'array'");
2764
+ break;
2765
+ case "Enum":
2766
+ case "EnumRef":
2767
+ rules.push("'string'");
2768
+ if (prop.enum && Array.isArray(prop.enum)) {
2769
+ const values = prop.enum.map((v) => `'${v}'`).join(", ");
2770
+ rules.push(`Rule::in([${values}])`);
2771
+ }
2772
+ break;
2773
+ case "Association":
2774
+ const assoc = propDef;
2775
+ if (assoc.relation === "ManyToOne" || assoc.relation === "OneToOne") {
2776
+ if (assoc.target) {
2777
+ const targetSchema = schemas[assoc.target];
2778
+ const targetTable = targetSchema?.options?.tableName ?? pluralize(toSnakeCase(assoc.target));
2779
+ rules.push("'integer'");
2780
+ rules.push(`'exists:${targetTable},id'`);
2781
+ }
2782
+ }
2783
+ break;
2784
+ }
2785
+ if (prop.unique === true) {
2786
+ rules.push(`Rule::unique('${tableName}')->ignore($this->route('${modelVar}'))`);
2787
+ }
2788
+ return rules;
2789
+ }
2790
+ function expandCompoundTypeFields(propName, propDef, options) {
2791
+ const typeDef = options.customTypes.get(propDef.type);
2792
+ if (!typeDef || !typeDef.compound || !typeDef.expand) {
2793
+ return [];
2794
+ }
2795
+ const snakeName = toSnakeCase(propName);
2796
+ const prop = propDef;
2797
+ const isNullable2 = prop.nullable === true;
2798
+ const fields = [];
2799
+ for (const field of typeDef.expand) {
2800
+ const suffixSnake = toSnakeCase(field.suffix);
2801
+ const fieldName = `${snakeName}_${suffixSnake}`;
2802
+ const fieldOverride = prop.fields?.[field.suffix];
2803
+ const fieldNullable = fieldOverride?.nullable ?? isNullable2;
2804
+ const rules = [];
2805
+ if (!fieldNullable) {
2806
+ rules.push("'required'");
2807
+ } else {
2808
+ rules.push("'nullable'");
2809
+ }
2810
+ rules.push("'string'");
2811
+ const fieldAny = field;
2812
+ const length = fieldAny.laravel?.length ?? 255;
2813
+ rules.push(`'max:${length}'`);
2814
+ fields.push({ fieldName, rules });
2815
+ }
2816
+ return fields;
2817
+ }
2818
+ function generateStoreRequestBase(schema, schemas, options) {
2819
+ const className = toPascalCase(schema.name);
2820
+ const module2 = getModuleName(schema);
2821
+ const namespaceModule = module2 ? `\\${module2}` : "";
2822
+ const namespace = `${options.baseRequestNamespace}${namespaceModule}`;
2823
+ const properties = schema.properties ?? {};
2824
+ const rulesLines = [];
2825
+ const attributeLines = [];
2826
+ const fieldList = [];
2827
+ let needsRuleImport = false;
2828
+ for (const [propName, propDef] of Object.entries(properties)) {
2829
+ const snakeName = toSnakeCase(propName);
2830
+ if (SKIP_FIELDS.has(snakeName)) continue;
2831
+ if (propDef.type === "Association") {
2832
+ const assoc = propDef;
2833
+ if (assoc.relation !== "ManyToOne" && assoc.relation !== "OneToOne") {
2834
+ continue;
2835
+ }
2836
+ const fkName = `${snakeName}_id`;
2837
+ const rules2 = generateStoreRules(propName, propDef, schema, schemas, options);
2838
+ if (rules2.some((r) => r.includes("Rule::"))) needsRuleImport = true;
2839
+ rulesLines.push(` '${fkName}' => [${rules2.join(", ")}],`);
2840
+ fieldList.push(fkName);
2841
+ const displayName2 = getDisplayName(propDef.displayName, options.locale, propName);
2842
+ attributeLines.push(` '${fkName}' => '${escapePhpString2(displayName2)}',`);
2843
+ continue;
2844
+ }
2845
+ const expandedFields = expandCompoundTypeFields(propName, propDef, options);
2846
+ if (expandedFields.length > 0) {
2847
+ for (const field of expandedFields) {
2848
+ rulesLines.push(` '${field.fieldName}' => [${field.rules.join(", ")}],`);
2849
+ fieldList.push(field.fieldName);
2850
+ attributeLines.push(` '${field.fieldName}' => '${escapePhpString2(field.fieldName)}',`);
2851
+ }
2852
+ continue;
2853
+ }
2854
+ const rules = generateStoreRules(propName, propDef, schema, schemas, options);
2855
+ if (rules.some((r) => r.includes("Rule::"))) needsRuleImport = true;
2856
+ rulesLines.push(` '${snakeName}' => [${rules.join(", ")}],`);
2857
+ fieldList.push(snakeName);
2858
+ const displayName = getDisplayName(propDef.displayName, options.locale, propName);
2859
+ attributeLines.push(` '${snakeName}' => '${escapePhpString2(displayName)}',`);
2860
+ }
2861
+ const ruleImport = needsRuleImport ? "\nuse Illuminate\\Validation\\Rule;" : "";
2862
+ const content = `<?php
2863
+
2864
+ /**
2865
+ * AUTO-GENERATED BY OMNIFY - DO NOT EDIT!
2866
+ *
2867
+ * This file is generated from Omnify schema: ${schema.name}
2868
+ * Re-run \`npx omnify generate\` to update.
2869
+ *
2870
+ * @generated
2871
+ */
2872
+
2873
+ namespace ${namespace};
2874
+
2875
+ use Illuminate\\Foundation\\Http\\FormRequest;${ruleImport}
2876
+
2877
+ abstract class ${className}StoreRequestBase extends FormRequest
2878
+ {
2879
+ /**
2880
+ * Validation rules generated from Omnify schema.
2881
+ *
2882
+ * Generated fields: ${fieldList.join(", ")}
2883
+ *
2884
+ * @return array<string, array<int, mixed>>
2885
+ */
2886
+ protected function schemaRules(): array
2887
+ {
2888
+ return [
2889
+ ${rulesLines.join("\n")}
2890
+ ];
2891
+ }
2892
+
2893
+ /**
2894
+ * Get custom attributes for validator errors.
2895
+ *
2896
+ * @return array<string, string>
2897
+ */
2898
+ protected function schemaAttributes(): array
2899
+ {
2900
+ return [
2901
+ ${attributeLines.join("\n")}
2902
+ ];
2903
+ }
2904
+ }
2905
+ `;
2906
+ const modulePath = module2 ? `/${module2}` : "";
2907
+ return {
2908
+ path: `${options.baseRequestPath}${modulePath}/${className}StoreRequestBase.php`,
2909
+ content,
2910
+ type: "store-base",
2911
+ overwrite: true,
2912
+ schemaName: schema.name,
2913
+ module: module2
2914
+ };
2915
+ }
2916
+ function generateUpdateRequestBase(schema, schemas, options) {
2917
+ const className = toPascalCase(schema.name);
2918
+ const module2 = getModuleName(schema);
2919
+ const namespaceModule = module2 ? `\\${module2}` : "";
2920
+ const namespace = `${options.baseRequestNamespace}${namespaceModule}`;
2921
+ const properties = schema.properties ?? {};
2922
+ const rulesLines = [];
2923
+ const attributeLines = [];
2924
+ let needsRuleImport = false;
2925
+ for (const [propName, propDef] of Object.entries(properties)) {
2926
+ const snakeName = toSnakeCase(propName);
2927
+ if (SKIP_FIELDS.has(snakeName)) continue;
2928
+ if (propDef.type === "Association") {
2929
+ const assoc = propDef;
2930
+ if (assoc.relation !== "ManyToOne" && assoc.relation !== "OneToOne") {
2931
+ continue;
2932
+ }
2933
+ const fkName = `${snakeName}_id`;
2934
+ const rules2 = generateUpdateRules(propName, propDef, schema, schemas, options);
2935
+ if (rules2.some((r) => r.includes("Rule::") || r.includes("Rule::"))) needsRuleImport = true;
2936
+ rulesLines.push(` '${fkName}' => [${rules2.join(", ")}],`);
2937
+ const displayName2 = getDisplayName(propDef.displayName, options.locale, propName);
2938
+ attributeLines.push(` '${fkName}' => '${escapePhpString2(displayName2)}',`);
2939
+ continue;
2940
+ }
2941
+ const expandedFields = expandCompoundTypeFields(propName, propDef, options);
2942
+ if (expandedFields.length > 0) {
2943
+ for (const field of expandedFields) {
2944
+ const updateRules = field.rules.map((r) => r === "'required'" ? "'sometimes'" : r);
2945
+ rulesLines.push(` '${field.fieldName}' => [${updateRules.join(", ")}],`);
2946
+ attributeLines.push(` '${field.fieldName}' => '${escapePhpString2(field.fieldName)}',`);
2947
+ }
2948
+ continue;
2949
+ }
2950
+ const rules = generateUpdateRules(propName, propDef, schema, schemas, options);
2951
+ if (rules.some((r) => r.includes("Rule::") || r.includes("Rule::"))) needsRuleImport = true;
2952
+ rulesLines.push(` '${snakeName}' => [${rules.join(", ")}],`);
2953
+ const displayName = getDisplayName(propDef.displayName, options.locale, propName);
2954
+ attributeLines.push(` '${snakeName}' => '${escapePhpString2(displayName)}',`);
2955
+ }
2956
+ const ruleImport = needsRuleImport ? "\nuse Illuminate\\Validation\\Rule;" : "";
2957
+ const content = `<?php
2958
+
2959
+ /**
2960
+ * AUTO-GENERATED BY OMNIFY - DO NOT EDIT!
2961
+ *
2962
+ * This file is generated from Omnify schema: ${schema.name}
2963
+ * Re-run \`npx omnify generate\` to update.
2964
+ *
2965
+ * @generated
2966
+ */
2967
+
2968
+ namespace ${namespace};
2969
+
2970
+ use Illuminate\\Foundation\\Http\\FormRequest;${ruleImport}
2971
+
2972
+ abstract class ${className}UpdateRequestBase extends FormRequest
2973
+ {
2974
+ /**
2975
+ * Validation rules generated from Omnify schema.
2976
+ * All fields use 'sometimes' for partial updates.
2977
+ *
2978
+ * @return array<string, array<int, mixed>>
2979
+ */
2980
+ protected function schemaRules(): array
2981
+ {
2982
+ return [
2983
+ ${rulesLines.join("\n")}
2984
+ ];
2985
+ }
2986
+
2987
+ /**
2988
+ * Get custom attributes for validator errors.
2989
+ *
2990
+ * @return array<string, string>
2991
+ */
2992
+ protected function schemaAttributes(): array
2993
+ {
2994
+ return [
2995
+ ${attributeLines.join("\n")}
2996
+ ];
2997
+ }
2998
+ }
2999
+ `;
3000
+ const modulePath = module2 ? `/${module2}` : "";
3001
+ return {
3002
+ path: `${options.baseRequestPath}${modulePath}/${className}UpdateRequestBase.php`,
3003
+ content,
3004
+ type: "update-base",
3005
+ overwrite: true,
3006
+ schemaName: schema.name,
3007
+ module: module2
3008
+ };
3009
+ }
3010
+ function generateStoreRequest(schema, options) {
3011
+ const className = toPascalCase(schema.name);
3012
+ const module2 = getModuleName(schema);
3013
+ const namespaceModule = module2 ? `\\${module2}` : "";
3014
+ const namespace = `${options.requestNamespace}${namespaceModule}`;
3015
+ const baseNamespace = `${options.baseRequestNamespace}${namespaceModule}`;
3016
+ const content = `<?php
3017
+
3018
+ /**
3019
+ * ${className} Store Request
3020
+ *
3021
+ * SAFE TO EDIT - This file is never overwritten by Omnify.
3022
+ */
3023
+
3024
+ namespace ${namespace};
3025
+
3026
+ use ${baseNamespace}\\${className}StoreRequestBase;
3027
+
3028
+ class ${className}StoreRequest extends ${className}StoreRequestBase
3029
+ {
3030
+ /**
3031
+ * Determine if the user is authorized to make this request.
3032
+ */
3033
+ public function authorize(): bool
3034
+ {
3035
+ return true;
3036
+ }
3037
+
3038
+ /**
3039
+ * Get the validation rules that apply to the request.
3040
+ *
3041
+ * @return array<string, array<int, mixed>>
3042
+ */
3043
+ public function rules(): array
3044
+ {
3045
+ return array_merge($this->schemaRules(), [
3046
+ // Custom/override rules here
3047
+ ]);
3048
+ }
3049
+
3050
+ /**
3051
+ * Get custom attributes for validator errors.
3052
+ *
3053
+ * @return array<string, string>
3054
+ */
3055
+ public function attributes(): array
3056
+ {
3057
+ return array_merge($this->schemaAttributes(), [
3058
+ // Custom attributes here
3059
+ ]);
3060
+ }
3061
+
3062
+ /**
3063
+ * Get custom messages for validator errors.
3064
+ *
3065
+ * @return array<string, string>
3066
+ */
3067
+ public function messages(): array
3068
+ {
3069
+ return [
3070
+ // Custom messages here
3071
+ ];
3072
+ }
3073
+ }
3074
+ `;
3075
+ const modulePath = module2 ? `/${module2}` : "";
3076
+ return {
3077
+ path: `${options.requestPath}${modulePath}/${className}StoreRequest.php`,
3078
+ content,
3079
+ type: "store",
3080
+ overwrite: false,
3081
+ schemaName: schema.name,
3082
+ module: module2
3083
+ };
3084
+ }
3085
+ function generateUpdateRequest(schema, options) {
3086
+ const className = toPascalCase(schema.name);
3087
+ const module2 = getModuleName(schema);
3088
+ const namespaceModule = module2 ? `\\${module2}` : "";
3089
+ const namespace = `${options.requestNamespace}${namespaceModule}`;
3090
+ const baseNamespace = `${options.baseRequestNamespace}${namespaceModule}`;
3091
+ const content = `<?php
3092
+
3093
+ /**
3094
+ * ${className} Update Request
3095
+ *
3096
+ * SAFE TO EDIT - This file is never overwritten by Omnify.
3097
+ */
3098
+
3099
+ namespace ${namespace};
3100
+
3101
+ use ${baseNamespace}\\${className}UpdateRequestBase;
3102
+
3103
+ class ${className}UpdateRequest extends ${className}UpdateRequestBase
3104
+ {
3105
+ /**
3106
+ * Determine if the user is authorized to make this request.
3107
+ */
3108
+ public function authorize(): bool
3109
+ {
3110
+ return true;
3111
+ }
3112
+
3113
+ /**
3114
+ * Get the validation rules that apply to the request.
3115
+ *
3116
+ * @return array<string, array<int, mixed>>
3117
+ */
3118
+ public function rules(): array
3119
+ {
3120
+ return array_merge($this->schemaRules(), [
3121
+ // Custom/override rules here
3122
+ ]);
3123
+ }
3124
+
3125
+ /**
3126
+ * Get custom attributes for validator errors.
3127
+ *
3128
+ * @return array<string, string>
3129
+ */
3130
+ public function attributes(): array
3131
+ {
3132
+ return array_merge($this->schemaAttributes(), [
3133
+ // Custom attributes here
3134
+ ]);
3135
+ }
3136
+
3137
+ /**
3138
+ * Get custom messages for validator errors.
3139
+ *
3140
+ * @return array<string, string>
3141
+ */
3142
+ public function messages(): array
3143
+ {
3144
+ return [
3145
+ // Custom messages here
3146
+ ];
3147
+ }
3148
+ }
3149
+ `;
3150
+ const modulePath = module2 ? `/${module2}` : "";
3151
+ return {
3152
+ path: `${options.requestPath}${modulePath}/${className}UpdateRequest.php`,
3153
+ content,
3154
+ type: "update",
3155
+ overwrite: false,
3156
+ schemaName: schema.name,
3157
+ module: module2
3158
+ };
3159
+ }
3160
+ function generateRequests(schemas, options) {
3161
+ const resolved = resolveOptions3(options);
3162
+ const requests = [];
3163
+ for (const schema of Object.values(schemas)) {
3164
+ if (schema.kind === "enum") continue;
3165
+ if (schema.options?.hidden === true) continue;
3166
+ requests.push(generateStoreRequestBase(schema, schemas, resolved));
3167
+ requests.push(generateUpdateRequestBase(schema, schemas, resolved));
3168
+ requests.push(generateStoreRequest(schema, resolved));
3169
+ requests.push(generateUpdateRequest(schema, resolved));
3170
+ }
3171
+ return requests;
3172
+ }
3173
+ function getRequestPath(request) {
3174
+ return request.path;
3175
+ }
3176
+
3177
+ // src/plugin.ts
2574
3178
  function getExistingMigrationTables(migrationsDir) {
2575
3179
  const existingTables = /* @__PURE__ */ new Set();
2576
3180
  if (!(0, import_node_fs.existsSync)(migrationsDir)) {
@@ -2654,10 +3258,34 @@ var LARAVEL_CONFIG_SCHEMA = {
2654
3258
  description: "Laravel database connection name (optional)",
2655
3259
  placeholder: "mysql",
2656
3260
  group: "options"
3261
+ },
3262
+ {
3263
+ key: "requestsPath",
3264
+ type: "path",
3265
+ label: "Requests Path",
3266
+ description: "Directory for user-editable FormRequest files",
3267
+ default: "app/Http/Requests",
3268
+ group: "output"
3269
+ },
3270
+ {
3271
+ key: "baseRequestsPath",
3272
+ type: "path",
3273
+ label: "Base Requests Path",
3274
+ description: "Directory for auto-generated base FormRequest files",
3275
+ default: "app/Http/Requests/OmnifyBase",
3276
+ group: "output"
3277
+ },
3278
+ {
3279
+ key: "generateRequests",
3280
+ type: "boolean",
3281
+ label: "Generate Requests",
3282
+ description: "Generate Laravel FormRequest classes for validation",
3283
+ default: false,
3284
+ group: "options"
2657
3285
  }
2658
3286
  ]
2659
3287
  };
2660
- function resolveOptions3(options) {
3288
+ function resolveOptions4(options) {
2661
3289
  return {
2662
3290
  migrationsPath: options?.migrationsPath ?? "database/migrations/omnify",
2663
3291
  modelsPath: options?.modelsPath ?? "app/Models",
@@ -2670,11 +3298,16 @@ function resolveOptions3(options) {
2670
3298
  generateFactories: options?.generateFactories ?? true,
2671
3299
  fakerLocale: options?.fakerLocale ?? "en_US",
2672
3300
  connection: options?.connection,
2673
- timestamp: options?.timestamp
3301
+ timestamp: options?.timestamp,
3302
+ requestsPath: options?.requestsPath ?? "app/Http/Requests",
3303
+ baseRequestsPath: options?.baseRequestsPath ?? "app/Http/Requests/OmnifyBase",
3304
+ requestNamespace: options?.requestNamespace ?? "App\\Http\\Requests",
3305
+ baseRequestNamespace: options?.baseRequestNamespace ?? "App\\Http\\Requests\\OmnifyBase",
3306
+ generateRequests: options?.generateRequests ?? false
2674
3307
  };
2675
3308
  }
2676
3309
  function laravelPlugin(options) {
2677
- const resolved = resolveOptions3(options);
3310
+ const resolved = resolveOptions4(options);
2678
3311
  const migrationGenerator = {
2679
3312
  name: "laravel-migrations",
2680
3313
  description: "Generate Laravel migration files",
@@ -2846,6 +3479,33 @@ function laravelPlugin(options) {
2846
3479
  }));
2847
3480
  }
2848
3481
  };
3482
+ const requestGenerator = {
3483
+ name: "laravel-requests",
3484
+ description: "Generate Laravel FormRequest classes for validation",
3485
+ generate: async (ctx) => {
3486
+ const requestOptions = {
3487
+ requestNamespace: resolved.requestNamespace,
3488
+ baseRequestNamespace: resolved.baseRequestNamespace,
3489
+ requestPath: resolved.requestsPath,
3490
+ baseRequestPath: resolved.baseRequestsPath,
3491
+ modelNamespace: resolved.modelNamespace,
3492
+ customTypes: ctx.customTypes
3493
+ };
3494
+ const requests = generateRequests(ctx.schemas, requestOptions);
3495
+ return requests.map((request) => ({
3496
+ path: getRequestPath(request),
3497
+ content: request.content,
3498
+ type: "other",
3499
+ // Skip writing user requests if they already exist
3500
+ skipIfExists: !request.overwrite,
3501
+ metadata: {
3502
+ requestType: request.type,
3503
+ schemaName: request.schemaName,
3504
+ module: request.module
3505
+ }
3506
+ }));
3507
+ }
3508
+ };
2849
3509
  const generators = [migrationGenerator];
2850
3510
  if (resolved.generateModels) {
2851
3511
  generators.push(modelGenerator);
@@ -2853,6 +3513,9 @@ function laravelPlugin(options) {
2853
3513
  if (resolved.generateFactories) {
2854
3514
  generators.push(factoryGenerator);
2855
3515
  }
3516
+ if (resolved.generateRequests) {
3517
+ generators.push(requestGenerator);
3518
+ }
2856
3519
  return {
2857
3520
  name: "@famgia/omnify-laravel",
2858
3521
  version: "0.0.14",