first commit

This commit is contained in:
编码猿
2024-09-27 01:15:47 +08:00
commit 8be1fcce6b
155 changed files with 9435 additions and 0 deletions

5
json-class-interface/.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
node_modules/
package-lock.json
笔记.txt
example.ts
src/

View File

@@ -0,0 +1 @@
f259e807-500b-424f-88db-2342f1ebdc6d

View File

@@ -0,0 +1 @@
d50b1a8c-81e3-4365-928b-1e5b39528942

View File

@@ -0,0 +1,51 @@
version: '1.0'
name: branch-pipeline
displayName: BranchPipeline
stages:
- stage:
name: compile
displayName: 编译
steps:
- step: build@nodejs
name: build_nodejs
displayName: Nodejs 构建
# 支持8.16.2、10.17.0、12.16.1、14.16.0、15.12.0五个版本
nodeVersion: 14.16.0
# 构建命令:安装依赖 -> 清除上次打包产物残留 -> 执行构建 【请根据项目实际产出进行填写】
commands:
- npm install && rm -rf ./dist && npm run build
# 非必填字段开启后表示将构建产物暂存但不会上传到制品库中7天后自动清除
artifacts:
# 构建产物名字作为产物的唯一标识可向下传递支持自定义默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
- name: BUILD_ARTIFACT
# 构建产物获取路径,是指代码编译完毕之后构建物的所在路径
path:
- ./dist
- step: publish@general_artifacts
name: publish_general_artifacts
displayName: 上传制品
# 上游构建任务定义的产物名默认BUILD_ARTIFACT
dependArtifact: BUILD_ARTIFACT
# 上传到制品库时的制品命名默认output
artifactName: output
dependsOn: build_nodejs
- stage:
name: release
displayName: 发布
steps:
- step: publish@release_artifacts
name: publish_release_artifacts
displayName: '发布'
# 上游上传制品任务的产出
dependArtifact: output
# 发布制品版本号
version: '1.0.0.0'
# 是否开启版本号自增,默认开启
autoIncrement: true
triggers:
push:
branches:
exclude:
- master
include:
- .*

View File

@@ -0,0 +1,49 @@
version: '1.0'
name: master-pipeline
displayName: MasterPipeline
stages:
- stage:
name: compile
displayName: 编译
steps:
- step: build@nodejs
name: build_nodejs
displayName: Nodejs 构建
# 支持8.16.2、10.17.0、12.16.1、14.16.0、15.12.0五个版本
nodeVersion: 14.16.0
# 构建命令:安装依赖 -> 清除上次打包产物残留 -> 执行构建 【请根据项目实际产出进行填写】
commands:
- npm install && rm -rf ./dist && npm run build
# 非必填字段开启后表示将构建产物暂存但不会上传到制品库中7天后自动清除
artifacts:
# 构建产物名字作为产物的唯一标识可向下传递支持自定义默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
- name: BUILD_ARTIFACT
# 构建产物获取路径,是指代码编译完毕之后构建物的所在路径
path:
- ./dist
- step: publish@general_artifacts
name: publish_general_artifacts
displayName: 上传制品
# 上游构建任务定义的产物名默认BUILD_ARTIFACT
dependArtifact: BUILD_ARTIFACT
# 上传到制品库时的制品命名默认output
artifactName: output
dependsOn: build_nodejs
- stage:
name: release
displayName: 发布
steps:
- step: publish@release_artifacts
name: publish_release_artifacts
displayName: '发布'
# 上游上传制品任务的产出
dependArtifact: output
# 发布制品版本号
version: '1.0.0.0'
# 是否开启版本号自增,默认开启
autoIncrement: true
triggers:
push:
branches:
include:
- master

View File

@@ -0,0 +1,36 @@
version: '1.0'
name: pr-pipeline
displayName: PRPipeline
stages:
- stage:
name: compile
displayName: 编译
steps:
- step: build@nodejs
name: build_nodejs
displayName: Nodejs 构建
# 支持8.16.2、10.17.0、12.16.1、14.16.0、15.12.0五个版本
nodeVersion: 14.16.0
# 构建命令:安装依赖 -> 清除上次打包产物残留 -> 执行构建 【请根据项目实际产出进行填写】
commands:
- npm install && rm -rf ./dist && npm run build
# 非必填字段开启后表示将构建产物暂存但不会上传到制品库中7天后自动清除
artifacts:
# 构建产物名字作为产物的唯一标识可向下传递支持自定义默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
- name: BUILD_ARTIFACT
# 构建产物获取路径,是指代码编译完毕之后构建物的所在路径
path:
- ./dist
- step: publish@general_artifacts
name: publish_general_artifacts
displayName: 上传制品
# 上游构建任务定义的产物名默认BUILD_ARTIFACT
dependArtifact: BUILD_ARTIFACT
# 上传到制品库时的制品命名默认output
artifactName: output
dependsOn: build_nodejs
triggers:
pr:
branches:
include:
- master

View File

@@ -0,0 +1,200 @@
# JsonToClassOrInterface
## 状态
持续开发中...
- 【完成】~~1: 将开发桌面端软件 和 web网页 进而 方便作为 独立的 工具来使用。~~
- 【完成】~~2: 增加功能,将生成的 Interface 和 class 自动生成 xxx.ts 文件,并保存到你给的项目路径中,方便开发者将本插件和项目请求进行深度集成~~
**基于本插件自己开发的支持MACLinuxWindows 的桌面端项目地址:**
> [https://gitee.com/bmycode/json-class-desktop](https://gitee.com/bmycode/json-class-desktop)
## 前言
顾名思义,这是一个把前端接口的`json`数据转化为 `typescript``Interface``Class`的插件。
当你在用`typescript`开发项目,你是否烦恼过后端接口给我们一坨`json`数据的时候,我们需要为数据 **手动编写大量**`Interface``Class`,来为请求中间层的方法标注返回类型,然后才能在页面中使用并获得优雅的类型提示
**手动写...很麻烦的,为何不 根据 json 数据自动生成???!!!**
受到 [flutter](https://flutter.dev/) 的 [json to dart](https://javiercbk.github.io/json_to_dart/) 启发,进而开发本插件。
## 注意
**本插件只能将json自动生成为 `Interface` 或 `Class`,避免我们手动编写的繁杂过程,但并不能实现类似 flutter json_serializable 将 json数据和类进行映射序列化的功能**
如果你想实现全套 json_serializable 的功能,可以在调用 `toClass` 方法的时候将参数 `needProperty` 开启并设置为`true`(参数说明看下面)。
这时候将生成 `json-mapper-class` 插件所需要的 **序列化代码**
---
至于为什么需要 `json-mapper-class` 这个插件,相信开发过`flutter`的你应该很清楚,不清楚去看官网说的说明:
> [https://docs.flutter.dev/data-and-backend/serialization/json](https://docs.flutter.dev/data-and-backend/serialization/json)
---
如果你需要使用`json和类映射`,那么要在项目里下载引入本插件才能使用,插件地址:
> [json-mapper-class](https://www.npmjs.com/package/json-mapper-class)
---
可能你会疑惑甚至一脸懵逼,我知道你很急,但是你先别着急,看说明你思考下就明白了:
插件有两个:
- json-class-interface
- json-mapper-class
它们之间的使用关系举例说明如下:
- 假设 http://www.xxx.com/newsInfo 接口返回了 **新闻详情数据**
- 这时我们 使用插件 `json-class-interface` 将接口返回数据转为 类(needProperty参数需要开启),然后将 插件返回的代码复制保存到 xxx.ts 中。
- 最后 使用插件 `json-mapper-class` 将上一步的类和接口json传入本插件会自动序列化json存储到类中**请求中间层方法返回数据类型和页面上直接 使用 类 即可**
**当然你也可以把这两个插件和你的项目进行深度的集成,让它们更加`自动化`,`无感`,`便捷`,`高效`。**
## 安装
> npm i --save json-class-interface
## 使用案例
```typescript
import { toClass, toInterface } from "json-class-interface";
// Json 数据
let json1 = {
status: 200,
message: "请求成功",
result_list: [
{
id: 1,
name: "新闻1",
tags_arr: [
{
tags_id: 1,
tags_title: '标签标题1'
},
{
tags_id: 1,
tags_title: '标签标题1'
}
]
},
{
id: 2,
name: "新闻2",
tags_arr: [
{
tags_id: 1,
tags_title: '标签标题2'
},
{
tags_id: 1,
tags_title: '标签标题2'
}
]
},
]
}
// 1 转换为 Class
// JsonToClass: 第一层类的名称,随便自定义
let type: string = toClass("JsonToClass", json1)
console.log(type);
// json转换为class的结果输出
// export class TagsArr {
// tags_id!: number;
// tags_title!: string;
// }
// export class ResultList {
// id!: number;
// name!: string;
// tags_arr!: TagsArr[];
// }
// export class JsonToClass {
// status!: number;
// message!: string;
// result_list!: ResultList[];
// }
// 2 转化为 Interface
let Interface: string = toInterface("JsonToInterface", json1)
console.log(Interface);
// json转换为Interface的结果输出
// export interface TagsArr {
// tags_id: number;
// tags_title: string;
// }
// export interface ResultList {
// id: number;
// name: string;
// tags_arr: TagsArr[];
// }
// export interface JsonToInterface {
// status: number;
// message: string;
// result_list: ResultList[];
// }
```
# 方法
`json` 数据转化为 `class`
## toClass(className: string = "JsonToClass", rawJson: JosnType | string, options: ToClassOptions = {}): string
---
`json` 数据转化为 `interface`,本方法的效果 和 `toClass` 参数 `interfaceModel: true` 效果一样。为了方便使用,故提供`toInterface`方法
## toInterface(className: string = "JsonToInterface", rawJson: JosnType | string, options: ToClassOptions = {}): string
---
方法参数说明:
| 名称 | 类型 | 默认值 |
| :-----:| :----: | :----: |
| className | string | JsonToClass 或 JsonToInterface |
| rawJson | JosnType 或 string | 不为空 |
| options | ToClassOptions | {} |
**JosnType 类型如下:**
```
export type JosnType = { [key: string]: any };
```
**ToClassOptions 类型如下:**
```
export interface ToClassOptions {
nullAlias?: string;
needProperty?: boolean;
needPropertyValue?: boolean;
interfaceModel?: boolean
}
```
| 名称 | 类型 | 默认值 | 说明 |
| :----:| :----:|:----:|:----:|
| nullAlias | string | "string" | 如果对象值为null转化为 class 或 interface 时候给这个对象key个默认类型 |
| needProperty | boolean | false | 是否需要生成Property装饰器用到插件 json-mapper-class 才需要开启 |
| needPropertyValue | boolean| false | 是否需要生成Property装饰器的默认值用到插件 json-mapper-class 才需要开启|
| interfaceModel | boolean| false | 是否需要生成 interface 模式 |

1
json-class-interface/dist/.pydio vendored Normal file
View File

@@ -0,0 +1 @@
9b3befbc-a965-48c7-ae4b-8602394b74c8

2
json-class-interface/dist/file.d.ts vendored Normal file
View File

@@ -0,0 +1,2 @@
import { PathLike } from "fs";
export declare const configFilePath: (path: PathLike) => void;

11
json-class-interface/dist/file.js vendored Normal file
View File

@@ -0,0 +1,11 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.configFilePath = void 0;
const fs_1 = require("fs");
const store_1 = require("./store");
const configFilePath = (path) => {
store_1.config.saveTypeFilePath = path;
console.log("config.saveTypeFilePath: ", store_1.config.saveTypeFilePath);
(0, fs_1.writeFileSync)(store_1.config.saveTypeFilePath, "testetststststststst");
};
exports.configFilePath = configFilePath;

3
json-class-interface/dist/index.d.ts vendored Normal file
View File

@@ -0,0 +1,3 @@
export * from './toClass';
export * from './toInterface';
export * from './file';

15
json-class-interface/dist/index.js vendored Normal file
View File

@@ -0,0 +1,15 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./toClass"), exports);
__exportStar(require("./toInterface"), exports);
__exportStar(require("./file"), exports);

2
json-class-interface/dist/store.d.ts vendored Normal file
View File

@@ -0,0 +1,2 @@
import { Config } from "./typing";
export declare const config: Config;

6
json-class-interface/dist/store.js vendored Normal file
View File

@@ -0,0 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.config = void 0;
exports.config = {
saveTypeFilePath: ""
};

View File

@@ -0,0 +1,2 @@
import { JosnType, ToClassOptions } from "./typing";
export declare const toClass: (className: string, rawJson: JosnType | string, options?: ToClassOptions, repeat?: boolean) => string;

38
json-class-interface/dist/toClass.js vendored Normal file
View File

@@ -0,0 +1,38 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.toClass = void 0;
const utils_1 = require("./utils");
let TextResult = "";
const toClass = (className = "JsonToClass", rawJson, options = {}, repeat = false) => {
typeof (rawJson) === "string" ? rawJson = JSON.parse(rawJson) : null;
(0, utils_1.isArray)(rawJson) ? rawJson = rawJson[0] : null;
if (!repeat) {
TextResult = "";
}
let classText = (0, utils_1.stripIndent) `
${(0, utils_1.setInterfaceModel)(options)} ${className} {
${Object.keys(rawJson).map(key => {
let ArrayInsideNotObject = false;
if ((0, utils_1.isObjectOrArray)(rawJson[key])) {
if ((0, utils_1.isArray)(rawJson[key]) && (0, utils_1.isObject)(rawJson[key][0])) {
(0, exports.toClass)((0, utils_1.firstLetterCap)(key), rawJson[key], options, true);
}
if ((0, utils_1.isObject)(rawJson[key])) {
ArrayInsideNotObject = false;
(0, exports.toClass)((0, utils_1.firstLetterCap)(key), rawJson[key], options, true);
}
}
return `${(0, utils_1.setDefaultNeedPropertyValue)(options, key) == null ? '' : (0, utils_1.setDefaultNeedPropertyValue)(options, key)}
${(0, utils_1.setKeyNotNull)(options, key)}: ${ArrayInsideNotObject
? `${typeof rawJson[key][0]}[]`
: (0, utils_1.isObjectOrArray)(rawJson[key])
? `${(0, utils_1.firstLetterCap)(key)}${(0, utils_1.isArray)(rawJson[key]) ? '[]' : ''}`
: (0, utils_1.isNull)(rawJson[key]) ? (0, utils_1.setDefaultNull)(options) : typeof rawJson[key]};
`;
})}
}
`;
TextResult += `${classText} \n\n`;
return TextResult;
};
exports.toClass = toClass;

View File

@@ -0,0 +1,2 @@
import { JosnType, ToClassOptions } from "./typing";
export declare const toInterface: (className: string, rawJson: JosnType | string, options?: ToClassOptions) => string;

View File

@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.toInterface = void 0;
const toClass_1 = require("./toClass");
const toInterface = (className = "JsonToInterface", rawJson, options = {}) => {
options.interfaceModel = true;
return (0, toClass_1.toClass)(className, rawJson, options);
};
exports.toInterface = toInterface;

14
json-class-interface/dist/typing.d.ts vendored Normal file
View File

@@ -0,0 +1,14 @@
/// <reference types="node" />
import { PathLike } from "fs";
export declare type JosnType = {
[key: string]: any;
};
export declare type Config = {
saveTypeFilePath: PathLike;
};
export interface ToClassOptions {
nullAlias?: string;
needProperty?: boolean;
needPropertyValue?: boolean;
interfaceModel?: boolean;
}

2
json-class-interface/dist/typing.js vendored Normal file
View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

13
json-class-interface/dist/utils.d.ts vendored Normal file
View File

@@ -0,0 +1,13 @@
import { ToClassOptions } from "./typing";
export declare const isNull: (val: any) => boolean;
export declare const isUndefined: (val: any) => boolean;
export declare const isNullOrUndefined: (val: any) => boolean;
export declare const isArray: (val: any) => boolean;
export declare const isObject: (val: any) => boolean;
export declare const isObjectOrArray: (val: any) => boolean;
export declare const firstLetterCap: (val: string) => string;
export declare const setDefaultNull: (options: ToClassOptions) => string;
export declare const setDefaultNeedPropertyValue: (options: ToClassOptions, key: string) => string;
export declare const setInterfaceModel: (options: ToClassOptions) => "export interface" | "export class";
export declare const setKeyNotNull: (options: ToClassOptions, key: string) => string;
export declare const stripIndent: (template: TemplateStringsArray, ...expressions: any[]) => string;

56
json-class-interface/dist/utils.js vendored Normal file
View File

@@ -0,0 +1,56 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.stripIndent = exports.setKeyNotNull = exports.setInterfaceModel = exports.setDefaultNeedPropertyValue = exports.setDefaultNull = exports.firstLetterCap = exports.isObjectOrArray = exports.isObject = exports.isArray = exports.isNullOrUndefined = exports.isUndefined = exports.isNull = void 0;
const isNull = (val) => val === null;
exports.isNull = isNull;
const isUndefined = (val) => val === undefined;
exports.isUndefined = isUndefined;
const isNullOrUndefined = (val) => (0, exports.isNull)(val) || (0, exports.isUndefined)(val);
exports.isNullOrUndefined = isNullOrUndefined;
const isArray = (val) => Array.isArray(val);
exports.isArray = isArray;
const isObject = (val) => (0, exports.isNull)(val) ? false : val.constructor === Object;
exports.isObject = isObject;
const isObjectOrArray = (val) => (0, exports.isObject)(val) || (0, exports.isArray)(val);
exports.isObjectOrArray = isObjectOrArray;
const firstLetterCap = (val) => {
let splitArr = val.split("_");
return splitArr.map(v => v.charAt(0).toUpperCase() + v.slice(1)).join("");
};
exports.firstLetterCap = firstLetterCap;
const setDefaultNull = (options) => options?.nullAlias ? options?.nullAlias : "string";
exports.setDefaultNull = setDefaultNull;
const setDefaultNeedPropertyValue = (options, key) => {
options.needProperty = options.needProperty || false;
return options?.needProperty
? options?.interfaceModel
? null
: options?.needPropertyValue
? `\t\n@property("${key}")`
: `@property()`
: null;
};
exports.setDefaultNeedPropertyValue = setDefaultNeedPropertyValue;
const setInterfaceModel = (options) => options?.interfaceModel ? 'export interface' : `export class`;
exports.setInterfaceModel = setInterfaceModel;
const setKeyNotNull = (options, key) => `${key}${options?.interfaceModel ? '' : '!'}`;
exports.setKeyNotNull = setKeyNotNull;
const stripIndent = (template, ...expressions) => {
let result = template.reduce((prev, next, i) => {
let expression = expressions[i - 1];
if ((0, exports.isArray)(expression)) {
expression = expression.join('');
}
return prev + expression + next;
});
const match = result.match(/^[^\S\n]*(?=\S)/gm);
const indent = match && Math.min(...match.map(el => el.length));
if (indent) {
const regexp = new RegExp(`^.{${indent}}`, 'gm');
result = result.replace(regexp, '');
}
result = result.replace(/^[^\S\n]+/gm, ' ');
result = result.trim();
return result;
};
exports.stripIndent = stripIndent;

View File

@@ -0,0 +1,21 @@
{
"name": "json-class-interface",
"version": "1.1.7",
"description": "将json数据自动转换为class或interface",
"main": "dist/index.js",
"scripts": {
"dev": "clear && ts-node example.ts",
"build": "tsc -w",
"publish": "npm publish",
"git": "git add -A && git commit -m '提交' && git pull && git push ",
"push": "npm run git && npm run publish "
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@types/node": "^20.7.2",
"tslib": "^2.6.2",
"typescript": "^5.2.2"
}
}

View File

@@ -0,0 +1,24 @@
{
"compilerOptions": {
"target": "esnext",
"module": "commonjs",
"resolveJsonModule": true,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"esModuleInterop": true,
"sourceMap": false,
"noImplicitAny": false,
"removeComments": true,
"declaration": true,
"outDir": "./dist",
"lib": [ "es6", "DOM" ]
},
"include": [
"src/**/*.ts"
],
"exclude": [
"node_modules",
"dist"
]
}