jax-hono 1.0.0 → 1.0.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/bin/jax.ts +16 -2
- package/build/generate-config.ts +7 -5
- package/build/generate-registry.ts +10 -13
- package/package.json +61 -6
- package/plugins/mongoose/model.ts +71 -60
package/bin/jax.ts
CHANGED
|
@@ -3,17 +3,31 @@
|
|
|
3
3
|
import { cac } from "cac";
|
|
4
4
|
import { $ } from "bun";
|
|
5
5
|
import path from "node:path";
|
|
6
|
+
import { existsSync } from "node:fs";
|
|
7
|
+
import { mkdir } from "node:fs/promises";
|
|
6
8
|
|
|
7
9
|
const cli = cac("jax");
|
|
8
10
|
|
|
9
11
|
cli
|
|
10
12
|
.command(
|
|
11
13
|
"link",
|
|
12
|
-
"Create a symlink
|
|
14
|
+
"Create a symlink to the jax-hono installation directory",
|
|
13
15
|
)
|
|
14
16
|
.action(async () => {
|
|
17
|
+
const cwd = process.cwd();
|
|
15
18
|
const sourceDir = path.resolve(import.meta.dir, "..");
|
|
16
|
-
const
|
|
19
|
+
const shouldUseNodeModules =
|
|
20
|
+
existsSync(path.join(cwd, "package.json")) ||
|
|
21
|
+
existsSync(path.join(cwd, "node_modules"));
|
|
22
|
+
const targetRoot = shouldUseNodeModules
|
|
23
|
+
? path.join(cwd, "node_modules")
|
|
24
|
+
: cwd;
|
|
25
|
+
const targetName = shouldUseNodeModules ? "jax-hono" : "jax";
|
|
26
|
+
const targetDir = path.resolve(targetRoot, targetName);
|
|
27
|
+
|
|
28
|
+
if (shouldUseNodeModules) {
|
|
29
|
+
await mkdir(targetRoot, { recursive: true });
|
|
30
|
+
}
|
|
17
31
|
|
|
18
32
|
if (process.platform === "win32") {
|
|
19
33
|
const result =
|
package/build/generate-config.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from 'node:fs'
|
|
2
|
+
import { cwd } from 'node:process'
|
|
2
3
|
import { join, parse, relative } from 'node:path'
|
|
3
4
|
|
|
4
|
-
const
|
|
5
|
+
const packageDir = join(import.meta.dir, '..')
|
|
6
|
+
const srcDir = join(cwd(), 'src')
|
|
5
7
|
const configDir = join(srcDir, 'config')
|
|
6
8
|
const typesFile = join(srcDir, 'types/index.ts')
|
|
7
|
-
const generatedDir = join(
|
|
9
|
+
const generatedDir = join(packageDir, 'generated')
|
|
8
10
|
const outputFile = join(generatedDir, 'config.ts')
|
|
9
11
|
const envStages = new Set([
|
|
10
12
|
'default',
|
|
@@ -35,9 +37,9 @@ function getStage(fileName: string) {
|
|
|
35
37
|
|
|
36
38
|
function getImportPath(fileName: string) {
|
|
37
39
|
const { dir, name } = parse(fileName)
|
|
38
|
-
const path = join(
|
|
40
|
+
const path = join(configDir, dir, name).replaceAll('\\', '/')
|
|
39
41
|
|
|
40
|
-
return path
|
|
42
|
+
return path
|
|
41
43
|
}
|
|
42
44
|
|
|
43
45
|
function getConfigFiles() {
|
|
@@ -83,7 +85,7 @@ export function generateConfig() {
|
|
|
83
85
|
return ` { name: '${fileName}', stage: '${getStage(fileName)}', config: ${toImportName(fileName, index)} },`
|
|
84
86
|
})
|
|
85
87
|
const hasProjectTypes = hasProjectConfigType()
|
|
86
|
-
const typeImports = hasProjectTypes ? [`import type { ProjectConfig } from '
|
|
88
|
+
const typeImports = hasProjectTypes ? [`import type { ProjectConfig } from '${join(srcDir, 'types').replaceAll('\\', '/')}'`] : []
|
|
87
89
|
const projectConfigType = hasProjectTypes
|
|
88
90
|
? 'export type { ProjectConfig }'
|
|
89
91
|
: defaultConfigIndex === -1
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from 'node:fs'
|
|
2
|
+
import { cwd } from 'node:process'
|
|
2
3
|
import { basename, join, parse, relative } from 'node:path'
|
|
3
4
|
|
|
4
|
-
const
|
|
5
|
-
const
|
|
5
|
+
const packageDir = join(import.meta.dir, '..')
|
|
6
|
+
const srcDir = join(cwd(), 'src')
|
|
7
|
+
const generatedDir = join(packageDir, 'generated')
|
|
6
8
|
const moduleExtensions = new Set(['.ts', '.js', '.mjs', '.cjs'])
|
|
7
|
-
const generatedHeader = `// This file is generated by
|
|
9
|
+
const generatedHeader = `// This file is generated by jax-hono/build/generate-registry.ts.
|
|
8
10
|
// Do not edit it directly.
|
|
9
11
|
`
|
|
10
12
|
|
|
@@ -75,11 +77,11 @@ function writeGeneratedFile(fileName: string, content: string) {
|
|
|
75
77
|
}
|
|
76
78
|
|
|
77
79
|
function toImportPath(filePath: string) {
|
|
78
|
-
const path =
|
|
80
|
+
const path = filePath
|
|
79
81
|
.replace(parse(filePath).ext, '')
|
|
80
82
|
.replaceAll('\\', '/')
|
|
81
83
|
|
|
82
|
-
return
|
|
84
|
+
return path
|
|
83
85
|
}
|
|
84
86
|
|
|
85
87
|
function toIdentifier(parts: string[]) {
|
|
@@ -277,7 +279,7 @@ function generateControllersRegistry() {
|
|
|
277
279
|
}
|
|
278
280
|
|
|
279
281
|
const helperImport = imports.length > 0
|
|
280
|
-
? `import { createController } from '
|
|
282
|
+
? `import { createController } from 'jax-hono/core/controller'\n`
|
|
281
283
|
: ''
|
|
282
284
|
const content = `${generatedHeader}
|
|
283
285
|
${helperImport}${imports.join('\n')}
|
|
@@ -531,15 +533,11 @@ function normalizePluginPackage(packageName: string, configFile: string) {
|
|
|
531
533
|
return packageName
|
|
532
534
|
}
|
|
533
535
|
|
|
534
|
-
const normalized =
|
|
536
|
+
const normalized = join(configFile, '..', packageName)
|
|
535
537
|
.replaceAll('\\', '/')
|
|
536
538
|
.replace(/\/index$/, '')
|
|
537
539
|
|
|
538
|
-
|
|
539
|
-
return normalized
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
return `@/${normalized}`
|
|
540
|
+
return normalized
|
|
543
541
|
}
|
|
544
542
|
|
|
545
543
|
function mergePluginConfig(configs: { filePath: string; config: PluginConfig }[]) {
|
|
@@ -578,7 +576,6 @@ function serializePluginOptions(options: unknown) {
|
|
|
578
576
|
|
|
579
577
|
function generatePluginContextRegistry() {
|
|
580
578
|
const enabledPlugins = mergePluginConfig([
|
|
581
|
-
{ filePath: join(srcDir, 'jax/plugins/config.ts'), config: readPluginConfig(join(srcDir, 'jax/plugins/config.ts')) },
|
|
582
579
|
{ filePath: join(srcDir, 'config/plugin.ts'), config: readPluginConfig(join(srcDir, 'config/plugin.ts')) },
|
|
583
580
|
])
|
|
584
581
|
const imports = enabledPlugins.map(([name, item]) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jax-hono",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Lightweight framework layer on top of Hono, built for Bun",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.ts",
|
|
@@ -10,7 +10,54 @@
|
|
|
10
10
|
"import": "./index.ts",
|
|
11
11
|
"types": "./index.ts"
|
|
12
12
|
},
|
|
13
|
-
"
|
|
13
|
+
"./setup": {
|
|
14
|
+
"import": "./setup.ts",
|
|
15
|
+
"types": "./setup.ts"
|
|
16
|
+
},
|
|
17
|
+
"./config": {
|
|
18
|
+
"import": "./config.ts",
|
|
19
|
+
"types": "./config.ts"
|
|
20
|
+
},
|
|
21
|
+
"./core/*": {
|
|
22
|
+
"import": "./core/*.ts",
|
|
23
|
+
"types": "./core/*.ts"
|
|
24
|
+
},
|
|
25
|
+
"./helpers": {
|
|
26
|
+
"import": "./helpers/index.ts",
|
|
27
|
+
"types": "./helpers/index.ts"
|
|
28
|
+
},
|
|
29
|
+
"./helpers/*": {
|
|
30
|
+
"import": "./helpers/*.ts",
|
|
31
|
+
"types": "./helpers/*.ts"
|
|
32
|
+
},
|
|
33
|
+
"./middleware/*": {
|
|
34
|
+
"import": "./middleware/*.ts",
|
|
35
|
+
"types": "./middleware/*.ts"
|
|
36
|
+
},
|
|
37
|
+
"./plugins/*": {
|
|
38
|
+
"import": "./plugins/*/index.ts",
|
|
39
|
+
"types": "./plugins/*/index.ts"
|
|
40
|
+
},
|
|
41
|
+
"./plugins/*/*": {
|
|
42
|
+
"import": "./plugins/*/*.ts",
|
|
43
|
+
"types": "./plugins/*/*.ts"
|
|
44
|
+
},
|
|
45
|
+
"./utils": {
|
|
46
|
+
"import": "./utils/index.ts",
|
|
47
|
+
"types": "./utils/index.ts"
|
|
48
|
+
},
|
|
49
|
+
"./utils/*": {
|
|
50
|
+
"import": "./utils/*.ts",
|
|
51
|
+
"types": "./utils/*.ts"
|
|
52
|
+
},
|
|
53
|
+
"./types": {
|
|
54
|
+
"import": "./types/index.ts",
|
|
55
|
+
"types": "./types/index.ts"
|
|
56
|
+
},
|
|
57
|
+
"./types/*": {
|
|
58
|
+
"import": "./types/*.ts",
|
|
59
|
+
"types": "./types/*.ts"
|
|
60
|
+
}
|
|
14
61
|
},
|
|
15
62
|
"bin": {
|
|
16
63
|
"jax": "./bin/jax.ts"
|
|
@@ -40,12 +87,20 @@
|
|
|
40
87
|
},
|
|
41
88
|
"peerDependencies": {
|
|
42
89
|
"dayjs": "*",
|
|
43
|
-
"deepmerge": "
|
|
44
|
-
"dotenv": "
|
|
90
|
+
"deepmerge": "^4.3.1",
|
|
91
|
+
"dotenv": "^17.4.2",
|
|
45
92
|
"jsonwebtoken": "*",
|
|
46
|
-
"minimist": "
|
|
93
|
+
"minimist": "^1.2.8",
|
|
47
94
|
"mongoose": "*"
|
|
48
95
|
},
|
|
96
|
+
"devDependencies": {
|
|
97
|
+
"dayjs": "^1.11.21",
|
|
98
|
+
"deepmerge": "^4.3.1",
|
|
99
|
+
"dotenv": "^17.4.2",
|
|
100
|
+
"jsonwebtoken": "^9.0.3",
|
|
101
|
+
"minimist": "^1.2.8",
|
|
102
|
+
"mongoose": "^8.24.1"
|
|
103
|
+
},
|
|
49
104
|
"peerDependenciesMeta": {
|
|
50
105
|
"dayjs": {
|
|
51
106
|
"optional": true
|
|
@@ -61,4 +116,4 @@
|
|
|
61
116
|
"bun": ">=1.0.0"
|
|
62
117
|
},
|
|
63
118
|
"license": "MIT"
|
|
64
|
-
}
|
|
119
|
+
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { basename, parse } from
|
|
1
|
+
import { basename, parse } from "node:path";
|
|
2
2
|
import mongoose, {
|
|
3
3
|
Schema,
|
|
4
4
|
model as mongooseModel,
|
|
5
5
|
type InferSchemaType,
|
|
6
6
|
type Model,
|
|
7
|
-
type SchemaOptions
|
|
8
|
-
} from
|
|
9
|
-
import config from
|
|
10
|
-
import { rankSetter } from
|
|
11
|
-
import dayjs from
|
|
7
|
+
type SchemaOptions,
|
|
8
|
+
} from "mongoose";
|
|
9
|
+
import config from "@/config";
|
|
10
|
+
import { rankSetter } from "./schema";
|
|
11
|
+
import dayjs from "dayjs";
|
|
12
12
|
|
|
13
13
|
export { rankSetter };
|
|
14
14
|
|
|
@@ -21,7 +21,7 @@ type PageOptions = {
|
|
|
21
21
|
export type ModelStatics = {
|
|
22
22
|
findPage(
|
|
23
23
|
filter?: Record<string, unknown>,
|
|
24
|
-
options?: PageOptions
|
|
24
|
+
options?: PageOptions,
|
|
25
25
|
): Promise<{
|
|
26
26
|
total: number;
|
|
27
27
|
list: unknown[];
|
|
@@ -48,14 +48,15 @@ export function createLooseModel(filePathOrName: string, collection?: string) {
|
|
|
48
48
|
installModelStatics(schema);
|
|
49
49
|
|
|
50
50
|
return (
|
|
51
|
-
mongoose.models[name] ??
|
|
51
|
+
mongoose.models[name] ??
|
|
52
|
+
mongooseModel(name, schema, collection ?? getCollectionName(name))
|
|
52
53
|
);
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
export function createSchemaModel<TSchema extends Schema>(
|
|
56
57
|
filePathOrName: string,
|
|
57
58
|
schema: TSchema,
|
|
58
|
-
collection?: string
|
|
59
|
+
collection?: string,
|
|
59
60
|
): Model<InferSchemaType<TSchema>> & ModelStatics {
|
|
60
61
|
const name = getModelName(filePathOrName);
|
|
61
62
|
|
|
@@ -67,7 +68,7 @@ export function createSchemaModel<TSchema extends Schema>(
|
|
|
67
68
|
mongooseModel<InferSchemaType<TSchema>>(
|
|
68
69
|
name,
|
|
69
70
|
schema as any,
|
|
70
|
-
collection ?? getCollectionName(name)
|
|
71
|
+
collection ?? getCollectionName(name),
|
|
71
72
|
)) as Model<InferSchemaType<TSchema>> & ModelStatics;
|
|
72
73
|
}
|
|
73
74
|
|
|
@@ -75,15 +76,16 @@ export const createModel = createSchemaModel;
|
|
|
75
76
|
|
|
76
77
|
export function getModelName(filePathOrName: string) {
|
|
77
78
|
const baseName =
|
|
78
|
-
filePathOrName.includes(
|
|
79
|
-
? parse(basename(filePathOrName)).name.replace(/\.model$/,
|
|
79
|
+
filePathOrName.includes("/") || filePathOrName.includes("\\")
|
|
80
|
+
? parse(basename(filePathOrName)).name.replace(/\.model$/, "")
|
|
80
81
|
: filePathOrName;
|
|
81
82
|
|
|
82
83
|
return toPascalCase(baseName);
|
|
83
84
|
}
|
|
84
85
|
|
|
85
86
|
export function getCollectionName(modelName: string) {
|
|
86
|
-
const prefix =
|
|
87
|
+
const prefix =
|
|
88
|
+
(config as any).mongoose?.prefix ?? (config as any).mongo?.prefix ?? "";
|
|
87
89
|
const name = toSnakeCase(modelName);
|
|
88
90
|
|
|
89
91
|
return prefix ? `${prefix}_${name}` : name;
|
|
@@ -102,23 +104,23 @@ export function schemaOptions(): SchemaOptions {
|
|
|
102
104
|
// }
|
|
103
105
|
|
|
104
106
|
if (ret.createdAt) {
|
|
105
|
-
ret.createdAt = dayjs(ret.createdAt).format(
|
|
107
|
+
ret.createdAt = dayjs(ret.createdAt).format("YYYY-MM-DD HH:mm:ss");
|
|
106
108
|
}
|
|
107
109
|
|
|
108
110
|
if (ret.updatedAt) {
|
|
109
|
-
ret.updatedAt = dayjs(ret.updatedAt).format(
|
|
111
|
+
ret.updatedAt = dayjs(ret.updatedAt).format("YYYY-MM-DD HH:mm:ss");
|
|
110
112
|
}
|
|
111
113
|
|
|
112
114
|
delete ret.__v;
|
|
113
115
|
delete ret._id;
|
|
114
116
|
|
|
115
117
|
return ret;
|
|
116
|
-
}
|
|
118
|
+
},
|
|
117
119
|
},
|
|
118
120
|
toObject: {
|
|
119
121
|
virtuals: true,
|
|
120
|
-
getters: true
|
|
121
|
-
}
|
|
122
|
+
getters: true,
|
|
123
|
+
},
|
|
122
124
|
};
|
|
123
125
|
}
|
|
124
126
|
|
|
@@ -126,37 +128,40 @@ export function applyDefaultSchemaOptions(schema: Schema) {
|
|
|
126
128
|
const defaults = schemaOptions();
|
|
127
129
|
|
|
128
130
|
if (schema.options.timestamps === undefined) {
|
|
129
|
-
schema.set(
|
|
131
|
+
schema.set("timestamps", defaults.timestamps);
|
|
130
132
|
}
|
|
131
133
|
|
|
132
|
-
if (
|
|
133
|
-
schema.
|
|
134
|
+
if (
|
|
135
|
+
schema.options.versionKey === undefined ||
|
|
136
|
+
schema.options.versionKey === "__v"
|
|
137
|
+
) {
|
|
138
|
+
schema.set("versionKey", defaults.versionKey);
|
|
134
139
|
}
|
|
135
140
|
|
|
136
141
|
const toJSON = {
|
|
137
142
|
...defaults.toJSON,
|
|
138
|
-
...(schema.options.toJSON ?? {})
|
|
143
|
+
...(schema.options.toJSON ?? {}),
|
|
139
144
|
} as any;
|
|
140
145
|
|
|
141
|
-
schema.set(
|
|
142
|
-
schema.set(
|
|
146
|
+
schema.set("toJSON", toJSON);
|
|
147
|
+
schema.set("toObject", {
|
|
143
148
|
...defaults.toObject,
|
|
144
|
-
...(schema.options.toObject ?? {})
|
|
149
|
+
...(schema.options.toObject ?? {}),
|
|
145
150
|
} as any);
|
|
146
151
|
}
|
|
147
152
|
|
|
148
153
|
export function installRankHooks(schema: Schema) {
|
|
149
|
-
schema.pre([
|
|
154
|
+
schema.pre(["updateOne", "findOneAndUpdate", "updateMany"], function () {
|
|
150
155
|
normalizeRank(this.getUpdate());
|
|
151
156
|
});
|
|
152
157
|
|
|
153
|
-
schema.pre(
|
|
158
|
+
schema.pre("save", function () {
|
|
154
159
|
normalizeRank(this);
|
|
155
160
|
});
|
|
156
161
|
}
|
|
157
162
|
|
|
158
163
|
export function installAutoNo(schema: Schema, field: string, start = 0) {
|
|
159
|
-
schema.pre(
|
|
164
|
+
schema.pre("save", async function () {
|
|
160
165
|
if (!this.isNew || this.get(field)) {
|
|
161
166
|
return;
|
|
162
167
|
}
|
|
@@ -169,29 +174,32 @@ export function installAutoNo(schema: Schema, field: string, start = 0) {
|
|
|
169
174
|
}
|
|
170
175
|
|
|
171
176
|
export function installModelStatics(schema: Schema) {
|
|
172
|
-
schema.static(
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
177
|
+
schema.static(
|
|
178
|
+
"findPage",
|
|
179
|
+
async function findPage(filter = {}, options: PageOptions = {}) {
|
|
180
|
+
const page = Number(options.page || 1);
|
|
181
|
+
const pageSize = Number(options.pageSize || 20);
|
|
182
|
+
const sort = (options.sort ?? { _id: -1 }) as any;
|
|
183
|
+
const total = await this.countDocuments(filter);
|
|
184
|
+
let query = this.find(filter).sort(sort);
|
|
185
|
+
|
|
186
|
+
if (pageSize !== -1) {
|
|
187
|
+
query = query.skip((page - 1) * pageSize).limit(pageSize);
|
|
188
|
+
}
|
|
182
189
|
|
|
183
|
-
|
|
190
|
+
const list = await query;
|
|
184
191
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
192
|
+
return {
|
|
193
|
+
total,
|
|
194
|
+
list,
|
|
195
|
+
maxPage: pageSize === -1 ? 1 : Math.ceil(total / pageSize),
|
|
196
|
+
page,
|
|
197
|
+
pageSize,
|
|
198
|
+
};
|
|
199
|
+
},
|
|
200
|
+
);
|
|
193
201
|
|
|
194
|
-
schema.static(
|
|
202
|
+
schema.static("tree", async function tree(options: any = {}) {
|
|
195
203
|
const docs = await this.find(options.filter ?? {})
|
|
196
204
|
.sort(options.sort ?? {})
|
|
197
205
|
.lean({ virtuals: true });
|
|
@@ -204,7 +212,7 @@ export function installModelStatics(schema: Schema) {
|
|
|
204
212
|
}
|
|
205
213
|
|
|
206
214
|
for (const item of byId.values()) {
|
|
207
|
-
const parentId = item.parentId ? String(item.parentId) :
|
|
215
|
+
const parentId = item.parentId ? String(item.parentId) : "";
|
|
208
216
|
const parent = parentId ? byId.get(parentId) : undefined;
|
|
209
217
|
|
|
210
218
|
if (parent) {
|
|
@@ -217,24 +225,27 @@ export function installModelStatics(schema: Schema) {
|
|
|
217
225
|
return tree;
|
|
218
226
|
});
|
|
219
227
|
|
|
220
|
-
schema.static(
|
|
221
|
-
|
|
222
|
-
|
|
228
|
+
schema.static(
|
|
229
|
+
"flatTree",
|
|
230
|
+
async function flatTree(this: any, options: any = {}) {
|
|
231
|
+
const tree = await this.tree(options);
|
|
232
|
+
const list: any[] = [];
|
|
223
233
|
|
|
224
|
-
|
|
234
|
+
walkTree(tree, 1, list);
|
|
225
235
|
|
|
226
|
-
|
|
227
|
-
|
|
236
|
+
return list;
|
|
237
|
+
},
|
|
238
|
+
);
|
|
228
239
|
}
|
|
229
240
|
|
|
230
241
|
export function installCommonFields(schema: Schema) {
|
|
231
242
|
const fields: Record<string, unknown> = {};
|
|
232
243
|
|
|
233
|
-
if (!schema.path(
|
|
244
|
+
if (!schema.path("isDelete")) {
|
|
234
245
|
fields.isDelete = { type: Boolean, default: false };
|
|
235
246
|
}
|
|
236
247
|
|
|
237
|
-
if (!schema.path(
|
|
248
|
+
if (!schema.path("isOpen")) {
|
|
238
249
|
fields.isOpen = { type: Boolean, default: false };
|
|
239
250
|
}
|
|
240
251
|
|
|
@@ -245,14 +256,14 @@ export function installCommonFields(schema: Schema) {
|
|
|
245
256
|
|
|
246
257
|
export function toSnakeCase(value: string) {
|
|
247
258
|
return value
|
|
248
|
-
.replace(/([a-z0-9])([A-Z])/g,
|
|
249
|
-
.replace(/[-\s]+/g,
|
|
259
|
+
.replace(/([a-z0-9])([A-Z])/g, "$1_$2")
|
|
260
|
+
.replace(/[-\s]+/g, "_")
|
|
250
261
|
.toLowerCase();
|
|
251
262
|
}
|
|
252
263
|
|
|
253
264
|
function toPascalCase(value: string) {
|
|
254
265
|
const camel = value.replace(/[-_\s]+([a-zA-Z0-9])/g, (_match, char: string) =>
|
|
255
|
-
char.toUpperCase()
|
|
266
|
+
char.toUpperCase(),
|
|
256
267
|
);
|
|
257
268
|
|
|
258
269
|
return camel.charAt(0).toUpperCase() + camel.slice(1);
|