Repository navigation
Expand file tree
/
Copy pathpackage.ts
More file actions
85 lines (79 loc) · 3.17 KB
/
Copy pathpackage.ts
File metadata and controls
85 lines (79 loc) · 3.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import { z } from "zod"
const Identifier = z.string().regex(/^[a-z][a-z0-9.-]*$/)
export const SynergyPackageName = z.string().regex(/^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/)
const Version = z.string().regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/)
const RelativeFile = z.string().refine(
(value) =>
value.startsWith("./") &&
value.length > 2 &&
!/[\\\0?#]/.test(value) &&
value
.slice(2)
.split("/")
.every((part) => part !== ".." && part !== "." && part !== ""),
"Package files must be relative paths inside the package",
)
const Packages = z.record(SynergyPackageName, z.string().min(1))
const common = {
formatVersion: z.literal(1),
id: Identifier,
version: Version,
compatibility: z.object({ synergy: z.string().min(1).max(256) }).strict(),
}
export const ComponentPackage = z
.object({
...common,
kind: z.literal("component"),
apiVersion: z.literal(1),
entry: RelativeFile,
export: z.string().regex(/^[A-Za-z_$][A-Za-z0-9_$]*$/),
runners: z
.record(
Identifier,
z.object({ entry: RelativeFile, export: z.string().regex(/^[A-Za-z_$][A-Za-z0-9_$]*$/) }).strict(),
)
.optional(),
requires: z.record(Identifier, z.string().min(1)).optional(),
packages: Packages.optional(),
})
.strict()
export const PresetPackage = z
.object({
...common,
kind: z.literal("preset"),
packages: Packages,
})
.strict()
export const AppArtifact = z
.object({
target: z.enum(["darwin-arm64", "darwin-x64", "win32-arm64", "win32-x64", "linux-arm64", "linux-x64"]),
url: z.url().refine((value) => new URL(value).protocol === "https:", "Application artifacts require HTTPS"),
sha256: z.string().regex(/^[a-f0-9]{64}$/),
executable: RelativeFile,
format: z.enum(["zip", "dmg", "exe", "AppImage", "deb", "tar.gz"]),
signing: z.discriminatedUnion("type", [
z.object({ type: z.literal("apple"), teamID: z.string().regex(/^[A-Z0-9]{10}$/) }).strict(),
z.object({ type: z.literal("authenticode"), publisher: z.string().min(1) }).strict(),
z.object({ type: z.literal("checksum") }).strict(),
]),
})
.strict()
.superRefine((artifact, context) => {
if (artifact.target.startsWith("darwin-") && artifact.signing.type !== "apple")
context.addIssue({ code: "custom", message: "macOS applications require an Apple signing identity" })
if (artifact.target.startsWith("win32-") && !["authenticode", "checksum"].includes(artifact.signing.type))
context.addIssue({
code: "custom",
message: "Windows applications require an Authenticode publisher or explicit checksum-only distribution",
})
})
export const SynergyPackage = z.discriminatedUnion("kind", [
ComponentPackage,
PresetPackage,
z.object({ ...common, kind: z.literal("plugin"), manifest: RelativeFile }).strict(),
z.object({ ...common, kind: z.literal("app"), artifacts: z.array(AppArtifact).min(1) }).strict(),
])
export type SynergyPackage = z.infer<typeof SynergyPackage>
export type ComponentPackage = z.infer<typeof ComponentPackage>
export type PresetPackage = z.infer<typeof PresetPackage>
export type AppArtifact = z.infer<typeof AppArtifact>