@openfairygui/functions 0.2.0 → 0.3.0-alpha.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/README.md +7 -4
- package/dist/index.cjs +3 -123
- package/dist/index.d.cts +11 -50
- package/dist/index.d.ts +11 -50
- package/dist/index.js +3 -122
- package/dist/node.cjs +83 -16
- package/dist/node.d.cts +5 -2
- package/dist/node.d.ts +5 -2
- package/dist/node.js +83 -17
- package/dist/{publish-CykUJfVa.cjs → publish-C7qHwEiP.cjs} +23 -0
- package/dist/{publish-DXoaC1Nl.js → publish-CyBj2o7n.js} +19 -2
- package/dist/{restore-BQp01WY3.js → restore-DVo1hXpN.js} +1 -1
- package/dist/{restore-CEywQUHz.cjs → restore-LXbDQqmT.cjs} +1 -1
- package/dist/uam-transaction.cjs +1 -1
- package/dist/uam-transaction.js +1 -1
- package/dist/web.cjs +46 -1
- package/dist/web.d.cts +5 -2
- package/dist/web.d.ts +5 -2
- package/dist/web.js +47 -3
- package/package.json +2 -2
- package/src/adapters/node/validate.ts +93 -0
- package/src/adapters/web/raster.ts +4 -0
- package/src/adapters/web/validate.ts +60 -0
- package/src/index.ts +2 -5
- package/src/node.ts +1 -0
- package/src/uam-transaction.ts +1 -1
- package/src/validate.ts +34 -183
- package/src/web.ts +1 -0
package/src/node.ts
CHANGED
package/src/uam-transaction.ts
CHANGED
|
@@ -63,7 +63,7 @@ function compactDiagnostic(diagnostic: ApplyUamTransactionAppDiagnostic): ApplyU
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
function isTransactionSupportIssue(issue: UamValidationIssue | UamTransactionSupportIssue): issue is UamTransactionSupportIssue {
|
|
66
|
-
return '
|
|
66
|
+
return !('severity' in issue);
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
function mapTransactionDiagnostics(error: UamTransactionError): ApplyUamTransactionAppDiagnostic[] {
|
package/src/validate.ts
CHANGED
|
@@ -1,186 +1,37 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
severity: ValidationSeverity;
|
|
19
|
-
message: string;
|
|
20
|
-
/** Package name where the issue was found. */
|
|
21
|
-
packageName?: string;
|
|
22
|
-
/** Component name where the issue was found. */
|
|
23
|
-
componentName?: string;
|
|
24
|
-
/** Resource/object name related to the issue. */
|
|
25
|
-
resourceName?: string;
|
|
1
|
+
import {
|
|
2
|
+
createProjectValidationReport,
|
|
3
|
+
type ProjectDiagnostic,
|
|
4
|
+
type ProjectValidationReport,
|
|
5
|
+
type UamProject,
|
|
6
|
+
validateUamReferences,
|
|
7
|
+
validateUamProject,
|
|
8
|
+
validateUamSourceBytes,
|
|
9
|
+
} from '@openfairygui/core';
|
|
10
|
+
|
|
11
|
+
export interface ValidateProjectOptions {
|
|
12
|
+
/** Diagnostics collected while reading the source project. */
|
|
13
|
+
readDiagnostics?: readonly ProjectDiagnostic[];
|
|
14
|
+
/** Whether the reader and host completed every requested check. */
|
|
15
|
+
complete?: boolean;
|
|
16
|
+
/** Validate hydrated resource bytes in addition to the UAM graph. */
|
|
17
|
+
validateSources?: boolean;
|
|
26
18
|
}
|
|
27
19
|
|
|
28
|
-
/**
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Validates a FairyGUI project for common issues:
|
|
49
|
-
* - Missing resource IDs
|
|
50
|
-
* - Broken `ui://` references (src pointing to non-existent resources)
|
|
51
|
-
* - Empty components (no children)
|
|
52
|
-
* - Controllers with no pages
|
|
53
|
-
* - Duplicate resource IDs within a package
|
|
54
|
-
*
|
|
55
|
-
* The validation result is stored in `doc.getRoot().getExtras()._validation`.
|
|
56
|
-
*
|
|
57
|
-
* ```ts
|
|
58
|
-
* await doc.transform(validate({ throwOnError: true }));
|
|
59
|
-
* ```
|
|
60
|
-
*/
|
|
61
|
-
export function validate(_options: ValidateOptions = {}): Transform {
|
|
62
|
-
const options = { ...VALIDATE_DEFAULTS, ..._options };
|
|
63
|
-
|
|
64
|
-
return createTransform('validate', (doc: Document): void => {
|
|
65
|
-
const issues: ValidationIssue[] = [];
|
|
66
|
-
const root = doc.getRoot();
|
|
67
|
-
|
|
68
|
-
if (!root.getProjectId()) {
|
|
69
|
-
issues.push({
|
|
70
|
-
severity: ValidationSeverity.WARNING,
|
|
71
|
-
message: 'Project has no ID.',
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Build global resource ID map for cross-reference validation
|
|
76
|
-
const globalResources = new Map<string, string>(); // id → "pkg/name"
|
|
77
|
-
|
|
78
|
-
for (const pkg of root.listPackages()) {
|
|
79
|
-
if (!pkg.getId()) {
|
|
80
|
-
issues.push({
|
|
81
|
-
severity: ValidationSeverity.ERROR,
|
|
82
|
-
message: `Package "${pkg.getName()}" has no ID.`,
|
|
83
|
-
packageName: pkg.getName(),
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Check for duplicate resource IDs within the package
|
|
88
|
-
const idSet = new Set<string>();
|
|
89
|
-
for (const res of pkg.listResources()) {
|
|
90
|
-
const resId = res.getId();
|
|
91
|
-
if (!resId) {
|
|
92
|
-
issues.push({
|
|
93
|
-
severity: ValidationSeverity.WARNING,
|
|
94
|
-
message: `Resource "${res.getName()}" has no ID.`,
|
|
95
|
-
packageName: pkg.getName(),
|
|
96
|
-
resourceName: res.getName(),
|
|
97
|
-
});
|
|
98
|
-
continue;
|
|
99
|
-
}
|
|
100
|
-
if (idSet.has(resId)) {
|
|
101
|
-
issues.push({
|
|
102
|
-
severity: ValidationSeverity.ERROR,
|
|
103
|
-
message: `Duplicate resource ID "${resId}" in package "${pkg.getName()}".`,
|
|
104
|
-
packageName: pkg.getName(),
|
|
105
|
-
resourceName: res.getName(),
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
idSet.add(resId);
|
|
109
|
-
globalResources.set(`${pkg.getId()}${resId}`, `${pkg.getName()}/${res.getName()}`);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// Validate components
|
|
113
|
-
for (const comp of pkg.listComponents()) {
|
|
114
|
-
const children = comp.listChildren();
|
|
115
|
-
if (children.length === 0) {
|
|
116
|
-
issues.push({
|
|
117
|
-
severity: ValidationSeverity.INFO,
|
|
118
|
-
message: `Component "${comp.getName()}" has no children.`,
|
|
119
|
-
packageName: pkg.getName(),
|
|
120
|
-
componentName: comp.getName(),
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
for (const ctrl of comp.listControllers()) {
|
|
125
|
-
if (ctrl.listPages().length === 0) {
|
|
126
|
-
issues.push({
|
|
127
|
-
severity: ValidationSeverity.WARNING,
|
|
128
|
-
message: `Controller "${ctrl.getName()}" in "${comp.getName()}" has no pages.`,
|
|
129
|
-
packageName: pkg.getName(),
|
|
130
|
-
componentName: comp.getName(),
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Validate src references in display objects
|
|
136
|
-
for (const child of children) {
|
|
137
|
-
const src = (child as HasOptionalSrc).getSrc?.();
|
|
138
|
-
if (!src) continue;
|
|
139
|
-
|
|
140
|
-
// ui://[8-char-packageId][resourceId] format
|
|
141
|
-
if (src.startsWith('ui://')) {
|
|
142
|
-
const idPart = src.slice(5);
|
|
143
|
-
if (idPart.length > 8) {
|
|
144
|
-
const pkgId = idPart.slice(0, 8);
|
|
145
|
-
const resId = idPart.slice(8);
|
|
146
|
-
const key = `${pkgId}${resId}`;
|
|
147
|
-
if (!globalResources.has(key)) {
|
|
148
|
-
issues.push({
|
|
149
|
-
severity: ValidationSeverity.ERROR,
|
|
150
|
-
message: `Broken reference "${src}" in "${child.getName()}" (component "${comp.getName()}").`,
|
|
151
|
-
packageName: pkg.getName(),
|
|
152
|
-
componentName: comp.getName(),
|
|
153
|
-
resourceName: child.getName(),
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Store result
|
|
163
|
-
const errors = issues.filter((i) => i.severity === ValidationSeverity.ERROR);
|
|
164
|
-
const warnings = issues.filter((i) => i.severity === ValidationSeverity.WARNING);
|
|
165
|
-
const infos = issues.filter((i) => i.severity === ValidationSeverity.INFO);
|
|
166
|
-
|
|
167
|
-
const result: ValidationResult = {
|
|
168
|
-
ok: errors.length === 0,
|
|
169
|
-
errors,
|
|
170
|
-
warnings,
|
|
171
|
-
infos,
|
|
172
|
-
};
|
|
173
|
-
|
|
174
|
-
root.setExtras({ ...root.getExtras(), _validation: result });
|
|
175
|
-
|
|
176
|
-
// Log summary
|
|
177
|
-
const logger = doc.getLogger();
|
|
178
|
-
if (errors.length) logger.warn(`validate: ${errors.length} error(s) found.`);
|
|
179
|
-
if (warnings.length) logger.warn(`validate: ${warnings.length} warning(s) found.`);
|
|
180
|
-
logger.info(`validate: ${issues.length} issue(s) total.`);
|
|
181
|
-
|
|
182
|
-
if (options.throwOnError && errors.length > 0) {
|
|
183
|
-
throw new Error(`Validation failed with ${errors.length} error(s):\n${errors.map((e) => ` - ${e.message}`).join('\n')}`);
|
|
184
|
-
}
|
|
185
|
-
});
|
|
20
|
+
/** Validate one authoritative UAM snapshot without mutating it. */
|
|
21
|
+
export function validateProject(
|
|
22
|
+
project: UamProject,
|
|
23
|
+
options: ValidateProjectOptions = {},
|
|
24
|
+
): ProjectValidationReport {
|
|
25
|
+
const diagnostics = [
|
|
26
|
+
...(options.readDiagnostics ?? []),
|
|
27
|
+
...validateUamProject(project),
|
|
28
|
+
...validateUamReferences(project),
|
|
29
|
+
];
|
|
30
|
+
let complete = options.complete ?? true;
|
|
31
|
+
if (options.validateSources) {
|
|
32
|
+
const source = validateUamSourceBytes(project);
|
|
33
|
+
diagnostics.push(...source.diagnostics);
|
|
34
|
+
complete = complete && source.complete;
|
|
35
|
+
}
|
|
36
|
+
return createProjectValidationReport(diagnostics, complete);
|
|
186
37
|
}
|
package/src/web.ts
CHANGED