json-as 1.1.11 → 1.1.13
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/CHANGELOG.md +15 -0
- package/README.md +1 -1
- package/assembly/__benches__/large.bench.ts +22 -19
- package/assembly/__tests__/generics.spec.ts +40 -0
- package/assembly/__tests__/lib/index.ts +3 -7
- package/assembly/__tests__/resolving.spec.ts +47 -0
- package/assembly/__tests__/types.spec.ts +26 -0
- package/assembly/test.json.ts +388 -0
- package/assembly/test.ts +28 -177
- package/assembly/types.ts +0 -1
- package/bench/large.bench.ts +104 -215
- package/package.json +2 -3
- package/run-bench.js.sh +1 -1
- package/transform/lib/index.js +78 -82
- package/transform/lib/index.js.map +1 -1
- package/transform/lib/linkers/alias.js +49 -0
- package/transform/lib/linkers/alias.js.map +1 -0
- package/transform/lib/{linker.js → linkers/classes.js} +3 -17
- package/transform/lib/linkers/classes.js.map +1 -0
- package/transform/lib/linkers/custom.js +32 -0
- package/transform/lib/linkers/custom.js.map +1 -0
- package/transform/lib/linkers/imports.js +17 -0
- package/transform/lib/linkers/imports.js.map +1 -0
- package/transform/lib/types.js +13 -0
- package/transform/lib/types.js.map +1 -1
- package/transform/src/index.ts +73 -84
- package/transform/src/linkers/alias.ts +59 -0
- package/transform/src/{linker.ts → linkers/classes.ts} +3 -23
- package/transform/src/linkers/custom.ts +32 -0
- package/transform/src/linkers/imports.ts +22 -0
- package/transform/src/types.ts +15 -1
- package/transform/tsconfig.json +1 -1
- package/bench/lib/test.ts +0 -37
- package/transform/lib/linker.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 2025-05-29 - 1.1.13
|
|
4
|
+
|
|
5
|
+
- fix: small issues with schema linking
|
|
6
|
+
- tests: add tests for schema linking and discovery
|
|
7
|
+
|
|
8
|
+
## 2025-05-29 - 1.1.12
|
|
9
|
+
|
|
10
|
+
- fix: add helpful warning on unknown or unaccessible types in fields
|
|
11
|
+
- feat: support deserialization of class generics
|
|
12
|
+
- fix: add support for numerical generics
|
|
13
|
+
- tests: add proper testing for generics
|
|
14
|
+
- feat: support type aliases with a custom type resolver/linker
|
|
15
|
+
- chore: add other linkers to tsconfig and clean up
|
|
16
|
+
- feat: add type alias resolving
|
|
17
|
+
|
|
3
18
|
## 2025-05-28 - 1.1.11
|
|
4
19
|
|
|
5
20
|
- fix: class resolving should only search top level statements for class declarations
|
package/README.md
CHANGED
|
@@ -2,10 +2,11 @@ import { JSON } from "..";
|
|
|
2
2
|
import { expect } from "../__tests__/lib";
|
|
3
3
|
import { bench } from "./lib/bench";
|
|
4
4
|
|
|
5
|
+
|
|
5
6
|
@json
|
|
6
7
|
class RepoOwner {
|
|
7
8
|
public login!: string;
|
|
8
|
-
public id!:
|
|
9
|
+
public id!: i32;
|
|
9
10
|
public node_id!: string;
|
|
10
11
|
public avatar_url!: string;
|
|
11
12
|
public gravatar_id!: string;
|
|
@@ -25,6 +26,7 @@ class RepoOwner {
|
|
|
25
26
|
public site_admin!: boolean;
|
|
26
27
|
}
|
|
27
28
|
|
|
29
|
+
|
|
28
30
|
@json
|
|
29
31
|
class RepoLicense {
|
|
30
32
|
public key!: string;
|
|
@@ -34,9 +36,10 @@ class RepoLicense {
|
|
|
34
36
|
public node_id!: string;
|
|
35
37
|
}
|
|
36
38
|
|
|
39
|
+
|
|
37
40
|
@json
|
|
38
41
|
class Repo {
|
|
39
|
-
public id!:
|
|
42
|
+
public id!: i32;
|
|
40
43
|
public node_id!: string;
|
|
41
44
|
public name!: string;
|
|
42
45
|
public full_name!: string;
|
|
@@ -90,9 +93,9 @@ class Repo {
|
|
|
90
93
|
public clone_url!: string;
|
|
91
94
|
public svn_url!: string;
|
|
92
95
|
public homepage!: string | null;
|
|
93
|
-
public size!:
|
|
94
|
-
public stargazers_count!:
|
|
95
|
-
public watchers_count!:
|
|
96
|
+
public size!: i32;
|
|
97
|
+
public stargazers_count!: i32;
|
|
98
|
+
public watchers_count!: i32;
|
|
96
99
|
public language!: string | null;
|
|
97
100
|
public has_issues!: boolean;
|
|
98
101
|
public has_projects!: boolean;
|
|
@@ -100,24 +103,24 @@ class Repo {
|
|
|
100
103
|
public has_wiki!: boolean;
|
|
101
104
|
public has_pages!: boolean;
|
|
102
105
|
public has_discussions!: boolean;
|
|
103
|
-
public forks_count!:
|
|
106
|
+
public forks_count!: i32;
|
|
104
107
|
public mirror_url!: string | null;
|
|
105
108
|
public archived!: boolean;
|
|
106
109
|
public disabled!: boolean;
|
|
107
|
-
public open_issues_count!:
|
|
110
|
+
public open_issues_count!: i32;
|
|
108
111
|
public license!: RepoLicense | null;
|
|
109
112
|
public allow_forking!: boolean;
|
|
110
113
|
public is_template!: boolean;
|
|
111
114
|
public web_commit_signoff_required!: boolean;
|
|
112
115
|
public topics!: string[];
|
|
113
116
|
public visibility!: string;
|
|
114
|
-
public forks!:
|
|
115
|
-
public open_issues!:
|
|
116
|
-
public watchers!:
|
|
117
|
+
public forks!: i32;
|
|
118
|
+
public open_issues!: i32;
|
|
119
|
+
public watchers!: i32;
|
|
117
120
|
public default_branch!: string;
|
|
118
121
|
}
|
|
119
122
|
|
|
120
|
-
|
|
123
|
+
const v1: Repo = {
|
|
121
124
|
id: 132935648,
|
|
122
125
|
node_id: "MDEwOlJlcG9zaXRvcnkxMzI5MzU2NDg=",
|
|
123
126
|
name: "boysenberry-repo-1",
|
|
@@ -142,7 +145,7 @@ let v1: Repo = {
|
|
|
142
145
|
received_events_url: "https://api.github.com/users/octocat/received_events",
|
|
143
146
|
type: "User",
|
|
144
147
|
user_view_type: "public",
|
|
145
|
-
site_admin: false
|
|
148
|
+
site_admin: false,
|
|
146
149
|
},
|
|
147
150
|
html_url: "https://github.com/octocat/boysenberry-repo-1",
|
|
148
151
|
description: "Testing",
|
|
@@ -216,26 +219,26 @@ let v1: Repo = {
|
|
|
216
219
|
forks: 20,
|
|
217
220
|
open_issues: 1,
|
|
218
221
|
watchers: 332,
|
|
219
|
-
default_branch: "master"
|
|
220
|
-
}
|
|
222
|
+
default_branch: "master",
|
|
223
|
+
};
|
|
221
224
|
|
|
222
225
|
const v2 = `{"id":132935648,"node_id":"MDEwOlJlcG9zaXRvcnkxMzI5MzU2NDg=","name":"boysenberry-repo-1","full_name":"octocat/boysenberry-repo-1","private":true,"owner":{"login":"octocat","id":583231,"node_id":"MDQ6VXNlcjU4MzIzMQ==","avatar_url":"https://avatars.githubusercontent.com/u/583231?v=4","gravatar_id":"","url":"https://api.github.com/users/octocat","html_url":"https://github.com/octocat","followers_url":"https://api.github.com/users/octocat/followers","following_url":"https://api.github.com/users/octocat/following{/other_user}","gists_url":"https://api.github.com/users/octocat/gists{/gist_id}","starred_url":"https://api.github.com/users/octocat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/octocat/subscriptions","organizations_url":"https://api.github.com/users/octocat/orgs","repos_url":"https://api.github.com/users/octocat/repos","events_url":"https://api.github.com/users/octocat/events{/privacy}","received_events_url":"https://api.github.com/users/octocat/received_events","type":"User","user_view_type":"public","site_admin":false},"html_url":"https://github.com/octocat/boysenberry-repo-1","description":"Testing","fork":true,"url":"https://api.github.com/repos/octocat/boysenberry-repo-1","forks_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/forks","keys_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/keys{/key_id}","collaborators_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/teams","hooks_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/hooks","issue_events_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/issues/events{/number}","events_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/events","assignees_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/assignees{/user}","branches_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/branches{/branch}","tags_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/tags","blobs_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/git/refs{/sha}","trees_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/git/trees{/sha}","statuses_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/statuses/{sha}","languages_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/languages","stargazers_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/stargazers","contributors_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/contributors","subscribers_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/subscribers","subscription_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/subscription","commits_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/commits{/sha}","git_commits_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/git/commits{/sha}","comments_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/comments{/number}","issue_comment_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/issues/comments{/number}","contents_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/contents/{+path}","compare_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/compare/{base}...{head}","merges_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/merges","archive_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/downloads","issues_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/issues{/number}","pulls_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/pulls{/number}","milestones_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/milestones{/number}","notifications_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/labels{/name}","releases_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/releases{/id}","deployments_url":"https://api.github.com/repos/octocat/boysenberry-repo-1/deployments","created_at":"2018-05-10T17:51:29Z","updated_at":"2025-05-24T02:01:19Z","pushed_at":"2024-05-26T07:02:05Z","git_url":"git://github.com/octocat/boysenberry-repo-1.git","ssh_url":"git@github.com:octocat/boysenberry-repo-1.git","clone_url":"https://github.com/octocat/boysenberry-repo-1.git","svn_url":"https://github.com/octocat/boysenberry-repo-1","homepage":"","size":4,"stargazers_count":332,"watchers_count":332,"language":null,"has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"has_discussions":false,"forks_count":20,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":1,"license":null,"allow_forking":true,"is_template":false,"web_commit_signoff_required":false,"topics":[],"visibility":"public","forks":20,"open_issues":1,"watchers":332,"default_branch":"master"}`;
|
|
223
226
|
|
|
224
227
|
expect(JSON.stringify(v1)).toBe(v2);
|
|
225
|
-
expect(JSON.stringify(JSON.parse(v2))).toBe(v2);
|
|
228
|
+
expect(JSON.stringify(JSON.parse<Repo>(v2))).toBe(v2);
|
|
226
229
|
|
|
227
230
|
bench(
|
|
228
231
|
"Serialize Large Object",
|
|
229
232
|
() => {
|
|
230
233
|
JSON.stringify(v1);
|
|
231
234
|
},
|
|
232
|
-
|
|
235
|
+
100_00,
|
|
233
236
|
);
|
|
234
237
|
|
|
235
238
|
bench(
|
|
236
239
|
"Deserialize Large Object",
|
|
237
240
|
() => {
|
|
238
|
-
JSON.parse(v2);
|
|
241
|
+
JSON.parse<Repo>(v2);
|
|
239
242
|
},
|
|
240
|
-
|
|
241
|
-
);
|
|
243
|
+
100_00,
|
|
244
|
+
);
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { JSON } from "..";
|
|
2
|
+
import { describe, expect } from "./lib";
|
|
3
|
+
|
|
4
|
+
@json
|
|
5
|
+
class GenericTest<T> {
|
|
6
|
+
public foo: T;
|
|
7
|
+
|
|
8
|
+
constructor(foo: T) {
|
|
9
|
+
this.foo = foo;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@json
|
|
14
|
+
class Vec3 {
|
|
15
|
+
public x!: i32;
|
|
16
|
+
public y!: i32;
|
|
17
|
+
public z!: i32;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
describe("Should serialize generics", () => {
|
|
21
|
+
expect(JSON.stringify(new GenericTest<string>("bar"))).toBe('{"foo":"bar"}');
|
|
22
|
+
expect(JSON.stringify(new GenericTest<i32>(42))).toBe('{"foo":42}');
|
|
23
|
+
expect(JSON.stringify(new GenericTest<boolean>(true))).toBe('{"foo":true}');
|
|
24
|
+
expect(JSON.stringify(new GenericTest<Vec3>({ x: 1, y: 2, z: 3 }))).toBe('{"foo":{"x":1,"y":2,"z":3}}');
|
|
25
|
+
expect(JSON.stringify(new GenericTest<string[]>(["item1", "item2"]))).toBe('{"foo":["item1","item2"]}');
|
|
26
|
+
expect(JSON.stringify(new GenericTest<Vec3[]>([{ x: 1, y: 2, z: 3 }, { x: 4, y: 5, z: 6 }]))).toBe('{"foo":[{"x":1,"y":2,"z":3},{"x":4,"y":5,"z":6}]}');
|
|
27
|
+
expect(JSON.stringify(new GenericTest<i32[]>([1, 2, 3]))).toBe('{"foo":[1,2,3]}');
|
|
28
|
+
expect(JSON.stringify(new GenericTest<boolean[]>([true, false, true]))).toBe('{"foo":[true,false,true]}');
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe("Should deserialize generics", () => {
|
|
32
|
+
expect(JSON.parse<GenericTest<string>>('{"foo":"bar"}').foo).toBe("bar");
|
|
33
|
+
expect(JSON.parse<GenericTest<i32>>('{"foo":42}').foo.toString()).toBe("42");
|
|
34
|
+
expect(JSON.parse<GenericTest<boolean>>('{"foo":true}').foo).toBe(true);
|
|
35
|
+
expect(JSON.stringify(JSON.parse<GenericTest<Vec3>>('{"foo":{"x":1,"y":2,"z":3}}'))).toBe('{"foo":{"x":1,"y":2,"z":3}}');
|
|
36
|
+
expect(JSON.stringify(JSON.parse<GenericTest<string[]>>('{"foo":["item1","item2"]}'))).toBe('{"foo":["item1","item2"]}');
|
|
37
|
+
expect(JSON.stringify(JSON.parse<GenericTest<Vec3[]>>('{"foo":[{"x":1,"y":2,"z":3},{"x":4,"y":5,"z":6}]}'))).toBe('{"foo":[{"x":1,"y":2,"z":3},{"x":4,"y":5,"z":6}]}');
|
|
38
|
+
expect(JSON.stringify(JSON.parse<GenericTest<i32[]>>('{"foo":[1,2,3]}'))).toBe('{"foo":[1,2,3]}');
|
|
39
|
+
expect(JSON.stringify(JSON.parse<GenericTest<boolean[]>>('{"foo":[true,false,true]}'))).toBe('{"foo":[true,false,true]}');
|
|
40
|
+
});
|
|
@@ -13,7 +13,7 @@ export function expect<T>(left: T): Expectation {
|
|
|
13
13
|
// @ts-ignore
|
|
14
14
|
if (!isDefined(left.toString)) throw new Error("Expected left to have a toString method, but it does not.");
|
|
15
15
|
// @ts-ignore
|
|
16
|
-
return new Expectation(
|
|
16
|
+
return new Expectation(left == null ? "null" : left.toString());
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
class Expectation {
|
|
@@ -26,16 +26,12 @@ class Expectation {
|
|
|
26
26
|
// @ts-ignore
|
|
27
27
|
if (!isDefined(right.toString)) throw new Error("Expected right to have a toString method, but it does not.");
|
|
28
28
|
// @ts-ignore
|
|
29
|
-
if (this.left != (
|
|
29
|
+
if (this.left != (right == null ? "null" : right.toString())) {
|
|
30
30
|
console.log(" " + currentDescription + "\n");
|
|
31
31
|
// @ts-ignore
|
|
32
|
-
console.log(" (expected) -> " + (
|
|
32
|
+
console.log(" (expected) -> " + (right == null ? "null" : right.toString()));
|
|
33
33
|
console.log(" (received) -> " + this.left);
|
|
34
34
|
unreachable();
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
|
-
|
|
39
|
-
function isNull<T>(value: T): boolean {
|
|
40
|
-
return isInteger<T>() && !isSigned<T>() && nameof<T>() == "usize" && value == 0;
|
|
41
|
-
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { JSON } from "..";
|
|
2
|
+
import { describe, expect } from "./lib";
|
|
3
|
+
import { Vec3 } from "./types";
|
|
4
|
+
|
|
5
|
+
@json
|
|
6
|
+
class Player {
|
|
7
|
+
@alias("first name")
|
|
8
|
+
firstName!: string;
|
|
9
|
+
lastName!: string;
|
|
10
|
+
lastActive!: i32[];
|
|
11
|
+
@omitif((self: Player) => self.age < 18)
|
|
12
|
+
age!: i32;
|
|
13
|
+
@omitnull()
|
|
14
|
+
pos!: Vec3 | null;
|
|
15
|
+
isVerified!: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const player: Player = {
|
|
19
|
+
firstName: "Jairus",
|
|
20
|
+
lastName: "Tanaka",
|
|
21
|
+
lastActive: [3, 9, 2025],
|
|
22
|
+
age: 18,
|
|
23
|
+
pos: {
|
|
24
|
+
x: 3.4,
|
|
25
|
+
y: 1.2,
|
|
26
|
+
z: 8.3,
|
|
27
|
+
},
|
|
28
|
+
isVerified: true,
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
@json
|
|
32
|
+
class Foo {
|
|
33
|
+
bar: Bar = new Bar();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@json
|
|
37
|
+
class Bar {
|
|
38
|
+
baz: string = "buz"
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
describe("Should resolve imported schemas", () => {
|
|
42
|
+
expect(JSON.stringify(player)).toBe('{"age":18,"pos":{"x":3.4,"y":1.2,"z":8.3},"first name":"Jairus","lastName":"Tanaka","lastActive":[3,9,2025],"isVerified":true}');
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe("Should resolve local schemas", () => {
|
|
46
|
+
expect(JSON.stringify(new Foo())).toBe('{"bar":{"baz":"buz"}}');
|
|
47
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { JSON } from "..";
|
|
2
|
+
import { describe, expect } from "./lib";
|
|
3
|
+
|
|
4
|
+
type StringAlias = string;
|
|
5
|
+
type StringAlias1 = StringAlias;
|
|
6
|
+
type StringAlias2 = StringAlias1;
|
|
7
|
+
type StringAlias3 = StringAlias2;
|
|
8
|
+
type StringAlias4 = StringAlias3;
|
|
9
|
+
|
|
10
|
+
@json
|
|
11
|
+
class Alias {
|
|
12
|
+
public foo: StringAlias4 = "";
|
|
13
|
+
constructor(foo: StringAlias2) {
|
|
14
|
+
this.foo = foo;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const alias = new Alias("bar");
|
|
19
|
+
|
|
20
|
+
describe("Should serialize with type aliases", () => {
|
|
21
|
+
expect(JSON.stringify(alias)).toBe('{"foo":"bar"}');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
describe("Should deserialize with type aliases", () => {
|
|
25
|
+
expect(JSON.stringify(JSON.parse<Alias>('{"foo":"bar"}'))).toBe('{"foo":"bar"}');
|
|
26
|
+
});
|