netlify-cli 14.4.0 → 15.0.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.
@@ -1,163 +0,0 @@
1
- // @ts-check
2
- import { Buffer } from 'buffer'
3
- import process from 'process'
4
-
5
- import { OneGraphClient } from 'netlify-onegraph-internal'
6
- import { v4 as uuidv4 } from 'uuid'
7
-
8
- import { OneGraphCliClient, ensureCLISession } from '../../lib/one-graph/cli-client.mjs'
9
- import { getNetlifyGraphConfig } from '../../lib/one-graph/cli-netlify-graph.mjs'
10
- import { NETLIFYDEVERR, chalk, error, exit, getToken, log } from '../../utils/command-helpers.mjs'
11
- import { translateFromEnvelopeToMongo } from '../../utils/env/index.mjs'
12
-
13
- const { ensureAppForSite, executeCreateApiTokenMutation } = OneGraphCliClient
14
-
15
- /**
16
- * Creates the `netlify graph:init` command
17
- * @param {import('commander').OptionValues} options
18
- * @param {import('../base-command.mjs').default} command
19
- * @returns
20
- */
21
- const graphInit = async (options, command) => {
22
- const { api, config, site, siteInfo, state } = command.netlify
23
- const accountId = siteInfo.account_slug
24
- const siteId = site.id
25
-
26
- if (!siteId) {
27
- error(
28
- `${NETLIFYDEVERR} Warning: no siteId defined, unable to start Netlify Graph. To enable, run ${chalk.yellow(
29
- 'netlify init',
30
- )} or ${chalk.yellow('netlify link')}`,
31
- )
32
- }
33
-
34
- let [netlifyToken] = await getToken()
35
- if (!netlifyToken) {
36
- netlifyToken = await command.authenticate()
37
- }
38
-
39
- if (netlifyToken == null) {
40
- error(
41
- `${NETLIFYDEVERR} Error: Unable to start Netlify Graph without a login. To enable, run ${chalk.yellow(
42
- 'netlify login',
43
- )} first`,
44
- )
45
- return exit()
46
- }
47
-
48
- await ensureAppForSite(netlifyToken, siteId)
49
-
50
- const netlifyGraphConfig = await getNetlifyGraphConfig({ command, options })
51
-
52
- if (process.env.NODE_ENV !== 'test') {
53
- await ensureCLISession({
54
- config,
55
- metadata: {},
56
- netlifyToken,
57
- site,
58
- state,
59
- netlifyGraphConfig,
60
- })
61
- }
62
-
63
- let envChanged = false
64
-
65
- // Get current environment variables set in the UI
66
- let env = (siteInfo.build_settings && siteInfo.build_settings.env) || {}
67
- const isUsingEnvelope = siteInfo.use_envelope
68
- if (isUsingEnvelope) {
69
- const envelopeVariables = await api.getEnvVars({ accountId, siteId })
70
- env = translateFromEnvelopeToMongo(envelopeVariables)
71
- }
72
-
73
- const newEnv = {
74
- ...env,
75
- }
76
-
77
- if (!env.NETLIFY_GRAPH_WEBHOOK_SECRET) {
78
- envChanged = true
79
- const secret = Buffer.from(uuidv4()).toString('base64')
80
- newEnv.NETLIFY_GRAPH_WEBHOOK_SECRET = secret
81
- }
82
-
83
- if (!env.NETLIFY_GRAPH_PERSIST_QUERY_TOKEN) {
84
- const variables = {
85
- input: {
86
- appId: siteId,
87
- scopes: ['MODIFY_SCHEMA', 'PERSIST_QUERY'],
88
- },
89
- }
90
-
91
- const { jwt } = await OneGraphClient.getGraphJwtForSite({ siteId, nfToken: netlifyToken })
92
- const result = await executeCreateApiTokenMutation(variables, {
93
- siteId,
94
- accessToken: jwt,
95
- })
96
-
97
- const token =
98
- result.data &&
99
- result.data.oneGraph &&
100
- result.data.oneGraph.createApiToken &&
101
- result.data.oneGraph.createApiToken.accessToken &&
102
- result.data.oneGraph.createApiToken.accessToken.token
103
-
104
- if (token) {
105
- envChanged = true
106
- newEnv.NETLIFY_GRAPH_PERSIST_QUERY_TOKEN = token
107
- } else {
108
- error(`Unable to create Netlify Graph persist query token: ${JSON.stringify(result.errors, null, 2)}`)
109
- }
110
- }
111
-
112
- if (!envChanged) {
113
- log(`Graph-related environment variables already set for site ${siteInfo.name}`)
114
- return true
115
- }
116
-
117
- // Apply environment variable updates
118
-
119
- // eslint-disable-next-line unicorn/prefer-ternary
120
- if (isUsingEnvelope) {
121
- await api.createEnvVars({
122
- accountId,
123
- siteId,
124
- body: [
125
- !env.NETLIFY_GRAPH_WEBHOOK_SECRET && {
126
- key: 'NETLIFY_GRAPH_WEBHOOK_SECRET',
127
- scopes: ['functions'],
128
- values: [{ context: 'all', value: newEnv.NETLIFY_GRAPH_WEBHOOK_SECRET }],
129
- },
130
- !env.NETLIFY_GRAPH_PERSIST_QUERY_TOKEN && {
131
- key: 'NETLIFY_GRAPH_PERSIST_QUERY_TOKEN',
132
- scopes: ['builds', 'functions'],
133
- values: [{ context: 'all', value: newEnv.NETLIFY_GRAPH_PERSIST_QUERY_TOKEN }],
134
- },
135
- ].filter(Boolean),
136
- })
137
- } else {
138
- // @ts-ignore
139
- await api.updateSite({
140
- siteId,
141
- body: {
142
- build_settings: {
143
- env: newEnv,
144
- },
145
- },
146
- })
147
- }
148
-
149
- log(`Finished updating Graph-related environment variables for site ${siteInfo.name}`)
150
- }
151
-
152
- /**
153
- * Creates the `netlify graph:init` command
154
- * @param {import('../base-command.mjs').default} program
155
- * @returns
156
- */
157
- export const createGraphInitCommand = (program) =>
158
- program
159
- .command('graph:init')
160
- .description('Initialize all the resources for Netlify Graph')
161
- .action(async (options, command) => {
162
- await graphInit(options, command)
163
- })
@@ -1,88 +0,0 @@
1
- // @ts-check
2
- import { GraphQL } from 'netlify-onegraph-internal'
3
-
4
- import { readLockfile } from '../../lib/one-graph/cli-client.mjs'
5
- import {
6
- buildSchema,
7
- defaultExampleOperationsDoc,
8
- extractFunctionsFromOperationDoc,
9
- generateFunctionsFile,
10
- getNetlifyGraphConfig,
11
- parse,
12
- readGraphQLOperationsSourceFile,
13
- readGraphQLSchemaFile,
14
- } from '../../lib/one-graph/cli-netlify-graph.mjs'
15
- import { NETLIFYDEVERR, chalk, error, log } from '../../utils/command-helpers.mjs'
16
-
17
- /**
18
- * Creates the `netlify graph:library` command
19
- * @param {import('commander').OptionValues} options
20
- * @param {import('../base-command.mjs').default} command
21
- * @returns
22
- */
23
- const graphLibrary = async (options, command) => {
24
- const { config } = command.netlify
25
- const netlifyGraphConfig = await getNetlifyGraphConfig({ command, options })
26
-
27
- const schemaString = readGraphQLSchemaFile(netlifyGraphConfig)
28
-
29
- let currentOperationsDoc = readGraphQLOperationsSourceFile(netlifyGraphConfig)
30
- if (currentOperationsDoc.trim().length === 0) {
31
- currentOperationsDoc = defaultExampleOperationsDoc
32
- }
33
-
34
- const parsedDoc = parse(currentOperationsDoc)
35
- const { fragments, functions } = extractFunctionsFromOperationDoc(GraphQL, parsedDoc)
36
-
37
- let schema
38
-
39
- try {
40
- schema = buildSchema(schemaString)
41
- } catch (buildSchemaError) {
42
- error(`Error parsing schema: ${buildSchemaError}`)
43
- }
44
-
45
- if (!schema) {
46
- error(`Failed to parse Netlify GraphQL schema`)
47
- return
48
- }
49
-
50
- const lockfile = readLockfile({ siteRoot: command.netlify.site.root })
51
-
52
- if (lockfile === undefined) {
53
- error(
54
- `${NETLIFYDEVERR} Error: no lockfile found, unable to run \`netlify graph:library\`. To pull a remote schema (and create a lockfile), run ${chalk.yellow(
55
- 'netlify graph:pull',
56
- )} `,
57
- )
58
- return
59
- }
60
-
61
- const { schemaId } = lockfile.locked
62
-
63
- const payload = {
64
- config,
65
- logger: log,
66
- netlifyGraphConfig,
67
- schema,
68
- schemaId,
69
- operationsDoc: currentOperationsDoc,
70
- functions,
71
- fragments,
72
- }
73
-
74
- generateFunctionsFile(payload)
75
- }
76
-
77
- /**
78
- * Creates the `netlify graph:library` command
79
- * @param {import('../base-command.mjs').default} program
80
- * @returns
81
- */
82
- export const createGraphLibraryCommand = (program) =>
83
- program
84
- .command('graph:library')
85
- .description('Generate the Graph function library')
86
- .action(async (options, command) => {
87
- await graphLibrary(options, command)
88
- })
@@ -1,116 +0,0 @@
1
- // @ts-check
2
- import { GraphQL } from 'netlify-onegraph-internal'
3
-
4
- import {
5
- defaultExampleOperationsDoc,
6
- extractFunctionsFromOperationDoc,
7
- getNetlifyGraphConfig,
8
- readGraphQLOperationsSourceFile,
9
- } from '../../lib/one-graph/cli-netlify-graph.mjs'
10
- import { log } from '../../utils/command-helpers.mjs'
11
-
12
- const { parse } = GraphQL
13
-
14
- /**
15
- * Creates the `netlify graph:operations` command
16
- * @param {import('commander').OptionValues} options
17
- * @param {import('../base-command.mjs').default} command
18
- * @returns
19
- */
20
- const graphOperations = async (options, command) => {
21
- const netlifyGraphConfig = await getNetlifyGraphConfig({ command, options })
22
- try {
23
- let currentOperationsDoc = readGraphQLOperationsSourceFile(netlifyGraphConfig)
24
- if (currentOperationsDoc.trim().length === 0) {
25
- currentOperationsDoc = defaultExampleOperationsDoc
26
- }
27
-
28
- const parsedDoc = parse(currentOperationsDoc)
29
- const { fragments, functions } = extractFunctionsFromOperationDoc(GraphQL, parsedDoc)
30
-
31
- const sorted = {
32
- /** @type {import('netlify-onegraph-internal/dist/netlifyGraph').ExtractedFunction[]} */
33
- queries: [],
34
- /** @type {import('netlify-onegraph-internal/dist/netlifyGraph').ExtractedFunction[]} */
35
- mutations: [],
36
- /** @type {import('netlify-onegraph-internal/dist/netlifyGraph').ExtractedFunction[]} */
37
- subscriptions: [],
38
- /** @type {import('netlify-onegraph-internal/dist/netlifyGraph').ExtractedFragment[]} */
39
- fragments: [],
40
- /** @type {any[]} */
41
- other: [],
42
- }
43
-
44
- // Sort the operations by name and add them to the correct array under the operation type in sorted
45
- Object.values(functions)
46
- .sort((aItem, bItem) => aItem.operationName.localeCompare(bItem.operationName))
47
- .forEach((operation) => {
48
- switch (operation.kind) {
49
- case 'query': {
50
- sorted.queries.push(operation)
51
-
52
- break
53
- }
54
- case 'mutation': {
55
- sorted.mutations.push(operation)
56
-
57
- break
58
- }
59
- case 'subscription': {
60
- sorted.subscriptions.push(operation)
61
-
62
- break
63
- }
64
- default: {
65
- sorted.other.push(operation)
66
- }
67
- }
68
- })
69
-
70
- Object.values(fragments)
71
- .sort((aItem, bItem) => aItem.fragmentName.localeCompare(bItem.fragmentName))
72
- .forEach((fragment) => {
73
- sorted.fragments.push(fragment)
74
- })
75
-
76
- if (sorted.queries.length !== 0) {
77
- log(`Queries:`)
78
- sorted.queries.forEach((operation) => {
79
- log(`\t${operation.operationName}`)
80
- })
81
- }
82
- if (sorted.mutations.length !== 0) {
83
- log(`Mutations:`)
84
- sorted.mutations.forEach((operation) => {
85
- log(`\t${operation.operationName}`)
86
- })
87
- }
88
- if (sorted.subscriptions.length !== 0) {
89
- log(`Subscriptions:`)
90
- sorted.subscriptions.forEach((operation) => {
91
- log(`\t${operation.operationName}`)
92
- })
93
- }
94
- if (sorted.fragments.length !== 0) {
95
- log(`Fragments:`)
96
- sorted.fragments.forEach((fragment) => {
97
- log(`\t${fragment.fragmentName}`)
98
- })
99
- }
100
- } catch (error) {
101
- error(`Error parsing operations library: ${error}`)
102
- }
103
- }
104
-
105
- /**
106
- * Creates the `netlify graph:operations` command
107
- * @param {import('../base-command.mjs').default} program
108
- * @returns
109
- */
110
- export const createGraphOperationsCommand = (program) =>
111
- program
112
- .command('graph:operations')
113
- .description('List all of the locally available operations')
114
- .action(async (options, command) => {
115
- await graphOperations(options, command)
116
- })
@@ -1,168 +0,0 @@
1
- // @ts-check
2
- /* eslint-disable eslint-comments/disable-enable-pair */
3
- /* eslint-disable fp/no-loops */
4
- import { OneGraphClient } from 'netlify-onegraph-internal'
5
-
6
- import {
7
- OneGraphCliClient,
8
- ensureCLISession,
9
- handleCliSessionEvent,
10
- loadCLISession,
11
- readLockfile,
12
- readSchemaIdFromLockfile,
13
- refetchAndGenerateFromOneGraph,
14
- } from '../../lib/one-graph/cli-client.mjs'
15
- import { buildSchema, getNetlifyGraphConfig, readGraphQLSchemaFile } from '../../lib/one-graph/cli-netlify-graph.mjs'
16
- import { NETLIFYDEVERR, chalk, error, log, warn } from '../../utils/command-helpers.mjs'
17
-
18
- /**
19
- * Creates the `netlify graph:pull` command
20
- * @param {import('commander').OptionValues} options
21
- * @param {import('../base-command.mjs').default} command
22
- * @returns
23
- */
24
- const graphPull = async (options, command) => {
25
- const { config, site, state } = command.netlify
26
-
27
- if (!site.id) {
28
- error(
29
- `No siteId defined, unable to start Netlify Graph. To enable, run ${chalk.yellow(
30
- 'netlify init',
31
- )} or ${chalk.yellow('netlify link')}`,
32
- )
33
- }
34
-
35
- const netlifyGraphConfig = await getNetlifyGraphConfig({ command, options })
36
- const netlifyToken = await command.authenticate()
37
- const siteId = site.id
38
-
39
- const { jwt } = await OneGraphCliClient.getGraphJwtForSite({ siteId, nfToken: netlifyToken })
40
-
41
- let oneGraphSessionId = loadCLISession(state)
42
- let lockfile = readLockfile({ siteRoot: command.netlify.site.root })
43
-
44
- if (!oneGraphSessionId || !lockfile) {
45
- warn(
46
- 'No local Netlify Graph session found, skipping command queue drain. Create a new session by running `netlify graph:edit`.',
47
- )
48
- oneGraphSessionId = await ensureCLISession({
49
- config,
50
- netlifyGraphConfig,
51
- metadata: {},
52
- netlifyToken,
53
- site,
54
- state,
55
- })
56
-
57
- lockfile = readLockfile({ siteRoot: command.netlify.site.root })
58
- }
59
-
60
- if (lockfile === undefined) {
61
- error(`${NETLIFYDEVERR} Error: unable to create lockfile for site and session, exiting.`)
62
- return
63
- }
64
-
65
- const { schemaId } = lockfile.locked
66
-
67
- await refetchAndGenerateFromOneGraph({
68
- config,
69
- logger: log,
70
- netlifyGraphConfig,
71
- jwt,
72
- schemaId,
73
- state,
74
- siteId,
75
- sessionId: oneGraphSessionId,
76
- })
77
-
78
- const schemaString = readGraphQLSchemaFile(netlifyGraphConfig)
79
-
80
- let schema
81
-
82
- try {
83
- schema = buildSchema(schemaString)
84
- } catch (buildSchemaError) {
85
- error(`Error parsing schema: ${buildSchemaError}`)
86
- }
87
-
88
- if (!schema) {
89
- error(`Failed to fetch and update Netlify GraphQL schema`)
90
- }
91
-
92
- const next = await OneGraphCliClient.fetchCliSessionEvents({
93
- appId: siteId,
94
- jwt,
95
- sessionId: oneGraphSessionId,
96
- })
97
-
98
- if (!next) {
99
- return
100
- }
101
-
102
- if (next.errors) {
103
- error(`Failed to fetch Netlify Graph cli session events: ${JSON.stringify(next.errors, null, 2)}`)
104
- }
105
-
106
- if (next.events) {
107
- const ackEventIds = []
108
- for (const event of next.events) {
109
- try {
110
- const audience = event.audience || OneGraphClient.eventAudience(event)
111
-
112
- if (audience === 'CLI') {
113
- const eventName = OneGraphClient.friendlyEventName(event)
114
- log(`${chalk.magenta('Handling')} Netlify Graph: ${eventName}...`)
115
- const nextSchemaId = readSchemaIdFromLockfile({ siteRoot: site.root })
116
-
117
- if (!nextSchemaId) {
118
- warn('Unable to load schemaId from Netlify Graph lockfile')
119
- return
120
- }
121
-
122
- if (!schema) {
123
- warn('Unable to load schema from for Netlify Graph')
124
- return
125
- }
126
-
127
- await handleCliSessionEvent({
128
- config,
129
- netlifyToken,
130
- // @ts-expect-error
131
- event,
132
- netlifyGraphConfig,
133
- schema,
134
- schemaId: nextSchemaId,
135
- sessionId: oneGraphSessionId,
136
- siteId: site.id,
137
- siteRoot: site.root,
138
- })
139
- ackEventIds.push(event.id)
140
- }
141
- } catch (error_) {
142
- warn(`Error processing individual Netlify Graph event, skipping:
143
- ${JSON.stringify(error_, null, 2)}`)
144
- ackEventIds.push(event.id)
145
- }
146
- }
147
-
148
- await OneGraphCliClient.ackCLISessionEvents({
149
- appId: siteId,
150
- jwt,
151
- sessionId: oneGraphSessionId,
152
- eventIds: ackEventIds,
153
- })
154
- }
155
- }
156
-
157
- /**
158
- * Creates the `netlify graph:pull` command
159
- * @param {import('../base-command.mjs').default} program
160
- * @returns
161
- */
162
- export const createGraphPullCommand = (program) =>
163
- program
164
- .command('graph:pull')
165
- .description('Pull your remote Netlify Graph schema locally, and process pending Graph edit events')
166
- .action(async (options, command) => {
167
- await graphPull(options, command)
168
- })
@@ -1,45 +0,0 @@
1
- // @ts-check
2
- import { warn } from '../../utils/command-helpers.mjs'
3
-
4
- import { createGraphConfigWriteCommand } from './graph-config-write.mjs'
5
- import { createGraphEditCommand } from './graph-edit.mjs'
6
- import { createGraphHandlerCommand } from './graph-handler.mjs'
7
- import { createGraphInitCommand } from './graph-init.mjs'
8
- import { createGraphLibraryCommand } from './graph-library.mjs'
9
- import { createGraphOperationsCommand } from './graph-operations.mjs'
10
- import { createGraphPullCommand } from './graph-pull.mjs'
11
-
12
- /**
13
- * The graph command
14
- * @param {import('commander').OptionValues} options
15
- * @param {import('../base-command.mjs').default} command
16
- */
17
- const graph = (options, command) => {
18
- command.help()
19
- }
20
-
21
- /**
22
- * Creates the `netlify graph` command
23
- * @param {import('../base-command.mjs').default} program
24
- * @returns
25
- */
26
- export const createGraphCommand = (program) => {
27
- createGraphConfigWriteCommand(program)
28
- createGraphEditCommand(program)
29
- createGraphHandlerCommand(program)
30
- createGraphInitCommand(program)
31
- createGraphLibraryCommand(program)
32
- createGraphOperationsCommand(program)
33
- createGraphPullCommand(program)
34
-
35
- return program
36
- .command('graph')
37
- .hook('preAction', () => {
38
- warn(
39
- 'Netlify Graph is deprecated and will be removed from the CLI in a future release at the end of April, 2023. Please migrate off of Netlify Graph beforehand.',
40
- )
41
- })
42
- .description('(Deprecated) Control the Netlify Graph functions for the current site')
43
- .addExamples(['netlify graph:pull', 'netlify graph:edit'])
44
- .action(graph)
45
- }
@@ -1 +0,0 @@
1
- export { createGraphCommand } from './graph.mjs'