@openpkg-ts/spec 0.4.0 → 0.4.1

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/dist/index.d.ts CHANGED
@@ -163,17 +163,40 @@ declare function diffSpec(oldSpec: OpenPkg, newSpec: OpenPkg): SpecDiff;
163
163
  */
164
164
  declare function categorizeBreakingChanges(breaking: string[], oldSpec: OpenPkg, newSpec: OpenPkg, memberChanges?: MemberChangeInfo[]): CategorizedBreaking[];
165
165
  declare function normalize(spec: OpenPkg): OpenPkg;
166
+ /** Supported schema versions */
167
+ type SchemaVersion = "0.1.0" | "0.2.0" | "latest";
166
168
  type SpecError = {
167
169
  instancePath: string;
168
170
  message: string;
169
171
  keyword: string;
170
172
  };
171
- declare function validateSpec(spec: unknown): {
173
+ /**
174
+ * Validate a spec against a specific schema version.
175
+ *
176
+ * @param spec - The spec object to validate
177
+ * @param version - Schema version to validate against (default: 'latest')
178
+ * @returns Validation result
179
+ */
180
+ declare function validateSpec(spec: unknown, version?: SchemaVersion): {
172
181
  ok: true;
173
182
  } | {
174
183
  ok: false;
175
184
  errors: SpecError[];
176
185
  };
177
- declare function assertSpec(spec: unknown): asserts spec is OpenPkg;
178
- declare function getValidationErrors(spec: unknown): SpecError[];
186
+ /**
187
+ * Assert that a value is a valid OpenPkg spec.
188
+ * Throws an error with details if validation fails.
189
+ *
190
+ * @param spec - The value to validate
191
+ * @param version - Schema version to validate against (default: 'latest')
192
+ */
193
+ declare function assertSpec(spec: unknown, version?: SchemaVersion): asserts spec is OpenPkg;
194
+ /**
195
+ * Get validation errors for a spec.
196
+ *
197
+ * @param spec - The spec to validate
198
+ * @param version - Schema version to validate against (default: 'latest')
199
+ * @returns Array of validation errors (empty if valid)
200
+ */
201
+ declare function getValidationErrors(spec: unknown, version?: SchemaVersion): SpecError[];
179
202
  export { validateSpec, normalize, getValidationErrors, diffSpec, dereference, categorizeBreakingChanges, assertSpec, SpecVisibility, SpecTypeParameter, SpecTypeKind, SpecType, SpecTag, SpecSource, SpecSignatureReturn, SpecSignatureParameter, SpecSignature, SpecSchema, SpecMember, SpecExtension, SpecExportKind, SpecExport, SpecExample, SpecDocsMetadata, SpecDocSignal, SpecDocDrift, SpecDiff, SCHEMA_VERSION, SCHEMA_URL, OpenPkgMeta, OpenPkg, MemberChangeInfo, JSON_SCHEMA_DRAFT, CategorizedBreaking, BreakingSeverity };
package/dist/index.js CHANGED
@@ -159,7 +159,21 @@ function toMap(items) {
159
159
  }
160
160
  return map;
161
161
  }
162
- var DOC_KEYS = new Set(["description", "examples", "tags", "source", "rawComments"]);
162
+ var DOC_KEYS = new Set([
163
+ "description",
164
+ "examples",
165
+ "tags",
166
+ "rawComments",
167
+ "source",
168
+ "docs",
169
+ "displayName",
170
+ "slug",
171
+ "importPath",
172
+ "category",
173
+ "coverageScore",
174
+ "missing",
175
+ "drift"
176
+ ]);
163
177
  function isDocOnlyChange(a, b) {
164
178
  const structuralA = normalizeForComparison(removeDocFields(a));
165
179
  const structuralB = normalizeForComparison(removeDocFields(b));
@@ -483,7 +497,16 @@ var openpkg_schema_default = {
483
497
  kind: {
484
498
  type: "string",
485
499
  description: "Kind of export",
486
- enum: ["function", "class", "variable", "interface", "type", "enum", "namespace", "external"]
500
+ enum: [
501
+ "function",
502
+ "class",
503
+ "variable",
504
+ "interface",
505
+ "type",
506
+ "enum",
507
+ "namespace",
508
+ "external"
509
+ ]
487
510
  },
488
511
  description: {
489
512
  type: "string",
@@ -724,8 +747,315 @@ var openpkg_schema_default = {
724
747
  }
725
748
  }
726
749
  };
750
+ // schemas/v0.1.0/openpkg.schema.json
751
+ var openpkg_schema_default2 = {
752
+ $schema: "https://json-schema.org/draft/2020-12/schema",
753
+ $id: "https://unpkg.com/@openpkg-ts/spec/schemas/v0.1.0/openpkg.schema.json",
754
+ title: "OpenPkg Specification",
755
+ description: "Schema for OpenPkg specification files",
756
+ type: "object",
757
+ required: ["openpkg", "meta", "exports"],
758
+ properties: {
759
+ $schema: {
760
+ type: "string",
761
+ description: "Reference to the OpenPkg schema version",
762
+ pattern: "^(https://raw\\.githubusercontent\\.com/ryanwaits/openpkg/main/schemas/v[0-9]+\\.[0-9]+\\.[0-9]+/openpkg\\.schema\\.json|https://unpkg\\.com/@openpkg-ts/spec/schemas/v[0-9]+\\.[0-9]+\\.[0-9]+/openpkg\\.schema\\.json)$"
763
+ },
764
+ openpkg: {
765
+ type: "string",
766
+ description: "OpenPkg specification version",
767
+ pattern: "^[0-9]+\\.[0-9]+\\.[0-9]+$",
768
+ const: "0.1.0"
769
+ },
770
+ meta: {
771
+ type: "object",
772
+ description: "Package metadata",
773
+ required: ["name"],
774
+ properties: {
775
+ name: {
776
+ type: "string",
777
+ description: "Package name"
778
+ },
779
+ version: {
780
+ type: "string",
781
+ description: "Package version"
782
+ },
783
+ description: {
784
+ type: "string",
785
+ description: "Package description"
786
+ },
787
+ license: {
788
+ type: "string",
789
+ description: "Package license"
790
+ },
791
+ repository: {
792
+ type: "string",
793
+ description: "Repository URL"
794
+ },
795
+ ecosystem: {
796
+ type: "string",
797
+ description: "Package ecosystem"
798
+ }
799
+ }
800
+ },
801
+ exports: {
802
+ type: "array",
803
+ description: "List of exported items",
804
+ items: {
805
+ $ref: "#/$defs/export"
806
+ }
807
+ },
808
+ types: {
809
+ type: "array",
810
+ description: "List of type definitions",
811
+ items: {
812
+ $ref: "#/$defs/typeDef"
813
+ }
814
+ }
815
+ },
816
+ $defs: {
817
+ export: {
818
+ type: "object",
819
+ required: ["id", "name", "kind"],
820
+ properties: {
821
+ id: {
822
+ type: "string",
823
+ description: "Unique identifier for the export"
824
+ },
825
+ name: {
826
+ type: "string",
827
+ description: "Export name"
828
+ },
829
+ slug: {
830
+ type: "string",
831
+ description: "Stable slug for linking"
832
+ },
833
+ displayName: {
834
+ type: "string",
835
+ description: "UI-friendly label"
836
+ },
837
+ category: {
838
+ type: "string",
839
+ description: "Grouping hint for navigation"
840
+ },
841
+ importPath: {
842
+ type: "string",
843
+ description: "Recommended import path"
844
+ },
845
+ kind: {
846
+ type: "string",
847
+ description: "Kind of export",
848
+ enum: ["function", "class", "variable", "interface", "type", "enum"]
849
+ },
850
+ description: {
851
+ type: "string",
852
+ description: "JSDoc/TSDoc description"
853
+ },
854
+ examples: {
855
+ type: "array",
856
+ description: "Usage examples from documentation",
857
+ items: {
858
+ type: "string"
859
+ }
860
+ },
861
+ signatures: {
862
+ type: "array",
863
+ description: "Function/method signatures",
864
+ items: {
865
+ $ref: "#/$defs/signature"
866
+ }
867
+ },
868
+ type: {
869
+ description: "Type reference or inline schema for variables",
870
+ oneOf: [{ type: "string" }, { $ref: "#/$defs/schema" }]
871
+ },
872
+ members: {
873
+ type: "array",
874
+ description: "Class/interface/enum members",
875
+ items: { type: "object" }
876
+ },
877
+ tags: {
878
+ type: "array",
879
+ description: "JSDoc/TSDoc tags",
880
+ items: {
881
+ type: "object",
882
+ required: ["name", "text"],
883
+ properties: {
884
+ name: { type: "string" },
885
+ text: { type: "string" }
886
+ },
887
+ additionalProperties: false
888
+ }
889
+ },
890
+ source: {
891
+ $ref: "#/$defs/sourceLocation"
892
+ }
893
+ }
894
+ },
895
+ typeDef: {
896
+ type: "object",
897
+ required: ["id", "name", "kind"],
898
+ properties: {
899
+ id: {
900
+ type: "string",
901
+ description: "Unique identifier for the type"
902
+ },
903
+ name: {
904
+ type: "string",
905
+ description: "Type name"
906
+ },
907
+ slug: {
908
+ type: "string",
909
+ description: "Stable slug for linking"
910
+ },
911
+ displayName: {
912
+ type: "string",
913
+ description: "UI-friendly label"
914
+ },
915
+ category: {
916
+ type: "string",
917
+ description: "Grouping hint for navigation"
918
+ },
919
+ importPath: {
920
+ type: "string",
921
+ description: "Recommended import path"
922
+ },
923
+ kind: {
924
+ type: "string",
925
+ description: "Kind of type definition",
926
+ enum: ["interface", "type", "enum", "class"]
927
+ },
928
+ description: {
929
+ type: "string",
930
+ description: "JSDoc/TSDoc description"
931
+ },
932
+ schema: {
933
+ $ref: "#/$defs/schema"
934
+ },
935
+ type: {
936
+ type: "string",
937
+ description: "Type expression for type aliases"
938
+ },
939
+ members: {
940
+ type: "array",
941
+ description: "Members for classes/interfaces/enums",
942
+ items: { type: "object" }
943
+ },
944
+ tags: {
945
+ type: "array",
946
+ description: "JSDoc/TSDoc tags",
947
+ items: {
948
+ type: "object",
949
+ required: ["name", "text"],
950
+ properties: {
951
+ name: { type: "string" },
952
+ text: { type: "string" }
953
+ },
954
+ additionalProperties: false
955
+ }
956
+ },
957
+ source: {
958
+ $ref: "#/$defs/sourceLocation"
959
+ }
960
+ }
961
+ },
962
+ signature: {
963
+ type: "object",
964
+ properties: {
965
+ parameters: {
966
+ type: "array",
967
+ items: {
968
+ $ref: "#/$defs/parameter"
969
+ }
970
+ },
971
+ returns: {
972
+ $ref: "#/$defs/returns"
973
+ },
974
+ description: {
975
+ type: "string",
976
+ description: "Signature-level description"
977
+ }
978
+ }
979
+ },
980
+ parameter: {
981
+ type: "object",
982
+ required: ["name", "required"],
983
+ properties: {
984
+ name: {
985
+ type: "string",
986
+ description: "Parameter name"
987
+ },
988
+ required: {
989
+ type: "boolean",
990
+ description: "Whether the parameter is required"
991
+ },
992
+ schema: {
993
+ $ref: "#/$defs/schema"
994
+ }
995
+ }
996
+ },
997
+ returns: {
998
+ type: "object",
999
+ properties: {
1000
+ schema: {
1001
+ $ref: "#/$defs/schema"
1002
+ },
1003
+ description: {
1004
+ type: "string",
1005
+ description: "Return value description"
1006
+ }
1007
+ }
1008
+ },
1009
+ schema: {
1010
+ anyOf: [
1011
+ {
1012
+ type: "boolean"
1013
+ },
1014
+ {
1015
+ type: "object",
1016
+ properties: {
1017
+ $ref: {
1018
+ type: "string",
1019
+ description: "Reference to another type",
1020
+ pattern: "^#/types/[A-Za-z0-9_.-]+$"
1021
+ }
1022
+ },
1023
+ required: ["$ref"],
1024
+ additionalProperties: false
1025
+ },
1026
+ {
1027
+ type: "object",
1028
+ not: {
1029
+ required: ["$ref"]
1030
+ },
1031
+ additionalProperties: true
1032
+ }
1033
+ ]
1034
+ },
1035
+ sourceLocation: {
1036
+ type: "object",
1037
+ required: ["file", "line"],
1038
+ properties: {
1039
+ file: {
1040
+ type: "string",
1041
+ description: "Source file path"
1042
+ },
1043
+ line: {
1044
+ type: "integer",
1045
+ description: "Line number in source file",
1046
+ minimum: 1
1047
+ }
1048
+ }
1049
+ }
1050
+ }
1051
+ };
727
1052
 
728
1053
  // src/validate.ts
1054
+ var LATEST_VERSION = "0.2.0";
1055
+ var schemas = {
1056
+ "0.1.0": openpkg_schema_default2,
1057
+ "0.2.0": openpkg_schema_default
1058
+ };
729
1059
  var ajv = new Ajv({
730
1060
  strict: false,
731
1061
  allErrors: true,
@@ -733,8 +1063,23 @@ var ajv = new Ajv({
733
1063
  $data: true
734
1064
  });
735
1065
  addFormats(ajv);
736
- var validate = ajv.compile(openpkg_schema_default);
737
- function validateSpec(spec) {
1066
+ var validatorCache = new Map;
1067
+ function getValidator(version = "latest") {
1068
+ const resolvedVersion = version === "latest" ? LATEST_VERSION : version;
1069
+ let validator = validatorCache.get(resolvedVersion);
1070
+ if (validator) {
1071
+ return validator;
1072
+ }
1073
+ const schema = schemas[resolvedVersion];
1074
+ if (!schema) {
1075
+ throw new Error(`Unknown schema version: ${resolvedVersion}. Available: ${Object.keys(schemas).join(", ")}`);
1076
+ }
1077
+ validator = ajv.compile(schema);
1078
+ validatorCache.set(resolvedVersion, validator);
1079
+ return validator;
1080
+ }
1081
+ function validateSpec(spec, version = "latest") {
1082
+ const validate = getValidator(version);
738
1083
  const ok = validate(spec);
739
1084
  if (ok) {
740
1085
  return { ok: true };
@@ -749,8 +1094,8 @@ function validateSpec(spec) {
749
1094
  errors
750
1095
  };
751
1096
  }
752
- function assertSpec(spec) {
753
- const result = validateSpec(spec);
1097
+ function assertSpec(spec, version = "latest") {
1098
+ const result = validateSpec(spec, version);
754
1099
  if (!result.ok) {
755
1100
  const details = result.errors.map((error) => `- ${error.instancePath || "/"} ${error.message}`).join(`
756
1101
  `);
@@ -758,8 +1103,8 @@ function assertSpec(spec) {
758
1103
  ${details}`);
759
1104
  }
760
1105
  }
761
- function getValidationErrors(spec) {
762
- const result = validateSpec(spec);
1106
+ function getValidationErrors(spec, version = "latest") {
1107
+ const result = validateSpec(spec, version);
763
1108
  return result.ok ? [] : result.errors;
764
1109
  }
765
1110
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openpkg-ts/spec",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Shared schema, validation, and diff utilities for OpenPkg specs",
5
5
  "keywords": [
6
6
  "openpkg",
@@ -173,7 +173,16 @@
173
173
  "kind": {
174
174
  "type": "string",
175
175
  "description": "Kind of export",
176
- "enum": ["function", "class", "variable", "interface", "type", "enum", "namespace", "external"]
176
+ "enum": [
177
+ "function",
178
+ "class",
179
+ "variable",
180
+ "interface",
181
+ "type",
182
+ "enum",
183
+ "namespace",
184
+ "external"
185
+ ]
177
186
  },
178
187
  "description": {
179
188
  "type": "string",