zapier-platform-cli 17.6.0 → 17.7.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/oclif.manifest.json +195 -181
- package/package.json +9 -8
- package/src/generators/index.js +18 -2
- package/src/oclif/ZapierBaseCommand.js +7 -2
- package/src/oclif/commands/invoke.js +33 -7
- package/src/oclif/commands/migrate.js +12 -11
- package/src/oclif/commands/pull.js +12 -4
- package/src/oclif/commands/scaffold.js +0 -1
- package/src/oclif/commands/validate.js +9 -0
- package/src/utils/analytics.js +1 -1
- package/src/utils/ast.js +20 -7
- package/src/utils/build.js +29 -10
- package/src/utils/scaffold.js +49 -11
package/oclif.manifest.json
CHANGED
|
@@ -652,6 +652,13 @@
|
|
|
652
652
|
"multiple": false,
|
|
653
653
|
"type": "option"
|
|
654
654
|
},
|
|
655
|
+
"paging-token": {
|
|
656
|
+
"description": "Set bundle.meta.paging_token. Used for search pagination or bulk reads. When used in production, this indicates which page of items you should fetch.",
|
|
657
|
+
"name": "paging-token",
|
|
658
|
+
"hasDynamicHelp": false,
|
|
659
|
+
"multiple": false,
|
|
660
|
+
"type": "option"
|
|
661
|
+
},
|
|
655
662
|
"debug": {
|
|
656
663
|
"char": "d",
|
|
657
664
|
"description": "Show extra debugging output.",
|
|
@@ -1150,7 +1157,7 @@
|
|
|
1150
1157
|
"pull": {
|
|
1151
1158
|
"aliases": [],
|
|
1152
1159
|
"args": {},
|
|
1153
|
-
"description": "Retrieve and update your local integration files with the latest version.\n\nThis command updates your local integration files with the latest version. You will be prompted with a confirmation dialog before continuing if there any destructive file changes.\n\nZapier may release new versions of your integration with bug fixes or new features. In the event this occurs, you will be unable to do the following until your local files are updated by running `zapier pull`:\n\n* push to the promoted version\n* promote a new version\n* migrate users from one version to another",
|
|
1160
|
+
"description": "Retrieve and update your local integration files with the promoted version (or latest version if not public).\n\nThis command updates your local integration files with the promoted version (or latest version if not public). You will be prompted with a confirmation dialog before continuing if there any destructive file changes.\n\nZapier may release new versions of your integration with bug fixes or new features. In the event this occurs, you will be unable to do the following until your local files are updated by running `zapier pull`:\n\n* push to the promoted version\n* promote a new version\n* migrate users from one version to another",
|
|
1154
1161
|
"flags": {
|
|
1155
1162
|
"debug": {
|
|
1156
1163
|
"char": "d",
|
|
@@ -1542,6 +1549,7 @@
|
|
|
1542
1549
|
"examples": [
|
|
1543
1550
|
"zapier validate",
|
|
1544
1551
|
"zapier validate --without-style",
|
|
1552
|
+
"zapier validate --skip-build",
|
|
1545
1553
|
"zapier validate --format json"
|
|
1546
1554
|
],
|
|
1547
1555
|
"flags": {
|
|
@@ -1551,6 +1559,12 @@
|
|
|
1551
1559
|
"allowNo": false,
|
|
1552
1560
|
"type": "boolean"
|
|
1553
1561
|
},
|
|
1562
|
+
"skip-build": {
|
|
1563
|
+
"description": "Skip running the _zapier-build script before validation.",
|
|
1564
|
+
"name": "skip-build",
|
|
1565
|
+
"allowNo": false,
|
|
1566
|
+
"type": "boolean"
|
|
1567
|
+
},
|
|
1554
1568
|
"debug": {
|
|
1555
1569
|
"char": "d",
|
|
1556
1570
|
"description": "Show extra debugging output.",
|
|
@@ -1705,88 +1719,6 @@
|
|
|
1705
1719
|
"clear.js"
|
|
1706
1720
|
]
|
|
1707
1721
|
},
|
|
1708
|
-
"delete:integration": {
|
|
1709
|
-
"aliases": [
|
|
1710
|
-
"delete:app"
|
|
1711
|
-
],
|
|
1712
|
-
"args": {},
|
|
1713
|
-
"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.",
|
|
1714
|
-
"flags": {
|
|
1715
|
-
"debug": {
|
|
1716
|
-
"char": "d",
|
|
1717
|
-
"description": "Show extra debugging output.",
|
|
1718
|
-
"name": "debug",
|
|
1719
|
-
"allowNo": false,
|
|
1720
|
-
"type": "boolean"
|
|
1721
|
-
},
|
|
1722
|
-
"invokedFromAnotherCommand": {
|
|
1723
|
-
"hidden": true,
|
|
1724
|
-
"name": "invokedFromAnotherCommand",
|
|
1725
|
-
"allowNo": false,
|
|
1726
|
-
"type": "boolean"
|
|
1727
|
-
}
|
|
1728
|
-
},
|
|
1729
|
-
"hasDynamicHelp": false,
|
|
1730
|
-
"hiddenAliases": [],
|
|
1731
|
-
"id": "delete:integration",
|
|
1732
|
-
"pluginAlias": "zapier-platform-cli",
|
|
1733
|
-
"pluginName": "zapier-platform-cli",
|
|
1734
|
-
"pluginType": "core",
|
|
1735
|
-
"strict": true,
|
|
1736
|
-
"enableJsonFlag": false,
|
|
1737
|
-
"skipValidInstallCheck": true,
|
|
1738
|
-
"isESM": false,
|
|
1739
|
-
"relativePath": [
|
|
1740
|
-
"src",
|
|
1741
|
-
"oclif",
|
|
1742
|
-
"commands",
|
|
1743
|
-
"delete",
|
|
1744
|
-
"integration.js"
|
|
1745
|
-
]
|
|
1746
|
-
},
|
|
1747
|
-
"delete:version": {
|
|
1748
|
-
"aliases": [],
|
|
1749
|
-
"args": {
|
|
1750
|
-
"version": {
|
|
1751
|
-
"description": "Specify the version to delete. It must have no users or Zaps.",
|
|
1752
|
-
"name": "version",
|
|
1753
|
-
"required": true
|
|
1754
|
-
}
|
|
1755
|
-
},
|
|
1756
|
-
"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.",
|
|
1757
|
-
"flags": {
|
|
1758
|
-
"debug": {
|
|
1759
|
-
"char": "d",
|
|
1760
|
-
"description": "Show extra debugging output.",
|
|
1761
|
-
"name": "debug",
|
|
1762
|
-
"allowNo": false,
|
|
1763
|
-
"type": "boolean"
|
|
1764
|
-
},
|
|
1765
|
-
"invokedFromAnotherCommand": {
|
|
1766
|
-
"hidden": true,
|
|
1767
|
-
"name": "invokedFromAnotherCommand",
|
|
1768
|
-
"allowNo": false,
|
|
1769
|
-
"type": "boolean"
|
|
1770
|
-
}
|
|
1771
|
-
},
|
|
1772
|
-
"hasDynamicHelp": false,
|
|
1773
|
-
"hiddenAliases": [],
|
|
1774
|
-
"id": "delete:version",
|
|
1775
|
-
"pluginAlias": "zapier-platform-cli",
|
|
1776
|
-
"pluginName": "zapier-platform-cli",
|
|
1777
|
-
"pluginType": "core",
|
|
1778
|
-
"strict": true,
|
|
1779
|
-
"enableJsonFlag": false,
|
|
1780
|
-
"skipValidInstallCheck": true,
|
|
1781
|
-
"isESM": false,
|
|
1782
|
-
"relativePath": [
|
|
1783
|
-
"src",
|
|
1784
|
-
"oclif",
|
|
1785
|
-
"commands",
|
|
1786
|
-
"delete",
|
|
1787
|
-
"version.js"
|
|
1788
|
-
]
|
|
1789
|
-
},
|
|
1790
1722
|
"canary:create": {
|
|
1791
1723
|
"aliases": [],
|
|
1792
1724
|
"args": {
|
|
@@ -1975,6 +1907,88 @@
|
|
|
1975
1907
|
"list.js"
|
|
1976
1908
|
]
|
|
1977
1909
|
},
|
|
1910
|
+
"delete:integration": {
|
|
1911
|
+
"aliases": [
|
|
1912
|
+
"delete:app"
|
|
1913
|
+
],
|
|
1914
|
+
"args": {},
|
|
1915
|
+
"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.",
|
|
1916
|
+
"flags": {
|
|
1917
|
+
"debug": {
|
|
1918
|
+
"char": "d",
|
|
1919
|
+
"description": "Show extra debugging output.",
|
|
1920
|
+
"name": "debug",
|
|
1921
|
+
"allowNo": false,
|
|
1922
|
+
"type": "boolean"
|
|
1923
|
+
},
|
|
1924
|
+
"invokedFromAnotherCommand": {
|
|
1925
|
+
"hidden": true,
|
|
1926
|
+
"name": "invokedFromAnotherCommand",
|
|
1927
|
+
"allowNo": false,
|
|
1928
|
+
"type": "boolean"
|
|
1929
|
+
}
|
|
1930
|
+
},
|
|
1931
|
+
"hasDynamicHelp": false,
|
|
1932
|
+
"hiddenAliases": [],
|
|
1933
|
+
"id": "delete:integration",
|
|
1934
|
+
"pluginAlias": "zapier-platform-cli",
|
|
1935
|
+
"pluginName": "zapier-platform-cli",
|
|
1936
|
+
"pluginType": "core",
|
|
1937
|
+
"strict": true,
|
|
1938
|
+
"enableJsonFlag": false,
|
|
1939
|
+
"skipValidInstallCheck": true,
|
|
1940
|
+
"isESM": false,
|
|
1941
|
+
"relativePath": [
|
|
1942
|
+
"src",
|
|
1943
|
+
"oclif",
|
|
1944
|
+
"commands",
|
|
1945
|
+
"delete",
|
|
1946
|
+
"integration.js"
|
|
1947
|
+
]
|
|
1948
|
+
},
|
|
1949
|
+
"delete:version": {
|
|
1950
|
+
"aliases": [],
|
|
1951
|
+
"args": {
|
|
1952
|
+
"version": {
|
|
1953
|
+
"description": "Specify the version to delete. It must have no users or Zaps.",
|
|
1954
|
+
"name": "version",
|
|
1955
|
+
"required": true
|
|
1956
|
+
}
|
|
1957
|
+
},
|
|
1958
|
+
"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.",
|
|
1959
|
+
"flags": {
|
|
1960
|
+
"debug": {
|
|
1961
|
+
"char": "d",
|
|
1962
|
+
"description": "Show extra debugging output.",
|
|
1963
|
+
"name": "debug",
|
|
1964
|
+
"allowNo": false,
|
|
1965
|
+
"type": "boolean"
|
|
1966
|
+
},
|
|
1967
|
+
"invokedFromAnotherCommand": {
|
|
1968
|
+
"hidden": true,
|
|
1969
|
+
"name": "invokedFromAnotherCommand",
|
|
1970
|
+
"allowNo": false,
|
|
1971
|
+
"type": "boolean"
|
|
1972
|
+
}
|
|
1973
|
+
},
|
|
1974
|
+
"hasDynamicHelp": false,
|
|
1975
|
+
"hiddenAliases": [],
|
|
1976
|
+
"id": "delete:version",
|
|
1977
|
+
"pluginAlias": "zapier-platform-cli",
|
|
1978
|
+
"pluginName": "zapier-platform-cli",
|
|
1979
|
+
"pluginType": "core",
|
|
1980
|
+
"strict": true,
|
|
1981
|
+
"enableJsonFlag": false,
|
|
1982
|
+
"skipValidInstallCheck": true,
|
|
1983
|
+
"isESM": false,
|
|
1984
|
+
"relativePath": [
|
|
1985
|
+
"src",
|
|
1986
|
+
"oclif",
|
|
1987
|
+
"commands",
|
|
1988
|
+
"delete",
|
|
1989
|
+
"version.js"
|
|
1990
|
+
]
|
|
1991
|
+
},
|
|
1978
1992
|
"env:get": {
|
|
1979
1993
|
"aliases": [],
|
|
1980
1994
|
"args": {
|
|
@@ -2151,9 +2165,9 @@
|
|
|
2151
2165
|
"unset.js"
|
|
2152
2166
|
]
|
|
2153
2167
|
},
|
|
2154
|
-
"
|
|
2168
|
+
"team:add": {
|
|
2155
2169
|
"aliases": [
|
|
2156
|
-
"
|
|
2170
|
+
"team:invite"
|
|
2157
2171
|
],
|
|
2158
2172
|
"args": {
|
|
2159
2173
|
"email": {
|
|
@@ -2161,24 +2175,28 @@
|
|
|
2161
2175
|
"name": "email",
|
|
2162
2176
|
"required": true
|
|
2163
2177
|
},
|
|
2164
|
-
"
|
|
2165
|
-
"description": "
|
|
2166
|
-
"name": "
|
|
2178
|
+
"role": {
|
|
2179
|
+
"description": "The level the invited team member should be at. Admins can edit everything and get email updates. Collaborators have read-access to the app and get email updates. Subscribers only get email updates.",
|
|
2180
|
+
"name": "role",
|
|
2181
|
+
"options": [
|
|
2182
|
+
"admin",
|
|
2183
|
+
"collaborator",
|
|
2184
|
+
"subscriber"
|
|
2185
|
+
],
|
|
2186
|
+
"required": true
|
|
2187
|
+
},
|
|
2188
|
+
"message": {
|
|
2189
|
+
"description": "A message sent in the email to your team member, if you need to provide context. Wrap the message in quotes to ensure spaces get saved.",
|
|
2190
|
+
"name": "message"
|
|
2167
2191
|
}
|
|
2168
2192
|
},
|
|
2169
|
-
"description": "Add a
|
|
2193
|
+
"description": "Add a team member to your integration.\n\nThese users come in three levels:\n\n * `admin`, who can edit everything about the integration\n * `collaborator`, who has read-only access for the app, and will receive periodic email updates. These updates include quarterly health scores and more.\n * `subscriber`, who can't directly access the app, but will receive periodic email updates. These updates include quarterly health scores and more.\n\nTeam members can be freely added and removed.",
|
|
2170
2194
|
"examples": [
|
|
2171
|
-
"zapier
|
|
2172
|
-
"zapier
|
|
2195
|
+
"zapier team:add bruce@wayne.com admin",
|
|
2196
|
+
"zapier team:add robin@wayne.com collaborator \"Hey Robin, check out this app.\"",
|
|
2197
|
+
"zapier team:add alfred@wayne.com subscriber \"Hey Alfred, check out this app.\""
|
|
2173
2198
|
],
|
|
2174
2199
|
"flags": {
|
|
2175
|
-
"force": {
|
|
2176
|
-
"char": "f",
|
|
2177
|
-
"description": "Skip confirmation. Useful for running programatically.",
|
|
2178
|
-
"name": "force",
|
|
2179
|
-
"allowNo": false,
|
|
2180
|
-
"type": "boolean"
|
|
2181
|
-
},
|
|
2182
2200
|
"debug": {
|
|
2183
2201
|
"char": "d",
|
|
2184
2202
|
"description": "Show extra debugging output.",
|
|
@@ -2195,7 +2213,7 @@
|
|
|
2195
2213
|
},
|
|
2196
2214
|
"hasDynamicHelp": false,
|
|
2197
2215
|
"hiddenAliases": [],
|
|
2198
|
-
"id": "
|
|
2216
|
+
"id": "team:add",
|
|
2199
2217
|
"pluginAlias": "zapier-platform-cli",
|
|
2200
2218
|
"pluginName": "zapier-platform-cli",
|
|
2201
2219
|
"pluginType": "core",
|
|
@@ -2207,16 +2225,16 @@
|
|
|
2207
2225
|
"src",
|
|
2208
2226
|
"oclif",
|
|
2209
2227
|
"commands",
|
|
2210
|
-
"
|
|
2228
|
+
"team",
|
|
2211
2229
|
"add.js"
|
|
2212
2230
|
]
|
|
2213
2231
|
},
|
|
2214
|
-
"
|
|
2232
|
+
"team:get": {
|
|
2215
2233
|
"aliases": [
|
|
2216
|
-
"
|
|
2234
|
+
"team:list"
|
|
2217
2235
|
],
|
|
2218
2236
|
"args": {},
|
|
2219
|
-
"description": "Get
|
|
2237
|
+
"description": "Get team members involved with your integration.\n\nThese users come in three levels:\n\n * `admin`, who can edit everything about the integration\n * `collaborator`, who has read-only access for the app, and will receive periodic email updates. These updates include quarterly health scores and more.\n * `subscriber`, who can't directly access the app, but will receive periodic email updates. These updates include quarterly health scores and more.\n\nUse the `zapier team:add` and `zapier team:remove` commands to modify your team.\n",
|
|
2220
2238
|
"flags": {
|
|
2221
2239
|
"debug": {
|
|
2222
2240
|
"char": "d",
|
|
@@ -2250,7 +2268,7 @@
|
|
|
2250
2268
|
},
|
|
2251
2269
|
"hasDynamicHelp": false,
|
|
2252
2270
|
"hiddenAliases": [],
|
|
2253
|
-
"id": "
|
|
2271
|
+
"id": "team:get",
|
|
2254
2272
|
"pluginAlias": "zapier-platform-cli",
|
|
2255
2273
|
"pluginName": "zapier-platform-cli",
|
|
2256
2274
|
"pluginType": "core",
|
|
@@ -2262,14 +2280,16 @@
|
|
|
2262
2280
|
"src",
|
|
2263
2281
|
"oclif",
|
|
2264
2282
|
"commands",
|
|
2265
|
-
"
|
|
2283
|
+
"team",
|
|
2266
2284
|
"get.js"
|
|
2267
2285
|
]
|
|
2268
2286
|
},
|
|
2269
|
-
"
|
|
2270
|
-
"aliases": [
|
|
2287
|
+
"team:remove": {
|
|
2288
|
+
"aliases": [
|
|
2289
|
+
"team:delete"
|
|
2290
|
+
],
|
|
2271
2291
|
"args": {},
|
|
2272
|
-
"description": "
|
|
2292
|
+
"description": "Remove a team member from all versions of your integration.\n\nAdmins will immediately lose write access to the integration.\nCollaborators will immediately lose read access to the integration.\nSubscribers won't receive future email updates.",
|
|
2273
2293
|
"flags": {
|
|
2274
2294
|
"debug": {
|
|
2275
2295
|
"char": "d",
|
|
@@ -2278,22 +2298,6 @@
|
|
|
2278
2298
|
"allowNo": false,
|
|
2279
2299
|
"type": "boolean"
|
|
2280
2300
|
},
|
|
2281
|
-
"format": {
|
|
2282
|
-
"char": "f",
|
|
2283
|
-
"description": "Change the way structured data is presented. If \"json\" or \"raw\", you can pipe the output of the command into other tools, such as jq.",
|
|
2284
|
-
"name": "format",
|
|
2285
|
-
"default": "table",
|
|
2286
|
-
"hasDynamicHelp": false,
|
|
2287
|
-
"multiple": false,
|
|
2288
|
-
"options": [
|
|
2289
|
-
"plain",
|
|
2290
|
-
"json",
|
|
2291
|
-
"raw",
|
|
2292
|
-
"row",
|
|
2293
|
-
"table"
|
|
2294
|
-
],
|
|
2295
|
-
"type": "option"
|
|
2296
|
-
},
|
|
2297
2301
|
"invokedFromAnotherCommand": {
|
|
2298
2302
|
"hidden": true,
|
|
2299
2303
|
"name": "invokedFromAnotherCommand",
|
|
@@ -2303,7 +2307,7 @@
|
|
|
2303
2307
|
},
|
|
2304
2308
|
"hasDynamicHelp": false,
|
|
2305
2309
|
"hiddenAliases": [],
|
|
2306
|
-
"id": "
|
|
2310
|
+
"id": "team:remove",
|
|
2307
2311
|
"pluginAlias": "zapier-platform-cli",
|
|
2308
2312
|
"pluginName": "zapier-platform-cli",
|
|
2309
2313
|
"pluginType": "core",
|
|
@@ -2315,26 +2319,34 @@
|
|
|
2315
2319
|
"src",
|
|
2316
2320
|
"oclif",
|
|
2317
2321
|
"commands",
|
|
2318
|
-
"
|
|
2319
|
-
"
|
|
2322
|
+
"team",
|
|
2323
|
+
"remove.js"
|
|
2320
2324
|
]
|
|
2321
2325
|
},
|
|
2322
|
-
"users:
|
|
2326
|
+
"users:add": {
|
|
2323
2327
|
"aliases": [
|
|
2324
|
-
"users:
|
|
2328
|
+
"users:invite"
|
|
2325
2329
|
],
|
|
2326
2330
|
"args": {
|
|
2327
2331
|
"email": {
|
|
2328
|
-
"description": "The user to be
|
|
2332
|
+
"description": "The user to be invited. If they don't have a Zapier account, they'll be prompted to create one.",
|
|
2329
2333
|
"name": "email",
|
|
2330
2334
|
"required": true
|
|
2335
|
+
},
|
|
2336
|
+
"version": {
|
|
2337
|
+
"description": "A version string (like 1.2.3). Optional, used only if you want to invite a user to a specific version instead of all versions.",
|
|
2338
|
+
"name": "version"
|
|
2331
2339
|
}
|
|
2332
2340
|
},
|
|
2333
|
-
"description": "
|
|
2341
|
+
"description": "Add a user to some or all versions of your integration.\n\nWhen this command is run, we'll send an email to the user inviting them to try your integration. You can track the status of that invite using the `zapier users:get` command.\n\nInvited users will be able to see your integration's name, logo, and description. They'll also be able to create Zaps using any available triggers and actions.",
|
|
2342
|
+
"examples": [
|
|
2343
|
+
"zapier users:add bruce@wayne.com",
|
|
2344
|
+
"zapier users:add alfred@wayne.com 1.2.3"
|
|
2345
|
+
],
|
|
2334
2346
|
"flags": {
|
|
2335
2347
|
"force": {
|
|
2336
2348
|
"char": "f",
|
|
2337
|
-
"description": "
|
|
2349
|
+
"description": "Skip confirmation. Useful for running programatically.",
|
|
2338
2350
|
"name": "force",
|
|
2339
2351
|
"allowNo": false,
|
|
2340
2352
|
"type": "boolean"
|
|
@@ -2355,7 +2367,7 @@
|
|
|
2355
2367
|
},
|
|
2356
2368
|
"hasDynamicHelp": false,
|
|
2357
2369
|
"hiddenAliases": [],
|
|
2358
|
-
"id": "users:
|
|
2370
|
+
"id": "users:add",
|
|
2359
2371
|
"pluginAlias": "zapier-platform-cli",
|
|
2360
2372
|
"pluginName": "zapier-platform-cli",
|
|
2361
2373
|
"pluginType": "core",
|
|
@@ -2368,40 +2380,15 @@
|
|
|
2368
2380
|
"oclif",
|
|
2369
2381
|
"commands",
|
|
2370
2382
|
"users",
|
|
2371
|
-
"
|
|
2383
|
+
"add.js"
|
|
2372
2384
|
]
|
|
2373
2385
|
},
|
|
2374
|
-
"
|
|
2386
|
+
"users:get": {
|
|
2375
2387
|
"aliases": [
|
|
2376
|
-
"
|
|
2377
|
-
],
|
|
2378
|
-
"args": {
|
|
2379
|
-
"email": {
|
|
2380
|
-
"description": "The user to be invited. If they don't have a Zapier account, they'll be prompted to create one.",
|
|
2381
|
-
"name": "email",
|
|
2382
|
-
"required": true
|
|
2383
|
-
},
|
|
2384
|
-
"role": {
|
|
2385
|
-
"description": "The level the invited team member should be at. Admins can edit everything and get email updates. Collaborators have read-access to the app and get email updates. Subscribers only get email updates.",
|
|
2386
|
-
"name": "role",
|
|
2387
|
-
"options": [
|
|
2388
|
-
"admin",
|
|
2389
|
-
"collaborator",
|
|
2390
|
-
"subscriber"
|
|
2391
|
-
],
|
|
2392
|
-
"required": true
|
|
2393
|
-
},
|
|
2394
|
-
"message": {
|
|
2395
|
-
"description": "A message sent in the email to your team member, if you need to provide context. Wrap the message in quotes to ensure spaces get saved.",
|
|
2396
|
-
"name": "message"
|
|
2397
|
-
}
|
|
2398
|
-
},
|
|
2399
|
-
"description": "Add a team member to your integration.\n\nThese users come in three levels:\n\n * `admin`, who can edit everything about the integration\n * `collaborator`, who has read-only access for the app, and will receive periodic email updates. These updates include quarterly health scores and more.\n * `subscriber`, who can't directly access the app, but will receive periodic email updates. These updates include quarterly health scores and more.\n\nTeam members can be freely added and removed.",
|
|
2400
|
-
"examples": [
|
|
2401
|
-
"zapier team:add bruce@wayne.com admin",
|
|
2402
|
-
"zapier team:add robin@wayne.com collaborator \"Hey Robin, check out this app.\"",
|
|
2403
|
-
"zapier team:add alfred@wayne.com subscriber \"Hey Alfred, check out this app.\""
|
|
2388
|
+
"users:list"
|
|
2404
2389
|
],
|
|
2390
|
+
"args": {},
|
|
2391
|
+
"description": "Get a list of users who have been invited to your integration.\n\nNote that this list of users is NOT a comprehensive list of everyone who is using your integration. It only includes users who were invited directly by email (using the `\u001b[36mzapier users:add\u001b[39m` command or the web UI). Users who joined by clicking links generated using the `\u001b[36mzapier user:links\u001b[39m` command won't show up here.",
|
|
2405
2392
|
"flags": {
|
|
2406
2393
|
"debug": {
|
|
2407
2394
|
"char": "d",
|
|
@@ -2410,6 +2397,22 @@
|
|
|
2410
2397
|
"allowNo": false,
|
|
2411
2398
|
"type": "boolean"
|
|
2412
2399
|
},
|
|
2400
|
+
"format": {
|
|
2401
|
+
"char": "f",
|
|
2402
|
+
"description": "Change the way structured data is presented. If \"json\" or \"raw\", you can pipe the output of the command into other tools, such as jq.",
|
|
2403
|
+
"name": "format",
|
|
2404
|
+
"default": "table",
|
|
2405
|
+
"hasDynamicHelp": false,
|
|
2406
|
+
"multiple": false,
|
|
2407
|
+
"options": [
|
|
2408
|
+
"plain",
|
|
2409
|
+
"json",
|
|
2410
|
+
"raw",
|
|
2411
|
+
"row",
|
|
2412
|
+
"table"
|
|
2413
|
+
],
|
|
2414
|
+
"type": "option"
|
|
2415
|
+
},
|
|
2413
2416
|
"invokedFromAnotherCommand": {
|
|
2414
2417
|
"hidden": true,
|
|
2415
2418
|
"name": "invokedFromAnotherCommand",
|
|
@@ -2419,7 +2422,7 @@
|
|
|
2419
2422
|
},
|
|
2420
2423
|
"hasDynamicHelp": false,
|
|
2421
2424
|
"hiddenAliases": [],
|
|
2422
|
-
"id": "
|
|
2425
|
+
"id": "users:get",
|
|
2423
2426
|
"pluginAlias": "zapier-platform-cli",
|
|
2424
2427
|
"pluginName": "zapier-platform-cli",
|
|
2425
2428
|
"pluginType": "core",
|
|
@@ -2431,16 +2434,14 @@
|
|
|
2431
2434
|
"src",
|
|
2432
2435
|
"oclif",
|
|
2433
2436
|
"commands",
|
|
2434
|
-
"
|
|
2435
|
-
"
|
|
2437
|
+
"users",
|
|
2438
|
+
"get.js"
|
|
2436
2439
|
]
|
|
2437
2440
|
},
|
|
2438
|
-
"
|
|
2439
|
-
"aliases": [
|
|
2440
|
-
"team:list"
|
|
2441
|
-
],
|
|
2441
|
+
"users:links": {
|
|
2442
|
+
"aliases": [],
|
|
2442
2443
|
"args": {},
|
|
2443
|
-
"description": "Get
|
|
2444
|
+
"description": "Get a list of links that are used to invite users to your integration.",
|
|
2444
2445
|
"flags": {
|
|
2445
2446
|
"debug": {
|
|
2446
2447
|
"char": "d",
|
|
@@ -2474,7 +2475,7 @@
|
|
|
2474
2475
|
},
|
|
2475
2476
|
"hasDynamicHelp": false,
|
|
2476
2477
|
"hiddenAliases": [],
|
|
2477
|
-
"id": "
|
|
2478
|
+
"id": "users:links",
|
|
2478
2479
|
"pluginAlias": "zapier-platform-cli",
|
|
2479
2480
|
"pluginName": "zapier-platform-cli",
|
|
2480
2481
|
"pluginType": "core",
|
|
@@ -2486,17 +2487,30 @@
|
|
|
2486
2487
|
"src",
|
|
2487
2488
|
"oclif",
|
|
2488
2489
|
"commands",
|
|
2489
|
-
"
|
|
2490
|
-
"
|
|
2490
|
+
"users",
|
|
2491
|
+
"links.js"
|
|
2491
2492
|
]
|
|
2492
2493
|
},
|
|
2493
|
-
"
|
|
2494
|
+
"users:remove": {
|
|
2494
2495
|
"aliases": [
|
|
2495
|
-
"
|
|
2496
|
+
"users:delete"
|
|
2496
2497
|
],
|
|
2497
|
-
"args": {
|
|
2498
|
-
|
|
2498
|
+
"args": {
|
|
2499
|
+
"email": {
|
|
2500
|
+
"description": "The user to be removed.",
|
|
2501
|
+
"name": "email",
|
|
2502
|
+
"required": true
|
|
2503
|
+
}
|
|
2504
|
+
},
|
|
2505
|
+
"description": "Remove a user from all versions of your integration.\n\nWhen this command is run, their Zaps will immediately turn off. They won't be able to use your app again until they're re-invited or it has gone public. In practice, this command isn't run often as it's very disruptive to users.",
|
|
2499
2506
|
"flags": {
|
|
2507
|
+
"force": {
|
|
2508
|
+
"char": "f",
|
|
2509
|
+
"description": "Skips confirmation. Useful for running programatically.",
|
|
2510
|
+
"name": "force",
|
|
2511
|
+
"allowNo": false,
|
|
2512
|
+
"type": "boolean"
|
|
2513
|
+
},
|
|
2500
2514
|
"debug": {
|
|
2501
2515
|
"char": "d",
|
|
2502
2516
|
"description": "Show extra debugging output.",
|
|
@@ -2513,7 +2527,7 @@
|
|
|
2513
2527
|
},
|
|
2514
2528
|
"hasDynamicHelp": false,
|
|
2515
2529
|
"hiddenAliases": [],
|
|
2516
|
-
"id": "
|
|
2530
|
+
"id": "users:remove",
|
|
2517
2531
|
"pluginAlias": "zapier-platform-cli",
|
|
2518
2532
|
"pluginName": "zapier-platform-cli",
|
|
2519
2533
|
"pluginType": "core",
|
|
@@ -2525,10 +2539,10 @@
|
|
|
2525
2539
|
"src",
|
|
2526
2540
|
"oclif",
|
|
2527
2541
|
"commands",
|
|
2528
|
-
"
|
|
2542
|
+
"users",
|
|
2529
2543
|
"remove.js"
|
|
2530
2544
|
]
|
|
2531
2545
|
}
|
|
2532
2546
|
},
|
|
2533
|
-
"version": "17.
|
|
2547
|
+
"version": "17.7.1"
|
|
2534
2548
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zapier-platform-cli",
|
|
3
|
-
"version": "17.
|
|
3
|
+
"version": "17.7.1",
|
|
4
4
|
"description": "The CLI for managing integrations in Zapier Developer Platform.",
|
|
5
5
|
"repository": "zapier/zapier-platform",
|
|
6
6
|
"homepage": "https://platform.zapier.com/",
|
|
@@ -25,16 +25,16 @@
|
|
|
25
25
|
"docs": "ZAPIER_BASE_ENDPOINT='' node scripts/docs.js",
|
|
26
26
|
"preversion": "git pull && yarn validate",
|
|
27
27
|
"prepack": "oclif manifest",
|
|
28
|
-
"postpack": "
|
|
28
|
+
"postpack": "rimraf oclif.manifest.json",
|
|
29
29
|
"precommit": "yarn docs && git add docs",
|
|
30
30
|
"version": "yarn docs && git add docs/*",
|
|
31
31
|
"postversion": "git push && git push --tags",
|
|
32
32
|
"lint": "eslint src",
|
|
33
33
|
"lint:fix": "eslint --fix src",
|
|
34
|
-
"test": "cross-env NODE_ENV=test mocha -t
|
|
35
|
-
"test:debug": "cross-env NODE_ENV=test node inspect ../../node_modules/.bin/mocha -t
|
|
36
|
-
"smoke-test": "cross-env NODE_ENV=test mocha -t
|
|
37
|
-
"smoke-test:debug": "cross-env NODE_ENV=test node inspect ../../node_modules/.bin/mocha -t
|
|
34
|
+
"test": "cross-env NODE_ENV=test mocha -t 200s --recursive src/tests --exit",
|
|
35
|
+
"test:debug": "cross-env NODE_ENV=test node inspect ../../node_modules/.bin/mocha -t 200s --recursive src/tests --exit",
|
|
36
|
+
"smoke-test": "cross-env NODE_ENV=test mocha -t 6m --recursive src/smoke-tests --exit",
|
|
37
|
+
"smoke-test:debug": "cross-env NODE_ENV=test node inspect ../../node_modules/.bin/mocha -t 6m --recursive src/smoke-tests --exit",
|
|
38
38
|
"validate-templates": "./scripts/validate-app-templates.js",
|
|
39
39
|
"set-template-versions": "./scripts/set-app-template-versions.js",
|
|
40
40
|
"validate": "yarn test && yarn smoke-test && yarn lint"
|
|
@@ -46,12 +46,12 @@
|
|
|
46
46
|
"@oclif/plugin-not-found": "3.2.51",
|
|
47
47
|
"@oclif/plugin-version": "2.2.28",
|
|
48
48
|
"adm-zip": "0.5.16",
|
|
49
|
-
"decompress": "4.2.1",
|
|
50
49
|
"archiver": "7.0.1",
|
|
51
50
|
"chrono-node": "2.8.0",
|
|
52
51
|
"cli-table3": "0.6.5",
|
|
53
52
|
"colors": "1.4.0",
|
|
54
53
|
"debug": "4.4.0",
|
|
54
|
+
"decompress": "4.2.1",
|
|
55
55
|
"dotenv": "16.5.0",
|
|
56
56
|
"esbuild": "0.25.4",
|
|
57
57
|
"fs-extra": "11.2.0",
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"semver": "7.7.1",
|
|
74
74
|
"string-length": "4.0.2",
|
|
75
75
|
"through2": "4.0.2",
|
|
76
|
-
"tmp": "0.2.
|
|
76
|
+
"tmp": "0.2.4",
|
|
77
77
|
"traverse": "0.6.11",
|
|
78
78
|
"update-notifier": "5.1.0",
|
|
79
79
|
"yeoman-environment": "3.19.3",
|
|
@@ -87,6 +87,7 @@
|
|
|
87
87
|
"mock-fs": "^5.5.0",
|
|
88
88
|
"nock": "^14.0.4",
|
|
89
89
|
"oclif": "^4.17.46",
|
|
90
|
+
"rimraf": "^5.0.10",
|
|
90
91
|
"typescript": "^5.8.3",
|
|
91
92
|
"yamljs": "0.3.0"
|
|
92
93
|
},
|
package/src/generators/index.js
CHANGED
|
@@ -79,6 +79,7 @@ const writeGenericTypeScriptPackageJson = (gen, packageJsonExtension) => {
|
|
|
79
79
|
test: 'npm run build && vitest --run',
|
|
80
80
|
clean: 'rimraf ./dist ./build',
|
|
81
81
|
build: 'npm run clean && tsc',
|
|
82
|
+
dev: 'npm run build -- --watch',
|
|
82
83
|
'_zapier-build': 'npm run build',
|
|
83
84
|
},
|
|
84
85
|
dependencies: {
|
|
@@ -252,13 +253,26 @@ class ProjectGenerator extends Generator {
|
|
|
252
253
|
|
|
253
254
|
async prompting() {
|
|
254
255
|
if (!this.options.template) {
|
|
256
|
+
// Filter template choices based on language and module type
|
|
257
|
+
let templateChoices = TEMPLATE_CHOICES;
|
|
258
|
+
let defaultTemplate = 'minimal';
|
|
259
|
+
|
|
260
|
+
// TypeScript filtering takes precedence over ESM filtering
|
|
261
|
+
if (this.options.language === 'typescript') {
|
|
262
|
+
templateChoices = TS_SUPPORTED_TEMPLATES;
|
|
263
|
+
defaultTemplate = 'basic-auth';
|
|
264
|
+
} else if (this.options.module === 'esm') {
|
|
265
|
+
templateChoices = ESM_SUPPORTED_TEMPLATES;
|
|
266
|
+
defaultTemplate = 'minimal'; // minimal is the only ESM template
|
|
267
|
+
}
|
|
268
|
+
|
|
255
269
|
this.answers = await this.prompt([
|
|
256
270
|
{
|
|
257
271
|
type: 'list',
|
|
258
272
|
name: 'template',
|
|
259
|
-
choices:
|
|
273
|
+
choices: templateChoices,
|
|
260
274
|
message: 'Choose a project template to start with:',
|
|
261
|
-
default:
|
|
275
|
+
default: defaultTemplate,
|
|
262
276
|
},
|
|
263
277
|
]);
|
|
264
278
|
this.options.template = this.answers.template;
|
|
@@ -320,6 +334,8 @@ class ProjectGenerator extends Generator {
|
|
|
320
334
|
|
|
321
335
|
module.exports = {
|
|
322
336
|
TEMPLATE_CHOICES,
|
|
337
|
+
ESM_SUPPORTED_TEMPLATES,
|
|
338
|
+
TS_SUPPORTED_TEMPLATES,
|
|
323
339
|
PullGenerator,
|
|
324
340
|
ProjectGenerator,
|
|
325
341
|
};
|
|
@@ -90,9 +90,14 @@ class ZapierBaseCommand extends Command {
|
|
|
90
90
|
|
|
91
91
|
// validate that user input looks like a semver version
|
|
92
92
|
throwForInvalidVersion(version) {
|
|
93
|
-
if (
|
|
93
|
+
if (
|
|
94
|
+
!version.match(
|
|
95
|
+
// this is mirrored in schemas/VersionSchema.js and developer_cli/constants.py
|
|
96
|
+
/^(?:0|[1-9]\d{0,2})\.(?:0|[1-9]\d{0,2})\.(?:0|[1-9]\d{0,2})(?:-(?=.{1,12}$)[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)?$/g,
|
|
97
|
+
)
|
|
98
|
+
) {
|
|
94
99
|
throw new Error(
|
|
95
|
-
`${version} is an invalid version str. Try something like \`1.2.3\``,
|
|
100
|
+
`${version} is an invalid version str. Try something like \`1.2.3\` or \`0.0.0-TICKET\``,
|
|
96
101
|
);
|
|
97
102
|
}
|
|
98
103
|
}
|
|
@@ -59,7 +59,14 @@ const loadAuthDataFromEnv = () => {
|
|
|
59
59
|
.filter(([k, v]) => k.startsWith(AUTH_FIELD_ENV_PREFIX))
|
|
60
60
|
.reduce((authData, [k, v]) => {
|
|
61
61
|
const fieldKey = k.substr(AUTH_FIELD_ENV_PREFIX.length);
|
|
62
|
-
|
|
62
|
+
// Try to parse as JSON if it looks like JSON, otherwise keep as string
|
|
63
|
+
try {
|
|
64
|
+
authData[fieldKey] =
|
|
65
|
+
v.startsWith('{') || v.startsWith('[') ? JSON.parse(v) : v;
|
|
66
|
+
} catch (e) {
|
|
67
|
+
// If JSON parsing fails, keep as string
|
|
68
|
+
authData[fieldKey] = v;
|
|
69
|
+
}
|
|
63
70
|
return authData;
|
|
64
71
|
}, {});
|
|
65
72
|
};
|
|
@@ -233,12 +240,26 @@ const resolveInputDataTypes = (inputData, inputFields, timezone) => {
|
|
|
233
240
|
};
|
|
234
241
|
|
|
235
242
|
const appendEnv = async (vars, prefix = '') => {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
243
|
+
const envFile = '.env';
|
|
244
|
+
let content = Object.entries(vars)
|
|
245
|
+
.filter(([k, v]) => v !== undefined)
|
|
246
|
+
.map(
|
|
247
|
+
([k, v]) =>
|
|
248
|
+
`${prefix}${k}='${typeof v === 'object' && v !== null ? JSON.stringify(v) : v || ''}'\n`,
|
|
249
|
+
)
|
|
250
|
+
.join('');
|
|
251
|
+
|
|
252
|
+
// Check if .env file exists and doesn't end with newline
|
|
253
|
+
try {
|
|
254
|
+
const existingContent = await fs.readFile(envFile, 'utf8');
|
|
255
|
+
if (existingContent.length > 0 && !existingContent.endsWith('\n')) {
|
|
256
|
+
content = '\n' + content;
|
|
257
|
+
}
|
|
258
|
+
} catch (error) {
|
|
259
|
+
// File doesn't exist or can't be read, proceed as normal
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
await fs.appendFile(envFile, content);
|
|
242
263
|
};
|
|
243
264
|
|
|
244
265
|
const replaceDoubleCurlies = async (request) => {
|
|
@@ -1303,6 +1324,7 @@ class InvokeCommand extends BaseCommand {
|
|
|
1303
1324
|
isPopulatingDedupe: this.flags.isPopulatingDedupe,
|
|
1304
1325
|
limit: this.flags.limit,
|
|
1305
1326
|
page: this.flags.page,
|
|
1327
|
+
paging_token: this.flags['paging-token'],
|
|
1306
1328
|
isTestingAuth: false, // legacy property
|
|
1307
1329
|
};
|
|
1308
1330
|
const output = await this.invokeAction(
|
|
@@ -1382,6 +1404,10 @@ InvokeCommand.flags = buildFlags({
|
|
|
1382
1404
|
description:
|
|
1383
1405
|
'EXPERIMENTAL: Instead of using the local .env file, use the production authentication data with the given authentication ID (aka the "app connection" on Zapier). Find them at https://zapier.com/app/assets/connections (https://zpr.io/z8SjFTdnTFZ2 for instructions) or specify \'-\' to interactively select one from your available authentications. When specified, the code will still run locally, but all outgoing requests will be proxied through Zapier with the production auth data.',
|
|
1384
1406
|
}),
|
|
1407
|
+
'paging-token': Flags.string({
|
|
1408
|
+
description:
|
|
1409
|
+
'Set bundle.meta.paging_token. Used for search pagination or bulk reads. When used in production, this indicates which page of items you should fetch.',
|
|
1410
|
+
}),
|
|
1385
1411
|
},
|
|
1386
1412
|
});
|
|
1387
1413
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const _ = require('lodash');
|
|
2
2
|
const debug = require('debug')('zapier:migrate');
|
|
3
3
|
const { Args, Flags } = require('@oclif/core');
|
|
4
|
+
const colors = require('colors/safe');
|
|
4
5
|
|
|
5
6
|
const BaseCommand = require('../ZapierBaseCommand');
|
|
6
7
|
const PromoteCommand = require('./promote');
|
|
@@ -118,17 +119,15 @@ class MigrateCommand extends BaseCommand {
|
|
|
118
119
|
|
|
119
120
|
await this.run_require_confirmation_pre_checks(app, body);
|
|
120
121
|
|
|
122
|
+
let message;
|
|
121
123
|
if (user || account) {
|
|
122
|
-
|
|
123
|
-
`Starting migration from ${fromVersion} to ${toVersion} for ${
|
|
124
|
-
user || account
|
|
125
|
-
}`,
|
|
126
|
-
);
|
|
124
|
+
message = `Requesting migration from ${fromVersion} to ${toVersion} for ${user || account}`;
|
|
127
125
|
} else {
|
|
128
|
-
|
|
129
|
-
`Starting migration from ${fromVersion} to ${toVersion} for ${percent}%`,
|
|
130
|
-
);
|
|
126
|
+
message = `Requesting migration from ${fromVersion} to ${toVersion} for ${percent}%`;
|
|
131
127
|
}
|
|
128
|
+
|
|
129
|
+
this.startSpinner(message);
|
|
130
|
+
|
|
132
131
|
if (percent) {
|
|
133
132
|
body.job.percent_human = percent;
|
|
134
133
|
}
|
|
@@ -137,12 +136,14 @@ class MigrateCommand extends BaseCommand {
|
|
|
137
136
|
|
|
138
137
|
try {
|
|
139
138
|
await callAPI(url, { method: 'POST', body });
|
|
140
|
-
}
|
|
141
|
-
this.stopSpinner();
|
|
139
|
+
} catch (err) {
|
|
140
|
+
this.stopSpinner({ success: false });
|
|
141
|
+
throw err;
|
|
142
142
|
}
|
|
143
|
+
this.stopSpinner();
|
|
143
144
|
|
|
144
145
|
this.log(
|
|
145
|
-
|
|
146
|
+
`\nMigration successfully queued, check ${colors.bold.underline('zapier jobs')} to track the status. Migrations usually take between 5-10 minutes.`,
|
|
146
147
|
);
|
|
147
148
|
}
|
|
148
149
|
}
|
|
@@ -6,10 +6,18 @@ const yeoman = require('yeoman-environment');
|
|
|
6
6
|
const ZapierBaseCommand = require('../ZapierBaseCommand');
|
|
7
7
|
const { downloadSourceZip } = require('../../utils/api');
|
|
8
8
|
const { ensureDir, makeTempDir, removeDirSync } = require('../../utils/files');
|
|
9
|
-
const {
|
|
9
|
+
const { walkDirWithPresetBlocklist } = require('../../utils/build');
|
|
10
10
|
const { buildFlags } = require('../buildFlags');
|
|
11
11
|
const PullGenerator = require('../../generators/pull');
|
|
12
12
|
|
|
13
|
+
const listFiles = (dir) => {
|
|
14
|
+
const relPaths = [];
|
|
15
|
+
for (const entry of walkDirWithPresetBlocklist(dir)) {
|
|
16
|
+
relPaths.push(path.join(path.relative(dir, entry.parentPath), entry.name));
|
|
17
|
+
}
|
|
18
|
+
return relPaths;
|
|
19
|
+
};
|
|
20
|
+
|
|
13
21
|
class PullCommand extends ZapierBaseCommand {
|
|
14
22
|
async perform() {
|
|
15
23
|
// Fetch the source zip from API
|
|
@@ -28,7 +36,7 @@ class PullCommand extends ZapierBaseCommand {
|
|
|
28
36
|
|
|
29
37
|
// Prompt user to confirm overwrite
|
|
30
38
|
const currentDir = process.cwd();
|
|
31
|
-
const sourceFiles =
|
|
39
|
+
const sourceFiles = listFiles(srcDst);
|
|
32
40
|
|
|
33
41
|
const env = yeoman.createEnv();
|
|
34
42
|
const namespace = 'zapier:pull';
|
|
@@ -45,9 +53,9 @@ class PullCommand extends ZapierBaseCommand {
|
|
|
45
53
|
}
|
|
46
54
|
|
|
47
55
|
PullCommand.flags = buildFlags();
|
|
48
|
-
PullCommand.description = `Retrieve and update your local integration files with the latest version.
|
|
56
|
+
PullCommand.description = `Retrieve and update your local integration files with the promoted version (or latest version if not public).
|
|
49
57
|
|
|
50
|
-
This command updates your local integration files with the latest version. You will be prompted with a confirmation dialog before continuing if there any destructive file changes.
|
|
58
|
+
This command updates your local integration files with the promoted version (or latest version if not public). You will be prompted with a confirmation dialog before continuing if there any destructive file changes.
|
|
51
59
|
|
|
52
60
|
Zapier may release new versions of your integration with bug fixes or new features. In the event this occurs, you will be unable to do the following until your local files are updated by running \`zapier pull\`:
|
|
53
61
|
|
|
@@ -6,9 +6,14 @@ const { buildFlags } = require('../buildFlags');
|
|
|
6
6
|
const { flattenCheckResult } = require('../../utils/display');
|
|
7
7
|
const { localAppCommand } = require('../../utils/local');
|
|
8
8
|
const { validateApp } = require('../../utils/api');
|
|
9
|
+
const { maybeRunBuildScript } = require('../../utils/build');
|
|
9
10
|
|
|
10
11
|
class ValidateCommand extends BaseCommand {
|
|
11
12
|
async perform() {
|
|
13
|
+
if (!this.flags['skip-build']) {
|
|
14
|
+
await maybeRunBuildScript({ printProgress: true });
|
|
15
|
+
}
|
|
16
|
+
|
|
12
17
|
this.log('Validating project locally');
|
|
13
18
|
|
|
14
19
|
const errors = await localAppCommand({ command: 'validate' });
|
|
@@ -121,6 +126,9 @@ ValidateCommand.flags = buildFlags({
|
|
|
121
126
|
'without-style': Flags.boolean({
|
|
122
127
|
description: 'Forgo pinging the Zapier server to run further checks.',
|
|
123
128
|
}),
|
|
129
|
+
'skip-build': Flags.boolean({
|
|
130
|
+
description: 'Skip running the _zapier-build script before validation.',
|
|
131
|
+
}),
|
|
124
132
|
},
|
|
125
133
|
opts: {
|
|
126
134
|
format: true,
|
|
@@ -130,6 +138,7 @@ ValidateCommand.flags = buildFlags({
|
|
|
130
138
|
ValidateCommand.examples = [
|
|
131
139
|
'zapier validate',
|
|
132
140
|
'zapier validate --without-style',
|
|
141
|
+
'zapier validate --skip-build',
|
|
133
142
|
'zapier validate --format json',
|
|
134
143
|
];
|
|
135
144
|
ValidateCommand.description = `Validate your integration.
|
package/src/utils/analytics.js
CHANGED
|
@@ -51,7 +51,7 @@ const recordAnalytics = async (command, isValidCommand, args, flags) => {
|
|
|
51
51
|
numArgs: argKeys.length,
|
|
52
52
|
appId: linkedAppId,
|
|
53
53
|
argsKeys: argKeys,
|
|
54
|
-
flagKeys
|
|
54
|
+
flagKeys,
|
|
55
55
|
cliVersion: pkg.version,
|
|
56
56
|
os: shouldRecordAnonymously ? undefined : process.platform,
|
|
57
57
|
};
|
package/src/utils/ast.js
CHANGED
|
@@ -115,17 +115,23 @@ const registerActionInJsApp = (codeStr, property, varName) => {
|
|
|
115
115
|
|
|
116
116
|
// check if this object already has the property at the top level
|
|
117
117
|
const existingProp = objToModify.properties.find(
|
|
118
|
-
(props) => props.key.name === property,
|
|
118
|
+
(props) => props.key && props.key.name === property,
|
|
119
119
|
);
|
|
120
120
|
if (existingProp) {
|
|
121
|
-
// `triggers: myTriggers` means we shouldn't bother
|
|
122
121
|
const value = existingProp.value;
|
|
123
|
-
if (value.type
|
|
122
|
+
if (value.type === 'Identifier') {
|
|
123
|
+
// Handle shorthand syntax like `creates` instead of `creates: { ... }`
|
|
124
|
+
// Transform it into an object with spread operator: `creates: { ...creates, [newAction.key]: newAction }`
|
|
125
|
+
const spreadProperty = j.spreadElement(j.identifier(value.name));
|
|
126
|
+
existingProp.value = j.objectExpression([spreadProperty, newProperty]);
|
|
127
|
+
existingProp.shorthand = false; // Disable shorthand since we're changing the value
|
|
128
|
+
} else if (value.type === 'ObjectExpression') {
|
|
129
|
+
value.properties.push(newProperty);
|
|
130
|
+
} else {
|
|
124
131
|
throw new Error(
|
|
125
132
|
`Tried to edit the ${property} key, but the value wasn't an object`,
|
|
126
133
|
);
|
|
127
134
|
}
|
|
128
|
-
value.properties.push(newProperty);
|
|
129
135
|
} else {
|
|
130
136
|
objToModify.properties.push(
|
|
131
137
|
j.property(
|
|
@@ -209,16 +215,23 @@ const registerActionInTsApp = (codeStr, actionTypePlural, identifierName) => {
|
|
|
209
215
|
|
|
210
216
|
// Check if this object already has the actionType group inside it.
|
|
211
217
|
const existingProp = appObj.properties.find(
|
|
212
|
-
(props) => props.key.name === actionTypePlural,
|
|
218
|
+
(props) => props.key && props.key.name === actionTypePlural,
|
|
213
219
|
);
|
|
214
220
|
if (existingProp) {
|
|
215
221
|
const value = existingProp.value;
|
|
216
|
-
if (value.type
|
|
222
|
+
if (value.type === 'Identifier') {
|
|
223
|
+
// Handle shorthand syntax like `creates` instead of `creates: { ... }`
|
|
224
|
+
// Transform it into an object with spread operator: `creates: { ...creates, [newAction.key]: newAction }`
|
|
225
|
+
const spreadProperty = j.spreadElement(j.identifier(value.name));
|
|
226
|
+
existingProp.value = j.objectExpression([spreadProperty, newProperty]);
|
|
227
|
+
existingProp.shorthand = false; // Disable shorthand since we're changing the value
|
|
228
|
+
} else if (value.type === 'ObjectExpression') {
|
|
229
|
+
value.properties.push(newProperty);
|
|
230
|
+
} else {
|
|
217
231
|
throw new Error(
|
|
218
232
|
`Tried to edit the ${actionTypePlural} key, but the value wasn't an object`,
|
|
219
233
|
);
|
|
220
234
|
}
|
|
221
|
-
value.properties.push(newProperty);
|
|
222
235
|
} else {
|
|
223
236
|
appObj.properties.push(
|
|
224
237
|
j.property(
|
package/src/utils/build.js
CHANGED
|
@@ -272,13 +272,28 @@ const countLeadingDoubleDots = (relPath) => {
|
|
|
272
272
|
// Join all relPaths with workingDir and return the common ancestor directory.
|
|
273
273
|
const findCommonAncestor = (workingDir, relPaths) => {
|
|
274
274
|
let maxLeadingDoubleDots = 0;
|
|
275
|
-
for (const relPath of relPaths) {
|
|
276
|
-
maxLeadingDoubleDots = Math.max(
|
|
277
|
-
maxLeadingDoubleDots,
|
|
278
|
-
countLeadingDoubleDots(relPath),
|
|
279
|
-
);
|
|
280
|
-
}
|
|
281
275
|
|
|
276
|
+
if (isWindows()) {
|
|
277
|
+
for (const relPath of relPaths) {
|
|
278
|
+
if (relPath.match(/^[a-zA-Z]:/)) {
|
|
279
|
+
// On Windows, relPath can be absolute if it starts with a different
|
|
280
|
+
// drive letter than workingDir.
|
|
281
|
+
return 'C:\\';
|
|
282
|
+
} else {
|
|
283
|
+
maxLeadingDoubleDots = Math.max(
|
|
284
|
+
maxLeadingDoubleDots,
|
|
285
|
+
countLeadingDoubleDots(relPath),
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
} else {
|
|
290
|
+
for (const relPath of relPaths) {
|
|
291
|
+
maxLeadingDoubleDots = Math.max(
|
|
292
|
+
maxLeadingDoubleDots,
|
|
293
|
+
countLeadingDoubleDots(relPath),
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
282
297
|
let commonAncestor = workingDir;
|
|
283
298
|
for (let i = 0; i < maxLeadingDoubleDots; i++) {
|
|
284
299
|
commonAncestor = path.dirname(commonAncestor);
|
|
@@ -286,6 +301,10 @@ const findCommonAncestor = (workingDir, relPaths) => {
|
|
|
286
301
|
return commonAncestor;
|
|
287
302
|
};
|
|
288
303
|
|
|
304
|
+
const stripDriveLetterForZip = (pathStr) => {
|
|
305
|
+
return pathStr.replace(/^[cC]:\\/, '').replace(/^([a-zA-Z]):/, '$1');
|
|
306
|
+
};
|
|
307
|
+
|
|
289
308
|
const writeBuildZipDumbly = async (workingDir, zip) => {
|
|
290
309
|
for (const entry of walkDirWithPresetBlocklist(workingDir)) {
|
|
291
310
|
const absPath = path.resolve(entry.parentPath, entry.name);
|
|
@@ -350,7 +369,7 @@ const writeBuildZipSmartly = async (workingDir, zip) => {
|
|
|
350
369
|
// Write required files to the zip
|
|
351
370
|
for (const relPath of relPaths) {
|
|
352
371
|
const absPath = path.resolve(workingDir, relPath);
|
|
353
|
-
const nameInZip = path.relative(zipRoot, absPath);
|
|
372
|
+
const nameInZip = stripDriveLetterForZip(path.relative(zipRoot, absPath));
|
|
354
373
|
if (nameInZip === 'package.json' && zipRoot !== workingDir) {
|
|
355
374
|
// Ignore workspace root's package.json
|
|
356
375
|
continue;
|
|
@@ -388,10 +407,10 @@ const writeBuildZipSmartly = async (workingDir, zip) => {
|
|
|
388
407
|
symlink.parentPath,
|
|
389
408
|
symlink.name,
|
|
390
409
|
);
|
|
391
|
-
const nameInZip = path.relative(zipRoot, absPath);
|
|
410
|
+
const nameInZip = stripDriveLetterForZip(path.relative(zipRoot, absPath));
|
|
392
411
|
const targetInZip = path.relative(
|
|
393
|
-
symlink.parentPath,
|
|
394
|
-
fs.realpathSync(absPath),
|
|
412
|
+
stripDriveLetterForZip(symlink.parentPath),
|
|
413
|
+
stripDriveLetterForZip(fs.realpathSync(absPath)),
|
|
395
414
|
);
|
|
396
415
|
zip.symlink(nameInZip, targetInZip, 0o644);
|
|
397
416
|
}
|
package/src/utils/scaffold.js
CHANGED
|
@@ -126,6 +126,16 @@ const writeTemplateFile = async ({
|
|
|
126
126
|
const getRelativeRequirePath = (entryFilePath, newFilePath) =>
|
|
127
127
|
path.relative(path.dirname(entryFilePath), newFilePath);
|
|
128
128
|
|
|
129
|
+
/**
|
|
130
|
+
* Detect if a JavaScript file uses ES Module syntax (export default) vs CommonJS (module.exports)
|
|
131
|
+
* @param {string} codeStr - The JavaScript code to check
|
|
132
|
+
* @returns {boolean} - True if the file uses ESM syntax
|
|
133
|
+
*/
|
|
134
|
+
const isEsmJavaScript = (codeStr) => {
|
|
135
|
+
// Look for export default statement
|
|
136
|
+
return /^\s*export\s+default\s/m.test(codeStr);
|
|
137
|
+
};
|
|
138
|
+
|
|
129
139
|
const isValidEntryFileUpdate = (
|
|
130
140
|
language,
|
|
131
141
|
indexFileResolved,
|
|
@@ -193,16 +203,32 @@ const updateEntryFileJs = async ({
|
|
|
193
203
|
let codeStr = (await readFile(indexFileResolved)).toString();
|
|
194
204
|
const originalCodeStr = codeStr; // untouched copy in case we need to bail
|
|
195
205
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
+
// Check if this JavaScript file uses ESM syntax (export default)
|
|
207
|
+
// If so, use the TypeScript functions which handle ESM correctly
|
|
208
|
+
if (isEsmJavaScript(codeStr)) {
|
|
209
|
+
codeStr = importActionInTsApp(
|
|
210
|
+
codeStr,
|
|
211
|
+
actionImportName,
|
|
212
|
+
actionRelativeImportPath,
|
|
213
|
+
);
|
|
214
|
+
codeStr = registerActionInTsApp(
|
|
215
|
+
codeStr,
|
|
216
|
+
plural(actionType),
|
|
217
|
+
actionImportName,
|
|
218
|
+
);
|
|
219
|
+
} else {
|
|
220
|
+
// Use traditional CommonJS functions for module.exports
|
|
221
|
+
codeStr = importActionInJsApp(
|
|
222
|
+
codeStr,
|
|
223
|
+
actionImportName,
|
|
224
|
+
actionRelativeImportPath,
|
|
225
|
+
);
|
|
226
|
+
codeStr = registerActionInJsApp(
|
|
227
|
+
codeStr,
|
|
228
|
+
plural(actionType),
|
|
229
|
+
actionImportName,
|
|
230
|
+
);
|
|
231
|
+
}
|
|
206
232
|
await writeFile(indexFileResolved, codeStr);
|
|
207
233
|
return originalCodeStr;
|
|
208
234
|
};
|
|
@@ -283,11 +309,22 @@ const createScaffoldingContext = ({
|
|
|
283
309
|
)}.test.${language}`;
|
|
284
310
|
const testFileLocal = `${path.join(testDirLocal, key)}.${language}`;
|
|
285
311
|
const testFileLocalStem = path.join(testDirLocal, key);
|
|
286
|
-
|
|
312
|
+
|
|
313
|
+
// Generate the relative import path
|
|
314
|
+
let actionRelativeImportPath = `./${getRelativeRequirePath(
|
|
287
315
|
indexFileResolved,
|
|
288
316
|
actionFileResolvedStem,
|
|
289
317
|
)}`;
|
|
290
318
|
|
|
319
|
+
// Normalize path separators to forward slashes for import statements
|
|
320
|
+
// (ES modules always use forward slashes, regardless of OS)
|
|
321
|
+
actionRelativeImportPath = actionRelativeImportPath.replace(/\\/g, '/');
|
|
322
|
+
|
|
323
|
+
// For TypeScript with ESM, imports must use .js extension
|
|
324
|
+
if (language === 'ts') {
|
|
325
|
+
actionRelativeImportPath += '.js';
|
|
326
|
+
}
|
|
327
|
+
|
|
291
328
|
return {
|
|
292
329
|
actionType,
|
|
293
330
|
actionTypePlural: plural(actionType),
|
|
@@ -324,6 +361,7 @@ module.exports = {
|
|
|
324
361
|
updateEntryFile,
|
|
325
362
|
isValidEntryFileUpdate,
|
|
326
363
|
writeTemplateFile,
|
|
364
|
+
isEsmJavaScript,
|
|
327
365
|
};
|
|
328
366
|
|
|
329
367
|
/**
|