com.thefibrehose.pattern
Schema Diff
+17 -7
Compatibility Analysis
Breaking Changes Detected
2 breaking changes, 3 non-breaking changes.
Breaking Changes (2)
- RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "com.thefibrehose.pattern:body", src: "com.thefibrehose.pattern:body", tgt: "com.thefibrehose.pattern:body.name", kind: "prop", name: Some("name") }
- RequiredEdgeRemoved RequiredEdgeRemoved { vertex_id: "com.thefibrehose.pattern:body", src: "com.thefibrehose.pattern:body", tgt: "com.thefibrehose.pattern:body.subject", kind: "prop", name: Some("subject") }
Non-Breaking Changes (3)
- AddedVertex AddedVertex { vertex_id: "com.thefibrehose.pattern:body.name" }
- AddedVertex AddedVertex { vertex_id: "com.thefibrehose.pattern:body.privatePdfId" }
- AddedEdge AddedEdge { src: "com.thefibrehose.pattern:body", tgt: "com.thefibrehose.pattern:body.privatePdfId", kind: "prop", name: Some("privatePdfId") }
Migration Guidance
Added Elements
AddedVertex { vertex_id: "com.thefibrehose.pattern:body.name" }AddedVertex { vertex_id: "com.thefibrehose.pattern:body.privatePdfId" }
Additional Notes
- Breaking: RequiredEdgeAdded { vertex_id: "com.thefibrehose.pattern:body", src: "com.thefibrehose.pattern:body", tgt: "com.thefibrehose.pattern:body.name", kind: "prop", name: Some("name") }
- Breaking: RequiredEdgeRemoved { vertex_id: "com.thefibrehose.pattern:body", src: "com.thefibrehose.pattern:body", tgt: "com.thefibrehose.pattern:body.subject", kind: "prop", name: Some("subject") }
- Non-breaking: AddedEdge { src: "com.thefibrehose.pattern:body", tgt: "com.thefibrehose.pattern:body.privatePdfId", kind: "prop", name: Some("privatePdfId") }
1
1
{
2
2
"$type": "com.atproto.lexicon.schema",
3
3
"defs": {
4
4
"main": {
5
-
"description": "Structured metadata for a knitting/crochet pattern, paired with a com.thefibrehose.pdf record.",
5
+
"description": "Structured metadata for a knitting/crochet pattern. The PDF itself lives either as a paired com.thefibrehose.pdf record (subject) or on thefibrehose's own backend (privatePdfId) - exactly one of the two must be set, enforced client-side only since atproto lexicon cannot express cross-field conditionals (same precedent as the yardage/meterage pair below).",
6
6
"key": "tid",
7
7
"record": {
8
8
"properties": {
9
9
"attributes": {
10
10
"description": "Freeform descriptive tags, e.g. textured, colorwork, top-down.",
11
11
"items": {
12
12
"maxLength": 64,
13
13
"type": "string"
14
14
},
15
15
"maxLength": 30,
16
16
"type": "array"
17
17
},
18
18
"colorCount": {
19
19
"description": "Number of distinct yarn colors used in the pattern.",
20
20
"minimum": 1,
21
21
"type": "integer"
22
22
},
23
23
"craftType": {
24
24
"description": "Whether this is a knitting, crochet, or other pattern.",
25
25
"enum": [
26
26
"knitting",
27
27
"crochet",
28
28
"other"
29
29
],
30
30
"type": "string"
31
31
},
32
32
"createdAt": {
33
33
"description": "Timestamp when this pattern record was created.",
34
34
"format": "datetime",
35
35
"type": "string"
36
36
},
37
37
"difficulty": {
38
38
"description": "Optional difficulty rating, 1 (easiest) to 10 (hardest).",
39
39
"maximum": 10,
40
40
"minimum": 1,
41
41
"type": "integer"
42
42
},
43
43
"hookSizeMm": {
44
44
"description": "Recommended crochet hook size in millimeters (e.g. \"5.0\"). Relevant only when craftType is crochet. A string because atproto lexicon has no decimal numeric type.",
45
45
"maxLength": 16,
46
46
"type": "string"
47
47
},
48
48
"language": {
49
49
"description": "BCP-47 language tag the pattern is written in (e.g. \"en\", \"en-US\").",
50
50
"format": "language",
51
51
"type": "string"
52
52
},
53
53
"meterage": {
54
-
"description": "Yarn requirement in meters. Mutually exclusive with yardage (enforced client-side).",
54
+
"description": "Yarn requirement in meters. Computed alongside yardage from whichever unit the uploader entered.",
55
55
"minimum": 0,
56
56
"type": "integer"
57
57
},
58
+
"name": {
59
+
"description": "The pattern's name/title, as given by the uploader.",
60
+
"maxLength": 200,
61
+
"type": "string"
62
+
},
58
63
"needleSizeMm": {
59
64
"description": "Recommended knitting needle size in millimeters (e.g. \"4.5\"). Relevant only when craftType is knitting. A string because atproto lexicon has no decimal numeric type.",
60
65
"maxLength": 16,
61
66
"type": "string"
62
67
},
63
68
"pdfFileName": {
64
-
"description": "Denormalized copy of the linked PDF's fileName, so the list view can display it without an extra fetch.",
69
+
"description": "The PDF's original filename, denormalized here so the list view can display it without an extra fetch regardless of where the file itself is hosted.",
65
70
"maxLength": 1024,
66
71
"type": "string"
67
72
},
68
73
"photo": {
69
74
"accept": [
70
75
"image/png",
71
76
"image/jpeg",
72
77
"image/webp"
73
78
],
74
-
"description": "Optional photo of the finished piece.",
79
+
"description": "Optional photo of the finished piece. Always an atproto blob regardless of where the PDF itself is hosted.",
75
80
"maxSize": 5242880,
76
81
"type": "blob"
77
82
},
83
+
"privatePdfId": {
84
+
"description": "Opaque id of the PDF as stored on thefibrehose's own access-controlled backend, when the PDF is not stored as an atproto blob. Mutually exclusive with subject; exactly one must be present.",
85
+
"maxLength": 64,
86
+
"type": "string"
87
+
},
78
88
"subject": {
79
-
"description": "Strong ref to the linked com.thefibrehose.pdf record holding the actual file.",
89
+
"description": "Strong ref to the linked com.thefibrehose.pdf record holding the actual file, when the PDF is stored as an atproto blob. Mutually exclusive with privatePdfId; exactly one must be present.",
80
90
"ref": "com.atproto.repo.strongRef",
81
91
"type": "ref"
82
92
},
83
93
"uploaderDid": {
84
94
"description": "DID of the account that originally uploaded this pattern. Redundant with the record's own repo ownership today, but keeps provenance explicit and self-describing if this record is ever copied, reposted, or indexed outside its own repo.",
85
95
"format": "did",
86
96
"type": "string"
87
97
},
88
98
"yardage": {
89
-
"description": "Yarn requirement in yards. Mutually exclusive with meterage (enforced client-side).",
99
+
"description": "Yarn requirement in yards. Computed alongside meterage from whichever unit the uploader entered.",
90
100
"minimum": 0,
91
101
"type": "integer"
92
102
},
93
103
"yarnWeight": {
94
104
"description": "Craft Yarn Council standard yarn weight, 0 (Lace) to 7 (Jumbo).",
95
105
"maximum": 7,
96
106
"minimum": 0,
97
107
"type": "integer"
98
108
}
99
109
},
100
110
"required": [
101
-
"subject",
102
111
"uploaderDid",
112
+
"name",
103
113
"pdfFileName",
104
114
"craftType",
105
115
"yarnWeight",
106
116
"colorCount",
107
117
"language",
108
118
"createdAt"
109
119
],
110
120
"type": "object"
111
121
},
112
122
"type": "record"
113
123
}
114
124
},
115
125
"id": "com.thefibrehose.pattern",
116
126
"lexicon": 1
117
127
}