@fmaplabs/meta-manifest 0.2.0 → 0.3.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 +45 -1
- package/dist/{chunk-PFU5VAO7.js → chunk-AUR2YQCW.js} +2 -2
- package/dist/{chunk-3R6VQ3Z3.js → chunk-VSJUGUH7.js} +15 -3
- package/dist/chunk-VSJUGUH7.js.map +1 -0
- package/dist/{chunk-GH5DXHS5.js → chunk-ZTWFDJHN.js} +318 -54
- package/dist/chunk-ZTWFDJHN.js.map +1 -0
- package/dist/cli/index.cjs +306 -32
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +35 -14
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +332 -54
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +168 -36
- package/dist/index.d.ts +168 -36
- package/dist/index.js +6 -2
- package/dist/node/client.cjs.map +1 -1
- package/dist/node/client.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-3R6VQ3Z3.js.map +0 -1
- package/dist/chunk-GH5DXHS5.js.map +0 -1
- /package/dist/{chunk-PFU5VAO7.js.map → chunk-AUR2YQCW.js.map} +0 -0
package/README.md
CHANGED
|
@@ -57,6 +57,48 @@ export const Book = defineMetaobject("book", {
|
|
|
57
57
|
});
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
+
### Configuration options
|
|
61
|
+
|
|
62
|
+
Beyond fields, a metaobject definition accepts these options — all optional, all
|
|
63
|
+
reconciled by `diff`/`push` against a live store:
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
export const Author = defineMetaobject("author", {
|
|
67
|
+
name: "Author",
|
|
68
|
+
displayName: "name", // optional; omit → Shopify auto-generates
|
|
69
|
+
scope: "merchant", // optional; overrides config.scope for this metaobject
|
|
70
|
+
access: {
|
|
71
|
+
admin: "merchant_read_write", // "merchant_read" | "merchant_read_write" (app scope only)
|
|
72
|
+
storefront: "public_read", // "none" | "public_read"
|
|
73
|
+
customerAccount: "read", // "none" | "read"
|
|
74
|
+
},
|
|
75
|
+
capabilities: {
|
|
76
|
+
publishable: true, // active/draft status
|
|
77
|
+
translatable: true, // translations
|
|
78
|
+
renderable: { metaTitleKey: "name", metaDescriptionKey: "bio" }, // SEO metadata; also accepts `true`
|
|
79
|
+
onlineStore: { urlHandle: "authors", createRedirects: true }, // publish entries as web pages
|
|
80
|
+
},
|
|
81
|
+
fields: {
|
|
82
|
+
name: m.text({ required: true, filterable: true }), // filterable → "use as filter" in the admin
|
|
83
|
+
bio: m.multilineText(),
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
| Option | Maps to | Notes |
|
|
89
|
+
| --- | --- | --- |
|
|
90
|
+
| `scope` (config or per-metaobject) | app (`$app:<handle>`) vs merchant (`<handle>`) `type` | default `"app"`; resolved at sync time — `Author.type` stays `"$app:author"` |
|
|
91
|
+
| `merchantEditable` (config) | `access.admin` default | `false` → `merchant_read`, `true` → `merchant_read_write` (app scope only) |
|
|
92
|
+
| `access.admin` | `access.admin` | per-metaobject override; invalid on merchant scope |
|
|
93
|
+
| `access.storefront` | `access.storefront` | Storefront API access |
|
|
94
|
+
| `access.customerAccount` | `access.customerAccount` | Customer Account API access (`none` \| `read`) |
|
|
95
|
+
| `capabilities.publishable` | `capabilities.publishable` | active/draft status |
|
|
96
|
+
| `capabilities.translatable` | `capabilities.translatable` | translations |
|
|
97
|
+
| `capabilities.renderable` | `capabilities.renderable` | `true` or `{ metaTitleKey?, metaDescriptionKey? }` (SEO) |
|
|
98
|
+
| `capabilities.onlineStore` | `capabilities.onlineStore` | publish as web pages; GraphQL-only (not `shopify.app.toml`) |
|
|
99
|
+
| `displayName` | `displayNameKey` | omit to let Shopify auto-generate |
|
|
100
|
+
| field `filterable` | field `capabilities.adminFilterable` | expose the field as an admin filter |
|
|
101
|
+
|
|
60
102
|
For the full `pull` → `diff` → `push` sync model (how local schema and a live store are
|
|
61
103
|
reconciled, destructive-change gating, dependency ordering, error handling), see
|
|
62
104
|
[`docs/SYNC.md`](./docs/SYNC.md).
|
|
@@ -79,6 +121,8 @@ export default defineConfig({
|
|
|
79
121
|
accessToken: process.env.SHOPIFY_ADMIN_TOKEN!,
|
|
80
122
|
apiVersion: "2026-07", // optional; defaults to DEFAULT_API_VERSION
|
|
81
123
|
schema: "./src/schema.ts", // where `pull` writes, `diff`/`push` read
|
|
124
|
+
scope: "app", // optional; "app" (default) | "merchant" — applies to all metaobjects
|
|
125
|
+
merchantEditable: false, // optional; default admin access for app-scoped metaobjects
|
|
82
126
|
});
|
|
83
127
|
```
|
|
84
128
|
|
|
@@ -120,4 +164,4 @@ config/transport error, and `0` otherwise — including when destructive ops wer
|
|
|
120
164
|
|
|
121
165
|
v1 covers metaobject **definitions** (schema sync) only. A runtime client for reading/writing
|
|
122
166
|
metaobject **entries** — the tento-style query API — is not implemented yet and is tracked as a
|
|
123
|
-
follow-up
|
|
167
|
+
follow-up.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DEFAULT_API_VERSION,
|
|
3
3
|
SyncTransportError
|
|
4
|
-
} from "./chunk-
|
|
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-
|
|
31
|
+
//# sourceMappingURL=chunk-AUR2YQCW.js.map
|
|
@@ -28,12 +28,14 @@ var PULL_DEFINITION_QUERY = `query PullMetaobjectDefinition($type: String!) {
|
|
|
28
28
|
required
|
|
29
29
|
type { name }
|
|
30
30
|
validations { name value }
|
|
31
|
+
capabilities { adminFilterable { enabled } }
|
|
31
32
|
}
|
|
32
|
-
access { admin storefront }
|
|
33
|
+
access { admin storefront customerAccount }
|
|
33
34
|
capabilities {
|
|
34
35
|
publishable { enabled }
|
|
35
36
|
translatable { enabled }
|
|
36
|
-
renderable { enabled }
|
|
37
|
+
renderable { enabled data { metaTitleKey metaDescriptionKey } }
|
|
38
|
+
onlineStore { enabled data { urlHandle } }
|
|
37
39
|
}
|
|
38
40
|
}
|
|
39
41
|
}`;
|
|
@@ -43,6 +45,8 @@ var LIST_DEFINITIONS_QUERY = `query ListMetaobjectDefinitions($after: String) {
|
|
|
43
45
|
id
|
|
44
46
|
name
|
|
45
47
|
type
|
|
48
|
+
description
|
|
49
|
+
displayNameKey
|
|
46
50
|
fieldDefinitions {
|
|
47
51
|
key
|
|
48
52
|
name
|
|
@@ -50,6 +54,14 @@ var LIST_DEFINITIONS_QUERY = `query ListMetaobjectDefinitions($after: String) {
|
|
|
50
54
|
required
|
|
51
55
|
type { name }
|
|
52
56
|
validations { name value }
|
|
57
|
+
capabilities { adminFilterable { enabled } }
|
|
58
|
+
}
|
|
59
|
+
access { admin storefront customerAccount }
|
|
60
|
+
capabilities {
|
|
61
|
+
publishable { enabled }
|
|
62
|
+
translatable { enabled }
|
|
63
|
+
renderable { enabled data { metaTitleKey metaDescriptionKey } }
|
|
64
|
+
onlineStore { enabled data { urlHandle } }
|
|
53
65
|
}
|
|
54
66
|
}
|
|
55
67
|
pageInfo { hasNextPage endCursor }
|
|
@@ -94,4 +106,4 @@ export {
|
|
|
94
106
|
SyncTransportError,
|
|
95
107
|
execute
|
|
96
108
|
};
|
|
97
|
-
//# sourceMappingURL=chunk-
|
|
109
|
+
//# sourceMappingURL=chunk-VSJUGUH7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/config.ts","../src/sync/client.ts"],"sourcesContent":["export const DEFAULT_API_VERSION = \"2026-07\";\n\nexport interface Config {\n /** e.g. \"my-store.myshopify.com\" */\n shop: string;\n /** Admin API access token; reference via process.env in your config file. */\n accessToken: string;\n /** Admin API version. Defaults to DEFAULT_API_VERSION. */\n apiVersion?: string;\n /** Path to the schema module whose `schemas` export drives diff/push, and pull writes. */\n schema: string;\n /** Scope for all metaobjects, unless overridden per-metaobject. Defaults to \"app\". */\n scope?: \"app\" | \"merchant\";\n /** Default admin access for app-scoped metaobjects: false → merchant_read, true → merchant_read_write. Defaults to false. */\n merchantEditable?: boolean;\n}\n\n/** Identity helper for type inference in `meta-manifest.config.ts`. */\nexport function defineConfig(config: Config): Config {\n return config;\n}\n\n/** Validate a loaded config object, throwing a one-line Error naming the first missing field. */\nexport function validateConfig(raw: unknown): Config {\n const c = raw as Partial<Config> | null | undefined;\n for (const key of [\"shop\", \"accessToken\", \"schema\"] as const) {\n if (!c || typeof c[key] !== \"string\" || c[key] === \"\") {\n throw new Error(`Invalid config: missing or empty \"${key}\".`);\n }\n }\n return c as Config;\n}\n","/**\n * The minimal Admin GraphQL transport the sync adapter depends on. The app\n * supplies a concrete implementation at its edge (wrapping `admin.graphql`),\n * keeping `@fmaplabs/meta-manifest` free of any runtime dependency on a GraphQL\n * client. [design §5]\n */\nexport interface AdminGraphQLClient {\n (query: string, options?: { variables?: Record<string, unknown> }): Promise<{ data?: unknown; errors?: unknown }>;\n}\n\n// GraphQL operation strings, copied verbatim from the schema-validated documents\n// in the design spec §3. Re-validated against Admin API 2026-07 during planning.\n// Do not edit by hand — keep equal to the validated documents (drift guard, §12).\n\nexport const PULL_DEFINITION_QUERY = `query PullMetaobjectDefinition($type: String!) {\n metaobjectDefinitionByType(type: $type) {\n id\n name\n type\n description\n displayNameKey\n fieldDefinitions {\n key\n name\n description\n required\n type { name }\n validations { name value }\n capabilities { adminFilterable { enabled } }\n }\n access { admin storefront customerAccount }\n capabilities {\n publishable { enabled }\n translatable { enabled }\n renderable { enabled data { metaTitleKey metaDescriptionKey } }\n onlineStore { enabled data { urlHandle } }\n }\n }\n}`;\n\nexport const LIST_DEFINITIONS_QUERY = `query ListMetaobjectDefinitions($after: String) {\n metaobjectDefinitions(first: 50, after: $after) {\n nodes {\n id\n name\n type\n description\n displayNameKey\n fieldDefinitions {\n key\n name\n description\n required\n type { name }\n validations { name value }\n capabilities { adminFilterable { enabled } }\n }\n access { admin storefront customerAccount }\n capabilities {\n publishable { enabled }\n translatable { enabled }\n renderable { enabled data { metaTitleKey metaDescriptionKey } }\n onlineStore { enabled data { urlHandle } }\n }\n }\n pageInfo { hasNextPage endCursor }\n }\n}`;\n\nexport const CREATE_DEFINITION_MUTATION = `mutation CreateMetaobjectDefinition($definition: MetaobjectDefinitionCreateInput!) {\n metaobjectDefinitionCreate(definition: $definition) {\n metaobjectDefinition { id type }\n userErrors { field message code }\n }\n}`;\n\nexport const UPDATE_DEFINITION_MUTATION = `mutation UpdateMetaobjectDefinition($id: ID!, $definition: MetaobjectDefinitionUpdateInput!) {\n metaobjectDefinitionUpdate(id: $id, definition: $definition) {\n metaobjectDefinition { id type }\n userErrors { field message code }\n }\n}`;\n\n/**\n * Thrown when a request fails at the transport or top-level GraphQL layer —\n * distinct from per-op `userErrors`, which `push` reports as `failed` rather\n * than throwing. Carries the offending top-level `errors` payload. [design §5]\n */\nexport class SyncTransportError extends Error {\n constructor(message: string, readonly errors: unknown) {\n super(message);\n this.name = \"SyncTransportError\";\n }\n}\n\n/**\n * Runs an operation through the injected client and returns its `data`.\n * A non-empty top-level `errors` payload becomes a `SyncTransportError`;\n * a rejected transport promise propagates unchanged. [design §5]\n */\nexport async function execute<T>(\n client: AdminGraphQLClient,\n query: string,\n variables?: Record<string, unknown>,\n): Promise<T> {\n const result = await client(query, variables ? { variables } : undefined);\n if (Array.isArray(result.errors) ? result.errors.length > 0 : result.errors != null) {\n throw new SyncTransportError(\"GraphQL request failed\", result.errors);\n }\n return result.data as T;\n}\n"],"mappings":";AAAO,IAAM,sBAAsB;AAkB5B,SAAS,aAAa,QAAwB;AACnD,SAAO;AACT;AAGO,SAAS,eAAe,KAAsB;AACnD,QAAM,IAAI;AACV,aAAW,OAAO,CAAC,QAAQ,eAAe,QAAQ,GAAY;AAC5D,QAAI,CAAC,KAAK,OAAO,EAAE,GAAG,MAAM,YAAY,EAAE,GAAG,MAAM,IAAI;AACrD,YAAM,IAAI,MAAM,qCAAqC,GAAG,IAAI;AAAA,IAC9D;AAAA,EACF;AACA,SAAO;AACT;;;ACjBO,IAAM,wBAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA0B9B,IAAM,yBAAyB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA6B/B,IAAM,6BAA6B;AAAA;AAAA;AAAA;AAAA;AAAA;AAOnC,IAAM,6BAA6B;AAAA;AAAA;AAAA;AAAA;AAAA;AAYnC,IAAM,qBAAN,cAAiC,MAAM;AAAA,EAC5C,YAAY,SAA0B,QAAiB;AACrD,UAAM,OAAO;AADuB;AAEpC,SAAK,OAAO;AAAA,EACd;AAAA,EAHsC;AAIxC;AAOA,eAAsB,QACpB,QACA,OACA,WACY;AACZ,QAAM,SAAS,MAAM,OAAO,OAAO,YAAY,EAAE,UAAU,IAAI,MAAS;AACxE,MAAI,MAAM,QAAQ,OAAO,MAAM,IAAI,OAAO,OAAO,SAAS,IAAI,OAAO,UAAU,MAAM;AACnF,UAAM,IAAI,mBAAmB,0BAA0B,OAAO,MAAM;AAAA,EACtE;AACA,SAAO,OAAO;AAChB;","names":[]}
|