/
PostmanImporter.coffee
273 lines (218 loc) · 10.4 KB
/
PostmanImporter.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
POSTMAN_ENVIRONMENT_DOMAIN_NAME = 'Postman Environments'
PostmanImporter = ->
# Create Paw requests from a Postman Request (object)
@createPawRequest = (context, postmanRequestsById, postmanRequestId) ->
# Get Request
postmanRequest = postmanRequestsById[postmanRequestId]
if not postmanRequest
console.log "Corrupted Postman file, no request found for ID: #{ postmanRequestId }"
return null
# Create Paw request
pawRequest = context.createRequest postmanRequest["name"], postmanRequest["method"], @expandEnvironmentVariables(context, postmanRequest["url"])
# Add Headers
# Postman stores headers like HTTP headers, separated by \n
postmanHeaders = postmanRequest["headers"].split "\n"
for headerLine in postmanHeaders
match = headerLine.match /^([^\s\:]*)\s*\:\s*(.*)$/
if match
pawRequest.setHeader @expandEnvironmentVariables(context, match[1]), @expandEnvironmentVariables(context, match[2])
# Set raw body
if postmanRequest["dataMode"] == "raw"
contentType = pawRequest.getHeaderByName "Content-Type"
rawRequestBody = postmanRequest["rawModeData"]
foundBody = false;
# If the Content-Type contains "json" make it a JSON body
if contentType and contentType.indexOf("json") >= 0 and rawRequestBody and rawRequestBody.length > 0
# try to parse JSON body input
try
jsonObject = JSON.parse rawRequestBody
catch error
console.log "Cannot parse Request JSON: #{ postmanRequest["name"] } (ID: #{ postmanRequestId })"
# set the JSON body
if jsonObject
pawRequest.body = @expandEnvironmentVariables context, rawRequestBody
foundBody = true
if not foundBody
if typeof rawRequestBody isnt 'undefined'
pawRequest.body = @expandEnvironmentVariables context, rawRequestBody
# Set Form URL-Encoded body
else if postmanRequest["dataMode"] == "urlencoded" and postmanRequest["data"] != null
postmanBodyData = postmanRequest["data"]
bodyObject = new Object()
for bodyItem in postmanBodyData
# Note: it sounds like all data fields are "text" type
# when in "urlencoded" data mode.
if bodyItem["type"] == "text"
bodyObject[bodyItem["key"]] = @expandEnvironmentVariables context, bodyItem["value"]
pawRequest.urlEncodedBody = bodyObject;
# Set Multipart body
else if postmanRequest["dataMode"] == "params" and postmanRequest["data"] != null
postmanBodyData = postmanRequest["data"]
bodyObject = new Object()
for bodyItem in postmanBodyData
# Note: due to Apple Sandbox limitations, we cannot import
# "file" type items
if bodyItem["type"] == "text"
bodyObject[bodyItem["key"]] = @expandEnvironmentVariables context, bodyItem["value"]
pawRequest.multipartBody = bodyObject
return pawRequest
@expandEnvironmentVariables = (context, string) ->
if string == null
string = ''
rx = /\{\{([^\n\}]+)\}\}/g;
items = string.split(rx)
if items.length < 2
return string
for i in [1...items.length] by 2
envVariable = @getEnvironmentVariable context, items[i]
varID = envVariable.id
dynamicValue = new DynamicValue "com.luckymarmot.EnvironmentVariableDynamicValue", {environmentVariable: varID}
items[i] = dynamicValue
return new DynamicString items...
@createPawGroup = (context, postmanRequestsById, postmanFolder) ->
# Create Paw group
pawGroup = context.createRequestGroup postmanFolder["name"]
# Iterate on requests in group
if postmanFolder["order"]
for postmanRequestId in postmanFolder["order"]
# Create a Paw request
pawRequest = @createPawRequest context, postmanRequestsById, postmanRequestId
# Add request to parent group
if pawRequest
pawGroup.appendChild pawRequest
return pawGroup
@importCollection = (context, postmanCollection) ->
# Check Postman data
if not postmanCollection || not postmanCollection["requests"]
throw new Error "Invalid Postman file (missing data)"
# Build Postman request dictionary (by id)
postmanRequestsById = new Object()
for postmanRequest in postmanCollection["requests"]
postmanRequestsById[postmanRequest["id"]] = postmanRequest
# Create a Paw Group
pawRootGroup = context.createRequestGroup postmanCollection["name"]
# If we have either "folders" or "order"
if postmanCollection["folders"]? || postmanCollection["order"]?
# Add Postman folders
if postmanCollection["folders"]?
for postmanFolder in postmanCollection["folders"]
pawGroup = @createPawGroup context, postmanRequestsById, postmanFolder
# Add group to root
pawRootGroup.appendChild pawGroup
# Add Postman requests in root
if postmanCollection["order"]?
for postmanRequestId in postmanCollection["order"]
# Create a Paw request
pawRequest = @createPawRequest context, postmanRequestsById, postmanRequestId
# Add request to root group
pawRootGroup.appendChild pawRequest
# If the collection does not have "folders" or "order"
# add all requests in root
else
for postmanRequestId, postmanRequest of postmanRequestsById
# Create a Paw request
pawRequest = @createPawRequest context, postmanRequestsById, postmanRequestId
# Add request to root group
pawRootGroup.appendChild pawRequest
@getEnvironmentDomain = (context) ->
env = context.getEnvironmentDomainByName(POSTMAN_ENVIRONMENT_DOMAIN_NAME)
if typeof env is 'undefined'
env = context.createEnvironmentDomain(POSTMAN_ENVIRONMENT_DOMAIN_NAME)
return env
@getEnvironment = (environmentDomain) ->
env = environmentDomain.getEnvironmentByName('Default Environment')
if typeof env is 'undefined'
env = environmentDomain.createEnvironment('Default Environment')
return env
@getEnvironmentVariable = (context, name) ->
envD = @getEnvironmentDomain context
variable = envD.getVariableByName(name)
if typeof variable is 'undefined'
env = @getEnvironment(envD)
varD = {}
varD[name] = ''
env.setVariablesValues(varD)
variable = envD.getVariableByName(name)
return variable
@canImport = (context, items) ->
a = 0
b = 0
for item in items
a += @_canImportItem(context, item)
b += 1
return if b > 0 then a/b else 0
@_canImportItem = (context, item) ->
# Parse JSON
try
obj = JSON.parse(item.content)
catch error
return 0
# That's a Postman dump
if obj and obj.collections? and obj.environments? and obj.globals? and obj.version?
return 1
# That's a Postman request or collection export
if obj and (obj.collections? or obj.requests?) and obj.order? and obj.name? and obj.id?
return 1
# That's a Postman environment export
if obj and obj.values? and obj.name? and obj.id?
return 1
return 0
@importString = (context, str) ->
return @import(context, [ { content: str } ])
@import = (context, items) ->
collections = []
environments = []
for item in items
# Parse JSON
try
obj = JSON.parse(item.content)
catch error
throw new Error "Invalid Postman file (not a valid JSON)"
# Dump file
if obj.collections? and obj.environments?
for collection in obj.collections
collections.push(collection)
for environment in obj.environments
environments.push(environment)
# Collection file
if obj.collections? or obj.requests?
collections.push(obj)
# Environments file
else if obj and obj.values? and obj.name?
environments.push(obj)
else
throw new Error "Invalid Postman file (missing required keys)"
# import environments, so binding can occur later on collection import
for obj in environments
@_importEnvironmentsFile(context, obj)
# import collections after, hope that variables will be bound to
# imported environment variables
for obj in collections
@_importCollectionFile(context, obj)
return true
@_importCollectionFile = (context, obj) ->
# import a list of collections
if obj.collections
for postmanCollection in obj.collections
@importCollection(context, postmanCollection)
# import a single collection
else
@importCollection(context, obj)
return true
@_importEnvironmentsFile = (context, obj) ->
# Get or create the environment domain
pawEnvironmentDomainName = POSTMAN_ENVIRONMENT_DOMAIN_NAME
pawEnvironmentDomain = context.getEnvironmentDomainByName(pawEnvironmentDomainName)
if not pawEnvironmentDomain
pawEnvironmentDomain = context.createEnvironmentDomain(pawEnvironmentDomainName)
# Create a new environment
pawEnvironment = pawEnvironmentDomain.createEnvironment(obj.name)
variablesDict = {}
for postmanValue in obj.values
variablesDict[postmanValue.key] = postmanValue.value
pawEnvironment.setVariablesValues(variablesDict)
return true;
return
PostmanImporter.identifier = "com.luckymarmot.PawExtensions.PostmanImporter"
PostmanImporter.title = "Postman Importer"
registerImporter PostmanImporter