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