noms-command 0.5.0 → 2.1.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.
- checksums.yaml +4 -4
- data/README.rst +104 -37
- data/TODO.rst +3 -3
- data/fixture/dnc.rb +110 -1
- data/fixture/public/dnc.json +6 -5
- data/fixture/public/lib/dnc.js +171 -24
- data/fixture/public/lib/nomsargs.js +72 -0
- data/lib/noms/command.rb +37 -8
- data/lib/noms/command/application.rb +32 -26
- data/lib/noms/command/auth.rb +44 -62
- data/lib/noms/command/auth/identity.rb +205 -5
- data/lib/noms/command/base.rb +11 -1
- data/lib/noms/command/formatter.rb +5 -4
- data/lib/noms/command/home.rb +21 -0
- data/lib/noms/command/useragent.rb +117 -40
- data/lib/noms/command/useragent/cache.rb +124 -0
- data/lib/noms/command/useragent/requester.rb +48 -0
- data/lib/noms/command/useragent/requester/httpclient.rb +61 -0
- data/lib/noms/command/useragent/requester/typhoeus.rb +73 -0
- data/lib/noms/command/useragent/response.rb +202 -0
- data/lib/noms/command/useragent/response/httpclient.rb +59 -0
- data/lib/noms/command/useragent/response/typhoeus.rb +74 -0
- data/lib/noms/command/version.rb +1 -1
- data/lib/noms/command/window.rb +21 -3
- data/lib/noms/command/xmlhttprequest.rb +8 -8
- data/noms-command.gemspec +3 -1
- data/spec/07js_spec.rb +1 -1
- data/spec/10auth_spec.rb +132 -0
- data/spec/11useragent_cache_spec.rb +160 -0
- data/spec/12useragent_auth_cookie_spec.rb +53 -0
- data/spec/13useragent_auth_spec.rb +90 -0
- data/spec/spec_helper.rb +5 -0
- metadata +46 -4
- data/fixture/public/lib/noms-args.js +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a2ac7a3782b3dc374c77d11d618d66ac99d37c45
|
4
|
+
data.tar.gz: 241d7122a0756c8f8f5229d6ebfabcbd66eedcba
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 760eb723b068038cdf9a65b082c22610a44ebcda16fe745ec2d7b415498d399bf36d89a1b162e18d026f6c80a7a5061a926a99691fde8c68857707eb2b389489
|
7
|
+
data.tar.gz: dcbd6336014c56f90e70d9e64957650fe5aa61c287ffb0c1be0f8b1b2892d620fd72204dcba9ebf5f9771f1df320382e26a1a5f489bcca6164b1b7a8d9fce559
|
data/README.rst
CHANGED
@@ -54,18 +54,18 @@ Syntax
|
|
54
54
|
|
55
55
|
The basic way of invoking a **noms** command is as follows::
|
56
56
|
|
57
|
-
noms
|
57
|
+
noms <url> <options> <arguments>
|
58
58
|
|
59
59
|
**noms** invokes the app at *url* with the given options and
|
60
|
-
|
60
|
+
arguments, displaying the results.
|
61
61
|
|
62
62
|
**noms** has its own options, which can be given before the
|
63
|
-
*url*, and are available when invoking ``noms --help
|
63
|
+
*url*, and are available when invoking ``noms --help``.
|
64
64
|
|
65
65
|
Bookmarks
|
66
66
|
~~~~~~~~~
|
67
67
|
|
68
|
-
* ``noms
|
68
|
+
* ``noms <bookmark>[/extra] ...``
|
69
69
|
|
70
70
|
**noms** bookmarks are stored, by default, in ``~/.noms/bookmarks.json``,
|
71
71
|
``/usr/local/etc/noms/bookmarks.json``, and ``/etc/noms/bookmarks.json``
|
@@ -101,7 +101,8 @@ strictness policies may be configurable in a file, but the point of
|
|
101
101
|
**noms** is to remove the distribution of thick client libraries that
|
102
102
|
try to abstract away server-side interfaces and the configurations
|
103
103
|
they require, so it would defeat part of its purpose to allow rich
|
104
|
-
configuration of things like default values for objects
|
104
|
+
configuration of things like default values for objects, extra
|
105
|
+
(application-level) connection or protocol information and so forth.
|
105
106
|
|
106
107
|
Implementation
|
107
108
|
--------------
|
@@ -119,28 +120,71 @@ according to `Dynamic Doctype`_, below. Otherwise, it is assumed to be
|
|
119
120
|
structured list or object data, and **noms** will render the object or
|
120
121
|
array using its default format (usually YAML).
|
121
122
|
|
123
|
+
Otherwise, **noms** assumes the data may be binary and will send it
|
124
|
+
to stdout as long as stdout is not a terminal.
|
125
|
+
|
122
126
|
Authentication
|
123
127
|
--------------
|
124
128
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
129
|
+
**noms** supports Basic authentication. It prompts the user for a
|
130
|
+
username and password when authorization is required, and saves the
|
131
|
+
authentication identity information in a "vault" to be used for future
|
132
|
+
invocations (that is, you don't need to enter a password for every
|
133
|
+
**noms** command run).
|
134
|
+
|
135
|
+
If you are "idle" for an hour (have not used the saved authentication
|
136
|
+
vault for any web transactions), **noms** will time out the vault and
|
137
|
+
you will need to re-authenticate.
|
138
|
+
|
139
|
+
You can "close" the vault immediately by using the ``--logout``
|
140
|
+
option. I strongly suggest you call this in your ``~/.logout``
|
141
|
+
mechanism so that it runs immediately when you have completed a
|
142
|
+
login session.
|
143
|
+
|
144
|
+
You can bypass the "vault" by running **noms** with the
|
145
|
+
``--plaintext-identity`` option. This has the effect of caching these
|
146
|
+
credentials permanently (well, until they are no longer good). You
|
147
|
+
should only use this option to generate an identity file for service
|
148
|
+
(non-interactive) accounts that need perpetual access to a web
|
149
|
+
service. The file will appear in the ``~/.noms/identities`` directory
|
150
|
+
in a file named for the SHA-1 hash of the munged authentication realm
|
151
|
+
and domain.
|
152
|
+
|
153
|
+
Such a saved identity file can be provided with the ``--identity`` option
|
154
|
+
to **noms** for non-interactive use.
|
155
|
+
|
156
|
+
Security
|
157
|
+
~~~~~~~~
|
158
|
+
|
159
|
+
**noms** uses strong cryptography to implement the "vault" metaphor, but
|
160
|
+
this is only a metaphor and the security provided is limited. The vault
|
161
|
+
is opened and closed by means of an on-disk key. Because you can easily
|
162
|
+
remove it and because it times out when idle (when this happens, **noms**
|
163
|
+
overwrites it the next time it tries to use it), it's significantly better
|
164
|
+
than ``.netrc`` files or passwords in environment variables or on the
|
165
|
+
command-line; and more ergonomic as well. In the future, this cryptographic
|
166
|
+
service will be provided by an independent **noms-agent**, similar to
|
167
|
+
ssh-agent or gpg-agent. These still have the same problem in that they
|
168
|
+
reduce the security of the system to operating system mechanisms rather
|
169
|
+
than cryptographic mechanisms, but it is still an improvement.
|
132
170
|
|
133
171
|
Dynamic Doctype
|
134
|
-
|
172
|
+
---------------
|
135
173
|
|
136
174
|
The dynamic doctype is the ``noms-v2`` type, which is an object with
|
137
175
|
the following top-level attributes:
|
138
176
|
|
139
177
|
``$doctype``
|
140
|
-
Must be ``noms-v2``. In future, backwards-incompatible extensions
|
178
|
+
Must be ``noms-v2``. In future, backwards-incompatible extensions
|
179
|
+
may be implemented in ``noms-v3`` or higher doctypes.
|
141
180
|
|
142
181
|
``$script``
|
143
|
-
An ordered array of
|
182
|
+
An ordered array of script references to fetch and evaluate; or
|
183
|
+
Javascript strings to evaluate directly. A script reference
|
184
|
+
consists of object with a ``$source`` key, the value of which
|
185
|
+
is the URL of the script to load. Additional fields in the
|
186
|
+
object are ignored and can be used to document the origin
|
187
|
+
or license of the scripts.
|
144
188
|
|
145
189
|
``$argv``
|
146
190
|
The arguments passed to the application. It's called ``$argv``
|
@@ -148,16 +192,18 @@ the following top-level attributes:
|
|
148
192
|
invoked (that is, the bookmark or URL).
|
149
193
|
|
150
194
|
``$exitcode``
|
151
|
-
The unix process exit code with which **noms** will exit at the
|
195
|
+
The unix process exit code with which **noms** will exit at the
|
196
|
+
completion of the command.
|
152
197
|
|
153
198
|
``$body``
|
154
|
-
The body of the document is the data to display. See `Output
|
199
|
+
The body of the document is the data to display. See `Output
|
200
|
+
Formatting`_ below.
|
155
201
|
|
156
202
|
From the perspective of javascript executing within the application,
|
157
203
|
these are accessible as properties of the global **document** object
|
158
204
|
(e.g., ``document.argv`` is the array of arguments given on the **noms**
|
159
205
|
command line; Javascript can set ``document.exitcode`` to determine
|
160
|
-
**noms'** exit code.
|
206
|
+
**noms'** exit code).
|
161
207
|
|
162
208
|
Output Formatting
|
163
209
|
~~~~~~~~~~~~~~~~~
|
@@ -202,8 +248,6 @@ The following entities are allowed in the body of a **noms-v2** document:
|
|
202
248
|
|
203
249
|
* **labels**: Default ``true``; whether to display header row with field labels
|
204
250
|
|
205
|
-
* **columns**: Field names, headings and widths
|
206
|
-
|
207
251
|
* **data**: The objects to render
|
208
252
|
|
209
253
|
* ``$type``: **object** An object has the following attributes:
|
@@ -251,7 +295,7 @@ Scripts have access to the following global objects:
|
|
251
295
|
* **argv** - The arguments being invoked. The first element of this
|
252
296
|
array is the first argument passed to **noms** itself (not the
|
253
297
|
script it ultimately fetches, but how it's invoked, similar to
|
254
|
-
``$
|
298
|
+
``$0``.
|
255
299
|
|
256
300
|
* **exitcode** - The numeric exit code with which **noms** will
|
257
301
|
exit. Initially 0.
|
@@ -264,20 +308,6 @@ Scripts have access to the following global objects:
|
|
264
308
|
|
265
309
|
.. _`NOMS::Command::XMLHttpRequest`: http://www.rubydoc.info/gems/noms-command/NOMS/Command/XMLHttpRequest
|
266
310
|
|
267
|
-
|
268
|
-
Web 1.0 vs Web 2.0
|
269
|
-
------------------
|
270
|
-
|
271
|
-
Like the "real web", **noms** commands can choose to do some
|
272
|
-
calculation on the server and some on the client: **noms** doesn't
|
273
|
-
care. You can use no ``$script`` tag at all and just calculate the
|
274
|
-
entire document to be rendered in the client (though this currently
|
275
|
-
doesn't allow for argument interpretation, in the future the
|
276
|
-
arguments may be passed in request headers or **noms** may allow a way
|
277
|
-
for them to show up in a query string or POST request--but **noms** is
|
278
|
-
not really a command-line http client either). This is up to the
|
279
|
-
application designer.
|
280
|
-
|
281
311
|
Example Application
|
282
312
|
-------------------
|
283
313
|
|
@@ -366,11 +396,48 @@ The example application is a very simple sinatra REST API to a data
|
|
366
396
|
store consisting of a JSON file, and the static files comprising the
|
367
397
|
Javascript source code and the **noms** application document.
|
368
398
|
|
369
|
-
Running Examples
|
370
|
-
|
399
|
+
Hacking/Running Examples
|
400
|
+
------------------------
|
401
|
+
|
402
|
+
Use Ruby 1.9.3 or higher (e.g. if you need to set PATH
|
403
|
+
so that Ruby 1.9 executables are found, do that:
|
404
|
+
``export PATH=/usr/local/ruby1.9/bin:$PATH``.
|
371
405
|
|
372
406
|
Use ``rake start`` to start the test webserver and run the
|
373
407
|
example applications (see the comments inside the
|
374
408
|
``fixture/public/*.json`` files for syntax).
|
375
409
|
|
376
410
|
Start with ``noms2 http://localhost:8787/echo.json hello world``.
|
411
|
+
|
412
|
+
Workflow
|
413
|
+
~~~~~~~~
|
414
|
+
|
415
|
+
Set up your environment::
|
416
|
+
|
417
|
+
mkdir ~/.noms
|
418
|
+
echo '{ "dnc": "http://localhost:8787/dnc.json" }' >~/.noms/bookmarks.json
|
419
|
+
export PATH=`pwd`/bin:$PATH
|
420
|
+
expert RUBYLIB=lib
|
421
|
+
bundle install
|
422
|
+
noms2 # NOMS usage message
|
423
|
+
noms2 dnc # dnc usage message
|
424
|
+
|
425
|
+
Do ``rake start`` to start the webserver: web root is is ``test/``.
|
426
|
+
|
427
|
+
Hack files in:
|
428
|
+
|
429
|
+
* ``lib/`` - Ruby files for ``noms2`` command
|
430
|
+
|
431
|
+
* ``fixture/dnc.rb`` - Sinatra app which is webserver for dnc app (serves
|
432
|
+
static files and implements rest interface).
|
433
|
+
|
434
|
+
* ``fixture/public/dnc.json`` - App document for 'dnc' subcommand.
|
435
|
+
|
436
|
+
* ``fixture/public/lib`` - Javascript files, ``dnc.js`` implements dnc
|
437
|
+
operations
|
438
|
+
|
439
|
+
Do ``rake sync`` to sync over updated files from ``fixture`` and test
|
440
|
+
(the webserver document root is ``test/public``).
|
441
|
+
|
442
|
+
``noms2 -d`` produces debugging showing full stack traces for Javascript
|
443
|
+
errors, ``console.log()`` output and web traffic.
|
data/TODO.rst
CHANGED
data/fixture/dnc.rb
CHANGED
@@ -7,7 +7,7 @@ class DNC < Sinatra::Application
|
|
7
7
|
|
8
8
|
set :port, 8787
|
9
9
|
set :root, File.expand_path("#{File.dirname(__FILE__)}")
|
10
|
-
enable :static
|
10
|
+
enable :static, :sessions
|
11
11
|
|
12
12
|
File.open(File.join(settings.root, 'dnc.pid'), 'w') {|f| f.puts Process.pid }
|
13
13
|
|
@@ -30,6 +30,41 @@ class DNC < Sinatra::Application
|
|
30
30
|
@auth ||= Rack::Auth::Basic::Request.new(request.env)
|
31
31
|
@auth.provided? and @auth.basic? and @auth.credentials and @auth.credentials == ['testuser', 'testpass']
|
32
32
|
end
|
33
|
+
|
34
|
+
def generated_body(h={})
|
35
|
+
JSON.pretty_generate({ 'generated' => Time.now.httpdate }.merge(h)) + "\n"
|
36
|
+
end
|
37
|
+
|
38
|
+
def require_cookie_auth
|
39
|
+
return if cookie_authorized?
|
40
|
+
redirect "/cookie/login?return_to=#{CGI.escape(request.path)}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def cookie_authorized?
|
44
|
+
session[:userid] == 'testuser'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
before do
|
49
|
+
content_type 'application/json'
|
50
|
+
end
|
51
|
+
|
52
|
+
get '/cookie/login' do
|
53
|
+
require_auth
|
54
|
+
session[:userid] = @auth.credentials.first
|
55
|
+
landing = params[:return_to] || '/cookie/home'
|
56
|
+
redirect landing
|
57
|
+
end
|
58
|
+
|
59
|
+
get '/cookie/home' do
|
60
|
+
require_cookie_auth
|
61
|
+
generated_body({'cookie_user' => session[:userid] })
|
62
|
+
end
|
63
|
+
|
64
|
+
get '/cookie/logout' do
|
65
|
+
old_userid = session[:userid]
|
66
|
+
session[:userid] = nil
|
67
|
+
generated_body({'message' => "#{old_userid} logged out"})
|
33
68
|
end
|
34
69
|
|
35
70
|
get '/readme' do
|
@@ -66,6 +101,8 @@ class DNC < Sinatra::Application
|
|
66
101
|
request.body.rewind
|
67
102
|
new_object = JSON.parse request.body.read
|
68
103
|
|
104
|
+
puts "POST for object: #{new_object.inspect}"
|
105
|
+
|
69
106
|
data = load_data
|
70
107
|
# How unsafe is this?
|
71
108
|
new_object['id'] = data.map { |e| e['id'] }.max + 1
|
@@ -115,6 +152,78 @@ class DNC < Sinatra::Application
|
|
115
152
|
redirect to('/dnc.json')
|
116
153
|
end
|
117
154
|
|
155
|
+
get '/auth/ok' do
|
156
|
+
require_auth
|
157
|
+
"SUCCESS"
|
158
|
+
end
|
159
|
+
|
160
|
+
# Caching client should let sit in cache
|
161
|
+
# for 4s then refetch
|
162
|
+
get '/static/max-age-4' do
|
163
|
+
cache_control :max_age => 4
|
164
|
+
generated_body
|
165
|
+
end
|
166
|
+
|
167
|
+
# Caching client must always revalidate
|
168
|
+
# even within 4s
|
169
|
+
get '/static/must-revalidate' do
|
170
|
+
cache_control :must_revalidate, :max_age => 4
|
171
|
+
expires 4
|
172
|
+
etag "10"
|
173
|
+
generated_body
|
174
|
+
end
|
175
|
+
|
176
|
+
# Caching client must never cache
|
177
|
+
get '/static/no-cache' do
|
178
|
+
cache_control :no_cache
|
179
|
+
generated_body
|
180
|
+
end
|
181
|
+
|
182
|
+
# Caching client should let sit in cache
|
183
|
+
# for 4s then refetch
|
184
|
+
get '/static/expires-4' do
|
185
|
+
expires 4
|
186
|
+
generated_body
|
187
|
+
end
|
188
|
+
|
189
|
+
# Caching client should let sit in cache
|
190
|
+
# for 4s then revalidate using If-Modified-Since
|
191
|
+
get '/static/last-modified' do
|
192
|
+
expires 4
|
193
|
+
$static_time ||= Time.now
|
194
|
+
last_modified $static_time
|
195
|
+
generated_body
|
196
|
+
end
|
197
|
+
|
198
|
+
# Caching client should let sit in cache
|
199
|
+
# for 4s then revalidate using If-None-Match
|
200
|
+
get '/static/expires-4-changing' do
|
201
|
+
expires 4
|
202
|
+
etag Time.now.httpdate
|
203
|
+
generated_body
|
204
|
+
end
|
205
|
+
|
206
|
+
# Caching client should let sit in cache
|
207
|
+
# for 2s then revalidate using If-None-Match
|
208
|
+
get '/static/expires-2-constant' do
|
209
|
+
etag "10"
|
210
|
+
expires 2
|
211
|
+
generated_body
|
212
|
+
end
|
213
|
+
|
214
|
+
get '/static/long-cache' do
|
215
|
+
etag "11"
|
216
|
+
expires 100
|
217
|
+
generated_body
|
218
|
+
end
|
219
|
+
|
220
|
+
get '/auth/cacheable' do
|
221
|
+
require_auth
|
222
|
+
expires 100
|
223
|
+
etag "11"
|
224
|
+
generated_body
|
225
|
+
end
|
226
|
+
|
118
227
|
run! if app_file = $0
|
119
228
|
|
120
229
|
end
|
data/fixture/public/dnc.json
CHANGED
@@ -8,15 +8,16 @@
|
|
8
8
|
"$comment": "Optparse.js 1.0.3 - https://github.com/jfd/optparse-js; via rawgit.com" },
|
9
9
|
{ "$source": "https://rawgit.com/douglascrockford/JSON-js/master/json2.js",
|
10
10
|
"$comment": "JSON in JavaScript - https://github.com/douglascrockford/JSON-js" },
|
11
|
-
{ "$source": "lib/
|
11
|
+
{ "$source": "lib/nomsargs.js" },
|
12
12
|
{ "$source": "lib/dnc.js" }
|
13
13
|
],
|
14
14
|
"$body": [
|
15
15
|
"Usage:",
|
16
|
-
" noms dnc query <field>=<value>",
|
16
|
+
" noms dnc query [<field>=<value> [...]] [<field> [...]]",
|
17
|
+
" noms dnc list [<field> [...]]",
|
18
|
+
" noms dnc show id [<field> [...]]",
|
17
19
|
" noms dnc add <field>=<value> [<field>=<value> [...]]",
|
18
|
-
" noms dnc
|
19
|
-
" noms dnc
|
20
|
-
" noms dnc list"
|
20
|
+
" noms dnc set id <field>=<value> [<field>=<value> [...]]",
|
21
|
+
" noms dnc remove <id>"
|
21
22
|
]
|
22
23
|
}
|
data/fixture/public/lib/dnc.js
CHANGED
@@ -1,32 +1,42 @@
|
|
1
1
|
if (document.argv.length > 1) {
|
2
2
|
var argv = document.argv;
|
3
3
|
var me = argv.shift();
|
4
|
-
var command;
|
5
4
|
var format;
|
6
5
|
var xmlhttp = new XMLHttpRequest();
|
7
6
|
|
8
|
-
// document attributes can be set
|
9
|
-
// but are immutable
|
10
|
-
document.body = [ ];
|
11
|
-
var output = [ ];
|
12
|
-
|
13
7
|
var optspec = [
|
14
8
|
["-J", "--json", "Display JSON"],
|
15
9
|
["-Y", "--yaml", "Display YAML"],
|
16
10
|
["-C", "--csv", "Display CSV"],
|
17
11
|
["-v", "--verbose", "Enable verbose output"],
|
18
|
-
["--
|
12
|
+
["-q", "--terse", "Use terse output"],
|
13
|
+
["--nofeedback", "Don't print feedback"],
|
14
|
+
["--nolabel", "Don't print field names"],
|
15
|
+
["--noheader", "Don't print column headings"]
|
19
16
|
];
|
20
17
|
|
18
|
+
// document attributes can be set
|
19
|
+
// but are immutable
|
20
|
+
document.body = [ ];
|
21
|
+
var output = [ ];
|
22
|
+
|
21
23
|
var parser = new optparse.OptionParser(optspec);
|
22
24
|
var options = {
|
23
|
-
"feedback": true,
|
24
25
|
"format": "default",
|
25
|
-
"verbose": false
|
26
|
+
"verbose": false,
|
27
|
+
"feedback": true,
|
28
|
+
"label": true,
|
26
29
|
};
|
27
|
-
var args = [ ];
|
28
30
|
|
29
|
-
|
31
|
+
var field_config = {
|
32
|
+
'id': { 'field': 'id', 'width': 3, 'align': 'right' },
|
33
|
+
'name': { 'field': 'name', 'width': 20 },
|
34
|
+
'phone': { 'field': 'phone', 'width': 20 },
|
35
|
+
'street': { 'field': 'street', 'width': 40 },
|
36
|
+
'city': { 'field': 'city', 'width': 31 }
|
37
|
+
}
|
38
|
+
|
39
|
+
parser.on("verbose", function() { options["verbose"] = true; });
|
30
40
|
parser.on("json", function() {
|
31
41
|
options["format"] = "json";
|
32
42
|
options["feedback"] = false;
|
@@ -40,36 +50,173 @@ if (document.argv.length > 1) {
|
|
40
50
|
options["feedback"] = false;
|
41
51
|
});
|
42
52
|
parser.on("nofeedback", function() { options["feedback"] = false; });
|
43
|
-
parser.on(
|
44
|
-
parser.on(function(
|
53
|
+
parser.on("nolabel", function() { options["label"] = false; });
|
54
|
+
parser.on("terse", function() {
|
55
|
+
options["feedback"] = false;
|
56
|
+
options["label"] = false;
|
57
|
+
});
|
58
|
+
// parser.on(0, function(arg) { command = arg; });
|
59
|
+
|
60
|
+
var args = parser.parse(argv);
|
61
|
+
var command = args.shift();
|
45
62
|
|
46
|
-
|
63
|
+
var format, records, field_list;
|
47
64
|
|
48
65
|
switch(command) {
|
49
|
-
|
50
|
-
|
51
|
-
|
66
|
+
|
67
|
+
case "add":
|
68
|
+
var keywords = new nomsargs.NomsArgs(args);
|
69
|
+
|
70
|
+
xmlhttp.open("POST", "/dnc", false);
|
71
|
+
xmlhttp.setRequestHeader("Content-type", "application/json");
|
72
|
+
xmlhttp.send(JSON.stringify(keywords.assignment));
|
73
|
+
|
74
|
+
if (xmlhttp.status == 201) {
|
75
|
+
record = JSON.parse(xmlhttp.responseText);
|
76
|
+
output.push("Entry created with id " + record['id']);
|
77
|
+
} else {
|
78
|
+
alert("Error " + xmlhttp.status + " creating entry");
|
79
|
+
document.exitcode = 2;
|
80
|
+
}
|
81
|
+
|
82
|
+
break;
|
83
|
+
|
84
|
+
case "remove":
|
85
|
+
var id = args.shift();
|
86
|
+
|
87
|
+
if (id == undefined) {
|
88
|
+
alert("No id to remove");
|
89
|
+
document.exitcode = 1;
|
90
|
+
} else {
|
91
|
+
xmlhttp.open("DELETE", "/dnc/" + id, false);
|
92
|
+
xmlhttp.send();
|
93
|
+
|
94
|
+
if (xmlhttp.status == 404) {
|
95
|
+
alert("Entry " + id + " does not exist");
|
96
|
+
} else if (xmlhttp.status != 204) {
|
97
|
+
alert("Error deleting id " + id);
|
98
|
+
document.exitcode = 2;
|
99
|
+
}
|
100
|
+
}
|
101
|
+
|
102
|
+
break;
|
103
|
+
|
104
|
+
case "set":
|
105
|
+
// We are not doing upsert
|
106
|
+
var id = args.shift();
|
107
|
+
var keywords = new nomsargs.NomsArgs(args);
|
108
|
+
|
109
|
+
if (id == undefined) {
|
110
|
+
alert("No id to set");
|
111
|
+
document.exitcode = 1;
|
52
112
|
} else {
|
53
|
-
|
113
|
+
xmlhttp.open("GET", "/dnc/" + id, false);
|
114
|
+
xmlhttp.send();
|
115
|
+
|
116
|
+
if (xmlhttp.status == 404) {
|
117
|
+
alert("Entry " + id + " does not exist (use add)");
|
118
|
+
document.exitcode = 2;
|
119
|
+
} else if (xmlhttp.status == 200) {
|
120
|
+
the_object = JSON.parse(xmlhttp.responseText);
|
121
|
+
|
122
|
+
// Update assigned fields in retrieved object
|
123
|
+
keywords.assignmentKeys().map(function (key) {
|
124
|
+
the_object[key] = keywords.assignment[key];
|
125
|
+
});
|
126
|
+
|
127
|
+
xmlhttp.open("PUT", "/dnc/" + id, false);
|
128
|
+
xmlhttp.send(JSON.stringify(the_object));
|
129
|
+
|
130
|
+
if (xmlhttp.status == 200) {
|
131
|
+
output.push("Entry " + id + " updated");
|
132
|
+
} else {
|
133
|
+
alert("Error " + xmlhttp.status + " updating entry " + id);
|
134
|
+
document.exitcode = 2;
|
135
|
+
}
|
136
|
+
}
|
137
|
+
}
|
138
|
+
|
139
|
+
break;
|
140
|
+
|
141
|
+
case "show":
|
142
|
+
var id = args.shift();
|
143
|
+
var field_list = args;
|
144
|
+
format = (options["format"] == "default" ? "record" : options["format"]);
|
145
|
+
|
146
|
+
if (id == undefined) {
|
147
|
+
alert("No id to show");
|
148
|
+
document.exitcode = 1;
|
149
|
+
} else {
|
150
|
+
xmlhttp.open("GET", "/dnc/" + id, false);
|
151
|
+
xmlhttp.send();
|
152
|
+
|
153
|
+
if (xmlhttp.status == 404) {
|
154
|
+
alert("Entry " + id + " not found");
|
155
|
+
document.exitcode = 2;
|
156
|
+
} else {
|
157
|
+
console.log("output for record");
|
158
|
+
record = JSON.parse(xmlhttp.responseText);
|
159
|
+
|
160
|
+
console.log(record);
|
161
|
+
|
162
|
+
output.push({
|
163
|
+
'$type': 'object',
|
164
|
+
'$format': format,
|
165
|
+
'$labels': options["label"],
|
166
|
+
'$fields': field_list,
|
167
|
+
'$data': record
|
168
|
+
});
|
169
|
+
}
|
170
|
+
}
|
171
|
+
|
172
|
+
break;
|
173
|
+
|
174
|
+
case "query":
|
175
|
+
var keywords = new nomsargs.NomsArgs(args);
|
176
|
+
format = (options["format"] == "default" ? "lines" : options["format"]);
|
177
|
+
var query = keywords.query();
|
178
|
+
var field_list = keywords.extra;
|
179
|
+
|
180
|
+
if (field_list.length == 0) {
|
181
|
+
field_list = ['id', 'name', 'phone'];
|
54
182
|
}
|
183
|
+
xmlhttp.open("GET", "/dnc?" + query, false);
|
184
|
+
xmlhttp.send();
|
185
|
+
records = JSON.parse(xmlhttp.responseText);
|
186
|
+
|
187
|
+
output.push(
|
188
|
+
{
|
189
|
+
'$type': 'object-list',
|
190
|
+
'$format': format,
|
191
|
+
'$labels': options["label"],
|
192
|
+
'$columns': field_list.map(function(item) { return field_config[item]; }),
|
193
|
+
'$data': records
|
194
|
+
});
|
195
|
+
if (options["feedback"]) {
|
196
|
+
output.push(records.length + " objects");
|
197
|
+
}
|
198
|
+
break;
|
199
|
+
|
200
|
+
case "list":
|
201
|
+
format = (options["format"] == "default" ? "lines" : options["format"]);
|
202
|
+
|
55
203
|
xmlhttp.open("GET", "/dnc", false);
|
56
204
|
xmlhttp.send();
|
57
|
-
|
205
|
+
records = JSON.parse(xmlhttp.responseText);
|
206
|
+
field_list = (args.length == 0 ? ['id', 'name', 'phone'] : args)
|
58
207
|
output.push(
|
59
208
|
{
|
60
209
|
'$type': 'object-list',
|
61
210
|
'$format': format,
|
62
|
-
'$
|
63
|
-
|
64
|
-
{ 'field': 'name', 'width': 20 },
|
65
|
-
{ 'field': 'phone', 'width': 20 }
|
66
|
-
],
|
211
|
+
'$labels': options["label"],
|
212
|
+
'$columns': field_list.map(function(item) { return field_config[item]; }),
|
67
213
|
'$data': records
|
68
214
|
});
|
69
215
|
if (options["feedback"]) {
|
70
216
|
output.push(records.length + " objects");
|
71
217
|
}
|
72
218
|
break;
|
219
|
+
|
73
220
|
default:
|
74
221
|
document.exitcode = 8;
|
75
222
|
window.alert(
|