@koltakov/ffa-core 0.6.0 → 0.16.0
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/README.md +402 -158
- package/dist/cli.js +361 -99
- package/dist/index.d.ts +75 -6
- package/dist/index.js +153 -8
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
|
-
type FieldType = 'string' | 'number' | 'boolean' | 'uuid' | 'datetime' | 'enum' | 'belongsTo' | 'hasMany';
|
|
1
|
+
type FieldType = 'string' | 'number' | 'boolean' | 'uuid' | 'datetime' | 'enum' | 'belongsTo' | 'hasMany' | 'object' | 'array';
|
|
2
|
+
type StringFakeHint = 'email' | 'url' | 'domain' | 'ip' | 'username' | 'image' | 'avatar' | 'firstName' | 'lastName' | 'fullName' | 'phone' | 'city' | 'country' | 'address' | 'zip' | 'locale' | 'company' | 'jobTitle' | 'department' | 'currency' | 'word' | 'slug' | 'sentence' | 'paragraph' | 'bio' | 'color' | 'hexColor' | 'uuid';
|
|
3
|
+
type NumberFakeHint = 'price' | 'age' | 'rating' | 'percent' | 'lat' | 'lng' | 'year';
|
|
4
|
+
type FakeHint = StringFakeHint | NumberFakeHint;
|
|
5
|
+
/** Function that receives filtered items (before pagination) and returns any value */
|
|
6
|
+
type MetaFn = (items: Record<string, unknown>[]) => unknown;
|
|
7
|
+
/**
|
|
8
|
+
* A meta value is either:
|
|
9
|
+
* - a static value (string, number, boolean, object, array, …)
|
|
10
|
+
* - a MetaFn computed from the current filtered dataset
|
|
11
|
+
*/
|
|
12
|
+
type MetaValue = MetaFn | unknown;
|
|
2
13
|
interface FieldRules {
|
|
3
14
|
required?: boolean;
|
|
4
15
|
min?: number;
|
|
@@ -7,6 +18,10 @@ interface FieldRules {
|
|
|
7
18
|
readonly?: boolean;
|
|
8
19
|
entity?: string;
|
|
9
20
|
enumValues?: string[];
|
|
21
|
+
fakeHint?: FakeHint;
|
|
22
|
+
objectFields?: Record<string, FieldDefinition>;
|
|
23
|
+
arrayItem?: FieldDefinition;
|
|
24
|
+
arrayCount?: [number, number];
|
|
10
25
|
}
|
|
11
26
|
interface FieldDefinition {
|
|
12
27
|
type: FieldType;
|
|
@@ -15,6 +30,8 @@ interface FieldDefinition {
|
|
|
15
30
|
interface EntityDefinition {
|
|
16
31
|
fields: Record<string, FieldDefinition>;
|
|
17
32
|
count?: number;
|
|
33
|
+
meta?: Record<string, MetaValue>;
|
|
34
|
+
seed?: Record<string, unknown>[];
|
|
18
35
|
}
|
|
19
36
|
|
|
20
37
|
interface ServerConfig {
|
|
@@ -24,6 +41,7 @@ interface ServerConfig {
|
|
|
24
41
|
};
|
|
25
42
|
persist?: boolean | string;
|
|
26
43
|
delay?: number | [number, number];
|
|
44
|
+
errorRate?: number;
|
|
27
45
|
}
|
|
28
46
|
interface FfaConfig {
|
|
29
47
|
server: ServerConfig;
|
|
@@ -33,13 +51,17 @@ declare function defineConfig(config: FfaConfig): FfaConfig;
|
|
|
33
51
|
|
|
34
52
|
declare function entity(fields: Record<string, any>, options?: {
|
|
35
53
|
count?: number;
|
|
54
|
+
meta?: Record<string, MetaValue>;
|
|
55
|
+
seed?: Record<string, unknown>[];
|
|
36
56
|
}): {
|
|
37
57
|
fields: Record<string, any>;
|
|
38
58
|
count: number | undefined;
|
|
59
|
+
meta: Record<string, unknown> | undefined;
|
|
60
|
+
seed: Record<string, unknown>[] | undefined;
|
|
39
61
|
};
|
|
40
62
|
|
|
41
63
|
declare class FieldBuilder {
|
|
42
|
-
|
|
64
|
+
protected def: FieldDefinition;
|
|
43
65
|
constructor(type: FieldType, extraRules?: Partial<FieldRules>);
|
|
44
66
|
required(): this;
|
|
45
67
|
optional(): this;
|
|
@@ -47,18 +69,65 @@ declare class FieldBuilder {
|
|
|
47
69
|
max(value: number): this;
|
|
48
70
|
default(value: any): this;
|
|
49
71
|
readonly(): this;
|
|
72
|
+
/** Explicit faker hint — overrides smart field-name detection */
|
|
73
|
+
fake(hint: FakeHint): this;
|
|
50
74
|
build(): FieldDefinition;
|
|
51
75
|
}
|
|
76
|
+
declare class StringFieldBuilder extends FieldBuilder {
|
|
77
|
+
constructor();
|
|
78
|
+
private hint;
|
|
79
|
+
email(): this;
|
|
80
|
+
url(): this;
|
|
81
|
+
domain(): this;
|
|
82
|
+
ip(): this;
|
|
83
|
+
username(): this;
|
|
84
|
+
image(): this;
|
|
85
|
+
avatar(): this;
|
|
86
|
+
firstName(): this;
|
|
87
|
+
lastName(): this;
|
|
88
|
+
fullName(): this;
|
|
89
|
+
phone(): this;
|
|
90
|
+
city(): this;
|
|
91
|
+
country(): this;
|
|
92
|
+
address(): this;
|
|
93
|
+
zip(): this;
|
|
94
|
+
locale(): this;
|
|
95
|
+
company(): this;
|
|
96
|
+
jobTitle(): this;
|
|
97
|
+
department(): this;
|
|
98
|
+
currency(): this;
|
|
99
|
+
word(): this;
|
|
100
|
+
slug(): this;
|
|
101
|
+
sentence(): this;
|
|
102
|
+
paragraph(): this;
|
|
103
|
+
bio(): this;
|
|
104
|
+
color(): this;
|
|
105
|
+
hexColor(): this;
|
|
106
|
+
uuid(): this;
|
|
107
|
+
}
|
|
108
|
+
declare class NumberFieldBuilder extends FieldBuilder {
|
|
109
|
+
constructor();
|
|
110
|
+
private hint;
|
|
111
|
+
price(): this;
|
|
112
|
+
age(): this;
|
|
113
|
+
rating(): this;
|
|
114
|
+
percent(): this;
|
|
115
|
+
lat(): this;
|
|
116
|
+
lng(): this;
|
|
117
|
+
year(): this;
|
|
118
|
+
}
|
|
52
119
|
|
|
53
|
-
declare const string: () =>
|
|
54
|
-
declare const number: () =>
|
|
120
|
+
declare const string: () => StringFieldBuilder;
|
|
121
|
+
declare const number: () => NumberFieldBuilder;
|
|
55
122
|
declare const boolean: () => FieldBuilder;
|
|
56
123
|
declare const uuid: () => FieldBuilder;
|
|
57
124
|
declare const datetime: () => FieldBuilder;
|
|
58
125
|
declare const enumField: (values: [string, ...string[]]) => FieldBuilder;
|
|
59
126
|
declare const belongsTo: (entity: string) => FieldBuilder;
|
|
60
127
|
declare const hasMany: (entity: string) => FieldBuilder;
|
|
128
|
+
declare const object: (fields: Record<string, FieldBuilder>) => FieldBuilder;
|
|
129
|
+
declare const array: (item: FieldBuilder, count?: [number, number]) => FieldBuilder;
|
|
61
130
|
|
|
62
|
-
declare const __ffa_version = "0.
|
|
131
|
+
declare const __ffa_version = "0.16.0";
|
|
63
132
|
|
|
64
|
-
export { type FfaConfig, __ffa_version, belongsTo, boolean, datetime, defineConfig, entity, enumField, hasMany, number, string, uuid };
|
|
133
|
+
export { type FakeHint, type FfaConfig, type MetaFn, type MetaValue, type NumberFakeHint, type StringFakeHint, __ffa_version, array, belongsTo, boolean, datetime, defineConfig, entity, enumField, hasMany, number, object, string, uuid };
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,9 @@ function entity(fields, options) {
|
|
|
14
14
|
}
|
|
15
15
|
return {
|
|
16
16
|
fields: builtFields,
|
|
17
|
-
count: options?.count
|
|
17
|
+
count: options?.count,
|
|
18
|
+
meta: options?.meta,
|
|
19
|
+
seed: options?.seed
|
|
18
20
|
};
|
|
19
21
|
}
|
|
20
22
|
|
|
@@ -22,10 +24,7 @@ function entity(fields, options) {
|
|
|
22
24
|
var FieldBuilder = class {
|
|
23
25
|
def;
|
|
24
26
|
constructor(type, extraRules) {
|
|
25
|
-
this.def = {
|
|
26
|
-
type,
|
|
27
|
-
rules: { ...extraRules }
|
|
28
|
-
};
|
|
27
|
+
this.def = { type, rules: { ...extraRules } };
|
|
29
28
|
}
|
|
30
29
|
required() {
|
|
31
30
|
this.def.rules.required = true;
|
|
@@ -51,25 +50,170 @@ var FieldBuilder = class {
|
|
|
51
50
|
this.def.rules.readonly = true;
|
|
52
51
|
return this;
|
|
53
52
|
}
|
|
53
|
+
/** Explicit faker hint — overrides smart field-name detection */
|
|
54
|
+
fake(hint) {
|
|
55
|
+
this.def.rules.fakeHint = hint;
|
|
56
|
+
return this;
|
|
57
|
+
}
|
|
54
58
|
build() {
|
|
55
59
|
return structuredClone(this.def);
|
|
56
60
|
}
|
|
57
61
|
};
|
|
62
|
+
var StringFieldBuilder = class extends FieldBuilder {
|
|
63
|
+
constructor() {
|
|
64
|
+
super("string");
|
|
65
|
+
}
|
|
66
|
+
hint(h) {
|
|
67
|
+
this.def.rules.fakeHint = h;
|
|
68
|
+
return this;
|
|
69
|
+
}
|
|
70
|
+
// Internet
|
|
71
|
+
email() {
|
|
72
|
+
return this.hint("email");
|
|
73
|
+
}
|
|
74
|
+
url() {
|
|
75
|
+
return this.hint("url");
|
|
76
|
+
}
|
|
77
|
+
domain() {
|
|
78
|
+
return this.hint("domain");
|
|
79
|
+
}
|
|
80
|
+
ip() {
|
|
81
|
+
return this.hint("ip");
|
|
82
|
+
}
|
|
83
|
+
username() {
|
|
84
|
+
return this.hint("username");
|
|
85
|
+
}
|
|
86
|
+
// Media
|
|
87
|
+
image() {
|
|
88
|
+
return this.hint("image");
|
|
89
|
+
}
|
|
90
|
+
avatar() {
|
|
91
|
+
return this.hint("avatar");
|
|
92
|
+
}
|
|
93
|
+
// Person
|
|
94
|
+
firstName() {
|
|
95
|
+
return this.hint("firstName");
|
|
96
|
+
}
|
|
97
|
+
lastName() {
|
|
98
|
+
return this.hint("lastName");
|
|
99
|
+
}
|
|
100
|
+
fullName() {
|
|
101
|
+
return this.hint("fullName");
|
|
102
|
+
}
|
|
103
|
+
// Contact
|
|
104
|
+
phone() {
|
|
105
|
+
return this.hint("phone");
|
|
106
|
+
}
|
|
107
|
+
// Location
|
|
108
|
+
city() {
|
|
109
|
+
return this.hint("city");
|
|
110
|
+
}
|
|
111
|
+
country() {
|
|
112
|
+
return this.hint("country");
|
|
113
|
+
}
|
|
114
|
+
address() {
|
|
115
|
+
return this.hint("address");
|
|
116
|
+
}
|
|
117
|
+
zip() {
|
|
118
|
+
return this.hint("zip");
|
|
119
|
+
}
|
|
120
|
+
locale() {
|
|
121
|
+
return this.hint("locale");
|
|
122
|
+
}
|
|
123
|
+
// Business
|
|
124
|
+
company() {
|
|
125
|
+
return this.hint("company");
|
|
126
|
+
}
|
|
127
|
+
jobTitle() {
|
|
128
|
+
return this.hint("jobTitle");
|
|
129
|
+
}
|
|
130
|
+
department() {
|
|
131
|
+
return this.hint("department");
|
|
132
|
+
}
|
|
133
|
+
currency() {
|
|
134
|
+
return this.hint("currency");
|
|
135
|
+
}
|
|
136
|
+
// Text
|
|
137
|
+
word() {
|
|
138
|
+
return this.hint("word");
|
|
139
|
+
}
|
|
140
|
+
slug() {
|
|
141
|
+
return this.hint("slug");
|
|
142
|
+
}
|
|
143
|
+
sentence() {
|
|
144
|
+
return this.hint("sentence");
|
|
145
|
+
}
|
|
146
|
+
paragraph() {
|
|
147
|
+
return this.hint("paragraph");
|
|
148
|
+
}
|
|
149
|
+
bio() {
|
|
150
|
+
return this.hint("bio");
|
|
151
|
+
}
|
|
152
|
+
// Visual
|
|
153
|
+
color() {
|
|
154
|
+
return this.hint("color");
|
|
155
|
+
}
|
|
156
|
+
hexColor() {
|
|
157
|
+
return this.hint("hexColor");
|
|
158
|
+
}
|
|
159
|
+
// Id
|
|
160
|
+
uuid() {
|
|
161
|
+
return this.hint("uuid");
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
var NumberFieldBuilder = class extends FieldBuilder {
|
|
165
|
+
constructor() {
|
|
166
|
+
super("number");
|
|
167
|
+
}
|
|
168
|
+
hint(h) {
|
|
169
|
+
this.def.rules.fakeHint = h;
|
|
170
|
+
return this;
|
|
171
|
+
}
|
|
172
|
+
price() {
|
|
173
|
+
return this.hint("price");
|
|
174
|
+
}
|
|
175
|
+
age() {
|
|
176
|
+
return this.hint("age");
|
|
177
|
+
}
|
|
178
|
+
rating() {
|
|
179
|
+
return this.hint("rating");
|
|
180
|
+
}
|
|
181
|
+
percent() {
|
|
182
|
+
return this.hint("percent");
|
|
183
|
+
}
|
|
184
|
+
lat() {
|
|
185
|
+
return this.hint("lat");
|
|
186
|
+
}
|
|
187
|
+
lng() {
|
|
188
|
+
return this.hint("lng");
|
|
189
|
+
}
|
|
190
|
+
year() {
|
|
191
|
+
return this.hint("year");
|
|
192
|
+
}
|
|
193
|
+
};
|
|
58
194
|
|
|
59
195
|
// src/field/factories.ts
|
|
60
|
-
var string = () => new
|
|
61
|
-
var number = () => new
|
|
196
|
+
var string = () => new StringFieldBuilder();
|
|
197
|
+
var number = () => new NumberFieldBuilder();
|
|
62
198
|
var boolean = () => new FieldBuilder("boolean");
|
|
63
199
|
var uuid = () => new FieldBuilder("uuid");
|
|
64
200
|
var datetime = () => new FieldBuilder("datetime");
|
|
65
201
|
var enumField = (values) => new FieldBuilder("enum", { enumValues: values });
|
|
66
202
|
var belongsTo = (entity2) => new FieldBuilder("belongsTo", { entity: entity2 });
|
|
67
203
|
var hasMany = (entity2) => new FieldBuilder("hasMany", { entity: entity2 });
|
|
204
|
+
var object = (fields) => {
|
|
205
|
+
const objectFields = Object.fromEntries(Object.entries(fields).map(([k, v]) => [k, v.build()]));
|
|
206
|
+
return new FieldBuilder("object", { objectFields });
|
|
207
|
+
};
|
|
208
|
+
var array = (item, count) => {
|
|
209
|
+
return new FieldBuilder("array", { arrayItem: item.build(), arrayCount: count });
|
|
210
|
+
};
|
|
68
211
|
|
|
69
212
|
// src/index.ts
|
|
70
|
-
var __ffa_version = "0.
|
|
213
|
+
var __ffa_version = "0.16.0";
|
|
71
214
|
export {
|
|
72
215
|
__ffa_version,
|
|
216
|
+
array,
|
|
73
217
|
belongsTo,
|
|
74
218
|
boolean,
|
|
75
219
|
datetime,
|
|
@@ -78,6 +222,7 @@ export {
|
|
|
78
222
|
enumField,
|
|
79
223
|
hasMany,
|
|
80
224
|
number,
|
|
225
|
+
object,
|
|
81
226
|
string,
|
|
82
227
|
uuid
|
|
83
228
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/config/defineConfig.ts","../src/entity/entity.ts","../src/field/FieldBuilder.ts","../src/field/factories.ts","../src/index.ts"],"sourcesContent":["import type { EntityDefinition } from '../field/types'\n\nexport interface ServerConfig {\n port: number\n cors?: boolean | { origin: string | string[] }\n persist?: boolean | string\n delay?: number | [number, number]\n}\n\nexport interface FfaConfig {\n server: ServerConfig\n entities: Record<string, EntityDefinition>\n}\n\nexport function defineConfig(config: FfaConfig): FfaConfig {\n return {\n server: config.server ?? { port: 3000 },\n entities: config.entities ?? {},\n }\n}\n","// src/entity/entity.ts\nexport function entity(fields: Record<string, any>, options?: { count?: number }) {\n const builtFields: Record<string, any> = {}\n\n for (const [key, value] of Object.entries(fields)) {\n builtFields[key] = value.build()\n }\n\n return {\n fields: builtFields,\n count: options?.count,\n }\n}\n","import { FieldDefinition, FieldRules, FieldType } from './types'\n\nexport class FieldBuilder {\n private def: FieldDefinition\n\n constructor(type: FieldType, extraRules?: Partial<FieldRules>) {\n this.def = {\n type,\n rules: { ...extraRules },\n }\n }\n\n required() {\n this.def.rules.required = true\n return this\n }\n\n optional() {\n this.def.rules.required = false\n return this\n }\n\n min(value: number) {\n this.def.rules.min = value\n return this\n }\n\n max(value: number) {\n this.def.rules.max = value\n return this\n }\n\n default(value: any) {\n this.def.rules.default = value\n return this\n }\n\n readonly() {\n this.def.rules.readonly = true\n return this\n }\n\n build(): FieldDefinition {\n return structuredClone(this.def)\n }\n}\n","import { FieldBuilder } from './FieldBuilder'\n\nexport const string = () => new FieldBuilder('string')\nexport const number = () => new FieldBuilder('number')\nexport const boolean = () => new FieldBuilder('boolean')\nexport const uuid = () => new FieldBuilder('uuid')\nexport const datetime = () => new FieldBuilder('datetime')\nexport const enumField = (values: [string, ...string[]]) => new FieldBuilder('enum', { enumValues: values })\nexport const belongsTo = (entity: string) => new FieldBuilder('belongsTo', { entity })\nexport const hasMany = (entity: string) => new FieldBuilder('hasMany', { entity })\n","// config\nexport { defineConfig } from './config/defineConfig'\nexport type { FfaConfig } from './config/defineConfig'\n\n// entity\nexport { entity } from './entity/entity'\n\n// field DSL\nexport { string, number, boolean, uuid, datetime, enumField, belongsTo, hasMany } from './field/factories'\n\nexport const __ffa_version = '0.6.0'\n"],"mappings":";AAcO,SAAS,aAAa,QAA8B;AACzD,SAAO;AAAA,IACL,QAAQ,OAAO,UAAU,EAAE,MAAM,IAAK;AAAA,IACtC,UAAU,OAAO,YAAY,CAAC;AAAA,EAChC;AACF;;;AClBO,SAAS,OAAO,QAA6B,SAA8B;AAChF,QAAM,cAAmC,CAAC;AAE1C,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,gBAAY,GAAG,IAAI,MAAM,MAAM;AAAA,EACjC;AAEA,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,OAAO,SAAS;AAAA,EAClB;AACF;;;ACVO,IAAM,eAAN,MAAmB;AAAA,EAChB;AAAA,EAER,YAAY,MAAiB,YAAkC;AAC7D,SAAK,MAAM;AAAA,MACT;AAAA,MACA,OAAO,EAAE,GAAG,WAAW;AAAA,IACzB;AAAA,EACF;AAAA,EAEA,WAAW;AACT,SAAK,IAAI,MAAM,WAAW;AAC1B,WAAO;AAAA,EACT;AAAA,EAEA,WAAW;AACT,SAAK,IAAI,MAAM,WAAW;AAC1B,WAAO;AAAA,EACT;AAAA,EAEA,IAAI,OAAe;AACjB,SAAK,IAAI,MAAM,MAAM;AACrB,WAAO;AAAA,EACT;AAAA,EAEA,IAAI,OAAe;AACjB,SAAK,IAAI,MAAM,MAAM;AACrB,WAAO;AAAA,EACT;AAAA,EAEA,QAAQ,OAAY;AAClB,SAAK,IAAI,MAAM,UAAU;AACzB,WAAO;AAAA,EACT;AAAA,EAEA,WAAW;AACT,SAAK,IAAI,MAAM,WAAW;AAC1B,WAAO;AAAA,EACT;AAAA,EAEA,QAAyB;AACvB,WAAO,gBAAgB,KAAK,GAAG;AAAA,EACjC;AACF;;;AC3CO,IAAM,SAAS,MAAM,IAAI,aAAa,QAAQ;AAC9C,IAAM,SAAS,MAAM,IAAI,aAAa,QAAQ;AAC9C,IAAM,UAAU,MAAM,IAAI,aAAa,SAAS;AAChD,IAAM,OAAO,MAAM,IAAI,aAAa,MAAM;AAC1C,IAAM,WAAW,MAAM,IAAI,aAAa,UAAU;AAClD,IAAM,YAAY,CAAC,WAAkC,IAAI,aAAa,QAAQ,EAAE,YAAY,OAAO,CAAC;AACpG,IAAM,YAAY,CAACA,YAAmB,IAAI,aAAa,aAAa,EAAE,QAAAA,QAAO,CAAC;AAC9E,IAAM,UAAU,CAACA,YAAmB,IAAI,aAAa,WAAW,EAAE,QAAAA,QAAO,CAAC;;;ACC1E,IAAM,gBAAgB;","names":["entity"]}
|
|
1
|
+
{"version":3,"sources":["../src/config/defineConfig.ts","../src/entity/entity.ts","../src/field/FieldBuilder.ts","../src/field/factories.ts","../src/index.ts"],"sourcesContent":["import type { EntityDefinition } from '../field/types'\n\nexport interface ServerConfig {\n port: number\n cors?: boolean | { origin: string | string[] }\n persist?: boolean | string\n delay?: number | [number, number]\n errorRate?: number\n}\n\nexport interface FfaConfig {\n server: ServerConfig\n entities: Record<string, EntityDefinition>\n}\n\nexport function defineConfig(config: FfaConfig): FfaConfig {\n return {\n server: config.server ?? { port: 3000 },\n entities: config.entities ?? {},\n }\n}\n","import type { MetaValue } from '../field/types'\n\nexport function entity(\n fields: Record<string, any>,\n options?: { count?: number; meta?: Record<string, MetaValue>; seed?: Record<string, unknown>[] },\n) {\n const builtFields: Record<string, any> = {}\n\n for (const [key, value] of Object.entries(fields)) {\n builtFields[key] = value.build()\n }\n\n return {\n fields: builtFields,\n count: options?.count,\n meta: options?.meta,\n seed: options?.seed,\n }\n}\n","import type { FieldDefinition, FieldRules, FieldType, FakeHint, StringFakeHint, NumberFakeHint } from './types'\n\n// ─── Base builder ────────────────────────────────────────────────────────────\n\nexport class FieldBuilder {\n protected def: FieldDefinition\n\n constructor(type: FieldType, extraRules?: Partial<FieldRules>) {\n this.def = { type, rules: { ...extraRules } }\n }\n\n required(): this {\n this.def.rules.required = true\n return this\n }\n\n optional(): this {\n this.def.rules.required = false\n return this\n }\n\n min(value: number): this {\n this.def.rules.min = value\n return this\n }\n\n max(value: number): this {\n this.def.rules.max = value\n return this\n }\n\n default(value: any): this {\n this.def.rules.default = value\n return this\n }\n\n readonly(): this {\n this.def.rules.readonly = true\n return this\n }\n\n /** Explicit faker hint — overrides smart field-name detection */\n fake(hint: FakeHint): this {\n this.def.rules.fakeHint = hint\n return this\n }\n\n build(): FieldDefinition {\n return structuredClone(this.def)\n }\n}\n\n// ─── String builder ──────────────────────────────────────────────────────────\n\nexport class StringFieldBuilder extends FieldBuilder {\n constructor() {\n super('string')\n }\n\n private hint(h: StringFakeHint): this {\n this.def.rules.fakeHint = h\n return this\n }\n\n // Internet\n email(): this { return this.hint('email') }\n url(): this { return this.hint('url') }\n domain(): this { return this.hint('domain') }\n ip(): this { return this.hint('ip') }\n username(): this { return this.hint('username') }\n\n // Media\n image(): this { return this.hint('image') }\n avatar(): this { return this.hint('avatar') }\n\n // Person\n firstName(): this { return this.hint('firstName') }\n lastName(): this { return this.hint('lastName') }\n fullName(): this { return this.hint('fullName') }\n\n // Contact\n phone(): this { return this.hint('phone') }\n\n // Location\n city(): this { return this.hint('city') }\n country(): this { return this.hint('country') }\n address(): this { return this.hint('address') }\n zip(): this { return this.hint('zip') }\n locale(): this { return this.hint('locale') }\n\n // Business\n company(): this { return this.hint('company') }\n jobTitle(): this { return this.hint('jobTitle') }\n department(): this { return this.hint('department') }\n currency(): this { return this.hint('currency') }\n\n // Text\n word(): this { return this.hint('word') }\n slug(): this { return this.hint('slug') }\n sentence(): this { return this.hint('sentence') }\n paragraph(): this { return this.hint('paragraph') }\n bio(): this { return this.hint('bio') }\n\n // Visual\n color(): this { return this.hint('color') }\n hexColor(): this { return this.hint('hexColor') }\n\n // Id\n uuid(): this { return this.hint('uuid') }\n}\n\n// ─── Number builder ──────────────────────────────────────────────────────────\n\nexport class NumberFieldBuilder extends FieldBuilder {\n constructor() {\n super('number')\n }\n\n private hint(h: NumberFakeHint): this {\n this.def.rules.fakeHint = h\n return this\n }\n\n price(): this { return this.hint('price') }\n age(): this { return this.hint('age') }\n rating(): this { return this.hint('rating') }\n percent(): this { return this.hint('percent') }\n lat(): this { return this.hint('lat') }\n lng(): this { return this.hint('lng') }\n year(): this { return this.hint('year') }\n}\n","import { FieldBuilder, StringFieldBuilder, NumberFieldBuilder } from './FieldBuilder'\n\nexport const string = (): StringFieldBuilder => new StringFieldBuilder()\nexport const number = (): NumberFieldBuilder => new NumberFieldBuilder()\nexport const boolean = () => new FieldBuilder('boolean')\nexport const uuid = () => new FieldBuilder('uuid')\nexport const datetime = () => new FieldBuilder('datetime')\nexport const enumField = (values: [string, ...string[]]) => new FieldBuilder('enum', { enumValues: values })\nexport const belongsTo = (entity: string) => new FieldBuilder('belongsTo', { entity })\nexport const hasMany = (entity: string) => new FieldBuilder('hasMany', { entity })\n\nexport const object = (fields: Record<string, FieldBuilder>): FieldBuilder => {\n const objectFields = Object.fromEntries(Object.entries(fields).map(([k, v]) => [k, v.build()]))\n return new FieldBuilder('object', { objectFields })\n}\n\nexport const array = (item: FieldBuilder, count?: [number, number]): FieldBuilder => {\n return new FieldBuilder('array', { arrayItem: item.build(), arrayCount: count })\n}\n","// config\nexport { defineConfig } from './config/defineConfig'\nexport type { FfaConfig } from './config/defineConfig'\n\n// entity\nexport { entity } from './entity/entity'\n\n// field DSL\nexport { string, number, boolean, uuid, datetime, enumField, belongsTo, hasMany, object, array } from './field/factories'\nexport type { FakeHint, StringFakeHint, NumberFakeHint, MetaFn, MetaValue } from './field/types'\n\nexport const __ffa_version = '0.16.0'\n"],"mappings":"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","names":["entity"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@koltakov/ffa-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"description": "Instant mock REST API for frontend development",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -22,6 +22,8 @@
|
|
|
22
22
|
"build": "tsup",
|
|
23
23
|
"dev": "tsx src/cli.ts",
|
|
24
24
|
"typecheck": "tsc --noEmit",
|
|
25
|
+
"test": "vitest run",
|
|
26
|
+
"test:watch": "vitest",
|
|
25
27
|
"prepublishOnly": "npm run typecheck && npm run build"
|
|
26
28
|
},
|
|
27
29
|
"keywords": [
|
|
@@ -64,6 +66,7 @@
|
|
|
64
66
|
"@types/node": "^25.3.3",
|
|
65
67
|
"tsup": "^8.0.0",
|
|
66
68
|
"tsx": "^4.21.0",
|
|
67
|
-
"typescript": "^5.9.3"
|
|
69
|
+
"typescript": "^5.9.3",
|
|
70
|
+
"vitest": "^4.0.18"
|
|
68
71
|
}
|
|
69
72
|
}
|