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

23
.gitignore vendored Normal file
View File

@@ -0,0 +1,23 @@
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

1
.pydio Normal file
View File

@@ -0,0 +1 @@
3a4371c0-fadd-476c-bd00-1adcf8f35262

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"
]
}

3
json-mapper-class/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
node_modules/
test.ts
src/

1
json-mapper-class/.pydio Normal file
View File

@@ -0,0 +1 @@
8df5a678-3cf4-4606-9f91-a723a276c56c

489
json-mapper-class/README.md Normal file
View File

@@ -0,0 +1,489 @@
# json-mapper-class
`json-mapper-class` 是类似flutter Json序列化的 **web前端 优雅 解决方案**,用来将接口 json 数据映射到 class 的工具,之后在我们的`TypeScript`项目中,可以通过 **类来为接口返回数据标注类型**,通过修改类属性达到不需要后端修改接口数据字段的情况下,前端来任意定义接口返回字段的效果,解决了实际项目中接口数据与页面深度耦合的过程,并提供其逆过程。
`json-mapper-class` 是一个独立的插件,可以与任何的 `TypeScript` 项目进行深度的集成最好是class语法同时提供了众多的装饰器让你更加**优雅**的去编写 `TypeScript`,请仔细阅读文档。
同时为了方便 `json-mapper-class` 的方法 `toClass` 第二个参数的生成,也是为了避免手动编写`json-mapper-class` **标准类 模版代码** 的过程,本人开发第二个插件简化了过程,插件地址(请自信阅读文档):
> [json-class-interface](https://www.npmjs.com/package/json-class-interface)
下面是一个案例:
```ts
import { property, toClass } from 'json-mapper-class';
class UserModel {
@property('i')
id: number;
@property()
name: string;
}
const userRaw = {
i: 1234,
name: 'name',
};
// 使用 toClass 将 json 转换成 class
const userModel = toClass(userRaw, UserModel);
// 你将获得如下数据
{
id: 1234,
name: 'name',
}
```
# 如何安装
```bash
npm i json-mapper-class --save
```
# 使用例子
## 聚合对象或数组
如果你想转换一个聚合对象,需要提供目标类。如果该对象的某个属性值是数组,则会递归该数组的所有元素(不管层级有多深),自动转换为目标类的实例。
列子:
```ts
class NestedModel {
@property('e', UserModel)
employees: UserModel[];
@typed(UserModel)
@property('u')
user: UserModel;
}
const model = toClass(
{
e: [
{ i: 1, n: 'n1' },
{ i: 2, n: 'n2' },
],
u: {
i: 1,
n: 'name',
}
},
NestedModel,
);
// you will get like this
{
employees: [
{ id: 1, name: 'n1' },
{ id: 2, name: 'n2' },
],
user: {
id: 1,
name: 'name'
}
}
const model = toPlain(
{
employees: [
{ id: 1, name: 'n1' },
{ id: 2, name: 'n2' },
],
user: {
id: 1,
name: 'name'
}
},
NestedModel,
);
// you will get like this
{
e: [
{ i: 1, n: 'n1' },
{ i: 2, n: 'n2' },
],
u: {
i: 1,
n: 'name'
}
}
```
## 其他数据类型转换
```ts
import * as moment from 'moment';
export class EduModel {
@property('i')
id: number;
@property('crt')
@deserialize(value => moment(value).format('YYYY-MM-DD HH:mm:ss'))
createTime: string;
}
```
## 依赖于其他属性值
```ts
class EmailModel {
@property('s')
site: string;
@property('e')
@deserialize((value, _instance, origin) => `${value}@${origin.s}`)
email: string;
}
```
# 方法
## toClass(raw, clazzType, options?) / toClasses(raws, clazzType, options?)
将一个 json 对象映射成一个类实例
- `raw` / `raws` `<Object|Array<Object>>` 一个 josn 对象或者 json 对象数据
- `clazzType` `<Class>` 类的构造函数
- `options?` `<Object>` 配置
- `ignoreDeserializer` `<Boolean>` 当设置为 true 时,不会调用使用 @deserialize 装饰器配置的方法
- `ignoreBeforeDeserializer` `<Boolean>` 当设置为 true 时,不会调用使用 @beforeDeserialize 装饰器配置的方法
- `distinguishNullAndUndefined` `<Boolean>` 当设置为 true 时,区分 null 和 undefined
示例:
```ts
const userRaw = {
i: 1234,
name: 'name',
};
const userRaws = [
{
i: 1000,
name: 'name1',
},
{
i: 2000,
name: 'name2',
},
];
const userModel = toClass(userRaw, UserModel);
const userModels = toClasses(userRaws, UserModel);
```
## toPlain(instance, clazzType, options?) / toPlains(instances, clazzType, options?)
将一个类实例或者 json 对象映射成另外一个 json 对象
- `instance` / `instances` `<Object|Array<Object>>` 一个 json 或类实例或者一个json或类实例组成的数组
- `clazzType` `<Class>` Constructor of the target class
- `options?` `<Object>` 类的构造函数
- `ignoreSerializer` `<Boolean>` 当设置为 true 时,不会调用使用 @serialize 装饰器配置的方法
- `ignoreAfterSerializer` `<Boolean>` 当设置为 true 时,不会调用使用 @afterSerialize 装饰器配置的方法
- `distinguishNullAndUndefined` `<Boolean>` 当设置为 true 时,区分 null 和 undefined
示例:
```ts
const userModel = {
id: 1234,
name: 'name',
};
const userModels = [
{
id: 1000,
name: 'name1',
},
{
id: 2000,
name: 'name2',
},
];
const userRaw = toPlain(userModel, UserModel);
const userRaws = toPlains(userModels, UserModel);
```
# 属性装饰器
调用不同的方法时,这些装饰器的执行顺序:
- `toClass/toClasses`: beforeDeserializer => typed(映射成一个类实例) => deserializer
- `toPlain/toPlains`: serializer => typed(映射成一个对象) => afterSerializer
## property(originalKey?, clazzType?, optional = false)
将一个 key 映射到另外一个 key`n => name`
- `originalKey` `<string>` 被映射的数据 key 如果不传则默认同名
- `clazzType` `<Class>` 自动将该属性的值映射到一个类实例,相当于调用了 `toClass` 方法
- `optional` `<Boolean>` 是否可选
示例:
```ts
class PropertyModel {
@property('i')
id: number;
@property()
name: string;
@property('u', UserModel)
user: UserModel;
@property('t', null, true)
timeStamp: number;
}
const model = toClass({ i: 234, name: 'property', u: { i: 123, n: 'name' } }, PropertyModel);
// 你将获得如下数据
{
id: 234,
name: 'property',
user: {
id: 123,
name: 'name'
}
}
```
## typed(clazzType)
设置一个目标类的构造器,相当于 property 装饰器的第二个参数
- `clazzType` `<Class>` 自动将该属性的值映射到一个类实例,相当于调用了 `toClass` 方法
示例:
```ts
// 与此设置一致 @property('n', UserModel)
class TypedModel {
@typed(UserModel)
@property('u')
user: UserModel;
}
const model = toClass({ u: { i: 123, n: 'name' } }, TypedModel);
// 你将获得如下数据
{
user: {
id: 123,
name: 'name'
}
}
```
## optional()
设置一个属性为可选,相当于 property 装饰器的第三个参数
示例:
```ts
// 与此设置一致 @property('n', null, true)
class OptionalModel {
@optional()
@property('n')
name: string;
}
const model = toClass({}, OptionalModel);
// 你将获得如下数据
{
}
const model = toClass({ n: 'name' }, OptionalModel);
// 你将获得如下数据
{
name: 'name';
}
```
## defaultVal(val)
给当前属性设置默认值
- `val` `<Any>` 要设置的默认值
示例:
```ts
class DefaultValModel {
@defaultVal(0)
@property('i')
id: number;
}
const model = toClass({}, DefaultValModel);
// 你将获得如下数据
{
id: 0;
}
const raw = toPLain({}, DefaultValModel);
// 你将获得如下数据
{
i: 0;
}
```
## serializeTarget()
当调 `toPlain` 进行序列化时,用使用当前数据作为基准
示例:
```ts
class SerializeTargetModel {
@serializeTarget()
@property('n')
name: string;
@property('n')
nick: string;
}
const raw = toPlain(
{
name: 'name',
nick: 'nick',
},
SerializeTargetModel,
);
// 你将获得如下数据
{
n: 'name';
}
```
## beforeDeserialize(beforeDeserializer, disallowIgnoreBeforeDeserializer = false)
`@typed` 调用之前调用
- `beforeDeserializer` `<(value: any, instance: any, origin: any) => any>`
- `value` `<Any>` 该属性在原始对象中的值
- `instance` `<Instance>` 类实例(未完成解析)
- `origin` `<Object>` 原始对象
- `disallowIgnoreBeforeDeserializer` `<Boolean>` 默认为 false如果设置为 true则当调用 `toClass` 时,将强制调用 `@beforeDeserialize` 配置的方法
示例:
```ts
class BeforeDeserializeModel {
@beforeDeserialize((value: any) => JSON.parse(value))
@property('m')
mail: object;
}
toClass(
{
m: '{"id":123}',
},
BeforeDeserializeModel,
);
// 你将获得如下数据
{
mail: { id: 123 },
};
```
## deserialize(deserializer, disallowIgnoreDeserializer =false)
将原始对象序列化成自定义的数组格式,仅在调用 `toClass/toClasses` 时可用
- `deserializer` `(value: any, instance: any, origin: any) => any`
- `value` `<Any>` 该属性的值经过 `@beforeDeserialize``@typed` 调用后的结果
- `instance` `<Instance>` 类实例(未完成解析)
- `origin` `<Object>` A raw object
- `disallowIgnoreDeserializer` `<Boolean>` 默认为 false如果设置为 true则当调用 `toClass` 时,将强制调用 `@deserialize` 配置的方法
示例:
```ts
class DeserializeModel {
@deserialize((value: string) => `${value}@xxx.com`)
@property('m')
mail: string;
}
toClass(
{
m: 'mail',
},
DeserializeModel,
);
// 你将获得如下数据
{
mail: 'mail@xxx.com',
};
```
## serialize(serializer, disallowIgnoreSerializer = false)
自定义属性值的序列化方式,仅当调用 `toPlain/toPlains` 时可用
- `serializer` `(value: any, instance: any, origin: any) => any`
- `value` `<Any>` 该属性在类实例中的值
- `instance` `<Instance>` 当前类实例
- `origin` `<Object>` 一个json对象未完成序列化
- `disallowIgnoreSerializer` `<Boolean>` 默认为 false如果设置为 true则当调用 `toClass` 时,将强制调用 `@serialize` 配置的方法
Example:
```ts
class SerializeModel {
@serialize((mail: string) => mail.replace('@xxx.com', ''))
@property('e')
mail: string;
}
toPlain(
{
mail: 'mail@xxx.com',
},
SerializeModel,
);
// 你将获得如下数据
{
e: 'mail@xxx.com',
}
```
## afterSerialize(afterSerializer, disallowIgnoreAfterSerializer = false)
Convert a key/value in instance to a target form data, it happened after serializer only
- `afterSerializer` `(value: any, instance: any, origin: any) => any`
- `value` `<Any>` 该属性的值经过 `@serializer``@typed` 调用后的结果
- `instance` `<Instance>` 当前类实例
- `origin` `<Object>` 一个json对象未完成序列化
- `disallowIgnoreAfterSerializer` `<Boolean>` 默认为 false如果设置为 true则当调用 `toClass` 时,将强制调用 `@afterSerialize` 配置的方法
示例:
```ts
class AfterSerializeModel {
@afterSerialize((mail: string) => JSON.stringify(mail))
@property('e')
mail: string;
}
toPlain(
{
mail: { id: 1000 },
},
SerializeModel,
);
// 你将获得如下数据
{
e: '{"id":1000}',
};
```

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

@@ -0,0 +1 @@
391e708b-cc22-49c3-8788-a0be45dd3948

10
json-mapper-class/dist/decorators.d.ts vendored Normal file
View File

@@ -0,0 +1,10 @@
import { StoreItemType } from './typing';
export declare function serialize(serializer: StoreItemType['serializer'], disallowIgnore?: boolean): (target: any, propertyKey: string) => void;
export declare function deserialize(deserializer: StoreItemType['deserializer'], disallowIgnore?: boolean): (target: any, propertyKey: string) => void;
export declare function beforeDeserialize(beforeDeserializer: StoreItemType['beforeDeserializer'], disallowIgnore?: boolean): (target: any, propertyKey: string) => void;
export declare function afterSerialize(afterSerializer: StoreItemType['afterSerializer'], disallowIgnore?: boolean): (target: any, propertyKey: string) => void;
export declare function serializeTarget(): (target: any, propertyKey: string) => void;
export declare function property(originalKey?: string, targetClass?: StoreItemType['targetClass'], isOptional?: boolean): (target: any, propertyKey: string) => void;
export declare function typed(targetClass: StoreItemType['targetClass']): (target: any, propertyKey: string) => void;
export declare function optional(): (target: any, propertyKey: string) => void;
export declare function defaultVal(value: any): (target: any, propertyKey: string) => void;

96
json-mapper-class/dist/decorators.js vendored Normal file
View File

@@ -0,0 +1,96 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.defaultVal = exports.optional = exports.typed = exports.property = exports.serializeTarget = exports.afterSerialize = exports.beforeDeserialize = exports.deserialize = exports.serialize = void 0;
const store_1 = require("./store");
function serialize(serializer, disallowIgnore = false) {
return (target, propertyKey) => {
store_1.setStore(target, {
key: propertyKey,
serializer,
disallowIgnoreSerializer: disallowIgnore,
});
};
}
exports.serialize = serialize;
function deserialize(deserializer, disallowIgnore = false) {
return (target, propertyKey) => {
store_1.setStore(target, {
key: propertyKey,
deserializer,
disallowIgnoreDeserializer: disallowIgnore,
});
};
}
exports.deserialize = deserialize;
function beforeDeserialize(beforeDeserializer, disallowIgnore = false) {
return (target, propertyKey) => {
store_1.setStore(target, {
key: propertyKey,
beforeDeserializer,
disallowIgnoreBeforeDeserializer: disallowIgnore,
});
};
}
exports.beforeDeserialize = beforeDeserialize;
function afterSerialize(afterSerializer, disallowIgnore = false) {
return (target, propertyKey) => {
store_1.setStore(target, {
key: propertyKey,
afterSerializer,
disallowIgnoreAfterSerializer: disallowIgnore,
});
};
}
exports.afterSerialize = afterSerialize;
function serializeTarget() {
return (target, propertyKey) => {
store_1.setStore(target, {
key: propertyKey,
serializeTarget: true,
});
};
}
exports.serializeTarget = serializeTarget;
function property(originalKey, targetClass, isOptional = false) {
return (target, propertyKey) => {
const config = {
originalKey: originalKey || propertyKey,
key: propertyKey,
};
if (targetClass) {
config.targetClass = targetClass.prototype.constructor;
}
if (isOptional) {
config.optional = isOptional;
}
store_1.setStore(target, config);
};
}
exports.property = property;
function typed(targetClass) {
return (target, propertyKey) => {
store_1.setStore(target, {
key: propertyKey,
targetClass,
});
};
}
exports.typed = typed;
function optional() {
return (target, propertyKey) => {
store_1.setStore(target, {
key: propertyKey,
optional: true,
});
};
}
exports.optional = optional;
function defaultVal(value) {
return (target, propertyKey) => {
store_1.setStore(target, {
key: propertyKey,
default: value,
});
};
}
exports.defaultVal = defaultVal;

View File

@@ -0,0 +1 @@
{"version":3,"file":"decorators.js","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"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"}

4
json-mapper-class/dist/index.d.ts vendored Normal file
View File

@@ -0,0 +1,4 @@
export * from './to-class';
export * from './to-plain';
export * from './decorators';
export * from './typing';

16
json-mapper-class/dist/index.js vendored Normal file
View File

@@ -0,0 +1,16 @@
"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" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./to-class"), exports);
__exportStar(require("./to-plain"), exports);
__exportStar(require("./decorators"), exports);
__exportStar(require("./typing"), exports);

1
json-mapper-class/dist/index.js.map vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6CAA2B;AAC3B,6CAA2B;AAC3B,+CAA6B;AAC7B,2CAAyB"}

6
json-mapper-class/dist/store.d.ts vendored Normal file
View File

@@ -0,0 +1,6 @@
import { StoreItemOptions, StoreItemType } from './typing';
declare const store: Map<Function, Map<string, StoreItemType>>;
export declare const originalKeyStores: Map<Function, Map<string, StoreItemOptions[]>>;
export declare const keyStores: Map<Function, Map<string, StoreItemType>>;
export declare const setStore: (target: Function, options: StoreItemOptions) => void;
export default store;

19
json-mapper-class/dist/store.js vendored Normal file
View File

@@ -0,0 +1,19 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.setStore = exports.keyStores = exports.originalKeyStores = void 0;
const store = new Map();
exports.originalKeyStores = new Map();
exports.keyStores = new Map();
exports.setStore = (target, options) => {
const { key, ...rest } = options;
const storeKey = target.constructor;
const targetStore = store.has(storeKey) ? store.get(storeKey) : new Map();
let value = targetStore.has(key) ? targetStore.get(key) : {};
value = {
...value,
...rest,
};
targetStore.set(key, value);
store.set(storeKey, targetStore);
};
exports.default = store;

1
json-mapper-class/dist/store.js.map vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":";;;AAEA,MAAM,KAAK,GAAG,IAAI,GAAG,EAAwC,CAAC;AAEjD,QAAA,iBAAiB,GAAG,IAAI,GAAG,EAA6C,CAAC;AACzE,QAAA,SAAS,GAAG,IAAI,GAAG,EAAwC,CAAC;AAE5D,QAAA,QAAQ,GAAG,CAAC,MAAgB,EAAE,OAAyB,EAAE,EAAE;IACtE,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IACjC,oCAAoC;IACpC,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC;IACpC,sDAAsD;IACtD,MAAM,WAAW,GAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,EAAyB,CAAC;IAEjG,iEAAiE;IACjE,IAAI,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7D,KAAK,GAAG;QACN,GAAG,KAAK;QACR,GAAG,IAAI;KACR,CAAC;IAEF,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC5B,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;AACnC,CAAC,CAAC;AAEF,kBAAe,KAAK,CAAC"}

4
json-mapper-class/dist/to-class.d.ts vendored Normal file
View File

@@ -0,0 +1,4 @@
import { JosnType, BasicClass, ToClassOptions } from './typing';
export declare const arrayItemToClass: <T>(arrayVal: any[], Clazz: BasicClass<T>, options: ToClassOptions) => any;
export declare const toClasses: <T>(rawJson: JosnType[], Clazz: BasicClass<T>, options?: ToClassOptions) => T[];
export declare const toClass: <T>(rawJson: JosnType, Clazz: BasicClass<T>, options?: ToClassOptions) => T;

61
json-mapper-class/dist/to-class.js vendored Normal file
View File

@@ -0,0 +1,61 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.toClass = exports.toClasses = exports.arrayItemToClass = void 0;
const isarray_1 = __importDefault(require("isarray"));
const utils_1 = require("./utils");
exports.arrayItemToClass = (arrayVal, Clazz, options) => {
return arrayVal.map((v) => isarray_1.default(v) ? exports.arrayItemToClass(v, Clazz, options) : objectToClass(v, Clazz, options));
};
const objectToClass = (jsonObj, Clazz, options) => {
const instance = new Clazz();
const originalKeyStore = utils_1.getOriginalKeyStore(Clazz);
originalKeyStore.forEach((propertiesOptions, originalKey) => {
const originalValue = jsonObj[originalKey];
propertiesOptions.forEach((storeItemoptions) => {
const { key, beforeDeserializer, deserializer, targetClass, optional } = storeItemoptions;
const disallowIgnoreDeserializer = storeItemoptions.disallowIgnoreDeserializer || !options.ignoreDeserializer;
const disallowIgnoreBeforeDeserializer = storeItemoptions.disallowIgnoreBeforeDeserializer || !options.ignoreBeforeDeserializer;
const isValueNotExist = options.distinguishNullAndUndefined ? utils_1.isUndefined : utils_1.isNullOrUndefined;
let value = originalValue;
if (isValueNotExist(value)) {
if (!isValueNotExist(storeItemoptions.default)) {
instance[key] = storeItemoptions.default;
return;
}
if (!optional) {
throw new Error(`Can't map '${originalKey}' to ${Clazz.name}.${key}, property '${originalKey}' not found`);
}
return;
}
value =
beforeDeserializer && disallowIgnoreBeforeDeserializer
? beforeDeserializer(value, instance, jsonObj, options)
: value;
if (value && targetClass) {
if (isarray_1.default(value)) {
value = exports.arrayItemToClass(value, targetClass, options);
}
else {
value = exports.toClass(value, targetClass, options);
}
}
instance[key] =
deserializer && disallowIgnoreDeserializer ? deserializer(value, instance, jsonObj, options) : value;
});
});
return instance;
};
exports.toClasses = (rawJson, Clazz, options = {}) => {
if (!isarray_1.default(rawJson)) {
throw new Error(`rawJson ${rawJson} must be an array`);
}
const { constructor } = Clazz.prototype;
return rawJson.map((item) => objectToClass(item, constructor, options));
};
exports.toClass = (rawJson, Clazz, options = {}) => {
const { constructor } = Clazz.prototype;
return objectToClass(rawJson, constructor, options);
};

View File

@@ -0,0 +1 @@
{"version":3,"file":"to-class.js","sourceRoot":"","sources":["../src/to-class.ts"],"names":[],"mappings":"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"}

4
json-mapper-class/dist/to-plain.d.ts vendored Normal file
View File

@@ -0,0 +1,4 @@
import { JosnType, BasicClass, ToPlainOptions } from './typing';
export declare const arrayItemToObject: <T>(arrayVal: any[], Clazz: BasicClass<T>, options: ToPlainOptions) => any;
export declare const toPlains: <T>(instances: (JosnType | T)[], Clazz: BasicClass<T>, options?: ToPlainOptions) => any[];
export declare const toPlain: <T>(instance: JosnType | T, Clazz: BasicClass<T>, options?: ToPlainOptions) => any;

49
json-mapper-class/dist/to-plain.js vendored Normal file
View File

@@ -0,0 +1,49 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.toPlain = exports.toPlains = exports.arrayItemToObject = void 0;
const isarray_1 = __importDefault(require("isarray"));
const utils_1 = require("./utils");
exports.arrayItemToObject = (arrayVal, Clazz, options) => {
return arrayVal.map((v) => isarray_1.default(v) ? exports.arrayItemToObject(v, Clazz, options) : classToObject(v, Clazz, options));
};
const classToObject = (instance, Clazz, options) => {
const obj = {};
const keyStore = utils_1.getKeyStore(Clazz);
keyStore.forEach((propertiesOption, key) => {
const isValueNotExist = options.distinguishNullAndUndefined ? utils_1.isUndefined : utils_1.isNullOrUndefined;
const instanceValue = isValueNotExist(instance[key]) ? propertiesOption.default : instance[key];
const { originalKey, afterSerializer, serializer, targetClass, optional } = propertiesOption;
const disallowIgnoreSerializer = propertiesOption.disallowIgnoreSerializer || !options.ignoreSerializer;
const disallowIgnoreAfterSerializer = propertiesOption.disallowIgnoreAfterSerializer || !options.ignoreAfterSerializer;
if (isValueNotExist(instanceValue)) {
if (!optional) {
throw new Error(`Property '${Clazz.name}.${key}' not found`);
}
return;
}
let value = serializer && disallowIgnoreSerializer ? serializer(instanceValue, instance, obj, options) : instanceValue;
if (value && targetClass) {
if (isarray_1.default(value)) {
value = exports.arrayItemToObject(value, targetClass, options);
}
else {
value = exports.toPlain(value, targetClass, options);
}
}
obj[originalKey] =
afterSerializer && disallowIgnoreAfterSerializer ? afterSerializer(value, instance, obj, options) : value;
});
return obj;
};
exports.toPlains = (instances, Clazz, options = {}) => {
if (!isarray_1.default(instances)) {
throw new Error(`${Clazz} instances must be an array`);
}
return instances.map((item) => classToObject(item, Clazz, options));
};
exports.toPlain = (instance, Clazz, options = {}) => {
return classToObject(instance, Clazz, options);
};

View File

@@ -0,0 +1 @@
{"version":3,"file":"to-plain.js","sourceRoot":"","sources":["../src/to-plain.ts"],"names":[],"mappings":"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"}

35
json-mapper-class/dist/typing.d.ts vendored Normal file
View File

@@ -0,0 +1,35 @@
export declare type StoreItemType = {
originalKey?: string;
targetClass?: BasicClass;
serializer?: (value: any, instance: any, origin: any, options: ToPlainOptions) => any;
disallowIgnoreSerializer?: boolean;
afterSerializer?: (value: any, instance: any, origin: any, options: ToPlainOptions) => any;
disallowIgnoreAfterSerializer?: boolean;
deserializer?: (value: any, instance: any, origin: any, options: ToClassOptions) => any;
disallowIgnoreDeserializer?: boolean;
beforeDeserializer?: (value: any, instance: any, origin: any, options: ToClassOptions) => any;
disallowIgnoreBeforeDeserializer?: boolean;
default?: any;
autoTypeDetection?: boolean;
optional?: boolean;
serializeTarget?: boolean;
};
export declare type StoreItemOptions = StoreItemType & {
key: string;
};
export declare type BasicClass<T = any> = {
new (...args: any[]): T;
};
export declare type JosnType = {
[key: string]: any;
};
export interface ToClassOptions {
ignoreDeserializer?: boolean;
ignoreBeforeDeserializer?: boolean;
distinguishNullAndUndefined?: boolean;
}
export interface ToPlainOptions {
ignoreSerializer?: boolean;
ignoreAfterSerializer?: boolean;
distinguishNullAndUndefined?: boolean;
}

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

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

1
json-mapper-class/dist/typing.js.map vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"typing.js","sourceRoot":"","sources":["../src/typing.ts"],"names":[],"mappings":""}

6
json-mapper-class/dist/utils.d.ts vendored Normal file
View File

@@ -0,0 +1,6 @@
import { StoreItemOptions, StoreItemType, BasicClass } 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 getOriginalKeyStore: <T>(Clazz: BasicClass<T>) => Map<string, StoreItemOptions[]>;
export declare const getKeyStore: <T>(Clazz: BasicClass<T>) => Map<string, StoreItemType>;

82
json-mapper-class/dist/utils.js vendored Normal file
View File

@@ -0,0 +1,82 @@
"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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getKeyStore = exports.getOriginalKeyStore = exports.isNullOrUndefined = exports.isUndefined = exports.isNull = void 0;
const store_1 = __importStar(require("./store"));
exports.isNull = (val) => val === null;
exports.isUndefined = (val) => val === undefined;
exports.isNullOrUndefined = (val) => exports.isNull(val) || exports.isUndefined(val);
exports.getOriginalKeyStore = (Clazz) => {
let curLayer = Clazz;
const cacheOriginalKeyStore = store_1.originalKeyStores.get(curLayer);
if (cacheOriginalKeyStore) {
return cacheOriginalKeyStore;
}
const originalKeyStore = new Map();
while (curLayer.name && curLayer.prototype) {
const { constructor } = curLayer.prototype;
const targetStore = store_1.default.get(constructor);
if (targetStore) {
targetStore.forEach((storeItem, key) => {
const item = {
key,
...storeItem,
};
if (!originalKeyStore.has(storeItem.originalKey)) {
originalKeyStore.set(storeItem.originalKey, [item]);
}
else {
const exists = originalKeyStore.get(storeItem.originalKey);
if (!exists.find((exist) => exist.key === key)) {
originalKeyStore.set(storeItem.originalKey, [...originalKeyStore.get(storeItem.originalKey), item]);
}
}
});
}
curLayer = Object.getPrototypeOf(constructor);
}
store_1.originalKeyStores.set(Clazz, originalKeyStore);
return originalKeyStore;
};
exports.getKeyStore = (Clazz) => {
const cacheKeyStore = store_1.keyStores.get(Clazz);
if (cacheKeyStore) {
return cacheKeyStore;
}
const keyStore = new Map();
const originalKeyStore = exports.getOriginalKeyStore(Clazz);
originalKeyStore.forEach(storeItems => {
const [firstStoreItem] = storeItems;
if (storeItems.length === 1) {
keyStore.set(firstStoreItem.key, firstStoreItem);
}
else {
const hasStoreItems = storeItems.filter(storeItem => storeItem.serializeTarget);
if (hasStoreItems.length !== 1) {
throw new Error(`Only one of keys(${storeItems.map(storeItem => storeItem.key).join(', ')}) in ${Clazz.name} can contain a serializeTarget when use toPlain`);
}
const hasStoreItem = hasStoreItems[0];
keyStore.set(hasStoreItem.key, hasStoreItem);
}
});
store_1.keyStores.set(Clazz, keyStore);
return keyStore;
};

1
json-mapper-class/dist/utils.js.map vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,27 @@
{
"name": "json-mapper-class",
"version": "1.0.2",
"description": "Json Mapper To Class",
"main": "dist/index.js",
"scripts": {
"build": "tsc",
"dev": "ts-node test.ts",
"publish": "npm publish"
},
"keywords": [
"class",
"json",
"mapper",
"typescript"
],
"dependencies": {
"isarray": "^2.0.5"
},
"devDependencies": {
"@types/isarray": "^2.0.0",
"@types/node": "^12.12.50",
"moment": "^2.27.0",
"ts-node": "^8.10.2",
"typescript": "^3.9.7"
}
}

View File

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

29
json-to-class/.gitignore vendored Normal file
View File

@@ -0,0 +1,29 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
test.json
笔记.txt
package-lock.json
stats.html
src-tauri/target/*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

1
json-to-class/.pydio Normal file
View File

@@ -0,0 +1 @@
2b79c44f-8eec-46bb-8888-ea29805a9038

89
json-to-class/README.md Normal file
View File

@@ -0,0 +1,89 @@
<p align="center">
<img style="width: 50px;height: 50px;" src="build/img/icon_128x128.png"/>
</p>
<p align="center">
<strong>JsonToClass</strong>
</p>
<p align="center">
帮助 TypeScript 项目为API接口数据自动生成 TypeScript 类型
</p>
<p align="center">
<a href="https://svelte.dev/">
<img src="https://img.shields.io/badge/svelte-v4.0.5-orange" alt="svelte">
</a>
<a href="https://beta.tauri.app/">
<img src="https://img.shields.io/badge/tauri-v2.0.0-brightgreen" alt="tauri">
</a>
<a href="https://www.typescriptlang.org/">
<img src="https://img.shields.io/badge/typescript-v5.0.2-blue" alt="typescript">
</a>
<a href="https://vitejs.dev/">
<img src="https://img.shields.io/badge/vite-v4.4.4-orange" alt="vitejs">
</a>
<a href="https://www.npmjs.com/package/json-class-interface">
<img src="https://img.shields.io/badge/json__class__interface-v1.1.3-brightgreen" alt="json-class-interface">
</a>
</p>
该软件是本人npm 插件 **[json-class-interface](https://www.npmjs.com/package/json-class-interface)** 的桌面端,为了方便使用所以开发!但为了学习新技术点,所以舍弃大而慢占内存的 electron谁还用 electron你用 electron 落伍了...
**`Tauri`谁用谁知道本项目打包后在Macos上可执行`app`才只有`5.5MB``dmg`可视化安装程序`3.1MB``app`还能再次优化到`2MB`
左右!!**
> 使用场景:本软件可以用在任意 TypeScript 项目中!只要你调接口了,需要为接口返回数据编写类型,那么就可以用。同时为了解耦接口数据字段 和 页面 的深度绑定,可以使用本人的另一个插件 [json-mapper-class](https://www.npmjs.com/package/json-mapper-class)
## 技术栈
- **Tauri**: 基于 `Rust` 的全新桌面端开发框架这里使用2.x版本 **注意: 2.x作者还未开发完成坑非常多慎入项目中用 1.x 即可**
- **Rust**: `Mozilla`开发的为了替代`C++`的系统级编程语言,不建议前端轻易尝试学习
- **Svelte**: 更快更高效更简单好用的 `Vue` 框架 替代者 & 竞争者!
- **Vite**: 更好用快速的 **新型前端构建工具**
- **TypeScript**: 基于 `JavaScript` 构建的强类型编程语言
- **monaco-editor**: `vscode` 的代码编辑器
- **json-class-interface**: 本人的`JSON`转换插件,强烈建议搭配我的另外一个插件 [json-mapper-class](https://www.npmjs.com/package/json-mapper-class) 一起使用
- **svelte-spa-router**: `svelte`的第三方路由
- **svelte-ui**: 唯一还能将就用的 `svelte` 第三方UI框架
## 已实现的功能
- [x] 1: `Json` 转换为 `Class`
- [x] 2: `Json` 转换为 `Interface` 接口
- [x] 3: 转换为**类**时候 自动生成 属性装饰器 `property`
- [x] 4: 转换为**类**时候,可以通过**设置**决定是否为 属性装饰器 `property` 开启默认值
- [x] 5: 可选 `Json` 数据中 `Value``null` 的类型
- [x] 6: **自动存储** 生成 的代码 到 **你指定的路径**,并**配置文件名**
- [x] 7: 手动 切换 **白天模式 & 夜间模式**,或是 **跟随操作系统自动切换**
- [x] 8: 开关 **代码行号**
- [x] 9: 开关 **代码小地图**
- [x] 10: 开关 自动粘贴代码 进入**剪贴板**
- [x] 11: 开机自启
- [x] 12: 软件升级
- [x] 13: 启动欢迎页面
## Windows & MacOs & Linux 下载
**下载地址:** [releases](https://gitee.com/bmycode/json-class-desktop/releases)
**文件说明:**
- Windows 版本JsonToClass_x.x.x_x64-setup.exe
- MacOs 版本JsonToClass_x.x.x_x64.dmg
- Linux 版本JsonToClass_x.x.x_amd64.deb
**注意事项:**
1MacOs 端由于没有`Apple`开发者账号无法进行软件签名,所以安装后打开的时候会提示风险,无法打开,具体参考这篇教程:
[https://blog.csdn.net/m0_37482190/article/details/128957808](https://blog.csdn.net/m0_37482190/article/details/128957808)
2**代码更新速度较快,所以 安装包 落后于 最新代码,有能力的推荐自己部署 Rust + Tauri 环境然后对代码进行打包即可!!!**
## 软件展示
![0](build/img/0.png)
![1](build/img/1.png)
![2](build/img/2.png)
![3](build/img/3.png)
![4](build/img/4.png)
![5](build/img/5.png)
![6](build/img/6.png)

View File

@@ -0,0 +1 @@
4408a16a-b5c1-47d5-9698-a27572ed5880

Binary file not shown.

View File

@@ -0,0 +1 @@
785daa35-f2c9-409b-ac24-288dc7e2af46

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

13
json-to-class/build/icns.sh Executable file
View File

@@ -0,0 +1,13 @@
#!/bin/bash
sips -z 16 16 JsonToClass.png --out JsonToClass.iconset/icon_16x16.png
sips -z 32 32 JsonToClass.png --out JsonToClass.iconset/icon_16x16@2x.png
sips -z 32 32 JsonToClass.png --out JsonToClass.iconset/icon_32x32.png
sips -z 64 64 JsonToClass.png --out JsonToClass.iconset/icon_32x32@2x.png
sips -z 128 128 JsonToClass.png --out JsonToClass.iconset/icon_128x128.png
sips -z 256 256 JsonToClass.png --out JsonToClass.iconset/icon_128x128@2x.png
sips -z 256 256 JsonToClass.png --out JsonToClass.iconset/icon_256x256.png
sips -z 512 512 JsonToClass.png --out JsonToClass.iconset/icon_256x256@2x.png
sips -z 512 512 JsonToClass.png --out JsonToClass.iconset/icon_512x512.png
sips -z 512 512 JsonToClass.png --out JsonToClass.iconset/icon_512x512@2x.png
iconutil -c icns JsonToClass.iconset -o JsonToClass.icns

View File

@@ -0,0 +1 @@
ee0f13d5-2393-42c0-9f2c-b24b7071070f

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

14
json-to-class/index.html Normal file
View File

@@ -0,0 +1,14 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./iconfont/iconfont.css">
<title></title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

View File

@@ -0,0 +1,47 @@
{
"name": "json-to-class",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"check": "svelte-check --tsconfig ./tsconfig.json",
"tauri-dev": "tauri dev",
"tauri-build": "tauri build",
"tauri": "tauri"
},
"dependencies": {
"@svelteuidev/composables": "^0.15.3",
"@svelteuidev/core": "^0.15.3",
"@tauri-apps/api": "^2.0.0-alpha.11",
"@tauri-apps/plugin-autostart": "^2.0.0-alpha.3",
"@tauri-apps/plugin-clipboard-manager": "^2.0.0-alpha.3",
"@tauri-apps/plugin-dialog": "^2.0.0-alpha.3",
"@tauri-apps/plugin-fs": "^2.0.0-alpha.3",
"@tauri-apps/plugin-notification": "^2.0.0-alpha.3",
"@tauri-apps/plugin-shell": "^2.0.0-alpha.3",
"@tauri-apps/plugin-window": "^2.0.0-alpha.1",
"json-class-interface": "^1.1.7",
"monaco-editor": "^0.43.0",
"svelte-spa-router": "^3.3.0"
},
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "^2.4.2",
"@tauri-apps/cli": "^2.0.0-rc.3",
"@tsconfig/svelte": "^5.0.0",
"@types/node": "^20.9.0",
"internal-ip": "^7.0.0",
"less": "^4.2.0",
"reflect-metadata": "^0.1.13",
"rollup-plugin-visualizer": "^5.9.2",
"svelte": "^4.0.5",
"svelte-check": "^3.4.6",
"svelte-preprocess-less": "^0.4.0",
"tslib": "^2.6.0",
"typescript": "^5.0.2",
"vite": "^4.4.4",
"vite-plugin-monaco-editor": "^1.1.0"
}
}

View File

@@ -0,0 +1 @@
217a9024-c835-4293-9269-e7be2a8dd55f

View File

@@ -0,0 +1 @@
9b4a28d6-e012-4f66-bc67-f102e825d19a

View File

@@ -0,0 +1,91 @@
@font-face {
font-family: "iconfont"; /* Project id 4318577 */
src: url('./iconfont.woff2?t=1700074221843') format('woff2'),
url('./iconfont.woff?t=1700074221843') format('woff'),
url('./iconfont.ttf?t=1700074221843') format('truetype');
}
.iconfont {
font-family: "iconfont", serif !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.json-guanyu:before {
content: "\e60b";
}
.json-cuowutishi-copy:before {
content: "\e7a2";
}
.json-wenjianjia:before {
content: "\e67c";
}
.json-sucai:before {
content: "\e603";
}
.json-open-folder:before {
content: "\e677";
}
.json-json:before {
content: "\e7bd";
}
.json-cunchuqia:before {
content: "\e638";
}
.json-cunchu:before {
content: "\e602";
}
.json-gengduo:before {
content: "\ec1c";
}
.json-shezhi:before {
content: "\e628";
}
.json-gengduo1:before {
content: "\e63f";
}
.json-shezhi2:before {
content: "\e6a9";
}
.json-shezhi-xitongshezhi:before {
content: "\e600";
}
.json-moon:before {
content: "\e6c2";
}
.json-wo:before {
content: "\e60f";
}
.json-wodewo:before {
content: "\e6df";
}
.json-31shezhi:before {
content: "\e601";
}
.json-shezhi1:before {
content: "\e8b7";
}
.json-taiyang:before {
content: "\e709";
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1 @@
7809e461-c368-4067-ae5e-0f0fdcd86be9

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@@ -0,0 +1,159 @@
<!--
~ Copyright (c) 2023.
~
~ 作者bmy
~ 邮箱2271608011@qq.com
~ giteehttps://gitee.com/bmycode
~ githubhttps://github.com/helpcode
~
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
body,ul,li,p,a{
font-family: "Al Bayan", serif;
list-style: none;
margin: 0;
padding: 0;
text-decoration: none;
}
.main {
width: 100%;
height: 100vh;
display: flex;
align-items: center;
flex-direction: column;
padding-top: 60px;
box-sizing: border-box;
}
.main img {
width: 150px;
height: 150px;
}
.main .name {
font-size: 18px;
letter-spacing: 1px;
}
.main .desc {
font-size: 13px;
color: #bdbdbd;
}
.loading,
.loading > div {
position: relative;
box-sizing: border-box;
}
.loading {
display: block;
font-size: 0;
color: #bdbdbd;
margin-top: 20px;
}
.loading.la-dark {
color: #333;
}
.loading > div {
display: inline-block;
float: none;
background-color: currentColor;
border: 0 solid currentColor;
}
.loading > div {
width: 10px;
height: 10px;
border-radius: 100%;
}
.loading > div:first-child {
transform: translateX(0%);
animation: ball-newton-cradle-left 1s 0s ease-out infinite;
}
.loading > div:last-child {
transform: translateX(0%);
animation: ball-newton-cradle-right 1s 0s ease-out infinite;
}
.loading.la-sm {
width: 20px;
height: 4px;
}
.loading.la-sm > div {
width: 4px;
height: 4px;
}
.loading.la-2x {
width: 80px;
height: 20px;
}
.loading.la-2x > div {
width: 20px;
height: 20px;
}
.loading.la-3x {
width: 120px;
height: 30px;
}
.loading.la-3x > div {
width: 30px;
height: 30px;
}
@keyframes ball-newton-cradle-left {
25% {
transform: translateX(-100%);
animation-timing-function: ease-in;
}
50% {
transform: translateX(0%);
}
}
@keyframes ball-newton-cradle-right {
50% {
transform: translateX(0%);
}
75% {
transform: translateX(100%);
animation-timing-function: ease-in;
}
100% {
transform: translateX(0%);
}
}
</style>
</head>
<body>
<div class="main" data-tauri-drag-region>
<img src="./img/JsonToClass.png" alt="">
<p class="name">Json To Class</p>
<p class="desc">帮助您更快编码</p>
<div class="loading">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
</body>
</html>

4
json-to-class/src-tauri/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
# Generated by Cargo
# will have compiled files and executables
/target/

View File

@@ -0,0 +1 @@
66a6e945-2049-4334-8fa1-a7f788930e3e

5061
json-to-class/src-tauri/Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,50 @@
[package]
name = "json-to-calss"
version = "1.0.2"
description = "json转换为类或接口的桌面端工具"
authors = ["bmy"]
license = ""
repository = ""
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
name = "tauri_app_lib"
crate-type = ["staticlib", "cdylib", "rlib"]
[build-dependencies]
tauri-build = { version = "2.0.0-alpha.11", features = [] }
[dependencies]
# devtools
tauri = { version = "2.0.0-alpha.17", features = ["macos-private-api"] }
# 窗口
tauri-plugin-window = "2.0.0-alpha.2"
# shell 命令行
tauri-plugin-shell = "2.0.0-alpha.4"
# 开机自启
tauri-plugin-autostart = "2.0.0-alpha.4"
# 通知
tauri-plugin-notification = "2.0.0-alpha.5"
# fs 文件系统
tauri-plugin-fs = "2.0.0-alpha.4"
# 剪切板插件
tauri-plugin-clipboard-manager = "2.0.0-alpha.4"
# dialog
tauri-plugin-dialog = "2.0.0-alpha.4"
serde_json = "1.0"
window-vibrancy = "0.4.3"
[profile.release]
panic = "abort" # Strip expensive panic clean-up logic
codegen-units = 1 # Compile crates one after another so the compiler can optimize better
lto = true # Enables link to optimizations
opt-level = "s" # Optimize for binary size
strip = true # Remove debug symbols
[features]
# this feature is used for production builds or when `devPath` points to the filesystem
# DO NOT REMOVE!!
custom-protocol = ["tauri/custom-protocol"]

View File

@@ -0,0 +1,3 @@
fn main() {
tauri_build::build()
}

View File

@@ -0,0 +1 @@
f9e7ed09-d338-436e-855a-9f6dc62c18fd

Some files were not shown because too many files have changed in this diff Show More