@digital-gravy/etch-public-api 0.6.0 → 0.7.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.
package/dist/index.d.ts CHANGED
@@ -12,7 +12,7 @@ interface EtchBlockContext {
12
12
  * panel. This is editor UI state, not document data — most scripts can
13
13
  * ignore it.
14
14
  */
15
- structureState?: "open" | "closed";
15
+ structureState?: 'open' | 'closed';
16
16
  /** Whether the block is hidden (not rendered) on the canvas. */
17
17
  hidden?: boolean;
18
18
  }
@@ -64,7 +64,7 @@ interface EtchBlockCommon {
64
64
  }
65
65
  /** A text block (`etch/text`). */
66
66
  interface EtchTextBlockJson extends EtchBlockCommon {
67
- type: "etch/text";
67
+ type: 'etch/text';
68
68
  /** The block's text content. */
69
69
  text: string;
70
70
  }
@@ -76,7 +76,7 @@ interface EtchTextBlockJson extends EtchBlockCommon {
76
76
  * `blocks.create()` / `blocks.replace()` ignore them.
77
77
  */
78
78
  interface EtchElementBlockJson extends EtchBlockCommon {
79
- type: "etch/element";
79
+ type: 'etch/element';
80
80
  /** The HTML tag name, e.g. `div`, `p`, `h1`. */
81
81
  tag: string;
82
82
  /** HTML attributes. */
@@ -90,7 +90,7 @@ interface EtchElementBlockJson extends EtchBlockCommon {
90
90
  * {@link EtchElementBlockJson}).
91
91
  */
92
92
  interface EtchDynamicElementBlockJson extends EtchBlockCommon {
93
- type: "etch/dynamic-element";
93
+ type: 'etch/dynamic-element';
94
94
  /** HTML attributes (the rendered tag is read from `attributes.tag`). */
95
95
  attributes: EtchHtmlAttributes;
96
96
  }
@@ -111,7 +111,7 @@ interface EtchDynamicElementBlockJson extends EtchBlockCommon {
111
111
  * to `"full"` when omitted.
112
112
  */
113
113
  interface EtchDynamicImageBlockJson extends EtchBlockCommon {
114
- type: "etch/dynamic-image";
114
+ type: 'etch/dynamic-image';
115
115
  /** HTML attributes (e.g. `src`, `alt`). */
116
116
  attributes: EtchHtmlAttributes;
117
117
  }
@@ -129,13 +129,13 @@ interface EtchDynamicImageBlockJson extends EtchBlockCommon {
129
129
  * when `src` is set.
130
130
  */
131
131
  interface EtchSvgBlockJson extends EtchBlockCommon {
132
- type: "etch/svg";
132
+ type: 'etch/svg';
133
133
  /** HTML/SVG attributes. */
134
134
  attributes: EtchHtmlAttributes;
135
135
  }
136
136
  /** A loop block (`etch/loop`) that repeats its children over a data source. */
137
137
  interface EtchLoopBlockJson extends EtchBlockCommon {
138
- type: "etch/loop";
138
+ type: 'etch/loop';
139
139
  /** Variable name bound to the current item (e.g. `item`). */
140
140
  itemId: string;
141
141
  /** What the block iterates over (a dynamic path); omitted when bound via `loopId`. */
@@ -149,13 +149,13 @@ interface EtchLoopBlockJson extends EtchBlockCommon {
149
149
  }
150
150
  /** A conditional block (`etch/condition`); renders its children when the expression holds. */
151
151
  interface EtchConditionBlockJson extends EtchBlockCommon {
152
- type: "etch/condition";
152
+ type: 'etch/condition';
153
153
  /** The condition expression. */
154
154
  conditionString: string;
155
155
  }
156
156
  /** An instance of a reusable component (`etch/component`). */
157
157
  interface EtchComponentBlockJson extends EtchBlockCommon {
158
- type: "etch/component";
158
+ type: 'etch/component';
159
159
  /** Id of the component being instantiated. */
160
160
  componentId: number;
161
161
  /** Values bound to the component's properties. */
@@ -163,23 +163,23 @@ interface EtchComponentBlockJson extends EtchBlockCommon {
163
163
  }
164
164
  /** Content projected into a component slot (`etch/slot-content`). */
165
165
  interface EtchSlotContentBlockJson extends EtchBlockCommon {
166
- type: "etch/slot-content";
166
+ type: 'etch/slot-content';
167
167
  /** Name of the slot this content targets. */
168
168
  slotName: string;
169
169
  }
170
170
  /** A slot placeholder inside a component definition (`etch/slot-placeholder`). */
171
171
  interface EtchSlotPlaceholderBlockJson extends EtchBlockCommon {
172
- type: "etch/slot-placeholder";
172
+ type: 'etch/slot-placeholder';
173
173
  /** Name of the slot. */
174
174
  slotName: string;
175
175
  }
176
176
  /** The post-content insertion point (`etch/post-content`). No extra fields. */
177
177
  interface EtchPostContentBlockJson extends EtchBlockCommon {
178
- type: "etch/post-content";
178
+ type: 'etch/post-content';
179
179
  }
180
180
  /** A raw-HTML block (`etch/raw-html`). */
181
181
  interface EtchRawHtmlBlockJson extends EtchBlockCommon {
182
- type: "etch/raw-html";
182
+ type: 'etch/raw-html';
183
183
  /** Sanitized HTML content. */
184
184
  content: string;
185
185
  /** The original, unsanitized HTML as authored. */
@@ -187,7 +187,7 @@ interface EtchRawHtmlBlockJson extends EtchBlockCommon {
187
187
  }
188
188
  /** A pass-through wrapper around a native Gutenberg block (`etch/passthrough`). */
189
189
  interface EtchPassthroughBlockJson extends EtchBlockCommon {
190
- type: "etch/passthrough";
190
+ type: 'etch/passthrough';
191
191
  /** The wrapped Gutenberg block. */
192
192
  gutenbergBlock: GutenbergBlock;
193
193
  }
@@ -201,7 +201,7 @@ interface EtchPassthroughBlockJson extends EtchBlockCommon {
201
201
  */
202
202
  type EtchBlockJson = EtchTextBlockJson | EtchElementBlockJson | EtchDynamicElementBlockJson | EtchDynamicImageBlockJson | EtchSvgBlockJson | EtchLoopBlockJson | EtchConditionBlockJson | EtchComponentBlockJson | EtchSlotContentBlockJson | EtchSlotPlaceholderBlockJson | EtchPostContentBlockJson | EtchRawHtmlBlockJson | EtchPassthroughBlockJson;
203
203
  /** Every known block `type` string (the discriminants of {@link EtchBlockJson}). */
204
- type EtchBlockTypeName = EtchBlockJson["type"];
204
+ type EtchBlockTypeName = EtchBlockJson['type'];
205
205
  /** Read-only identity attached to every serialized (read) block. */
206
206
  interface BlockIdentity {
207
207
  /** Stable id of this block. */
@@ -217,7 +217,7 @@ interface BlockIdentity {
217
217
  * writable {@link EtchBlockJson}, so they cannot be set via
218
218
  * `blocks.create()` / `blocks.replace()`.
219
219
  */
220
- type StyledBlockType = "etch/element" | "etch/dynamic-element" | "etch/dynamic-image" | "etch/svg";
220
+ type StyledBlockType = 'etch/element' | 'etch/dynamic-element' | 'etch/dynamic-image' | 'etch/svg';
221
221
  /** The read-only `styles` exposed on a {@link StyledBlockType} when reading. */
222
222
  interface ReadOnlyBlockStyles {
223
223
  /** Ids of the global styles applied to this block (read-only). */
@@ -227,7 +227,7 @@ interface ReadOnlyBlockStyles {
227
227
  * Attach read-only identity (`id`/`parentId`) to a block, recursively, plus the
228
228
  * read-only `styles` array for the {@link StyledBlockType}s that carry one.
229
229
  */
230
- type WithIdentity<B> = B extends EtchBlockCommon ? Omit<B, "children"> & BlockIdentity & (B extends {
230
+ type WithIdentity<B> = B extends EtchBlockCommon ? Omit<B, 'children'> & BlockIdentity & (B extends {
231
231
  type: StyledBlockType;
232
232
  } ? ReadOnlyBlockStyles : unknown) : never;
233
233
  /**
@@ -256,8 +256,10 @@ interface BlockPatch {
256
256
  /** Hide or show the block on the canvas. */
257
257
  hidden?: boolean;
258
258
  /**
259
- * Merge HTML attributes — a key set to `undefined` removes that attribute.
260
- * Only valid on HTML blocks.
259
+ * Merge attributes — a key set to `undefined` removes that attribute. Valid
260
+ * on HTML blocks (free-form HTML attributes) and on component instances,
261
+ * whose attributes are their bound props — a closed schema, so each key must
262
+ * be a property declared by the component (an unknown key is rejected).
261
263
  */
262
264
  attributes?: Record<string, string | undefined>;
263
265
  /** Replace the text content. Only valid on text blocks. */
@@ -299,11 +301,26 @@ interface EtchBlocksApi {
299
301
  setText(blockId: string, text: string): void;
300
302
  /** Rename a block (sets its label / display name). */
301
303
  rename(blockId: string, name: string): void;
302
- /** Read an HTML attribute, or `undefined` when it is not set. */
304
+ /**
305
+ * Read an attribute, or `undefined` when it is not set. Works on HTML blocks
306
+ * (HTML attributes) and component instances (bound prop values). Throws
307
+ * `WRONG_BLOCK_TYPE` for a block that has no attributes (e.g. a text block).
308
+ */
303
309
  getAttribute(blockId: string, key: string): string | undefined;
304
- /** Set an HTML attribute; omit `value` for a valueless (boolean) attribute. */
310
+ /**
311
+ * Set an attribute; omit `value` for a valueless (boolean) attribute. Works
312
+ * on HTML blocks and component instances. On a component, `key` must be a
313
+ * declared property — props are a closed schema — otherwise
314
+ * `INVALID_ARGUMENT` is thrown (or `OPERATION_FAILED` if the component
315
+ * definition has not loaded yet). Throws `WRONG_BLOCK_TYPE` for a block with
316
+ * no attributes.
317
+ */
305
318
  setAttribute(blockId: string, key: string, value?: string): void;
306
- /** Remove an HTML attribute. */
319
+ /**
320
+ * Remove an attribute. Works on HTML blocks and component instances. On a
321
+ * component, `key` must be a declared property (see {@link setAttribute}).
322
+ * Throws `WRONG_BLOCK_TYPE` for a block with no attributes.
323
+ */
307
324
  removeAttribute(blockId: string, key: string): void;
308
325
  /** Add a CSS class to the block. */
309
326
  addClass(blockId: string, className: string): void;
@@ -373,9 +390,9 @@ interface MetaQueryItem {
373
390
  /** The value(s) to compare against. */
374
391
  value: string | number | Array<string | number>;
375
392
  /** Comparison operator (defaults to `=`). */
376
- compare?: "=" | "!=" | ">" | ">=" | "<" | "<=" | "LIKE" | "NOT LIKE" | "IN" | "NOT IN" | "BETWEEN" | "NOT BETWEEN" | "EXISTS" | "NOT EXISTS";
393
+ compare?: '=' | '!=' | '>' | '>=' | '<' | '<=' | 'LIKE' | 'NOT LIKE' | 'IN' | 'NOT IN' | 'BETWEEN' | 'NOT BETWEEN' | 'EXISTS' | 'NOT EXISTS';
377
394
  /** SQL type the value is cast to before comparison. */
378
- type?: "NUMERIC" | "BINARY" | "CHAR" | "DATE" | "DATETIME" | "DECIMAL" | "SIGNED" | "TIME" | "UNSIGNED";
395
+ type?: 'NUMERIC' | 'BINARY' | 'CHAR' | 'DATE' | 'DATETIME' | 'DECIMAL' | 'SIGNED' | 'TIME' | 'UNSIGNED';
379
396
  [key: string]: unknown;
380
397
  }
381
398
  /**
@@ -386,11 +403,11 @@ interface TaxQueryItem {
386
403
  /** The taxonomy to query (e.g. `category`, `post_tag`). */
387
404
  taxonomy: string;
388
405
  /** Which term field `terms` refers to. */
389
- field: "term_id" | "slug" | "name";
406
+ field: 'term_id' | 'slug' | 'name';
390
407
  /** The term(s) to match. */
391
408
  terms: string | number | Array<string | number>;
392
409
  /** How to match the terms (defaults to `IN`). */
393
- operator?: "IN" | "NOT IN" | "AND";
410
+ operator?: 'IN' | 'NOT IN' | 'AND';
394
411
  /** Whether to include child terms of a hierarchical taxonomy. */
395
412
  include_children?: boolean;
396
413
  [key: string]: unknown;
@@ -412,11 +429,11 @@ interface WpQueryArgs {
412
429
  /** Alias of `paged` used in some contexts. */
413
430
  page?: NumericParam;
414
431
  /** Field to order results by. */
415
- orderby?: "date" | "title" | "menu_order" | "rand" | "ID" | "author" | "name" | "modified" | "parent" | "comment_count" | (string & {});
432
+ orderby?: 'date' | 'title' | 'menu_order' | 'rand' | 'ID' | 'author' | 'name' | 'modified' | 'parent' | 'comment_count' | (string & {});
416
433
  /** Sort direction. */
417
- order?: "ASC" | "DESC" | (string & {});
434
+ order?: 'ASC' | 'DESC' | (string & {});
418
435
  /** Post status to include. */
419
- post_status?: "publish" | "pending" | "draft" | "auto-draft" | "future" | "private" | "inherit" | "trash" | (string & {});
436
+ post_status?: 'publish' | 'pending' | 'draft' | 'auto-draft' | 'future' | 'private' | 'inherit' | 'trash' | (string & {});
420
437
  /** Whether to ignore sticky posts. */
421
438
  ignore_sticky_posts?: BooleanParam;
422
439
  /** Author id (number) or username (string). */
@@ -442,9 +459,9 @@ interface WpTermsArgs {
442
459
  /** Taxonomy to fetch terms from. */
443
460
  taxonomy?: string;
444
461
  /** Field to order terms by. */
445
- orderby?: "name" | "slug" | "term_group" | "term_id" | "description" | "count" | (string & {});
462
+ orderby?: 'name' | 'slug' | 'term_group' | 'term_id' | 'description' | 'count' | (string & {});
446
463
  /** Sort direction. */
447
- order?: "ASC" | "DESC" | (string & {});
464
+ order?: 'ASC' | 'DESC' | (string & {});
448
465
  [key: string]: unknown;
449
466
  }
450
467
  /** WordPress user query arguments (extensible). */
@@ -460,9 +477,9 @@ interface WpUsersArgs {
460
477
  /** Columns the `search` keyword is matched against. */
461
478
  search_columns?: string[] | string;
462
479
  /** Field to order users by. */
463
- orderby?: "ID" | "display_name" | "name" | "user_login" | "user_email" | "user_registered" | "post_count" | "meta_value" | "meta_value_num" | (string & {});
480
+ orderby?: 'ID' | 'display_name' | 'name' | 'user_login' | 'user_email' | 'user_registered' | 'post_count' | 'meta_value' | 'meta_value_num' | (string & {});
464
481
  /** Sort direction. */
465
- order?: "ASC" | "DESC" | (string & {});
482
+ order?: 'ASC' | 'DESC' | (string & {});
466
483
  /** Number of users to return. */
467
484
  number?: NumericParam;
468
485
  /** Number of users to skip. */
@@ -473,19 +490,19 @@ interface WpUsersArgs {
473
490
  }
474
491
  /** Type-specific configuration of an {@link EtchLoop}, discriminated by `type`. */
475
492
  type EtchLoopConfig = {
476
- type: "wp-query";
493
+ type: 'wp-query';
477
494
  args: WpQueryArgs;
478
495
  } | {
479
- type: "wp-terms";
496
+ type: 'wp-terms';
480
497
  args: WpTermsArgs;
481
498
  } | {
482
- type: "wp-users";
499
+ type: 'wp-users';
483
500
  args: WpUsersArgs;
484
501
  } | {
485
- type: "main-query";
502
+ type: 'main-query';
486
503
  args: WpQueryArgs;
487
504
  } | {
488
- type: "json";
505
+ type: 'json';
489
506
  data: unknown[];
490
507
  };
491
508
  /** A loop definition (extensible). */
@@ -549,7 +566,7 @@ interface EtchLoopsApi {
549
566
  * - `attribute` — `[data-foo]`, `[type="submit"]`, etc.
550
567
  * - `custom` — anything else (pseudo-classes, combinators, etc.)
551
568
  */
552
- type StyleSelectorType = "class" | "id" | "tag" | "element" | "attribute" | "custom";
569
+ type StyleSelectorType = 'class' | 'id' | 'tag' | 'element' | 'attribute' | 'custom';
553
570
  /** A style entry as returned by `styles.list()`. */
554
571
  interface StyleSummary {
555
572
  /** Stable id of the style rule. */
@@ -636,7 +653,7 @@ interface EtchStylesApi {
636
653
  * Global stylesheet shapes and the `etch.stylesheets` API surface.
637
654
  */
638
655
  /** Type of a global stylesheet. */
639
- type StylesheetType = "default" | "@custom-media";
656
+ type StylesheetType = 'default' | '@custom-media';
640
657
  /** A global stylesheet entry. */
641
658
  interface StylesheetSummary {
642
659
  /** Stable id of the stylesheet. */
@@ -737,8 +754,8 @@ type SelectOptionsString = string;
737
754
  */
738
755
  interface StringComponentProperty {
739
756
  type: {
740
- primitive: "string";
741
- specialized?: "color" | "url" | "image" | "select" | "array" | "wpMediaId";
757
+ primitive: 'string';
758
+ specialized?: 'color' | 'url' | 'image' | 'select' | 'array' | 'wpMediaId';
742
759
  };
743
760
  /** Default value. */
744
761
  default?: string;
@@ -760,7 +777,7 @@ interface StringComponentProperty {
760
777
  */
761
778
  interface NumberComponentProperty {
762
779
  type: {
763
- primitive: "number";
780
+ primitive: 'number';
764
781
  };
765
782
  /** Default value. */
766
783
  default?: number;
@@ -770,7 +787,7 @@ interface NumberComponentProperty {
770
787
  /** A boolean property. */
771
788
  interface BooleanComponentProperty {
772
789
  type: {
773
- primitive: "boolean";
790
+ primitive: 'boolean';
774
791
  };
775
792
  /** Default value (a string is allowed for expression-driven defaults). */
776
793
  default?: boolean | string;
@@ -784,7 +801,7 @@ interface BooleanComponentProperty {
784
801
  */
785
802
  interface ObjectComponentProperty {
786
803
  type: {
787
- primitive: "object";
804
+ primitive: 'object';
788
805
  specialized?: string;
789
806
  };
790
807
  /** Default value. */
@@ -799,7 +816,7 @@ interface ObjectComponentProperty {
799
816
  */
800
817
  interface ArrayComponentProperty {
801
818
  type: {
802
- primitive: "array";
819
+ primitive: 'array';
803
820
  specialized?: string;
804
821
  };
805
822
  /** Default value. */
@@ -808,8 +825,8 @@ interface ArrayComponentProperty {
808
825
  /** A list of CSS class names — an `array` specialized as `'class'`. */
809
826
  interface ClassComponentProperty {
810
827
  type: {
811
- primitive: "array";
812
- specialized: "class";
828
+ primitive: 'array';
829
+ specialized: 'class';
813
830
  };
814
831
  /** Default value. */
815
832
  default?: string[];
@@ -817,8 +834,8 @@ interface ClassComponentProperty {
817
834
  /** A group of nested properties — an `object` specialized as `'group'` (no default). */
818
835
  interface GroupComponentProperty {
819
836
  type: {
820
- primitive: "object";
821
- specialized: "group";
837
+ primitive: 'object';
838
+ specialized: 'group';
822
839
  };
823
840
  /** The nested properties in this group. */
824
841
  properties: ComponentProperty[];
@@ -826,8 +843,8 @@ interface GroupComponentProperty {
826
843
  /** A repeatable group — an `array` specialized as `'repeater'` (no default). */
827
844
  interface RepeaterComponentProperty {
828
845
  type: {
829
- primitive: "array";
830
- specialized: "repeater";
846
+ primitive: 'array';
847
+ specialized: 'repeater';
831
848
  };
832
849
  /** The nested properties repeated per row. */
833
850
  properties: ComponentProperty[];
@@ -835,8 +852,8 @@ interface RepeaterComponentProperty {
835
852
  /** A conditional group gated by an expression — a `string` specialized as `'condition'`. */
836
853
  interface ConditionComponentProperty {
837
854
  type: {
838
- primitive: "string";
839
- specialized: "condition";
855
+ primitive: 'string';
856
+ specialized: 'condition';
840
857
  };
841
858
  /** The nested properties shown when the condition holds. */
842
859
  properties: ComponentProperty[];
@@ -942,7 +959,7 @@ interface EtchComponentsApi {
942
959
  * - `style-manager` — the global style manager
943
960
  * - `loop-manager` — the loop manager
944
961
  */
945
- type NavigationPlace = "builder" | "templates" | "style-manager" | "content-hub" | "loop-manager";
962
+ type NavigationPlace = 'builder' | 'templates' | 'style-manager' | 'content-hub' | 'loop-manager';
946
963
  /** Lightweight post entry returned by `navigation.listPostsAsync()`. */
947
964
  interface PostSummary {
948
965
  /** Post id. */
@@ -991,7 +1008,7 @@ interface EtchNavigationApi {
991
1008
  * Custom field group/value shapes and the `etch.fields` API surface.
992
1009
  */
993
1010
  /** Custom field type. Open-ended for future field types. */
994
- type CustomFieldType = "text" | "textarea" | "number" | "boolean" | (string & {});
1011
+ type CustomFieldType = 'text' | 'textarea' | 'number' | 'boolean' | (string & {});
995
1012
  /** A custom field definition (extensible). */
996
1013
  interface CustomField {
997
1014
  /** Display label. */
@@ -1009,13 +1026,13 @@ interface CustomField {
1009
1026
  /** Where a custom field group is assigned. */
1010
1027
  type CustomFieldAssignment = {
1011
1028
  post_types: string[];
1012
- op: "isIn" | "isNotIn";
1029
+ op: 'isIn' | 'isNotIn';
1013
1030
  } | {
1014
1031
  post_ids: number[];
1015
- op: "isIn" | "isNotIn";
1032
+ op: 'isIn' | 'isNotIn';
1016
1033
  } | {
1017
1034
  taxonomies: string[];
1018
- op: "isIn" | "isNotIn";
1035
+ op: 'isIn' | 'isNotIn';
1019
1036
  };
1020
1037
  /** A custom field group definition (extensible). */
1021
1038
  interface CustomFieldGroup {
@@ -1111,7 +1128,7 @@ interface EtchFieldsApi {
1111
1128
  * Builder chrome controls (`etch.ui`) and undo/redo (`etch.history`).
1112
1129
  */
1113
1130
  /** Canvas color scheme. */
1114
- type ColorScheme = "light" | "dark";
1131
+ type ColorScheme = 'light' | 'dark';
1115
1132
  /** Builder app/chrome controls: color scheme, interface visibility, exit. */
1116
1133
  interface EtchUiApi {
1117
1134
  /** The current canvas color scheme. */
package/dist/index.js CHANGED
@@ -45,7 +45,10 @@ function getEtch(options = {}) {
45
45
  return etch.connect(options);
46
46
  }
47
47
  if (options.apiVersion) {
48
- warnIfIncompatible(options.apiVersion, etch.apiVersion ?? ETCH_API_VERSION);
48
+ warnIfIncompatible(
49
+ options.apiVersion,
50
+ etch.apiVersion ?? ETCH_API_VERSION
51
+ );
49
52
  }
50
53
  return etch;
51
54
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/version.ts","../src/client.ts"],"names":[],"mappings":";AAyBO,IAAM,YAAA,GAAN,cAA2B,KAAA,CAAM;AAAA,EAGvC,WAAA,CAAY,MAAwB,OAAA,EAAiB;AACpD,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,cAAA;AACZ,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AAAA,EACb;AACD;AAGO,SAAS,eAAe,KAAA,EAAuC;AACrE,EAAA,OAAO,KAAA,YAAiB,YAAA,IAAiB,KAAA,EAAiB,IAAA,KAAS,cAAA;AACpE;;;AC9BO,IAAM,gBAAA,GAAmB;;;ACIhC,SAAS,QAAA,GAA6B;AACrC,EAAA,MAAM,KAAA,GAAQ,UAAA;AACd,EAAA,OAAO,KAAA,CAAM,IAAA;AACd;AAMO,SAAS,eAAA,GAA2B;AAC1C,EAAA,OAAO,UAAS,KAAM,MAAA;AACvB;AAGA,SAAS,QAAQ,OAAA,EAAgC;AAChD,EAAA,MAAM,KAAA,GAAQ,WAAA,CAAY,IAAA,CAAK,OAAO,CAAA;AACtC,EAAA,OAAO,KAAA,GAAQ,MAAA,CAAO,KAAA,CAAM,CAAC,CAAC,CAAA,GAAI,IAAA;AACnC;AAOA,SAAS,kBAAA,CAAmB,WAAmB,OAAA,EAAuB;AACrE,EAAA,MAAM,IAAA,GAAO,QAAQ,SAAS,CAAA;AAC9B,EAAA,MAAM,IAAA,GAAO,QAAQ,OAAO,CAAA;AAC5B,EAAA,IAAI,IAAA,KAAS,IAAA,IAAQ,IAAA,KAAS,IAAA,IAAQ,SAAS,IAAA,EAAM;AAErD,EAAA,OAAA,CAAQ,IAAA;AAAA,IACP,CAAA,qDAAA,EAAwD,SAAS,CAAA,wBAAA,EAC9C,OAAO,CAAA,sBAAA;AAAA,GAC3B;AACD;AAsBO,SAAS,OAAA,CAAQ,OAAA,GAA0B,EAAC,EAAS;AAC3D,EAAA,MAAM,OAAO,QAAA,EAAS;AACtB,EAAA,IAAI,CAAC,IAAA,EAAM;AACV,IAAA,MAAM,IAAI,YAAA;AAAA,MACT,eAAA;AAAA,MACA;AAAA,KAED;AAAA,EACD;AAEA,EAAA,IAAI,OAAO,IAAA,CAAK,OAAA,KAAY,UAAA,EAAY;AACvC,IAAA,OAAO,IAAA,CAAK,QAAQ,OAAO,CAAA;AAAA,EAC5B;AAEA,EAAA,IAAI,QAAQ,UAAA,EAAY;AACvB,IAAA,kBAAA,CAAmB,OAAA,CAAQ,UAAA,EAAY,IAAA,CAAK,UAAA,IAAc,gBAAgB,CAAA;AAAA,EAC3E;AACA,EAAA,OAAO,IAAA;AACR","file":"index.js","sourcesContent":["/**\n * Error codes thrown by the public `window.etch` API.\n *\n * The API throws typed errors (rather than returning sentinels) so that AI\n * assistants and plugin authors can `try`/`catch` and react to a precise cause.\n *\n * The union ends with `(string & {})` so that codes added by newer Etch\n * runtimes still type-check as `EtchApiErrorCode` while keeping autocomplete for\n * the known values.\n */\nexport type EtchApiErrorCode =\n\t| 'BLOCK_NOT_FOUND'\n\t| 'WRONG_BLOCK_TYPE'\n\t| 'READONLY'\n\t| 'INVALID_ARGUMENT'\n\t| 'LOOP_NOT_FOUND'\n\t| 'STYLE_NOT_FOUND'\n\t| 'STYLESHEET_NOT_FOUND'\n\t| 'COMPONENT_NOT_FOUND'\n\t| 'POST_NOT_FOUND'\n\t| 'OPERATION_FAILED'\n\t| 'NOT_AVAILABLE'\n\t| (string & {});\n\n/** Error thrown by the public Etch API (and by this client). */\nexport class EtchApiError extends Error {\n\treadonly code: EtchApiErrorCode;\n\n\tconstructor(code: EtchApiErrorCode, message: string) {\n\t\tsuper(message);\n\t\tthis.name = 'EtchApiError';\n\t\tthis.code = code;\n\t}\n}\n\n/** Narrow an unknown caught value to an {@link EtchApiError}. */\nexport function isEtchApiError(value: unknown): value is EtchApiError {\n\treturn value instanceof EtchApiError || (value as Error)?.name === 'EtchApiError';\n}\n","/**\n * Version of the Etch scripting **contract** this package targets, independent\n * of the Etch product version and of this package's own npm version.\n *\n * `0.x` signals the surface is **experimental** and may change without a major\n * bump until it stabilizes. It matches the value returned by the runtime's\n * {@link Etch.apiVersion} getter on `window.etch`.\n */\nexport const ETCH_API_VERSION = '0.x';\n","import type { ConnectOptions, Etch } from './contract';\nimport { EtchApiError } from './errors';\nimport { ETCH_API_VERSION } from './version';\n\ndeclare global {\n\tinterface Window {\n\t\t/** The Etch scripting API, present once the builder has loaded. */\n\t\tetch?: Etch;\n\t}\n}\n\n/** Read `window.etch` from whatever global object exists, or `undefined`. */\nfunction readEtch(): Etch | undefined {\n\tconst scope = globalThis as { etch?: Etch };\n\treturn scope.etch;\n}\n\n/**\n * Whether the Etch scripting API is present on the page. Use this to guard code\n * that should no-op when not running inside the builder.\n */\nexport function isEtchAvailable(): boolean {\n\treturn readEtch() !== undefined;\n}\n\n/** The major version number of a semver-ish string, or `null` if unparseable. */\nfunction majorOf(version: string): number | null {\n\tconst match = /^\\D*(\\d+)/.exec(version);\n\treturn match ? Number(match[1]) : null;\n}\n\n/**\n * Best-effort compatibility check for `0.x` runtimes that have no native\n * `connect()`. Warns (does not throw) when the requested major differs from the\n * runtime's, so experimental consumers aren't hard-blocked.\n */\nfunction warnIfIncompatible(requested: string, runtime: string): void {\n\tconst want = majorOf(requested);\n\tconst have = majorOf(runtime);\n\tif (want === null || have === null || want === have) return;\n\t// eslint-disable-next-line no-console\n\tconsole.warn(\n\t\t`[@digital-gravy/etch-public-api] Requested Etch API v${requested} but the ` +\n\t\t\t`page provides v${runtime}. Behavior may differ.`\n\t);\n}\n\n/**\n * Acquire the Etch scripting API from the page.\n *\n * The runtime lives on `window.etch` (injected by the builder); this returns it\n * typed. When the page exposes a future stable runtime with a native\n * `connect()`, version negotiation is delegated to it. On today's `0.x`\n * runtime, the global is returned directly after a best-effort version check.\n *\n * @throws {EtchApiError} `NOT_AVAILABLE` when the builder is not present.\n *\n * @example\n * ```ts\n * import { getEtch } from '@etchwp/public-api';\n *\n * const etch = getEtch();\n * const ids = etch.blocks.find({ type: 'text' });\n * etch.blocks.setText(ids[0], 'Hello');\n * await etch.saveAsync();\n * ```\n */\nexport function getEtch(options: ConnectOptions = {}): Etch {\n\tconst etch = readEtch();\n\tif (!etch) {\n\t\tthrow new EtchApiError(\n\t\t\t'NOT_AVAILABLE',\n\t\t\t'window.etch is not available. The Etch builder is not loaded on this page, ' +\n\t\t\t\t'or getEtch() ran before it finished initializing.'\n\t\t);\n\t}\n\n\tif (typeof etch.connect === 'function') {\n\t\treturn etch.connect(options);\n\t}\n\n\tif (options.apiVersion) {\n\t\twarnIfIncompatible(options.apiVersion, etch.apiVersion ?? ETCH_API_VERSION);\n\t}\n\treturn etch;\n}\n"]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/version.ts","../src/client.ts"],"names":[],"mappings":";AAyBO,IAAM,YAAA,GAAN,cAA2B,KAAA,CAAM;AAAA,EAGvC,WAAA,CAAY,MAAwB,OAAA,EAAiB;AACpD,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,cAAA;AACZ,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AAAA,EACb;AACD;AAGO,SAAS,eAAe,KAAA,EAAuC;AACrE,EAAA,OACC,KAAA,YAAiB,YAAA,IAChB,KAAA,EAAiB,IAAA,KAAS,cAAA;AAE7B;;;ACjCO,IAAM,gBAAA,GAAmB;;;ACIhC,SAAS,QAAA,GAA6B;AACrC,EAAA,MAAM,KAAA,GAAQ,UAAA;AACd,EAAA,OAAO,KAAA,CAAM,IAAA;AACd;AAMO,SAAS,eAAA,GAA2B;AAC1C,EAAA,OAAO,UAAS,KAAM,MAAA;AACvB;AAGA,SAAS,QAAQ,OAAA,EAAgC;AAChD,EAAA,MAAM,KAAA,GAAQ,WAAA,CAAY,IAAA,CAAK,OAAO,CAAA;AACtC,EAAA,OAAO,KAAA,GAAQ,MAAA,CAAO,KAAA,CAAM,CAAC,CAAC,CAAA,GAAI,IAAA;AACnC;AAOA,SAAS,kBAAA,CAAmB,WAAmB,OAAA,EAAuB;AACrE,EAAA,MAAM,IAAA,GAAO,QAAQ,SAAS,CAAA;AAC9B,EAAA,MAAM,IAAA,GAAO,QAAQ,OAAO,CAAA;AAC5B,EAAA,IAAI,IAAA,KAAS,IAAA,IAAQ,IAAA,KAAS,IAAA,IAAQ,SAAS,IAAA,EAAM;AACrD,EAAA,OAAA,CAAQ,IAAA;AAAA,IACP,CAAA,qDAAA,EAAwD,SAAS,CAAA,wBAAA,EAC9C,OAAO,CAAA,sBAAA;AAAA,GAC3B;AACD;AAsBO,SAAS,OAAA,CAAQ,OAAA,GAA0B,EAAC,EAAS;AAC3D,EAAA,MAAM,OAAO,QAAA,EAAS;AACtB,EAAA,IAAI,CAAC,IAAA,EAAM;AACV,IAAA,MAAM,IAAI,YAAA;AAAA,MACT,eAAA;AAAA,MACA;AAAA,KAED;AAAA,EACD;AAEA,EAAA,IAAI,OAAO,IAAA,CAAK,OAAA,KAAY,UAAA,EAAY;AACvC,IAAA,OAAO,IAAA,CAAK,QAAQ,OAAO,CAAA;AAAA,EAC5B;AAEA,EAAA,IAAI,QAAQ,UAAA,EAAY;AACvB,IAAA,kBAAA;AAAA,MACC,OAAA,CAAQ,UAAA;AAAA,MACR,KAAK,UAAA,IAAc;AAAA,KACpB;AAAA,EACD;AACA,EAAA,OAAO,IAAA;AACR","file":"index.js","sourcesContent":["/**\n * Error codes thrown by the public `window.etch` API.\n *\n * The API throws typed errors (rather than returning sentinels) so that AI\n * assistants and plugin authors can `try`/`catch` and react to a precise cause.\n *\n * The union ends with `(string & {})` so that codes added by newer Etch\n * runtimes still type-check as `EtchApiErrorCode` while keeping autocomplete for\n * the known values.\n */\nexport type EtchApiErrorCode =\n\t| 'BLOCK_NOT_FOUND'\n\t| 'WRONG_BLOCK_TYPE'\n\t| 'READONLY'\n\t| 'INVALID_ARGUMENT'\n\t| 'LOOP_NOT_FOUND'\n\t| 'STYLE_NOT_FOUND'\n\t| 'STYLESHEET_NOT_FOUND'\n\t| 'COMPONENT_NOT_FOUND'\n\t| 'POST_NOT_FOUND'\n\t| 'OPERATION_FAILED'\n\t| 'NOT_AVAILABLE'\n\t| (string & {});\n\n/** Error thrown by the public Etch API (and by this client). */\nexport class EtchApiError extends Error {\n\treadonly code: EtchApiErrorCode;\n\n\tconstructor(code: EtchApiErrorCode, message: string) {\n\t\tsuper(message);\n\t\tthis.name = 'EtchApiError';\n\t\tthis.code = code;\n\t}\n}\n\n/** Narrow an unknown caught value to an {@link EtchApiError}. */\nexport function isEtchApiError(value: unknown): value is EtchApiError {\n\treturn (\n\t\tvalue instanceof EtchApiError ||\n\t\t(value as Error)?.name === 'EtchApiError'\n\t);\n}\n","/**\n * Version of the Etch scripting **contract** this package targets, independent\n * of the Etch product version and of this package's own npm version.\n *\n * `0.x` signals the surface is **experimental** and may change without a major\n * bump until it stabilizes. It matches the value returned by the runtime's\n * {@link Etch.apiVersion} getter on `window.etch`.\n */\nexport const ETCH_API_VERSION = '0.x';\n","import type { ConnectOptions, Etch } from './contract';\nimport { EtchApiError } from './errors';\nimport { ETCH_API_VERSION } from './version';\n\ndeclare global {\n\tinterface Window {\n\t\t/** The Etch scripting API, present once the builder has loaded. */\n\t\tetch?: Etch;\n\t}\n}\n\n/** Read `window.etch` from whatever global object exists, or `undefined`. */\nfunction readEtch(): Etch | undefined {\n\tconst scope = globalThis as { etch?: Etch };\n\treturn scope.etch;\n}\n\n/**\n * Whether the Etch scripting API is present on the page. Use this to guard code\n * that should no-op when not running inside the builder.\n */\nexport function isEtchAvailable(): boolean {\n\treturn readEtch() !== undefined;\n}\n\n/** The major version number of a semver-ish string, or `null` if unparseable. */\nfunction majorOf(version: string): number | null {\n\tconst match = /^\\D*(\\d+)/.exec(version);\n\treturn match ? Number(match[1]) : null;\n}\n\n/**\n * Best-effort compatibility check for `0.x` runtimes that have no native\n * `connect()`. Warns (does not throw) when the requested major differs from the\n * runtime's, so experimental consumers aren't hard-blocked.\n */\nfunction warnIfIncompatible(requested: string, runtime: string): void {\n\tconst want = majorOf(requested);\n\tconst have = majorOf(runtime);\n\tif (want === null || have === null || want === have) return;\n\tconsole.warn(\n\t\t`[@digital-gravy/etch-public-api] Requested Etch API v${requested} but the ` +\n\t\t\t`page provides v${runtime}. Behavior may differ.`\n\t);\n}\n\n/**\n * Acquire the Etch scripting API from the page.\n *\n * The runtime lives on `window.etch` (injected by the builder); this returns it\n * typed. When the page exposes a future stable runtime with a native\n * `connect()`, version negotiation is delegated to it. On today's `0.x`\n * runtime, the global is returned directly after a best-effort version check.\n *\n * @throws {EtchApiError} `NOT_AVAILABLE` when the builder is not present.\n *\n * @example\n * ```ts\n * import { getEtch } from '@etchwp/public-api';\n *\n * const etch = getEtch();\n * const ids = etch.blocks.find({ type: 'text' });\n * etch.blocks.setText(ids[0], 'Hello');\n * await etch.saveAsync();\n * ```\n */\nexport function getEtch(options: ConnectOptions = {}): Etch {\n\tconst etch = readEtch();\n\tif (!etch) {\n\t\tthrow new EtchApiError(\n\t\t\t'NOT_AVAILABLE',\n\t\t\t'window.etch is not available. The Etch builder is not loaded on this page, ' +\n\t\t\t\t'or getEtch() ran before it finished initializing.'\n\t\t);\n\t}\n\n\tif (typeof etch.connect === 'function') {\n\t\treturn etch.connect(options);\n\t}\n\n\tif (options.apiVersion) {\n\t\twarnIfIncompatible(\n\t\t\toptions.apiVersion,\n\t\t\tetch.apiVersion ?? ETCH_API_VERSION\n\t\t);\n\t}\n\treturn etch;\n}\n"]}
package/package.json CHANGED
@@ -1,46 +1,60 @@
1
1
  {
2
- "name": "@digital-gravy/etch-public-api",
3
- "version": "0.6.0",
4
- "description": "MIT-licensed typed client and contract for the Etch builder scripting API (window.etch). Etch itself is a separate proprietary product governed by its own commercial terms.",
5
- "license": "MIT",
6
- "type": "module",
7
- "main": "./dist/index.cjs",
8
- "module": "./dist/index.js",
9
- "types": "./dist/index.d.ts",
10
- "exports": {
11
- ".": {
12
- "types": "./dist/index.d.ts",
13
- "import": "./dist/index.js",
14
- "require": "./dist/index.cjs"
15
- }
16
- },
17
- "files": [
18
- "dist",
19
- "README.md"
20
- ],
21
- "sideEffects": false,
22
- "scripts": {
23
- "build": "tsup",
24
- "dev": "tsup --watch",
25
- "test": "vitest run",
26
- "test:watch": "vitest",
27
- "typecheck": "tsc --noEmit",
28
- "prepublishOnly": "bun run build"
29
- },
30
- "keywords": [
31
- "etch",
32
- "etchwp",
33
- "wordpress",
34
- "builder",
35
- "scripting",
36
- "api"
37
- ],
38
- "publishConfig": {
39
- "access": "public"
40
- },
41
- "devDependencies": {
42
- "tsup": "^8.3.5",
43
- "typescript": "^5.7.2",
44
- "vitest": "^3.0.5"
45
- }
2
+ "name": "@digital-gravy/etch-public-api",
3
+ "version": "0.7.1",
4
+ "description": "MIT-licensed typed client and contract for the Etch builder scripting API (window.etch). Etch itself is a separate proprietary product governed by its own commercial terms.",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/Digital-Gravy/etch-public-api.git"
9
+ },
10
+ "type": "module",
11
+ "main": "./dist/index.cjs",
12
+ "module": "./dist/index.js",
13
+ "types": "./dist/index.d.ts",
14
+ "exports": {
15
+ ".": {
16
+ "types": "./dist/index.d.ts",
17
+ "import": "./dist/index.js",
18
+ "require": "./dist/index.cjs"
19
+ }
20
+ },
21
+ "files": [
22
+ "dist",
23
+ "README.md"
24
+ ],
25
+ "sideEffects": false,
26
+ "scripts": {
27
+ "build": "tsup",
28
+ "dev": "tsup --watch",
29
+ "test": "vitest run",
30
+ "test:watch": "vitest",
31
+ "typecheck": "tsc --noEmit",
32
+ "lint": "bun run eslint && bun run format:check",
33
+ "eslint": "eslint .",
34
+ "format": "prettier --write .",
35
+ "format:check": "prettier --check .",
36
+ "prepublishOnly": "bun run build"
37
+ },
38
+ "keywords": [
39
+ "etch",
40
+ "etchwp",
41
+ "wordpress",
42
+ "builder",
43
+ "scripting",
44
+ "api"
45
+ ],
46
+ "publishConfig": {
47
+ "access": "public"
48
+ },
49
+ "devDependencies": {
50
+ "@eslint/js": "^9.39.2",
51
+ "eslint": "^9.39.2",
52
+ "eslint-config-prettier": "^10.1.8",
53
+ "globals": "^17.1.0",
54
+ "prettier": "^3.8.1",
55
+ "tsup": "^8.3.5",
56
+ "typescript": "^5.7.2",
57
+ "typescript-eslint": "^8.53.1",
58
+ "vitest": "^3.0.5"
59
+ }
46
60
  }