great 1.1.0 → 1.2.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/README.md +137 -43
- package/dist/accounts/create.d.ts +1 -1
- package/dist/accounts/create.js +2 -4
- package/dist/accounts/create.js.map +1 -1
- package/dist/accounts/index.d.ts +1 -1
- package/dist/accounts/index.js +2 -4
- package/dist/accounts/index.js.map +1 -1
- package/dist/clone/index.d.ts +4 -2
- package/dist/clone/index.js +19 -43
- package/dist/clone/index.js.map +1 -1
- package/dist/config/index.js +4 -30
- package/dist/config/index.js.map +1 -1
- package/dist/deploy/index.d.ts +1 -1
- package/dist/deploy/index.js +54 -14
- package/dist/deploy/index.js.map +1 -1
- package/dist/env/index.d.ts +12 -0
- package/dist/env/index.js +131 -0
- package/dist/env/index.js.map +1 -0
- package/dist/explode/transform.d.ts +1 -1
- package/dist/explode/transform.js +3 -1
- package/dist/explode/transform.js.map +1 -1
- package/dist/generated/operations.d.ts +615 -0
- package/dist/generated/operations.js +2 -0
- package/dist/generated/operations.js.map +1 -0
- package/dist/generated/schema.d.ts +965 -0
- package/dist/generated/{graphql.js → schema.js} +13 -1
- package/dist/generated/schema.js.map +1 -0
- package/dist/implode/index.js +22 -43
- package/dist/implode/index.js.map +1 -1
- package/dist/implode/transform.d.ts +3 -5
- package/dist/implode/transform.js +10 -10
- package/dist/implode/transform.js.map +1 -1
- package/dist/{integrations/describe.d.ts → import/index.d.ts} +4 -1
- package/dist/import/index.js +40 -0
- package/dist/import/index.js.map +1 -0
- package/dist/include/index.d.ts +10 -0
- package/dist/include/index.js +38 -0
- package/dist/include/index.js.map +1 -0
- package/dist/index.js +13 -2
- package/dist/index.js.map +1 -1
- package/dist/init/index.js +8 -16
- package/dist/init/index.js.map +1 -1
- package/dist/integrations/create.d.ts +1 -1
- package/dist/integrations/create.js +2 -4
- package/dist/integrations/create.js.map +1 -1
- package/dist/integrations/list.d.ts +1 -1
- package/dist/integrations/list.js +2 -4
- package/dist/integrations/list.js.map +1 -1
- package/dist/migrate/index.d.ts +5 -0
- package/dist/migrate/index.js +101 -0
- package/dist/migrate/index.js.map +1 -0
- package/dist/pull/index.d.ts +4 -2
- package/dist/pull/index.js +25 -44
- package/dist/pull/index.js.map +1 -1
- package/dist/push/index.d.ts +1 -1
- package/dist/push/index.js +340 -97
- package/dist/push/index.js.map +1 -1
- package/dist/rename/index.d.ts +8 -0
- package/dist/rename/index.js +109 -0
- package/dist/rename/index.js.map +1 -0
- package/dist/repl/dispatch.d.ts +8 -2
- package/dist/repl/dispatch.js +43 -29
- package/dist/repl/dispatch.js.map +1 -1
- package/dist/repl/dispatchAndLoad.d.ts +7 -0
- package/dist/repl/dispatchAndLoad.js +35 -0
- package/dist/repl/dispatchAndLoad.js.map +1 -0
- package/dist/repl/help.js +8 -1
- package/dist/repl/help.js.map +1 -1
- package/dist/repl/index.d.ts +1 -1
- package/dist/repl/index.js +29 -9
- package/dist/repl/index.js.map +1 -1
- package/dist/repl/load.d.ts +8 -0
- package/dist/repl/load.js +53 -0
- package/dist/repl/load.js.map +1 -0
- package/dist/run/index.d.ts +4 -5
- package/dist/run/index.js +4 -6
- package/dist/run/index.js.map +1 -1
- package/dist/status/index.d.ts +1 -1
- package/dist/status/index.js +5 -7
- package/dist/status/index.js.map +1 -1
- package/dist/utils/config.d.ts +9 -2
- package/dist/utils/config.js +39 -6
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/createIntegrationFromFile.d.ts +2 -0
- package/dist/utils/createIntegrationFromFile.js +14 -33
- package/dist/utils/createIntegrationFromFile.js.map +1 -1
- package/dist/utils/detectPullConflicts.d.ts +8 -0
- package/dist/utils/detectPullConflicts.js +65 -0
- package/dist/utils/detectPullConflicts.js.map +1 -0
- package/dist/utils/dispatch.d.ts +1 -1
- package/dist/utils/dispatch.js +3 -2
- package/dist/utils/dispatch.js.map +1 -1
- package/dist/utils/elementFiles.d.ts +13 -0
- package/dist/utils/elementFiles.js +76 -0
- package/dist/utils/elementFiles.js.map +1 -0
- package/dist/utils/fetchIntegrationDefinition.d.ts +8 -0
- package/dist/utils/fetchIntegrationDefinition.js +58 -0
- package/dist/utils/fetchIntegrationDefinition.js.map +1 -0
- package/dist/utils/fetchLocal.d.ts +3 -1
- package/dist/utils/fetchLocal.js +11 -9
- package/dist/utils/fetchLocal.js.map +1 -1
- package/dist/utils/fetchSession.d.ts +1 -1
- package/dist/utils/fetchSession.js +2 -1
- package/dist/utils/fetchSession.js.map +1 -1
- package/dist/utils/graphqlClient.d.ts +3 -0
- package/dist/utils/graphqlClient.js +3 -0
- package/dist/utils/graphqlClient.js.map +1 -1
- package/dist/utils/graphqlError.d.ts +1 -0
- package/dist/utils/graphqlError.js +13 -1
- package/dist/utils/graphqlError.js.map +1 -1
- package/dist/utils/greatFile.d.ts +40 -0
- package/dist/utils/greatFile.js +66 -0
- package/dist/utils/greatFile.js.map +1 -0
- package/dist/utils/hashContent.js +1 -1
- package/dist/utils/hashContent.js.map +1 -1
- package/dist/utils/integrationType.d.ts +3 -0
- package/dist/utils/integrationType.js +15 -0
- package/dist/utils/integrationType.js.map +1 -0
- package/dist/utils/resolveAccount.d.ts +3 -2
- package/dist/utils/resolveAccount.js +11 -1
- package/dist/utils/resolveAccount.js.map +1 -1
- package/dist/utils/resolveElement.d.ts +1 -1
- package/dist/utils/resolveElementInclude.d.ts +3 -0
- package/dist/utils/resolveElementInclude.js +27 -0
- package/dist/utils/resolveElementInclude.js.map +1 -0
- package/dist/utils/resolveIntegration.d.ts +4 -2
- package/dist/utils/resolveIntegration.js +7 -3
- package/dist/utils/resolveIntegration.js.map +1 -1
- package/dist/utils/resolveTemplateImport.d.ts +3 -0
- package/dist/utils/resolveTemplateImport.js +30 -0
- package/dist/utils/resolveTemplateImport.js.map +1 -0
- package/dist/utils/response.d.ts +3 -0
- package/dist/utils/response.js +24 -0
- package/dist/utils/response.js.map +1 -0
- package/dist/utils/saveIntegration.d.ts +8 -4
- package/dist/utils/saveIntegration.js +76 -34
- package/dist/utils/saveIntegration.js.map +1 -1
- package/dist/utils/token.js +1 -1
- package/dist/utils/token.js.map +1 -1
- package/dist/utils/url.d.ts +1 -0
- package/dist/utils/url.js +10 -0
- package/dist/utils/url.js.map +1 -0
- package/dist/utils/writeShadowElement.d.ts +25 -0
- package/dist/utils/writeShadowElement.js +119 -0
- package/dist/utils/writeShadowElement.js.map +1 -0
- package/dist/{value → values}/get.d.ts +1 -1
- package/dist/{value → values}/get.js +7 -8
- package/dist/values/get.js.map +1 -0
- package/dist/{value → values}/index.js +13 -1
- package/dist/values/index.js.map +1 -0
- package/dist/{value → values}/list.js +10 -9
- package/dist/values/list.js.map +1 -0
- package/dist/{value → values}/set.d.ts +1 -1
- package/dist/{value → values}/set.js +9 -9
- package/dist/values/set.js.map +1 -0
- package/dist/values/unset.d.ts +8 -0
- package/dist/values/unset.js +61 -0
- package/dist/values/unset.js.map +1 -0
- package/dist/whoami/fetchSession.d.ts +3 -3
- package/dist/whoami/fetchSession.js +2 -4
- package/dist/whoami/fetchSession.js.map +1 -1
- package/dist/whoami/index.d.ts +1 -1
- package/package.json +14 -14
- package/dist/create/account.d.ts +0 -2
- package/dist/create/account.js +0 -40
- package/dist/create/account.js.map +0 -1
- package/dist/create/integration.d.ts +0 -4
- package/dist/create/integration.js +0 -73
- package/dist/create/integration.js.map +0 -1
- package/dist/create/utils.d.ts +0 -4
- package/dist/create/utils.js +0 -8
- package/dist/create/utils.js.map +0 -1
- package/dist/generated/graphql.d.ts +0 -1867
- package/dist/generated/graphql.js.map +0 -1
- package/dist/integrations/describe.js +0 -51
- package/dist/integrations/describe.js.map +0 -1
- package/dist/projects/describe.d.ts +0 -5
- package/dist/projects/describe.js +0 -51
- package/dist/projects/describe.js.map +0 -1
- package/dist/projects/index.d.ts +0 -5
- package/dist/projects/index.js +0 -83
- package/dist/projects/index.js.map +0 -1
- package/dist/repl/fetchUserAndIntegration.d.ts +0 -10
- package/dist/repl/fetchUserAndIntegration.js +0 -73
- package/dist/repl/fetchUserAndIntegration.js.map +0 -1
- package/dist/utils/apiUrl.d.ts +0 -1
- package/dist/utils/apiUrl.js +0 -7
- package/dist/utils/apiUrl.js.map +0 -1
- package/dist/utils/callApi.d.ts +0 -5
- package/dist/utils/callApi.js +0 -17
- package/dist/utils/callApi.js.map +0 -1
- package/dist/utils/fetchAccount.d.ts +0 -10
- package/dist/utils/fetchAccount.js +0 -60
- package/dist/utils/fetchAccount.js.map +0 -1
- package/dist/utils/fetchLocalProject.d.ts +0 -1
- package/dist/utils/fetchLocalProject.js +0 -12
- package/dist/utils/fetchLocalProject.js.map +0 -1
- package/dist/utils/fetchUserAndIntegration.d.ts +0 -9
- package/dist/utils/fetchUserAndIntegration.js +0 -48
- package/dist/utils/fetchUserAndIntegration.js.map +0 -1
- package/dist/utils/graphqlRequestClient.d.ts +0 -10
- package/dist/utils/graphqlRequestClient.js +0 -20
- package/dist/utils/graphqlRequestClient.js.map +0 -1
- package/dist/utils/saveProject.d.ts +0 -8
- package/dist/utils/saveProject.js +0 -93
- package/dist/utils/saveProject.js.map +0 -1
- package/dist/utils/session.d.ts +0 -9
- package/dist/utils/session.js +0 -17
- package/dist/utils/session.js.map +0 -1
- package/dist/value/get.js.map +0 -1
- package/dist/value/index.js.map +0 -1
- package/dist/value/list.js.map +0 -1
- package/dist/value/set.js.map +0 -1
- /package/dist/{value → values}/index.d.ts +0 -0
- /package/dist/{value → values}/list.d.ts +0 -0
package/dist/push/index.js
CHANGED
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
|
-
import path from 'node:path';
|
|
3
2
|
import chalk from 'chalk';
|
|
4
3
|
import parseJson from '../utils/parseJson.js';
|
|
5
4
|
import { sentenceCase } from 'change-case';
|
|
6
|
-
import {
|
|
5
|
+
import { fetchIntegrationFromFile } from '../utils/fetchLocal.js';
|
|
6
|
+
import { readGreatFile, writeGreatFile, getElementRecord, setElementRecord, removeElementRecordById, sameProvenance, } from '../utils/greatFile.js';
|
|
7
|
+
import { readElementFolder, folderToElementType, } from '../utils/elementFiles.js';
|
|
7
8
|
import createIntegrationFromFile from '../utils/createIntegrationFromFile.js';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
9
|
+
import { typeToFolder } from '../utils/saveIntegration.js';
|
|
10
|
+
import { getClient } from '../utils/graphqlClient.js';
|
|
11
|
+
import { getGraphQLErrorMessage, handleGraphQLError, } from '../utils/graphqlError.js';
|
|
11
12
|
import hashContent from '../utils/hashContent.js';
|
|
12
13
|
import { VALID_VALUE_TYPES, isValidValueElementType, } from '../utils/valueTypes.js';
|
|
13
|
-
import { setValueForElement } from '../
|
|
14
|
+
import { setValueForElement } from '../values/set.js';
|
|
14
15
|
import { promptForValueSetting } from '../utils/promptForValue.js';
|
|
15
|
-
import {
|
|
16
|
+
import { SHADOW_MARKER } from '../utils/writeShadowElement.js';
|
|
17
|
+
import resolveIntegrationType from '../utils/integrationType.js';
|
|
18
|
+
import { ElementType } from '../generated/schema.js';
|
|
16
19
|
import { gql } from 'graphql-tag';
|
|
17
20
|
const IntegrationForPushQueryDocument = gql `
|
|
18
21
|
query IntegrationForPush($id: ID!) {
|
|
@@ -20,6 +23,14 @@ const IntegrationForPushQueryDocument = gql `
|
|
|
20
23
|
id
|
|
21
24
|
key
|
|
22
25
|
name
|
|
26
|
+
type
|
|
27
|
+
templateImports {
|
|
28
|
+
id
|
|
29
|
+
timestamp
|
|
30
|
+
template {
|
|
31
|
+
id
|
|
32
|
+
}
|
|
33
|
+
}
|
|
23
34
|
latest {
|
|
24
35
|
timestamp
|
|
25
36
|
elements {
|
|
@@ -31,13 +42,23 @@ const IntegrationForPushQueryDocument = gql `
|
|
|
31
42
|
createdAt
|
|
32
43
|
content {
|
|
33
44
|
checksum
|
|
34
|
-
|
|
45
|
+
createdAt
|
|
46
|
+
sourceTimestamp
|
|
47
|
+
provenance
|
|
35
48
|
}
|
|
36
49
|
}
|
|
37
50
|
}
|
|
38
51
|
}
|
|
39
52
|
}
|
|
40
53
|
`;
|
|
54
|
+
const UpdateIntegrationTypeMutationDocument = gql `
|
|
55
|
+
mutation UpdateIntegrationType($id: ID!, $type: IntegrationType!) {
|
|
56
|
+
updateIntegrationType(id: $id, type: $type) {
|
|
57
|
+
id
|
|
58
|
+
type
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
`;
|
|
41
62
|
const CreateElementMutationDocument = gql `
|
|
42
63
|
mutation CreateElement(
|
|
43
64
|
$integrationId: ID!
|
|
@@ -58,6 +79,52 @@ const CreateElementMutationDocument = gql `
|
|
|
58
79
|
}
|
|
59
80
|
}
|
|
60
81
|
`;
|
|
82
|
+
const IncludeElementMutationDocument = gql `
|
|
83
|
+
mutation IncludeElement(
|
|
84
|
+
$integrationId: ID!
|
|
85
|
+
$elementId: ID!
|
|
86
|
+
$sourceTimestamp: DateTime
|
|
87
|
+
$provenance: [ID!]
|
|
88
|
+
) {
|
|
89
|
+
includeElement(
|
|
90
|
+
integrationId: $integrationId
|
|
91
|
+
elementId: $elementId
|
|
92
|
+
sourceTimestamp: $sourceTimestamp
|
|
93
|
+
provenance: $provenance
|
|
94
|
+
) {
|
|
95
|
+
id
|
|
96
|
+
name
|
|
97
|
+
description
|
|
98
|
+
content {
|
|
99
|
+
data
|
|
100
|
+
checksum
|
|
101
|
+
createdAt
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
`;
|
|
106
|
+
const RegisterTemplateImportMutationDocument = gql `
|
|
107
|
+
mutation RegisterTemplateImport(
|
|
108
|
+
$integrationId: ID!
|
|
109
|
+
$templateId: ID!
|
|
110
|
+
$timestamp: DateTime!
|
|
111
|
+
) {
|
|
112
|
+
registerTemplateImport(
|
|
113
|
+
integrationId: $integrationId
|
|
114
|
+
templateId: $templateId
|
|
115
|
+
timestamp: $timestamp
|
|
116
|
+
) {
|
|
117
|
+
id
|
|
118
|
+
templateImports {
|
|
119
|
+
id
|
|
120
|
+
timestamp
|
|
121
|
+
template {
|
|
122
|
+
id
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
`;
|
|
61
128
|
const UpdateElementMutationDocument = gql `
|
|
62
129
|
mutation UpdateElement($id: ID!, $name: String, $description: String) {
|
|
63
130
|
updateElement(id: $id, name: $name, description: $description) {
|
|
@@ -72,7 +139,7 @@ const SetElementContentMutationDocument = gql `
|
|
|
72
139
|
setElementContent(id: $id, content: $content) {
|
|
73
140
|
id
|
|
74
141
|
content {
|
|
75
|
-
|
|
142
|
+
createdAt
|
|
76
143
|
checksum
|
|
77
144
|
}
|
|
78
145
|
}
|
|
@@ -91,50 +158,11 @@ const SetSecretRefMutationDocument = gql `
|
|
|
91
158
|
setSecretRef(id: $id, secretRef: $secretRef)
|
|
92
159
|
}
|
|
93
160
|
`;
|
|
94
|
-
const JSON_EXTENSIONS = ['.jsonc', '.json'];
|
|
95
|
-
function elementKeyFromFileName(fileName) {
|
|
96
|
-
const ext = JSON_EXTENSIONS.find((e) => fileName.endsWith(e));
|
|
97
|
-
return ext ? fileName.slice(0, -ext.length) : undefined;
|
|
98
|
-
}
|
|
99
|
-
const folderToElementType = {
|
|
100
|
-
schemas: ElementType.Schema,
|
|
101
|
-
services: ElementType.Service,
|
|
102
|
-
auths: ElementType.Auth,
|
|
103
|
-
mutations: ElementType.Mutation,
|
|
104
|
-
dictionaries: ElementType.Dictionary,
|
|
105
|
-
jobs: ElementType.Job,
|
|
106
|
-
values: ElementType.Value,
|
|
107
|
-
flows: ElementType.Flow,
|
|
108
|
-
retryRules: ElementType.RetryRule,
|
|
109
|
-
};
|
|
110
161
|
function readLocalElements(fsImpl) {
|
|
111
162
|
const elements = [];
|
|
112
163
|
for (const folder of Object.keys(folderToElementType)) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
const files = fsImpl.readdirSync(folder);
|
|
117
|
-
const seenKeys = new Map();
|
|
118
|
-
for (const file of files) {
|
|
119
|
-
const fileName = String(file);
|
|
120
|
-
const key = elementKeyFromFileName(fileName);
|
|
121
|
-
if (!key) {
|
|
122
|
-
continue;
|
|
123
|
-
}
|
|
124
|
-
const filePath = path.join(folder, fileName);
|
|
125
|
-
const existingFile = seenKeys.get(key);
|
|
126
|
-
if (existingFile) {
|
|
127
|
-
throw new Error(`Duplicate element key "${key}" in ${folder}/: found both ${existingFile} and ${fileName}`);
|
|
128
|
-
}
|
|
129
|
-
seenKeys.set(key, fileName);
|
|
130
|
-
try {
|
|
131
|
-
const content = fsImpl.readFileSync(filePath, 'utf8');
|
|
132
|
-
const data = parseJson(content);
|
|
133
|
-
elements.push({ folder, key, filePath, data });
|
|
134
|
-
}
|
|
135
|
-
catch (error) {
|
|
136
|
-
throw new Error(`Failed to read or parse ${filePath}: ${error}`);
|
|
137
|
-
}
|
|
164
|
+
for (const { key, filePath, data } of readElementFolder(folder, undefined, fsImpl)) {
|
|
165
|
+
elements.push({ folder, key, filePath, data });
|
|
138
166
|
}
|
|
139
167
|
}
|
|
140
168
|
return elements;
|
|
@@ -143,15 +171,32 @@ function compareLocalAndRemote(local, remote) {
|
|
|
143
171
|
if (!remote) {
|
|
144
172
|
return {
|
|
145
173
|
category: 'conflict',
|
|
146
|
-
reason: 'Element exists locally with
|
|
174
|
+
reason: 'Element exists locally with an id but not found in Integreat',
|
|
147
175
|
};
|
|
148
176
|
}
|
|
149
|
-
const localChecksum = hashContent(local.data);
|
|
150
177
|
const localName = local.data.name || '';
|
|
151
178
|
const localDesc = local.data.description || '';
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
179
|
+
if (local.source) {
|
|
180
|
+
const hasNameChanged = localName !== (remote.name || '');
|
|
181
|
+
const hasDescriptionChanged = localDesc !== (remote.description || '');
|
|
182
|
+
const hasPinChanged = (local.source.timestamp ?? null) !== (remote.sourceTimestamp ?? null);
|
|
183
|
+
const hasProvenanceChanged = !sameProvenance(local.provenance, remote.provenance);
|
|
184
|
+
if (!hasNameChanged &&
|
|
185
|
+
!hasDescriptionChanged &&
|
|
186
|
+
!hasPinChanged &&
|
|
187
|
+
!hasProvenanceChanged) {
|
|
188
|
+
return { category: 'unchanged' };
|
|
189
|
+
}
|
|
190
|
+
if (hasPinChanged && local.timestamp !== remote.contentCreatedAt) {
|
|
191
|
+
return {
|
|
192
|
+
category: 'conflict',
|
|
193
|
+
reason: ' Shadow pin changed both local and remote',
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
return { category: 'update' };
|
|
197
|
+
}
|
|
198
|
+
const localChecksum = hashContent(local.data);
|
|
199
|
+
const localTimestamp = local.timestamp ? new Date(local.timestamp) : undefined;
|
|
155
200
|
const remoteChecksum = remote.checksum || '';
|
|
156
201
|
const remoteName = remote.name || '';
|
|
157
202
|
const remoteDesc = remote.description || '';
|
|
@@ -166,7 +211,7 @@ function compareLocalAndRemote(local, remote) {
|
|
|
166
211
|
}
|
|
167
212
|
const metaDateConflict = localTimestamp && remoteCreatedAt && localTimestamp < remoteCreatedAt;
|
|
168
213
|
const conflicts = [];
|
|
169
|
-
if (hasContentChanged && local.
|
|
214
|
+
if (hasContentChanged && local.timestamp !== remote.contentCreatedAt) {
|
|
170
215
|
conflicts.push('Content changed both local and remote');
|
|
171
216
|
}
|
|
172
217
|
if (hasNameChanged && metaDateConflict) {
|
|
@@ -187,12 +232,17 @@ function compareLocalAndRemote(local, remote) {
|
|
|
187
232
|
}
|
|
188
233
|
function categorizeElements(localElements, remoteElementsMap) {
|
|
189
234
|
const toCreate = [];
|
|
235
|
+
const toInclude = [];
|
|
190
236
|
const toUpdate = [];
|
|
191
237
|
const toDelete = [];
|
|
192
238
|
const conflicts = [];
|
|
193
239
|
const localElementIds = new Set();
|
|
194
240
|
for (const local of localElements) {
|
|
195
|
-
const localId = local.
|
|
241
|
+
const localId = local.id;
|
|
242
|
+
if (local.source && !localId) {
|
|
243
|
+
toInclude.push(local);
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
196
246
|
if (!localId) {
|
|
197
247
|
toCreate.push(local);
|
|
198
248
|
continue;
|
|
@@ -212,9 +262,9 @@ function categorizeElements(localElements, remoteElementsMap) {
|
|
|
212
262
|
toDelete.push(remoteLement);
|
|
213
263
|
}
|
|
214
264
|
}
|
|
215
|
-
return { toCreate, toUpdate, toDelete, conflicts };
|
|
265
|
+
return { toCreate, toInclude, toUpdate, toDelete, conflicts };
|
|
216
266
|
}
|
|
217
|
-
const prepareContentForApi = ({
|
|
267
|
+
const prepareContentForApi = ({ name, description, ...content }, elementType) => {
|
|
218
268
|
if (elementType === ElementType.Value) {
|
|
219
269
|
const { value, ref, type, ...rest } = content;
|
|
220
270
|
if (type === undefined) {
|
|
@@ -251,6 +301,65 @@ async function createElementOnApi(client, integrationId, element) {
|
|
|
251
301
|
}
|
|
252
302
|
return { id, name };
|
|
253
303
|
}
|
|
304
|
+
function writeShadowFileAndRecord(fsImpl, element, great, source, included) {
|
|
305
|
+
const name = element.data.name || included.name;
|
|
306
|
+
const description = element.data.description ||
|
|
307
|
+
included.description ||
|
|
308
|
+
undefined;
|
|
309
|
+
const content = included.content;
|
|
310
|
+
const fileData = {
|
|
311
|
+
[SHADOW_MARKER]: true,
|
|
312
|
+
...(name ? { name } : {}),
|
|
313
|
+
...(description ? { description } : {}),
|
|
314
|
+
...content?.data,
|
|
315
|
+
};
|
|
316
|
+
fsImpl.writeFileSync(element.filePath, JSON.stringify(fileData, null, 2));
|
|
317
|
+
setElementRecord(great, element.folder, element.key, {
|
|
318
|
+
id: included.id,
|
|
319
|
+
...(content?.createdAt ? { timestamp: content.createdAt } : {}),
|
|
320
|
+
...(content?.checksum ? { hash: content.checksum } : {}),
|
|
321
|
+
source,
|
|
322
|
+
...(element.provenance && element.provenance.length > 0
|
|
323
|
+
? { provenance: element.provenance }
|
|
324
|
+
: {}),
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
async function includeShadowElement(element, graphqlClient, integrationId, fsImpl, log, great) {
|
|
328
|
+
const source = element.source;
|
|
329
|
+
if (!source) {
|
|
330
|
+
return false;
|
|
331
|
+
}
|
|
332
|
+
const provenance = element.provenance && element.provenance.length > 0
|
|
333
|
+
? element.provenance
|
|
334
|
+
: undefined;
|
|
335
|
+
const result = await graphqlClient.request(IncludeElementMutationDocument, {
|
|
336
|
+
integrationId,
|
|
337
|
+
elementId: source.id,
|
|
338
|
+
sourceTimestamp: source.timestamp,
|
|
339
|
+
provenance,
|
|
340
|
+
});
|
|
341
|
+
if (result.error || !result.data?.includeElement) {
|
|
342
|
+
log(chalk.red(`Failed to include shadow element ${element.key} in ${element.folder}`));
|
|
343
|
+
return false;
|
|
344
|
+
}
|
|
345
|
+
const included = result.data.includeElement;
|
|
346
|
+
const localName = element.data.name || '';
|
|
347
|
+
const localDesc = element.data.description || '';
|
|
348
|
+
const nameDiffers = localName !== (included.name || '');
|
|
349
|
+
const descDiffers = localDesc !== (included.description || '');
|
|
350
|
+
if (nameDiffers || descDiffers) {
|
|
351
|
+
const updateResult = await graphqlClient.request(UpdateElementMutationDocument, {
|
|
352
|
+
id: included.id,
|
|
353
|
+
name: nameDiffers ? localName : undefined,
|
|
354
|
+
description: descDiffers ? localDesc : undefined,
|
|
355
|
+
});
|
|
356
|
+
if (updateResult.error) {
|
|
357
|
+
log(chalk.yellow(`Warning: Failed to update metadata for shadow ${element.key} in ${element.folder}`));
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
writeShadowFileAndRecord(fsImpl, element, great, source, included);
|
|
361
|
+
return true;
|
|
362
|
+
}
|
|
254
363
|
async function updateElementContent(client, elementId, content) {
|
|
255
364
|
const result = await client.request(SetElementContentMutationDocument, {
|
|
256
365
|
id: elementId,
|
|
@@ -259,37 +368,51 @@ async function updateElementContent(client, elementId, content) {
|
|
|
259
368
|
if (result.error) {
|
|
260
369
|
return undefined;
|
|
261
370
|
}
|
|
262
|
-
return result.data?.setElementContent?.content?.
|
|
371
|
+
return result.data?.setElementContent?.content?.createdAt;
|
|
263
372
|
}
|
|
264
|
-
function updateLocalFile(fsImpl,
|
|
265
|
-
const content = fsImpl.readFileSync(filePath, 'utf8');
|
|
373
|
+
function updateLocalFile(fsImpl, element, great, updatedId, updatedTimestamp, generatedName, keepValue = false) {
|
|
374
|
+
const content = fsImpl.readFileSync(element.filePath, 'utf8');
|
|
266
375
|
const parsed = parseJson(content);
|
|
267
|
-
const {
|
|
268
|
-
const
|
|
269
|
-
const
|
|
376
|
+
const { name, description, value, ref, ...data } = parsed;
|
|
377
|
+
const existing = getElementRecord(great, element.folder, element.key);
|
|
378
|
+
const id = updatedId ?? existing?.id;
|
|
379
|
+
const timestamp = updatedTimestamp ?? existing?.timestamp;
|
|
270
380
|
const finalName = generatedName || name;
|
|
271
381
|
const orderedData = {
|
|
272
|
-
...(id ? { __id: id } : {}),
|
|
273
|
-
__key,
|
|
274
|
-
...(timestamp ? { __timestamp: timestamp } : {}),
|
|
275
382
|
...(finalName ? { name: finalName } : {}),
|
|
276
383
|
...(description ? { description } : {}),
|
|
277
384
|
...data,
|
|
278
385
|
...(keepValue && value !== undefined ? { value } : {}),
|
|
279
386
|
...(keepValue && ref !== undefined ? { ref } : {}),
|
|
280
387
|
};
|
|
281
|
-
fsImpl.writeFileSync(filePath, JSON.stringify(orderedData, null, 2));
|
|
388
|
+
fsImpl.writeFileSync(element.filePath, JSON.stringify(orderedData, null, 2));
|
|
389
|
+
setElementRecord(great, element.folder, element.key, {
|
|
390
|
+
...(id ? { id } : {}),
|
|
391
|
+
...(timestamp ? { timestamp } : {}),
|
|
392
|
+
hash: hashContent(orderedData),
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
function recordElementProgress(great, element, fields) {
|
|
396
|
+
const existing = getElementRecord(great, element.folder, element.key);
|
|
397
|
+
setElementRecord(great, element.folder, element.key, {
|
|
398
|
+
...existing,
|
|
399
|
+
...fields,
|
|
400
|
+
});
|
|
282
401
|
}
|
|
283
402
|
function buildRemoteElementsMap(elements) {
|
|
284
403
|
const remoteElements = new Map();
|
|
285
404
|
for (const element of elements) {
|
|
286
405
|
remoteElements.set(element.id, {
|
|
287
406
|
id: element.id,
|
|
407
|
+
key: element.key,
|
|
408
|
+
folder: typeToFolder[element.__typename],
|
|
288
409
|
checksum: element.content?.checksum,
|
|
289
|
-
|
|
410
|
+
contentCreatedAt: element.content?.createdAt,
|
|
290
411
|
name: element.name,
|
|
291
412
|
description: element.description,
|
|
292
413
|
createdAt: element.createdAt,
|
|
414
|
+
sourceTimestamp: element.content?.sourceTimestamp,
|
|
415
|
+
provenance: element.content?.provenance,
|
|
293
416
|
});
|
|
294
417
|
}
|
|
295
418
|
return remoteElements;
|
|
@@ -302,7 +425,7 @@ function handleConflicts(conflicts, log) {
|
|
|
302
425
|
}
|
|
303
426
|
log(`\nRun ${chalk.bold('great pull')} to get remote changes, then manually merge and push again.`);
|
|
304
427
|
}
|
|
305
|
-
async function createOrUpdateElement(element, graphqlClient, integrationId, fsImpl, log, apiElementsMap, shouldSetValue) {
|
|
428
|
+
async function createOrUpdateElement(element, graphqlClient, integrationId, fsImpl, log, apiElementsMap, shouldSetValue, great) {
|
|
306
429
|
let id = element.remoteId;
|
|
307
430
|
let generatedName;
|
|
308
431
|
if (!id) {
|
|
@@ -313,6 +436,7 @@ async function createOrUpdateElement(element, graphqlClient, integrationId, fsIm
|
|
|
313
436
|
}
|
|
314
437
|
id = result.id;
|
|
315
438
|
generatedName = result.name;
|
|
439
|
+
recordElementProgress(great, element, { id });
|
|
316
440
|
}
|
|
317
441
|
else {
|
|
318
442
|
const apiElement = apiElementsMap.get(id);
|
|
@@ -335,6 +459,15 @@ async function createOrUpdateElement(element, graphqlClient, integrationId, fsIm
|
|
|
335
459
|
}
|
|
336
460
|
}
|
|
337
461
|
}
|
|
462
|
+
if (element.source) {
|
|
463
|
+
const remote = apiElementsMap.get(id);
|
|
464
|
+
const pinChanged = (element.source.timestamp ?? null) !== (remote?.sourceTimestamp ?? null);
|
|
465
|
+
const provenanceChanged = !sameProvenance(element.provenance, remote?.provenance);
|
|
466
|
+
if (pinChanged || provenanceChanged) {
|
|
467
|
+
return includeShadowElement(element, graphqlClient, integrationId, fsImpl, log, great);
|
|
468
|
+
}
|
|
469
|
+
return true;
|
|
470
|
+
}
|
|
338
471
|
const elementType = folderToElementType[element.folder];
|
|
339
472
|
let content;
|
|
340
473
|
try {
|
|
@@ -349,6 +482,7 @@ async function createOrUpdateElement(element, graphqlClient, integrationId, fsIm
|
|
|
349
482
|
log(chalk.red(`Failed to ${element.remoteId ? 'update' : 'set'} content for ${element.key} in ${element.folder}`));
|
|
350
483
|
return false;
|
|
351
484
|
}
|
|
485
|
+
recordElementProgress(great, element, { id, timestamp });
|
|
352
486
|
const hasValue = element.data.value !== undefined;
|
|
353
487
|
const hasRef = element.data.ref !== undefined;
|
|
354
488
|
const isSecret = content.type === 'secret';
|
|
@@ -357,7 +491,7 @@ async function createOrUpdateElement(element, graphqlClient, integrationId, fsIm
|
|
|
357
491
|
const secretRef = String(element.data.ref);
|
|
358
492
|
const result = await graphqlClient.request(SetSecretRefMutationDocument, { id, secretRef });
|
|
359
493
|
if (result.error) {
|
|
360
|
-
log(chalk.red(`Failed to set secret ref for ${element.key}: ${result.error
|
|
494
|
+
log(chalk.red(`Failed to set secret ref for ${element.key}: ${getGraphQLErrorMessage(result.error)}`));
|
|
361
495
|
return false;
|
|
362
496
|
}
|
|
363
497
|
log(chalk.green(`✓ Secret ref set for element "${element.key}"`));
|
|
@@ -372,7 +506,7 @@ async function createOrUpdateElement(element, graphqlClient, integrationId, fsIm
|
|
|
372
506
|
log(chalk.green(`✓ Value set for element "${element.key}" (${content.type})`));
|
|
373
507
|
}
|
|
374
508
|
}
|
|
375
|
-
updateLocalFile(fsImpl, element
|
|
509
|
+
updateLocalFile(fsImpl, element, great, element.remoteId ? undefined : id, timestamp, generatedName, !shouldSetValue && hasValue);
|
|
376
510
|
return true;
|
|
377
511
|
}
|
|
378
512
|
async function deleteElement(element, graphqlClient, log) {
|
|
@@ -385,26 +519,91 @@ async function deleteElement(element, graphqlClient, log) {
|
|
|
385
519
|
}
|
|
386
520
|
return true;
|
|
387
521
|
}
|
|
388
|
-
function
|
|
389
|
-
const
|
|
522
|
+
function buildRemoteImportsMap(templateImports) {
|
|
523
|
+
const map = new Map();
|
|
524
|
+
for (const templateImport of templateImports) {
|
|
525
|
+
if (templateImport.template) {
|
|
526
|
+
map.set(templateImport.template.id, templateImport);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
return map;
|
|
530
|
+
}
|
|
531
|
+
function findImportsToRegister(great, remoteImports) {
|
|
532
|
+
return (great.imports ?? []).filter((record) => {
|
|
533
|
+
const remote = remoteImports.get(record.templateId);
|
|
534
|
+
return !remote || remote.timestamp !== record.timestamp;
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
function rebuildImportRecords(great, templateImports) {
|
|
538
|
+
const records = [];
|
|
539
|
+
for (const templateImport of templateImports) {
|
|
540
|
+
if (templateImport.template) {
|
|
541
|
+
records.push({
|
|
542
|
+
templateId: templateImport.template.id,
|
|
543
|
+
timestamp: templateImport.timestamp,
|
|
544
|
+
id: templateImport.id,
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
if (records.length > 0 || great.imports?.length) {
|
|
549
|
+
great.imports = records;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
async function registerTemplateImports(pending, initialRemoteImports, graphqlClient, integrationId, great, log) {
|
|
553
|
+
let latestRemoteImports = initialRemoteImports;
|
|
554
|
+
let registeredCount = 0;
|
|
555
|
+
for (const record of pending) {
|
|
556
|
+
const result = await graphqlClient.request(RegisterTemplateImportMutationDocument, {
|
|
557
|
+
integrationId,
|
|
558
|
+
templateId: record.templateId,
|
|
559
|
+
timestamp: record.timestamp,
|
|
560
|
+
});
|
|
561
|
+
if (result.error || !result.data?.registerTemplateImport) {
|
|
562
|
+
log(chalk.red(`Failed to register template import ${record.templateId}`));
|
|
563
|
+
return undefined;
|
|
564
|
+
}
|
|
565
|
+
latestRemoteImports = result.data.registerTemplateImport.templateImports;
|
|
566
|
+
log(chalk.green(`✓ Registered template import ${record.templateId}`));
|
|
567
|
+
registeredCount++;
|
|
568
|
+
}
|
|
569
|
+
rebuildImportRecords(great, latestRemoteImports);
|
|
570
|
+
return registeredCount;
|
|
571
|
+
}
|
|
572
|
+
async function syncIntegrationType(graphqlClient, integrationId, remoteType, localType, log) {
|
|
573
|
+
if (localType === remoteType) {
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
const result = await graphqlClient.request(UpdateIntegrationTypeMutationDocument, { id: integrationId, type: localType });
|
|
577
|
+
if (result.error) {
|
|
578
|
+
handleGraphQLError(result.error, log);
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
log(`${chalk.green('✓')} Updated integration type to ${chalk.cyan(localType)}`);
|
|
582
|
+
}
|
|
583
|
+
function logSummary(createdCount, includedCount, updatedCount, deletedCount, registeredCount, log) {
|
|
584
|
+
const total = createdCount + includedCount + updatedCount + deletedCount + registeredCount;
|
|
390
585
|
if (total > 0) {
|
|
391
586
|
const parts = [];
|
|
392
587
|
if (createdCount > 0)
|
|
393
588
|
parts.push(`${createdCount} created`);
|
|
589
|
+
if (includedCount > 0)
|
|
590
|
+
parts.push(`${includedCount} included`);
|
|
394
591
|
if (updatedCount > 0)
|
|
395
592
|
parts.push(`${updatedCount} updated`);
|
|
396
593
|
if (deletedCount > 0)
|
|
397
594
|
parts.push(`${deletedCount} deleted`);
|
|
595
|
+
if (registeredCount > 0)
|
|
596
|
+
parts.push(`${registeredCount} template imports registered`);
|
|
398
597
|
log(`\n${chalk.green('✓')} ${parts.join(', ')}`);
|
|
399
598
|
}
|
|
400
599
|
}
|
|
401
600
|
export const action = (log, apiToken, client, fsImpl = fs, config, promptForValueSettingFn = promptForValueSetting) => async function pushIntegration(options) {
|
|
402
|
-
|
|
601
|
+
const great = readGreatFile(undefined, fsImpl);
|
|
602
|
+
let integrationId = great.id;
|
|
403
603
|
if (!integrationId) {
|
|
404
|
-
log(chalk.yellow('No integration ID found
|
|
604
|
+
log(chalk.yellow('No integration ID found'));
|
|
405
605
|
log('Creating integration on server...\n');
|
|
406
|
-
const
|
|
407
|
-
const graphqlClient = client ?? createGraphQLClient(apiToken, apiBaseUrl);
|
|
606
|
+
const graphqlClient = getClient(apiToken, client, config);
|
|
408
607
|
const result = await createIntegrationFromFile(graphqlClient, apiToken ?? '', options ?? {}, config, fsImpl);
|
|
409
608
|
if (!result.success || !result.integration) {
|
|
410
609
|
if (result.error) {
|
|
@@ -424,27 +623,26 @@ export const action = (log, apiToken, client, fsImpl = fs, config, promptForValu
|
|
|
424
623
|
return;
|
|
425
624
|
}
|
|
426
625
|
const updatedData = {
|
|
427
|
-
__id: integration.id,
|
|
428
|
-
__key: integration.key,
|
|
429
626
|
name: integration.name,
|
|
430
627
|
description: fileData.description,
|
|
431
628
|
status: integration.status,
|
|
432
|
-
|
|
433
|
-
__id: integration.account.id,
|
|
434
|
-
__key: integration.account.key,
|
|
435
|
-
name: integration.account.name,
|
|
436
|
-
},
|
|
629
|
+
type: integration.type,
|
|
437
630
|
flags: fileData.flags,
|
|
438
631
|
identConfig: fileData.identConfig,
|
|
439
632
|
nonvalues: fileData.nonvalues,
|
|
440
633
|
queueService: fileData.queueService,
|
|
441
634
|
};
|
|
442
635
|
fsImpl.writeFileSync('integration.json', JSON.stringify(updatedData, null, 2));
|
|
636
|
+
great.id = integration.id;
|
|
637
|
+
great.account = {
|
|
638
|
+
id: integration.account.id,
|
|
639
|
+
key: integration.account.key,
|
|
640
|
+
};
|
|
641
|
+
writeGreatFile(great, undefined, fsImpl);
|
|
443
642
|
integrationId = integration.id;
|
|
444
643
|
log(chalk.green('✓ Updated integration.json with server details\n'));
|
|
445
644
|
}
|
|
446
|
-
const
|
|
447
|
-
const graphqlClient = client ?? createGraphQLClient(apiToken, apiBaseUrl);
|
|
645
|
+
const graphqlClient = getClient(apiToken, client, config);
|
|
448
646
|
const result = await graphqlClient.request(IntegrationForPushQueryDocument, { id: integrationId });
|
|
449
647
|
if (result.error) {
|
|
450
648
|
handleGraphQLError(result.error, log);
|
|
@@ -455,6 +653,8 @@ export const action = (log, apiToken, client, fsImpl = fs, config, promptForValu
|
|
|
455
653
|
log(chalk.red('Integration has no latest version'));
|
|
456
654
|
return;
|
|
457
655
|
}
|
|
656
|
+
const localData = fetchIntegrationFromFile(fsImpl);
|
|
657
|
+
await syncIntegrationType(graphqlClient, integrationId, resolveIntegrationType(integration.type), resolveIntegrationType(localData?.type, log), log);
|
|
458
658
|
const apiElementsMap = buildRemoteElementsMap(integration.latest.elements);
|
|
459
659
|
let localElements;
|
|
460
660
|
try {
|
|
@@ -464,12 +664,26 @@ export const action = (log, apiToken, client, fsImpl = fs, config, promptForValu
|
|
|
464
664
|
log(chalk.red(`Error reading local files: ${error}`));
|
|
465
665
|
return;
|
|
466
666
|
}
|
|
467
|
-
const
|
|
667
|
+
for (const local of localElements) {
|
|
668
|
+
const record = getElementRecord(great, local.folder, local.key);
|
|
669
|
+
local.id = record?.id;
|
|
670
|
+
local.timestamp = record?.timestamp;
|
|
671
|
+
local.source = record?.source;
|
|
672
|
+
local.provenance = record?.provenance;
|
|
673
|
+
}
|
|
674
|
+
const { toCreate, toInclude, toUpdate, toDelete, conflicts } = categorizeElements(localElements, apiElementsMap);
|
|
468
675
|
if (conflicts.length > 0) {
|
|
469
676
|
handleConflicts(conflicts, log);
|
|
470
677
|
return;
|
|
471
678
|
}
|
|
472
|
-
|
|
679
|
+
const remoteImportsMap = buildRemoteImportsMap(integration.templateImports ?? []);
|
|
680
|
+
const importsToRegister = findImportsToRegister(great, remoteImportsMap);
|
|
681
|
+
if (toCreate.length +
|
|
682
|
+
toInclude.length +
|
|
683
|
+
toUpdate.length +
|
|
684
|
+
toDelete.length +
|
|
685
|
+
importsToRegister.length ===
|
|
686
|
+
0) {
|
|
473
687
|
log(chalk.green('No changes to push'));
|
|
474
688
|
return;
|
|
475
689
|
}
|
|
@@ -481,31 +695,60 @@ export const action = (log, apiToken, client, fsImpl = fs, config, promptForValu
|
|
|
481
695
|
log(chalk.yellow('\nPush cancelled'));
|
|
482
696
|
return;
|
|
483
697
|
}
|
|
698
|
+
const persistProgress = () => writeGreatFile(great, undefined, fsImpl);
|
|
484
699
|
let createdCount = 0;
|
|
485
700
|
for (const element of toCreate) {
|
|
486
|
-
const success = await createOrUpdateElement(element, graphqlClient, integrationId, fsImpl, log, apiElementsMap, shouldSetValue);
|
|
487
|
-
if (!success)
|
|
701
|
+
const success = await createOrUpdateElement(element, graphqlClient, integrationId, fsImpl, log, apiElementsMap, shouldSetValue, great);
|
|
702
|
+
if (!success) {
|
|
703
|
+
persistProgress();
|
|
488
704
|
return;
|
|
705
|
+
}
|
|
489
706
|
log(chalk.green(`✓ Created ${element.folder}/${element.key}`));
|
|
490
707
|
createdCount++;
|
|
491
708
|
}
|
|
709
|
+
let includedCount = 0;
|
|
710
|
+
for (const element of toInclude) {
|
|
711
|
+
const success = await includeShadowElement(element, graphqlClient, integrationId, fsImpl, log, great);
|
|
712
|
+
if (!success) {
|
|
713
|
+
persistProgress();
|
|
714
|
+
return;
|
|
715
|
+
}
|
|
716
|
+
log(chalk.green(`✓ Included ${element.folder}/${element.key}`));
|
|
717
|
+
includedCount++;
|
|
718
|
+
}
|
|
492
719
|
let updatedCount = 0;
|
|
493
720
|
for (const element of toUpdate) {
|
|
494
|
-
const success = await createOrUpdateElement(element, graphqlClient, integrationId, fsImpl, log, apiElementsMap, shouldSetValue);
|
|
495
|
-
if (!success)
|
|
721
|
+
const success = await createOrUpdateElement(element, graphqlClient, integrationId, fsImpl, log, apiElementsMap, shouldSetValue, great);
|
|
722
|
+
if (!success) {
|
|
723
|
+
persistProgress();
|
|
496
724
|
return;
|
|
725
|
+
}
|
|
497
726
|
log(chalk.green(`✓ Updated ${element.folder}/${element.key}`));
|
|
498
727
|
updatedCount++;
|
|
499
728
|
}
|
|
500
729
|
let deletedCount = 0;
|
|
501
730
|
for (const element of toDelete) {
|
|
502
731
|
const success = await deleteElement(element, graphqlClient, log);
|
|
503
|
-
if (!success)
|
|
732
|
+
if (!success) {
|
|
733
|
+
persistProgress();
|
|
504
734
|
return;
|
|
505
|
-
|
|
735
|
+
}
|
|
736
|
+
removeElementRecordById(great, element.id);
|
|
737
|
+
const label = element.folder
|
|
738
|
+
? `${element.folder}/${element.key}`
|
|
739
|
+
: element.id;
|
|
740
|
+
log(chalk.green(`✓ Deleted ${label}`));
|
|
506
741
|
deletedCount++;
|
|
507
742
|
}
|
|
508
|
-
|
|
743
|
+
const registeredCount = await registerTemplateImports(importsToRegister, integration.templateImports ?? [], graphqlClient, integrationId, great, log);
|
|
744
|
+
if (registeredCount === undefined) {
|
|
745
|
+
persistProgress();
|
|
746
|
+
return;
|
|
747
|
+
}
|
|
748
|
+
const localKeys = new Set(localElements.map((el) => `${el.folder}/${el.key}`));
|
|
749
|
+
great.elements = Object.fromEntries(Object.entries(great.elements).filter(([key]) => localKeys.has(key)));
|
|
750
|
+
writeGreatFile(great, undefined, fsImpl);
|
|
751
|
+
logSummary(createdCount, includedCount, updatedCount, deletedCount, registeredCount, log);
|
|
509
752
|
};
|
|
510
753
|
export default (program, apiToken) => program
|
|
511
754
|
.command('push')
|