@fmaplabs/meta-manifest 0.2.0 → 0.4.0

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/README.md CHANGED
@@ -45,18 +45,72 @@ Author.parse(fields); // Shopify {key, jsonValue}[] -> typed, validated
45
45
  Author.encode({ name: "Ursula" }); // typed -> [{ key, value }] for metaobjectUpsert
46
46
  ```
47
47
 
48
- References between metaobjects are declared with `m.ref(...)` / `m.list(m.ref(...))`:
48
+ References between metaobjects are declared with `m.ref(...)` / `m.list(m.ref(...))`.
49
+ Use `m.mixedRef([...])` (and `m.list(m.mixedRef([...]))`) for a field that may point at
50
+ **several** metaobject types:
49
51
 
50
52
  ```ts
51
53
  export const Book = defineMetaobject("book", {
52
54
  name: "Book",
53
55
  fields: {
54
56
  title: m.text({ required: true }),
55
- author: m.ref(Author),
57
+ author: m.ref(Author), // → one Author
58
+ related: m.list(m.ref(Author)), // → many Authors
59
+ feature: m.mixedRef([Author, Publisher]), // → one Author *or* Publisher
56
60
  },
57
61
  });
58
62
  ```
59
63
 
64
+ `m.ref` maps to Shopify's `metaobject_reference` (a `metaobject_definition_type`
65
+ validation); `m.mixedRef` maps to `mixed_reference` (a `metaobject_definition_types`
66
+ validation). Targets are referenced by type, so `push` orders creates so a referenced
67
+ definition exists first — and a **reference cycle** is created two-pass (the
68
+ cycle-breaking fields are added by a follow-up update once every member exists).
69
+ Pass a thunk (`m.ref(() => Book)`, `m.mixedRef([() => Book])`) for forward/circular
70
+ references.
71
+
72
+ ### Configuration options
73
+
74
+ Beyond fields, a metaobject definition accepts these options — all optional, all
75
+ reconciled by `diff`/`push` against a live store:
76
+
77
+ ```ts
78
+ export const Author = defineMetaobject("author", {
79
+ name: "Author",
80
+ displayName: "name", // optional; omit → Shopify auto-generates
81
+ scope: "merchant", // optional; overrides config.scope for this metaobject
82
+ access: {
83
+ admin: "merchant_read_write", // "merchant_read" | "merchant_read_write" (app scope only)
84
+ storefront: "public_read", // "none" | "public_read"
85
+ customerAccount: "read", // "none" | "read"
86
+ },
87
+ capabilities: {
88
+ publishable: true, // active/draft status
89
+ translatable: true, // translations
90
+ renderable: { metaTitleKey: "name", metaDescriptionKey: "bio" }, // SEO metadata; also accepts `true`
91
+ onlineStore: { urlHandle: "authors", createRedirects: true }, // publish entries as web pages
92
+ },
93
+ fields: {
94
+ name: m.text({ required: true, filterable: true }), // filterable → "use as filter" in the admin
95
+ bio: m.multilineText(),
96
+ },
97
+ });
98
+ ```
99
+
100
+ | Option | Maps to | Notes |
101
+ | --- | --- | --- |
102
+ | `scope` (config or per-metaobject) | app (`$app:<handle>`) vs merchant (`<handle>`) `type` | default `"app"`; resolved at sync time — `Author.type` stays `"$app:author"` |
103
+ | `merchantEditable` (config) | `access.admin` default | `false` → `merchant_read`, `true` → `merchant_read_write` (app scope only) |
104
+ | `access.admin` | `access.admin` | per-metaobject override; invalid on merchant scope |
105
+ | `access.storefront` | `access.storefront` | Storefront API access |
106
+ | `access.customerAccount` | `access.customerAccount` | Customer Account API access (`none` \| `read`) |
107
+ | `capabilities.publishable` | `capabilities.publishable` | active/draft status |
108
+ | `capabilities.translatable` | `capabilities.translatable` | translations |
109
+ | `capabilities.renderable` | `capabilities.renderable` | `true` or `{ metaTitleKey?, metaDescriptionKey? }` (SEO) |
110
+ | `capabilities.onlineStore` | `capabilities.onlineStore` | publish as web pages; GraphQL-only (not `shopify.app.toml`) |
111
+ | `displayName` | `displayNameKey` | omit to let Shopify auto-generate |
112
+ | field `filterable` | field `capabilities.adminFilterable` | expose the field as an admin filter |
113
+
60
114
  For the full `pull` → `diff` → `push` sync model (how local schema and a live store are
61
115
  reconciled, destructive-change gating, dependency ordering, error handling), see
62
116
  [`docs/SYNC.md`](./docs/SYNC.md).
@@ -79,6 +133,8 @@ export default defineConfig({
79
133
  accessToken: process.env.SHOPIFY_ADMIN_TOKEN!,
80
134
  apiVersion: "2026-07", // optional; defaults to DEFAULT_API_VERSION
81
135
  schema: "./src/schema.ts", // where `pull` writes, `diff`/`push` read
136
+ scope: "app", // optional; "app" (default) | "merchant" — applies to all metaobjects
137
+ merchantEditable: false, // optional; default admin access for app-scoped metaobjects
82
138
  });
83
139
  ```
84
140
 
@@ -120,4 +176,4 @@ config/transport error, and `0` otherwise — including when destructive ops wer
120
176
 
121
177
  v1 covers metaobject **definitions** (schema sync) only. A runtime client for reading/writing
122
178
  metaobject **entries** — the tento-style query API — is not implemented yet and is tracked as a
123
- follow-up, along with codegen of `access`/`capabilities` config.
179
+ follow-up.
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  DEFAULT_API_VERSION,
3
3
  SyncTransportError
4
- } from "./chunk-3R6VQ3Z3.js";
4
+ } from "./chunk-VSJUGUH7.js";
5
5
 
6
6
  // src/node/client.ts
7
7
  function createAdminClient(opts) {
@@ -28,4 +28,4 @@ function createAdminClient(opts) {
28
28
  export {
29
29
  createAdminClient
30
30
  };
31
- //# sourceMappingURL=chunk-PFU5VAO7.js.map
31
+ //# sourceMappingURL=chunk-AUR2YQCW.js.map