@xnetjs/data 0.0.2
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/LICENSE +21 -0
- package/README.md +229 -0
- package/dist/canvas-HSIKIQFK.js +7 -0
- package/dist/chunk-2L5ZUGG5.js +53 -0
- package/dist/chunk-4MTS5KAQ.js +22 -0
- package/dist/chunk-BQBPA5HS.js +76 -0
- package/dist/chunk-GZHARFKC.js +25 -0
- package/dist/chunk-IDMBCRUC.js +29 -0
- package/dist/chunk-SZC345Z2.js +2347 -0
- package/dist/chunk-VYR5GPJP.js +39 -0
- package/dist/chunk-WKIKJTI2.js +45 -0
- package/dist/comment-277JD7DV.js +7 -0
- package/dist/database-W3KEHLI3.js +7 -0
- package/dist/database-row-3O2QSNZN.js +7 -0
- package/dist/grant-QVZ454YC.js +7 -0
- package/dist/index.d.ts +4598 -0
- package/dist/index.js +5103 -0
- package/dist/page-O4WTOIEO.js +7 -0
- package/dist/task-SEKAYJH7.js +7 -0
- package/dist/ts-plugin/index.cjs +240 -0
- package/dist/ts-plugin/index.d.cts +46 -0
- package/dist/ts-plugin/index.d.ts +46 -0
- package/dist/ts-plugin/index.js +213 -0
- package/package.json +54 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/ts-plugin/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
default: () => index_default,
|
|
24
|
+
diffSchemaProperties: () => diffSchemaProperties,
|
|
25
|
+
extractSchemaInfo: () => extractSchemaInfo,
|
|
26
|
+
isDefineSchemaCall: () => isDefineSchemaCall
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(index_exports);
|
|
29
|
+
function init(modules) {
|
|
30
|
+
const typescript = modules.typescript;
|
|
31
|
+
function create(info) {
|
|
32
|
+
const logger = info.project.projectService.logger;
|
|
33
|
+
logger.info("[xnet-schema-plugin] Initializing...");
|
|
34
|
+
const proxy = createLanguageServiceProxy(info.languageService);
|
|
35
|
+
const schemaCache = /* @__PURE__ */ new Map();
|
|
36
|
+
proxy.getSemanticDiagnostics = (fileName) => {
|
|
37
|
+
const prior = info.languageService.getSemanticDiagnostics(fileName);
|
|
38
|
+
const program = info.languageService.getProgram();
|
|
39
|
+
if (!program) return prior;
|
|
40
|
+
const sourceFile = program.getSourceFile(fileName);
|
|
41
|
+
if (!sourceFile) return prior;
|
|
42
|
+
const schemaDiagnostics = analyzeSchemaChanges(typescript, sourceFile, schemaCache, logger);
|
|
43
|
+
return [...prior, ...schemaDiagnostics];
|
|
44
|
+
};
|
|
45
|
+
proxy.getCodeFixesAtPosition = (fileName, start, end, errorCodes, formatOptions, preferences) => {
|
|
46
|
+
const prior = info.languageService.getCodeFixesAtPosition(
|
|
47
|
+
fileName,
|
|
48
|
+
start,
|
|
49
|
+
end,
|
|
50
|
+
errorCodes,
|
|
51
|
+
formatOptions,
|
|
52
|
+
preferences
|
|
53
|
+
);
|
|
54
|
+
const schemaFixes = getSchemaCodeFixes(
|
|
55
|
+
typescript,
|
|
56
|
+
info.languageService,
|
|
57
|
+
fileName,
|
|
58
|
+
start,
|
|
59
|
+
end,
|
|
60
|
+
errorCodes
|
|
61
|
+
);
|
|
62
|
+
return [...prior, ...schemaFixes];
|
|
63
|
+
};
|
|
64
|
+
logger.info("[xnet-schema-plugin] Ready");
|
|
65
|
+
return proxy;
|
|
66
|
+
}
|
|
67
|
+
return { create };
|
|
68
|
+
}
|
|
69
|
+
function createLanguageServiceProxy(ls) {
|
|
70
|
+
const proxy = /* @__PURE__ */ Object.create(null);
|
|
71
|
+
for (const k of Object.keys(ls)) {
|
|
72
|
+
const x = ls[k];
|
|
73
|
+
proxy[k] = typeof x === "function" ? x.bind(ls) : x;
|
|
74
|
+
}
|
|
75
|
+
return proxy;
|
|
76
|
+
}
|
|
77
|
+
function analyzeSchemaChanges(typescript, sourceFile, schemaCache, _logger) {
|
|
78
|
+
const diagnostics = [];
|
|
79
|
+
typescript.forEachChild(sourceFile, function visit(node) {
|
|
80
|
+
if (isDefineSchemaCall(typescript, node)) {
|
|
81
|
+
const schemaInfo = extractSchemaInfo(typescript, node, sourceFile);
|
|
82
|
+
if (schemaInfo) {
|
|
83
|
+
const cached = schemaCache.get(schemaInfo.name);
|
|
84
|
+
if (cached && cached.version !== schemaInfo.version) {
|
|
85
|
+
const changes = diffSchemaProperties(cached, schemaInfo);
|
|
86
|
+
const breakingChanges = changes.filter((c) => c.risk === "breaking");
|
|
87
|
+
const cautionChanges = changes.filter((c) => c.risk === "caution");
|
|
88
|
+
for (const change of breakingChanges) {
|
|
89
|
+
diagnostics.push({
|
|
90
|
+
file: sourceFile,
|
|
91
|
+
start: node.getStart(),
|
|
92
|
+
length: node.getWidth(),
|
|
93
|
+
messageText: `Breaking schema change: ${change.description}. ${change.suggestedFix || "Consider adding a migration lens."}`,
|
|
94
|
+
category: typescript.DiagnosticCategory.Error,
|
|
95
|
+
code: 90001,
|
|
96
|
+
// Custom error code
|
|
97
|
+
source: "xnet-schema-plugin"
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
for (const change of cautionChanges) {
|
|
101
|
+
diagnostics.push({
|
|
102
|
+
file: sourceFile,
|
|
103
|
+
start: node.getStart(),
|
|
104
|
+
length: node.getWidth(),
|
|
105
|
+
messageText: `Schema change requires attention: ${change.description}`,
|
|
106
|
+
category: typescript.DiagnosticCategory.Warning,
|
|
107
|
+
code: 90002,
|
|
108
|
+
source: "xnet-schema-plugin"
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
schemaCache.set(schemaInfo.name, schemaInfo);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
typescript.forEachChild(node, visit);
|
|
116
|
+
});
|
|
117
|
+
return diagnostics;
|
|
118
|
+
}
|
|
119
|
+
function isDefineSchemaCall(typescript, node) {
|
|
120
|
+
if (!typescript.isCallExpression(node)) return false;
|
|
121
|
+
const expr = node.expression;
|
|
122
|
+
if (typescript.isIdentifier(expr) && expr.text === "defineSchema") {
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
if (typescript.isPropertyAccessExpression(expr) && typescript.isIdentifier(expr.name) && expr.name.text === "defineSchema") {
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
function extractSchemaInfo(typescript, node, _sourceFile) {
|
|
131
|
+
const args = node.arguments;
|
|
132
|
+
if (args.length === 0) return null;
|
|
133
|
+
const configArg = args[0];
|
|
134
|
+
if (!typescript.isObjectLiteralExpression(configArg)) return null;
|
|
135
|
+
let name = "";
|
|
136
|
+
let version = "1.0.0";
|
|
137
|
+
const properties = /* @__PURE__ */ new Map();
|
|
138
|
+
for (const prop of configArg.properties) {
|
|
139
|
+
if (!typescript.isPropertyAssignment(prop)) continue;
|
|
140
|
+
if (!typescript.isIdentifier(prop.name)) continue;
|
|
141
|
+
const propName = prop.name.text;
|
|
142
|
+
if (propName === "name" && typescript.isStringLiteral(prop.initializer)) {
|
|
143
|
+
name = prop.initializer.text;
|
|
144
|
+
}
|
|
145
|
+
if (propName === "version" && typescript.isStringLiteral(prop.initializer)) {
|
|
146
|
+
version = prop.initializer.text;
|
|
147
|
+
}
|
|
148
|
+
if (propName === "properties" && typescript.isObjectLiteralExpression(prop.initializer)) {
|
|
149
|
+
for (const propDef of prop.initializer.properties) {
|
|
150
|
+
if (!typescript.isPropertyAssignment(propDef)) continue;
|
|
151
|
+
if (!typescript.isIdentifier(propDef.name)) continue;
|
|
152
|
+
const propertyName = propDef.name.text;
|
|
153
|
+
const propertyInfo = extractPropertyInfo(typescript, propDef.initializer);
|
|
154
|
+
if (propertyInfo) {
|
|
155
|
+
properties.set(propertyName, { ...propertyInfo, name: propertyName });
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (!name) return null;
|
|
161
|
+
return { name, version, properties, location: node };
|
|
162
|
+
}
|
|
163
|
+
function extractPropertyInfo(typescript, node) {
|
|
164
|
+
if (!typescript.isObjectLiteralExpression(node)) return null;
|
|
165
|
+
let type = "unknown";
|
|
166
|
+
let required = false;
|
|
167
|
+
for (const prop of node.properties) {
|
|
168
|
+
if (!typescript.isPropertyAssignment(prop)) continue;
|
|
169
|
+
if (!typescript.isIdentifier(prop.name)) continue;
|
|
170
|
+
if (prop.name.text === "type" && typescript.isStringLiteral(prop.initializer)) {
|
|
171
|
+
type = prop.initializer.text;
|
|
172
|
+
}
|
|
173
|
+
if (prop.name.text === "required") {
|
|
174
|
+
required = prop.initializer.kind === typescript.SyntaxKind.TrueKeyword;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return { type, required };
|
|
178
|
+
}
|
|
179
|
+
function diffSchemaProperties(oldSchema, newSchema) {
|
|
180
|
+
const changes = [];
|
|
181
|
+
for (const [name] of oldSchema.properties) {
|
|
182
|
+
if (!newSchema.properties.has(name)) {
|
|
183
|
+
changes.push({
|
|
184
|
+
type: "remove",
|
|
185
|
+
property: name,
|
|
186
|
+
risk: "caution",
|
|
187
|
+
description: `Property "${name}" was removed`,
|
|
188
|
+
suggestedFix: `Add lens: remove('${name}')`
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
for (const [name, newProp] of newSchema.properties) {
|
|
193
|
+
if (!oldSchema.properties.has(name)) {
|
|
194
|
+
changes.push({
|
|
195
|
+
type: "add",
|
|
196
|
+
property: name,
|
|
197
|
+
risk: newProp.required ? "caution" : "safe",
|
|
198
|
+
description: newProp.required ? `Required property "${name}" was added` : `Optional property "${name}" was added`,
|
|
199
|
+
suggestedFix: newProp.required ? `Add lens: addDefault('${name}', defaultValue)` : void 0
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
for (const [name, oldProp] of oldSchema.properties) {
|
|
204
|
+
const newProp = newSchema.properties.get(name);
|
|
205
|
+
if (!newProp) continue;
|
|
206
|
+
if (oldProp.type !== newProp.type) {
|
|
207
|
+
changes.push({
|
|
208
|
+
type: "modify",
|
|
209
|
+
property: name,
|
|
210
|
+
risk: "breaking",
|
|
211
|
+
description: `Property "${name}" changed type from "${oldProp.type}" to "${newProp.type}"`,
|
|
212
|
+
suggestedFix: `Add lens: transform('${name}', forwardFn, backwardFn)`
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
if (!oldProp.required && newProp.required) {
|
|
216
|
+
changes.push({
|
|
217
|
+
type: "modify",
|
|
218
|
+
property: name,
|
|
219
|
+
risk: "caution",
|
|
220
|
+
description: `Property "${name}" became required`,
|
|
221
|
+
suggestedFix: `Add lens: addDefault('${name}', defaultValue)`
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return changes;
|
|
226
|
+
}
|
|
227
|
+
function getSchemaCodeFixes(_typescript, _languageService, _fileName, _start, _end, errorCodes) {
|
|
228
|
+
const fixes = [];
|
|
229
|
+
if (!errorCodes.includes(90001) && !errorCodes.includes(90002)) {
|
|
230
|
+
return fixes;
|
|
231
|
+
}
|
|
232
|
+
return fixes;
|
|
233
|
+
}
|
|
234
|
+
var index_default = init;
|
|
235
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
236
|
+
0 && (module.exports = {
|
|
237
|
+
diffSchemaProperties,
|
|
238
|
+
extractSchemaInfo,
|
|
239
|
+
isDefineSchemaCall
|
|
240
|
+
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import * as ts from 'typescript/lib/tsserverlibrary';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* TypeScript Language Service Plugin for xNet Schema Validation
|
|
5
|
+
*
|
|
6
|
+
* This plugin provides:
|
|
7
|
+
* - Warnings when schema changes are breaking
|
|
8
|
+
* - Suggestions for migration code
|
|
9
|
+
* - Quick fixes for common issues
|
|
10
|
+
*
|
|
11
|
+
* Usage in tsconfig.json:
|
|
12
|
+
* ```json
|
|
13
|
+
* {
|
|
14
|
+
* "compilerOptions": {
|
|
15
|
+
* "plugins": [{ "name": "@xnetjs/data/ts-plugin" }]
|
|
16
|
+
* }
|
|
17
|
+
* }
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
interface SchemaInfo {
|
|
22
|
+
name: string;
|
|
23
|
+
version: string;
|
|
24
|
+
properties: Map<string, PropertyInfo>;
|
|
25
|
+
location: ts.Node;
|
|
26
|
+
}
|
|
27
|
+
interface PropertyInfo {
|
|
28
|
+
name: string;
|
|
29
|
+
type: string;
|
|
30
|
+
required: boolean;
|
|
31
|
+
}
|
|
32
|
+
interface SchemaChange {
|
|
33
|
+
type: 'add' | 'remove' | 'modify' | 'rename';
|
|
34
|
+
property: string;
|
|
35
|
+
risk: 'safe' | 'caution' | 'breaking';
|
|
36
|
+
description: string;
|
|
37
|
+
suggestedFix?: string;
|
|
38
|
+
}
|
|
39
|
+
declare function init(modules: {
|
|
40
|
+
typescript: typeof ts;
|
|
41
|
+
}): ts.server.PluginModule;
|
|
42
|
+
declare function isDefineSchemaCall(typescript: typeof ts, node: ts.Node): node is ts.CallExpression;
|
|
43
|
+
declare function extractSchemaInfo(typescript: typeof ts, node: ts.CallExpression, _sourceFile: ts.SourceFile): SchemaInfo | null;
|
|
44
|
+
declare function diffSchemaProperties(oldSchema: SchemaInfo, newSchema: SchemaInfo): SchemaChange[];
|
|
45
|
+
|
|
46
|
+
export { type PropertyInfo, type SchemaChange, type SchemaInfo, init as default, diffSchemaProperties, extractSchemaInfo, isDefineSchemaCall };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import * as ts from 'typescript/lib/tsserverlibrary';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* TypeScript Language Service Plugin for xNet Schema Validation
|
|
5
|
+
*
|
|
6
|
+
* This plugin provides:
|
|
7
|
+
* - Warnings when schema changes are breaking
|
|
8
|
+
* - Suggestions for migration code
|
|
9
|
+
* - Quick fixes for common issues
|
|
10
|
+
*
|
|
11
|
+
* Usage in tsconfig.json:
|
|
12
|
+
* ```json
|
|
13
|
+
* {
|
|
14
|
+
* "compilerOptions": {
|
|
15
|
+
* "plugins": [{ "name": "@xnetjs/data/ts-plugin" }]
|
|
16
|
+
* }
|
|
17
|
+
* }
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
interface SchemaInfo {
|
|
22
|
+
name: string;
|
|
23
|
+
version: string;
|
|
24
|
+
properties: Map<string, PropertyInfo>;
|
|
25
|
+
location: ts.Node;
|
|
26
|
+
}
|
|
27
|
+
interface PropertyInfo {
|
|
28
|
+
name: string;
|
|
29
|
+
type: string;
|
|
30
|
+
required: boolean;
|
|
31
|
+
}
|
|
32
|
+
interface SchemaChange {
|
|
33
|
+
type: 'add' | 'remove' | 'modify' | 'rename';
|
|
34
|
+
property: string;
|
|
35
|
+
risk: 'safe' | 'caution' | 'breaking';
|
|
36
|
+
description: string;
|
|
37
|
+
suggestedFix?: string;
|
|
38
|
+
}
|
|
39
|
+
declare function init(modules: {
|
|
40
|
+
typescript: typeof ts;
|
|
41
|
+
}): ts.server.PluginModule;
|
|
42
|
+
declare function isDefineSchemaCall(typescript: typeof ts, node: ts.Node): node is ts.CallExpression;
|
|
43
|
+
declare function extractSchemaInfo(typescript: typeof ts, node: ts.CallExpression, _sourceFile: ts.SourceFile): SchemaInfo | null;
|
|
44
|
+
declare function diffSchemaProperties(oldSchema: SchemaInfo, newSchema: SchemaInfo): SchemaChange[];
|
|
45
|
+
|
|
46
|
+
export { type PropertyInfo, type SchemaChange, type SchemaInfo, init as default, diffSchemaProperties, extractSchemaInfo, isDefineSchemaCall };
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
// src/ts-plugin/index.ts
|
|
2
|
+
function init(modules) {
|
|
3
|
+
const typescript = modules.typescript;
|
|
4
|
+
function create(info) {
|
|
5
|
+
const logger = info.project.projectService.logger;
|
|
6
|
+
logger.info("[xnet-schema-plugin] Initializing...");
|
|
7
|
+
const proxy = createLanguageServiceProxy(info.languageService);
|
|
8
|
+
const schemaCache = /* @__PURE__ */ new Map();
|
|
9
|
+
proxy.getSemanticDiagnostics = (fileName) => {
|
|
10
|
+
const prior = info.languageService.getSemanticDiagnostics(fileName);
|
|
11
|
+
const program = info.languageService.getProgram();
|
|
12
|
+
if (!program) return prior;
|
|
13
|
+
const sourceFile = program.getSourceFile(fileName);
|
|
14
|
+
if (!sourceFile) return prior;
|
|
15
|
+
const schemaDiagnostics = analyzeSchemaChanges(typescript, sourceFile, schemaCache, logger);
|
|
16
|
+
return [...prior, ...schemaDiagnostics];
|
|
17
|
+
};
|
|
18
|
+
proxy.getCodeFixesAtPosition = (fileName, start, end, errorCodes, formatOptions, preferences) => {
|
|
19
|
+
const prior = info.languageService.getCodeFixesAtPosition(
|
|
20
|
+
fileName,
|
|
21
|
+
start,
|
|
22
|
+
end,
|
|
23
|
+
errorCodes,
|
|
24
|
+
formatOptions,
|
|
25
|
+
preferences
|
|
26
|
+
);
|
|
27
|
+
const schemaFixes = getSchemaCodeFixes(
|
|
28
|
+
typescript,
|
|
29
|
+
info.languageService,
|
|
30
|
+
fileName,
|
|
31
|
+
start,
|
|
32
|
+
end,
|
|
33
|
+
errorCodes
|
|
34
|
+
);
|
|
35
|
+
return [...prior, ...schemaFixes];
|
|
36
|
+
};
|
|
37
|
+
logger.info("[xnet-schema-plugin] Ready");
|
|
38
|
+
return proxy;
|
|
39
|
+
}
|
|
40
|
+
return { create };
|
|
41
|
+
}
|
|
42
|
+
function createLanguageServiceProxy(ls) {
|
|
43
|
+
const proxy = /* @__PURE__ */ Object.create(null);
|
|
44
|
+
for (const k of Object.keys(ls)) {
|
|
45
|
+
const x = ls[k];
|
|
46
|
+
proxy[k] = typeof x === "function" ? x.bind(ls) : x;
|
|
47
|
+
}
|
|
48
|
+
return proxy;
|
|
49
|
+
}
|
|
50
|
+
function analyzeSchemaChanges(typescript, sourceFile, schemaCache, _logger) {
|
|
51
|
+
const diagnostics = [];
|
|
52
|
+
typescript.forEachChild(sourceFile, function visit(node) {
|
|
53
|
+
if (isDefineSchemaCall(typescript, node)) {
|
|
54
|
+
const schemaInfo = extractSchemaInfo(typescript, node, sourceFile);
|
|
55
|
+
if (schemaInfo) {
|
|
56
|
+
const cached = schemaCache.get(schemaInfo.name);
|
|
57
|
+
if (cached && cached.version !== schemaInfo.version) {
|
|
58
|
+
const changes = diffSchemaProperties(cached, schemaInfo);
|
|
59
|
+
const breakingChanges = changes.filter((c) => c.risk === "breaking");
|
|
60
|
+
const cautionChanges = changes.filter((c) => c.risk === "caution");
|
|
61
|
+
for (const change of breakingChanges) {
|
|
62
|
+
diagnostics.push({
|
|
63
|
+
file: sourceFile,
|
|
64
|
+
start: node.getStart(),
|
|
65
|
+
length: node.getWidth(),
|
|
66
|
+
messageText: `Breaking schema change: ${change.description}. ${change.suggestedFix || "Consider adding a migration lens."}`,
|
|
67
|
+
category: typescript.DiagnosticCategory.Error,
|
|
68
|
+
code: 90001,
|
|
69
|
+
// Custom error code
|
|
70
|
+
source: "xnet-schema-plugin"
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
for (const change of cautionChanges) {
|
|
74
|
+
diagnostics.push({
|
|
75
|
+
file: sourceFile,
|
|
76
|
+
start: node.getStart(),
|
|
77
|
+
length: node.getWidth(),
|
|
78
|
+
messageText: `Schema change requires attention: ${change.description}`,
|
|
79
|
+
category: typescript.DiagnosticCategory.Warning,
|
|
80
|
+
code: 90002,
|
|
81
|
+
source: "xnet-schema-plugin"
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
schemaCache.set(schemaInfo.name, schemaInfo);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
typescript.forEachChild(node, visit);
|
|
89
|
+
});
|
|
90
|
+
return diagnostics;
|
|
91
|
+
}
|
|
92
|
+
function isDefineSchemaCall(typescript, node) {
|
|
93
|
+
if (!typescript.isCallExpression(node)) return false;
|
|
94
|
+
const expr = node.expression;
|
|
95
|
+
if (typescript.isIdentifier(expr) && expr.text === "defineSchema") {
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
if (typescript.isPropertyAccessExpression(expr) && typescript.isIdentifier(expr.name) && expr.name.text === "defineSchema") {
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
function extractSchemaInfo(typescript, node, _sourceFile) {
|
|
104
|
+
const args = node.arguments;
|
|
105
|
+
if (args.length === 0) return null;
|
|
106
|
+
const configArg = args[0];
|
|
107
|
+
if (!typescript.isObjectLiteralExpression(configArg)) return null;
|
|
108
|
+
let name = "";
|
|
109
|
+
let version = "1.0.0";
|
|
110
|
+
const properties = /* @__PURE__ */ new Map();
|
|
111
|
+
for (const prop of configArg.properties) {
|
|
112
|
+
if (!typescript.isPropertyAssignment(prop)) continue;
|
|
113
|
+
if (!typescript.isIdentifier(prop.name)) continue;
|
|
114
|
+
const propName = prop.name.text;
|
|
115
|
+
if (propName === "name" && typescript.isStringLiteral(prop.initializer)) {
|
|
116
|
+
name = prop.initializer.text;
|
|
117
|
+
}
|
|
118
|
+
if (propName === "version" && typescript.isStringLiteral(prop.initializer)) {
|
|
119
|
+
version = prop.initializer.text;
|
|
120
|
+
}
|
|
121
|
+
if (propName === "properties" && typescript.isObjectLiteralExpression(prop.initializer)) {
|
|
122
|
+
for (const propDef of prop.initializer.properties) {
|
|
123
|
+
if (!typescript.isPropertyAssignment(propDef)) continue;
|
|
124
|
+
if (!typescript.isIdentifier(propDef.name)) continue;
|
|
125
|
+
const propertyName = propDef.name.text;
|
|
126
|
+
const propertyInfo = extractPropertyInfo(typescript, propDef.initializer);
|
|
127
|
+
if (propertyInfo) {
|
|
128
|
+
properties.set(propertyName, { ...propertyInfo, name: propertyName });
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (!name) return null;
|
|
134
|
+
return { name, version, properties, location: node };
|
|
135
|
+
}
|
|
136
|
+
function extractPropertyInfo(typescript, node) {
|
|
137
|
+
if (!typescript.isObjectLiteralExpression(node)) return null;
|
|
138
|
+
let type = "unknown";
|
|
139
|
+
let required = false;
|
|
140
|
+
for (const prop of node.properties) {
|
|
141
|
+
if (!typescript.isPropertyAssignment(prop)) continue;
|
|
142
|
+
if (!typescript.isIdentifier(prop.name)) continue;
|
|
143
|
+
if (prop.name.text === "type" && typescript.isStringLiteral(prop.initializer)) {
|
|
144
|
+
type = prop.initializer.text;
|
|
145
|
+
}
|
|
146
|
+
if (prop.name.text === "required") {
|
|
147
|
+
required = prop.initializer.kind === typescript.SyntaxKind.TrueKeyword;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return { type, required };
|
|
151
|
+
}
|
|
152
|
+
function diffSchemaProperties(oldSchema, newSchema) {
|
|
153
|
+
const changes = [];
|
|
154
|
+
for (const [name] of oldSchema.properties) {
|
|
155
|
+
if (!newSchema.properties.has(name)) {
|
|
156
|
+
changes.push({
|
|
157
|
+
type: "remove",
|
|
158
|
+
property: name,
|
|
159
|
+
risk: "caution",
|
|
160
|
+
description: `Property "${name}" was removed`,
|
|
161
|
+
suggestedFix: `Add lens: remove('${name}')`
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
for (const [name, newProp] of newSchema.properties) {
|
|
166
|
+
if (!oldSchema.properties.has(name)) {
|
|
167
|
+
changes.push({
|
|
168
|
+
type: "add",
|
|
169
|
+
property: name,
|
|
170
|
+
risk: newProp.required ? "caution" : "safe",
|
|
171
|
+
description: newProp.required ? `Required property "${name}" was added` : `Optional property "${name}" was added`,
|
|
172
|
+
suggestedFix: newProp.required ? `Add lens: addDefault('${name}', defaultValue)` : void 0
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
for (const [name, oldProp] of oldSchema.properties) {
|
|
177
|
+
const newProp = newSchema.properties.get(name);
|
|
178
|
+
if (!newProp) continue;
|
|
179
|
+
if (oldProp.type !== newProp.type) {
|
|
180
|
+
changes.push({
|
|
181
|
+
type: "modify",
|
|
182
|
+
property: name,
|
|
183
|
+
risk: "breaking",
|
|
184
|
+
description: `Property "${name}" changed type from "${oldProp.type}" to "${newProp.type}"`,
|
|
185
|
+
suggestedFix: `Add lens: transform('${name}', forwardFn, backwardFn)`
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
if (!oldProp.required && newProp.required) {
|
|
189
|
+
changes.push({
|
|
190
|
+
type: "modify",
|
|
191
|
+
property: name,
|
|
192
|
+
risk: "caution",
|
|
193
|
+
description: `Property "${name}" became required`,
|
|
194
|
+
suggestedFix: `Add lens: addDefault('${name}', defaultValue)`
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return changes;
|
|
199
|
+
}
|
|
200
|
+
function getSchemaCodeFixes(_typescript, _languageService, _fileName, _start, _end, errorCodes) {
|
|
201
|
+
const fixes = [];
|
|
202
|
+
if (!errorCodes.includes(90001) && !errorCodes.includes(90002)) {
|
|
203
|
+
return fixes;
|
|
204
|
+
}
|
|
205
|
+
return fixes;
|
|
206
|
+
}
|
|
207
|
+
var index_default = init;
|
|
208
|
+
export {
|
|
209
|
+
index_default as default,
|
|
210
|
+
diffSchemaProperties,
|
|
211
|
+
extractSchemaInfo,
|
|
212
|
+
isDefineSchemaCall
|
|
213
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@xnetjs/data",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/crs48/xNet"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"main": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"import": "./dist/index.js",
|
|
15
|
+
"types": "./dist/index.d.ts"
|
|
16
|
+
},
|
|
17
|
+
"./ts-plugin": {
|
|
18
|
+
"types": "./dist/ts-plugin/index.d.ts",
|
|
19
|
+
"require": "./dist/ts-plugin/index.cjs",
|
|
20
|
+
"import": "./dist/ts-plugin/index.js"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist",
|
|
25
|
+
"README.md",
|
|
26
|
+
"LICENSE"
|
|
27
|
+
],
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public",
|
|
30
|
+
"provenance": true
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"lib0": "^0.2.102",
|
|
34
|
+
"nanoid": "^5.1.6",
|
|
35
|
+
"y-protocols": "^1.0.6",
|
|
36
|
+
"yjs": "^13.6.24",
|
|
37
|
+
"@xnetjs/core": "0.0.2",
|
|
38
|
+
"@xnetjs/crypto": "0.0.2",
|
|
39
|
+
"@xnetjs/identity": "0.0.2",
|
|
40
|
+
"@xnetjs/sqlite": "0.0.2",
|
|
41
|
+
"@xnetjs/storage": "0.0.2",
|
|
42
|
+
"@xnetjs/sync": "0.0.2"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"tsup": "^8.0.0",
|
|
46
|
+
"typescript": "^5.4.0"
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsup src/index.ts --format esm --dts && tsup src/ts-plugin/index.ts --format cjs,esm --dts --outDir dist/ts-plugin",
|
|
50
|
+
"test": "vitest run",
|
|
51
|
+
"typecheck": "tsc --noEmit",
|
|
52
|
+
"clean": "rm -rf dist"
|
|
53
|
+
}
|
|
54
|
+
}
|