@figulus/validator-core 0.5.0-alpha-dev-01 → 0.5.0-alpha-dev-03

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 (84) hide show
  1. package/dist/changed-file.d.ts +30 -0
  2. package/dist/changed-file.d.ts.map +1 -0
  3. package/dist/changed-file.js +131 -0
  4. package/dist/changed-file.js.map +1 -0
  5. package/dist/index.d.ts +4 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +3 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/lib/check-push-limit.d.ts +5 -0
  10. package/dist/lib/check-push-limit.d.ts.map +1 -0
  11. package/dist/lib/check-push-limit.js +61 -0
  12. package/dist/lib/check-push-limit.js.map +1 -0
  13. package/dist/lib/git-head.d.ts +5 -0
  14. package/dist/lib/git-head.d.ts.map +1 -0
  15. package/dist/lib/git-head.js +20 -0
  16. package/dist/lib/git-head.js.map +1 -0
  17. package/dist/lib/namespace.d.ts +5 -0
  18. package/dist/lib/namespace.d.ts.map +1 -0
  19. package/dist/lib/namespace.js +10 -0
  20. package/dist/lib/namespace.js.map +1 -0
  21. package/dist/lib/parse.d.ts +7 -0
  22. package/dist/lib/parse.d.ts.map +1 -0
  23. package/dist/lib/parse.js +29 -0
  24. package/dist/lib/parse.js.map +1 -0
  25. package/dist/lib/permissions.d.ts +4 -0
  26. package/dist/lib/permissions.d.ts.map +1 -0
  27. package/dist/lib/permissions.js +9 -0
  28. package/dist/lib/permissions.js.map +1 -0
  29. package/dist/lib/validate-blob-references.d.ts +5 -0
  30. package/dist/lib/validate-blob-references.d.ts.map +1 -0
  31. package/dist/lib/validate-blob-references.js +21 -0
  32. package/dist/lib/validate-blob-references.js.map +1 -0
  33. package/dist/lib/validate-file/blob.d.ts +4 -0
  34. package/dist/lib/validate-file/blob.d.ts.map +1 -0
  35. package/dist/lib/validate-file/blob.js +57 -0
  36. package/dist/lib/validate-file/blob.js.map +1 -0
  37. package/dist/lib/validate-file/entity.d.ts +4 -0
  38. package/dist/lib/validate-file/entity.d.ts.map +1 -0
  39. package/dist/lib/validate-file/entity.js +74 -0
  40. package/dist/lib/validate-file/entity.js.map +1 -0
  41. package/dist/lib/validate-file/namespace-metadata.d.ts +4 -0
  42. package/dist/lib/validate-file/namespace-metadata.d.ts.map +1 -0
  43. package/dist/lib/validate-file/namespace-metadata.js +128 -0
  44. package/dist/lib/validate-file/namespace-metadata.js.map +1 -0
  45. package/dist/lib/validate-file/namespace-overrides.d.ts +4 -0
  46. package/dist/lib/validate-file/namespace-overrides.d.ts.map +1 -0
  47. package/dist/lib/validate-file/namespace-overrides.js +47 -0
  48. package/dist/lib/validate-file/namespace-overrides.js.map +1 -0
  49. package/dist/lib/validate-ownership-transfer.d.ts +3 -0
  50. package/dist/lib/validate-ownership-transfer.d.ts.map +1 -0
  51. package/dist/lib/validate-ownership-transfer.js +13 -0
  52. package/dist/lib/validate-ownership-transfer.js.map +1 -0
  53. package/dist/lib/validate-push-limit-constraints.d.ts +19 -0
  54. package/dist/lib/validate-push-limit-constraints.d.ts.map +1 -0
  55. package/dist/lib/validate-push-limit-constraints.js +14 -0
  56. package/dist/lib/validate-push-limit-constraints.js.map +1 -0
  57. package/dist/pr.d.ts +13 -0
  58. package/dist/pr.d.ts.map +1 -0
  59. package/dist/pr.js +80 -0
  60. package/dist/pr.js.map +1 -0
  61. package/dist/registry-validator.d.ts +39 -0
  62. package/dist/registry-validator.d.ts.map +1 -0
  63. package/dist/registry-validator.js +19 -0
  64. package/dist/registry-validator.js.map +1 -0
  65. package/dist/settings.d.ts +39 -0
  66. package/dist/settings.d.ts.map +1 -0
  67. package/dist/settings.js +56 -0
  68. package/dist/settings.js.map +1 -0
  69. package/dist/types.d.ts +20 -0
  70. package/dist/types.d.ts.map +1 -0
  71. package/dist/types.js +2 -0
  72. package/dist/types.js.map +1 -0
  73. package/dist/validation-result.d.ts +39 -0
  74. package/dist/validation-result.d.ts.map +1 -0
  75. package/dist/validation-result.js +44 -0
  76. package/dist/validation-result.js.map +1 -0
  77. package/package.json +2 -2
  78. package/src/changed-file.ts +3 -3
  79. package/src/lib/check-push-limit.ts +7 -7
  80. package/src/lib/git-head.ts +5 -5
  81. package/src/lib/validate-file/entity.ts +6 -6
  82. package/src/lib/validate-file/namespace-metadata.ts +2 -2
  83. package/src/pr.ts +2 -2
  84. package/src/registry-validator.ts +7 -7
@@ -0,0 +1,30 @@
1
+ import z from "zod";
2
+ import { PR } from "./pr.js";
3
+ import { FileValidationResult, SchemaObject } from "./types.js";
4
+ declare const fileTypeEntitySchema: z.ZodEnum<{
5
+ spec: "spec";
6
+ stack: "stack";
7
+ parser: "parser";
8
+ }>;
9
+ export type FileTypeEntity = z.infer<typeof fileTypeEntitySchema>;
10
+ export declare function getExtensionFromFileTypeEntity(entityType: FileTypeEntity): string;
11
+ export declare function getSchemaFromFileTypeEntity(entityType: FileTypeEntity): SchemaObject;
12
+ export declare function getFileTypeEntityFromExtension(extension: string): FileTypeEntity | null;
13
+ declare const fileTypeNamespaceOverridesSchema: z.ZodEnum<{
14
+ verified: "verified";
15
+ limits: "limits";
16
+ }>;
17
+ export type FileTypeNamespaceOverrides = z.infer<typeof fileTypeNamespaceOverridesSchema>;
18
+ export declare function getSchemaFromFileTypeNamespaceOverrides(overridesFileType: FileTypeNamespaceOverrides): SchemaObject;
19
+ type FileType = FileTypeEntity | "blob" | "namespace" | FileTypeNamespaceOverrides;
20
+ export declare class ChangedFile {
21
+ path: string;
22
+ pr: PR;
23
+ constructor(path: string, pr: PR);
24
+ getFileType(): FileType | null;
25
+ getNamespace(type: FileTypeEntity | "namespace"): string;
26
+ parseJson(): any;
27
+ validate(): Promise<FileValidationResult>;
28
+ }
29
+ export {};
30
+ //# sourceMappingURL=changed-file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"changed-file.d.ts","sourceRoot":"","sources":["../src/changed-file.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,KAAK,CAAC;AAMpB,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAQ7B,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAWhE,QAAA,MAAM,oBAAoB;;;;EAAsC,CAAC;AACjE,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AA0BlE,wBAAgB,8BAA8B,CAC5C,UAAU,EAAE,cAAc,GACzB,MAAM,CAER;AAED,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,cAAc,GACzB,YAAY,CAEd;AAED,wBAAgB,8BAA8B,CAC5C,SAAS,EAAE,MAAM,GAChB,cAAc,GAAG,IAAI,CAKvB;AAMD,QAAA,MAAM,gCAAgC;;;EAAiC,CAAC;AACxE,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAC9C,OAAO,gCAAgC,CACxC,CAAC;AAeF,wBAAgB,uCAAuC,CACrD,iBAAiB,EAAE,0BAA0B,GAC5C,YAAY,CAEd;AAMD,KAAK,QAAQ,GACT,cAAc,GACd,MAAM,GACN,WAAW,GACX,0BAA0B,CAAC;AAM/B,qBAAa,WAAW;IAEb,IAAI,EAAE,MAAM;IACZ,EAAE,EAAE,EAAE;gBADN,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,EAAE;IAGR,WAAW,IAAI,QAAQ,GAAG,IAAI;IAa9B,YAAY,CAAC,IAAI,EAAE,cAAc,GAAG,WAAW,GAAG,MAAM;IAMxD,SAAS,IAAI,GAAG;IAUV,QAAQ,IAAI,OAAO,CAAC,oBAAoB,CAAC;CAwCvD"}
@@ -0,0 +1,131 @@
1
+ import z from "zod";
2
+ import { parseJSON } from "./lib/parse.js";
3
+ import { validateBlob } from "./lib/validate-file/blob.js";
4
+ import { validateEntity } from "./lib/validate-file/entity.js";
5
+ import { validateNamespaceMetadata } from "./lib/validate-file/namespace-metadata.js";
6
+ import { validateNamespaceOverrides } from "./lib/validate-file/namespace-overrides.js";
7
+ import { figParserMetadataSchema, figSpecMetadataSchema, figStackMetadataSchema, namespaceVerificationsSchema, pushLimitOverridesSchema, } from "@figulus/schema/registry";
8
+ import { ERROR_CODES, createError, } from "./validation-result.js";
9
+ //
10
+ // Entity metadata files
11
+ //
12
+ const fileTypeEntitySchema = z.enum(["spec", "stack", "parser"]);
13
+ const entityFileMap = {
14
+ spec: {
15
+ id: "spec",
16
+ metadataSchema: figSpecMetadataSchema,
17
+ extension: "figspec",
18
+ },
19
+ stack: {
20
+ id: "stack",
21
+ metadataSchema: figStackMetadataSchema,
22
+ extension: "figstack",
23
+ },
24
+ parser: {
25
+ id: "parser",
26
+ metadataSchema: figParserMetadataSchema,
27
+ extension: "js",
28
+ },
29
+ };
30
+ export function getExtensionFromFileTypeEntity(entityType) {
31
+ return entityFileMap[entityType].extension;
32
+ }
33
+ export function getSchemaFromFileTypeEntity(entityType) {
34
+ return entityFileMap[entityType].metadataSchema;
35
+ }
36
+ export function getFileTypeEntityFromExtension(extension) {
37
+ return (Object.values(entityFileMap).find((e) => e.extension === extension)?.id ||
38
+ null);
39
+ }
40
+ //
41
+ // Namespace overrides files
42
+ //
43
+ const fileTypeNamespaceOverridesSchema = z.enum(["verified", "limits"]);
44
+ const namespaceOverridesFileMap = {
45
+ verified: {
46
+ schema: namespaceVerificationsSchema,
47
+ },
48
+ limits: {
49
+ schema: pushLimitOverridesSchema,
50
+ },
51
+ };
52
+ export function getSchemaFromFileTypeNamespaceOverrides(overridesFileType) {
53
+ return namespaceOverridesFileMap[overridesFileType].schema;
54
+ }
55
+ //
56
+ // Main ChangedFile class
57
+ //
58
+ export class ChangedFile {
59
+ path;
60
+ pr;
61
+ constructor(path, pr) {
62
+ this.path = path;
63
+ this.pr = pr;
64
+ }
65
+ getFileType() {
66
+ if (this.path.startsWith("specs/"))
67
+ return "spec";
68
+ if (this.path.startsWith("stacks/"))
69
+ return "stack";
70
+ if (this.path.startsWith("parsers/"))
71
+ return "parser";
72
+ if (this.path.startsWith("blobs/"))
73
+ return "blob";
74
+ if (this.path.startsWith("namespaces/") && this.path.endsWith(".json")) {
75
+ if (this.path === "namespaces/verified.json")
76
+ return "verified";
77
+ if (this.path === "namespaces/push-limit-overrides.json")
78
+ return "limits";
79
+ return "namespace";
80
+ }
81
+ return null;
82
+ }
83
+ getNamespace(type) {
84
+ const base = this.pr.registry.helpers.fs.splitPath(this.path)[1];
85
+ if (type === "namespace")
86
+ return base.replace(".json", "");
87
+ return base;
88
+ }
89
+ parseJson() {
90
+ const { settings, helpers } = this.pr.registry;
91
+ const { fs } = helpers;
92
+ const fullPath = fs.resolvePath(settings.repoRoot, this.path);
93
+ const content = fs.readFileAsUtf8(fullPath);
94
+ return parseJSON(content);
95
+ }
96
+ async validate() {
97
+ const fileType = this.getFileType();
98
+ if (!fileType) {
99
+ return {
100
+ file: this.path,
101
+ type: "unknown",
102
+ result: {
103
+ success: false,
104
+ errors: [
105
+ createError("File path does not match any known registry structure", ERROR_CODES.FILE_TYPE_UNKNOWN),
106
+ ],
107
+ },
108
+ };
109
+ }
110
+ let result;
111
+ switch (fileType) {
112
+ case "spec":
113
+ case "stack":
114
+ case "parser":
115
+ result = await validateEntity(this, fileType);
116
+ break;
117
+ case "blob":
118
+ result = validateBlob(this);
119
+ break;
120
+ case "namespace":
121
+ result = await validateNamespaceMetadata(this);
122
+ break;
123
+ case "verified":
124
+ case "limits":
125
+ result = validateNamespaceOverrides(this, fileType);
126
+ break;
127
+ }
128
+ return { file: this.path, type: fileType, result };
129
+ }
130
+ }
131
+ //# sourceMappingURL=changed-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"changed-file.js","sourceRoot":"","sources":["../src/changed-file.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { Helpers, RegistryValidator } from "./registry-validator.js";
2
+ export { settingsSchema } from "./settings.js";
3
+ export type { Settings } from "./settings.js";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { RegistryValidator } from "./registry-validator.js";
2
+ export { settingsSchema } from "./settings.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { Helpers } from "../registry-validator.js";
2
+ import { ValidationError } from "../validation-result.js";
3
+ import { Settings } from "../settings.js";
4
+ export declare function checkPushLimit(prAuthor: string, namespace: string, helpers: Helpers, settings: Settings): Promise<ValidationError | null>;
5
+ //# sourceMappingURL=check-push-limit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-push-limit.d.ts","sourceRoot":"","sources":["../../src/lib/check-push-limit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAMnD,OAAO,EACL,eAAe,EAGhB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,wBAAsB,cAAc,CAClC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAwEjC"}
@@ -0,0 +1,61 @@
1
+ import { getNamespaceEditorEntry } from "./namespace.js";
2
+ import { getNamespaceMetadataFromHead, getPushLimitOverridesFromHead, } from "./git-head.js";
3
+ import { ERROR_CODES, createError, } from "../validation-result.js";
4
+ export async function checkPushLimit(prAuthor, namespace, helpers, settings) {
5
+ const namespaceMetadata = await getNamespaceMetadataFromHead(namespace, helpers);
6
+ if (!namespaceMetadata)
7
+ return null;
8
+ const editorEntry = getNamespaceEditorEntry(prAuthor, namespaceMetadata);
9
+ if (!editorEntry)
10
+ return null;
11
+ let editorLimit = editorEntry.pushLimit || {
12
+ unit: settings.pushLimits.default.unit,
13
+ value: settings.pushLimits.default.pushes,
14
+ };
15
+ const overrides = await getPushLimitOverridesFromHead(helpers);
16
+ const override = overrides
17
+ ? overrides.find((o) => o.namespace === namespace)
18
+ : undefined;
19
+ let effectiveLimit = editorLimit;
20
+ let limitSource = "editor settings";
21
+ if (override) {
22
+ const overrideValue = override.pushLimit.value;
23
+ const editorValue = editorLimit.value;
24
+ if (overrideValue < editorValue) {
25
+ effectiveLimit = override.pushLimit;
26
+ limitSource = "namespace override";
27
+ }
28
+ }
29
+ else if (!editorEntry.pushLimit) {
30
+ limitSource = "default (10/day)";
31
+ }
32
+ try {
33
+ const now = new Date();
34
+ const msInDay = 24 * 60 * 60 * 1000;
35
+ const msInUnit = effectiveLimit.unit === "daily" ? msInDay : msInDay * 7;
36
+ const startDate = new Date(now.getTime() - msInUnit);
37
+ const filePrefixes = [
38
+ `specs/${namespace}/`,
39
+ `stacks/${namespace}/`,
40
+ `parsers/${namespace}/`,
41
+ `blobs/${namespace}/`,
42
+ ];
43
+ const prs = (await helpers.git
44
+ .getAllPRs())
45
+ .filter((pr) => pr.user.id === prAuthor && new Date(pr.createdAt) >= startDate);
46
+ let count = 0;
47
+ for (const pr of prs) {
48
+ const files = await helpers.git.getPRFiles(pr.url);
49
+ const touchesNamespace = files.some((f) => filePrefixes.some((prefix) => f.filename.startsWith(prefix)));
50
+ if (touchesNamespace)
51
+ count++;
52
+ }
53
+ if (count >= effectiveLimit.value)
54
+ return createError(`Push limit exceeded for namespace "${namespace}": ${count}/${effectiveLimit.value} ${effectiveLimit.unit} pushes used. Limit set by ${limitSource}.`, ERROR_CODES.PUSH_LIMIT_EXCEEDED);
55
+ return null;
56
+ }
57
+ catch (error) {
58
+ return null;
59
+ }
60
+ }
61
+ //# sourceMappingURL=check-push-limit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-push-limit.js","sourceRoot":"","sources":["../../src/lib/check-push-limit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { Helpers } from "../registry-validator.js";
2
+ import { NamespaceMetadata, PushLimitOverrides } from "@figulus/schema/registry";
3
+ export declare function getPushLimitOverridesFromHead(helpers: Helpers): Promise<PushLimitOverrides | null>;
4
+ export declare function getNamespaceMetadataFromHead(namespace: string, helpers: Helpers): Promise<NamespaceMetadata | null>;
5
+ //# sourceMappingURL=git-head.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-head.d.ts","sourceRoot":"","sources":["../../src/lib/git-head.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACnD,OAAO,EACL,iBAAiB,EAEjB,kBAAkB,EAEnB,MAAM,0BAA0B,CAAC;AAkBlC,wBAAsB,6BAA6B,CACjD,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAMpC;AAED,wBAAgB,4BAA4B,CAC1C,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAMnC"}
@@ -0,0 +1,20 @@
1
+ import { namespaceMetadataSchema, pushLimitOverridesSchema, } from "@figulus/schema/registry";
2
+ import { parseJSON } from "./parse.js";
3
+ async function getFileFromHeadAndParse(filePath, schema, helpers) {
4
+ try {
5
+ const headContent = await helpers.git.showHead(filePath);
6
+ const data = parseJSON(headContent);
7
+ const result = schema.safeParse(data);
8
+ return result.success ? data : null;
9
+ }
10
+ catch (error) {
11
+ return null;
12
+ }
13
+ }
14
+ export async function getPushLimitOverridesFromHead(helpers) {
15
+ return getFileFromHeadAndParse("namespaces/push-limit-overrides.json", pushLimitOverridesSchema, helpers);
16
+ }
17
+ export function getNamespaceMetadataFromHead(namespace, helpers) {
18
+ return getFileFromHeadAndParse(`namespaces/${namespace}.json`, namespaceMetadataSchema, helpers);
19
+ }
20
+ //# sourceMappingURL=git-head.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-head.js","sourceRoot":"","sources":["../../src/lib/git-head.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,uBAAuB,EAEvB,wBAAwB,GACzB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,KAAK,UAAU,uBAAuB,CACpC,QAAgB,EAChB,MAAoB,EACpB,OAAgB;IAEhB,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACzD,MAAM,IAAI,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC;QACpC,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACtC,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IACtC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,6BAA6B,CACjD,OAAgB;IAEhB,OAAO,uBAAuB,CAC5B,sCAAsC,EACtC,wBAAwB,EACxB,OAAO,CACR,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,4BAA4B,CAC1C,SAAiB,EACjB,OAAgB;IAEhB,OAAO,uBAAuB,CAC5B,cAAc,SAAS,OAAO,EAC9B,uBAAuB,EACvB,OAAO,CACR,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { ChangedFile, FileTypeEntity } from "../changed-file.js";
2
+ import { NamespaceMetadata, NamespaceMetadataEditorEntry } from "@figulus/schema/registry";
3
+ export declare function getNamespaceFromFilePath(file: ChangedFile, type: FileTypeEntity | "namespace"): string;
4
+ export declare function getNamespaceEditorEntry(user: string, namespaceMetadata: NamespaceMetadata): NamespaceMetadataEditorEntry | undefined;
5
+ //# sourceMappingURL=namespace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"namespace.d.ts","sourceRoot":"","sources":["../../src/lib/namespace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EACL,iBAAiB,EACjB,4BAA4B,EAC7B,MAAM,0BAA0B,CAAC;AAElC,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,WAAW,EACjB,IAAI,EAAE,cAAc,GAAG,WAAW,GACjC,MAAM,CAIR;AAED,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,MAAM,EACZ,iBAAiB,EAAE,iBAAiB,GACnC,4BAA4B,GAAG,SAAS,CAE1C"}
@@ -0,0 +1,10 @@
1
+ export function getNamespaceFromFilePath(file, type) {
2
+ const base = file.pr.registry.helpers.fs.splitPath(file.path)[1];
3
+ if (type === "namespace")
4
+ return base.replace(".json", "");
5
+ return base;
6
+ }
7
+ export function getNamespaceEditorEntry(user, namespaceMetadata) {
8
+ return namespaceMetadata.editors.find((e) => e.username === user);
9
+ }
10
+ //# sourceMappingURL=namespace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"namespace.js","sourceRoot":"","sources":["../../src/lib/namespace.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,wBAAwB,CACtC,IAAiB,EACjB,IAAkC;IAElC,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACjE,IAAI,IAAI,KAAK,WAAW;QAAE,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC3D,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,uBAAuB,CACrC,IAAY,EACZ,iBAAoC;IAEpC,OAAO,iBAAiB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC;AACpE,CAAC"}
@@ -0,0 +1,7 @@
1
+ import z from "zod";
2
+ import { ChangedFile } from "../changed-file.js";
3
+ import { ValidationResult } from "../validation-result.js";
4
+ export declare function parseJSON(data: string): any;
5
+ export declare function parseSchema(data: any, schema: z.ZodType<any>): ValidationResult;
6
+ export declare function parseFileJson(file: ChangedFile): any;
7
+ //# sourceMappingURL=parse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/lib/parse.ts"],"names":[],"mappings":"AACA,OAAO,CAAC,MAAM,KAAK,CAAC;AACpB,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EACL,gBAAgB,EAIjB,MAAM,yBAAyB,CAAC;AAEjC,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAE3C;AAED,wBAAgB,WAAW,CACzB,IAAI,EAAE,GAAG,EACT,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,GACrB,gBAAgB,CAalB;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,WAAW,GAAG,GAAG,CAcpD"}
@@ -0,0 +1,29 @@
1
+ import stripComments from "strip-json-comments";
2
+ import { ERROR_CODES, createError, success, } from "../validation-result.js";
3
+ export function parseJSON(data) {
4
+ return JSON.parse(stripComments(data));
5
+ }
6
+ export function parseSchema(data, schema) {
7
+ const result = schema.safeParse(data);
8
+ if (!result.success) {
9
+ const errors = result.error.issues.map((err) => {
10
+ const path = err.path.length > 0 ? err.path.join(".") : "root";
11
+ return createError(`${path}: ${err.message}`, ERROR_CODES.ENTITY_SCHEMA_INVALID);
12
+ });
13
+ return { success: false, errors };
14
+ }
15
+ return success();
16
+ }
17
+ export function parseFileJson(file) {
18
+ try {
19
+ const { settings, helpers } = file.pr.registry;
20
+ const { fs } = helpers;
21
+ const fullPath = fs.resolvePath(settings.repoRoot, file.path);
22
+ const content = fs.readFileAsUtf8(fullPath);
23
+ return parseJSON(content);
24
+ }
25
+ catch (error) {
26
+ throw new Error(`Failed to parse JSON: ${error instanceof Error ? error.message : String(error)}`);
27
+ }
28
+ }
29
+ //# sourceMappingURL=parse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/lib/parse.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,MAAM,qBAAqB,CAAC;AAGhD,OAAO,EAEL,WAAW,EACX,WAAW,EACX,OAAO,GACR,MAAM,yBAAyB,CAAC;AAEjC,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,OAAO,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,WAAW,CACzB,IAAS,EACT,MAAsB;IAEtB,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACtC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;YAC7C,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;YAC/D,OAAO,WAAW,CAChB,GAAG,IAAI,KAAK,GAAG,CAAC,OAAO,EAAE,EACzB,WAAW,CAAC,qBAAqB,CAClC,CAAC;QACJ,CAAC,CAAC,CAAC;QACH,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IACpC,CAAC;IACD,OAAO,OAAO,EAAE,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAiB;IAC7C,IAAI,CAAC;QACH,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC;QAC/C,MAAM,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC;QAEvB,MAAM,QAAQ,GAAG,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9D,MAAM,OAAO,GAAG,EAAE,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAE5C,OAAO,SAAS,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,yBAAyB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAClF,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { RegistryValidator } from "../registry-validator.js";
2
+ export declare function isRegistryMaintainer(user: string, registry: RegistryValidator): boolean;
3
+ export declare function isReservedNamespace(namespace: string, registry: RegistryValidator): boolean;
4
+ //# sourceMappingURL=permissions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/lib/permissions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,iBAAiB,GAC1B,OAAO,CAGT;AAED,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,iBAAiB,GAC1B,OAAO,CAGT"}
@@ -0,0 +1,9 @@
1
+ export function isRegistryMaintainer(user, registry) {
2
+ const { registryMaintainers } = registry.settings;
3
+ return registryMaintainers.includes(user);
4
+ }
5
+ export function isReservedNamespace(namespace, registry) {
6
+ const { restrictedNamespaces } = registry.settings;
7
+ return restrictedNamespaces.includes(namespace);
8
+ }
9
+ //# sourceMappingURL=permissions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../src/lib/permissions.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,oBAAoB,CAClC,IAAY,EACZ,QAA2B;IAE3B,MAAM,EAAE,mBAAmB,EAAE,GAAG,QAAQ,CAAC,QAAQ,CAAC;IAClD,OAAO,mBAAmB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,SAAiB,EACjB,QAA2B;IAE3B,MAAM,EAAE,oBAAoB,EAAE,GAAG,QAAQ,CAAC,QAAQ,CAAC;IACnD,OAAO,oBAAoB,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AAClD,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { FileTypeEntity } from "../changed-file.js";
2
+ import { RegistryValidator } from "../registry-validator.js";
3
+ import { ValidationResult } from "../validation-result.js";
4
+ export declare function validateBlobReferences(data: any, namespace: string, type: FileTypeEntity, registry: RegistryValidator): ValidationResult;
5
+ //# sourceMappingURL=validate-blob-references.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-blob-references.d.ts","sourceRoot":"","sources":["../../src/lib/validate-blob-references.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EAEf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EACL,gBAAgB,EAIjB,MAAM,yBAAyB,CAAC;AAEjC,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,GAAG,EACT,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,cAAc,EACpB,QAAQ,EAAE,iBAAiB,GAC1B,gBAAgB,CA6BlB"}
@@ -0,0 +1,21 @@
1
+ import { getExtensionFromFileTypeEntity, } from "../changed-file.js";
2
+ import { ERROR_CODES, createError, success, } from "../validation-result.js";
3
+ export function validateBlobReferences(data, namespace, type, registry) {
4
+ const errors = [];
5
+ const variants = data.variants || [];
6
+ if (!Array.isArray(variants))
7
+ return success();
8
+ for (const variant of variants) {
9
+ const blob = variant.blob || {};
10
+ const contentHash = blob.contentHash;
11
+ const extension = getExtensionFromFileTypeEntity(type);
12
+ if (!contentHash || !extension)
13
+ continue;
14
+ const blobPath = registry.helpers.fs.resolvePath(registry.settings.repoRoot, `blobs/${namespace}/${contentHash}.${extension}`);
15
+ if (!registry.helpers.fs.fileOrDirExists(blobPath)) {
16
+ errors.push(createError(`Variant references blob ${contentHash} but blobs/${namespace}/${contentHash}.${extension} does not exist in the repository`, ERROR_CODES.BLOB_REFERENCE_NOT_FOUND));
17
+ }
18
+ }
19
+ return errors.length > 0 ? { success: false, errors } : success();
20
+ }
21
+ //# sourceMappingURL=validate-blob-references.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-blob-references.js","sourceRoot":"","sources":["../../src/lib/validate-blob-references.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,8BAA8B,GAC/B,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAEL,WAAW,EACX,WAAW,EACX,OAAO,GACR,MAAM,yBAAyB,CAAC;AAEjC,MAAM,UAAU,sBAAsB,CACpC,IAAS,EACT,SAAiB,EACjB,IAAoB,EACpB,QAA2B;IAE3B,MAAM,MAAM,GAAG,EAAE,CAAC;IAElB,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC;IACrC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;QAAE,OAAO,OAAO,EAAE,CAAC;IAE/C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC;QAChC,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;QACrC,MAAM,SAAS,GAAG,8BAA8B,CAAC,IAAI,CAAC,CAAC;QAEvD,IAAI,CAAC,WAAW,IAAI,CAAC,SAAS;YAAE,SAAS;QAEzC,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,WAAW,CAC9C,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAC1B,SAAS,SAAS,IAAI,WAAW,IAAI,SAAS,EAAE,CACjD,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC;YACnD,MAAM,CAAC,IAAI,CACT,WAAW,CACT,2BAA2B,WAAW,cAAc,SAAS,IAAI,WAAW,IAAI,SAAS,mCAAmC,EAC5H,WAAW,CAAC,wBAAwB,CACrC,CACF,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;AACpE,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { ChangedFile } from "../../changed-file.js";
2
+ import { ValidationResult } from "../../validation-result.js";
3
+ export declare function validateBlob(file: ChangedFile): ValidationResult;
4
+ //# sourceMappingURL=blob.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blob.d.ts","sourceRoot":"","sources":["../../../src/lib/validate-file/blob.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EAEZ,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,gBAAgB,EAIjB,MAAM,4BAA4B,CAAC;AAEpC,wBAAgB,YAAY,CAAC,IAAI,EAAE,WAAW,GAAG,gBAAgB,CAwEhE"}
@@ -0,0 +1,57 @@
1
+ import { getFileTypeEntityFromExtension, } from "../../changed-file.js";
2
+ import { ERROR_CODES, createError, success, } from "../../validation-result.js";
3
+ export function validateBlob(file) {
4
+ const { helpers, settings } = file.pr.registry;
5
+ const fileName = helpers.fs.splitPath(file.path).pop();
6
+ if (!fileName) {
7
+ return {
8
+ success: false,
9
+ errors: [
10
+ createError("Invalid blob filename", ERROR_CODES.BLOB_INVALID_FILENAME),
11
+ ],
12
+ };
13
+ }
14
+ const parts = fileName.split(".");
15
+ if (parts.length < 2) {
16
+ return {
17
+ success: false,
18
+ errors: [
19
+ createError("Blob filename must have extension", ERROR_CODES.BLOB_MISSING_EXTENSION),
20
+ ],
21
+ };
22
+ }
23
+ const expectedHash = parts[0];
24
+ const extension = parts.slice(1).join(".");
25
+ const entityType = getFileTypeEntityFromExtension(extension);
26
+ if (!entityType) {
27
+ return {
28
+ success: false,
29
+ errors: [
30
+ createError(`Invalid blob extension: ${extension} (must be js, figspec, or figstack)`, ERROR_CODES.BLOB_INVALID_EXTENSION),
31
+ ],
32
+ };
33
+ }
34
+ try {
35
+ const path = helpers.fs.resolvePath(settings.repoRoot, file.path);
36
+ const content = helpers.fs.readFileAsUtf8(path);
37
+ const actualHash = helpers.crypto.createSha256HexHash(content);
38
+ if (actualHash !== expectedHash) {
39
+ return {
40
+ success: false,
41
+ errors: [
42
+ createError(`Hash mismatch: filename hash ${expectedHash} does not match content hash ${actualHash}`, ERROR_CODES.BLOB_HASH_MISMATCH),
43
+ ],
44
+ };
45
+ }
46
+ }
47
+ catch (error) {
48
+ return {
49
+ success: false,
50
+ errors: [
51
+ createError(`Failed to verify blob: ${error instanceof Error ? error.message : String(error)}`, ERROR_CODES.BLOB_VERIFICATION_FAILED),
52
+ ],
53
+ };
54
+ }
55
+ return success();
56
+ }
57
+ //# sourceMappingURL=blob.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blob.js","sourceRoot":"","sources":["../../../src/lib/validate-file/blob.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,8BAA8B,GAC/B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAEL,WAAW,EACX,WAAW,EACX,OAAO,GACR,MAAM,4BAA4B,CAAC;AAEpC,MAAM,UAAU,YAAY,CAAC,IAAiB;IAC5C,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC;IAE/C,MAAM,QAAQ,GAAG,OAAO,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC;IACvD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE;gBACN,WAAW,CAAC,uBAAuB,EAAE,WAAW,CAAC,qBAAqB,CAAC;aACxE;SACF,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE;gBACN,WAAW,CACT,mCAAmC,EACnC,WAAW,CAAC,sBAAsB,CACnC;aACF;SACF,CAAC;IACJ,CAAC;IAED,MAAM,YAAY,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAC9B,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAE3C,MAAM,UAAU,GAAG,8BAA8B,CAAC,SAAS,CAAC,CAAC;IAE7D,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE;gBACN,WAAW,CACT,2BAA2B,SAAS,qCAAqC,EACzE,WAAW,CAAC,sBAAsB,CACnC;aACF;SACF,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,OAAO,CAAC,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAClE,MAAM,OAAO,GAAG,OAAO,CAAC,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QAChD,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC;QAE/D,IAAI,UAAU,KAAK,YAAY,EAAE,CAAC;YAChC,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE;oBACN,WAAW,CACT,gCAAgC,YAAY,gCAAgC,UAAU,EAAE,EACxF,WAAW,CAAC,kBAAkB,CAC/B;iBACF;aACF,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE;gBACN,WAAW,CACT,0BAA0B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAClF,WAAW,CAAC,wBAAwB,CACrC;aACF;SACF,CAAC;IACJ,CAAC;IAED,OAAO,OAAO,EAAE,CAAC;AACnB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { ChangedFile, FileTypeEntity } from "../../changed-file.js";
2
+ import { ValidationResult } from "../../validation-result.js";
3
+ export declare function validateEntity(file: ChangedFile, type: FileTypeEntity): Promise<ValidationResult>;
4
+ //# sourceMappingURL=entity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity.d.ts","sourceRoot":"","sources":["../../../src/lib/validate-file/entity.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,cAAc,EAEf,MAAM,uBAAuB,CAAC;AAM/B,OAAO,EACL,gBAAgB,EAIjB,MAAM,4BAA4B,CAAC;AAEpC,wBAAsB,cAAc,CAClC,IAAI,EAAE,WAAW,EACjB,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,gBAAgB,CAAC,CA0F3B"}
@@ -0,0 +1,74 @@
1
+ import { getSchemaFromFileTypeEntity, } from "../../changed-file.js";
2
+ import { getNamespaceEditorEntry } from "../namespace.js";
3
+ import { parseSchema } from "../parse.js";
4
+ import { checkPushLimit } from "../check-push-limit.js";
5
+ import { getNamespaceMetadataFromHead } from "../git-head.js";
6
+ import { validateBlobReferences } from "../validate-blob-references.js";
7
+ import { ERROR_CODES, createError, success, } from "../../validation-result.js";
8
+ export async function validateEntity(file, type) {
9
+ const { registry, prInfo } = file.pr;
10
+ const { settings, helpers } = registry;
11
+ const { fs } = helpers;
12
+ const namespace = file.getNamespace(type);
13
+ const isAllowedToChangeEntityFile = async () => {
14
+ if (registry.isNamespaceRestricted(namespace)) {
15
+ if (!registry.isMaintainer(prInfo.author)) {
16
+ return {
17
+ success: false,
18
+ errors: [
19
+ createError(`The ${namespace}/ namespace is reserved. Changes require maintainer approval.`, ERROR_CODES.NAMESPACE_RESERVED),
20
+ ],
21
+ };
22
+ }
23
+ }
24
+ else {
25
+ const namespaceMetadata = await getNamespaceMetadataFromHead(namespace, registry.helpers);
26
+ if (namespaceMetadata === null) {
27
+ return {
28
+ success: false,
29
+ errors: [
30
+ createError(`Namespace "${namespace}" does not exist. Run \`figulus registry claim ${namespace}\` to claim it before publishing.`, ERROR_CODES.NAMESPACE_NOT_FOUND),
31
+ ],
32
+ };
33
+ }
34
+ if (!getNamespaceEditorEntry(prInfo.author, namespaceMetadata)) {
35
+ return {
36
+ success: false,
37
+ errors: [
38
+ createError(`PR author "${prInfo.author}" is not listed as an editor for namespace "${namespace}"`, ERROR_CODES.NAMESPACE_NOT_EDITOR),
39
+ ],
40
+ };
41
+ }
42
+ const pushLimitError = await checkPushLimit(prInfo.author, namespace, helpers, settings);
43
+ if (pushLimitError) {
44
+ return {
45
+ success: false,
46
+ errors: [pushLimitError],
47
+ };
48
+ }
49
+ }
50
+ return success();
51
+ };
52
+ const permissionResult = await isAllowedToChangeEntityFile();
53
+ if (!permissionResult.success)
54
+ return permissionResult;
55
+ try {
56
+ const data = file.parseJson();
57
+ const schemaResult = parseSchema(data, getSchemaFromFileTypeEntity(type));
58
+ if (!schemaResult.success)
59
+ return schemaResult;
60
+ const blobResult = validateBlobReferences(data, namespace, type, registry);
61
+ if (!blobResult.success)
62
+ return blobResult;
63
+ return success();
64
+ }
65
+ catch (error) {
66
+ return {
67
+ success: false,
68
+ errors: [
69
+ createError(`Failed to parse ${type}: ${error instanceof Error ? error.message : String(error)}`, ERROR_CODES.ENTITY_PARSE_ERROR),
70
+ ],
71
+ };
72
+ }
73
+ }
74
+ //# sourceMappingURL=entity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity.js","sourceRoot":"","sources":["../../../src/lib/validate-file/entity.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,2BAA2B,GAC5B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,4BAA4B,EAAE,MAAM,gBAAgB,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAEL,WAAW,EACX,WAAW,EACX,OAAO,GACR,MAAM,4BAA4B,CAAC;AAEpC,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,IAAiB,EACjB,IAAoB;IAEpB,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;IACrC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,QAAQ,CAAC;IACvC,MAAM,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC;IAEvB,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IAE1C,MAAM,2BAA2B,GAAG,KAAK,IAAI,EAAE;QAC7C,IAAI,QAAQ,CAAC,qBAAqB,CAAC,SAAS,CAAC,EAAE,CAAC;YAC9C,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC1C,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,MAAM,EAAE;wBACN,WAAW,CACT,OAAO,SAAS,+DAA+D,EAC/E,WAAW,CAAC,kBAAkB,CAC/B;qBACF;iBACF,CAAC;YACJ,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,iBAAiB,GAAG,MAAM,4BAA4B,CAC1D,SAAS,EACT,QAAQ,CAAC,OAAO,CACjB,CAAC;YACF,IAAI,iBAAiB,KAAK,IAAI,EAAE,CAAC;gBAC/B,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,MAAM,EAAE;wBACN,WAAW,CACT,cAAc,SAAS,kDAAkD,SAAS,mCAAmC,EACrH,WAAW,CAAC,mBAAmB,CAChC;qBACF;iBACF,CAAC;YACJ,CAAC;YAED,IAAI,CAAC,uBAAuB,CAAC,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,EAAE,CAAC;gBAC/D,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,MAAM,EAAE;wBACN,WAAW,CACT,cAAc,MAAM,CAAC,MAAM,+CAA+C,SAAS,GAAG,EACtF,WAAW,CAAC,oBAAoB,CACjC;qBACF;iBACF,CAAC;YACJ,CAAC;YAED,MAAM,cAAc,GAAG,MAAM,cAAc,CACzC,MAAM,CAAC,MAAM,EACb,SAAS,EACT,OAAO,EACP,QAAQ,CACT,CAAC;YACF,IAAI,cAAc,EAAE,CAAC;gBACnB,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,MAAM,EAAE,CAAC,cAAc,CAAC;iBACzB,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO,OAAO,EAAE,CAAC;IACnB,CAAC,CAAC;IAEF,MAAM,gBAAgB,GAAG,MAAM,2BAA2B,EAAE,CAAC;IAC7D,IAAI,CAAC,gBAAgB,CAAC,OAAO;QAAE,OAAO,gBAAgB,CAAC;IAEvD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAE9B,MAAM,YAAY,GAAG,WAAW,CAAC,IAAI,EAAE,2BAA2B,CAAC,IAAI,CAAC,CAAC,CAAC;QAC1E,IAAI,CAAC,YAAY,CAAC,OAAO;YAAE,OAAO,YAAY,CAAC;QAE/C,MAAM,UAAU,GAAG,sBAAsB,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC3E,IAAI,CAAC,UAAU,CAAC,OAAO;YAAE,OAAO,UAAU,CAAC;QAE3C,OAAO,OAAO,EAAE,CAAC;IACnB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE;gBACN,WAAW,CACT,mBAAmB,IAAI,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EACpF,WAAW,CAAC,kBAAkB,CAC/B;aACF;SACF,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { ChangedFile } from "../../changed-file.js";
2
+ import { ValidationResult } from "../../validation-result.js";
3
+ export declare function validateNamespaceMetadata(file: ChangedFile): Promise<ValidationResult>;
4
+ //# sourceMappingURL=namespace-metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"namespace-metadata.d.ts","sourceRoot":"","sources":["../../../src/lib/validate-file/namespace-metadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAIpD,OAAO,EACL,gBAAgB,EAKjB,MAAM,4BAA4B,CAAC;AAMpC,wBAAsB,yBAAyB,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAkK5F"}