@pramen/cms 0.0.16 → 0.0.17

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.
package/dist/index.d.ts CHANGED
@@ -557,6 +557,28 @@ export declare function createCmsHandlers(opts?: CmsHandlerOpts): {
557
557
  fieldsSchema?: FieldDefinition[];
558
558
  defaultBlocks?: DefaultBlockDefinition[];
559
559
  }, Record<string, unknown>>;
560
+ /** Update a block type (found by `id` or `slug`). `slug` is the stable key and is
561
+ * NOT mutable; only the metadata + `fieldsSchema` are patched. Editor-gated. This is
562
+ * what lets a schema evolve (e.g. a field text → date) without recreating the type. */
563
+ updateBlockType: import("@pramen/server").Handler<{
564
+ id?: string;
565
+ slug?: string;
566
+ name?: string;
567
+ fieldsSchema?: FieldDefinition[];
568
+ icon?: string | null;
569
+ category?: string | null;
570
+ description?: string | null;
571
+ }, Record<string, unknown> | undefined>;
572
+ /** Update a content type (found by `id` or `slug`). `slug` is the stable key and is
573
+ * NOT mutable; `name`/`regions`/`fieldsSchema`/`defaultBlocks` are patched. Editor-gated. */
574
+ updateContentType: import("@pramen/server").Handler<{
575
+ id?: string;
576
+ slug?: string;
577
+ name?: string;
578
+ regions?: RegionDefinition[];
579
+ fieldsSchema?: FieldDefinition[];
580
+ defaultBlocks?: DefaultBlockDefinition[];
581
+ }, Record<string, unknown> | undefined>;
560
582
  /** Mint a signed upload URL for a media blob (keyed under the tenant's `media/`
561
583
  * prefix so the public /media route can serve it). The client PUTs the bytes to
562
584
  * `url`, then calls `createMedia` with the returned `ref`. */
@@ -788,6 +810,28 @@ export declare const cmsHandlers: {
788
810
  fieldsSchema?: FieldDefinition[];
789
811
  defaultBlocks?: DefaultBlockDefinition[];
790
812
  }, Record<string, unknown>>;
813
+ /** Update a block type (found by `id` or `slug`). `slug` is the stable key and is
814
+ * NOT mutable; only the metadata + `fieldsSchema` are patched. Editor-gated. This is
815
+ * what lets a schema evolve (e.g. a field text → date) without recreating the type. */
816
+ updateBlockType: import("@pramen/server").Handler<{
817
+ id?: string;
818
+ slug?: string;
819
+ name?: string;
820
+ fieldsSchema?: FieldDefinition[];
821
+ icon?: string | null;
822
+ category?: string | null;
823
+ description?: string | null;
824
+ }, Record<string, unknown> | undefined>;
825
+ /** Update a content type (found by `id` or `slug`). `slug` is the stable key and is
826
+ * NOT mutable; `name`/`regions`/`fieldsSchema`/`defaultBlocks` are patched. Editor-gated. */
827
+ updateContentType: import("@pramen/server").Handler<{
828
+ id?: string;
829
+ slug?: string;
830
+ name?: string;
831
+ regions?: RegionDefinition[];
832
+ fieldsSchema?: FieldDefinition[];
833
+ defaultBlocks?: DefaultBlockDefinition[];
834
+ }, Record<string, unknown> | undefined>;
791
835
  /** Mint a signed upload URL for a media blob (keyed under the tenant's `media/`
792
836
  * prefix so the public /media route can serve it). The client PUTs the bytes to
793
837
  * `url`, then calls `createMedia` with the returned `ref`. */
package/dist/index.js CHANGED
@@ -571,6 +571,55 @@ export function createCmsHandlers(opts = {}) {
571
571
  return o;
572
572
  },
573
573
  }),
574
+ /** Update a block type (found by `id` or `slug`). `slug` is the stable key and is
575
+ * NOT mutable; only the metadata + `fieldsSchema` are patched. Editor-gated. This is
576
+ * what lets a schema evolve (e.g. a field text → date) without recreating the type. */
577
+ updateBlockType: mutation(async (ctx, input) => {
578
+ const db = cdb(ctx);
579
+ const rows = await db.find({ from: "cms_block_types", where: input.id ? { id: input.id } : { slug: input.slug }, limit: 1 });
580
+ const row = rows[0];
581
+ if (!row)
582
+ throw notFound("block type");
583
+ const patch = {};
584
+ for (const k of ["name", "fieldsSchema", "icon", "category", "description"]) {
585
+ if (k in input)
586
+ patch[k] = input[k];
587
+ }
588
+ return db.update("cms_block_types", String(row.id), patch);
589
+ }, {
590
+ ...editor,
591
+ input: (raw) => {
592
+ const o = asObj(raw);
593
+ if (typeof o.id !== "string" && typeof o.slug !== "string")
594
+ throw new BadRequest("id or slug is required");
595
+ return o;
596
+ },
597
+ }),
598
+ /** Update a content type (found by `id` or `slug`). `slug` is the stable key and is
599
+ * NOT mutable; `name`/`regions`/`fieldsSchema`/`defaultBlocks` are patched. Editor-gated. */
600
+ updateContentType: mutation(async (ctx, input) => {
601
+ const db = cdb(ctx);
602
+ if ("regions" in input && (!Array.isArray(input.regions) || input.regions.length === 0))
603
+ throw new BadRequest("at least one region is required");
604
+ const rows = await db.find({ from: "cms_content_types", where: input.id ? { id: input.id } : { slug: input.slug }, limit: 1 });
605
+ const row = rows[0];
606
+ if (!row)
607
+ throw notFound("content type");
608
+ const patch = {};
609
+ for (const k of ["name", "regions", "fieldsSchema", "defaultBlocks"]) {
610
+ if (k in input)
611
+ patch[k] = input[k];
612
+ }
613
+ return db.update("cms_content_types", String(row.id), patch);
614
+ }, {
615
+ ...editor,
616
+ input: (raw) => {
617
+ const o = asObj(raw);
618
+ if (typeof o.id !== "string" && typeof o.slug !== "string")
619
+ throw new BadRequest("id or slug is required");
620
+ return o;
621
+ },
622
+ }),
574
623
  // ---- media library ----
575
624
  /** Mint a signed upload URL for a media blob (keyed under the tenant's `media/`
576
625
  * prefix so the public /media route can serve it). The client PUTs the bytes to
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pramen/cms",
3
- "version": "0.0.16",
3
+ "version": "0.0.17",
4
4
  "description": "Optional block/page builder for pramen — Drupal-Paragraphs-style typed blocks in named regions, reusable blocks, scheduled publishing, built entirely from pramen primitives.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -41,7 +41,7 @@
41
41
  "access": "public"
42
42
  },
43
43
  "dependencies": {
44
- "@pramen/server": "0.0.16"
44
+ "@pramen/server": "0.0.17"
45
45
  },
46
46
  "peerDependencies": {
47
47
  "react": ">=18"
package/src/index.ts CHANGED
@@ -827,6 +827,50 @@ export function createCmsHandlers(opts: CmsHandlerOpts = {}) {
827
827
  },
828
828
  }),
829
829
 
830
+ /** Update a block type (found by `id` or `slug`). `slug` is the stable key and is
831
+ * NOT mutable; only the metadata + `fieldsSchema` are patched. Editor-gated. This is
832
+ * what lets a schema evolve (e.g. a field text → date) without recreating the type. */
833
+ updateBlockType: mutation(async (ctx, input: { id?: string; slug?: string; name?: string; fieldsSchema?: FieldDefinition[]; icon?: string | null; category?: string | null; description?: string | null }) => {
834
+ const db = cdb(ctx);
835
+ const rows = await db.find({ from: "cms_block_types", where: input.id ? { id: input.id } : { slug: input.slug }, limit: 1 });
836
+ const row = rows[0];
837
+ if (!row) throw notFound("block type");
838
+ const patch: Record<string, unknown> = {};
839
+ for (const k of ["name", "fieldsSchema", "icon", "category", "description"] as const) {
840
+ if (k in input) patch[k] = (input as Record<string, unknown>)[k];
841
+ }
842
+ return db.update("cms_block_types", String(row.id), patch);
843
+ }, {
844
+ ...editor,
845
+ input: (raw): { id?: string; slug?: string; name?: string; fieldsSchema?: FieldDefinition[]; icon?: string | null; category?: string | null; description?: string | null } => {
846
+ const o = asObj(raw);
847
+ if (typeof o.id !== "string" && typeof o.slug !== "string") throw new BadRequest("id or slug is required");
848
+ return o as never;
849
+ },
850
+ }),
851
+
852
+ /** Update a content type (found by `id` or `slug`). `slug` is the stable key and is
853
+ * NOT mutable; `name`/`regions`/`fieldsSchema`/`defaultBlocks` are patched. Editor-gated. */
854
+ updateContentType: mutation(async (ctx, input: { id?: string; slug?: string; name?: string; regions?: RegionDefinition[]; fieldsSchema?: FieldDefinition[]; defaultBlocks?: DefaultBlockDefinition[] }) => {
855
+ const db = cdb(ctx);
856
+ if ("regions" in input && (!Array.isArray(input.regions) || input.regions.length === 0)) throw new BadRequest("at least one region is required");
857
+ const rows = await db.find({ from: "cms_content_types", where: input.id ? { id: input.id } : { slug: input.slug }, limit: 1 });
858
+ const row = rows[0];
859
+ if (!row) throw notFound("content type");
860
+ const patch: Record<string, unknown> = {};
861
+ for (const k of ["name", "regions", "fieldsSchema", "defaultBlocks"] as const) {
862
+ if (k in input) patch[k] = (input as Record<string, unknown>)[k];
863
+ }
864
+ return db.update("cms_content_types", String(row.id), patch);
865
+ }, {
866
+ ...editor,
867
+ input: (raw): { id?: string; slug?: string; name?: string; regions?: RegionDefinition[]; fieldsSchema?: FieldDefinition[]; defaultBlocks?: DefaultBlockDefinition[] } => {
868
+ const o = asObj(raw);
869
+ if (typeof o.id !== "string" && typeof o.slug !== "string") throw new BadRequest("id or slug is required");
870
+ return o as never;
871
+ },
872
+ }),
873
+
830
874
  // ---- media library ----
831
875
  /** Mint a signed upload URL for a media blob (keyed under the tenant's `media/`
832
876
  * prefix so the public /media route can serve it). The client PUTs the bytes to