@zwa73/utils 1.0.86 → 1.0.88

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/compile.bat CHANGED
@@ -1,2 +1,2 @@
1
- npm run compile
1
+ call npm run compile
2
2
  pause
@@ -1,4 +1,4 @@
1
- import { JToken } from "./UtilInterfaces";
1
+ import { JObject, JToken } from "./UtilInterfaces";
2
2
  /**文件工具 */
3
3
  export declare namespace UtilFT {
4
4
  /**验证路径 文件或文件夹 是否存在 异步
@@ -84,4 +84,23 @@ export declare namespace UtilFT {
84
84
  * @deprecated 请使用 fileSearchRegex 或 fileSearchGlob
85
85
  */
86
86
  function fileSearch(...patams: any[]): void;
87
+ /**是一个有效的文件路径
88
+ * @param filePath - 需要验证的文件路径
89
+ */
90
+ function isValidFilePath(filePath: string): boolean;
91
+ /**构造Schema
92
+ * @async
93
+ * @param configPath - tsconfig路径
94
+ * @param outDir - schema文件夹路径 如 ./schema/
95
+ * @param coverDefine - 将会覆盖 definitions 对应内容的表
96
+ */
97
+ function builAllSchema(configPath: string, outDir: string, coverDefine?: JObject): Promise<void>;
98
+ /**生成匹配的文件的所有type的schema
99
+ * @async
100
+ * @param globPattern - glob匹配符
101
+ * @param outDir - schema输出路径目录 如 ./schema/
102
+ * @param ignore - glob忽略匹配符
103
+ * @param coverDefine - 将会覆盖 definitions 对应内容的表
104
+ */
105
+ function buildMatchSchema(globPattern: string | string[], outDir: string, ignore?: string | string[], coverDefine?: JObject): Promise<void>;
87
106
  }
@@ -7,6 +7,7 @@ const UtilLogger_1 = require("./UtilLogger");
7
7
  const JSON5 = require("json5");
8
8
  const glob_1 = require("glob");
9
9
  const UtilFunctions_1 = require("./UtilFunctions");
10
+ const TJS = require("typescript-json-schema");
10
11
  /**文件工具 */
11
12
  var UtilFT;
12
13
  (function (UtilFT) {
@@ -204,4 +205,99 @@ var UtilFT;
204
205
  throw "请使用 fileSearchRegex 或 fileSearchGlob";
205
206
  }
206
207
  UtilFT.fileSearch = fileSearch;
208
+ /**是一个有效的文件路径
209
+ * @param filePath - 需要验证的文件路径
210
+ */
211
+ function isValidFilePath(filePath) {
212
+ if (filePath.length > 255)
213
+ return false;
214
+ const invalidCharacters = ['<', '>', '"', '|', '?', '*'];
215
+ for (const invalidCharacter of invalidCharacters) {
216
+ if (filePath.includes(invalidCharacter))
217
+ return false;
218
+ }
219
+ return true;
220
+ }
221
+ UtilFT.isValidFilePath = isValidFilePath;
222
+ //#region schema
223
+ /**构造Schema
224
+ * @async
225
+ * @param configPath - tsconfig路径
226
+ * @param outDir - schema文件夹路径 如 ./schema/
227
+ * @param coverDefine - 将会覆盖 definitions 对应内容的表
228
+ */
229
+ async function builAllSchema(configPath, outDir, coverDefine = {}) {
230
+ outDir = path.join(outDir, "schemas.json");
231
+ const log = await UtilFunctions_1.UtilFunc.exec(`typescript-json-schema ${configPath} * --out ${outDir} --required --strictNullChecks --aliasRefs`);
232
+ console.log(log);
233
+ const schema = (await UtilFT.loadJSONFileSync(outDir));
234
+ //进行预处理并展开
235
+ await expandSchema(outDir, schema, coverDefine);
236
+ }
237
+ UtilFT.builAllSchema = builAllSchema;
238
+ /**生成匹配的文件的所有type的schema
239
+ * @async
240
+ * @param globPattern - glob匹配符
241
+ * @param outDir - schema输出路径目录 如 ./schema/
242
+ * @param ignore - glob忽略匹配符
243
+ * @param coverDefine - 将会覆盖 definitions 对应内容的表
244
+ */
245
+ async function buildMatchSchema(globPattern, outDir, ignore, coverDefine = {}) {
246
+ //生成
247
+ const settings = {
248
+ required: true,
249
+ aliasRef: true,
250
+ };
251
+ const compilerOptions = {
252
+ strictNullChecks: true,
253
+ };
254
+ const files = UtilFT.fileSearchGlob(globPattern, ignore);
255
+ const program = TJS.getProgramFromFiles(files, compilerOptions);
256
+ const schema = TJS.generateSchema(program, "*", settings);
257
+ outDir = outDir ?? path.join(process.cwd(), 'schema');
258
+ const schemasPath = path.join(outDir, 'schemas.json');
259
+ //进行预处理并展开
260
+ await expandSchema(schemasPath, schema, coverDefine);
261
+ }
262
+ UtilFT.buildMatchSchema = buildMatchSchema;
263
+ /**展开schema以供使用 */
264
+ async function expandSchema(schemasPath, schema, coverDefine) {
265
+ //覆盖
266
+ coverObj(schema["definitions"], coverDefine);
267
+ //替换SchemaString标识符
268
+ schema = JSON.parse(JSON.stringify(schema).replace(/\^\.\*SchemaString\$/g, '^.*$'));
269
+ const plist = [];
270
+ plist.push(UtilFT.writeJSONFile(schemasPath, schema));
271
+ const definitions = schema["definitions"];
272
+ //展开定义
273
+ for (const typeName in definitions) {
274
+ const schema = definitions[typeName];
275
+ //展开所有object与忽略检测的类型
276
+ if (!(schema.type == "object" || schema.type == "array" || schema.type == undefined))
277
+ continue;
278
+ if ((/^.+_[0-9]/).test(typeName) || (/^{./).test(typeName))
279
+ continue;
280
+ const basename = path.basename(schemasPath);
281
+ const tpath = path.join(path.dirname(schemasPath), `${typeName}.schema.json`);
282
+ if (!isValidFilePath(tpath))
283
+ continue;
284
+ plist.push(UtilFT.writeJSONFile(tpath, {
285
+ "$schema": "http://json-schema.org/draft-07/schema#",
286
+ "$ref": `${basename}#/definitions/${typeName}`
287
+ }));
288
+ }
289
+ await Promise.all(plist);
290
+ }
291
+ /**覆盖object */
292
+ function coverObj(base, cover) {
293
+ for (const k in cover) {
294
+ const v = cover[k];
295
+ if (typeof v === "object" && !Array.isArray(v) &&
296
+ typeof base[k] === "object" && !Array.isArray(base[k]))
297
+ coverObj(base[k], v);
298
+ else
299
+ base[k] = v;
300
+ }
301
+ }
302
+ //#endregion
207
303
  })(UtilFT || (exports.UtilFT = UtilFT = {}));
@@ -134,4 +134,8 @@ export type Matchable<T extends Keyable> = T | Outcome<T, unknown>;
134
134
  export type MatchableFlag<T> = T extends infer O | Outcome<infer O, unknown> ? O : never;
135
135
  /**从联合 Outcome 中 根据 id 提取对应 Outcome */
136
136
  export type ExtractOutcome<T, K extends Keyable> = T extends Outcome<infer O, unknown> ? O extends Exclude<O, K> ? never : T : never;
137
+ /**用于辅助解析智能补全的类型
138
+ * 输出schema后替换为 ^.*$ 的 string 匹配
139
+ */
140
+ export type SchemaString = `${string}SchemaString`;
137
141
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zwa73/utils",
3
- "version": "1.0.86",
3
+ "version": "1.0.88",
4
4
  "description": "my utils",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -26,6 +26,7 @@
26
26
  "https-proxy-agent": "^5.0.1",
27
27
  "json5": "^2.2.3",
28
28
  "tiktoken": "^1.0.7",
29
+ "typescript-json-schema": "^0.63.0",
29
30
  "winston": "^3.10.0",
30
31
  "winston-daily-rotate-file": "^4.7.1"
31
32
  },
@@ -0,0 +1,4 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$ref": "schemas.json#/definitions/TestType1"
4
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$ref": "schemas.json#/definitions/TestType2"
4
+ }
@@ -0,0 +1,35 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "definitions": {
4
+ "TestType2": {
5
+ "type": "object",
6
+ "properties": {
7
+ "a": {
8
+ "type": "string"
9
+ },
10
+ "b": {
11
+ "type": "number"
12
+ }
13
+ },
14
+ "required": [
15
+ "a",
16
+ "b"
17
+ ]
18
+ },
19
+ "TestType1": {
20
+ "type": "object",
21
+ "properties": {
22
+ "a": {
23
+ "type": "string"
24
+ },
25
+ "b": {
26
+ "type": "number"
27
+ }
28
+ },
29
+ "required": [
30
+ "a",
31
+ "b"
32
+ ]
33
+ }
34
+ }
35
+ }
package/src/UtilClass.ts CHANGED
@@ -1,3 +1,8 @@
1
+ import { UtilFT } from "./UtilFileTools";
2
+ import { UtilFunc } from "./UtilFunctions";
3
+ import { JObject } from "./UtilInterfaces";
4
+ import * as path from "path";
5
+ import * as TJS from "typescript-json-schema";
1
6
  type struct = number | string;
2
7
 
3
8
  /**遍历函数
@@ -1,10 +1,11 @@
1
1
  import * as fs from "fs";
2
2
  import * as path from "path";
3
- import { JToken } from "@src/UtilInterfaces";
3
+ import { JObject, JToken } from "@src/UtilInterfaces";
4
4
  import { SLogger } from "@src/UtilLogger";
5
5
  import * as JSON5 from 'json5';
6
6
  import { globSync } from "glob";
7
7
  import { UtilFunc } from "./UtilFunctions";
8
+ import * as TJS from "typescript-json-schema";
8
9
 
9
10
  /**文件工具 */
10
11
  export namespace UtilFT{
@@ -230,4 +231,98 @@ export function fileSearchGlob(globPattern:string|string[],ignore?:string|string
230
231
  export function fileSearch(...patams:any[]){
231
232
  throw "请使用 fileSearchRegex 或 fileSearchGlob"
232
233
  }
234
+ /**是一个有效的文件路径
235
+ * @param filePath - 需要验证的文件路径
236
+ */
237
+ export function isValidFilePath(filePath:string){
238
+ if(filePath.length>255) return false;
239
+ const invalidCharacters = ['<', '>', '"', '|', '?', '*'];
240
+ for (const invalidCharacter of invalidCharacters) {
241
+ if (filePath.includes(invalidCharacter))
242
+ return false;
243
+ }
244
+ return true;
245
+ }
246
+
247
+ //#region schema
248
+ /**构造Schema
249
+ * @async
250
+ * @param configPath - tsconfig路径
251
+ * @param outDir - schema文件夹路径 如 ./schema/
252
+ * @param coverDefine - 将会覆盖 definitions 对应内容的表
253
+ */
254
+ export async function builAllSchema(configPath:string,outDir:string,coverDefine:JObject={}){
255
+ outDir = path.join(outDir,"schemas.json");
256
+ const log = await UtilFunc.exec(`typescript-json-schema ${configPath} * --out ${outDir} --required --strictNullChecks --aliasRefs`);
257
+ console.log(log);
258
+ const schema = (await UtilFT.loadJSONFileSync(outDir)) as any;
259
+ //进行预处理并展开
260
+ await expandSchema(outDir,schema,coverDefine);
261
+ }
262
+ /**生成匹配的文件的所有type的schema
263
+ * @async
264
+ * @param globPattern - glob匹配符
265
+ * @param outDir - schema输出路径目录 如 ./schema/
266
+ * @param ignore - glob忽略匹配符
267
+ * @param coverDefine - 将会覆盖 definitions 对应内容的表
268
+ */
269
+ export async function buildMatchSchema(globPattern:string|string[],outDir:string,ignore?:string|string[],coverDefine:JObject={}){
270
+ //生成
271
+ const settings: TJS.PartialArgs = {
272
+ required: true,
273
+ aliasRef:true,
274
+ };
275
+ const compilerOptions: TJS.CompilerOptions = {
276
+ strictNullChecks: true,
277
+ };
278
+ const files = UtilFT.fileSearchGlob(globPattern,ignore);
279
+ const program = TJS.getProgramFromFiles(
280
+ files,
281
+ compilerOptions,
282
+ );
283
+ const schema = TJS.generateSchema(program, "*", settings) as any;
284
+ outDir = outDir??path.join(process.cwd(),'schema');
285
+ const schemasPath = path.join(outDir,'schemas.json');
286
+ //进行预处理并展开
287
+ await expandSchema(schemasPath,schema,coverDefine);
288
+ }
289
+ /**展开schema以供使用 */
290
+ async function expandSchema(schemasPath:string,schema:any,coverDefine:JObject){
291
+ //覆盖
292
+ coverObj(schema["definitions"],coverDefine);
293
+ //替换SchemaString标识符
294
+ schema = JSON.parse(JSON.stringify(schema).replace(/\^\.\*SchemaString\$/g,'^.*$'));
295
+ const plist:Promise<void>[] = [];
296
+ plist.push(UtilFT.writeJSONFile(schemasPath,schema));
297
+
298
+ const definitions = schema["definitions"] as Record<string,JObject>;
299
+ //展开定义
300
+ for(const typeName in definitions){
301
+ const schema = definitions[typeName];
302
+ //展开所有object与忽略检测的类型
303
+ if(!(schema.type == "object" || schema.type == "array" || schema.type == undefined)) continue;
304
+ if((/^.+_[0-9]/).test(typeName) || (/^{./).test(typeName)) continue;
305
+
306
+ const basename = path.basename(schemasPath);
307
+ const tpath = path.join(path.dirname(schemasPath),`${typeName}.schema.json`);
308
+ if(!isValidFilePath(tpath)) continue;
309
+ plist.push(UtilFT.writeJSONFile(tpath,{
310
+ "$schema": "http://json-schema.org/draft-07/schema#",
311
+ "$ref": `${basename}#/definitions/${typeName}`
312
+ }));
313
+ }
314
+ await Promise.all(plist);
315
+ }
316
+ /**覆盖object */
317
+ function coverObj(base:JObject,cover:JObject){
318
+ for(const k in cover){
319
+ const v = cover[k];
320
+ if( typeof v === "object" && !Array.isArray(v) &&
321
+ typeof base[k] === "object" && !Array.isArray(base[k]) )
322
+ coverObj(base[k] as JObject,v as JObject);
323
+ else
324
+ base[k] = v;
325
+ }
326
+ }
327
+ //#endregion
233
328
  }
@@ -205,3 +205,8 @@ export type ExtractOutcome<T,K extends Keyable> =
205
205
  : T
206
206
  : never;
207
207
 
208
+ /**用于辅助解析智能补全的类型
209
+ * 输出schema后替换为 ^.*$ 的 string 匹配
210
+ */
211
+ export type SchemaString = `${string}SchemaString`;
212
+