zapier-platform-cli 17.0.4 → 17.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/oclif.manifest.json +156 -91
- package/package.json +1 -1
- package/src/oclif/commands/convert.js +81 -15
- package/src/oclif/commands/deprecate.js +58 -2
- package/src/utils/convert.js +4 -4
package/oclif.manifest.json
CHANGED
|
@@ -111,11 +111,6 @@
|
|
|
111
111
|
"convert": {
|
|
112
112
|
"aliases": [],
|
|
113
113
|
"args": {
|
|
114
|
-
"integrationId": {
|
|
115
|
-
"description": "To get the integration/app ID, go to \"https://developer.zapier.com\", click on an integration, and copy the number directly after \"/app/\" in the URL.",
|
|
116
|
-
"name": "integrationId",
|
|
117
|
-
"required": true
|
|
118
|
-
},
|
|
119
114
|
"path": {
|
|
120
115
|
"description": "Relative to your current path - IE: `.` for current directory.",
|
|
121
116
|
"name": "path",
|
|
@@ -124,11 +119,64 @@
|
|
|
124
119
|
},
|
|
125
120
|
"description": "Convert a Visual Builder integration to a CLI integration.\n\nThe resulting CLI integration will be identical to its Visual Builder version and ready to push and use immediately!\n\nIf you re-run this command on an existing directory it will leave existing files alone and not clobber them.\n\nYou'll need to do a `zapier push` before the new version is visible in the editor, but otherwise you're good to go.",
|
|
126
121
|
"flags": {
|
|
122
|
+
"integrationId": {
|
|
123
|
+
"char": "i",
|
|
124
|
+
"dependsOn": [
|
|
125
|
+
"version"
|
|
126
|
+
],
|
|
127
|
+
"description": "To get the integration/app ID, go to \"https://developer.zapier.com\", click on an integration, and copy the number directly after \"/app/\" in the URL.",
|
|
128
|
+
"exclusive": [
|
|
129
|
+
"definition"
|
|
130
|
+
],
|
|
131
|
+
"name": "integrationId",
|
|
132
|
+
"required": false,
|
|
133
|
+
"hasDynamicHelp": false,
|
|
134
|
+
"type": "option"
|
|
135
|
+
},
|
|
127
136
|
"version": {
|
|
128
137
|
"char": "v",
|
|
138
|
+
"dependsOn": [
|
|
139
|
+
"integrationId"
|
|
140
|
+
],
|
|
129
141
|
"description": "Convert a specific version. Required when converting a Visual Builder integration.",
|
|
130
142
|
"name": "version",
|
|
131
|
-
"required":
|
|
143
|
+
"required": false,
|
|
144
|
+
"hasDynamicHelp": false,
|
|
145
|
+
"multiple": false,
|
|
146
|
+
"type": "option"
|
|
147
|
+
},
|
|
148
|
+
"json": {
|
|
149
|
+
"char": "j",
|
|
150
|
+
"description": "The JSON definition to use, as alternative for reading from a Visual Builder integration. Must be a JSON-encoded object. The data can be passed from the command directly like '{\"key\": \"value\"}', read from a file like @file.json, or read from stdin like @-.",
|
|
151
|
+
"exclusive": [
|
|
152
|
+
"integrationId"
|
|
153
|
+
],
|
|
154
|
+
"name": "json",
|
|
155
|
+
"required": false,
|
|
156
|
+
"hasDynamicHelp": false,
|
|
157
|
+
"multiple": false,
|
|
158
|
+
"type": "option"
|
|
159
|
+
},
|
|
160
|
+
"title": {
|
|
161
|
+
"char": "t",
|
|
162
|
+
"dependsOn": [
|
|
163
|
+
"json"
|
|
164
|
+
],
|
|
165
|
+
"description": "The integration title, which will be snake-cased for the package.json name.",
|
|
166
|
+
"name": "title",
|
|
167
|
+
"required": false,
|
|
168
|
+
"hasDynamicHelp": false,
|
|
169
|
+
"multiple": false,
|
|
170
|
+
"type": "option"
|
|
171
|
+
},
|
|
172
|
+
"description": {
|
|
173
|
+
"char": "d",
|
|
174
|
+
"dependsOn": [
|
|
175
|
+
"json"
|
|
176
|
+
],
|
|
177
|
+
"description": "The integration description, which will be used for the package.json description.",
|
|
178
|
+
"name": "description",
|
|
179
|
+
"required": false,
|
|
132
180
|
"hasDynamicHelp": false,
|
|
133
181
|
"multiple": false,
|
|
134
182
|
"type": "option"
|
|
@@ -178,9 +226,11 @@
|
|
|
178
226
|
"required": true
|
|
179
227
|
}
|
|
180
228
|
},
|
|
181
|
-
"description": "Mark a non-production version of your integration as deprecated, with removal by a certain date.\n\nUse this when an integration version will not be supported or start breaking at a known date.\n\nZapier will immediately send emails warning users of the deprecation if a date less than 30 days in the future is set, otherwise the emails will be sent exactly 30 days before the configured deprecation date.\n\nThere are other side effects: they'll start seeing it as \"Deprecated\" in the UI, and once the deprecation date arrives, if the Zaps weren't updated, they'll be paused and the users will be emailed again explaining what happened.\n\nDo not use deprecation if you only have non-breaking changes, such as:\n- Fixing help text\n- Adding new triggers/actions\n- Improving existing functionality\n- other bug fixes that don't break existing automations.",
|
|
229
|
+
"description": "Mark a non-production version of your integration as deprecated, with removal by a certain date.\n\nUse this when an integration version will not be supported or start breaking at a known date.\n\nWhen deprecating a version, you must provide a reason for the deprecation. You can either specify the reason using the --reason flag or you will be prompted to select from the following options:\n- API endpoint deprecated\n- Security vulnerability\n- Critical bug\n- Legal requirement\n- Other\n\nZapier will immediately send emails warning users of the deprecation if a date less than 30 days in the future is set, otherwise the emails will be sent exactly 30 days before the configured deprecation date.\n\nThere are other side effects: they'll start seeing it as \"Deprecated\" in the UI, and once the deprecation date arrives, if the Zaps weren't updated, they'll be paused and the users will be emailed again explaining what happened.\n\nDo not use deprecation if you only have non-breaking changes, such as:\n- Fixing help text\n- Adding new triggers/actions\n- Improving existing functionality\n- other bug fixes that don't break existing automations.",
|
|
182
230
|
"examples": [
|
|
183
|
-
"zapier deprecate 1.2.3 2011-10-01"
|
|
231
|
+
"zapier deprecate 1.2.3 2011-10-01",
|
|
232
|
+
"zapier deprecate 1.2.3 2011-10-01 --reason=security_vulnerability",
|
|
233
|
+
"zapier deprecate 1.2.3 2011-10-01 -r critical_bug"
|
|
184
234
|
],
|
|
185
235
|
"flags": {
|
|
186
236
|
"force": {
|
|
@@ -190,6 +240,21 @@
|
|
|
190
240
|
"allowNo": false,
|
|
191
241
|
"type": "boolean"
|
|
192
242
|
},
|
|
243
|
+
"reason": {
|
|
244
|
+
"char": "r",
|
|
245
|
+
"description": "Reason for deprecation.",
|
|
246
|
+
"name": "reason",
|
|
247
|
+
"hasDynamicHelp": false,
|
|
248
|
+
"multiple": false,
|
|
249
|
+
"options": [
|
|
250
|
+
"api endpoint deprecated",
|
|
251
|
+
"security vulnerability",
|
|
252
|
+
"critical bug",
|
|
253
|
+
"legal requirement",
|
|
254
|
+
"other"
|
|
255
|
+
],
|
|
256
|
+
"type": "option"
|
|
257
|
+
},
|
|
193
258
|
"debug": {
|
|
194
259
|
"char": "d",
|
|
195
260
|
"description": "Show extra debugging output.",
|
|
@@ -1630,6 +1695,88 @@
|
|
|
1630
1695
|
"clear.js"
|
|
1631
1696
|
]
|
|
1632
1697
|
},
|
|
1698
|
+
"delete:integration": {
|
|
1699
|
+
"aliases": [
|
|
1700
|
+
"delete:app"
|
|
1701
|
+
],
|
|
1702
|
+
"args": {},
|
|
1703
|
+
"description": "Delete your integration (including all versions).\n\nThis only works if there are no active users or Zaps on any version. If you only want to delete certain versions, use the `zapier delete:version` command instead. It's unlikely that you'll be able to run this on an app that you've pushed publicly, since there are usually still users.",
|
|
1704
|
+
"flags": {
|
|
1705
|
+
"debug": {
|
|
1706
|
+
"char": "d",
|
|
1707
|
+
"description": "Show extra debugging output.",
|
|
1708
|
+
"name": "debug",
|
|
1709
|
+
"allowNo": false,
|
|
1710
|
+
"type": "boolean"
|
|
1711
|
+
},
|
|
1712
|
+
"invokedFromAnotherCommand": {
|
|
1713
|
+
"hidden": true,
|
|
1714
|
+
"name": "invokedFromAnotherCommand",
|
|
1715
|
+
"allowNo": false,
|
|
1716
|
+
"type": "boolean"
|
|
1717
|
+
}
|
|
1718
|
+
},
|
|
1719
|
+
"hasDynamicHelp": false,
|
|
1720
|
+
"hiddenAliases": [],
|
|
1721
|
+
"id": "delete:integration",
|
|
1722
|
+
"pluginAlias": "zapier-platform-cli",
|
|
1723
|
+
"pluginName": "zapier-platform-cli",
|
|
1724
|
+
"pluginType": "core",
|
|
1725
|
+
"strict": true,
|
|
1726
|
+
"enableJsonFlag": false,
|
|
1727
|
+
"skipValidInstallCheck": true,
|
|
1728
|
+
"isESM": false,
|
|
1729
|
+
"relativePath": [
|
|
1730
|
+
"src",
|
|
1731
|
+
"oclif",
|
|
1732
|
+
"commands",
|
|
1733
|
+
"delete",
|
|
1734
|
+
"integration.js"
|
|
1735
|
+
]
|
|
1736
|
+
},
|
|
1737
|
+
"delete:version": {
|
|
1738
|
+
"aliases": [],
|
|
1739
|
+
"args": {
|
|
1740
|
+
"version": {
|
|
1741
|
+
"description": "Specify the version to delete. It must have no users or Zaps.",
|
|
1742
|
+
"name": "version",
|
|
1743
|
+
"required": true
|
|
1744
|
+
}
|
|
1745
|
+
},
|
|
1746
|
+
"description": "Delete a specific version of your integration.\n\nThis only works if there are no users or Zaps on that version. You will probably need to have run `zapier migrate` and `zapier deprecate` before this command will work.",
|
|
1747
|
+
"flags": {
|
|
1748
|
+
"debug": {
|
|
1749
|
+
"char": "d",
|
|
1750
|
+
"description": "Show extra debugging output.",
|
|
1751
|
+
"name": "debug",
|
|
1752
|
+
"allowNo": false,
|
|
1753
|
+
"type": "boolean"
|
|
1754
|
+
},
|
|
1755
|
+
"invokedFromAnotherCommand": {
|
|
1756
|
+
"hidden": true,
|
|
1757
|
+
"name": "invokedFromAnotherCommand",
|
|
1758
|
+
"allowNo": false,
|
|
1759
|
+
"type": "boolean"
|
|
1760
|
+
}
|
|
1761
|
+
},
|
|
1762
|
+
"hasDynamicHelp": false,
|
|
1763
|
+
"hiddenAliases": [],
|
|
1764
|
+
"id": "delete:version",
|
|
1765
|
+
"pluginAlias": "zapier-platform-cli",
|
|
1766
|
+
"pluginName": "zapier-platform-cli",
|
|
1767
|
+
"pluginType": "core",
|
|
1768
|
+
"strict": true,
|
|
1769
|
+
"enableJsonFlag": false,
|
|
1770
|
+
"skipValidInstallCheck": true,
|
|
1771
|
+
"isESM": false,
|
|
1772
|
+
"relativePath": [
|
|
1773
|
+
"src",
|
|
1774
|
+
"oclif",
|
|
1775
|
+
"commands",
|
|
1776
|
+
"delete",
|
|
1777
|
+
"version.js"
|
|
1778
|
+
]
|
|
1779
|
+
},
|
|
1633
1780
|
"canary:create": {
|
|
1634
1781
|
"aliases": [],
|
|
1635
1782
|
"args": {
|
|
@@ -1793,88 +1940,6 @@
|
|
|
1793
1940
|
"list.js"
|
|
1794
1941
|
]
|
|
1795
1942
|
},
|
|
1796
|
-
"delete:integration": {
|
|
1797
|
-
"aliases": [
|
|
1798
|
-
"delete:app"
|
|
1799
|
-
],
|
|
1800
|
-
"args": {},
|
|
1801
|
-
"description": "Delete your integration (including all versions).\n\nThis only works if there are no active users or Zaps on any version. If you only want to delete certain versions, use the `zapier delete:version` command instead. It's unlikely that you'll be able to run this on an app that you've pushed publicly, since there are usually still users.",
|
|
1802
|
-
"flags": {
|
|
1803
|
-
"debug": {
|
|
1804
|
-
"char": "d",
|
|
1805
|
-
"description": "Show extra debugging output.",
|
|
1806
|
-
"name": "debug",
|
|
1807
|
-
"allowNo": false,
|
|
1808
|
-
"type": "boolean"
|
|
1809
|
-
},
|
|
1810
|
-
"invokedFromAnotherCommand": {
|
|
1811
|
-
"hidden": true,
|
|
1812
|
-
"name": "invokedFromAnotherCommand",
|
|
1813
|
-
"allowNo": false,
|
|
1814
|
-
"type": "boolean"
|
|
1815
|
-
}
|
|
1816
|
-
},
|
|
1817
|
-
"hasDynamicHelp": false,
|
|
1818
|
-
"hiddenAliases": [],
|
|
1819
|
-
"id": "delete:integration",
|
|
1820
|
-
"pluginAlias": "zapier-platform-cli",
|
|
1821
|
-
"pluginName": "zapier-platform-cli",
|
|
1822
|
-
"pluginType": "core",
|
|
1823
|
-
"strict": true,
|
|
1824
|
-
"enableJsonFlag": false,
|
|
1825
|
-
"skipValidInstallCheck": true,
|
|
1826
|
-
"isESM": false,
|
|
1827
|
-
"relativePath": [
|
|
1828
|
-
"src",
|
|
1829
|
-
"oclif",
|
|
1830
|
-
"commands",
|
|
1831
|
-
"delete",
|
|
1832
|
-
"integration.js"
|
|
1833
|
-
]
|
|
1834
|
-
},
|
|
1835
|
-
"delete:version": {
|
|
1836
|
-
"aliases": [],
|
|
1837
|
-
"args": {
|
|
1838
|
-
"version": {
|
|
1839
|
-
"description": "Specify the version to delete. It must have no users or Zaps.",
|
|
1840
|
-
"name": "version",
|
|
1841
|
-
"required": true
|
|
1842
|
-
}
|
|
1843
|
-
},
|
|
1844
|
-
"description": "Delete a specific version of your integration.\n\nThis only works if there are no users or Zaps on that version. You will probably need to have run `zapier migrate` and `zapier deprecate` before this command will work.",
|
|
1845
|
-
"flags": {
|
|
1846
|
-
"debug": {
|
|
1847
|
-
"char": "d",
|
|
1848
|
-
"description": "Show extra debugging output.",
|
|
1849
|
-
"name": "debug",
|
|
1850
|
-
"allowNo": false,
|
|
1851
|
-
"type": "boolean"
|
|
1852
|
-
},
|
|
1853
|
-
"invokedFromAnotherCommand": {
|
|
1854
|
-
"hidden": true,
|
|
1855
|
-
"name": "invokedFromAnotherCommand",
|
|
1856
|
-
"allowNo": false,
|
|
1857
|
-
"type": "boolean"
|
|
1858
|
-
}
|
|
1859
|
-
},
|
|
1860
|
-
"hasDynamicHelp": false,
|
|
1861
|
-
"hiddenAliases": [],
|
|
1862
|
-
"id": "delete:version",
|
|
1863
|
-
"pluginAlias": "zapier-platform-cli",
|
|
1864
|
-
"pluginName": "zapier-platform-cli",
|
|
1865
|
-
"pluginType": "core",
|
|
1866
|
-
"strict": true,
|
|
1867
|
-
"enableJsonFlag": false,
|
|
1868
|
-
"skipValidInstallCheck": true,
|
|
1869
|
-
"isESM": false,
|
|
1870
|
-
"relativePath": [
|
|
1871
|
-
"src",
|
|
1872
|
-
"oclif",
|
|
1873
|
-
"commands",
|
|
1874
|
-
"delete",
|
|
1875
|
-
"version.js"
|
|
1876
|
-
]
|
|
1877
|
-
},
|
|
1878
1943
|
"env:get": {
|
|
1879
1944
|
"aliases": [],
|
|
1880
1945
|
"args": {
|
|
@@ -2430,5 +2495,5 @@
|
|
|
2430
2495
|
]
|
|
2431
2496
|
}
|
|
2432
2497
|
},
|
|
2433
|
-
"version": "17.0
|
|
2498
|
+
"version": "17.2.0"
|
|
2434
2499
|
}
|
package/package.json
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
const fs = require('node:fs/promises');
|
|
2
|
+
|
|
1
3
|
const { Args, Flags } = require('@oclif/core');
|
|
2
4
|
|
|
3
5
|
const BaseCommand = require('../ZapierBaseCommand');
|
|
@@ -8,9 +10,40 @@ const { convertApp } = require('../../utils/convert');
|
|
|
8
10
|
const { isExistingEmptyDir } = require('../../utils/files');
|
|
9
11
|
const { initApp } = require('../../utils/init');
|
|
10
12
|
|
|
13
|
+
const readStream = async (stream) => {
|
|
14
|
+
const chunks = [];
|
|
15
|
+
for await (const chunk of stream) {
|
|
16
|
+
chunks.push(chunk);
|
|
17
|
+
}
|
|
18
|
+
return chunks.join('');
|
|
19
|
+
};
|
|
20
|
+
|
|
11
21
|
class ConvertCommand extends BaseCommand {
|
|
12
|
-
generateCreateFunc(appId, version) {
|
|
22
|
+
generateCreateFunc(appId, version, json, title, description) {
|
|
13
23
|
return async (tempAppDir) => {
|
|
24
|
+
if (json) {
|
|
25
|
+
const appInfo = {
|
|
26
|
+
title,
|
|
27
|
+
description,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
let parsedDefinition = json;
|
|
31
|
+
if (parsedDefinition.startsWith('@')) {
|
|
32
|
+
const filePath = parsedDefinition.substr(1);
|
|
33
|
+
let definitionStream;
|
|
34
|
+
if (filePath === '-') {
|
|
35
|
+
definitionStream = process.stdin;
|
|
36
|
+
} else {
|
|
37
|
+
const fd = await fs.open(filePath);
|
|
38
|
+
definitionStream = fd.createReadStream({ encoding: 'utf8' });
|
|
39
|
+
}
|
|
40
|
+
parsedDefinition = await readStream(definitionStream);
|
|
41
|
+
}
|
|
42
|
+
parsedDefinition = JSON.parse(parsedDefinition);
|
|
43
|
+
|
|
44
|
+
return convertApp(appInfo, parsedDefinition, tempAppDir);
|
|
45
|
+
}
|
|
46
|
+
|
|
14
47
|
// has info about the app, such as title
|
|
15
48
|
// has a CLI version of the actual app implementation
|
|
16
49
|
this.throwForInvalidVersion(version);
|
|
@@ -41,13 +74,14 @@ class ConvertCommand extends BaseCommand {
|
|
|
41
74
|
}
|
|
42
75
|
|
|
43
76
|
async perform() {
|
|
44
|
-
const {
|
|
45
|
-
const {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
77
|
+
const { path } = this.args;
|
|
78
|
+
const {
|
|
79
|
+
integrationId: appId,
|
|
80
|
+
version,
|
|
81
|
+
json,
|
|
82
|
+
title,
|
|
83
|
+
description,
|
|
84
|
+
} = this.flags;
|
|
51
85
|
|
|
52
86
|
if (
|
|
53
87
|
(await isExistingEmptyDir(path)) &&
|
|
@@ -56,16 +90,18 @@ class ConvertCommand extends BaseCommand {
|
|
|
56
90
|
this.exit();
|
|
57
91
|
}
|
|
58
92
|
|
|
59
|
-
|
|
93
|
+
if (!appId && !json) {
|
|
94
|
+
this.error('You must provide either an integrationId or json.');
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
await initApp(
|
|
98
|
+
path,
|
|
99
|
+
this.generateCreateFunc(appId, version, json, title, description),
|
|
100
|
+
);
|
|
60
101
|
}
|
|
61
102
|
}
|
|
62
103
|
|
|
63
104
|
ConvertCommand.args = {
|
|
64
|
-
integrationId: Args.string({
|
|
65
|
-
description: `To get the integration/app ID, go to "https://developer.zapier.com", click on an integration, and copy the number directly after "/app/" in the URL.`,
|
|
66
|
-
required: true,
|
|
67
|
-
parse: (input) => Number(input),
|
|
68
|
-
}),
|
|
69
105
|
path: Args.string({
|
|
70
106
|
description:
|
|
71
107
|
'Relative to your current path - IE: `.` for current directory.',
|
|
@@ -75,11 +111,41 @@ ConvertCommand.args = {
|
|
|
75
111
|
|
|
76
112
|
ConvertCommand.flags = buildFlags({
|
|
77
113
|
commandFlags: {
|
|
114
|
+
integrationId: Args.string({
|
|
115
|
+
char: 'i',
|
|
116
|
+
description: `To get the integration/app ID, go to "https://developer.zapier.com", click on an integration, and copy the number directly after "/app/" in the URL.`,
|
|
117
|
+
required: false,
|
|
118
|
+
dependsOn: ['version'],
|
|
119
|
+
exclusive: ['definition'],
|
|
120
|
+
parse: (input) => Number(input),
|
|
121
|
+
}),
|
|
78
122
|
version: Flags.string({
|
|
79
123
|
char: 'v',
|
|
80
124
|
description:
|
|
81
125
|
'Convert a specific version. Required when converting a Visual Builder integration.',
|
|
82
|
-
required:
|
|
126
|
+
required: false,
|
|
127
|
+
dependsOn: ['integrationId'],
|
|
128
|
+
}),
|
|
129
|
+
json: Flags.string({
|
|
130
|
+
char: 'j',
|
|
131
|
+
description:
|
|
132
|
+
'The JSON definition to use, as alternative for reading from a Visual Builder integration. Must be a JSON-encoded object. The data can be passed from the command directly like \'{"key": "value"}\', read from a file like @file.json, or read from stdin like @-.',
|
|
133
|
+
required: false,
|
|
134
|
+
exclusive: ['integrationId'],
|
|
135
|
+
}),
|
|
136
|
+
title: Flags.string({
|
|
137
|
+
char: 't',
|
|
138
|
+
description:
|
|
139
|
+
'The integration title, which will be snake-cased for the package.json name.',
|
|
140
|
+
required: false,
|
|
141
|
+
dependsOn: ['json'],
|
|
142
|
+
}),
|
|
143
|
+
description: Flags.string({
|
|
144
|
+
char: 'd',
|
|
145
|
+
description:
|
|
146
|
+
'The integration description, which will be used for the package.json description.',
|
|
147
|
+
required: false,
|
|
148
|
+
dependsOn: ['json'],
|
|
83
149
|
}),
|
|
84
150
|
},
|
|
85
151
|
});
|
|
@@ -5,6 +5,14 @@ const colors = require('colors/safe');
|
|
|
5
5
|
|
|
6
6
|
const { callAPI, getSpecificVersionInfo } = require('../../utils/api');
|
|
7
7
|
|
|
8
|
+
const DEPRECATION_REASONS = [
|
|
9
|
+
{ name: 'API endpoint deprecated', value: 'api endpoint deprecated' },
|
|
10
|
+
{ name: 'Security vulnerability', value: 'security vulnerability' },
|
|
11
|
+
{ name: 'Critical bug', value: 'critical bug' },
|
|
12
|
+
{ name: 'Legal requirement', value: 'legal requirement' },
|
|
13
|
+
{ name: 'Other', value: 'other' },
|
|
14
|
+
];
|
|
15
|
+
|
|
8
16
|
class DeprecateCommand extends BaseCommand {
|
|
9
17
|
async perform() {
|
|
10
18
|
const app = await this.getWritableApp();
|
|
@@ -18,6 +26,40 @@ class DeprecateCommand extends BaseCommand {
|
|
|
18
26
|
`${colors.yellow('If all your changes are non-breaking, use `zapier migrate` instead to move users over to a newer version.')}\n`,
|
|
19
27
|
);
|
|
20
28
|
|
|
29
|
+
// Get deprecation reason - either from flag or prompt user
|
|
30
|
+
let deprecationReason = this.flags.reason;
|
|
31
|
+
|
|
32
|
+
if (!deprecationReason) {
|
|
33
|
+
deprecationReason = await this.promptWithList(
|
|
34
|
+
'Please select a reason for deprecating this version:',
|
|
35
|
+
DEPRECATION_REASONS,
|
|
36
|
+
{
|
|
37
|
+
useStderr: true,
|
|
38
|
+
},
|
|
39
|
+
);
|
|
40
|
+
} else {
|
|
41
|
+
// Validate the provided reason
|
|
42
|
+
const validReasons = DEPRECATION_REASONS.map((r) => r.value);
|
|
43
|
+
if (!validReasons.includes(deprecationReason)) {
|
|
44
|
+
this.error(
|
|
45
|
+
`Invalid deprecation reason: ${deprecationReason}. Valid options are: ${validReasons.join(', ')}`,
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
let customReason = null;
|
|
51
|
+
if (deprecationReason === 'other') {
|
|
52
|
+
customReason = await this.prompt(
|
|
53
|
+
'Please provide a brief user-facing reason (50 characters max):',
|
|
54
|
+
{
|
|
55
|
+
required: true,
|
|
56
|
+
charLimit: 50,
|
|
57
|
+
useStderr: true,
|
|
58
|
+
},
|
|
59
|
+
);
|
|
60
|
+
customReason = 'other: ' + customReason;
|
|
61
|
+
}
|
|
62
|
+
|
|
21
63
|
if (
|
|
22
64
|
!this.flags.force &&
|
|
23
65
|
!(await this.confirm(
|
|
@@ -32,14 +74,16 @@ class DeprecateCommand extends BaseCommand {
|
|
|
32
74
|
}
|
|
33
75
|
|
|
34
76
|
this.log(
|
|
35
|
-
`\nPreparing to deprecate version ${version} your app "${app.title}".\n`,
|
|
77
|
+
`\nPreparing to deprecate version ${version} your app "${app.title}" due to: ${customReason || DEPRECATION_REASONS.find((r) => r.value === deprecationReason)?.name}.\n`,
|
|
36
78
|
);
|
|
79
|
+
|
|
37
80
|
const url = `/apps/${app.id}/versions/${version}/deprecate`;
|
|
38
81
|
this.startSpinner(`Deprecating ${version}`);
|
|
39
82
|
await callAPI(url, {
|
|
40
83
|
method: 'PUT',
|
|
41
84
|
body: {
|
|
42
85
|
deprecation_date: date,
|
|
86
|
+
deprecation_reason: customReason || deprecationReason,
|
|
43
87
|
},
|
|
44
88
|
});
|
|
45
89
|
this.stopSpinner();
|
|
@@ -55,6 +99,11 @@ DeprecateCommand.flags = buildFlags({
|
|
|
55
99
|
char: 'f',
|
|
56
100
|
description: 'Skip confirmation prompt. Use with caution.',
|
|
57
101
|
}),
|
|
102
|
+
reason: Flags.string({
|
|
103
|
+
char: 'r',
|
|
104
|
+
description: 'Reason for deprecation.',
|
|
105
|
+
options: DEPRECATION_REASONS.map((r) => r.value),
|
|
106
|
+
}),
|
|
58
107
|
},
|
|
59
108
|
});
|
|
60
109
|
DeprecateCommand.args = {
|
|
@@ -68,11 +117,18 @@ DeprecateCommand.args = {
|
|
|
68
117
|
required: true,
|
|
69
118
|
}),
|
|
70
119
|
};
|
|
71
|
-
DeprecateCommand.examples = [
|
|
120
|
+
DeprecateCommand.examples = [
|
|
121
|
+
'zapier deprecate 1.2.3 2011-10-01',
|
|
122
|
+
'zapier deprecate 1.2.3 2011-10-01 --reason=security_vulnerability',
|
|
123
|
+
'zapier deprecate 1.2.3 2011-10-01 -r critical_bug',
|
|
124
|
+
];
|
|
72
125
|
DeprecateCommand.description = `Mark a non-production version of your integration as deprecated, with removal by a certain date.
|
|
73
126
|
|
|
74
127
|
Use this when an integration version will not be supported or start breaking at a known date.
|
|
75
128
|
|
|
129
|
+
When deprecating a version, you must provide a reason for the deprecation. You can either specify the reason using the --reason flag or you will be prompted to select from the following options:
|
|
130
|
+
${DEPRECATION_REASONS.map((r) => `- ${r.name}`).join('\n')}
|
|
131
|
+
|
|
76
132
|
Zapier will immediately send emails warning users of the deprecation if a date less than 30 days in the future is set, otherwise the emails will be sent exactly 30 days before the configured deprecation date.
|
|
77
133
|
|
|
78
134
|
There are other side effects: they'll start seeing it as "Deprecated" in the UI, and once the deprecation date arrives, if the Zaps weren't updated, they'll be paused and the users will be emailed again explaining what happened.
|
package/src/utils/convert.js
CHANGED
|
@@ -101,7 +101,7 @@ const getAuthFieldKeys = (appDefinition) => {
|
|
|
101
101
|
|
|
102
102
|
const renderPackageJson = async (appInfo, appDefinition) => {
|
|
103
103
|
const name = _.kebabCase(
|
|
104
|
-
appInfo.title || _.get(appInfo, ['general', 'title']),
|
|
104
|
+
appInfo.title || _.get(appInfo, ['general', 'title']) || '',
|
|
105
105
|
);
|
|
106
106
|
|
|
107
107
|
// Not using escapeSpecialChars because we don't want to escape single quotes (not
|
|
@@ -366,10 +366,10 @@ const writeGitIgnore = async (newAppDir) => {
|
|
|
366
366
|
};
|
|
367
367
|
|
|
368
368
|
const writeZapierAppRc = async (appInfo, appDefinition, newAppDir) => {
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
json.id = appInfo.id;
|
|
369
|
+
if (!appInfo.id) {
|
|
370
|
+
return;
|
|
372
371
|
}
|
|
372
|
+
const json = { id: appInfo.id };
|
|
373
373
|
if (appInfo.key) {
|
|
374
374
|
json.key = appInfo.key;
|
|
375
375
|
}
|