@graphcommerce/hygraph-cli 6.2.0-canary.82 → 6.2.0-canary.83

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.
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./graphcommerce5to6"), exports);
18
+ __exportStar(require("./graphcommerce6to7"), exports);
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.readSchema = void 0;
4
+ const client_1 = require("@apollo/client");
5
+ const fetch_1 = require("@whatwg-node/fetch");
6
+ const readSchema = async (config) => {
7
+ if (!config.hygraphProjectId) {
8
+ throw new Error('Please provide GC_HYGRAPH_PROJECT_ID in your env file');
9
+ }
10
+ if (!config.hygraphWriteAccessToken) {
11
+ throw new Error('Please provide GC_HYGRAPH_WRITE_ACCESS_TOKEN in your env file');
12
+ }
13
+ const projectId = config.hygraphProjectId;
14
+ const hygraphClient = new client_1.ApolloClient({
15
+ link: new client_1.HttpLink({
16
+ uri: 'https://management.hygraph.com/graphql',
17
+ fetch: fetch_1.fetch,
18
+ headers: { Authorization: `Bearer ${config.hygraphWriteAccessToken}` },
19
+ }),
20
+ cache: new client_1.InMemoryCache(),
21
+ });
22
+ const { data } = await hygraphClient.query({
23
+ query: (0, client_1.gql) `
24
+ query getSchema($projectId: ID!) {
25
+ viewer {
26
+ project(id: $projectId) {
27
+ environment(name: "master") {
28
+ contentModel {
29
+ models {
30
+ apiId
31
+ apiIdPlural
32
+ fields {
33
+ apiId
34
+ }
35
+ }
36
+ components {
37
+ apiId
38
+ apiIdPlural
39
+ fields {
40
+ apiId
41
+ }
42
+ }
43
+ enumerations {
44
+ apiId
45
+ }
46
+ }
47
+ }
48
+ }
49
+ }
50
+ }
51
+ `,
52
+ variables: {
53
+ projectId,
54
+ },
55
+ });
56
+ return data;
57
+ };
58
+ exports.readSchema = readSchema;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@graphcommerce/hygraph-cli",
3
3
  "homepage": "https://www.graphcommerce.org/",
4
4
  "repository": "github:graphcommerce-org/graphcommerce",
5
- "version": "6.2.0-canary.82",
5
+ "version": "6.2.0-canary.83",
6
6
  "author": "",
7
7
  "license": "MIT",
8
8
  "scripts": {
@@ -14,21 +14,22 @@
14
14
  "main": "dist/index.js",
15
15
  "types": "src/index.ts",
16
16
  "dependencies": {
17
- "@graphcommerce/next-config": "6.2.0-canary.82",
18
- "@graphql-codegen/cli": "4.0.1",
19
- "@graphql-mesh/cli": "latest",
20
- "@graphql-mesh/types": "latest",
21
- "@graphql-mesh/utils": "latest",
17
+ "@apollo/client": "~3.7.17",
18
+ "@graphcommerce/next-config": "6.2.0-canary.83",
22
19
  "@hygraph/management-sdk": "^1.1.2-alpha.1",
23
- "graphql-tag": "^2.12.6"
20
+ "graphql-tag": "^2.12.6",
21
+ "prompts": "^2.4.2",
22
+ "@whatwg-node/fetch": "^0.9.4"
24
23
  },
25
24
  "peerDependencies": {
26
- "graphql": "^16.7.1"
25
+ "graphql": "^16.7.1",
26
+ "dotenv": "^16.1.4"
27
27
  },
28
28
  "devDependencies": {
29
- "@graphcommerce/eslint-config-pwa": "6.2.0-canary.82",
30
- "@graphcommerce/prettier-config-pwa": "6.2.0-canary.82",
31
- "@graphcommerce/typescript-config-pwa": "6.2.0-canary.82",
29
+ "@types/prompts": "^2.4.4",
30
+ "@graphcommerce/eslint-config-pwa": "6.2.0-canary.83",
31
+ "@graphcommerce/prettier-config-pwa": "6.2.0-canary.83",
32
+ "@graphcommerce/typescript-config-pwa": "6.2.0-canary.83",
32
33
  "typescript": "5.1.3"
33
34
  },
34
35
  "sideEffects": false,
package/src/client.ts ADDED
@@ -0,0 +1,25 @@
1
+ import { GraphCommerceConfig } from '@graphcommerce/next-config'
2
+ import { Client } from '@hygraph/management-sdk'
3
+ import { graphcommerceLog } from './log-functions'
4
+
5
+ export const initClient = (config: GraphCommerceConfig, name: string | undefined) => {
6
+ if (!config.hygraphWriteAccessEndpoint) {
7
+ graphcommerceLog(
8
+ 'Please provide hygraphWriteAccessEndpoint in your config or GC_HYGRAPH_WRITE_ACCESS_ENDPOINT in your env file',
9
+ 'error',
10
+ )
11
+
12
+ return 0
13
+ }
14
+ if (!config.hygraphWriteAccessToken) {
15
+ graphcommerceLog('Please provide GC_HYGRAPH_WRITE_ACCESS_TOKEN in your env file')
16
+
17
+ return 0
18
+ }
19
+
20
+ return new Client({
21
+ authToken: config.hygraphWriteAccessToken,
22
+ endpoint: config.hygraphWriteAccessEndpoint,
23
+ name,
24
+ })
25
+ }
@@ -0,0 +1,12 @@
1
+ export const capitalize = (word: string) =>
2
+ word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()
3
+
4
+ export const graphcommerceLog = (message: string, type?: 'info' | 'warning' | 'error') => {
5
+ const color = {
6
+ error: '\x1b[31m\x1b[1m%s\x1b[0m',
7
+ warning: '\x1b[33m\x1b[1m%s\x1b[0m',
8
+ info: '\x1b[36m\x1b[1m%s\x1b[0m',
9
+ }
10
+ // eslint-disable-next-line no-console
11
+ console.log(type ? color[type] : '', `[GraphCommerce]: ${message}`)
12
+ }
@@ -1,73 +1,86 @@
1
- /* eslint-disable no-console */
2
- /* eslint-disable import/no-extraneous-dependencies */
3
- import readline from 'readline'
1
+ import fs from 'fs'
2
+ import { loadConfig } from '@graphcommerce/next-config'
4
3
  import { MigrationInfo } from '@hygraph/management-sdk/dist/ManagementAPIClient'
5
- import { dynamicRow } from './migrations/dynamicRow'
4
+ import dotenv from 'dotenv'
5
+ import prompts, { PromptObject } from 'prompts'
6
+ import { graphcommerceLog } from './log-functions'
7
+ import * as migrations from './migrations'
8
+ import { readSchema } from './readSchema'
9
+ import { Schema } from './types'
6
10
 
7
- export async function migrateHygraph() {
8
- let forceRun = false
9
-
10
- // Interface to determine if force run should be enabled
11
- readline.createInterface({
12
- input: process.stdin,
13
- output: process.stdout,
14
- })
11
+ dotenv.config()
15
12
 
16
- const affirmativeAnswers = ['y', 'yes', 'Y', 'YES']
13
+ export async function migrateHygraph() {
14
+ const config = loadConfig(process.cwd())
17
15
 
18
- const handleKeypress = (key: string) => {
19
- if (affirmativeAnswers.includes(key.toLowerCase())) {
20
- console.log('\nForce run enabled')
21
- forceRun = true
22
- } else {
23
- console.log('\nForce run disabled')
24
- forceRun = false
25
- }
16
+ /**
17
+ * Extracting the current GC version. Are we gonna use the current version to determine which
18
+ * scripts should be runned? Or do we let the user pick the migration from a list? 🤔
19
+ */
20
+ const packageJson = fs.readFileSync('package.json', 'utf8')
21
+ const packageData = JSON.parse(packageJson)
22
+ const graphcommerceVersion = packageData.dependencies['@graphcommerce/next-ui']
26
23
 
27
- process.stdin.pause()
28
- }
24
+ graphcommerceLog(`Graphcommerce version: ${graphcommerceVersion}`, 'info')
29
25
 
30
- // Listen for keypress events
31
- process.stdin.on('keypress', handleKeypress)
32
- process.stdin.setRawMode(true)
33
- process.stdin.resume()
26
+ // Extract the currently existing models, components and enumerations from the Hygraph schema.
27
+ const schemaViewer = await readSchema(config)
28
+ const schema: Schema = schemaViewer.viewer.project.environment.contentModel
34
29
 
35
- console.log('Enable force run? (y/n)')
30
+ // A list of possible migrations
31
+ const possibleMigrations: [string, (schema: Schema) => Promise<0 | MigrationInfo>][] =
32
+ Object.entries(migrations)
36
33
 
37
- // Wait for input
38
- await new Promise<void>((resolve) => {
39
- process.stdin.once('data', () => {
40
- // Stop listening for input
41
- process.stdin.removeListener('keypress', handleKeypress)
42
- process.stdin.setRawMode(false)
34
+ // Here we setup the list we ask the user to choose from
35
+ const selectMigrationInput: PromptObject<string> | PromptObject<string>[] = {
36
+ type: 'select',
37
+ name: 'selectedMigration',
38
+ message: '\x1b[36m\x1b[1m[GraphCommerce]: Select migration',
39
+ choices: [],
40
+ }
43
41
 
44
- resolve()
45
- })
46
- })
42
+ for (const [name, migration] of possibleMigrations) {
43
+ if (Array.isArray(selectMigrationInput.choices)) {
44
+ selectMigrationInput?.choices?.push({ title: name, value: { name, migration } })
45
+ }
46
+ }
47
47
 
48
- // TODO: Choose migration
49
- // TODO: GC-Version based migration
50
- const possibleMigrations: [string, (name: string | undefined) => Promise<MigrationInfo>][] = [
51
- ['add_dynamic_rows', dynamicRow],
52
- ]
48
+ // Here we ask the user to choose a migration from a list of possible migrations
49
+ try {
50
+ graphcommerceLog('Available migrations: ', 'info')
51
+ const selectMigrationOutput = await prompts(selectMigrationInput)
52
+ const { migration, name } = selectMigrationOutput.selectedMigration
53
+ graphcommerceLog(
54
+ `You have selected the ${selectMigrationOutput.selectedMigration.name} migration`,
55
+ 'info',
56
+ )
53
57
 
54
- for (const [name, migration] of possibleMigrations) {
55
58
  try {
59
+ // Here we try to run the migration
56
60
  // eslint-disable-next-line no-await-in-loop
57
- const result = await migration(forceRun ? undefined : name)
58
- console.log(result)
61
+ const result = await migration(schema)
59
62
 
63
+ graphcommerceLog(`Migration result: ${JSON.stringify(result)}`, 'info')
64
+ if (!result) {
65
+ throw new Error(
66
+ '[GraphCommerce]: No migration client found. Please make sure your GC_HYGRAPH_WRITE_ACCESS_ENDPOINT and GC_HYGRAPH_WRITE_ACCESS_TOKEN in your env file are correct.',
67
+ )
68
+ }
60
69
  if (result.status !== 'SUCCESS') {
61
- throw new Error(`Migration not successful: ${result.status} ${name}:\n${result.errors}`)
70
+ throw new Error(
71
+ `[GraphCommerce]: Migration not successful: ${result.status} ${name}:\n${result.errors}`,
72
+ )
62
73
  }
63
74
 
64
- console.log(`Migration successful: ${name}`)
75
+ graphcommerceLog(`Migration successful: ${name}`, 'info')
65
76
  } catch (err) {
66
77
  if (err instanceof Error) {
67
78
  const garbledErrorIndex = err.message.indexOf(': {"')
68
79
  const msg = garbledErrorIndex > 0 ? err.message.slice(0, garbledErrorIndex) : err.message
69
- console.error(msg)
80
+ graphcommerceLog(`${msg}`, 'error')
70
81
  }
71
82
  }
83
+ } catch (error) {
84
+ graphcommerceLog(`[GraphCommerce]: An error occurred: ${error}`, 'error')
72
85
  }
73
86
  }
@@ -0,0 +1,217 @@
1
+ import { loadConfig } from '@graphcommerce/next-config'
2
+ import {
3
+ BatchMigrationCreateModelInput,
4
+ BatchMigrationCreateComponentInput,
5
+ BatchMigrationCreateEnumerationInput,
6
+ BatchMigrationCreateSimpleFieldInput,
7
+ BatchMigrationCreateEnumerableFieldInput,
8
+ BatchMigrationCreateRelationalFieldInput,
9
+ BatchMigrationCreateUnionFieldInput,
10
+ BatchMigrationCreateComponentFieldInput,
11
+ BatchMigrationDeleteComponentInput,
12
+ BatchMigrationDeleteEnumerationInput,
13
+ BatchMigrationDeleteModelInput,
14
+ BatchMigrationUpdateComponentFieldInput,
15
+ BatchMigrationUpdateComponentInput,
16
+ BatchMigrationUpdateEnumerableFieldInput,
17
+ BatchMigrationUpdateEnumerationInput,
18
+ BatchMigrationUpdateModelInput,
19
+ BatchMigrationUpdateRelationalFieldInput,
20
+ BatchMigrationUpdateSimpleFieldInput,
21
+ BatchMigrationUpdateUnionFieldInput,
22
+ BatchMigrationDeleteFieldInput,
23
+ BatchMigrationCreateComponentUnionFieldInput,
24
+ BatchMigrationUpdateComponentUnionFieldInput,
25
+ } from '@hygraph/management-sdk'
26
+ import dotenv from 'dotenv'
27
+ import { initClient } from './client'
28
+ import { graphcommerceLog, capitalize } from './log-functions'
29
+ import { Schema } from './types'
30
+
31
+ dotenv.config()
32
+ const config = loadConfig(process.cwd())
33
+
34
+ export const client = initClient(config, undefined)
35
+
36
+ type AllActions =
37
+ | BatchMigrationCreateModelInput
38
+ | BatchMigrationUpdateModelInput
39
+ | BatchMigrationDeleteModelInput
40
+ | BatchMigrationCreateComponentInput
41
+ | BatchMigrationUpdateComponentInput
42
+ | BatchMigrationDeleteComponentInput
43
+ | BatchMigrationCreateEnumerationInput
44
+ | BatchMigrationUpdateEnumerationInput
45
+ | BatchMigrationDeleteEnumerationInput
46
+ | BatchMigrationCreateSimpleFieldInput // type: SimpleFieldType
47
+ | BatchMigrationUpdateSimpleFieldInput
48
+ | BatchMigrationCreateEnumerableFieldInput
49
+ | BatchMigrationUpdateEnumerableFieldInput
50
+ | BatchMigrationCreateRelationalFieldInput // type: RelationalFieldType
51
+ | BatchMigrationUpdateRelationalFieldInput
52
+ | BatchMigrationCreateUnionFieldInput
53
+ | BatchMigrationUpdateUnionFieldInput
54
+ | BatchMigrationCreateComponentFieldInput
55
+ | BatchMigrationUpdateComponentFieldInput
56
+ | BatchMigrationDeleteFieldInput
57
+ | BatchMigrationCreateComponentUnionFieldInput
58
+ | BatchMigrationUpdateComponentUnionFieldInput
59
+
60
+ /**
61
+ * This constant is used to assign the right action of the management SDK to the migratioAction
62
+ * function
63
+ */
64
+ const actionMap = client
65
+ ? {
66
+ create: {
67
+ model: (innerprops: BatchMigrationCreateModelInput) => client.createModel(innerprops),
68
+ component: (innerprops: BatchMigrationCreateComponentInput) =>
69
+ client.createComponent(innerprops),
70
+ enumeration: (innerprops: BatchMigrationCreateEnumerationInput) =>
71
+ client.createEnumeration(innerprops),
72
+ simpleField: (innerprops: BatchMigrationCreateSimpleFieldInput) =>
73
+ client.createSimpleField(innerprops),
74
+ enumerableField: (innerprops: BatchMigrationCreateEnumerableFieldInput) =>
75
+ client.createEnumerableField(innerprops),
76
+ componentField: (innerprops: BatchMigrationCreateComponentFieldInput) =>
77
+ client.createComponentField(innerprops),
78
+ relationalField: (innerprops: BatchMigrationCreateRelationalFieldInput) =>
79
+ client.createRelationalField(innerprops),
80
+ unionField: (innerprops: BatchMigrationCreateUnionFieldInput) =>
81
+ client.createUnionField(innerprops),
82
+ componentUnionField: (innerprops: BatchMigrationCreateComponentUnionFieldInput) =>
83
+ client.createComponentUnionField(innerprops),
84
+ },
85
+ update: {
86
+ model: (innerprops: BatchMigrationUpdateModelInput) => client.updateModel(innerprops),
87
+ component: (innerprops: BatchMigrationUpdateComponentInput) =>
88
+ client.updateComponent(innerprops),
89
+ enumeration: (innerprops: BatchMigrationUpdateEnumerationInput) =>
90
+ client.updateEnumeration(innerprops),
91
+ simpleField: (innerprops: BatchMigrationUpdateSimpleFieldInput) =>
92
+ client.updateSimpleField(innerprops),
93
+ enumerableField: (innerprops: BatchMigrationUpdateEnumerableFieldInput) =>
94
+ client.updateEnumerableField(innerprops),
95
+ componentField: (innerprops: BatchMigrationUpdateComponentFieldInput) =>
96
+ client.updateComponentField(innerprops),
97
+ relationalField: (innerprops: BatchMigrationUpdateRelationalFieldInput) =>
98
+ client.updateRelationalField(innerprops),
99
+ unionField: (innerprops: BatchMigrationUpdateUnionFieldInput) =>
100
+ client.updateUnionField(innerprops),
101
+ componentUnionField: (innerprops: BatchMigrationUpdateComponentUnionFieldInput) =>
102
+ client.updateComponentUnionField(innerprops),
103
+ },
104
+ delete: {
105
+ model: (innerprops: BatchMigrationDeleteModelInput) => client.deleteModel(innerprops),
106
+ component: (innerprops: BatchMigrationDeleteComponentInput) =>
107
+ client.deleteComponent(innerprops),
108
+ enumeration: (innerprops: BatchMigrationDeleteEnumerationInput) =>
109
+ client.deleteEnumeration(innerprops),
110
+ simpleField: (innerprops: BatchMigrationDeleteFieldInput) => client.deleteField(innerprops),
111
+ enumerableField: (innerprops: BatchMigrationDeleteFieldInput) =>
112
+ client.deleteField(innerprops),
113
+ componentField: (innerprops: BatchMigrationDeleteFieldInput) =>
114
+ client.deleteField(innerprops),
115
+ relationalField: (innerprops: BatchMigrationDeleteFieldInput) =>
116
+ client.deleteField(innerprops),
117
+ unionField: (innerprops: BatchMigrationDeleteFieldInput) => client.deleteField(innerprops),
118
+ componentUnionField: (innerprops: BatchMigrationDeleteFieldInput) =>
119
+ client.deleteField(innerprops),
120
+ },
121
+ }
122
+ : undefined
123
+
124
+ /**
125
+ * This function is our variation on the client.migrationAction functions from the hygraph
126
+ * management sdk.
127
+ *
128
+ * MigrationAction() is better suited because it is a single function for all actions. More
129
+ * importantly, if the action fails, because a field with the apiID already exists for instance. it
130
+ * will skip this action but still continue the whole migration, while the management sdk function
131
+ * will bail.
132
+ *
133
+ * It takes the schema as argument, which is always the same.
134
+ *
135
+ * Then it takes the type of schema entity you want to do an action upon, and the action you want to
136
+ * do.
137
+ *
138
+ * The fourth arguments are the props that belong to the action you want to do. For instance, if you
139
+ * want to create a model, you need to pass the props that belong to a model.
140
+ *
141
+ * The last two arguments are optional. If you want to create a field, you need to pass the apiId of
142
+ * the model or component you want to create the field on. If you want to create a field on a
143
+ * component, you also need to pass the parentType, which is either 'model' or 'component'.
144
+ */
145
+ export const migrationAction = (
146
+ schema: Schema,
147
+ type:
148
+ | 'model'
149
+ | 'component'
150
+ | 'enumeration'
151
+ | 'simpleField'
152
+ | 'componentField'
153
+ | 'enumerableField'
154
+ | 'relationalField'
155
+ | 'unionField'
156
+ | 'componentUnionField',
157
+ action: 'create' | 'update' | 'delete',
158
+ props: AllActions,
159
+ parentApiId?: string,
160
+ parentType?: 'model' | 'component' | 'enumeration',
161
+ ) => {
162
+ // Check if the entity already exists
163
+ const alreadyExists = () => {
164
+ switch (type) {
165
+ case 'model':
166
+ return schema.models.some((model) => model.apiId === props.apiId)
167
+
168
+ case 'component':
169
+ return schema.components.some((component) => component.apiId === props.apiId)
170
+
171
+ case 'enumeration':
172
+ return schema.enumerations.some((enumeration) => enumeration.apiId === props.apiId)
173
+
174
+ case 'simpleField':
175
+ case 'enumerableField':
176
+ case 'relationalField':
177
+ case 'unionField':
178
+ case 'componentUnionField': {
179
+ let parent
180
+ switch (parentType) {
181
+ case 'model': {
182
+ parent = schema.models.find((model) => model.apiId === parentApiId)
183
+ break
184
+ }
185
+ case 'component': {
186
+ parent = schema.components.find((component) => component.apiId === parentApiId)
187
+ break
188
+ }
189
+ default:
190
+ return false // or undefined or any other value you want if no match
191
+ }
192
+ return parent?.fields.some((field) => field.apiId === props.apiId)
193
+ }
194
+ default: {
195
+ return false // or undefined or any other value you want if no match
196
+ }
197
+ }
198
+ }
199
+
200
+ const actionFunc = actionMap && actionMap[action] && actionMap[action][type]
201
+
202
+ if (!alreadyExists()) {
203
+ if (actionFunc) {
204
+ graphcommerceLog(`${capitalize(action)} ${type} with apiId ${props.apiId}...`)
205
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
206
+ // @ts-ignore | This error is a loss on typescript autocomplete, but the function is called correctly
207
+ actionFunc(props)
208
+ } else {
209
+ graphcommerceLog(`Action ${action} is not supported for ${type}`, 'error')
210
+ }
211
+ } else {
212
+ graphcommerceLog(
213
+ `${capitalize(type)} with apiId ${props.apiId} on ${parentApiId} already exists`,
214
+ 'warning',
215
+ )
216
+ }
217
+ }
@@ -0,0 +1,149 @@
1
+ import { RelationalFieldType, SimpleFieldType, VisibilityTypes } from '@hygraph/management-sdk'
2
+ import { migrationAction, client } from '../migrationAction'
3
+ import { Schema } from '../types'
4
+
5
+ export const graphcommerce5to6 = async (schema: Schema) => {
6
+ if (!client) {
7
+ return 0
8
+ }
9
+
10
+ // ? ENUMERATIONS
11
+ migrationAction(schema, 'enumeration', 'create', {
12
+ displayName: 'Row Links Variants',
13
+ apiId: 'RowLinksVariants',
14
+ values: [
15
+ { displayName: 'Inline', apiId: 'Inline' },
16
+ { displayName: 'Image Label Swiper', apiId: 'ImageLabelSwiper' },
17
+ { displayName: 'Logo Swiper', apiId: 'LogoSwiper' },
18
+ { displayName: 'USPS', apiId: 'Usps' },
19
+ ],
20
+ })
21
+
22
+ // ? MODEL
23
+ migrationAction(schema, 'model', 'create', {
24
+ apiId: 'RowLinks',
25
+ apiIdPlural: 'RowLinksMultiple',
26
+ displayName: 'Row Links',
27
+ description: 'Row Links is a Row of PageLinks with different variants',
28
+ })
29
+
30
+ migrationAction(
31
+ schema,
32
+ 'simpleField',
33
+ 'create',
34
+ {
35
+ displayName: 'Identity',
36
+ apiId: 'identity',
37
+ description: 'Only used for internal reference',
38
+ type: SimpleFieldType.String,
39
+ isTitle: true,
40
+ isRequired: true,
41
+ isUnique: true,
42
+ modelApiId: 'RowLinks',
43
+ },
44
+ 'RowLinks',
45
+ 'model',
46
+ )
47
+
48
+ migrationAction(
49
+ schema,
50
+ 'enumerableField',
51
+ 'create',
52
+ {
53
+ displayName: 'Variant',
54
+ apiId: 'linksVariant',
55
+ parentApiId: 'RowLinks',
56
+ enumerationApiId: 'RowLinksVariants',
57
+ description: 'Different variants for Row Links',
58
+ },
59
+ 'RowLinks',
60
+ 'model',
61
+ )
62
+
63
+ migrationAction(
64
+ schema,
65
+ 'simpleField',
66
+ 'create',
67
+ {
68
+ displayName: 'Title',
69
+ apiId: 'title',
70
+ type: SimpleFieldType.String,
71
+ isRequired: true,
72
+ modelApiId: 'RowLinks',
73
+ isLocalized: true,
74
+ },
75
+ 'RowLinks',
76
+ 'model',
77
+ )
78
+
79
+ migrationAction(
80
+ schema,
81
+ 'simpleField',
82
+ 'create',
83
+ {
84
+ displayName: 'Copy',
85
+ apiId: 'rowLinksCopy',
86
+ type: SimpleFieldType.Richtext,
87
+ isLocalized: true,
88
+ modelApiId: 'RowLinks',
89
+ },
90
+ 'RowLinks',
91
+ 'model',
92
+ )
93
+
94
+ migrationAction(
95
+ schema,
96
+ 'relationalField',
97
+ 'create',
98
+ {
99
+ displayName: 'Links',
100
+ apiId: 'pageLinks',
101
+ modelApiId: 'RowLinks',
102
+ type: RelationalFieldType.Relation,
103
+ reverseField: {
104
+ apiId: 'rowLinks',
105
+ modelApiId: 'PageLink',
106
+ displayName: 'RowLinks',
107
+ visibility: VisibilityTypes.Hidden,
108
+ isList: true,
109
+ },
110
+ visibility: VisibilityTypes.ReadWrite,
111
+ isList: true,
112
+ },
113
+ 'RowLinks',
114
+ 'model',
115
+ )
116
+
117
+ migrationAction(
118
+ schema,
119
+ 'unionField',
120
+ 'update',
121
+ {
122
+ apiId: 'content',
123
+ displayName: 'Content',
124
+ modelApiId: 'Page',
125
+ reverseField: {
126
+ modelApiIds: [
127
+ 'RowLinks',
128
+ 'RowServiceOptions',
129
+ 'RowSpecialBanner',
130
+ 'RowQuote',
131
+ 'RowProduct',
132
+ 'RowColumnOne',
133
+ 'RowColumnTwo',
134
+ 'RowColumnThree',
135
+ 'RowHeroBanner',
136
+ 'RowBlogContent',
137
+ 'RowButtonList',
138
+ 'RowContentLinks',
139
+ 'RowButtonLinkList',
140
+ ],
141
+ // visibility: VisibilityTypes.Hidden, => Currently not supported for updateUnionField | https://github.com/hygraph/management-sdk/issues/34
142
+ },
143
+ },
144
+ 'Page',
145
+ 'model',
146
+ )
147
+
148
+ return client.run(true)
149
+ }