easyeda-mcp-pro 0.3.2 → 0.5.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.
Files changed (173) hide show
  1. package/README.md +369 -52
  2. package/dist/bom-quality/adapter.d.ts +90 -0
  3. package/dist/bom-quality/adapter.js +295 -0
  4. package/dist/bom-quality/adapter.js.map +1 -0
  5. package/dist/bom-quality/index.d.ts +10 -0
  6. package/dist/bom-quality/index.js +9 -0
  7. package/dist/bom-quality/index.js.map +1 -0
  8. package/dist/bom-quality/quality.d.ts +28 -0
  9. package/dist/bom-quality/quality.js +179 -0
  10. package/dist/bom-quality/quality.js.map +1 -0
  11. package/dist/bom-quality/types.d.ts +94 -0
  12. package/dist/bom-quality/types.js +12 -0
  13. package/dist/bom-quality/types.js.map +1 -0
  14. package/dist/bridge/manager.d.ts +41 -0
  15. package/dist/bridge/manager.js +334 -47
  16. package/dist/bridge/manager.js.map +1 -1
  17. package/dist/bridge/protocol.d.ts +48 -1
  18. package/dist/bridge/protocol.js +43 -1
  19. package/dist/bridge/protocol.js.map +1 -1
  20. package/dist/bridge/types.d.ts +6 -0
  21. package/dist/bridge/types.js +6 -0
  22. package/dist/bridge/types.js.map +1 -1
  23. package/dist/catalog/errors.d.ts +49 -0
  24. package/dist/catalog/errors.js +60 -0
  25. package/dist/catalog/errors.js.map +1 -0
  26. package/dist/catalog/index.d.ts +15 -0
  27. package/dist/catalog/index.js +17 -0
  28. package/dist/catalog/index.js.map +1 -0
  29. package/dist/catalog/schema.d.ts +268 -0
  30. package/dist/catalog/schema.js +245 -0
  31. package/dist/catalog/schema.js.map +1 -0
  32. package/dist/catalog/starter.d.ts +159 -0
  33. package/dist/catalog/starter.js +579 -0
  34. package/dist/catalog/starter.js.map +1 -0
  35. package/dist/catalog/validation.d.ts +48 -0
  36. package/dist/catalog/validation.js +263 -0
  37. package/dist/catalog/validation.js.map +1 -0
  38. package/dist/circuit/circuit-ir.d.ts +460 -0
  39. package/dist/circuit/circuit-ir.js +292 -0
  40. package/dist/circuit/circuit-ir.js.map +1 -0
  41. package/dist/circuit/compiler.d.ts +55 -0
  42. package/dist/circuit/compiler.js +197 -0
  43. package/dist/circuit/compiler.js.map +1 -0
  44. package/dist/circuit/design-intent.d.ts +94 -0
  45. package/dist/circuit/design-intent.js +118 -0
  46. package/dist/circuit/design-intent.js.map +1 -0
  47. package/dist/circuit/errors.d.ts +50 -0
  48. package/dist/circuit/errors.js +61 -0
  49. package/dist/circuit/errors.js.map +1 -0
  50. package/dist/circuit/index.d.ts +17 -0
  51. package/dist/circuit/index.js +18 -0
  52. package/dist/circuit/index.js.map +1 -0
  53. package/dist/circuit/types.d.ts +186 -0
  54. package/dist/circuit/types.js +123 -0
  55. package/dist/circuit/types.js.map +1 -0
  56. package/dist/cli/auto-setup.d.ts +5 -0
  57. package/dist/cli/auto-setup.js +355 -0
  58. package/dist/cli/auto-setup.js.map +1 -0
  59. package/dist/cli/client-definitions.d.ts +34 -0
  60. package/dist/cli/client-definitions.js +194 -0
  61. package/dist/cli/client-definitions.js.map +1 -0
  62. package/dist/cli/local-setup.d.ts +5 -1
  63. package/dist/cli/local-setup.js +40 -6
  64. package/dist/cli/local-setup.js.map +1 -1
  65. package/dist/config/env.d.ts +6 -1
  66. package/dist/config/env.js +93 -5
  67. package/dist/config/env.js.map +1 -1
  68. package/dist/config/profiles.js +4 -4
  69. package/dist/config/version.d.ts +1 -1
  70. package/dist/config/version.js +1 -1
  71. package/dist/export-manifest/errors.d.ts +55 -0
  72. package/dist/export-manifest/errors.js +69 -0
  73. package/dist/export-manifest/errors.js.map +1 -0
  74. package/dist/export-manifest/index.d.ts +10 -0
  75. package/dist/export-manifest/index.js +9 -0
  76. package/dist/export-manifest/index.js.map +1 -0
  77. package/dist/export-manifest/types.d.ts +170 -0
  78. package/dist/export-manifest/types.js +36 -0
  79. package/dist/export-manifest/types.js.map +1 -0
  80. package/dist/export-manifest/validation.d.ts +39 -0
  81. package/dist/export-manifest/validation.js +298 -0
  82. package/dist/export-manifest/validation.js.map +1 -0
  83. package/dist/index.js +20 -0
  84. package/dist/index.js.map +1 -1
  85. package/dist/net-validation/errors.d.ts +89 -0
  86. package/dist/net-validation/errors.js +69 -0
  87. package/dist/net-validation/errors.js.map +1 -0
  88. package/dist/net-validation/fixtures.d.ts +38 -0
  89. package/dist/net-validation/fixtures.js +215 -0
  90. package/dist/net-validation/fixtures.js.map +1 -0
  91. package/dist/net-validation/index.d.ts +10 -0
  92. package/dist/net-validation/index.js +9 -0
  93. package/dist/net-validation/index.js.map +1 -0
  94. package/dist/net-validation/schema.d.ts +118 -0
  95. package/dist/net-validation/schema.js +140 -0
  96. package/dist/net-validation/schema.js.map +1 -0
  97. package/dist/net-validation/validation.d.ts +45 -0
  98. package/dist/net-validation/validation.js +369 -0
  99. package/dist/net-validation/validation.js.map +1 -0
  100. package/dist/pcb-constraints/errors.d.ts +39 -0
  101. package/dist/pcb-constraints/errors.js +133 -0
  102. package/dist/pcb-constraints/errors.js.map +1 -0
  103. package/dist/pcb-constraints/index.d.ts +9 -0
  104. package/dist/pcb-constraints/index.js +9 -0
  105. package/dist/pcb-constraints/index.js.map +1 -0
  106. package/dist/pcb-constraints/types.d.ts +102 -0
  107. package/dist/pcb-constraints/types.js +7 -0
  108. package/dist/pcb-constraints/types.js.map +1 -0
  109. package/dist/pcb-constraints/validation.d.ts +70 -0
  110. package/dist/pcb-constraints/validation.js +309 -0
  111. package/dist/pcb-constraints/validation.js.map +1 -0
  112. package/dist/server/factory.js +2 -0
  113. package/dist/server/factory.js.map +1 -1
  114. package/dist/server/transports/http.d.ts +20 -1
  115. package/dist/server/transports/http.js +156 -34
  116. package/dist/server/transports/http.js.map +1 -1
  117. package/dist/storage/database.d.ts +25 -0
  118. package/dist/storage/database.js +126 -51
  119. package/dist/storage/database.js.map +1 -1
  120. package/dist/tools/{L0_diagnostics.d.ts → L0_diagnostics_api.d.ts} +2 -2
  121. package/dist/tools/L0_diagnostics_api.js +152 -0
  122. package/dist/tools/L0_diagnostics_api.js.map +1 -0
  123. package/dist/tools/L0_diagnostics_core.d.ts +6 -0
  124. package/dist/tools/{L0_diagnostics.js → L0_diagnostics_core.js} +50 -124
  125. package/dist/tools/L0_diagnostics_core.js.map +1 -0
  126. package/dist/tools/L1_board.js +20 -4
  127. package/dist/tools/L1_board.js.map +1 -1
  128. package/dist/tools/{L1_bom.d.ts → L1_bom_core.d.ts} +2 -2
  129. package/dist/tools/{L1_bom.js → L1_bom_core.js} +21 -101
  130. package/dist/tools/L1_bom_core.js.map +1 -0
  131. package/dist/tools/{L1_schematic.d.ts → L1_bom_sourcing.d.ts} +2 -2
  132. package/dist/tools/L1_bom_sourcing.js +265 -0
  133. package/dist/tools/L1_bom_sourcing.js.map +1 -0
  134. package/dist/tools/L1_drc_erc.js +15 -3
  135. package/dist/tools/L1_drc_erc.js.map +1 -1
  136. package/dist/tools/L1_export.js +20 -4
  137. package/dist/tools/L1_export.js.map +1 -1
  138. package/dist/tools/L1_pcb_constraints.d.ts +6 -0
  139. package/dist/tools/L1_pcb_constraints.js +234 -0
  140. package/dist/tools/L1_pcb_constraints.js.map +1 -0
  141. package/dist/tools/L1_pcb_write.js +26 -12
  142. package/dist/tools/L1_pcb_write.js.map +1 -1
  143. package/dist/tools/L1_schematic_read.d.ts +6 -0
  144. package/dist/tools/{L1_schematic.js → L1_schematic_read.js} +125 -190
  145. package/dist/tools/L1_schematic_read.js.map +1 -0
  146. package/dist/tools/L1_schematic_write.d.ts +6 -0
  147. package/dist/tools/L1_schematic_write.js +516 -0
  148. package/dist/tools/L1_schematic_write.js.map +1 -0
  149. package/dist/tools/register.js +15 -7
  150. package/dist/tools/register.js.map +1 -1
  151. package/dist/tools/registry.d.ts +41 -7
  152. package/dist/tools/registry.js +111 -12
  153. package/dist/tools/registry.js.map +1 -1
  154. package/dist/tools/types.d.ts +16 -0
  155. package/dist/utils/logger.d.ts +1 -1
  156. package/dist/utils/logger.js +1 -1
  157. package/dist/utils/logger.js.map +1 -1
  158. package/dist/vendors/base-http-client.d.ts +48 -0
  159. package/dist/vendors/base-http-client.js +75 -0
  160. package/dist/vendors/base-http-client.js.map +1 -0
  161. package/dist/vendors/digikey/client.js +10 -19
  162. package/dist/vendors/digikey/client.js.map +1 -1
  163. package/dist/vendors/jlcpcb/client.js +41 -70
  164. package/dist/vendors/jlcpcb/client.js.map +1 -1
  165. package/dist/vendors/lcsc/client.js +5 -18
  166. package/dist/vendors/lcsc/client.js.map +1 -1
  167. package/dist/vendors/mouser/client.js +4 -12
  168. package/dist/vendors/mouser/client.js.map +1 -1
  169. package/easyeda-bridge-extension.eext +0 -0
  170. package/package.json +41 -26
  171. package/dist/tools/L0_diagnostics.js.map +0 -1
  172. package/dist/tools/L1_bom.js.map +0 -1
  173. package/dist/tools/L1_schematic.js.map +0 -1
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Export manifest — error codes, structured issues, and factories.
3
+ *
4
+ * Follows the same pattern as `net-validation/errors.ts`:
5
+ * a const-object error code enum, a structured issue interface
6
+ * (re-exported from types.ts), and factory helpers.
7
+ *
8
+ * @module
9
+ */
10
+ // ── Error codes ─────────────────────────────────────────────────────────────
11
+ export const ExportManifestCode = {
12
+ // ── Completeness errors ────────────────────────────────────────────────
13
+ /** A required artifact file was not found in the export output. */
14
+ MISSING_REQUIRED_FILE: 'MISSING_REQUIRED_FILE',
15
+ /** An artifact file exists but has zero bytes. */
16
+ EMPTY_FILE: 'EMPTY_FILE',
17
+ /** An artifact is flagged as stale (outdated). */
18
+ STALE_FILE: 'STALE_FILE',
19
+ /** An artifact appears in the output but was not in the expected set. */
20
+ UNEXPECTED_FILE: 'UNEXPECTED_FILE',
21
+ // ── Integrity errors ───────────────────────────────────────────────────
22
+ /** Artifact checksum does not match the expected value. */
23
+ CHECKSUM_MISMATCH: 'CHECKSUM_MISMATCH',
24
+ /** Artifact's declared file type does not match its content/name. */
25
+ WRONG_FILE_TYPE: 'WRONG_FILE_TYPE',
26
+ // ── Metadata errors ────────────────────────────────────────────────────
27
+ /** Artifact is missing a human-readable purpose description. */
28
+ MISSING_PURPOSE: 'MISSING_PURPOSE',
29
+ /** Artifact is missing a generation timestamp. */
30
+ MISSING_GENERATED_TIMESTAMP: 'MISSING_GENERATED_TIMESTAMP',
31
+ /** Artifact is missing a source project reference. */
32
+ MISSING_SOURCE_PROJECT: 'MISSING_SOURCE_PROJECT',
33
+ // ── Schema errors ──────────────────────────────────────────────────────
34
+ /** Manifest version string is not valid semver. */
35
+ INVALID_MANIFEST_VERSION: 'INVALID_MANIFEST_VERSION',
36
+ // ── Internal ───────────────────────────────────────────────────────────
37
+ /** Validation could not be completed due to an internal error. */
38
+ MANIFEST_INTERNAL: 'MANIFEST_INTERNAL',
39
+ };
40
+ // ── Factory ─────────────────────────────────────────────────────────────────
41
+ /**
42
+ * Create a single export manifest issue.
43
+ */
44
+ export function manifestIssue(code, message, opts) {
45
+ return {
46
+ code,
47
+ message,
48
+ severity: opts?.severity ?? 'error',
49
+ path: opts?.path,
50
+ artifactPath: opts?.artifactPath,
51
+ artifactType: opts?.artifactType,
52
+ purpose: opts?.purpose,
53
+ remediationHint: opts?.remediationHint ?? '',
54
+ details: opts?.details,
55
+ };
56
+ }
57
+ /**
58
+ * Convenience: create an error-severity issue.
59
+ */
60
+ export function manifestError(code, message, opts) {
61
+ return manifestIssue(code, message, { ...opts, severity: 'error' });
62
+ }
63
+ /**
64
+ * Convenience: create a warning-severity issue.
65
+ */
66
+ export function manifestWarning(code, message, opts) {
67
+ return manifestIssue(code, message, { ...opts, severity: 'warning' });
68
+ }
69
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/export-manifest/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,+EAA+E;AAE/E,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,0EAA0E;IAE1E,mEAAmE;IACnE,qBAAqB,EAAE,uBAAuB;IAC9C,kDAAkD;IAClD,UAAU,EAAE,YAAY;IACxB,kDAAkD;IAClD,UAAU,EAAE,YAAY;IACxB,yEAAyE;IACzE,eAAe,EAAE,iBAAiB;IAElC,0EAA0E;IAE1E,2DAA2D;IAC3D,iBAAiB,EAAE,mBAAmB;IACtC,qEAAqE;IACrE,eAAe,EAAE,iBAAiB;IAElC,0EAA0E;IAE1E,gEAAgE;IAChE,eAAe,EAAE,iBAAiB;IAClC,kDAAkD;IAClD,2BAA2B,EAAE,6BAA6B;IAC1D,sDAAsD;IACtD,sBAAsB,EAAE,wBAAwB;IAEhD,0EAA0E;IAE1E,mDAAmD;IACnD,wBAAwB,EAAE,0BAA0B;IAEpD,0EAA0E;IAE1E,kEAAkE;IAClE,iBAAiB,EAAE,mBAAmB;CAC9B,CAAC;AAIX,+EAA+E;AAE/E;;GAEG;AACH,MAAM,UAAU,aAAa,CAC3B,IAAwB,EACxB,OAAe,EACf,IAQC;IAED,OAAO;QACL,IAAI;QACJ,OAAO;QACP,QAAQ,EAAE,IAAI,EAAE,QAAQ,IAAI,OAAO;QACnC,IAAI,EAAE,IAAI,EAAE,IAAI;QAChB,YAAY,EAAE,IAAI,EAAE,YAAY;QAChC,YAAY,EAAE,IAAI,EAAE,YAAY;QAChC,OAAO,EAAE,IAAI,EAAE,OAAO;QACtB,eAAe,EAAE,IAAI,EAAE,eAAe,IAAI,EAAE;QAC5C,OAAO,EAAE,IAAI,EAAE,OAAO;KACvB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAC3B,IAAwB,EACxB,OAAe,EACf,IAA4D;IAE5D,OAAO,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;AACtE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAC7B,IAAwB,EACxB,OAAe,EACf,IAA4D;IAE5D,OAAO,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;AACxE,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Export manifest — public API barrel export.
3
+ *
4
+ * @module
5
+ */
6
+ export { ArtifactType } from './types.js';
7
+ export type { ExportManifestEntry, ExpectedArtifact, ExportManifestInput, ExportManifestIssue, ExportManifestSummary, ExportManifestReport, } from './types.js';
8
+ export { ExportManifestCode, manifestIssue, manifestError, manifestWarning } from './errors.js';
9
+ export type { ExportManifestCode as ExportManifestCodeType } from './errors.js';
10
+ export { validateExportManifest } from './validation.js';
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Export manifest — public API barrel export.
3
+ *
4
+ * @module
5
+ */
6
+ export { ArtifactType } from './types.js';
7
+ export { ExportManifestCode, manifestIssue, manifestError, manifestWarning } from './errors.js';
8
+ export { validateExportManifest } from './validation.js';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/export-manifest/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAU1C,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGhG,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,170 @@
1
+ /**
2
+ * Export manifest — types for export artifact manifests and validation.
3
+ *
4
+ * Defines the schema for export manifests — structural metadata files
5
+ * that describe what was exported (artifacts), when, and by which tool,
6
+ * and enable subsequent validation of completeness and integrity.
7
+ *
8
+ * @module
9
+ */
10
+ /**
11
+ * Supported export artifact types.
12
+ *
13
+ * Maps to the file format enum used by EasyEDA Pro export tools and
14
+ * the golden fixture's `exportManifest.expectedFormats`.
15
+ */
16
+ export declare enum ArtifactType {
17
+ /** Gerber RS-274X (fabrication layers). */
18
+ Gerber = "gerber",
19
+ /** NC drill file (Excellon). */
20
+ Drill = "drill",
21
+ /** Bill of materials (CSV). */
22
+ Bom = "bom",
23
+ /** Pick-and-place / centroid file (CSV). */
24
+ Pnp = "pnp",
25
+ /** PDF export (schematic, board, or both). */
26
+ Pdf = "pdf",
27
+ /** Netlist (PADS / Allegro / Altium format). */
28
+ Netlist = "netlist",
29
+ /** Electrical rules check report. */
30
+ ErcReport = "erc-report",
31
+ /** Design rules check report. */
32
+ DrcReport = "drc-report"
33
+ }
34
+ /**
35
+ * A single artifact entry in an export manifest.
36
+ *
37
+ * Each entry describes one file produced by an export operation, including
38
+ * its origin, integrity metadata, and required/optional classification.
39
+ */
40
+ export interface ExportManifestEntry {
41
+ /** File name (e.g. "ESP32-S3-Board-F.Cu.gbr"). */
42
+ filename: string;
43
+ /** Relative path from the export root directory. */
44
+ relativePath?: string;
45
+ /** The type of exported file. */
46
+ fileType: ArtifactType;
47
+ /** Human-readable purpose (e.g. "Top copper layer"). */
48
+ purpose: string;
49
+ /** Source project identifier. */
50
+ sourceProject?: string;
51
+ /** Tool that generated this artifact (e.g. "easyeda-export-gerbers"). */
52
+ generatedByTool?: string;
53
+ /** ISO-8601 timestamp when this artifact was generated. */
54
+ timestamp?: string;
55
+ /** Hex-encoded SHA-256 or MD5 checksum. */
56
+ checksum?: string;
57
+ /** File size in bytes. */
58
+ fileSize?: number;
59
+ /** Whether this artifact is required for the export to be valid. */
60
+ required: boolean;
61
+ /** Whether this artifact is stale (outdated relative to source design). */
62
+ stale: boolean;
63
+ }
64
+ /**
65
+ * Expected artifact descriptor used to validate actual export output.
66
+ *
67
+ * Mirrors the golden fixture's `exportManifest.files[]` structure.
68
+ */
69
+ export interface ExpectedArtifact {
70
+ /** Expected file name pattern. */
71
+ filename: string;
72
+ /** Expected file type. */
73
+ fileType: ArtifactType;
74
+ /** Minimum acceptable file size in bytes. */
75
+ minSizeBytes?: number;
76
+ /** Whether this artifact is required (missing = validation error). */
77
+ required?: boolean;
78
+ }
79
+ /**
80
+ * Complete input to export manifest validation.
81
+ *
82
+ * Carries both the actual exported artifacts and an optional set of
83
+ * expectations to compare against.
84
+ */
85
+ export interface ExportManifestInput {
86
+ /** Manifest schema version (semver, e.g. "1.0.0"). */
87
+ version: string;
88
+ /** Source project identifier (EasyEDA project UUID). */
89
+ sourceProjectId: string;
90
+ /** Human-readable source project name. */
91
+ sourceProjectName?: string;
92
+ /** ISO-8601 timestamp of manifest generation. */
93
+ generatedAt: string;
94
+ /** Server / tool version that produced this manifest. */
95
+ serverVersion?: string;
96
+ /** EasyEDA / bridge metadata if available. */
97
+ bridgeMetadata?: Record<string, unknown>;
98
+ /** Artifacts produced by the export. */
99
+ artifacts: ExportManifestEntry[];
100
+ /** Expected artifacts for comparison-based validation. */
101
+ expectedArtifacts?: ExpectedArtifact[];
102
+ }
103
+ /**
104
+ * A single export manifest validation issue (error or warning).
105
+ *
106
+ * Mirrors the pattern from `net-validation/errors.ts` for consistency
107
+ * across validation modules.
108
+ */
109
+ export interface ExportManifestIssue {
110
+ /** Machine-readable error code. */
111
+ code: string;
112
+ /** Human-readable description of what is wrong. */
113
+ message: string;
114
+ /** Whether this issue blocks validation or is advisory. */
115
+ severity: 'error' | 'warning';
116
+ /** Dot-notation path to the offending field (e.g. "artifacts[2]"). */
117
+ path?: string;
118
+ /** Related artifact path for file-level issues. */
119
+ artifactPath?: string;
120
+ /** Related artifact type for type-specific issues. */
121
+ artifactType?: string;
122
+ /** Related purpose field for purpose-related issues. */
123
+ purpose?: string;
124
+ /** Actionable hint for the user. */
125
+ remediationHint: string;
126
+ /** Additional machine-readable context. */
127
+ details?: Record<string, unknown>;
128
+ }
129
+ /**
130
+ * Validation summary breakdown.
131
+ */
132
+ export interface ExportManifestSummary {
133
+ /** Total artifact count in the manifest. */
134
+ totalFiles: number;
135
+ /** Number of error-severity issues. */
136
+ errors: number;
137
+ /** Number of warning-severity issues. */
138
+ warnings: number;
139
+ /** Count of missing required files. */
140
+ missingRequired: number;
141
+ /** Count of empty files. */
142
+ emptyFiles: number;
143
+ /** Count of stale files. */
144
+ staleFiles: number;
145
+ /** Count of checksum mismatches. */
146
+ checksumMismatches: number;
147
+ /** Count of unexpected files (present but not expected). */
148
+ unexpectedFiles: number;
149
+ /** Count of wrong file type assignments. */
150
+ wrongFileTypes: number;
151
+ /** Count of artifacts missing a purpose description. */
152
+ missingPurposes: number;
153
+ /** Count of artifacts missing a generation timestamp. */
154
+ missingTimestamps: number;
155
+ /** Count of artifacts missing a source project reference. */
156
+ missingSourceProjects: number;
157
+ }
158
+ /**
159
+ * Complete export manifest validation report.
160
+ */
161
+ export interface ExportManifestReport {
162
+ /** True when there are zero errors (warnings are allowed). */
163
+ valid: boolean;
164
+ /** The manifest that was validated (as provided). */
165
+ manifest: ExportManifestInput;
166
+ /** All issues found during validation. */
167
+ issues: ExportManifestIssue[];
168
+ /** Aggregated summary counts. */
169
+ summary: ExportManifestSummary;
170
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Export manifest — types for export artifact manifests and validation.
3
+ *
4
+ * Defines the schema for export manifests — structural metadata files
5
+ * that describe what was exported (artifacts), when, and by which tool,
6
+ * and enable subsequent validation of completeness and integrity.
7
+ *
8
+ * @module
9
+ */
10
+ // ── Artifact type ───────────────────────────────────────────────────────────
11
+ /**
12
+ * Supported export artifact types.
13
+ *
14
+ * Maps to the file format enum used by EasyEDA Pro export tools and
15
+ * the golden fixture's `exportManifest.expectedFormats`.
16
+ */
17
+ export var ArtifactType;
18
+ (function (ArtifactType) {
19
+ /** Gerber RS-274X (fabrication layers). */
20
+ ArtifactType["Gerber"] = "gerber";
21
+ /** NC drill file (Excellon). */
22
+ ArtifactType["Drill"] = "drill";
23
+ /** Bill of materials (CSV). */
24
+ ArtifactType["Bom"] = "bom";
25
+ /** Pick-and-place / centroid file (CSV). */
26
+ ArtifactType["Pnp"] = "pnp";
27
+ /** PDF export (schematic, board, or both). */
28
+ ArtifactType["Pdf"] = "pdf";
29
+ /** Netlist (PADS / Allegro / Altium format). */
30
+ ArtifactType["Netlist"] = "netlist";
31
+ /** Electrical rules check report. */
32
+ ArtifactType["ErcReport"] = "erc-report";
33
+ /** Design rules check report. */
34
+ ArtifactType["DrcReport"] = "drc-report";
35
+ })(ArtifactType || (ArtifactType = {}));
36
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/export-manifest/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,+EAA+E;AAE/E;;;;;GAKG;AACH,MAAM,CAAN,IAAY,YAiBX;AAjBD,WAAY,YAAY;IACtB,2CAA2C;IAC3C,iCAAiB,CAAA;IACjB,gCAAgC;IAChC,+BAAe,CAAA;IACf,+BAA+B;IAC/B,2BAAW,CAAA;IACX,4CAA4C;IAC5C,2BAAW,CAAA;IACX,8CAA8C;IAC9C,2BAAW,CAAA;IACX,gDAAgD;IAChD,mCAAmB,CAAA;IACnB,qCAAqC;IACrC,wCAAwB,CAAA;IACxB,iCAAiC;IACjC,wCAAwB,CAAA;AAC1B,CAAC,EAjBW,YAAY,KAAZ,YAAY,QAiBvB"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Export manifest — validation rules and entry point.
3
+ *
4
+ * Implements 10 validation rules that operate on {@link ExportManifestInput}
5
+ * and produce structured {@link ExportManifestIssue}s.
6
+ *
7
+ * Rules:
8
+ * 1. Invalid manifest version — error if version is not valid semver
9
+ * 2. Missing source project — error if sourceProjectId is empty
10
+ * 3. Missing generated timestamp — error if generatedAt is empty
11
+ * 4. Missing purpose — warning for each artifact without purpose
12
+ * 5. Empty file — error for each artifact with fileSize === 0
13
+ * 6. Stale file — warning for each artifact flagged stale
14
+ * 7. Checksum mismatch — error when expected checksum != actual
15
+ * 8. Missing required file — error when expected artifact not found in output
16
+ * 9. Unexpected file — warning when output file not in expected set
17
+ * 10. Wrong file type — error when artifact type doesn't match expected
18
+ *
19
+ * @module
20
+ */
21
+ import type { ExportManifestInput, ExportManifestReport } from './types.js';
22
+ /**
23
+ * Run all export manifest validation rules against an input manifest.
24
+ *
25
+ * Orchestrates 10 rules:
26
+ * 1. Invalid manifest version — error if version is not valid semver
27
+ * 2. Missing source project — error if sourceProjectId is empty
28
+ * — warning per artifact without sourceProject
29
+ * 3. Missing generated timestamp— error if generatedAt is empty
30
+ * — warning per artifact without timestamp
31
+ * 4. Missing purpose — warning per artifact without purpose
32
+ * 5. Empty file — error per artifact with fileSize === 0
33
+ * 6. Stale file — warning per artifact with stale === true
34
+ * 7. Checksum mismatch — error when checksum "expected:actual" differs
35
+ * 8. Missing required file — error when expected artifact not in output
36
+ * 9. Unexpected file — warning when output file not in expected set
37
+ * 10. Wrong file type — error when artifact type !== expected type
38
+ */
39
+ export declare function validateExportManifest(input: ExportManifestInput): ExportManifestReport;
@@ -0,0 +1,298 @@
1
+ /**
2
+ * Export manifest — validation rules and entry point.
3
+ *
4
+ * Implements 10 validation rules that operate on {@link ExportManifestInput}
5
+ * and produce structured {@link ExportManifestIssue}s.
6
+ *
7
+ * Rules:
8
+ * 1. Invalid manifest version — error if version is not valid semver
9
+ * 2. Missing source project — error if sourceProjectId is empty
10
+ * 3. Missing generated timestamp — error if generatedAt is empty
11
+ * 4. Missing purpose — warning for each artifact without purpose
12
+ * 5. Empty file — error for each artifact with fileSize === 0
13
+ * 6. Stale file — warning for each artifact flagged stale
14
+ * 7. Checksum mismatch — error when expected checksum != actual
15
+ * 8. Missing required file — error when expected artifact not found in output
16
+ * 9. Unexpected file — warning when output file not in expected set
17
+ * 10. Wrong file type — error when artifact type doesn't match expected
18
+ *
19
+ * @module
20
+ */
21
+ import { ExportManifestCode, manifestError, manifestWarning } from './errors.js';
22
+ // ── Constants ───────────────────────────────────────────────────────────────
23
+ /** Simple semver regex: major.minor.patch with optional pre-release. */
24
+ const SEMVER_RE = /^\d+\.\d+\.\d+(?:-[a-zA-Z0-9.]+)?$/;
25
+ // ── Rule: invalid manifest version ──────────────────────────────────────────
26
+ function checkManifestVersion(input) {
27
+ const issues = [];
28
+ if (!input.version || !SEMVER_RE.test(input.version)) {
29
+ issues.push(manifestError(ExportManifestCode.INVALID_MANIFEST_VERSION, `Manifest version "${input.version ?? ''}" is not a valid semver string (expected e.g. "1.0.0")`, {
30
+ path: 'version',
31
+ remediationHint: 'Set the manifest version to a valid semver string like "1.0.0"',
32
+ details: { providedVersion: input.version },
33
+ }));
34
+ }
35
+ return issues;
36
+ }
37
+ // ── Rule: missing source project ────────────────────────────────────────────
38
+ function checkSourceProject(input) {
39
+ const issues = [];
40
+ if (!input.sourceProjectId || input.sourceProjectId.trim().length === 0) {
41
+ issues.push(manifestError(ExportManifestCode.MISSING_SOURCE_PROJECT, 'Manifest is missing a source project identifier', {
42
+ path: 'sourceProjectId',
43
+ remediationHint: 'Set sourceProjectId to the EasyEDA project UUID that produced this export',
44
+ }));
45
+ }
46
+ // Check each artifact for source project
47
+ for (let i = 0; i < input.artifacts.length; i++) {
48
+ const artifact = input.artifacts[i];
49
+ if (!artifact.sourceProject || artifact.sourceProject.trim().length === 0) {
50
+ issues.push(manifestWarning(ExportManifestCode.MISSING_SOURCE_PROJECT, `Artifact "${artifact.filename}" is missing a source project reference`, {
51
+ path: `artifacts[${i}]`,
52
+ artifactPath: artifact.filename,
53
+ remediationHint: 'Set sourceProject on each artifact to trace it back to its origin project',
54
+ }));
55
+ }
56
+ }
57
+ return issues;
58
+ }
59
+ // ── Rule: missing generated timestamp ────────────────────────────────────────
60
+ function checkGeneratedTimestamps(input) {
61
+ const issues = [];
62
+ // Check manifest-level timestamp
63
+ if (!input.generatedAt || input.generatedAt.trim().length === 0) {
64
+ issues.push(manifestError(ExportManifestCode.MISSING_GENERATED_TIMESTAMP, 'Manifest is missing a generation timestamp', {
65
+ path: 'generatedAt',
66
+ remediationHint: 'Set generatedAt to the ISO-8601 timestamp of manifest creation',
67
+ }));
68
+ }
69
+ // Check per-artifact timestamps
70
+ for (let i = 0; i < input.artifacts.length; i++) {
71
+ const artifact = input.artifacts[i];
72
+ if (!artifact.timestamp || artifact.timestamp.trim().length === 0) {
73
+ issues.push(manifestWarning(ExportManifestCode.MISSING_GENERATED_TIMESTAMP, `Artifact "${artifact.filename}" is missing a generation timestamp`, {
74
+ path: `artifacts[${i}]`,
75
+ artifactPath: artifact.filename,
76
+ remediationHint: 'Add an ISO-8601 timestamp to each artifact for staleness tracking',
77
+ }));
78
+ }
79
+ }
80
+ return issues;
81
+ }
82
+ // ── Rule: missing purpose ────────────────────────────────────────────────────
83
+ function checkMissingPurposes(input) {
84
+ const issues = [];
85
+ for (let i = 0; i < input.artifacts.length; i++) {
86
+ const artifact = input.artifacts[i];
87
+ if (!artifact.purpose || artifact.purpose.trim().length === 0) {
88
+ issues.push(manifestWarning(ExportManifestCode.MISSING_PURPOSE, `Artifact "${artifact.filename}" is missing a purpose description`, {
89
+ path: `artifacts[${i}]`,
90
+ artifactPath: artifact.filename,
91
+ remediationHint: 'Add a brief purpose description (e.g. "Top copper layer", "Schematic PDF")',
92
+ }));
93
+ }
94
+ }
95
+ return issues;
96
+ }
97
+ // ── Rule: empty files ────────────────────────────────────────────────────────
98
+ function checkEmptyFiles(input) {
99
+ const issues = [];
100
+ for (let i = 0; i < input.artifacts.length; i++) {
101
+ const artifact = input.artifacts[i];
102
+ if (artifact.fileSize !== undefined && artifact.fileSize === 0) {
103
+ issues.push(manifestError(ExportManifestCode.EMPTY_FILE, `Artifact "${artifact.filename}" is empty (0 bytes)`, {
104
+ path: `artifacts[${i}]`,
105
+ artifactPath: artifact.filename,
106
+ artifactType: artifact.fileType,
107
+ remediationHint: 'Re-export the artifact — the file may have been truncated or the export may have failed silently',
108
+ details: { fileSize: artifact.fileSize },
109
+ }));
110
+ }
111
+ }
112
+ return issues;
113
+ }
114
+ // ── Rule: stale files ────────────────────────────────────────────────────────
115
+ function checkStaleFiles(input) {
116
+ const issues = [];
117
+ for (let i = 0; i < input.artifacts.length; i++) {
118
+ const artifact = input.artifacts[i];
119
+ if (artifact.stale) {
120
+ issues.push(manifestWarning(ExportManifestCode.STALE_FILE, `Artifact "${artifact.filename}" is stale and may not reflect the current design`, {
121
+ path: `artifacts[${i}]`,
122
+ artifactPath: artifact.filename,
123
+ artifactType: artifact.fileType,
124
+ remediationHint: 'Re-export this artifact to ensure it reflects the latest design changes',
125
+ details: { stale: true },
126
+ }));
127
+ }
128
+ }
129
+ return issues;
130
+ }
131
+ // ── Rule: checksum mismatch ─────────────────────────────────────────────────
132
+ function checkChecksumMismatches(input) {
133
+ const issues = [];
134
+ for (let i = 0; i < input.artifacts.length; i++) {
135
+ const artifact = input.artifacts[i];
136
+ if (artifact.checksum !== undefined &&
137
+ artifact.checksum !== null &&
138
+ artifact.checksum.trim().length > 0 &&
139
+ artifact.checksum.includes(':') // format: "expected:actual" for comparison
140
+ ) {
141
+ const parts = artifact.checksum.split(':');
142
+ const expected = parts[0];
143
+ const actual = parts[1];
144
+ if (expected && actual && expected !== actual) {
145
+ issues.push(manifestError(ExportManifestCode.CHECKSUM_MISMATCH, `Checksum mismatch for "${artifact.filename}": expected ${expected}, got ${actual}`, {
146
+ path: `artifacts[${i}]`,
147
+ artifactPath: artifact.filename,
148
+ remediationHint: 'Re-export the file or verify the source file integrity',
149
+ details: {
150
+ expectedChecksum: expected,
151
+ actualChecksum: actual,
152
+ },
153
+ }));
154
+ }
155
+ }
156
+ }
157
+ return issues;
158
+ }
159
+ // ── Rule: missing required files ────────────────────────────────────────────
160
+ function checkMissingRequiredFiles(input) {
161
+ const issues = [];
162
+ if (!input.expectedArtifacts || input.expectedArtifacts.length === 0) {
163
+ return issues;
164
+ }
165
+ const exportedNames = new Set(input.artifacts.map((a) => a.filename));
166
+ for (let i = 0; i < input.expectedArtifacts.length; i++) {
167
+ const expected = input.expectedArtifacts[i];
168
+ const isRequired = expected.required ?? true; // default to required
169
+ if (isRequired && !exportedNames.has(expected.filename)) {
170
+ issues.push(manifestError(ExportManifestCode.MISSING_REQUIRED_FILE, `Required artifact "${expected.filename}" (${expected.fileType}) was not found in the export output`, {
171
+ path: `expectedArtifacts[${i}]`,
172
+ artifactType: expected.fileType,
173
+ remediationHint: 'Re-run the export to ensure all required files are generated',
174
+ details: {
175
+ expectedFilename: expected.filename,
176
+ expectedFileType: expected.fileType,
177
+ },
178
+ }));
179
+ }
180
+ }
181
+ return issues;
182
+ }
183
+ // ── Rule: unexpected files ──────────────────────────────────────────────────
184
+ function checkUnexpectedFiles(input) {
185
+ const issues = [];
186
+ if (!input.expectedArtifacts || input.expectedArtifacts.length === 0) {
187
+ return issues;
188
+ }
189
+ const expectedNames = new Set(input.expectedArtifacts.map((a) => a.filename));
190
+ for (let i = 0; i < input.artifacts.length; i++) {
191
+ const artifact = input.artifacts[i];
192
+ if (!expectedNames.has(artifact.filename)) {
193
+ issues.push(manifestWarning(ExportManifestCode.UNEXPECTED_FILE, `Unexpected artifact "${artifact.filename}" was found but is not listed in expected artifacts`, {
194
+ path: `artifacts[${i}]`,
195
+ artifactPath: artifact.filename,
196
+ artifactType: artifact.fileType,
197
+ remediationHint: 'Either add this file to the expected artifact list or verify it is intentionally included',
198
+ details: { filename: artifact.filename },
199
+ }));
200
+ }
201
+ }
202
+ return issues;
203
+ }
204
+ // ── Rule: wrong file type ───────────────────────────────────────────────────
205
+ function checkWrongFileTypes(input) {
206
+ const issues = [];
207
+ if (!input.expectedArtifacts || input.expectedArtifacts.length === 0) {
208
+ return issues;
209
+ }
210
+ // Build a map of expected file types by filename
211
+ const expectedTypeByFile = new Map();
212
+ for (const expected of input.expectedArtifacts) {
213
+ expectedTypeByFile.set(expected.filename, expected.fileType);
214
+ }
215
+ for (let i = 0; i < input.artifacts.length; i++) {
216
+ const artifact = input.artifacts[i];
217
+ const expectedType = expectedTypeByFile.get(artifact.filename);
218
+ if (expectedType && artifact.fileType !== expectedType) {
219
+ issues.push(manifestError(ExportManifestCode.WRONG_FILE_TYPE, `Artifact "${artifact.filename}" has type "${artifact.fileType}" but expected "${expectedType}"`, {
220
+ path: `artifacts[${i}]`,
221
+ artifactPath: artifact.filename,
222
+ artifactType: artifact.fileType,
223
+ remediationHint: 'Check the export configuration — the file may have been assigned the wrong format',
224
+ details: {
225
+ actualType: artifact.fileType,
226
+ expectedType,
227
+ },
228
+ }));
229
+ }
230
+ }
231
+ return issues;
232
+ }
233
+ const RULES = [
234
+ checkManifestVersion,
235
+ checkSourceProject,
236
+ checkGeneratedTimestamps,
237
+ checkMissingPurposes,
238
+ checkEmptyFiles,
239
+ checkStaleFiles,
240
+ checkChecksumMismatches,
241
+ checkMissingRequiredFiles,
242
+ checkUnexpectedFiles,
243
+ checkWrongFileTypes,
244
+ ];
245
+ // ── Summary builder ─────────────────────────────────────────────────────────
246
+ function buildSummary(issues, input) {
247
+ const errors = issues.filter((i) => i.severity === 'error').length;
248
+ const warnings = issues.filter((i) => i.severity === 'warning').length;
249
+ return {
250
+ totalFiles: input.artifacts.length,
251
+ errors,
252
+ warnings,
253
+ missingRequired: issues.filter((i) => i.code === ExportManifestCode.MISSING_REQUIRED_FILE)
254
+ .length,
255
+ emptyFiles: issues.filter((i) => i.code === ExportManifestCode.EMPTY_FILE).length,
256
+ staleFiles: issues.filter((i) => i.code === ExportManifestCode.STALE_FILE).length,
257
+ checksumMismatches: issues.filter((i) => i.code === ExportManifestCode.CHECKSUM_MISMATCH)
258
+ .length,
259
+ unexpectedFiles: issues.filter((i) => i.code === ExportManifestCode.UNEXPECTED_FILE).length,
260
+ wrongFileTypes: issues.filter((i) => i.code === ExportManifestCode.WRONG_FILE_TYPE).length,
261
+ missingPurposes: issues.filter((i) => i.code === ExportManifestCode.MISSING_PURPOSE).length,
262
+ missingTimestamps: issues.filter((i) => i.code === ExportManifestCode.MISSING_GENERATED_TIMESTAMP).length,
263
+ missingSourceProjects: issues.filter((i) => i.code === ExportManifestCode.MISSING_SOURCE_PROJECT).length,
264
+ };
265
+ }
266
+ // ── Main entry point ────────────────────────────────────────────────────────
267
+ /**
268
+ * Run all export manifest validation rules against an input manifest.
269
+ *
270
+ * Orchestrates 10 rules:
271
+ * 1. Invalid manifest version — error if version is not valid semver
272
+ * 2. Missing source project — error if sourceProjectId is empty
273
+ * — warning per artifact without sourceProject
274
+ * 3. Missing generated timestamp— error if generatedAt is empty
275
+ * — warning per artifact without timestamp
276
+ * 4. Missing purpose — warning per artifact without purpose
277
+ * 5. Empty file — error per artifact with fileSize === 0
278
+ * 6. Stale file — warning per artifact with stale === true
279
+ * 7. Checksum mismatch — error when checksum "expected:actual" differs
280
+ * 8. Missing required file — error when expected artifact not in output
281
+ * 9. Unexpected file — warning when output file not in expected set
282
+ * 10. Wrong file type — error when artifact type !== expected type
283
+ */
284
+ export function validateExportManifest(input) {
285
+ const issues = [];
286
+ for (const rule of RULES) {
287
+ const ruleIssues = rule(input);
288
+ issues.push(...ruleIssues);
289
+ }
290
+ const errors = issues.filter((i) => i.severity === 'error').length;
291
+ return {
292
+ valid: errors === 0,
293
+ manifest: input,
294
+ issues,
295
+ summary: buildSummary(issues, input),
296
+ };
297
+ }
298
+ //# sourceMappingURL=validation.js.map