@openrails/contentkit-ui 0.85.1 → 0.87.0-rc.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.
Files changed (211) hide show
  1. package/README.md +28 -7
  2. package/dist/client/beacons.d.ts +13 -4
  3. package/dist/client/beacons.js +14 -7
  4. package/dist/client/beacons.js.map +1 -1
  5. package/dist/client/client.d.ts +3 -0
  6. package/dist/client/client.js +29 -27
  7. package/dist/client/client.js.map +1 -1
  8. package/dist/client/codes.d.ts +6 -1
  9. package/dist/client/codes.js +4 -1
  10. package/dist/client/codes.js.map +1 -1
  11. package/dist/client/content/types.d.ts +4 -2
  12. package/dist/client/content/types.js.map +1 -1
  13. package/dist/client/discovery.js +3 -0
  14. package/dist/client/discovery.js.map +1 -1
  15. package/dist/client/errors.d.ts +6 -0
  16. package/dist/client/errors.js +6 -2
  17. package/dist/client/errors.js.map +1 -1
  18. package/dist/client/gallery.d.ts +3 -5
  19. package/dist/client/gallery.js +16 -20
  20. package/dist/client/gallery.js.map +1 -1
  21. package/dist/client/generated/error-codes.d.ts +1 -1
  22. package/dist/client/generated/error-codes.js +9 -1
  23. package/dist/client/generated/error-codes.js.map +1 -1
  24. package/dist/client/generated/routes.d.ts +29 -3
  25. package/dist/client/generated/routes.js +44 -3
  26. package/dist/client/generated/routes.js.map +1 -1
  27. package/dist/client/generated/wire.d.ts +60 -10
  28. package/dist/client/generated/wire.js.map +1 -1
  29. package/dist/client/index.d.ts +2 -1
  30. package/dist/client/media/queue.d.ts +4 -2
  31. package/dist/client/media/queue.js +18 -12
  32. package/dist/client/media/queue.js.map +1 -1
  33. package/dist/client/media/rules.d.ts +7 -1
  34. package/dist/client/media/rules.js +27 -21
  35. package/dist/client/media/rules.js.map +1 -1
  36. package/dist/client/media/windows.js +1 -1
  37. package/dist/client/media/windows.js.map +1 -1
  38. package/dist/client/stats.d.ts +32 -0
  39. package/dist/client/stats.js +35 -0
  40. package/dist/client/stats.js.map +1 -0
  41. package/dist/client/versions.d.ts +6 -4
  42. package/dist/client/versions.js +24 -26
  43. package/dist/client/versions.js.map +1 -1
  44. package/dist/client.js +30 -29
  45. package/dist/components/admin/content-manager.js +206 -206
  46. package/dist/components/admin/content-manager.js.map +1 -1
  47. package/dist/components/admin/group-manager.js +71 -70
  48. package/dist/components/admin/group-manager.js.map +1 -1
  49. package/dist/components/admin/media-item-panel.d.ts +24 -7
  50. package/dist/components/admin/media-item-panel.js +209 -197
  51. package/dist/components/admin/media-item-panel.js.map +1 -1
  52. package/dist/components/admin/poll-manager.js +25 -25
  53. package/dist/components/admin/stats-dashboard.d.ts +22 -0
  54. package/dist/components/admin/stats-dashboard.js +257 -0
  55. package/dist/components/admin/stats-dashboard.js.map +1 -0
  56. package/dist/components/content/card.d.ts +5 -3
  57. package/dist/components/content/card.js +155 -133
  58. package/dist/components/content/card.js.map +1 -1
  59. package/dist/components/content/download-button.d.ts +26 -0
  60. package/dist/components/content/download-button.js +51 -0
  61. package/dist/components/content/download-button.js.map +1 -0
  62. package/dist/components/content/editors.js +455 -427
  63. package/dist/components/content/editors.js.map +1 -1
  64. package/dist/components/content/grid.d.ts +8 -1
  65. package/dist/components/content/grid.js +153 -104
  66. package/dist/components/content/grid.js.map +1 -1
  67. package/dist/components/content/index.d.ts +4 -2
  68. package/dist/components/content/listing.d.ts +3 -1
  69. package/dist/components/content/listing.js +34 -34
  70. package/dist/components/content/listing.js.map +1 -1
  71. package/dist/components/content/paywall.d.ts +17 -5
  72. package/dist/components/content/paywall.js +115 -100
  73. package/dist/components/content/paywall.js.map +1 -1
  74. package/dist/components/content/reader-stats.d.ts +12 -0
  75. package/dist/components/content/reader-stats.js +47 -0
  76. package/dist/components/content/reader-stats.js.map +1 -0
  77. package/dist/components/groups/banner.js +33 -33
  78. package/dist/components/groups/directory.js +11 -11
  79. package/dist/components/groups/editor.js +293 -293
  80. package/dist/components/groups/editor.js.map +1 -1
  81. package/dist/components/groups/header.js +27 -27
  82. package/dist/components/groups/header.js.map +1 -1
  83. package/dist/components/groups/memberships.js +180 -180
  84. package/dist/components/groups/parts.d.ts +0 -2
  85. package/dist/components/groups/parts.js +9 -27
  86. package/dist/components/groups/parts.js.map +1 -1
  87. package/dist/components/media-folder-editor.js +239 -189
  88. package/dist/components/media-folder-editor.js.map +1 -1
  89. package/dist/components/media-gallery.d.ts +1 -4
  90. package/dist/components/media-gallery.js +19 -34
  91. package/dist/components/media-gallery.js.map +1 -1
  92. package/dist/components/notifications.js +17 -17
  93. package/dist/components/slot-upload.d.ts +2 -2
  94. package/dist/components/slot-upload.js +84 -79
  95. package/dist/components/slot-upload.js.map +1 -1
  96. package/dist/components/social/bans.js +34 -34
  97. package/dist/components/social/comments.js +1 -1
  98. package/dist/components/social/comments.js.map +1 -1
  99. package/dist/components/social/engagement.d.ts +2 -1
  100. package/dist/components/social/engagement.js +5 -3
  101. package/dist/components/social/engagement.js.map +1 -1
  102. package/dist/components/social/moderation.js +52 -48
  103. package/dist/components/social/moderation.js.map +1 -1
  104. package/dist/components/video-player.d.ts +2 -0
  105. package/dist/components/video-player.js +318 -314
  106. package/dist/components/video-player.js.map +1 -1
  107. package/dist/i18n/context.d.ts +2 -0
  108. package/dist/i18n/context.js +23 -5
  109. package/dist/i18n/context.js.map +1 -1
  110. package/dist/index.d.ts +2 -1
  111. package/dist/index.js +13 -10
  112. package/dist/locales/admin/de.js +27 -0
  113. package/dist/locales/admin/de.js.map +1 -1
  114. package/dist/locales/admin/en.d.ts +27 -0
  115. package/dist/locales/admin/en.js +27 -0
  116. package/dist/locales/admin/en.js.map +1 -1
  117. package/dist/locales/admin/es.js +27 -0
  118. package/dist/locales/admin/es.js.map +1 -1
  119. package/dist/locales/admin/ja.js +27 -0
  120. package/dist/locales/admin/ja.js.map +1 -1
  121. package/dist/locales/admin/ko.js +27 -0
  122. package/dist/locales/admin/ko.js.map +1 -1
  123. package/dist/locales/admin/zh.js +27 -0
  124. package/dist/locales/admin/zh.js.map +1 -1
  125. package/dist/locales/content/de.js +6 -0
  126. package/dist/locales/content/de.js.map +1 -1
  127. package/dist/locales/content/en.d.ts +6 -0
  128. package/dist/locales/content/en.js +6 -0
  129. package/dist/locales/content/en.js.map +1 -1
  130. package/dist/locales/content/es.js +6 -0
  131. package/dist/locales/content/es.js.map +1 -1
  132. package/dist/locales/content/ja.js +6 -0
  133. package/dist/locales/content/ja.js.map +1 -1
  134. package/dist/locales/content/ko.js +6 -0
  135. package/dist/locales/content/ko.js.map +1 -1
  136. package/dist/locales/content/zh.js +6 -0
  137. package/dist/locales/content/zh.js.map +1 -1
  138. package/dist/locales/de.js +14 -2
  139. package/dist/locales/de.js.map +1 -1
  140. package/dist/locales/discovery/de.js +3 -0
  141. package/dist/locales/discovery/de.js.map +1 -1
  142. package/dist/locales/discovery/en.d.ts +3 -0
  143. package/dist/locales/discovery/en.js +3 -0
  144. package/dist/locales/discovery/en.js.map +1 -1
  145. package/dist/locales/discovery/es.js +3 -0
  146. package/dist/locales/discovery/es.js.map +1 -1
  147. package/dist/locales/discovery/ja.js +3 -0
  148. package/dist/locales/discovery/ja.js.map +1 -1
  149. package/dist/locales/discovery/ko.js +3 -0
  150. package/dist/locales/discovery/ko.js.map +1 -1
  151. package/dist/locales/discovery/zh.js +3 -0
  152. package/dist/locales/discovery/zh.js.map +1 -1
  153. package/dist/locales/en.d.ts +50 -2
  154. package/dist/locales/en.js +14 -2
  155. package/dist/locales/en.js.map +1 -1
  156. package/dist/locales/es.js +14 -2
  157. package/dist/locales/es.js.map +1 -1
  158. package/dist/locales/ja.js +14 -2
  159. package/dist/locales/ja.js.map +1 -1
  160. package/dist/locales/ko.js +14 -2
  161. package/dist/locales/ko.js.map +1 -1
  162. package/dist/locales/zh.js +14 -2
  163. package/dist/locales/zh.js.map +1 -1
  164. package/dist/react/admin.js +22 -23
  165. package/dist/react/admin.js.map +1 -1
  166. package/dist/react/canonical.d.ts +4 -3
  167. package/dist/react/canonical.js +34 -33
  168. package/dist/react/canonical.js.map +1 -1
  169. package/dist/react/comments.d.ts +1 -1
  170. package/dist/react/comments.js +3 -2
  171. package/dist/react/comments.js.map +1 -1
  172. package/dist/react/contents.js +144 -144
  173. package/dist/react/contents.js.map +1 -1
  174. package/dist/react/context.d.ts +1 -1
  175. package/dist/react/context.js.map +1 -1
  176. package/dist/react/detail.d.ts +12 -6
  177. package/dist/react/detail.js +31 -24
  178. package/dist/react/detail.js.map +1 -1
  179. package/dist/react/discovery.d.ts +11 -0
  180. package/dist/react/discovery.js +49 -30
  181. package/dist/react/discovery.js.map +1 -1
  182. package/dist/react/engagement.d.ts +6 -2
  183. package/dist/react/engagement.js +2 -6
  184. package/dist/react/engagement.js.map +1 -1
  185. package/dist/react/folder.d.ts +7 -2
  186. package/dist/react/folder.js +165 -147
  187. package/dist/react/folder.js.map +1 -1
  188. package/dist/react/groups.d.ts +0 -1
  189. package/dist/react/groups.js +13 -12
  190. package/dist/react/groups.js.map +1 -1
  191. package/dist/react/index.d.ts +6 -4
  192. package/dist/react/location.d.ts +11 -0
  193. package/dist/react/location.js +18 -0
  194. package/dist/react/location.js.map +1 -0
  195. package/dist/react/public.d.ts +8 -0
  196. package/dist/react/public.js +32 -27
  197. package/dist/react/public.js.map +1 -1
  198. package/dist/react/stats.d.ts +24 -0
  199. package/dist/react/stats.js +28 -0
  200. package/dist/react/stats.js.map +1 -0
  201. package/dist/react/use-resource.js +8 -7
  202. package/dist/react/use-resource.js.map +1 -1
  203. package/dist/react/versions.d.ts +25 -5
  204. package/dist/react/versions.js +61 -40
  205. package/dist/react/versions.js.map +1 -1
  206. package/dist/react.js +26 -24
  207. package/dist/styles.css +1 -1
  208. package/dist/urls/index.d.ts +35 -10
  209. package/dist/urls.js +100 -70
  210. package/dist/urls.js.map +1 -1
  211. package/package.json +1 -1
@@ -8,10 +8,9 @@ var e = (e) => !!e?.startsWith("video/"), t = (e) => !!e?.startsWith("audio/"),
8
8
  function i(e, t) {
9
9
  return e?.w && e.h ? e.w / e.h : t;
10
10
  }
11
- var a = (e) => e.slice(0, e.lastIndexOf("/") + 1);
12
- function o(r) {
11
+ function a(r) {
13
12
  if (!r) return [];
14
- let o = r.access === "full", s = r.hls ?? [], c = (e) => s.find((t) => e.path.startsWith(t)), l = (e) => a(e.path) || e.path, u = r.files.filter((n) => n.locked && (e(n.type) || t(n.type))), d = new Set(u.map(l)), f = r.files.filter((e) => e.locked && n(e.type) && !d.has(a(e.path))), p = new Set(u.filter((t) => e(t.type)).map(l)).size, m = o ? [] : r.previews ?? [], h = Math.max(f.length - m.length, 0) + d.size, g = m.map((e, t) => ({
13
+ let a = r.access === "full", o = r.hls ?? [], s = (e) => o.find((t) => e.path.startsWith(t)), c = a ? [] : r.previews ?? [], l = c.map((e, t) => ({
15
14
  kind: "image",
16
15
  key: `preview/${t + 1}`,
17
16
  file: {
@@ -20,17 +19,16 @@ function o(r) {
20
19
  url: e
21
20
  },
22
21
  aspect: 1
23
- })), _ = /* @__PURE__ */ new Set();
22
+ })), u = /* @__PURE__ */ new Set();
24
23
  for (let a of r.files) {
25
- if (a.locked) continue;
26
- let o = c(a);
24
+ let o = s(a);
27
25
  if (o) {
28
- if (_.has(o)) continue;
29
- _.add(o);
26
+ if (u.has(o)) continue;
27
+ u.add(o);
30
28
  let n = r.files.filter((e) => e.path.startsWith(o)), a = n.filter((t) => e(t.type)).reduce((e, t) => (t.w ?? 0) > (e?.w ?? -1) ? t : e, void 0);
31
29
  if (a) {
32
30
  let e = a.dur ?? n.find((e) => e.dur)?.dur;
33
- g.push({
31
+ l.push({
34
32
  kind: "video",
35
33
  key: o,
36
34
  dir: o,
@@ -42,7 +40,7 @@ function o(r) {
42
40
  });
43
41
  } else {
44
42
  let e = n.find((e) => e.path.endsWith(".m4a")) ?? n.find((e) => t(e.type));
45
- e && g.push({
43
+ e && l.push({
46
44
  kind: "audio",
47
45
  key: o,
48
46
  dir: o,
@@ -52,35 +50,33 @@ function o(r) {
52
50
  }
53
51
  continue;
54
52
  }
55
- n(a.type) ? g.push({
53
+ n(a.type) ? l.push({
56
54
  kind: "image",
57
55
  key: a.path,
58
56
  file: a,
59
57
  aspect: i(a, 1)
60
- }) : t(a.type) && g.push({
58
+ }) : t(a.type) && l.push({
61
59
  kind: "audio",
62
60
  key: a.path,
63
61
  file: a,
64
62
  aspect: 3
65
63
  });
66
64
  }
67
- return h > 0 && g.push({
65
+ return !a && r.locked && l.push({
68
66
  kind: "locked",
69
67
  key: "locked",
70
- count: h,
71
- videos: p,
72
- backdrop: m.at(-1),
68
+ backdrop: c.at(-1),
73
69
  aspect: 1
74
- }), g;
70
+ }), l;
75
71
  }
76
- function s(e, t = 0) {
72
+ function o(e, t = 0) {
77
73
  return e[t]?.aspect ?? 1;
78
74
  }
79
- function c(e) {
75
+ function s(e) {
80
76
  let t = Math.max(0, Math.round(e)), n = Math.floor(t / 3600), r = Math.floor(t % 3600 / 60), i = String(t % 60).padStart(2, "0");
81
77
  return n ? `${n}:${String(r).padStart(2, "0")}:${i}` : `${r}:${i}`;
82
78
  }
83
79
  //#endregion
84
- export { c as formatDuration, o as galleryItems, t as isAudioType, n as isImageType, r as isSubtitleType, e as isVideoType, s as stageAspect };
80
+ export { s as formatDuration, a as galleryItems, t as isAudioType, n as isImageType, r as isSubtitleType, e as isVideoType, o as stageAspect };
85
81
 
86
82
  //# sourceMappingURL=gallery.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"gallery.js","names":[],"sources":["../../src/client/gallery.ts"],"sourcesContent":["import type { FileInfo, ReadResult } from \"./generated/wire.js\";\n\nexport type GalleryView = \"carousel\" | \"grid\";\n\nexport interface GalleryMediaItem {\n kind: \"image\" | \"video\" | \"audio\";\n key: string;\n /** An image; a ladder's widest video track (its size and duration) or its audio file. */\n file: FileInfo;\n /** A video or audio ladder's HLS folder from the read's `hls`, e.g. \"hls/\". */\n dir?: string;\n /** Width / height from the read API; a default when unknown. */\n aspect: number;\n}\n\n/** What a viewer without access is missing; `backdrop` is the public preview drawn behind it. */\nexport interface GalleryLockedItem {\n kind: \"locked\";\n key: string;\n count: number;\n videos: number;\n backdrop?: string;\n aspect: number;\n}\n\nexport type GalleryItem = GalleryMediaItem | GalleryLockedItem;\n\nexport const isVideoType = (type?: string) => !!type?.startsWith(\"video/\");\nexport const isAudioType = (type?: string) => !!type?.startsWith(\"audio/\");\nexport const isImageType = (type?: string) => !!type?.startsWith(\"image/\");\n\n/** The stage aspect of an audio slide. */\nexport const AUDIO_ASPECT = 3;\n\n/** Subtitle files are a video's text tracks, not gallery items. */\nexport const isSubtitleType = (type?: string) =>\n [\"text/vtt\", \"application/x-subrip\", \"text/x-ssa\", \"text/x-ass\"].includes(type ?? \"\");\n\nfunction aspectOf(f: FileInfo | undefined, fallback: number) {\n return f?.w && f.h ? f.w / f.h : fallback;\n}\n\nconst parent = (path: string) => path.slice(0, path.lastIndexOf(\"/\") + 1);\n\n/**\n * The read result as gallery items in manifest order. With access: each\n * image, each playable HLS ladder (a folder in `hls`: a video, or an\n * audio-only one) and each other audio file. Without: the item's public\n * previews (the read's `previews`), then one locked item for the rest; an\n * item's private files are all or nothing, so locked files never carry URLs.\n * Other files (plain videos, subtitles, zips) are not items; scope the read\n * with a prefix to choose.\n */\nexport function galleryItems(read: ReadResult | null | undefined): GalleryItem[] {\n if (!read) return [];\n const full = read.access === \"full\";\n const dirs = read.hls ?? [];\n const dirOf = (f: FileInfo) => dirs.find((d) => f.path.startsWith(d));\n // A locked ladder lists its tracks (and sprite): count each folder once.\n const unit = (f: FileInfo) => parent(f.path) || f.path;\n const lockedMedia = read.files.filter((f) => f.locked && (isVideoType(f.type) || isAudioType(f.type)));\n const units = new Set(lockedMedia.map(unit));\n const lockedImages = read.files.filter((f) => f.locked && isImageType(f.type) && !units.has(parent(f.path)));\n const lockedVideos = new Set(lockedMedia.filter((f) => isVideoType(f.type)).map(unit)).size;\n const previews = full ? [] : (read.previews ?? []);\n // Each preview shows one of the locked images.\n const lockedCount = Math.max(lockedImages.length - previews.length, 0) + units.size;\n const items: GalleryItem[] = previews.map((url, i) => ({ kind: \"image\", key: `preview/${i + 1}`, file: { path: `preview/${i + 1}`, type: \"image/webp\", url }, aspect: 1 }));\n const seen = new Set<string>();\n for (const f of read.files) {\n if (f.locked) continue;\n const dir = dirOf(f);\n if (dir) {\n if (seen.has(dir)) continue;\n seen.add(dir);\n const files = read.files.filter((x) => x.path.startsWith(dir));\n const video = files.filter((x) => isVideoType(x.type)).reduce<FileInfo | undefined>((a, x) => ((x.w ?? 0) > (a?.w ?? -1) ? x : a), undefined);\n if (video) {\n const dur = video.dur ?? files.find((x) => x.dur)?.dur;\n items.push({ kind: \"video\", key: dir, dir, file: { ...video, dur }, aspect: aspectOf(video, 16 / 9) });\n } else {\n const audio = files.find((x) => x.path.endsWith(\".m4a\")) ?? files.find((x) => isAudioType(x.type));\n if (audio) items.push({ kind: \"audio\", key: dir, dir, file: audio, aspect: AUDIO_ASPECT });\n }\n continue;\n }\n if (isImageType(f.type)) items.push({ kind: \"image\", key: f.path, file: f, aspect: aspectOf(f, 1) });\n else if (isAudioType(f.type)) items.push({ kind: \"audio\", key: f.path, file: f, aspect: AUDIO_ASPECT });\n }\n if (lockedCount > 0)\n items.push({ kind: \"locked\", key: \"locked\", count: lockedCount, videos: lockedVideos, backdrop: previews.at(-1), aspect: 1 });\n return items;\n}\n\n/** The carousel stage's width / height: the current item's native aspect. */\nexport function stageAspect(items: readonly GalleryItem[], index = 0): number {\n return items[index]?.aspect ?? 1;\n}\n\n/** \"0:42\", \"12:05\", \"1:02:09\". */\nexport function formatDuration(seconds: number): string {\n const s = Math.max(0, Math.round(seconds));\n const h = Math.floor(s / 3600);\n const m = Math.floor((s % 3600) / 60);\n const ss = String(s % 60).padStart(2, \"0\");\n return h ? `${h}:${String(m).padStart(2, \"0\")}:${ss}` : `${m}:${ss}`;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"gallery.js","names":[],"sources":["../../src/client/gallery.ts"],"sourcesContent":["import type { FileInfo, ReadResult } from \"./generated/wire.js\";\n\nexport type GalleryView = \"carousel\" | \"grid\";\n\nexport interface GalleryMediaItem {\n kind: \"image\" | \"video\" | \"audio\";\n key: string;\n /** An image; a ladder's widest video track (its size and duration) or its audio file. */\n file: FileInfo;\n /** A video or audio ladder's HLS folder from the read's `hls`, e.g. \"hls/\". */\n dir?: string;\n /** Width / height from the read API; a default when unknown. */\n aspect: number;\n}\n\n/** What a viewer without access is missing, uncounted; `backdrop` is the public preview drawn behind it. */\nexport interface GalleryLockedItem {\n kind: \"locked\";\n key: string;\n backdrop?: string;\n aspect: number;\n}\n\nexport type GalleryItem = GalleryMediaItem | GalleryLockedItem;\n\nexport const isVideoType = (type?: string) => !!type?.startsWith(\"video/\");\nexport const isAudioType = (type?: string) => !!type?.startsWith(\"audio/\");\nexport const isImageType = (type?: string) => !!type?.startsWith(\"image/\");\n\n/** The stage aspect of an audio slide. */\nexport const AUDIO_ASPECT = 3;\n\n/** Subtitle files are a video's text tracks, not gallery items. */\nexport const isSubtitleType = (type?: string) =>\n [\"text/vtt\", \"application/x-subrip\", \"text/x-ssa\", \"text/x-ass\"].includes(type ?? \"\");\n\nfunction aspectOf(f: FileInfo | undefined, fallback: number) {\n return f?.w && f.h ? f.w / f.h : fallback;\n}\n\n/**\n * The read result as gallery items in manifest order. With access: each\n * image, each playable HLS ladder (a folder in `hls`: a video, or an\n * audio-only one) and each other audio file. Without: the item's public\n * previews (the read's `previews`), then one locked item when the read says\n * it holds locked files; a locked read lists none, so nothing counts them.\n * Other files (plain videos, subtitles, zips) are not items; scope the read\n * with a prefix to choose.\n */\nexport function galleryItems(read: ReadResult | null | undefined): GalleryItem[] {\n if (!read) return [];\n const full = read.access === \"full\";\n const dirs = read.hls ?? [];\n const dirOf = (f: FileInfo) => dirs.find((d) => f.path.startsWith(d));\n const previews = full ? [] : (read.previews ?? []);\n const items: GalleryItem[] = previews.map((url, i) => ({ kind: \"image\", key: `preview/${i + 1}`, file: { path: `preview/${i + 1}`, type: \"image/webp\", url }, aspect: 1 }));\n const seen = new Set<string>();\n for (const f of read.files) {\n const dir = dirOf(f);\n if (dir) {\n if (seen.has(dir)) continue;\n seen.add(dir);\n const files = read.files.filter((x) => x.path.startsWith(dir));\n const video = files.filter((x) => isVideoType(x.type)).reduce<FileInfo | undefined>((a, x) => ((x.w ?? 0) > (a?.w ?? -1) ? x : a), undefined);\n if (video) {\n const dur = video.dur ?? files.find((x) => x.dur)?.dur;\n items.push({ kind: \"video\", key: dir, dir, file: { ...video, dur }, aspect: aspectOf(video, 16 / 9) });\n } else {\n const audio = files.find((x) => x.path.endsWith(\".m4a\")) ?? files.find((x) => isAudioType(x.type));\n if (audio) items.push({ kind: \"audio\", key: dir, dir, file: audio, aspect: AUDIO_ASPECT });\n }\n continue;\n }\n if (isImageType(f.type)) items.push({ kind: \"image\", key: f.path, file: f, aspect: aspectOf(f, 1) });\n else if (isAudioType(f.type)) items.push({ kind: \"audio\", key: f.path, file: f, aspect: AUDIO_ASPECT });\n }\n if (!full && read.locked) items.push({ kind: \"locked\", key: \"locked\", backdrop: previews.at(-1), aspect: 1 });\n return items;\n}\n\n/** The carousel stage's width / height: the current item's native aspect. */\nexport function stageAspect(items: readonly GalleryItem[], index = 0): number {\n return items[index]?.aspect ?? 1;\n}\n\n/** \"0:42\", \"12:05\", \"1:02:09\". */\nexport function formatDuration(seconds: number): string {\n const s = Math.max(0, Math.round(seconds));\n const h = Math.floor(s / 3600);\n const m = Math.floor((s % 3600) / 60);\n const ss = String(s % 60).padStart(2, \"0\");\n return h ? `${h}:${String(m).padStart(2, \"0\")}:${ss}` : `${m}:${ss}`;\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- export type ErrorCode = "animation_not_allowed" | "animation_too_long" | "animation_unsupported" | "checksum_mismatch" | "comment_banned" | "comment_too_long" | "comments_closed" | "comments_locked" | "conflict" | "forbidden" | "gone" | "image_too_large" | "image_too_small" | "image_unreadable" | "incomplete" | "internal_error" | "invalid_request" | "limit_reached" | "moderation_rejected" | "not_configured" | "not_found" | "not_joinable" | "not_uploaded" | "quota_exceeded" | "rate_limited" | "tenant_mismatch" | "too_large" | "too_many_files" | "type_not_allowed" | "unauthorized" | "unavailable" | "upgrade_required" | "video_aspect_unsupported" | "video_over_budget" | "video_too_large" | "video_too_long";
1
+ export type ErrorCode = "animation_not_allowed" | "animation_too_long" | "animation_unsupported" | "checksum_mismatch" | "comment_banned" | "comment_too_long" | "comments_closed" | "comments_locked" | "conflict" | "download_unavailable" | "forbidden" | "gone" | "image_too_large" | "image_too_small" | "image_unreadable" | "incomplete" | "internal_error" | "invalid_request" | "limit_reached" | "moderation_rejected" | "no_download" | "not_configured" | "not_found" | "not_joinable" | "not_uploaded" | "quota_exceeded" | "rate_limited" | "tenant_mismatch" | "too_large" | "too_many_files" | "type_not_allowed" | "unauthorized" | "unavailable" | "upgrade_required" | "video_aspect_unsupported" | "video_over_budget" | "video_too_large" | "video_too_long";
2
2
  export declare const CONTENTKIT_ERROR_CODES: Readonly<Record<ErrorCode, {
3
3
  status: number;
4
4
  meaning: string;
@@ -36,6 +36,10 @@ var e = {
36
36
  status: 409,
37
37
  meaning: "A concurrent change, a path or slug already taken, or an operation id already used for another commit."
38
38
  },
39
+ download_unavailable: {
40
+ status: 403,
41
+ meaning: "The host's download policy refuses this download now: `reason` is its code, `available_at` when it opens if a matter of time. Nothing was charged."
42
+ },
39
43
  forbidden: {
40
44
  status: 403,
41
45
  meaning: "The actor may not do this."
@@ -76,6 +80,10 @@ var e = {
76
80
  status: 422,
77
81
  meaning: "The moderator refused the text; `error` says why."
78
82
  },
83
+ no_download: {
84
+ status: 409,
85
+ meaning: "The version has no file its kind's download serves: nothing uploaded, or its upload failed or was dropped."
86
+ },
79
87
  not_configured: {
80
88
  status: 501,
81
89
  meaning: "The capability needs a port the host did not configure; retrying does not help."
@@ -122,7 +130,7 @@ var e = {
122
130
  },
123
131
  unavailable: {
124
132
  status: 503,
125
- meaning: "The host's auth or media storage cannot be reached, or a commit's recovery is pending; retry."
133
+ meaning: "The host's auth, media storage or signal plane cannot be reached, or a commit's recovery is pending; retry."
126
134
  },
127
135
  upgrade_required: {
128
136
  status: 503,
@@ -1 +1 @@
1
- {"version":3,"file":"error-codes.js","names":[],"sources":["../../../src/client/generated/error-codes.ts"],"sourcesContent":["// Generated by `go generate ./internal/contract` from ContentKit's error-code registry. Do not edit.\n\nexport type ErrorCode =\n | \"animation_not_allowed\"\n | \"animation_too_long\"\n | \"animation_unsupported\"\n | \"checksum_mismatch\"\n | \"comment_banned\"\n | \"comment_too_long\"\n | \"comments_closed\"\n | \"comments_locked\"\n | \"conflict\"\n | \"forbidden\"\n | \"gone\"\n | \"image_too_large\"\n | \"image_too_small\"\n | \"image_unreadable\"\n | \"incomplete\"\n | \"internal_error\"\n | \"invalid_request\"\n | \"limit_reached\"\n | \"moderation_rejected\"\n | \"not_configured\"\n | \"not_found\"\n | \"not_joinable\"\n | \"not_uploaded\"\n | \"quota_exceeded\"\n | \"rate_limited\"\n | \"tenant_mismatch\"\n | \"too_large\"\n | \"too_many_files\"\n | \"type_not_allowed\"\n | \"unauthorized\"\n | \"unavailable\"\n | \"upgrade_required\"\n | \"video_aspect_unsupported\"\n | \"video_over_budget\"\n | \"video_too_large\"\n | \"video_too_long\"\n;\n\n// Each code's HTTP status and meaning. A message on the wire is for people;\n// classify by code.\nexport const CONTENTKIT_ERROR_CODES: Readonly<Record<ErrorCode, { status: number; meaning: string }>> = {\n animation_not_allowed: { status: 422, meaning: \"An animated image where the upload path refuses animation.\" },\n animation_too_long: { status: 422, meaning: \"The animation has more frames or seconds than the processor allows.\" },\n animation_unsupported: { status: 415, meaning: \"An AVIF or HEIF image sequence, which is decoded as one frame.\" },\n checksum_mismatch: { status: 422, meaning: \"The stored bytes differ from the declared SHA-256.\" },\n comment_banned: { status: 403, meaning: \"The actor is banned from commenting on this target; `ban` says the scope, the reason and when it ends.\" },\n comment_too_long: { status: 422, meaning: \"The comment is longer than the site allows; `details.max` is the limit in characters.\" },\n comments_closed: { status: 403, meaning: \"The target's comments are closed or hidden: existing ones may show, new ones and edits are refused.\" },\n comments_locked: { status: 403, meaning: \"The actor can't open the content (or the comment's version), so its comments take no writes from them; reads withhold them.\" },\n conflict: { status: 409, meaning: \"A concurrent change, a path or slug already taken, or an operation id already used for another commit.\" },\n forbidden: { status: 403, meaning: \"The actor may not do this.\" },\n gone: { status: 410, meaning: \"The content was removed.\" },\n image_too_large: { status: 413, meaning: \"The image has more pixels or frames than the processor decodes.\" },\n image_too_small: { status: 422, meaning: \"The edited image is narrower than its public preset's minimum width.\" },\n image_unreadable: { status: 422, meaning: \"The file is not a decodable image of its declared type.\" },\n incomplete: { status: 409, meaning: \"A multipart upload is missing parts.\" },\n internal_error: { status: 500, meaning: \"A server fault; the cause is in the server log.\" },\n invalid_request: { status: 400, meaning: \"The request is malformed: its body, a query parameter or a path value.\" },\n limit_reached: { status: 409, meaning: \"The owner already has as many groups of the kind as the site allows (max_per_owner).\" },\n moderation_rejected: { status: 422, meaning: \"The moderator refused the text; `error` says why.\" },\n not_configured: { status: 501, meaning: \"The capability needs a port the host did not configure; retrying does not help.\" },\n not_found: { status: 404, meaning: \"Nothing by that name, or nothing the actor may see.\" },\n not_joinable: { status: 409, meaning: \"The group has no free offer to join: it sells its membership, or nothing.\" },\n not_uploaded: { status: 409, meaning: \"A commit names an upload that has not landed; `blobs` lists the ones to upload again.\" },\n quota_exceeded: { status: 413, meaning: \"The uploader's storage quota is used up.\" },\n rate_limited: { status: 429, meaning: \"Too many requests; retry after `retry_after` seconds (also the Retry-After header).\" },\n tenant_mismatch: { status: 500, meaning: \"A host port answered with another tenant's data: a configuration fault.\" },\n too_large: { status: 413, meaning: \"The file is larger than its upload path allows; `details` has `size` and `max_bytes`.\" },\n too_many_files: { status: 409, meaning: \"The commit would put more files in an upload path, or the item, than allowed; `details.max` is the limit.\" },\n type_not_allowed: { status: 415, meaning: \"The file type is not allowed in the upload path; `details.allowed` lists the types.\" },\n unauthorized: { status: 401, meaning: \"The request needs a valid credential: it has none where the route needs one, or one that is expired, revoked or invalid. WWW-Authenticate says which.\" },\n unavailable: { status: 503, meaning: \"The host's auth or media storage cannot be reached, or a commit's recovery is pending; retry.\" },\n upgrade_required: { status: 503, meaning: \"The media item was stored before v0.68 and is served once the host's media upgrade (contentkit_media_upgrade) has converted it.\" },\n video_aspect_unsupported: { status: 422, meaning: \"The video's display aspect is outside what its upload path accepts; `details` has `min_aspect` and `max_aspect` (width/height).\" },\n video_over_budget: { status: 422, meaning: \"The planned encode costs more than its upload path allows, or the source averages under a frame a second.\" },\n video_too_large: { status: 422, meaning: \"The video's frames are larger than its upload path allows.\" },\n video_too_long: { status: 422, meaning: \"The video or audio runs longer than its upload path allows.\" },\n};\n"],"mappings":";AA2CA,IAAa,IAA2F;CACtG,uBAAuB;EAAE,QAAQ;EAAK,SAAS;CAA6D;CAC5G,oBAAoB;EAAE,QAAQ;EAAK,SAAS;CAAsE;CAClH,uBAAuB;EAAE,QAAQ;EAAK,SAAS;CAAiE;CAChH,mBAAmB;EAAE,QAAQ;EAAK,SAAS;CAAqD;CAChG,gBAAgB;EAAE,QAAQ;EAAK,SAAS;CAAyG;CACjJ,kBAAkB;EAAE,QAAQ;EAAK,SAAS;CAAwF;CAClI,iBAAiB;EAAE,QAAQ;EAAK,SAAS;CAAsG;CAC/I,iBAAiB;EAAE,QAAQ;EAAK,SAAS;CAA8H;CACvK,UAAU;EAAE,QAAQ;EAAK,SAAS;CAAyG;CAC3I,WAAW;EAAE,QAAQ;EAAK,SAAS;CAA6B;CAChE,MAAM;EAAE,QAAQ;EAAK,SAAS;CAA2B;CACzD,iBAAiB;EAAE,QAAQ;EAAK,SAAS;CAAkE;CAC3G,iBAAiB;EAAE,QAAQ;EAAK,SAAS;CAAuE;CAChH,kBAAkB;EAAE,QAAQ;EAAK,SAAS;CAA0D;CACpG,YAAY;EAAE,QAAQ;EAAK,SAAS;CAAuC;CAC3E,gBAAgB;EAAE,QAAQ;EAAK,SAAS;CAAkD;CAC1F,iBAAiB;EAAE,QAAQ;EAAK,SAAS;CAAyE;CAClH,eAAe;EAAE,QAAQ;EAAK,SAAS;CAAuF;CAC9H,qBAAqB;EAAE,QAAQ;EAAK,SAAS;CAAoD;CACjG,gBAAgB;EAAE,QAAQ;EAAK,SAAS;CAAkF;CAC1H,WAAW;EAAE,QAAQ;EAAK,SAAS;CAAsD;CACzF,cAAc;EAAE,QAAQ;EAAK,SAAS;CAA4E;CAClH,cAAc;EAAE,QAAQ;EAAK,SAAS;CAAwF;CAC9H,gBAAgB;EAAE,QAAQ;EAAK,SAAS;CAA2C;CACnF,cAAc;EAAE,QAAQ;EAAK,SAAS;CAAsF;CAC5H,iBAAiB;EAAE,QAAQ;EAAK,SAAS;CAA0E;CACnH,WAAW;EAAE,QAAQ;EAAK,SAAS;CAAwF;CAC3H,gBAAgB;EAAE,QAAQ;EAAK,SAAS;CAA4G;CACpJ,kBAAkB;EAAE,QAAQ;EAAK,SAAS;CAAsF;CAChI,cAAc;EAAE,QAAQ;EAAK,SAAS;CAAwJ;CAC9L,aAAa;EAAE,QAAQ;EAAK,SAAS;CAAgG;CACrI,kBAAkB;EAAE,QAAQ;EAAK,SAAS;CAAkI;CAC5K,0BAA0B;EAAE,QAAQ;EAAK,SAAS;CAAkI;CACpL,mBAAmB;EAAE,QAAQ;EAAK,SAAS;CAA4G;CACvJ,iBAAiB;EAAE,QAAQ;EAAK,SAAS;CAA6D;CACtG,gBAAgB;EAAE,QAAQ;EAAK,SAAS;CAA8D;AACxG"}
1
+ {"version":3,"file":"error-codes.js","names":[],"sources":["../../../src/client/generated/error-codes.ts"],"sourcesContent":["// Generated by `go generate ./internal/contract` from ContentKit's error-code registry. Do not edit.\n\nexport type ErrorCode =\n | \"animation_not_allowed\"\n | \"animation_too_long\"\n | \"animation_unsupported\"\n | \"checksum_mismatch\"\n | \"comment_banned\"\n | \"comment_too_long\"\n | \"comments_closed\"\n | \"comments_locked\"\n | \"conflict\"\n | \"download_unavailable\"\n | \"forbidden\"\n | \"gone\"\n | \"image_too_large\"\n | \"image_too_small\"\n | \"image_unreadable\"\n | \"incomplete\"\n | \"internal_error\"\n | \"invalid_request\"\n | \"limit_reached\"\n | \"moderation_rejected\"\n | \"no_download\"\n | \"not_configured\"\n | \"not_found\"\n | \"not_joinable\"\n | \"not_uploaded\"\n | \"quota_exceeded\"\n | \"rate_limited\"\n | \"tenant_mismatch\"\n | \"too_large\"\n | \"too_many_files\"\n | \"type_not_allowed\"\n | \"unauthorized\"\n | \"unavailable\"\n | \"upgrade_required\"\n | \"video_aspect_unsupported\"\n | \"video_over_budget\"\n | \"video_too_large\"\n | \"video_too_long\"\n;\n\n// Each code's HTTP status and meaning. A message on the wire is for people;\n// classify by code.\nexport const CONTENTKIT_ERROR_CODES: Readonly<Record<ErrorCode, { status: number; meaning: string }>> = {\n animation_not_allowed: { status: 422, meaning: \"An animated image where the upload path refuses animation.\" },\n animation_too_long: { status: 422, meaning: \"The animation has more frames or seconds than the processor allows.\" },\n animation_unsupported: { status: 415, meaning: \"An AVIF or HEIF image sequence, which is decoded as one frame.\" },\n checksum_mismatch: { status: 422, meaning: \"The stored bytes differ from the declared SHA-256.\" },\n comment_banned: { status: 403, meaning: \"The actor is banned from commenting on this target; `ban` says the scope, the reason and when it ends.\" },\n comment_too_long: { status: 422, meaning: \"The comment is longer than the site allows; `details.max` is the limit in characters.\" },\n comments_closed: { status: 403, meaning: \"The target's comments are closed or hidden: existing ones may show, new ones and edits are refused.\" },\n comments_locked: { status: 403, meaning: \"The actor can't open the content (or the comment's version), so its comments take no writes from them; reads withhold them.\" },\n conflict: { status: 409, meaning: \"A concurrent change, a path or slug already taken, or an operation id already used for another commit.\" },\n download_unavailable: { status: 403, meaning: \"The host's download policy refuses this download now: `reason` is its code, `available_at` when it opens if a matter of time. Nothing was charged.\" },\n forbidden: { status: 403, meaning: \"The actor may not do this.\" },\n gone: { status: 410, meaning: \"The content was removed.\" },\n image_too_large: { status: 413, meaning: \"The image has more pixels or frames than the processor decodes.\" },\n image_too_small: { status: 422, meaning: \"The edited image is narrower than its public preset's minimum width.\" },\n image_unreadable: { status: 422, meaning: \"The file is not a decodable image of its declared type.\" },\n incomplete: { status: 409, meaning: \"A multipart upload is missing parts.\" },\n internal_error: { status: 500, meaning: \"A server fault; the cause is in the server log.\" },\n invalid_request: { status: 400, meaning: \"The request is malformed: its body, a query parameter or a path value.\" },\n limit_reached: { status: 409, meaning: \"The owner already has as many groups of the kind as the site allows (max_per_owner).\" },\n moderation_rejected: { status: 422, meaning: \"The moderator refused the text; `error` says why.\" },\n no_download: { status: 409, meaning: \"The version has no file its kind's download serves: nothing uploaded, or its upload failed or was dropped.\" },\n not_configured: { status: 501, meaning: \"The capability needs a port the host did not configure; retrying does not help.\" },\n not_found: { status: 404, meaning: \"Nothing by that name, or nothing the actor may see.\" },\n not_joinable: { status: 409, meaning: \"The group has no free offer to join: it sells its membership, or nothing.\" },\n not_uploaded: { status: 409, meaning: \"A commit names an upload that has not landed; `blobs` lists the ones to upload again.\" },\n quota_exceeded: { status: 413, meaning: \"The uploader's storage quota is used up.\" },\n rate_limited: { status: 429, meaning: \"Too many requests; retry after `retry_after` seconds (also the Retry-After header).\" },\n tenant_mismatch: { status: 500, meaning: \"A host port answered with another tenant's data: a configuration fault.\" },\n too_large: { status: 413, meaning: \"The file is larger than its upload path allows; `details` has `size` and `max_bytes`.\" },\n too_many_files: { status: 409, meaning: \"The commit would put more files in an upload path, or the item, than allowed; `details.max` is the limit.\" },\n type_not_allowed: { status: 415, meaning: \"The file type is not allowed in the upload path; `details.allowed` lists the types.\" },\n unauthorized: { status: 401, meaning: \"The request needs a valid credential: it has none where the route needs one, or one that is expired, revoked or invalid. WWW-Authenticate says which.\" },\n unavailable: { status: 503, meaning: \"The host's auth, media storage or signal plane cannot be reached, or a commit's recovery is pending; retry.\" },\n upgrade_required: { status: 503, meaning: \"The media item was stored before v0.68 and is served once the host's media upgrade (contentkit_media_upgrade) has converted it.\" },\n video_aspect_unsupported: { status: 422, meaning: \"The video's display aspect is outside what its upload path accepts; `details` has `min_aspect` and `max_aspect` (width/height).\" },\n video_over_budget: { status: 422, meaning: \"The planned encode costs more than its upload path allows, or the source averages under a frame a second.\" },\n video_too_large: { status: 422, meaning: \"The video's frames are larger than its upload path allows.\" },\n video_too_long: { status: 422, meaning: \"The video or audio runs longer than its upload path allows.\" },\n};\n"],"mappings":";AA6CA,IAAa,IAA2F;CACtG,uBAAuB;EAAE,QAAQ;EAAK,SAAS;CAA6D;CAC5G,oBAAoB;EAAE,QAAQ;EAAK,SAAS;CAAsE;CAClH,uBAAuB;EAAE,QAAQ;EAAK,SAAS;CAAiE;CAChH,mBAAmB;EAAE,QAAQ;EAAK,SAAS;CAAqD;CAChG,gBAAgB;EAAE,QAAQ;EAAK,SAAS;CAAyG;CACjJ,kBAAkB;EAAE,QAAQ;EAAK,SAAS;CAAwF;CAClI,iBAAiB;EAAE,QAAQ;EAAK,SAAS;CAAsG;CAC/I,iBAAiB;EAAE,QAAQ;EAAK,SAAS;CAA8H;CACvK,UAAU;EAAE,QAAQ;EAAK,SAAS;CAAyG;CAC3I,sBAAsB;EAAE,QAAQ;EAAK,SAAS;CAAqJ;CACnM,WAAW;EAAE,QAAQ;EAAK,SAAS;CAA6B;CAChE,MAAM;EAAE,QAAQ;EAAK,SAAS;CAA2B;CACzD,iBAAiB;EAAE,QAAQ;EAAK,SAAS;CAAkE;CAC3G,iBAAiB;EAAE,QAAQ;EAAK,SAAS;CAAuE;CAChH,kBAAkB;EAAE,QAAQ;EAAK,SAAS;CAA0D;CACpG,YAAY;EAAE,QAAQ;EAAK,SAAS;CAAuC;CAC3E,gBAAgB;EAAE,QAAQ;EAAK,SAAS;CAAkD;CAC1F,iBAAiB;EAAE,QAAQ;EAAK,SAAS;CAAyE;CAClH,eAAe;EAAE,QAAQ;EAAK,SAAS;CAAuF;CAC9H,qBAAqB;EAAE,QAAQ;EAAK,SAAS;CAAoD;CACjG,aAAa;EAAE,QAAQ;EAAK,SAAS;CAA6G;CAClJ,gBAAgB;EAAE,QAAQ;EAAK,SAAS;CAAkF;CAC1H,WAAW;EAAE,QAAQ;EAAK,SAAS;CAAsD;CACzF,cAAc;EAAE,QAAQ;EAAK,SAAS;CAA4E;CAClH,cAAc;EAAE,QAAQ;EAAK,SAAS;CAAwF;CAC9H,gBAAgB;EAAE,QAAQ;EAAK,SAAS;CAA2C;CACnF,cAAc;EAAE,QAAQ;EAAK,SAAS;CAAsF;CAC5H,iBAAiB;EAAE,QAAQ;EAAK,SAAS;CAA0E;CACnH,WAAW;EAAE,QAAQ;EAAK,SAAS;CAAwF;CAC3H,gBAAgB;EAAE,QAAQ;EAAK,SAAS;CAA4G;CACpJ,kBAAkB;EAAE,QAAQ;EAAK,SAAS;CAAsF;CAChI,cAAc;EAAE,QAAQ;EAAK,SAAS;CAAwJ;CAC9L,aAAa;EAAE,QAAQ;EAAK,SAAS;CAA8G;CACnJ,kBAAkB;EAAE,QAAQ;EAAK,SAAS;CAAkI;CAC5K,0BAA0B;EAAE,QAAQ;EAAK,SAAS;CAAkI;CACpL,mBAAmB;EAAE,QAAQ;EAAK,SAAS;CAA4G;CACvJ,iBAAiB;EAAE,QAAQ;EAAK,SAAS;CAA6D;CACtG,gBAAgB;EAAE,QAAQ;EAAK,SAAS;CAA8D;AACxG"}
@@ -1284,7 +1284,7 @@ export declare const CONTENTKIT_ROUTES: readonly [{
1284
1284
  readonly path: "/{code}";
1285
1285
  readonly auth: "open";
1286
1286
  readonly permission: null;
1287
- readonly query: readonly ["lang"];
1287
+ readonly query: readonly ["lang", "v"];
1288
1288
  readonly request: null;
1289
1289
  readonly responses: {
1290
1290
  readonly 200: "Resolved";
@@ -1665,10 +1665,23 @@ export declare const CONTENTKIT_ROUTES: readonly [{
1665
1665
  readonly query: readonly [];
1666
1666
  readonly request: null;
1667
1667
  readonly responses: {
1668
- readonly 200: "application/zip";
1668
+ readonly 200: "FileDownload";
1669
1669
  readonly 202: "Pending";
1670
1670
  };
1671
- readonly errors: readonly ["forbidden", "rate_limited"];
1671
+ readonly errors: readonly ["forbidden", "download_unavailable", "rate_limited", "no_download"];
1672
+ readonly errorSets: readonly ["module:versions", "auth", "request"];
1673
+ }, {
1674
+ readonly method: "GET";
1675
+ readonly module: "versions";
1676
+ readonly path: "/contents/{id}/versions/{version}/archive";
1677
+ readonly auth: "public";
1678
+ readonly permission: null;
1679
+ readonly query: readonly ["for", "mark", "ticket"];
1680
+ readonly request: null;
1681
+ readonly responses: {
1682
+ readonly 200: "application/zip";
1683
+ };
1684
+ readonly errors: readonly [];
1672
1685
  readonly errorSets: readonly ["module:versions", "auth", "request"];
1673
1686
  }, {
1674
1687
  readonly method: "PUT";
@@ -2086,5 +2099,18 @@ export declare const CONTENTKIT_ROUTES: readonly [{
2086
2099
  };
2087
2100
  readonly errors: readonly [];
2088
2101
  readonly errorSets: readonly ["module:import", "auth", "request"];
2102
+ }, {
2103
+ readonly method: "POST";
2104
+ readonly module: "import";
2105
+ readonly path: "/import/external-ids";
2106
+ readonly auth: "staff";
2107
+ readonly permission: "root:import:write";
2108
+ readonly query: readonly [];
2109
+ readonly request: "ExternalIDsQuery";
2110
+ readonly responses: {
2111
+ readonly 200: "ExternalIDs";
2112
+ };
2113
+ readonly errors: readonly [];
2114
+ readonly errorSets: readonly ["module:import", "auth", "request"];
2089
2115
  }];
2090
2116
  export declare const CONTENTKIT_ERROR_SETS: Readonly<Record<string, readonly string[]>>;
@@ -1809,7 +1809,7 @@ var e = {
1809
1809
  path: "/{code}",
1810
1810
  auth: "open",
1811
1811
  permission: null,
1812
- query: ["lang"],
1812
+ query: ["lang", "v"],
1813
1813
  request: null,
1814
1814
  responses: { 200: "Resolved" },
1815
1815
  errors: ["gone", "not_found"],
@@ -2301,10 +2301,35 @@ var e = {
2301
2301
  query: [],
2302
2302
  request: null,
2303
2303
  responses: {
2304
- 200: "application/zip",
2304
+ 200: "FileDownload",
2305
2305
  202: "Pending"
2306
2306
  },
2307
- errors: ["forbidden", "rate_limited"],
2307
+ errors: [
2308
+ "forbidden",
2309
+ "download_unavailable",
2310
+ "rate_limited",
2311
+ "no_download"
2312
+ ],
2313
+ errorSets: [
2314
+ "module:versions",
2315
+ "auth",
2316
+ "request"
2317
+ ]
2318
+ },
2319
+ {
2320
+ method: "GET",
2321
+ module: "versions",
2322
+ path: "/contents/{id}/versions/{version}/archive",
2323
+ auth: "public",
2324
+ permission: null,
2325
+ query: [
2326
+ "for",
2327
+ "mark",
2328
+ "ticket"
2329
+ ],
2330
+ request: null,
2331
+ responses: { 200: "application/zip" },
2332
+ errors: [],
2308
2333
  errorSets: [
2309
2334
  "module:versions",
2310
2335
  "auth",
@@ -2969,6 +2994,22 @@ var e = {
2969
2994
  "auth",
2970
2995
  "request"
2971
2996
  ]
2997
+ },
2998
+ {
2999
+ method: "POST",
3000
+ module: "import",
3001
+ path: "/import/external-ids",
3002
+ auth: "staff",
3003
+ permission: "root:import:write",
3004
+ query: [],
3005
+ request: "ExternalIDsQuery",
3006
+ responses: { 200: "ExternalIDs" },
3007
+ errors: [],
3008
+ errorSets: [
3009
+ "module:import",
3010
+ "auth",
3011
+ "request"
3012
+ ]
2972
3013
  }
2973
3014
  ];
2974
3015
  //#endregion