@koltakov/ffa-core 0.16.0 → 0.16.1
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 +22 -2
- package/dist/cli.js +10 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -251,8 +251,10 @@ string().ip() // "192.168.1.1"
|
|
|
251
251
|
string().username() // "john_doe"
|
|
252
252
|
|
|
253
253
|
// Media
|
|
254
|
-
string().image()
|
|
255
|
-
string().
|
|
254
|
+
string().image() // "https://picsum.photos/seed/xxx/1280/720" (default 16:9)
|
|
255
|
+
string().image(300, 450) // "https://picsum.photos/seed/xxx/300/450" (portrait 2:3)
|
|
256
|
+
string().image(1920, 1080) // "https://picsum.photos/seed/xxx/1920/1080" (Full HD)
|
|
257
|
+
string().avatar() // avatar URL
|
|
256
258
|
|
|
257
259
|
// Person
|
|
258
260
|
string().firstName() // "Alice"
|
|
@@ -335,6 +337,7 @@ All builders share these chainable rules:
|
|
|
335
337
|
| `.readonly()` | Excluded from create/update validation |
|
|
336
338
|
| `.default(val)` | Default value |
|
|
337
339
|
| `.fake(hint)` | Explicit faker hint |
|
|
340
|
+
| `.image(w, h)` | Image dimensions (only for `string().image()`) |
|
|
338
341
|
|
|
339
342
|
---
|
|
340
343
|
|
|
@@ -520,6 +523,23 @@ Save as `ffa.config.json`. `"string!"` = required, `"string"` = optional. Arrays
|
|
|
520
523
|
|
|
521
524
|
---
|
|
522
525
|
|
|
526
|
+
## Testing
|
|
527
|
+
|
|
528
|
+
```bash
|
|
529
|
+
npm test # run all tests once
|
|
530
|
+
npm run test:watch # watch mode
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
Tests live in `tests/` and are excluded from the build. 144 tests covering:
|
|
534
|
+
|
|
535
|
+
- DSL builders and all fake hints (`string()`, `number()`, `object()`, `array()`, ...)
|
|
536
|
+
- Zod schema generation for all field types
|
|
537
|
+
- `entity()` helper
|
|
538
|
+
- `createMemoryDB` — CRUD, pagination, sorting, search, filter operators, seed, meta, relations, image dimensions
|
|
539
|
+
- `validateConfig` — all warning scenarios
|
|
540
|
+
|
|
541
|
+
---
|
|
542
|
+
|
|
523
543
|
## License
|
|
524
544
|
|
|
525
545
|
ISC
|
package/dist/cli.js
CHANGED
|
@@ -105,7 +105,7 @@ var HINT_MAP = {
|
|
|
105
105
|
ip: () => faker.internet.ip(),
|
|
106
106
|
username: () => faker.internet.username(),
|
|
107
107
|
// media
|
|
108
|
-
image: () => faker.image.url(),
|
|
108
|
+
image: () => faker.image.url({ width: 1280, height: 720 }),
|
|
109
109
|
avatar: () => faker.image.avatar(),
|
|
110
110
|
// person
|
|
111
111
|
firstName: () => faker.person.firstName(),
|
|
@@ -181,7 +181,15 @@ var FIELD_NAME_MAP = {
|
|
|
181
181
|
amount: HINT_MAP.price
|
|
182
182
|
};
|
|
183
183
|
function generateFakeValue(def, fieldName, db) {
|
|
184
|
-
if (def.rules.fakeHint)
|
|
184
|
+
if (def.rules.fakeHint) {
|
|
185
|
+
if (def.rules.fakeHint === "image") {
|
|
186
|
+
return faker.image.url({
|
|
187
|
+
width: def.rules.imageWidth ?? 1280,
|
|
188
|
+
height: def.rules.imageHeight ?? 720
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
return HINT_MAP[def.rules.fakeHint]();
|
|
192
|
+
}
|
|
185
193
|
if (def.type === "belongsTo") {
|
|
186
194
|
const target = def.rules.entity;
|
|
187
195
|
if (target && db[target]?.length) {
|
package/dist/index.d.ts
CHANGED
|
@@ -19,6 +19,8 @@ interface FieldRules {
|
|
|
19
19
|
entity?: string;
|
|
20
20
|
enumValues?: string[];
|
|
21
21
|
fakeHint?: FakeHint;
|
|
22
|
+
imageWidth?: number;
|
|
23
|
+
imageHeight?: number;
|
|
22
24
|
objectFields?: Record<string, FieldDefinition>;
|
|
23
25
|
arrayItem?: FieldDefinition;
|
|
24
26
|
arrayCount?: [number, number];
|
|
@@ -81,7 +83,7 @@ declare class StringFieldBuilder extends FieldBuilder {
|
|
|
81
83
|
domain(): this;
|
|
82
84
|
ip(): this;
|
|
83
85
|
username(): this;
|
|
84
|
-
image(): this;
|
|
86
|
+
image(width?: number, height?: number): this;
|
|
85
87
|
avatar(): this;
|
|
86
88
|
firstName(): this;
|
|
87
89
|
lastName(): this;
|
|
@@ -128,6 +130,6 @@ declare const hasMany: (entity: string) => FieldBuilder;
|
|
|
128
130
|
declare const object: (fields: Record<string, FieldBuilder>) => FieldBuilder;
|
|
129
131
|
declare const array: (item: FieldBuilder, count?: [number, number]) => FieldBuilder;
|
|
130
132
|
|
|
131
|
-
declare const __ffa_version = "0.16.
|
|
133
|
+
declare const __ffa_version = "0.16.1";
|
|
132
134
|
|
|
133
135
|
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
|
@@ -84,8 +84,11 @@ var StringFieldBuilder = class extends FieldBuilder {
|
|
|
84
84
|
return this.hint("username");
|
|
85
85
|
}
|
|
86
86
|
// Media
|
|
87
|
-
image() {
|
|
88
|
-
|
|
87
|
+
image(width, height) {
|
|
88
|
+
this.hint("image");
|
|
89
|
+
if (width !== void 0) this.def.rules.imageWidth = width;
|
|
90
|
+
if (height !== void 0) this.def.rules.imageHeight = height;
|
|
91
|
+
return this;
|
|
89
92
|
}
|
|
90
93
|
avatar() {
|
|
91
94
|
return this.hint("avatar");
|
|
@@ -210,7 +213,7 @@ var array = (item, count) => {
|
|
|
210
213
|
};
|
|
211
214
|
|
|
212
215
|
// src/index.ts
|
|
213
|
-
var __ffa_version = "0.16.
|
|
216
|
+
var __ffa_version = "0.16.1";
|
|
214
217
|
export {
|
|
215
218
|
__ffa_version,
|
|
216
219
|
array,
|
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 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"]}
|
|
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(width?: number, height?: number): this {\n this.hint('image')\n if (width !== undefined) this.def.rules.imageWidth = width\n if (height !== undefined) this.def.rules.imageHeight = height\n return this\n }\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 {\n string,\n number,\n boolean,\n uuid,\n datetime,\n enumField,\n belongsTo,\n hasMany,\n object,\n array,\n} from './field/factories'\nexport type {\n FakeHint,\n StringFakeHint,\n NumberFakeHint,\n MetaFn,\n MetaValue,\n} from './field/types'\n\nexport const __ffa_version = '0.16.1'\n"],"mappings":"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","names":["entity"]}
|