@naanlang/naan 1.0.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.
Files changed (98) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +46 -0
  3. package/dist/env_web.js +431 -0
  4. package/dist/naan.min.js +73 -0
  5. package/frameworks/browser/browser.nlg +30 -0
  6. package/frameworks/browser/pouchdb/pouchdb.min.js +7 -0
  7. package/frameworks/browser/spark-md5/spark-md5.min.js +1 -0
  8. package/frameworks/browser/sworker.js +192 -0
  9. package/frameworks/browser/terminals.nlg +787 -0
  10. package/frameworks/browser/workers.nlg +386 -0
  11. package/frameworks/client/apiclient.nlg +183 -0
  12. package/frameworks/client/client.nlg +29 -0
  13. package/frameworks/client/psm_client.nlg +572 -0
  14. package/frameworks/common/common.nlg +464 -0
  15. package/frameworks/common/preferences.nlg +131 -0
  16. package/frameworks/common/repltools.nlg +100 -0
  17. package/frameworks/common/watching.nlg +97 -0
  18. package/frameworks/node/apiserver.nlg +399 -0
  19. package/frameworks/node/filesystem.nlg +1012 -0
  20. package/frameworks/node/gitter.nlg +234 -0
  21. package/frameworks/node/node.nlg +81 -0
  22. package/frameworks/node/psm_server.nlg +465 -0
  23. package/frameworks/node/worker.nlg +560 -0
  24. package/frameworks/project/build.nlg +1229 -0
  25. package/frameworks/project/jszip.js +30 -0
  26. package/frameworks/project/jszip.nlg +87 -0
  27. package/frameworks/project/proj_cliser.nlg +139 -0
  28. package/frameworks/project/proj_console.nlg +137 -0
  29. package/frameworks/project/proj_folder.nlg +143 -0
  30. package/frameworks/project/proj_lambda.nlg +137 -0
  31. package/frameworks/project/proj_static.nlg +138 -0
  32. package/frameworks/project/project.nlg +29 -0
  33. package/frameworks/project/projects.nlg +587 -0
  34. package/frameworks/project/uglifyjs.js +1 -0
  35. package/frameworks/project/uglifyjs.nlg +79 -0
  36. package/frameworks/running/debugcom.nlg +163 -0
  37. package/frameworks/running/debugnub.nlg +565 -0
  38. package/frameworks/running/debugutil.nlg +510 -0
  39. package/frameworks/running/executors.nlg +767 -0
  40. package/frameworks/running/running.nlg +151 -0
  41. package/frameworks/running/sourcecode.nlg +346 -0
  42. package/frameworks/running/taskexec.nlg +196 -0
  43. package/frameworks/storage/dbt_pouch.nlg +773 -0
  44. package/frameworks/storage/file_manager.nlg +772 -0
  45. package/frameworks/storage/psm.nlg +326 -0
  46. package/frameworks/storage/psm_dbtables.nlg +814 -0
  47. package/frameworks/storage/resources.nlg +445 -0
  48. package/frameworks/storage/storage.nlg +52 -0
  49. package/lib/browser/env_web.js +431 -0
  50. package/lib/browser/env_webworker.js +146 -0
  51. package/lib/browser/require.js +1653 -0
  52. package/lib/core/naanlib.js +73 -0
  53. package/lib/env_node.js +282 -0
  54. package/lib/env_nodeworker.js +165 -0
  55. package/lib/node_repl.js +25 -0
  56. package/lib/node_repl_init.nlg +52 -0
  57. package/package.json +13 -0
  58. package/plugins/gitClient/clientops.nlg +317 -0
  59. package/plugins/gitClient/gitClient.nlg +63 -0
  60. package/plugins/gitClient/gitutils.nlg +1331 -0
  61. package/plugins/gitClient/minimatch.js +945 -0
  62. package/plugins/gitClient/minimatch_license.txt +15 -0
  63. package/plugins/gitClient/minimatch_readme.md +208 -0
  64. package/plugins/nodeLib/nodeLib.nlg +26 -0
  65. package/plugins/nodeLib/node_cp.nlg +65 -0
  66. package/plugins/nodeLib/node_fs.nlg +137 -0
  67. package/plugins/nodeLib/node_https.nlg +172 -0
  68. package/plugins/nodeLib/node_util.nlg +180 -0
  69. package/plugins/serviceAws/aws/aws-sdk.min.js +88 -0
  70. package/plugins/serviceAws/aws/lambda_rest_index.js +122 -0
  71. package/plugins/serviceAws/aws/lambda_rest_init.nlg +58 -0
  72. package/plugins/serviceAws/aws/lambda_ws_index.js +498 -0
  73. package/plugins/serviceAws/aws/lambda_ws_init.nlg +49 -0
  74. package/plugins/serviceAws/aws_cloudwatchlogs.nlg +122 -0
  75. package/plugins/serviceAws/aws_cognito.nlg +76 -0
  76. package/plugins/serviceAws/aws_dynamo.nlg +509 -0
  77. package/plugins/serviceAws/aws_lambda.nlg +95 -0
  78. package/plugins/serviceAws/aws_s3.nlg +134 -0
  79. package/plugins/serviceAws/aws_utils.nlg +86 -0
  80. package/plugins/serviceAws/dbt_aws.nlg +769 -0
  81. package/plugins/serviceAws/lambda_naan_control.nlg +175 -0
  82. package/plugins/serviceAws/psm_aws.nlg +258 -0
  83. package/plugins/serviceAws/serviceAws.nlg +38 -0
  84. package/plugins/serviceGitHub/gitops.nlg +522 -0
  85. package/plugins/serviceGitHub/psm_github.nlg +205 -0
  86. package/plugins/serviceGitHub/serviceGitHub.nlg +65 -0
  87. package/plugins/serviceGitLab/gitops.nlg +528 -0
  88. package/plugins/serviceGitLab/psm_gitlab.nlg +205 -0
  89. package/plugins/serviceGitLab/serviceGitLab.nlg +65 -0
  90. package/test/harness.nlg +312 -0
  91. package/test/node_test.js +33 -0
  92. package/test/test_01_core.nlg +768 -0
  93. package/test/test_02_context.nlg +269 -0
  94. package/test/test_03_jsinterop.nlg +137 -0
  95. package/test/test_04_numerics.nlg +450 -0
  96. package/test/test_05_strings.nlg +63 -0
  97. package/test/test_06_lingoparse.nlg +500 -0
  98. package/test/test_07_lingo.nlg +623 -0
@@ -0,0 +1,572 @@
1
+ /*
2
+ * psm_client.nlg
3
+ * Naanlib/frameworks/client
4
+ *
5
+ * PSM Connector for Browser data stores.
6
+ *
7
+ * column positioning: // // !
8
+ *
9
+ * Copyright (c) 2019-2022 by Richard C. Zulch
10
+ *
11
+ */
12
+
13
+
14
+ /*
15
+ * psmcFsView
16
+ *
17
+ * Filesystem services via the specified API to remote NodeJS functions.
18
+ *
19
+ */
20
+
21
+ closure psmcFsView(api, rootpath, local view, pathmod) {
22
+ view = new(object, this)
23
+ view.api = api
24
+ view.rootpath = rootpath
25
+
26
+ // psmRemote
27
+ //
28
+ // Call the API to remote a PSM call.
29
+
30
+ closure psmRemote(path, op, options, putdata, callback, local params, item) {
31
+ if !callback
32
+ return (syncAdapter(psmRemote, path, op, options, putdata))
33
+ if !string(path)
34
+ return (asyncResult(callback, Error("invalid path:", typeof(path))))
35
+ params = {
36
+ path: JSpath.resolve(rootpath, path)
37
+ op: op
38
+ }
39
+ for item in options
40
+ params[item] = options[item]
41
+ api.psmRemote(params, putdata, function(error, data) {
42
+ if !error && !data
43
+ debuglog("psmRemote: invalid result for op", op)
44
+ if error
45
+ callback(error)
46
+ else
47
+ callback(false, data)
48
+ })
49
+ }
50
+
51
+ // close
52
+ //
53
+ // Close the view
54
+
55
+ view.close = function close() {
56
+ if api {
57
+ view.api = api = false }
58
+ }
59
+
60
+ // path
61
+ //
62
+ // The path sub-object remotes calls to the NodeJS path module.
63
+
64
+ view.path = new(object, this)
65
+ view.path[".undefined"] = closure path args {
66
+ closure (selector, arglist, local error, info) {
67
+ if !pathmod {
68
+ `(error, data) = view.data()
69
+ if error
70
+ return (list(error))
71
+ if info.pathsep == "\\"
72
+ pathmod = JSpath.win32
73
+ else
74
+ pathmod = JSpath.posix
75
+ }
76
+ xapply(pathmod, selector, arglist)
77
+ } (args.0, args.-1)
78
+ }
79
+
80
+ // data
81
+ //
82
+ // Return the filesystem data, i.e. the tree data field. The minimum information is:
83
+ // platform -- e.g. "darwin" or "win32"
84
+ // semantics -- e.g. "win32" or "posix"
85
+ // pathsep -- e.g. / or \
86
+
87
+ view.data = closure data(callback) {
88
+ if !callback
89
+ return (syncAdapter(data))
90
+ psmRemote("", "tree", { depthlimit: 0 }, false, function(error, tree) {
91
+ view.fsdata = tree.data
92
+ callback(error, tree.data)
93
+ })
94
+ }
95
+
96
+ // readLines
97
+ //
98
+ // Read a lines of a file at the specified path with options:
99
+ // matchRE: -- JavaScript regex
100
+ // ignoreCase: -- ignore case during match
101
+ // invert: -- return lines that DO NOT match the regex
102
+ // returnText: -- return text of matched lines
103
+ // When using a matchRE, the return value is an array of [ lineNumber, text ] pairs if
104
+ // returnText is specified, or just an array of one-based line numbers otherwise.
105
+ //
106
+
107
+ view.readLines = function readLines(path, options, callback) {
108
+ psmRemote(path, "readLines", options, false, callback)
109
+ }
110
+
111
+ // readFile
112
+ //
113
+ // Read a file at the specified path
114
+
115
+ view.readFile = function readFile(path, options, callback) {
116
+ psmRemote(path, "readFile", options, false, callback)
117
+ }
118
+
119
+ // writeFile
120
+ //
121
+ // Write a file at the specified path
122
+
123
+ view.writeFile = function writeFile(path, data, options, callback) {
124
+ psmRemote(path, "writeFile", options, data, callback)
125
+ }
126
+
127
+ // delete
128
+ //
129
+ // Delete a file or directory at the specified path
130
+
131
+ view.delete = function delete(path, options, callback) {
132
+ psmRemote(path, "delete", options, false, callback)
133
+ }
134
+
135
+ // info
136
+ //
137
+ // Get file info at the specified path
138
+
139
+ view.info = function info(path, callback) {
140
+ psmRemote(path, "info", { }, false, callback)
141
+ }
142
+
143
+ // setTimes
144
+ //
145
+ // Set file modify and access times at the specified path
146
+
147
+ view.setTimes = function setTimes(path, atime, mtime, callback) {
148
+ psmRemote(path, "setTimes", {
149
+ atime: atime
150
+ mtime: mtime
151
+ }, false, callback)
152
+ }
153
+
154
+ // dirList
155
+ //
156
+ // Read a directory at the specified path
157
+
158
+ view.dirList = function dirList(path, options, callback) {
159
+ psmRemote(path, "dirList", {
160
+ head: options.head
161
+ }, false, callback)
162
+ }
163
+
164
+ // readir
165
+ //
166
+ // Read a directory at the specified path
167
+
168
+ view.readir = function readir(path, callback) {
169
+ psmRemote(path, "dirList", {
170
+ head: true
171
+ }, false, callback)
172
+ }
173
+
174
+ // mkdir
175
+ //
176
+ // Create a directory at the specified path
177
+
178
+ view.mkdir = function mkdir(path, callback) {
179
+ psmRemote(path, "mkdir", { }, false, callback)
180
+ }
181
+
182
+ // tree
183
+ //
184
+ // Return a tree for the specified path, which is relative to the root of the view.
185
+
186
+ view.tree = function tree(path, options, callback) {
187
+ psmRemote(path, "tree", {
188
+ depthlimit: options.depthlimit
189
+ }, false, callback)
190
+ }
191
+
192
+ // dirSearch
193
+ //
194
+ // Search the specified file or recursive directory.
195
+
196
+ view.dirSearch = function dirSearch(path, options, callback) {
197
+ psmRemote(path, "dirSearch", options, false, callback)
198
+ }
199
+
200
+ // copy
201
+ //
202
+ // Copy / move / rename a file or directory. The source is the full path of the item. The
203
+ // destination is:
204
+ // - a new name if it has no embedded slashes, or
205
+ // - a new location if it ends in a slash, otherwise
206
+ // - a new pathname for the source if it does not end in a slash.
207
+ // This works by creating a new file or directory of files in the new location and then
208
+ // optionally deleting the files in the existing location. If options.move is true then we
209
+ // delete the source after the copy.
210
+
211
+ view.copy = closure copy(srcpath, dest, options, callback, local parameters) {
212
+ if !options
213
+ options = { }
214
+ options.destination = JSpath.resolve(rootpath, dest)
215
+ psmRemote(srcpath, "copy", options, false, callback)
216
+ }
217
+
218
+ // reveal
219
+ //
220
+ // Reveal the file at the specified path in the UI.
221
+
222
+ view.reveal = function reveal(path, callback) {
223
+ psmRemote(path, "reveal", { }, false, callback)
224
+ }
225
+
226
+ // minimize
227
+ //
228
+ // Minimize the JavaScript source and return as a string
229
+
230
+ view.minimize = function minimize(data, callback) {
231
+ psmRemote("", "minimize", { }, data, callback)
232
+ }
233
+
234
+ // unzip
235
+ //
236
+ // Get file info at the specified path
237
+
238
+ view.unzip = function unzip(path, dest, callback, local parameters) {
239
+ parameters = { destination: JSpath.resolve(rootpath, dest) }
240
+ psmRemote(path, "unzip", parameters, false, callback)
241
+ }
242
+
243
+ // touch
244
+ //
245
+ // Touch the file at the specified path
246
+
247
+ view.touch = function touch(path, callback) {
248
+ psmRemote(path, "touch", { }, false, callback)
249
+ }
250
+
251
+ // shellOpen
252
+ //
253
+ // Tell the shell to open the specified file.
254
+
255
+ view.shellOpen = function shellOpen(path, args, callback) {
256
+ psmRemote(path, "shellOpen", { args: args }, false, callback)
257
+ }
258
+
259
+ // grepLines
260
+ //
261
+ // Grep the specified file or recursive directory.
262
+
263
+ view.grepLines = function grepLines(path, options, callback) {
264
+ psmRemote(path, "grepLines", options, false, callback)
265
+ }
266
+
267
+ // gitStatus
268
+ //
269
+ // Get git status. Optional pathspec is a path string or array of strings.
270
+
271
+ view.gitStatus = function gitStatus(pathspec, callback, local options) {
272
+ if pathspec
273
+ options = { pathspec: pathspec }
274
+ else
275
+ options = { }
276
+ psmRemote("", "gitStatus", options, false, callback)
277
+ }
278
+
279
+ // gitLog
280
+ //
281
+ // Get git log for a file. Optional pathspec is a path string or array of strings.
282
+
283
+ view.gitLog = function gitLog(pathspec, callback, local options) {
284
+ if pathspec
285
+ options = { pathspec: pathspec }
286
+ else
287
+ options = { }
288
+ psmRemote("", "gitLog", options, false, callback)
289
+ }
290
+
291
+ // gitShowFile
292
+ //
293
+ // Get the content of a specified file and revision.
294
+
295
+ view.gitShowFile = function gitShowFile(pathspec, hash, callback, local options) {
296
+ options = {
297
+ pathspec: pathspec
298
+ hash: hash
299
+ }
300
+ psmRemote("", "gitShowFile", options, false, callback)
301
+ }
302
+
303
+ // util
304
+ //
305
+ // Utility operations for the filesystem
306
+
307
+ view.util = require("../storage/psm.nlg").MakePSMutil(view)
308
+
309
+ // finis
310
+
311
+ list(false, view)
312
+ };
313
+
314
+
315
+ /*
316
+ * psmcFsConnector
317
+ *
318
+ * Make a PSM connector for the host filesystem.
319
+ *
320
+ */
321
+
322
+ closure psmcFsConnector(psm, nicc, local connClassID, connector, watch) {
323
+ connClassID = "NodeFS"
324
+ connector = new(object, this)
325
+ connector.psm = psm
326
+ connector.api = nicc.api
327
+ connector.vault = psm.vault(connClassID)
328
+ connector.label = "Naan IDE Server"
329
+ watch = psm.watchable(connector)
330
+
331
+ // uifields
332
+ //
333
+ // Report the UI fields we need to add a resource
334
+ connector.uifields = function uifields() {
335
+ [{
336
+ label: "URL"
337
+ placeholder: "http://host.com/endpoint"
338
+ key: "urlName" },
339
+ {
340
+ label: "Auth Name"
341
+ placeholder: "account name"
342
+ key: "authName" },
343
+ {
344
+ label: "Auth Password"
345
+ placeholder: "account password"
346
+ key: "authPW"
347
+ type: "password" },
348
+ ]
349
+ }
350
+
351
+ // hashResourceID
352
+ //
353
+ // Make a stable hash based on the resource credentials that we can persist or share between
354
+ // different domains accessing the same resource.
355
+ connector.hashResourceID = function hashResourceID(resource, local ident) {
356
+ ident = resource.urlName
357
+ if resource.label
358
+ ident = ident.concat(resource.label)
359
+ HashSHA256(ident)
360
+ }
361
+
362
+ // findResource
363
+ //
364
+ // Find a resource with the specified contents, returning the resID or false. The loose criteria
365
+ // is: if added, would the specified contents be redundant to an existing resource?
366
+ connector.findResource = function findResource(resource, local resID, creds) {
367
+ for resID in listResources().1 {
368
+ creds = access(resID).1
369
+ if resource.urlName == creds.urlName
370
+ && (!resource.label || resource.label == creds.label)
371
+ && resource.authName == creds.authName
372
+ return (resID)
373
+ }
374
+ false
375
+ }
376
+
377
+ // addResource
378
+ //
379
+ // Add credentials for a named resource. The resource is a dictionary comprising these keys:
380
+ // label - [optional] label we use for this resource
381
+ // urlName - URL (e.g. "http://host.com/node/fsapi")
382
+ // authName - [optional] the authentication name for a URL
383
+ // authPW - [optional] the autentication password, required if authname is provided
384
+ // hidden - [optional] don't enumerate to user
385
+ // locked - [optional] don't allow user delete
386
+ //
387
+ // The return value is (error, resID) tuple. Error, if non-false, is a dictionary of field
388
+ // keys and error diagnostic strings.
389
+ connector.addResource = function addResource(resource, local creds, errors, error, resID, data) {
390
+ function badField(str) { !string(str) || str.trim().length == 0 }
391
+ creds = { urlName: resource.urlName }
392
+ errors = { }
393
+ if resource.label
394
+ creds.label = resource.label
395
+ else
396
+ creds.label = resource.urlName
397
+ if badField(creds.label)
398
+ errors.label = "invalid label"
399
+ if badField(resource.urlName)
400
+ errors.urlName = "required field"
401
+ if !badField(resource.authName) {
402
+ creds.authName = resource.authName
403
+ creds.authPW = resource.authPW
404
+ if badField(resource.authPW)
405
+ errors.authPW = "required if Auth Name specified" }
406
+ if length(errors) > 0
407
+ error = errors
408
+ else {
409
+ if resource.hidden
410
+ creds.hidden = resource.hidden
411
+ if resource.locked
412
+ creds.locked = resource.locked
413
+ resID = hashResourceID(resource)
414
+ `(error, data) = connector.vault.addResource(resID, creds)
415
+ if data {
416
+ watch.notify(connClassID, { added: [resID] })
417
+ data = resID } }
418
+ list(error, data)
419
+ }
420
+
421
+ // getResource
422
+ //
423
+ // Get credentials for a named resource, matching the dictionary semantics of addResource. The
424
+ // result is a standard result tuple.
425
+ connector.getResource = function getResource(resID, local error, creds, resource) {
426
+ `(error, creds) = connector.vault.accessResource(resID)
427
+ if error
428
+ return (list(error))
429
+ resource = {
430
+ classID: connClassID
431
+ label: creds.label
432
+ }
433
+ if string(creds.urlName)
434
+ resource.urlName = creds.urlName
435
+ if string(creds.authName)
436
+ resource.authName = creds.authName
437
+ if string(creds.authPW)
438
+ resource.authPW = creds.authPW
439
+ list(false, resource)
440
+ }
441
+
442
+ // deleteResource
443
+ //
444
+ // Delete credentials for a resource
445
+ connector.deleteResource = function deleteResource(resID) {
446
+ connector.vault.deleteResource(resID)
447
+ watch.notify(connClassID, { deleted: [resID] })
448
+ list(false, { ok: true})
449
+ }
450
+
451
+ // listResources
452
+ //
453
+ // List saved resources in our database
454
+ connector.listResources = function listResources(local error, original) {
455
+ `(error, output) = connector.vault.listResources()
456
+ if error
457
+ return (list(error)) // can't access our saved resources
458
+ original = ["Host"]
459
+ if original
460
+ output = original.concat(output)
461
+ list(false, output)
462
+ }
463
+
464
+ // info
465
+ //
466
+ // Return info for a resource.
467
+ connector.info = function info(resID, local info, error, creds) {
468
+ info = {
469
+ classID: connClassID
470
+ type: "remote filesystem"
471
+ services: ["NideFS", "NideHostAPI"]
472
+ }
473
+ if resID == "Host" {
474
+ info.name = "Host"
475
+ info.type = "host filesystem"
476
+ info.locked = true
477
+ info.where = nicc.api.url
478
+ info.access = "HostFS"
479
+ } else {
480
+ `(error, creds) = connector.vault.accessResource(resID)
481
+ if creds {
482
+ if creds.label
483
+ info.name = creds.label
484
+ if creds.locked
485
+ info.locked = true
486
+ if creds.hidden
487
+ info.hidden = true
488
+ info.where = creds.urlName
489
+ }
490
+ }
491
+ list(false, info)
492
+ }
493
+
494
+ // access
495
+ //
496
+ // Return credentials for connecting to a service.
497
+ connector.access = function access(resID) {
498
+ if resID == "Host"
499
+ list(false, "HostFS")
500
+ else
501
+ connector.vault.accessResource(resID)
502
+ }
503
+
504
+ // connect
505
+ //
506
+ // Connect to the specified service.
507
+ connector.connect = function connect(resID, service, args, local error, creds, api, rootpath) {
508
+ `(error, creds) = connector.access(resID)
509
+ if !error {
510
+ if creds == "HostFS"
511
+ api = connector.api
512
+ else
513
+ `(error, api) = MakeNideAPIclient(creds.urlName) // API to remote NodeJS filesystem
514
+ }
515
+ if error
516
+ list(error)
517
+ else if service == "NideExecutor"
518
+ require("../browser/terminals.nlg").TermHost(nicc.track, api, args.0, args.1) // host executor, args: (name, workerID)
519
+ else if service == "NideHostAPI"
520
+ list(false, api) // connect to the Host API
521
+ else if service == "NideFS" {
522
+ rootpath = args.0 // connect to a NideFS filesystem
523
+ if !rootpath
524
+ return (list(Error("mandatory rootpath missing")))
525
+ psmcFsView(api, rootpath)
526
+ } else
527
+ list(Error("unsupported service", service))
528
+ }
529
+
530
+ // finis
531
+
532
+ psm.register(connClassID, connector)
533
+ connector
534
+ };
535
+
536
+
537
+ /*
538
+ * psmcMakeClientPSM
539
+ *
540
+ * Return a new client PSM with our known connectors.
541
+ *
542
+ */
543
+
544
+ function psmcMakeClientPSM(nicc, dbname, local importPSM) {
545
+ importPSM = require("../storage/psm.nlg")
546
+ App.psm = importPSM.MakePSM(dbname).1
547
+ if App.psm {
548
+ psmcFsConnector(App.psm, nicc) // HostFS access
549
+ require("../storage/dbt_pouch.nlg").DbConnector(App.psm) // Pouch databases as filesystems
550
+ }
551
+ App.psm
552
+ };
553
+
554
+
555
+ /*
556
+ * psmcInit
557
+ *
558
+ * Initialize the module.
559
+ *
560
+ */
561
+
562
+ function psmcInit(local manifest) {
563
+
564
+ manifest = `(psmcFsView, psmcFsConnector, psmcMakeClientPSM, psmcInit)
565
+
566
+ Naan.module.build(module.id, "psm_client", function(modobj, compobj) {
567
+ require("./client.nlg")
568
+ compobj.manifest = manifest
569
+ modobj.exports.MakeClientPSM = psmcMakeClientPSM
570
+ })
571
+
572
+ } ();