@famgia/omnify-cli 0.0.85 → 0.0.87
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/cli.js +109 -494
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +92 -479
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +105 -492
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/dist/index.cjs
CHANGED
|
@@ -122,11 +122,14 @@ async function resolveConfig(userConfig, configPath) {
|
|
|
122
122
|
migrationsPath: userConfig.output?.laravel?.migrationsPath ?? "database/migrations"
|
|
123
123
|
};
|
|
124
124
|
const laravel = buildLaravelConfig(laravelConfig, userConfig.output?.laravel);
|
|
125
|
+
const tsConfig = userConfig.output?.typescript;
|
|
125
126
|
const typescript = {
|
|
126
|
-
path:
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
127
|
+
path: tsConfig?.path ?? "types",
|
|
128
|
+
schemasDir: tsConfig?.schemasDir ?? "schemas",
|
|
129
|
+
enumDir: tsConfig?.enumDir ?? "enum",
|
|
130
|
+
singleFile: tsConfig?.singleFile ?? true,
|
|
131
|
+
generateEnums: tsConfig?.generateEnums ?? true,
|
|
132
|
+
generateRelationships: tsConfig?.generateRelationships ?? true
|
|
130
133
|
};
|
|
131
134
|
const result = {
|
|
132
135
|
schemasDir: userConfig.schemasDir ?? "./schemas",
|
|
@@ -724,475 +727,24 @@ var CLAUDE_MD = `## Omnify
|
|
|
724
727
|
This project uses Omnify for schema-driven code generation.
|
|
725
728
|
|
|
726
729
|
**Documentation**: \`.claude/omnify/\`
|
|
727
|
-
- \`
|
|
728
|
-
- \`laravel
|
|
729
|
-
- \`
|
|
730
|
-
- \`
|
|
730
|
+
- \`guides/omnify/\` - Omnify tool docs (schema syntax, config)
|
|
731
|
+
- \`guides/laravel/\` - Laravel implementation guides
|
|
732
|
+
- \`guides/react/\` - React implementation guides
|
|
733
|
+
- \`checklists/\` - Development checklists
|
|
734
|
+
- \`workflows/\` - Workflow guides
|
|
735
|
+
- \`agents/\` - AI agent prompts
|
|
731
736
|
|
|
732
737
|
**Commands**:
|
|
733
738
|
- \`npx omnify generate\` - Generate code from schemas
|
|
734
739
|
- \`npx omnify validate\` - Validate schemas
|
|
735
740
|
`;
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
## Schema File Format
|
|
739
|
-
|
|
740
|
-
Schemas are YAML files defining data models. Each file represents one entity.
|
|
741
|
-
|
|
742
|
-
\`\`\`yaml
|
|
743
|
-
name: User
|
|
744
|
-
displayName:
|
|
745
|
-
ja: \u30E6\u30FC\u30B6\u30FC
|
|
746
|
-
en: User
|
|
747
|
-
kind: object
|
|
748
|
-
|
|
749
|
-
properties:
|
|
750
|
-
email:
|
|
751
|
-
type: Email
|
|
752
|
-
unique: true
|
|
753
|
-
name:
|
|
754
|
-
type: String
|
|
755
|
-
bio:
|
|
756
|
-
type: Text
|
|
757
|
-
nullable: true
|
|
758
|
-
|
|
759
|
-
options:
|
|
760
|
-
timestamps: true
|
|
761
|
-
softDelete: true
|
|
762
|
-
\`\`\`
|
|
763
|
-
|
|
764
|
-
## Property Types
|
|
765
|
-
|
|
766
|
-
### String Types
|
|
767
|
-
- \`String\` - VARCHAR(255)
|
|
768
|
-
- \`Text\` - TEXT
|
|
769
|
-
- \`LongText\` - LONGTEXT
|
|
770
|
-
- \`Email\` - VARCHAR(255) for email addresses
|
|
771
|
-
- \`Password\` - VARCHAR(255), hidden in serialization
|
|
772
|
-
|
|
773
|
-
### Numeric Types
|
|
774
|
-
- \`Int\` - INTEGER
|
|
775
|
-
- \`BigInt\` - BIGINT
|
|
776
|
-
- \`TinyInt\` - TINYINT
|
|
777
|
-
- \`Float\` - DOUBLE
|
|
778
|
-
- \`Decimal\` - DECIMAL(precision, scale)
|
|
779
|
-
|
|
780
|
-
### Date/Time Types
|
|
781
|
-
- \`Date\` - DATE
|
|
782
|
-
- \`Time\` - TIME
|
|
783
|
-
- \`DateTime\` - DATETIME
|
|
784
|
-
- \`Timestamp\` - TIMESTAMP
|
|
785
|
-
|
|
786
|
-
### Other Types
|
|
787
|
-
- \`Boolean\` - BOOLEAN
|
|
788
|
-
- \`Json\` - JSON
|
|
789
|
-
- \`Enum\` - ENUM with values
|
|
790
|
-
- \`EnumRef\` - Reference to enum schema
|
|
791
|
-
|
|
792
|
-
## Property Options
|
|
793
|
-
|
|
794
|
-
\`\`\`yaml
|
|
795
|
-
propertyName:
|
|
796
|
-
type: String
|
|
797
|
-
nullable: true # Can be NULL
|
|
798
|
-
unique: true # Unique constraint
|
|
799
|
-
default: "value" # Default value
|
|
800
|
-
length: 100 # VARCHAR length
|
|
801
|
-
hidden: true # Hide from JSON output
|
|
802
|
-
fillable: false # Exclude from mass assignment
|
|
803
|
-
\`\`\`
|
|
804
|
-
|
|
805
|
-
## Associations
|
|
806
|
-
|
|
807
|
-
\`\`\`yaml
|
|
808
|
-
# Many-to-One (belongsTo)
|
|
809
|
-
author:
|
|
810
|
-
type: Association
|
|
811
|
-
relation: ManyToOne
|
|
812
|
-
target: User
|
|
813
|
-
onDelete: CASCADE
|
|
814
|
-
|
|
815
|
-
# One-to-Many (hasMany)
|
|
816
|
-
posts:
|
|
817
|
-
type: Association
|
|
818
|
-
relation: OneToMany
|
|
819
|
-
target: Post
|
|
820
|
-
|
|
821
|
-
# Many-to-Many (belongsToMany)
|
|
822
|
-
tags:
|
|
823
|
-
type: Association
|
|
824
|
-
relation: ManyToMany
|
|
825
|
-
target: Tag
|
|
826
|
-
joinTable: post_tags
|
|
827
|
-
|
|
828
|
-
# Polymorphic
|
|
829
|
-
commentable:
|
|
830
|
-
type: Association
|
|
831
|
-
relation: MorphTo
|
|
832
|
-
\`\`\`
|
|
833
|
-
|
|
834
|
-
## Indexes
|
|
835
|
-
|
|
836
|
-
\`\`\`yaml
|
|
837
|
-
indexes:
|
|
838
|
-
- columns: [status, published_at]
|
|
839
|
-
- columns: [email]
|
|
840
|
-
unique: true
|
|
841
|
-
\`\`\`
|
|
842
|
-
|
|
843
|
-
## Schema Options
|
|
844
|
-
|
|
845
|
-
\`\`\`yaml
|
|
846
|
-
options:
|
|
847
|
-
timestamps: true # Add created_at, updated_at
|
|
848
|
-
softDelete: true # Add deleted_at
|
|
849
|
-
idType: BigInt # Primary key type (Int, BigInt, Uuid)
|
|
850
|
-
\`\`\`
|
|
851
|
-
`;
|
|
852
|
-
var LARAVEL_GUIDE = `# Laravel Generator Guide
|
|
853
|
-
|
|
854
|
-
## Generated Files
|
|
855
|
-
|
|
856
|
-
### Migrations
|
|
857
|
-
Located in \`database/migrations/omnify/\`
|
|
858
|
-
- Auto-generated from schema changes
|
|
859
|
-
- Handles column additions, modifications, removals
|
|
860
|
-
- Preserves manual migrations outside omnify folder
|
|
861
|
-
|
|
862
|
-
### Models
|
|
863
|
-
Two-tier model structure:
|
|
864
|
-
- \`app/Models/OmnifyBase/*BaseModel.php\` - Auto-generated, DO NOT EDIT
|
|
865
|
-
- \`app/Models/*.php\` - User models, extend base models, safe to customize
|
|
866
|
-
|
|
867
|
-
### Factories
|
|
868
|
-
Located in \`database/factories/\`
|
|
869
|
-
- Generated once, safe to customize
|
|
870
|
-
- Uses appropriate Faker methods for each type
|
|
871
|
-
|
|
872
|
-
## Model Features
|
|
873
|
-
|
|
874
|
-
### Fillable
|
|
875
|
-
All schema properties are mass-assignable by default.
|
|
876
|
-
Use \`fillable: false\` to exclude.
|
|
877
|
-
|
|
878
|
-
### Hidden
|
|
879
|
-
Use \`hidden: true\` to exclude from JSON/array output.
|
|
880
|
-
|
|
881
|
-
\`\`\`yaml
|
|
882
|
-
password:
|
|
883
|
-
type: Password
|
|
884
|
-
hidden: true
|
|
885
|
-
\`\`\`
|
|
886
|
-
|
|
887
|
-
### Casts
|
|
888
|
-
Auto-generated based on property types:
|
|
889
|
-
- \`Boolean\` \u2192 \`'boolean'\`
|
|
890
|
-
- \`Json\` \u2192 \`'array'\`
|
|
891
|
-
- \`Timestamp\` \u2192 \`'datetime'\`
|
|
892
|
-
|
|
893
|
-
### Relationships
|
|
894
|
-
Generated from Association properties:
|
|
895
|
-
- \`ManyToOne\` \u2192 \`belongsTo()\`
|
|
896
|
-
- \`OneToMany\` \u2192 \`hasMany()\`
|
|
897
|
-
- \`ManyToMany\` \u2192 \`belongsToMany()\`
|
|
898
|
-
- \`MorphTo\` \u2192 \`morphTo()\`
|
|
899
|
-
- \`MorphMany\` \u2192 \`morphMany()\`
|
|
900
|
-
|
|
901
|
-
## Commands
|
|
902
|
-
|
|
903
|
-
\`\`\`bash
|
|
904
|
-
# Generate migrations and models
|
|
905
|
-
npx omnify generate
|
|
906
|
-
|
|
907
|
-
# Force regeneration
|
|
908
|
-
npx omnify generate --force
|
|
909
|
-
|
|
910
|
-
# Validate schemas
|
|
911
|
-
npx omnify validate
|
|
912
|
-
\`\`\`
|
|
913
|
-
`;
|
|
914
|
-
var TYPESCRIPT_GUIDE = `# TypeScript Generator Guide
|
|
915
|
-
|
|
916
|
-
## Generated Types
|
|
917
|
-
|
|
918
|
-
Types are generated in the configured output directory.
|
|
919
|
-
|
|
920
|
-
### Interface Generation
|
|
921
|
-
|
|
922
|
-
Each schema generates a TypeScript interface:
|
|
923
|
-
|
|
924
|
-
\`\`\`typescript
|
|
925
|
-
export interface User {
|
|
926
|
-
id: number;
|
|
927
|
-
email: string;
|
|
928
|
-
name: string;
|
|
929
|
-
bio: string | null;
|
|
930
|
-
created_at: string;
|
|
931
|
-
updated_at: string;
|
|
932
|
-
}
|
|
933
|
-
\`\`\`
|
|
934
|
-
|
|
935
|
-
### Type Mappings
|
|
936
|
-
|
|
937
|
-
| Omnify Type | TypeScript Type |
|
|
938
|
-
|-------------|-----------------|
|
|
939
|
-
| String, Text | string |
|
|
940
|
-
| Int, BigInt | number |
|
|
941
|
-
| Float, Decimal | number |
|
|
942
|
-
| Boolean | boolean |
|
|
943
|
-
| Date, DateTime | string |
|
|
944
|
-
| Json | Record<string, unknown> |
|
|
945
|
-
| Enum | union of literals |
|
|
946
|
-
|
|
947
|
-
### Nullable Types
|
|
948
|
-
|
|
949
|
-
Nullable properties become \`T | null\`:
|
|
950
|
-
|
|
951
|
-
\`\`\`typescript
|
|
952
|
-
bio: string | null;
|
|
953
|
-
\`\`\`
|
|
954
|
-
|
|
955
|
-
### Associations
|
|
956
|
-
|
|
957
|
-
Associations generate optional relation properties:
|
|
958
|
-
|
|
959
|
-
\`\`\`typescript
|
|
960
|
-
export interface Post {
|
|
961
|
-
id: number;
|
|
962
|
-
title: string;
|
|
963
|
-
author_id: number;
|
|
964
|
-
author?: User; // Optional relation
|
|
965
|
-
comments?: Comment[]; // Optional array relation
|
|
966
|
-
}
|
|
967
|
-
\`\`\`
|
|
968
|
-
`;
|
|
969
|
-
var JAPAN_GUIDE = `# Japan Plugin Types Guide
|
|
970
|
-
|
|
971
|
-
This project uses \`@famgia/omnify-japan\` plugin which provides Japan-specific types.
|
|
972
|
-
|
|
973
|
-
## Available Types
|
|
974
|
-
|
|
975
|
-
### Simple Types
|
|
976
|
-
|
|
977
|
-
#### JapanesePhone
|
|
978
|
-
Japanese phone number format (e.g., \`090-1234-5678\`, \`03-1234-5678\`)
|
|
979
|
-
- SQL: \`VARCHAR(15)\`
|
|
980
|
-
- Accepts with or without hyphens
|
|
981
|
-
|
|
982
|
-
\`\`\`yaml
|
|
983
|
-
phone:
|
|
984
|
-
type: JapanesePhone
|
|
985
|
-
\`\`\`
|
|
986
|
-
|
|
987
|
-
#### JapanesePostalCode
|
|
988
|
-
Japanese postal code format (e.g., \`123-4567\`)
|
|
989
|
-
- SQL: \`VARCHAR(8)\`
|
|
990
|
-
- Accepts with or without hyphen
|
|
991
|
-
|
|
992
|
-
\`\`\`yaml
|
|
993
|
-
postal_code:
|
|
994
|
-
type: JapanesePostalCode
|
|
995
|
-
nullable: true
|
|
996
|
-
\`\`\`
|
|
997
|
-
|
|
998
|
-
### Compound Types
|
|
999
|
-
|
|
1000
|
-
Compound types expand into multiple database columns automatically.
|
|
1001
|
-
|
|
1002
|
-
#### JapaneseName
|
|
1003
|
-
Japanese name with kanji and kana variants.
|
|
1004
|
-
|
|
1005
|
-
**Expands to 4 columns:**
|
|
1006
|
-
- \`{property}_lastname\` - VARCHAR(50) - Family name (\u59D3)
|
|
1007
|
-
- \`{property}_firstname\` - VARCHAR(50) - Given name (\u540D)
|
|
1008
|
-
- \`{property}_kana_lastname\` - VARCHAR(100) - Family name in katakana
|
|
1009
|
-
- \`{property}_kana_firstname\` - VARCHAR(100) - Given name in katakana
|
|
1010
|
-
|
|
1011
|
-
**Accessors generated:**
|
|
1012
|
-
- \`{property}_full_name\` - "\u59D3 \u540D" (space-separated)
|
|
1013
|
-
- \`{property}_full_name_kana\` - "\u30BB\u30A4 \u30E1\u30A4" (space-separated)
|
|
1014
|
-
|
|
1015
|
-
\`\`\`yaml
|
|
1016
|
-
name:
|
|
1017
|
-
type: JapaneseName
|
|
1018
|
-
displayName:
|
|
1019
|
-
ja: \u6C0F\u540D
|
|
1020
|
-
en: Full Name
|
|
1021
|
-
# Per-field overrides
|
|
1022
|
-
fields:
|
|
1023
|
-
KanaLastname:
|
|
1024
|
-
nullable: true
|
|
1025
|
-
hidden: true
|
|
1026
|
-
KanaFirstname:
|
|
1027
|
-
nullable: true
|
|
1028
|
-
hidden: true
|
|
1029
|
-
\`\`\`
|
|
1030
|
-
|
|
1031
|
-
#### JapaneseAddress
|
|
1032
|
-
Japanese address with postal code and prefecture ID.
|
|
1033
|
-
|
|
1034
|
-
**Expands to 5 columns:**
|
|
1035
|
-
- \`{property}_postal_code\` - VARCHAR(8) - Postal code (\u90F5\u4FBF\u756A\u53F7)
|
|
1036
|
-
- \`{property}_prefecture_id\` - TINYINT UNSIGNED - Prefecture ID 1-47 (\u90FD\u9053\u5E9C\u770C)
|
|
1037
|
-
- \`{property}_address1\` - VARCHAR(255) - City/Ward (\u5E02\u533A\u753A\u6751)
|
|
1038
|
-
- \`{property}_address2\` - VARCHAR(255) - Street address (\u4E01\u76EE\u756A\u5730\u53F7)
|
|
1039
|
-
- \`{property}_address3\` - VARCHAR(255) NULLABLE - Building name (\u30D3\u30EB\u30FB\u30DE\u30F3\u30B7\u30E7\u30F3\u540D)
|
|
1040
|
-
|
|
1041
|
-
**Accessors generated:**
|
|
1042
|
-
- \`{property}_full_address\` - Concatenation of address1 + address2 + address3
|
|
1043
|
-
|
|
1044
|
-
\`\`\`yaml
|
|
1045
|
-
address:
|
|
1046
|
-
type: JapaneseAddress
|
|
1047
|
-
displayName:
|
|
1048
|
-
ja: \u4F4F\u6240
|
|
1049
|
-
en: Address
|
|
1050
|
-
fields:
|
|
1051
|
-
Address3:
|
|
1052
|
-
nullable: true
|
|
1053
|
-
\`\`\`
|
|
1054
|
-
|
|
1055
|
-
**Prefecture IDs (JIS X 0401):**
|
|
1056
|
-
| ID | Prefecture | ID | Prefecture | ID | Prefecture |
|
|
1057
|
-
|----|-----------|----|-----------|----|-----------|
|
|
1058
|
-
| 1 | \u5317\u6D77\u9053 | 17 | \u77F3\u5DDD\u770C | 33 | \u5CA1\u5C71\u770C |
|
|
1059
|
-
| 2 | \u9752\u68EE\u770C | 18 | \u798F\u4E95\u770C | 34 | \u5E83\u5CF6\u770C |
|
|
1060
|
-
| 3 | \u5CA9\u624B\u770C | 19 | \u5C71\u68A8\u770C | 35 | \u5C71\u53E3\u770C |
|
|
1061
|
-
| 4 | \u5BAE\u57CE\u770C | 20 | \u9577\u91CE\u770C | 36 | \u5FB3\u5CF6\u770C |
|
|
1062
|
-
| 5 | \u79CB\u7530\u770C | 21 | \u5C90\u961C\u770C | 37 | \u9999\u5DDD\u770C |
|
|
1063
|
-
| 6 | \u5C71\u5F62\u770C | 22 | \u9759\u5CA1\u770C | 38 | \u611B\u5A9B\u770C |
|
|
1064
|
-
| 7 | \u798F\u5CF6\u770C | 23 | \u611B\u77E5\u770C | 39 | \u9AD8\u77E5\u770C |
|
|
1065
|
-
| 8 | \u8328\u57CE\u770C | 24 | \u4E09\u91CD\u770C | 40 | \u798F\u5CA1\u770C |
|
|
1066
|
-
| 9 | \u6803\u6728\u770C | 25 | \u6ECB\u8CC0\u770C | 41 | \u4F50\u8CC0\u770C |
|
|
1067
|
-
| 10 | \u7FA4\u99AC\u770C | 26 | \u4EAC\u90FD\u5E9C | 42 | \u9577\u5D0E\u770C |
|
|
1068
|
-
| 11 | \u57FC\u7389\u770C | 27 | \u5927\u962A\u5E9C | 43 | \u718A\u672C\u770C |
|
|
1069
|
-
| 12 | \u5343\u8449\u770C | 28 | \u5175\u5EAB\u770C | 44 | \u5927\u5206\u770C |
|
|
1070
|
-
| 13 | \u6771\u4EAC\u90FD | 29 | \u5948\u826F\u770C | 45 | \u5BAE\u5D0E\u770C |
|
|
1071
|
-
| 14 | \u795E\u5948\u5DDD\u770C | 30 | \u548C\u6B4C\u5C71\u770C | 46 | \u9E7F\u5150\u5CF6\u770C |
|
|
1072
|
-
| 15 | \u65B0\u6F5F\u770C | 31 | \u9CE5\u53D6\u770C | 47 | \u6C96\u7E04\u770C |
|
|
1073
|
-
| 16 | \u5BCC\u5C71\u770C | 32 | \u5CF6\u6839\u770C | | |
|
|
1074
|
-
|
|
1075
|
-
#### JapaneseBankAccount
|
|
1076
|
-
Japanese bank account information.
|
|
1077
|
-
|
|
1078
|
-
**Expands to 5 columns:**
|
|
1079
|
-
- \`{property}_bank_code\` - VARCHAR(4) - Bank code (\u9280\u884C\u30B3\u30FC\u30C9)
|
|
1080
|
-
- \`{property}_branch_code\` - VARCHAR(3) - Branch code (\u652F\u5E97\u30B3\u30FC\u30C9)
|
|
1081
|
-
- \`{property}_account_type\` - ENUM - Account type: 1=\u666E\u901A, 2=\u5F53\u5EA7, 4=\u8CAF\u84C4
|
|
1082
|
-
- \`{property}_account_number\` - VARCHAR(7) - Account number (\u53E3\u5EA7\u756A\u53F7)
|
|
1083
|
-
- \`{property}_account_holder\` - VARCHAR(100) - Account holder name (\u53E3\u5EA7\u540D\u7FA9)
|
|
1084
|
-
|
|
1085
|
-
\`\`\`yaml
|
|
1086
|
-
bank_account:
|
|
1087
|
-
type: JapaneseBankAccount
|
|
1088
|
-
\`\`\`
|
|
1089
|
-
|
|
1090
|
-
## Per-field Overrides
|
|
1091
|
-
|
|
1092
|
-
All compound types support per-field overrides:
|
|
1093
|
-
|
|
1094
|
-
\`\`\`yaml
|
|
1095
|
-
name:
|
|
1096
|
-
type: JapaneseName
|
|
1097
|
-
fields:
|
|
1098
|
-
Lastname:
|
|
1099
|
-
length: 100 # Override default VARCHAR length
|
|
1100
|
-
Firstname:
|
|
1101
|
-
length: 100
|
|
1102
|
-
KanaLastname:
|
|
1103
|
-
length: 200
|
|
1104
|
-
nullable: true
|
|
1105
|
-
hidden: true
|
|
1106
|
-
KanaFirstname:
|
|
1107
|
-
length: 200
|
|
1108
|
-
nullable: true
|
|
1109
|
-
hidden: true
|
|
1110
|
-
\`\`\`
|
|
1111
|
-
|
|
1112
|
-
**Available overrides:**
|
|
1113
|
-
- \`length\` - VARCHAR length (override default)
|
|
1114
|
-
- \`nullable\` - Whether the field can be NULL
|
|
1115
|
-
- \`hidden\` - Exclude from JSON/array output
|
|
1116
|
-
- \`fillable\` - Control mass assignment
|
|
1117
|
-
|
|
1118
|
-
## Factory Examples
|
|
1119
|
-
|
|
1120
|
-
\`\`\`php
|
|
1121
|
-
$faker = fake('ja_JP');
|
|
1122
|
-
|
|
1123
|
-
return [
|
|
1124
|
-
// JapaneseName
|
|
1125
|
-
'name_lastname' => $faker->lastName(),
|
|
1126
|
-
'name_firstname' => $faker->firstName(),
|
|
1127
|
-
'name_kana_lastname' => $faker->lastKanaName(),
|
|
1128
|
-
'name_kana_firstname' => $faker->firstKanaName(),
|
|
1129
|
-
|
|
1130
|
-
// JapanesePhone
|
|
1131
|
-
'phone' => $faker->phoneNumber(),
|
|
1132
|
-
|
|
1133
|
-
// JapanesePostalCode
|
|
1134
|
-
'postal_code' => $faker->postcode(),
|
|
1135
|
-
|
|
1136
|
-
// JapaneseAddress
|
|
1137
|
-
'address_postal_code' => $faker->postcode(),
|
|
1138
|
-
'address_prefecture_id' => $faker->numberBetween(1, 47),
|
|
1139
|
-
'address_address1' => $faker->city(),
|
|
1140
|
-
'address_address2' => $faker->streetAddress(),
|
|
1141
|
-
'address_address3' => $faker->optional(0.5)->secondaryAddress(),
|
|
1142
|
-
];
|
|
1143
|
-
\`\`\`
|
|
1144
|
-
|
|
1145
|
-
## Model Accessors
|
|
1146
|
-
|
|
1147
|
-
\`\`\`php
|
|
1148
|
-
// JapaneseName accessors
|
|
1149
|
-
$customer->name_full_name; // "\u7530\u4E2D \u592A\u90CE"
|
|
1150
|
-
$customer->name_full_name_kana; // "\u30BF\u30CA\u30AB \u30BF\u30ED\u30A6"
|
|
1151
|
-
|
|
1152
|
-
// JapaneseAddress accessor
|
|
1153
|
-
$customer->address_full_address; // "\u5343\u4EE3\u7530\u533A\u4E38\u306E\u51851-1-1\u30D3\u30EB5F"
|
|
1154
|
-
\`\`\`
|
|
1155
|
-
`;
|
|
1156
|
-
function isJapanPlugin(plugin) {
|
|
1157
|
-
return plugin.name === "@famgia/omnify-japan";
|
|
1158
|
-
}
|
|
1159
|
-
function isLaravelPlugin(plugin) {
|
|
1160
|
-
return plugin.name === "@famgia/omnify-laravel";
|
|
1161
|
-
}
|
|
1162
|
-
function isTypeScriptPlugin(plugin) {
|
|
1163
|
-
return plugin.name === "@famgia/omnify-typescript";
|
|
1164
|
-
}
|
|
1165
|
-
function generateAIGuides(rootDir, plugins) {
|
|
1166
|
-
const guidesDir = (0, import_node_path5.resolve)(rootDir, ".claude/omnify");
|
|
741
|
+
function generateAIGuides(rootDir, _plugins) {
|
|
1167
742
|
let filesWritten = 0;
|
|
1168
|
-
if (!(0, import_node_fs3.existsSync)(guidesDir)) {
|
|
1169
|
-
(0, import_node_fs3.mkdirSync)(guidesDir, { recursive: true });
|
|
1170
|
-
}
|
|
1171
743
|
const claudeMdPath = (0, import_node_path5.resolve)(rootDir, "CLAUDE.md");
|
|
1172
744
|
if (!(0, import_node_fs3.existsSync)(claudeMdPath)) {
|
|
1173
745
|
(0, import_node_fs3.writeFileSync)(claudeMdPath, CLAUDE_MD);
|
|
1174
746
|
filesWritten++;
|
|
1175
747
|
}
|
|
1176
|
-
const schemaGuidePath = (0, import_node_path5.resolve)(guidesDir, "schema-guide.md");
|
|
1177
|
-
(0, import_node_fs3.writeFileSync)(schemaGuidePath, SCHEMA_GUIDE);
|
|
1178
|
-
filesWritten++;
|
|
1179
|
-
for (const plugin of plugins) {
|
|
1180
|
-
if (isLaravelPlugin(plugin)) {
|
|
1181
|
-
const laravelGuidePath = (0, import_node_path5.resolve)(guidesDir, "laravel-guide.md");
|
|
1182
|
-
(0, import_node_fs3.writeFileSync)(laravelGuidePath, LARAVEL_GUIDE);
|
|
1183
|
-
filesWritten++;
|
|
1184
|
-
}
|
|
1185
|
-
if (isTypeScriptPlugin(plugin)) {
|
|
1186
|
-
const tsGuidePath = (0, import_node_path5.resolve)(guidesDir, "typescript-guide.md");
|
|
1187
|
-
(0, import_node_fs3.writeFileSync)(tsGuidePath, TYPESCRIPT_GUIDE);
|
|
1188
|
-
filesWritten++;
|
|
1189
|
-
}
|
|
1190
|
-
if (isJapanPlugin(plugin)) {
|
|
1191
|
-
const japanGuidePath = (0, import_node_path5.resolve)(guidesDir, "japan-guide.md");
|
|
1192
|
-
(0, import_node_fs3.writeFileSync)(japanGuidePath, JAPAN_GUIDE);
|
|
1193
|
-
filesWritten++;
|
|
1194
|
-
}
|
|
1195
|
-
}
|
|
1196
748
|
return filesWritten;
|
|
1197
749
|
}
|
|
1198
750
|
|
|
@@ -1451,6 +1003,14 @@ function runDirectGeneration(schemas, config, rootDir, options, changes) {
|
|
|
1451
1003
|
}
|
|
1452
1004
|
}
|
|
1453
1005
|
}
|
|
1006
|
+
const pluginEnumsMap = /* @__PURE__ */ new Map();
|
|
1007
|
+
for (const plugin of config.plugins) {
|
|
1008
|
+
if (plugin.enums) {
|
|
1009
|
+
for (const enumDef of plugin.enums) {
|
|
1010
|
+
pluginEnumsMap.set(enumDef.name, enumDef);
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1454
1014
|
if (!options.typesOnly && config.output.laravel) {
|
|
1455
1015
|
logger.step("Generating Laravel migrations...");
|
|
1456
1016
|
const migrationsDir = (0, import_node_path6.resolve)(rootDir, config.output.laravel.migrationsPath);
|
|
@@ -1556,22 +1116,32 @@ function runDirectGeneration(schemas, config, rootDir, options, changes) {
|
|
|
1556
1116
|
}
|
|
1557
1117
|
if (!options.migrationsOnly && config.output.typescript) {
|
|
1558
1118
|
logger.step("Generating TypeScript types...");
|
|
1559
|
-
const
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1119
|
+
const tsConfig = config.output.typescript;
|
|
1120
|
+
const basePath = (0, import_node_path6.resolve)(rootDir, tsConfig.path);
|
|
1121
|
+
const schemasDir = (0, import_node_path6.resolve)(basePath, tsConfig.schemasDir ?? "schemas");
|
|
1122
|
+
const enumDir = (0, import_node_path6.resolve)(basePath, tsConfig.enumDir ?? "enum");
|
|
1123
|
+
const enumImportPrefix = (0, import_node_path6.relative)(schemasDir, enumDir).replace(/\\/g, "/");
|
|
1124
|
+
if (!(0, import_node_fs4.existsSync)(schemasDir)) {
|
|
1125
|
+
(0, import_node_fs4.mkdirSync)(schemasDir, { recursive: true });
|
|
1126
|
+
logger.debug(`Created directory: ${schemasDir}`);
|
|
1127
|
+
}
|
|
1128
|
+
if (!(0, import_node_fs4.existsSync)(enumDir)) {
|
|
1129
|
+
(0, import_node_fs4.mkdirSync)(enumDir, { recursive: true });
|
|
1130
|
+
logger.debug(`Created directory: ${enumDir}`);
|
|
1563
1131
|
}
|
|
1564
1132
|
const isMultiLocale = config.locale && config.locale.locales && config.locale.locales.length > 1;
|
|
1565
|
-
const typescriptConfig = config.output.typescript;
|
|
1566
1133
|
const typeFiles = (0, import_omnify_typescript.generateTypeScript)(schemas, {
|
|
1567
1134
|
customTypes: customTypesMap,
|
|
1135
|
+
pluginEnums: pluginEnumsMap,
|
|
1568
1136
|
localeConfig: config.locale,
|
|
1569
1137
|
multiLocale: isMultiLocale,
|
|
1570
|
-
generateRules:
|
|
1571
|
-
validationTemplates:
|
|
1138
|
+
generateRules: tsConfig.generateRules ?? true,
|
|
1139
|
+
validationTemplates: tsConfig.validationTemplates,
|
|
1140
|
+
enumImportPrefix
|
|
1572
1141
|
});
|
|
1573
1142
|
for (const file of typeFiles) {
|
|
1574
|
-
const
|
|
1143
|
+
const outputDir = file.category === "enum" ? enumDir : schemasDir;
|
|
1144
|
+
const filePath = (0, import_node_path6.resolve)(outputDir, file.filePath);
|
|
1575
1145
|
const fileDir = (0, import_node_path6.dirname)(filePath);
|
|
1576
1146
|
if (!(0, import_node_fs4.existsSync)(fileDir)) {
|
|
1577
1147
|
(0, import_node_fs4.mkdirSync)(fileDir, { recursive: true });
|
|
@@ -1585,6 +1155,13 @@ function runDirectGeneration(schemas, config, rootDir, options, changes) {
|
|
|
1585
1155
|
typesGenerated++;
|
|
1586
1156
|
}
|
|
1587
1157
|
logger.success(`Generated ${typesGenerated} TypeScript file(s)`);
|
|
1158
|
+
const stubsResult = (0, import_omnify_typescript.copyStubs)({
|
|
1159
|
+
targetDir: basePath,
|
|
1160
|
+
skipIfExists: true
|
|
1161
|
+
});
|
|
1162
|
+
if (stubsResult.copied.length > 0) {
|
|
1163
|
+
logger.success(`Generated ${stubsResult.copied.length} React stub(s)`);
|
|
1164
|
+
}
|
|
1588
1165
|
}
|
|
1589
1166
|
return { migrations: migrationsGenerated, types: typesGenerated, models: modelsGenerated, factories: factoriesGenerated };
|
|
1590
1167
|
}
|
|
@@ -1631,7 +1208,9 @@ async function runGenerate(options) {
|
|
|
1631
1208
|
const v2Lock = existingLock && (0, import_omnify_atlas2.isLockFileV2)(existingLock) ? existingLock : null;
|
|
1632
1209
|
const comparison = (0, import_omnify_atlas2.compareSchemasDeep)(currentSnapshots, v2Lock);
|
|
1633
1210
|
const skipMigrations = !comparison.hasChanges && !options.force;
|
|
1634
|
-
|
|
1211
|
+
const pluginsHaveGenerators = config.plugins.some((p) => p.generators && p.generators.length > 0);
|
|
1212
|
+
const hasTypescriptOutput = !!config.output.typescript;
|
|
1213
|
+
if (skipMigrations && !config.output.laravel?.modelsPath && !pluginsHaveGenerators && !hasTypescriptOutput) {
|
|
1635
1214
|
logger.success("No changes to generate");
|
|
1636
1215
|
return;
|
|
1637
1216
|
}
|
|
@@ -1654,6 +1233,14 @@ async function runGenerate(options) {
|
|
|
1654
1233
|
}
|
|
1655
1234
|
}
|
|
1656
1235
|
}
|
|
1236
|
+
const pluginEnumsMap = /* @__PURE__ */ new Map();
|
|
1237
|
+
for (const plugin of config.plugins) {
|
|
1238
|
+
if (plugin.enums) {
|
|
1239
|
+
for (const enumDef of plugin.enums) {
|
|
1240
|
+
pluginEnumsMap.set(enumDef.name, enumDef);
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1657
1244
|
if (usePlugins) {
|
|
1658
1245
|
logger.step("Running plugin generators...");
|
|
1659
1246
|
const counts = await runPluginGeneration(
|
|
@@ -1682,22 +1269,32 @@ async function runGenerate(options) {
|
|
|
1682
1269
|
}
|
|
1683
1270
|
if (!options.migrationsOnly && config.output.typescript && typesGenerated === 0) {
|
|
1684
1271
|
logger.step("Generating TypeScript types...");
|
|
1685
|
-
const
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1272
|
+
const tsConfig2 = config.output.typescript;
|
|
1273
|
+
const basePath2 = (0, import_node_path6.resolve)(rootDir, tsConfig2.path);
|
|
1274
|
+
const schemasDir2 = (0, import_node_path6.resolve)(basePath2, tsConfig2.schemasDir ?? "schemas");
|
|
1275
|
+
const enumDir2 = (0, import_node_path6.resolve)(basePath2, tsConfig2.enumDir ?? "enum");
|
|
1276
|
+
const enumImportPrefix2 = (0, import_node_path6.relative)(schemasDir2, enumDir2).replace(/\\/g, "/");
|
|
1277
|
+
if (!(0, import_node_fs4.existsSync)(schemasDir2)) {
|
|
1278
|
+
(0, import_node_fs4.mkdirSync)(schemasDir2, { recursive: true });
|
|
1279
|
+
logger.debug(`Created directory: ${schemasDir2}`);
|
|
1280
|
+
}
|
|
1281
|
+
if (!(0, import_node_fs4.existsSync)(enumDir2)) {
|
|
1282
|
+
(0, import_node_fs4.mkdirSync)(enumDir2, { recursive: true });
|
|
1283
|
+
logger.debug(`Created directory: ${enumDir2}`);
|
|
1689
1284
|
}
|
|
1690
1285
|
const isMultiLocale = config.locale && config.locale.locales && config.locale.locales.length > 1;
|
|
1691
|
-
const typescriptConfig = config.output.typescript;
|
|
1692
1286
|
const typeFiles = (0, import_omnify_typescript.generateTypeScript)(schemas, {
|
|
1693
1287
|
customTypes: customTypesMap,
|
|
1288
|
+
pluginEnums: pluginEnumsMap,
|
|
1694
1289
|
localeConfig: config.locale,
|
|
1695
1290
|
multiLocale: isMultiLocale,
|
|
1696
|
-
generateRules:
|
|
1697
|
-
validationTemplates:
|
|
1291
|
+
generateRules: tsConfig2.generateRules ?? true,
|
|
1292
|
+
validationTemplates: tsConfig2.validationTemplates,
|
|
1293
|
+
enumImportPrefix: enumImportPrefix2
|
|
1698
1294
|
});
|
|
1699
1295
|
for (const file of typeFiles) {
|
|
1700
|
-
const
|
|
1296
|
+
const outputDir2 = file.category === "enum" ? enumDir2 : schemasDir2;
|
|
1297
|
+
const filePath = (0, import_node_path6.resolve)(outputDir2, file.filePath);
|
|
1701
1298
|
const fileDir = (0, import_node_path6.dirname)(filePath);
|
|
1702
1299
|
if (!(0, import_node_fs4.existsSync)(fileDir)) {
|
|
1703
1300
|
(0, import_node_fs4.mkdirSync)(fileDir, { recursive: true });
|
|
@@ -1711,6 +1308,22 @@ async function runGenerate(options) {
|
|
|
1711
1308
|
typesGenerated++;
|
|
1712
1309
|
}
|
|
1713
1310
|
logger.success(`Generated ${typesGenerated} TypeScript file(s)`);
|
|
1311
|
+
const stubsResult2 = (0, import_omnify_typescript.copyStubs)({
|
|
1312
|
+
targetDir: basePath2,
|
|
1313
|
+
skipIfExists: true
|
|
1314
|
+
});
|
|
1315
|
+
if (stubsResult2.copied.length > 0) {
|
|
1316
|
+
logger.success(`Generated ${stubsResult2.copied.length} React stub(s)`);
|
|
1317
|
+
}
|
|
1318
|
+
if ((0, import_omnify_typescript.shouldGenerateAIGuides)(rootDir)) {
|
|
1319
|
+
const tsAIResult = (0, import_omnify_typescript.generateAIGuides)(rootDir, {
|
|
1320
|
+
typescriptPath: tsConfig2.path
|
|
1321
|
+
});
|
|
1322
|
+
const tsClaudeTotal = tsAIResult.claudeGuides + tsAIResult.claudeChecklists;
|
|
1323
|
+
if (tsClaudeTotal > 0 || tsAIResult.cursorRules > 0) {
|
|
1324
|
+
logger.debug(`Generated ${tsClaudeTotal} React Claude files, ${tsAIResult.cursorRules} Cursor rules`);
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1714
1327
|
}
|
|
1715
1328
|
} else {
|
|
1716
1329
|
const counts = runDirectGeneration(schemas, config, rootDir, options, comparison.changes);
|