fauxy 0.0.1-alpha.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 ADDED
@@ -0,0 +1,47 @@
1
+ # Vue Api Mock 182
2
+ description
3
+
4
+ ## Содержание
5
+ - [Начало работы](#начало-работы)
6
+
7
+ ## Начало работы
8
+
9
+ #### Установка пакета
10
+ ```bash
11
+ npm i fauxy
12
+ ```
13
+
14
+ #### Настройка окружения
15
+ 1. Для добавления Mock API в Laravel Mix, необходимо добавить новый файл, например, `resources/ts/mock.ts` с содержимым:
16
+ ```ts
17
+ import { mockApi } from 'fauxy'
18
+
19
+ mockApi.start()
20
+ ```
21
+
22
+ 2. Изменить файл `package.json`:
23
+ ```json
24
+ "scripts": {
25
+ "watch:msw": "MIX_MOCK_API=true mix watch",
26
+ },
27
+ ```
28
+
29
+ Добавить в конец файла:
30
+ ```json
31
+ "msw": {
32
+ "workerDirectory": [
33
+ "public"
34
+ ]
35
+ }
36
+ ```
37
+
38
+ 3. В файле `webpack.mix.js` добавить в сборку файл `mock.ts` (из п.1):
39
+ ```js
40
+ const mockSrc = process.env.MIX_MOCK_API === 'true' ? ['resources/ts/mock.ts'] : [];
41
+
42
+ mix
43
+ .ts([
44
+ ...mockSrc,
45
+ 'resources/ts/vue.ts'
46
+ ], 'public/js/vue.js')
47
+ ```
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+
6
+ const colors = {
7
+ error: '\x1b[31m',
8
+ success: '\x1b[32m',
9
+ reset: '\x1b[0m'
10
+ };
11
+
12
+ const sourceSwPath = path.join(__dirname, '../node_modules/msw/lib/mockServiceWorker.js');
13
+ const targetSwPath = path.join(process.cwd(), 'public/mockServiceWorker.js');
14
+
15
+ try {
16
+ if (!fs.existsSync(sourceSwPath)) {
17
+ console.error(colors.error + '❌ Mock Service Worker not found' + colors.reset);
18
+ process.exit(0);
19
+ }
20
+
21
+ const publicDir = path.dirname(targetSwPath);
22
+ if (!fs.existsSync(publicDir)) {
23
+ fs.mkdirSync(publicDir, { recursive: true });
24
+ }
25
+
26
+ fs.copyFileSync(sourceSwPath, targetSwPath);
27
+ console.log(colors.success + '✅ Mock Service Worker copied to public/' + colors.reset);
28
+
29
+ } catch (error) {
30
+ console.error(colors.error + '❌ Failed to copy Mock Service Worker:' + colors.reset);
31
+ console.error(colors.error + error.message + colors.reset);
32
+ }
@@ -0,0 +1,9 @@
1
+ import { HttpResponse, RequestHandler, delay, http, passthrough } from 'msw'
2
+ import { SetupWorkerApi } from 'msw/browser'
3
+ import { Faker } from '@/faker/faker'
4
+
5
+ export { HttpResponse, RequestHandler, http, delay, passthrough }
6
+
7
+ export declare const mockApi: (handlers: RequestHandler[]) => SetupWorkerApi
8
+
9
+ export declare function faker(): typeof Faker
@@ -0,0 +1,153 @@
1
+ import { generate } from './generators'
2
+ import {
3
+ ArrayElementFakerConfig,
4
+ ArrayElementsFakerConfig,
5
+ ArrayFakerConfig,
6
+ CallbackFakerConfig,
7
+ ExtractFakerConfig,
8
+ FakerType,
9
+ NumberFakerConfig,
10
+ ObjectFakerConfig,
11
+ WordsFakerConfig,
12
+ } from './types'
13
+
14
+ export class Faker<T extends FakerType> {
15
+ private readonly params: {
16
+ config: ExtractFakerConfig<T>
17
+ nullable: boolean
18
+ nullableProbability: number
19
+ }
20
+
21
+ private constructor(config: ExtractFakerConfig<T>) {
22
+ this.params = {
23
+ config,
24
+ nullable: false,
25
+ nullableProbability: 0,
26
+ }
27
+ }
28
+
29
+ public static uuid() {
30
+ return new Faker<'uuid'>({
31
+ type: 'uuid',
32
+ })
33
+ }
34
+
35
+ public static boolean() {
36
+ return new Faker<'boolean'>({
37
+ type: 'boolean',
38
+ })
39
+ }
40
+
41
+ public static words(params: Omit<WordsFakerConfig, 'type'> = {}) {
42
+ return new Faker<'words'>({
43
+ type: 'words',
44
+ count: params?.count,
45
+ })
46
+ }
47
+
48
+ public static number(params: Omit<NumberFakerConfig, 'type'> = {}) {
49
+ return new Faker<'number'>({
50
+ type: 'number',
51
+ min: params?.min ?? 0,
52
+ max: params?.max ?? 1000,
53
+ })
54
+ }
55
+
56
+ public static url() {
57
+ return new Faker<'url'>({
58
+ type: 'url',
59
+ })
60
+ }
61
+
62
+ public static date() {
63
+ return new Faker<'date'>({
64
+ type: 'date',
65
+ })
66
+ }
67
+
68
+ public static fullName() {
69
+ return new Faker<'fullName'>({
70
+ type: 'fullName',
71
+ })
72
+ }
73
+
74
+ public static personalNumber() {
75
+ return new Faker<'personalNumber'>({
76
+ type: 'personalNumber',
77
+ })
78
+ }
79
+
80
+ public static rank() {
81
+ return new Faker<'rank'>({
82
+ type: 'rank',
83
+ })
84
+ }
85
+
86
+ public static arrayElement(params: Omit<ArrayElementFakerConfig, 'type'>) {
87
+ return new Faker<'arrayElement'>({
88
+ type: 'arrayElement',
89
+ items: params.items,
90
+ })
91
+ }
92
+
93
+ public static arrayElements(params: Omit<ArrayElementsFakerConfig, 'type'>) {
94
+ return new Faker<'arrayElements'>({
95
+ type: 'arrayElements',
96
+ items: params.items,
97
+ count: params?.count,
98
+ })
99
+ }
100
+
101
+ public static callback(callback: CallbackFakerConfig['callback']) {
102
+ return new Faker<'callback'>({
103
+ type: 'callback',
104
+ callback,
105
+ })
106
+ }
107
+
108
+ public static array(params: Omit<ArrayFakerConfig, 'type'>) {
109
+ return new Faker<'array'>({
110
+ type: 'array',
111
+ items: params.items,
112
+ count: params.count,
113
+ })
114
+ }
115
+
116
+ public static object<O extends object = object>(params: Omit<ObjectFakerConfig<O>, 'type'>) {
117
+ return new Faker<'object'>({
118
+ type: 'object',
119
+ properties: params.properties,
120
+ })
121
+ }
122
+
123
+ // modifiers
124
+ public nullable(probability: number = 0.5) {
125
+ this.params.nullable = true
126
+ this.params.nullableProbability = probability
127
+
128
+ return this
129
+ }
130
+
131
+ // create methods
132
+ private createSingle<U>(): U {
133
+ return generate(this.params) as U
134
+ }
135
+
136
+ private createMultiple<U>(count: number): U[] {
137
+ return Array(count)
138
+ .fill(null)
139
+ .map(() => this.createSingle<U>())
140
+ }
141
+
142
+ public create<U>(): U
143
+
144
+ public create<U>(count: number): U[]
145
+
146
+ public create<U>(count?: number): U | U[] {
147
+ if (count === undefined) {
148
+ return this.createSingle<U>()
149
+ }
150
+
151
+ return this.createMultiple<U>(count)
152
+ }
153
+ }
@@ -0,0 +1,7 @@
1
+ import { faker } from '@faker-js/faker'
2
+ import { ArrayElementFakerConfig } from '../types'
3
+
4
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
5
+ export const generateArrayElement = (config: ArrayElementFakerConfig) => {
6
+ return faker.helpers.arrayElement(config.items)
7
+ }
@@ -0,0 +1,8 @@
1
+ import { faker } from '@faker-js/faker'
2
+ import { makeCount } from '@/faker/utils'
3
+ import { ArrayElementsFakerConfig } from '../types'
4
+
5
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
6
+ export const generateArrayElements = (config: ArrayElementsFakerConfig) => {
7
+ return faker.helpers.arrayElements(config.items, makeCount(config.count))
8
+ }
@@ -0,0 +1,10 @@
1
+ import { makeCount } from '@/faker/utils'
2
+ import { ArrayFakerConfig } from '../types'
3
+
4
+ export const generateArray = (config: ArrayFakerConfig) => {
5
+ return Array(makeCount(config.count))
6
+ .fill(null)
7
+ .map(() => {
8
+ return config.items.create()
9
+ })
10
+ }
@@ -0,0 +1,7 @@
1
+ import { faker } from '@faker-js/faker'
2
+ import { BooleanFakerConfig } from '../types'
3
+
4
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
5
+ export const generateBoolean = (config: BooleanFakerConfig) => {
6
+ return faker.datatype.boolean()
7
+ }
@@ -0,0 +1,5 @@
1
+ import { CallbackFakerConfig } from '../types'
2
+
3
+ export const generateCallback = (config: CallbackFakerConfig) => {
4
+ return config.callback()
5
+ }
@@ -0,0 +1,13 @@
1
+ import { faker } from '@faker-js/faker'
2
+ import { DateFakerConfig } from '../types'
3
+
4
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
5
+ export const generateDate = (config: DateFakerConfig) => {
6
+ const date = new Date(faker.date.anytime())
7
+
8
+ const day = date.getDate()
9
+ const month = date.getMonth() + 1
10
+ const year = date.getFullYear()
11
+
12
+ return `${day}.${month.toString().padStart(2, '0')}.${year}`
13
+ }
@@ -0,0 +1,11 @@
1
+ import { fakerRU } from '@faker-js/faker'
2
+ import { FullNameFakerConfig } from '../types'
3
+
4
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
5
+ export const generateFullName = (config: FullNameFakerConfig) => {
6
+ const firstName = fakerRU.person.firstName('male')
7
+ const lastName = fakerRU.person.lastName('male')
8
+ const middleName = fakerRU.person.middleName('male')
9
+
10
+ return `${lastName} ${firstName} ${middleName}`
11
+ }
@@ -0,0 +1,66 @@
1
+ import { FakerConfig } from '../types'
2
+ import { generateArray } from './array'
3
+ import { generateArrayElement } from './array-element'
4
+ import { generateArrayElements } from './array-elements'
5
+ import { generateBoolean } from './boolean'
6
+ import { generateCallback } from './callback'
7
+ import { generateDate } from './date'
8
+ import { generateFullName } from './full-name'
9
+ import { generateNumber } from './number'
10
+ import { generateObject } from './object'
11
+ import { generatePersonalNumber } from './personal-number'
12
+ import { generateRank } from './rank'
13
+ import { generateUrl } from './url'
14
+ import { generateUuid } from './uuid'
15
+ import { generateWords } from './words'
16
+
17
+ const random = (probability: number) => {
18
+ return Math.random() < probability
19
+ }
20
+
21
+ export const generate = (params: {
22
+ config: FakerConfig
23
+ nullable: boolean
24
+ nullableProbability: number
25
+ }) => {
26
+ const { type } = params.config
27
+
28
+ if (params.nullable && random(params.nullableProbability)) {
29
+ return null
30
+ }
31
+
32
+ switch (type) {
33
+ case 'uuid':
34
+ return generateUuid(params.config)
35
+ case 'boolean':
36
+ return generateBoolean(params.config)
37
+ case 'words':
38
+ return generateWords(params.config)
39
+ case 'number':
40
+ return generateNumber(params.config)
41
+ case 'url':
42
+ return generateUrl(params.config)
43
+ case 'date':
44
+ return generateDate(params.config)
45
+ case 'personalNumber':
46
+ return generatePersonalNumber(params.config)
47
+ case 'fullName':
48
+ return generateFullName(params.config)
49
+ case 'rank':
50
+ return generateRank(params.config)
51
+ case 'arrayElement':
52
+ return generateArrayElement(params.config)
53
+ case 'arrayElements':
54
+ return generateArrayElements(params.config)
55
+ case 'callback':
56
+ return generateCallback(params.config)
57
+ case 'object':
58
+ return generateObject(params.config)
59
+ case 'array':
60
+ return generateArray(params.config)
61
+ default: {
62
+ const _: never = type
63
+ throw new Error(`Unsupported type ${_}`)
64
+ }
65
+ }
66
+ }
@@ -0,0 +1,9 @@
1
+ import { faker } from '@faker-js/faker'
2
+ import { NumberFakerConfig } from '../types'
3
+
4
+ export const generateNumber = (config: NumberFakerConfig) => {
5
+ return faker.number.int({
6
+ min: config.min,
7
+ max: config.max,
8
+ })
9
+ }
@@ -0,0 +1,15 @@
1
+ import { Faker } from '@/faker/faker'
2
+ import { ObjectFakerConfig } from '../types'
3
+
4
+ export const generateObject = (config: ObjectFakerConfig) => {
5
+ return Object.keys(config.properties).reduce((carry, propertyName) => {
6
+ const propertyValue = config.properties[propertyName]
7
+
8
+ const value = propertyValue instanceof Faker ? propertyValue.create() : propertyValue
9
+
10
+ return {
11
+ ...carry,
12
+ [propertyName]: value,
13
+ }
14
+ }, {})
15
+ }
@@ -0,0 +1,12 @@
1
+ import { PersonalNumberFakerConfig } from '../types'
2
+
3
+ const letters = ['Х', 'Э', 'ВЕ', 'Е']
4
+ const digits = '0123456789'
5
+
6
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
7
+ export const generatePersonalNumber = (config: PersonalNumberFakerConfig) => {
8
+ return `${letters[Math.floor(Math.random() * letters.length)]}-${Array.from(
9
+ { length: 6 },
10
+ () => digits[Math.floor(Math.random() * digits.length)],
11
+ ).join('')}`
12
+ }
@@ -0,0 +1,36 @@
1
+ import { RankFakerConfig } from '../types'
2
+
3
+ const ranks = [
4
+ 'рядовой',
5
+ 'матрос',
6
+ 'ефрейтор',
7
+ 'старший матрос',
8
+ 'младший сержант',
9
+ 'старшина 2 статьи',
10
+ 'сержант',
11
+ 'старшина 3 статьи',
12
+ 'старший сержант',
13
+ 'главный старшина',
14
+ 'старшина',
15
+ 'главный корабельный старшина',
16
+ 'прапорщик',
17
+ 'мичман',
18
+ 'старший прапорщик',
19
+ 'старший мичман',
20
+ 'младший лейтенант',
21
+ 'лейтенант',
22
+ 'старший лейтенант',
23
+ 'капитан',
24
+ 'капитан-лейтенант',
25
+ 'майор',
26
+ 'капитан 3 ранга',
27
+ 'подполковник',
28
+ 'капитан 2 ранга',
29
+ 'полковник',
30
+ 'капитан 1 ранга',
31
+ ]
32
+
33
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
34
+ export const generateRank = (config: RankFakerConfig) => {
35
+ return ranks[Math.floor(Math.random() * ranks.length)]
36
+ }
@@ -0,0 +1,7 @@
1
+ import { faker } from '@faker-js/faker'
2
+ import { UrlFakerConfig } from '../types'
3
+
4
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
5
+ export const generateUrl = (config: UrlFakerConfig) => {
6
+ return faker.internet.url()
7
+ }
@@ -0,0 +1,7 @@
1
+ import { faker } from '@faker-js/faker'
2
+ import { UuidFakerConfig } from '../types'
3
+
4
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
5
+ export const generateUuid = (config: UuidFakerConfig) => {
6
+ return faker.string.uuid()
7
+ }
@@ -0,0 +1,10 @@
1
+ import { fakerRU } from '@faker-js/faker'
2
+ import { makeCount } from '@/faker/utils'
3
+ import { WordsFakerConfig } from '../types'
4
+
5
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
6
+ export const generateWords = (config: WordsFakerConfig) => {
7
+ return fakerRU.word.words({
8
+ count: makeCount(config?.count),
9
+ })
10
+ }
@@ -0,0 +1,5 @@
1
+ import { Faker } from '@/faker/faker'
2
+
3
+ export const faker = () => {
4
+ return Faker
5
+ }
@@ -0,0 +1,121 @@
1
+ import { Faker } from './faker'
2
+
3
+ /**
4
+ * Utils
5
+ */
6
+ export type Count =
7
+ | number
8
+ | {
9
+ min: number
10
+ max: number
11
+ }
12
+
13
+ /**
14
+ * Mock config
15
+ */
16
+ export type FakerType =
17
+ | 'uuid'
18
+ | 'boolean'
19
+ | 'words'
20
+ | 'number'
21
+ | 'url'
22
+ | 'fullName'
23
+ | 'date'
24
+ | 'personalNumber'
25
+ | 'rank'
26
+ | 'arrayElement'
27
+ | 'arrayElements'
28
+ | 'callback'
29
+ | 'array'
30
+ | 'object'
31
+
32
+ interface BaseFakerConfig {
33
+ type: FakerType
34
+ }
35
+
36
+ export interface UuidFakerConfig extends BaseFakerConfig {
37
+ type: 'uuid'
38
+ }
39
+
40
+ export interface BooleanFakerConfig extends BaseFakerConfig {
41
+ type: 'boolean'
42
+ }
43
+
44
+ export interface WordsFakerConfig extends BaseFakerConfig {
45
+ type: 'words'
46
+ count?: Count
47
+ }
48
+
49
+ export interface NumberFakerConfig extends BaseFakerConfig {
50
+ type: 'number'
51
+ min?: number
52
+ max?: number
53
+ }
54
+
55
+ export interface UrlFakerConfig extends BaseFakerConfig {
56
+ type: 'url'
57
+ }
58
+
59
+ export interface DateFakerConfig extends BaseFakerConfig {
60
+ type: 'date'
61
+ }
62
+
63
+ export interface FullNameFakerConfig extends BaseFakerConfig {
64
+ type: 'fullName'
65
+ }
66
+
67
+ export interface PersonalNumberFakerConfig extends BaseFakerConfig {
68
+ type: 'personalNumber'
69
+ }
70
+
71
+ export interface RankFakerConfig extends BaseFakerConfig {
72
+ type: 'rank'
73
+ }
74
+
75
+ export interface ArrayElementFakerConfig extends BaseFakerConfig {
76
+ type: 'arrayElement'
77
+ items: unknown[]
78
+ }
79
+
80
+ export interface ArrayElementsFakerConfig extends BaseFakerConfig {
81
+ type: 'arrayElements'
82
+ items: unknown[]
83
+ count?: Count
84
+ }
85
+
86
+ export interface CallbackFakerConfig extends BaseFakerConfig {
87
+ type: 'callback'
88
+ callback: (...args: unknown[]) => any
89
+ }
90
+
91
+ export interface ArrayFakerConfig extends BaseFakerConfig {
92
+ type: 'array'
93
+ items: Faker<any>
94
+ count: Count
95
+ }
96
+
97
+ export interface ObjectFakerConfig<O extends Record<string, any> = Record<string, any>>
98
+ extends BaseFakerConfig {
99
+ type: 'object'
100
+ properties: {
101
+ [_ in keyof O]: Faker<any> | any
102
+ }
103
+ }
104
+
105
+ export type FakerConfig =
106
+ | UuidFakerConfig
107
+ | BooleanFakerConfig
108
+ | WordsFakerConfig
109
+ | NumberFakerConfig
110
+ | UrlFakerConfig
111
+ | FullNameFakerConfig
112
+ | DateFakerConfig
113
+ | PersonalNumberFakerConfig
114
+ | RankFakerConfig
115
+ | ArrayElementFakerConfig
116
+ | ArrayElementsFakerConfig
117
+ | CallbackFakerConfig
118
+ | ArrayFakerConfig
119
+ | ObjectFakerConfig
120
+
121
+ export type ExtractFakerConfig<T extends FakerType> = Extract<FakerConfig, { type: T }>
@@ -0,0 +1,23 @@
1
+ import { Count } from '@/faker/types'
2
+
3
+ export const makeCount = (count?: Count): number => {
4
+ if (count === undefined) {
5
+ return 1
6
+ }
7
+
8
+ if (typeof count === 'number') {
9
+ return count
10
+ }
11
+
12
+ const { min, max } = count
13
+
14
+ if (min > max) {
15
+ throw new Error('Min cannot be greater than max')
16
+ }
17
+
18
+ if (min < 0 || max < 0) {
19
+ throw new Error('Count values cannot be negative')
20
+ }
21
+
22
+ return Math.floor(Math.random() * (max - min + 1)) + min
23
+ }
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from './msw'
2
+ export * from './faker'
@@ -0,0 +1,14 @@
1
+ import { HttpResponse, RequestHandler, delay, http, passthrough } from 'msw'
2
+ import { setupWorker } from 'msw/browser'
3
+
4
+ const mockApi = async (handlers: RequestHandler[]) => {
5
+ const worker = setupWorker(...handlers)
6
+
7
+ await worker.start({
8
+ onUnhandledRequest: 'bypass',
9
+ })
10
+
11
+ return worker
12
+ }
13
+
14
+ export { mockApi, HttpResponse, RequestHandler, http, delay, passthrough }