@kernhq/module-quire 0.13.0 → 0.13.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.
@@ -32,6 +32,22 @@ import {
32
32
  } from './properties.js'
33
33
 
34
34
  const ws = z.object({ workspaceId: WorkspaceId })
35
+
36
+ /**
37
+ * What names the workspace in a **public** URL: its id or its slug.
38
+ *
39
+ * The address the share dialog copies is `/p/<workspace-slug>/<publication-slug>/`, because a uuid
40
+ * in a link somebody sends a colleague is a receipt rather than an address. Every `public.*`
41
+ * procedure still needs an id before it touches `mod_quire` — anonymous means no principal, not no
42
+ * tenant — so the slug is resolved at the one anonymous entry point and everything downstream is
43
+ * unchanged. Widened here rather than parsed in the handler because a `z.uuid()` rejects the slug
44
+ * before any handler runs, which is how this shipped answering 404 for its own published URLs.
45
+ */
46
+ const WorkspaceSegment = z
47
+ .string()
48
+ .min(1)
49
+ .max(64)
50
+ .regex(/^[0-9a-zA-Z][0-9a-zA-Z-]*$/, 'not a workspace id or slug')
35
51
  const t = (...tags: string[]) => ({ tags })
36
52
 
37
53
  /** The page fields a shortcut row draws, so a sidebar is one request rather than one per entry. */
@@ -795,7 +811,7 @@ export const quireContract = {
795
811
  .route({ method: 'GET', path: '/public/{workspaceId}/{slug}', ...t('public') })
796
812
  .input(
797
813
  z.object({
798
- workspaceId: WorkspaceId,
814
+ workspaceId: WorkspaceSegment,
799
815
  slug: Publication.shape.slug,
800
816
  token: z.string().max(4096).nullable().default(null),
801
817
  }),
@@ -811,7 +827,7 @@ export const quireContract = {
811
827
  .route({ method: 'GET', path: '/public/{workspaceId}/{slug}/page', ...t('public') })
812
828
  .input(
813
829
  z.object({
814
- workspaceId: WorkspaceId,
830
+ workspaceId: WorkspaceSegment,
815
831
  slug: Publication.shape.slug,
816
832
  /** '' is the front page */
817
833
  path: z.string().max(1024).default(''),
@@ -832,7 +848,7 @@ export const quireContract = {
832
848
  .route({ method: 'GET', path: '/public/{workspaceId}/{slug}/search', ...t('public') })
833
849
  .input(
834
850
  z.object({
835
- workspaceId: WorkspaceId,
851
+ workspaceId: WorkspaceSegment,
836
852
  slug: Publication.shape.slug,
837
853
  q: z.string().min(2).max(200),
838
854
  limit: z.number().int().min(1).max(50).default(20),
@@ -846,7 +862,7 @@ export const quireContract = {
846
862
  */
847
863
  sitemap: baseContract
848
864
  .route({ method: 'GET', path: '/public/{workspaceId}/{slug}/sitemap', ...t('public') })
849
- .input(z.object({ workspaceId: WorkspaceId, slug: Publication.shape.slug }))
865
+ .input(z.object({ workspaceId: WorkspaceSegment, slug: Publication.shape.slug }))
850
866
  .output(z.object({ entries: z.array(PublicSitemapEntry) })),
851
867
  /**
852
868
  * The one procedure here that never distinguishes one slug from another.
@@ -859,7 +875,7 @@ export const quireContract = {
859
875
  */
860
876
  robots: baseContract
861
877
  .route({ method: 'GET', path: '/public/{workspaceId}/{slug}/robots', ...t('public') })
862
- .input(z.object({ workspaceId: WorkspaceId, slug: Publication.shape.slug }))
878
+ .input(z.object({ workspaceId: WorkspaceSegment, slug: Publication.shape.slug }))
863
879
  .output(z.object({ indexable: z.boolean(), sitemapPath: z.string().nullable() })),
864
880
  /**
865
881
  * The bytes of one picture on a published page.
@@ -879,7 +895,7 @@ export const quireContract = {
879
895
  .route({ method: 'GET', path: '/public/{workspaceId}/{slug}/asset', ...t('public') })
880
896
  .input(
881
897
  z.object({
882
- workspaceId: WorkspaceId,
898
+ workspaceId: WorkspaceSegment,
883
899
  slug: Publication.shape.slug,
884
900
  asset: z.string().min(1).max(2048),
885
901
  token: z.string().max(4096).nullable().default(null),
@@ -891,7 +907,7 @@ export const quireContract = {
891
907
  .route({ method: 'POST', path: '/public/{workspaceId}/{slug}/unlock', ...t('public') })
892
908
  .input(
893
909
  z.object({
894
- workspaceId: WorkspaceId,
910
+ workspaceId: WorkspaceSegment,
895
911
  slug: Publication.shape.slug,
896
912
  password: z.string().min(1).max(200),
897
913
  }),