@naanlang/naan 1.0.7 → 1.0.8

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 (36) hide show
  1. package/LICENSE.md +3 -4
  2. package/README.md +20 -2
  3. package/bin/index.js +2 -2
  4. package/dist/env_web.js +86 -17
  5. package/dist/naan.min.js +7 -7
  6. package/frameworks/browser/browser.nlg +26 -2
  7. package/frameworks/browser/sworker.js +17 -17
  8. package/frameworks/browser/workers.nlg +7 -0
  9. package/frameworks/client/psm_client.nlg +1 -0
  10. package/frameworks/common/common.nlg +33 -5
  11. package/frameworks/node/filesystem.nlg +32 -26
  12. package/frameworks/node/gitter.nlg +9 -4
  13. package/frameworks/node/https_request.nlg +19 -14
  14. package/frameworks/project/build.nlg +177 -68
  15. package/frameworks/project/projects.nlg +1 -1
  16. package/frameworks/running/running.nlg +32 -10
  17. package/frameworks/storage/psm.nlg +20 -4
  18. package/lib/browser/env_web.js +90 -21
  19. package/lib/core/naanlib.js +7 -7
  20. package/package.json +1 -1
  21. package/plugins/serviceAws/aws/aws-sdk-node.min.js +1 -1
  22. package/plugins/serviceAws/aws/aws-sdk.min.js +1 -1
  23. package/plugins/serviceAws/aws/lambda_ws_init.nlg +2 -1
  24. package/plugins/serviceAws/aws_dynamo.nlg +27 -20
  25. package/plugins/serviceAws/aws_dynextra.nlg +110 -5
  26. package/plugins/serviceAws/aws_lambda.nlg +4 -8
  27. package/plugins/serviceAws/aws_sqs.nlg +113 -0
  28. package/plugins/serviceAws/serviceAws.nlg +1 -1
  29. package/plugins/serviceYC/generic_api.yaml +36 -0
  30. package/plugins/serviceYC/naanide-relay-index.js +148 -0
  31. package/plugins/serviceYC/serviceYC.nlg +59 -0
  32. package/plugins/serviceYC/yc_function.nlg +161 -0
  33. package/test/test_01_core.nlg +2 -2
  34. package/test/test_02_context.nlg +2 -2
  35. package/test/test_05_strings.nlg +11 -1
  36. package/test/test_06_lingoparse.nlg +43 -14
@@ -22,7 +22,8 @@ function initPreload() {
22
22
  Naan.module.chns("Play")
23
23
  sudo(putproc(exception, false)) // ### need a better mechanism
24
24
  };
25
- initPreload();
25
+ if symbol(NideBuild)
26
+ initPreload(); // not building
26
27
 
27
28
 
28
29
  /*
@@ -652,7 +652,7 @@ closure DynaTable(dyna, tablename, local table) {
652
652
  // Ensure that the table is ready before executing an operation. This returns an error tuple or
653
653
  // false to proceed.
654
654
  //
655
- function preflightError(op) {
655
+ function preflightError(op, local result) {
656
656
  if !dyna.aws
657
657
  return (list(Error("DynaTable.".concat(op, ": not logged into AWS"))))
658
658
  if !table.hashKey {
@@ -683,7 +683,7 @@ closure DynaTable(dyna, tablename, local table) {
683
683
  //
684
684
  // Get a record from the table with the specified hash value, and optional range value.
685
685
  //
686
- table.getRecord = closure getRecord(hashValue, rangeValue, local result, params, pending) {
686
+ table.getRecord = closure getRecord(hashValue, rangeValue, local params, pending) {
687
687
  if preflightError(this)
688
688
  return
689
689
  params = {
@@ -708,7 +708,7 @@ closure DynaTable(dyna, tablename, local table) {
708
708
  //
709
709
  // Put a record in the table, replacing any existing record with the same key.
710
710
 
711
- table.putRecord = closure putRecord(record, local result, params, pending) {
711
+ table.putRecord = closure putRecord(record, local params, pending) {
712
712
  if preflightError(this)
713
713
  return
714
714
  params = {
@@ -737,13 +737,15 @@ closure DynaTable(dyna, tablename, local table) {
737
737
  // set: [`(attribute, value)] // set attributes to values
738
738
  // sum: [`(attribute, value)] // attributes += values
739
739
  // diff: [`(attribute, value)] // attributes -= values
740
+ // add: [`(attribute, value)] // ADD(attributes, values) -- attrib need not exist
740
741
  // remove: [attribute] // remove attributes from the record
741
742
  // return: "all_old" | "all_new" | "updated_old" | "updated_new"
742
743
  // // return the record as chosen, otherwise { }
743
744
  // }
744
745
  // The result is a standard result tuple `(error, record).
745
746
 
746
- table.updateRecord = closure updateRecord(hashValue, rangeValue, options, local error, result, params, actions, pending) {
747
+ table.updateRecord = closure updateRecord(hashValue, rangeValue, options,
748
+ local error, params, actions, pending) {
747
749
  if preflightError(this)
748
750
  return
749
751
  params = {
@@ -752,13 +754,10 @@ closure DynaTable(dyna, tablename, local table) {
752
754
  params.Key = makeDynKey(list(hashValue, rangeValue))
753
755
  if options.condition {
754
756
  `(error) = dyna.conv.createKeyExpression(params, {
755
- KeyConditionExpression: {
756
- key: table.hashKey
757
- "=": hashValue
758
- }
757
+ ConditionExpression: options.condition
759
758
  })
760
759
  if error
761
- return (list(Error("table.updateRecord:", error)))
760
+ return (list(Error("table.updateRecord condition:", error)))
762
761
  }
763
762
  dyna.conv.createUpdateExpression(params, options)
764
763
  if options.return {
@@ -795,7 +794,8 @@ closure DynaTable(dyna, tablename, local table) {
795
794
  // }
796
795
 
797
796
 
798
- table.deleteRecord = closure deleteRecord(hashValue, rangeValue, options, local result, params, pending) {
797
+ table.deleteRecord = closure deleteRecord(hashValue, rangeValue, options,
798
+ local params, pending) {
799
799
  if preflightError(this)
800
800
  return
801
801
  params = {
@@ -804,13 +804,10 @@ closure DynaTable(dyna, tablename, local table) {
804
804
  params.Key = makeDynKey(list(hashValue, rangeValue))
805
805
  if options.condition {
806
806
  `(error) = dyna.conv.createKeyExpression(params, {
807
- KeyConditionExpression: {
808
- key: table.hashKey
809
- "=": hashValue
810
- }
807
+ ConditionExpression: options.condition
811
808
  })
812
809
  if error
813
- return (list(Error("table.deleteRecord:", error)))
810
+ return (list(Error("table.deleteRecord condition:", error)))
814
811
  }
815
812
  if options.return {
816
813
  params.ReturnValues = {
@@ -871,7 +868,7 @@ closure DynaTable(dyna, tablename, local table) {
871
868
  //
872
869
 
873
870
  table.queryRecords = closure queryRecords(hashValue, options
874
- local error, result, params, hashKey, op, expr, output, error)
871
+ local error, params, hashKey, op, expr, output, error)
875
872
  {
876
873
  if preflightError(this)
877
874
  return
@@ -940,7 +937,7 @@ closure DynaTable(dyna, tablename, local table) {
940
937
  //
941
938
 
942
939
  table.scanRecords = closure scanRecords(options
943
- local result, params, op, expr, output, error)
940
+ local params, op, expr, output, error)
944
941
  {
945
942
  if preflightError(this)
946
943
  return
@@ -1044,9 +1041,9 @@ closure DynamoDB(local dyna) {
1044
1041
  dynexBatchGetRecords(dyna, request, options)
1045
1042
  }
1046
1043
 
1047
- // dynexBatchWriteRecords
1044
+ // batchWriteRecords
1048
1045
  //
1049
- dyna.batchWriteRecords = function batchWriteRecords(request, options) {
1046
+ dyna.batchWriteRecords = function loadBatchWriteRecords(request, options) {
1050
1047
  require("./aws_dynextra.nlg")
1051
1048
  dyna.batchWriteRecords = function bwr(request, options) {
1052
1049
  dynexBatchWriteRecords(dyna, request, options)
@@ -1054,7 +1051,7 @@ closure DynamoDB(local dyna) {
1054
1051
  dynexBatchWriteRecords(dyna, request, options)
1055
1052
  }
1056
1053
 
1057
- // dynexTransactGetRecords
1054
+ // transactGetRecords
1058
1055
  //
1059
1056
  dyna.transactGetRecords = function loadTransactGetRecords(request, options) {
1060
1057
  require("./aws_dynextra.nlg")
@@ -1064,6 +1061,16 @@ closure DynamoDB(local dyna) {
1064
1061
  dynexTransactGetRecords(dyna, request, options)
1065
1062
  }
1066
1063
 
1064
+ // transactWriteRecords
1065
+ //
1066
+ dyna.transactWriteRecords = function loadTransactWriteRecords(request, options) {
1067
+ require("./aws_dynextra.nlg")
1068
+ dyna.transactWriteRecords = function tgr(request, options) {
1069
+ dynexTransactWriteRecords(dyna, request, options)
1070
+ }
1071
+ dynexTransactWriteRecords(dyna, request, options)
1072
+ }
1073
+
1067
1074
  // finis
1068
1075
  dyna
1069
1076
  }
@@ -228,7 +228,6 @@ closure dynexBatchWriteRecords(dyna, request,
228
228
  };
229
229
 
230
230
 
231
-
232
231
  /*
233
232
  * dynexTransactGetRecords
234
233
  *
@@ -257,10 +256,10 @@ closure dynexTransactGetRecords(dyna, request,
257
256
  for titem in request { // preflight all tables
258
257
  tname = titem.table.name
259
258
  if index[tname]
260
- return (Error("DynaTable.batchGetRecords: duplicate table in request:", tname))
259
+ return (Error("DynaTable.transactGetRecords: duplicate table in request:", tname))
261
260
  `(error) = titem.table.info()
262
261
  if error
263
- return (Error("DynaTable.batchGetRecords: table", tname, ":", error))
262
+ return (Error("DynaTable.transactGetRecords: table", tname, ":", error))
264
263
  titem.data = []
265
264
  index[tname] = titem
266
265
  }
@@ -272,7 +271,7 @@ closure dynexTransactGetRecords(dyna, request,
272
271
  params.TransactItems.push({
273
272
  Get: {
274
273
  TableName: tname
275
- Key: makeDynKey(titem.keys.shift())
274
+ Key: titem.table.makeDynKey(titem.keys.shift())
276
275
  }
277
276
  })
278
277
  }
@@ -297,6 +296,111 @@ closure dynexTransactGetRecords(dyna, request,
297
296
  };
298
297
 
299
298
 
299
+ /*
300
+ * dynexTransactWriteRecords
301
+ *
302
+ * column positioning: // // !
303
+ * Write records to one or more tables using arrays of keys as a single transaction. The result is an
304
+ * error if anything failed or generic success if it worked. The request layout is as follows. Note
305
+ * that unlike the other dynex* calls, each table/key/operation item is separately specified.
306
+ *
307
+ * [
308
+ * {
309
+ * table: <DynaTable object> // table to act upon
310
+ * key: <hash-range tuple>
311
+ * put: {
312
+ * condition: <range-expression> // conditional expression
313
+ * item: <record-to-put>
314
+ * }
315
+ * update: {
316
+ * condition: <range-expression> // conditional expression
317
+ * set: [`(attribute, value)] // set attributes to values
318
+ * sum: [`(attribute, value)] // attributes += values
319
+ * diff: [`(attribute, value)] // attributes -= values
320
+ * add: [`(attribute, value)] // ADD(attributes, values) -- attrib need not exist
321
+ * remove: [attribute] // remove attributes from the record
322
+ * }
323
+ * delete: {
324
+ * condition: <range-expression> // conditional expression
325
+ * }
326
+ * check: {
327
+ * condition: <range-expression> // conditional expression
328
+ * return: "all_old" // optionally return record if condition fails
329
+ * }
330
+ * }
331
+ * { <next-item> }
332
+ * ]
333
+ * This returns a standard result tuple `(error, result). An error is only reported if we are
334
+ * unable to complete all operations.
335
+ *
336
+ */
337
+
338
+ closure dynexTransactWriteRecords(dyna, request,
339
+ local index, titem, tname, error, params, opset, spec, op, pending, response) {
340
+ if !dyna.aws
341
+ return (list(Error("DynaTable.transactWriteRecords: not logged into AWS")))
342
+ request = new(request) // allow local modifications
343
+ index = { }
344
+ for titem in request { // preflight all tables
345
+ tname = titem.table.name
346
+ if !index[tname] {
347
+ `(error) = titem.table.info()
348
+ if error
349
+ return (Error("DynaTable.transactWriteRecords: table", tname, ":", error))
350
+ index[tname] = titem
351
+ }
352
+ }
353
+ params = {
354
+ TransactItems: []
355
+ }
356
+ for titem in request {
357
+ opset = {
358
+ TableName: titem.table.name
359
+ Key: titem.table.makeDynKey(titem.key)
360
+ }
361
+ if titem.check {
362
+ spec = titem.check
363
+ op = `ConditionCheck
364
+ if spec.return
365
+ opset.ReturnValues = "ALL_OLD"
366
+ } else if titem.put {
367
+ spec = titem.put
368
+ op = `Put
369
+ opset.Item = dyna.conv.recordNaanToDyn(spec.item)
370
+ opset.Key = undefined // key must be in item
371
+ } else if titem.update {
372
+ spec = titem.update
373
+ op = `Update
374
+ dyna.conv.createUpdateExpression(opset, spec)
375
+ } else if titem.delete {
376
+ spec = titem.delete
377
+ op = `Delete
378
+ }
379
+ if spec.condition {
380
+ `(error) = dyna.conv.createKeyExpression(opset, {
381
+ ConditionExpression: spec.condition
382
+ })
383
+ if error
384
+ return (list(Error("DynaTable.transactWriteRecords condition:", error)))
385
+ }
386
+ titem = { }
387
+ titem[op] = opset
388
+ params.TransactItems.push(titem)
389
+ }
390
+ pending = new(nonce)
391
+ dyna.aws.transactWriteItems(params, function(err, data) {
392
+ if err
393
+ debuglog("aws.transactWriteItems failed", err)
394
+ pending.signal(list(err, data))
395
+ })
396
+ `(error, response) = pending.wait()
397
+ if error
398
+ list(error)
399
+ else
400
+ list(false, response)
401
+ };
402
+
403
+
300
404
  /*
301
405
  * dynexInit
302
406
  *
@@ -305,7 +409,8 @@ closure dynexTransactGetRecords(dyna, request,
305
409
  */
306
410
 
307
411
  function dynexInit(local manifest) {
308
- manifest = `(dynexBatchGetRecords, dynexBatchWriteRecords, dynexTransactGetRecords, dynexInit)
412
+ manifest = `(dynexBatchGetRecords, dynexBatchWriteRecords, dynexTransactGetRecords,
413
+ dynexTransactWriteRecords, dynexInit)
309
414
 
310
415
  Naan.module.build(module.id, "aws_dynextra", function(modobj, compobj) {
311
416
  compobj.manifest = manifest
@@ -46,10 +46,8 @@ closure Lambda(local lamb) {
46
46
  params.Qualifier = qualifier
47
47
  pending = new(nonce)
48
48
  lamb.aws.getFunction(params, function(error, data) {
49
- if error {
50
- lambdaError = error
51
- debuglog("aws.getFunction failed", error)
52
- }
49
+ if error
50
+ ErrorDebuglog("aws.getFunction failed", error)
53
51
  pending.signal(list(error, data))
54
52
  })
55
53
  pending.wait()
@@ -69,10 +67,8 @@ closure Lambda(local lamb) {
69
67
  }
70
68
  pending = new(nonce)
71
69
  lamb.aws.updateFunctionCode(params, function(error, data) {
72
- if error {
73
- lambdaError = error
74
- debuglog("aws.updateFunctionCode failed", error)
75
- }
70
+ if error
71
+ ErrorDebuglog("aws.updateFunctionCode failed", error)
76
72
  pending.signal(list(error, data))
77
73
  })
78
74
  pending.wait()
@@ -0,0 +1,113 @@
1
+ /*
2
+ * aws_sqs.nlg
3
+ * serviceAws
4
+ *
5
+ * Access to SQS (Simple Queue Service) for AWS.
6
+ *
7
+ * column positioning: // // !
8
+ *
9
+ * Copyright (c) 2023 by Richard C. Zulch
10
+ *
11
+ */
12
+
13
+
14
+ /*
15
+ * SqsMQ
16
+ *
17
+ * SqsMQ, a container for holding the queue name and sending messages to it.
18
+ *
19
+ */
20
+
21
+ closure SqsMQ(sqs, queueUrl, local sqsq) {
22
+ sqsq = new(object, this)
23
+
24
+ //
25
+ // sendMessage
26
+ //
27
+ sqsq.sendMessage = closure sendMessage(msgBody) {
28
+ sqs.sendMessage(queueUrl, msgBody)
29
+ }
30
+
31
+ // finis
32
+ sqsq
33
+ }
34
+
35
+
36
+ /*
37
+ * SQS
38
+ *
39
+ * SQS service functions.
40
+ *
41
+ */
42
+
43
+ closure SQS(local sqs) {
44
+ sqs = new(object, this)
45
+
46
+ //
47
+ // login
48
+ //
49
+ sqs.login = closure login(creds, local params) {
50
+ if !awsSDK
51
+ return (list(Error("SQS.login: no AWS SDK available")))
52
+ params = {
53
+ }
54
+ if creds {
55
+ params.region = creds.region
56
+ params.credentials = {
57
+ accessKeyId: creds.keyID
58
+ secretAccessKey: creds.keySecret
59
+ }
60
+ if creds.sqs_endpoint
61
+ params.endpoint = creds.sqs_endpoint
62
+ }
63
+ sqs.aws = xnew(awsSDK.SQS, params)
64
+ `(false, { ok: true })
65
+ }
66
+
67
+ //
68
+ // sendMessage
69
+ //
70
+ sqs.sendMessage = closure sendMessage(queueUrl, msgBody, local params, pending) {
71
+ debuglog("SQS.sendMessage:", awsSDK, sqs.aws, sqs.aws.sendMessage)
72
+ params = {
73
+ MessageBody: msgBody
74
+ QueueUrl: queueUrl
75
+ }
76
+ pending = new(nonce)
77
+ sqs.aws.sendMessage(params, function(error, data) {
78
+ if error
79
+ ErrorDebuglog("aws.sendMessage failed", error)
80
+ pending.signal(list(error, data))
81
+ })
82
+ pending.wait()
83
+ }
84
+
85
+ //
86
+ // mq
87
+ //
88
+ sqs.mq = function(queueUrl) {
89
+ SqsMQ(sqs, queueUrl)
90
+ }
91
+
92
+ // finis
93
+ sqs
94
+ }
95
+
96
+
97
+ /*
98
+ * sqsInit
99
+ *
100
+ * Initialize the SQS module.
101
+ *
102
+ */
103
+
104
+ function sqsInit(local manifest) {
105
+ manifest = `(SqsMQ, SQS, sqsInit)
106
+
107
+ Naan.module.build(module.id, "aws_sqs", function(modobj, compobj) {
108
+ require("./serviceAws.nlg")
109
+ compobj.manifest = manifest
110
+ modobj.exports.SQS = SQS
111
+ })
112
+
113
+ } ();
@@ -27,7 +27,7 @@ function sawsInit(local manifest) {
27
27
  require("./aws_utils.nlg")
28
28
  function sawsPostload() {
29
29
  if js.g
30
- awsSDK = js.r(JSpath.join(js.d, module.locpath, "./aws/aws-sdk-node.min.js"))
30
+ awsSDK = js.r(JSpath.resolve(js.d, module.locpath, "aws/aws-sdk-node.min.js"))
31
31
  else
32
32
  awsSDK = JsLoadScript(JSpath.join(module.locpath, "./aws/aws-sdk.min.js"), "awsSdk")
33
33
  module.exports.awsSDK = awsSDK
@@ -0,0 +1,36 @@
1
+ openapi: 3.0.0
2
+ info:
3
+ title: tutor-backend API
4
+ version: 1.0.0
5
+ servers:
6
+ - url: https://d5dhrgakpe39e11lqefr.apigw.yandexcloud.net
7
+ paths:
8
+ /{proxy+}:
9
+ options:
10
+ parameters:
11
+ - name: proxy
12
+ in: path
13
+ required: true
14
+ schema:
15
+ type: string
16
+ x-yc-apigateway-integration:
17
+ type: dummy
18
+ http_code: 200
19
+ http_headers:
20
+ Access-Control-Allow-Headers: "*"
21
+ Access-Control-Allow-Methods: "DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT"
22
+ Access-Control-Allow-Origin: "*"
23
+ content:
24
+ "application/json": ""
25
+ x-yc-apigateway-any-method:
26
+ parameters:
27
+ - name: proxy
28
+ in: path
29
+ required: true
30
+ schema:
31
+ type: string
32
+ x-yc-apigateway-integration:
33
+ type: cloud_functions
34
+ function_id: d4ehjjcfk8ffe43o5t7j
35
+ tag: $latest
36
+ service_account_id: ajeuftvbtshn348ert80
@@ -0,0 +1,148 @@
1
+ /*
2
+ * index.js
3
+ * naanide-relay
4
+ *
5
+ * Yandex Cloud Function for proxying API requests from NaanIDE in the browser.
6
+ *
7
+ * This function acts as a relay (mitm) proxy so that a browser may access Yandex Cloud APIs without
8
+ * needing a transient access token and without CORS problems. Security is provided by a pre-shared
9
+ * static key, configured as an environment variable in the YCF and known to the browser code.
10
+ *
11
+ * The request to the proxy should be precisely what is intended for the target API, except that the
12
+ * following headers should be included:
13
+ *
14
+ * x-naanide-auth: <pre-shared-key>
15
+ * x-naanide-ep: <target-url-with-path-and-query-variables>
16
+ * x-naanide-hdrs: <optional headers>
17
+ *
18
+ * The response in the browser contains some remapped headers, but is otherwise the API's response.
19
+ *
20
+ * Assuming the pre-shared key is "foo", the following gets a list of YDB databases in a folder:
21
+
22
+ curl -H "x-naanide-auth: foo" \
23
+ -H "x-naanide-ep: https://ydb.api.cloud.yandex.net/ydb/v1/databases?folderId=b1gjjahqm5u9tjolom9l" \
24
+ 'https://functions.yandexcloud.net/d4e5gicpajcqdbj91jt8'
25
+
26
+ *
27
+ * column positioning: // // !
28
+ *
29
+ * Copyright (c) 2022 by Richard C. Zulch
30
+ *
31
+ */
32
+
33
+
34
+ /*
35
+ * index.handler
36
+ *
37
+ * Forward a request and respond with the result.
38
+ *
39
+ */
40
+
41
+ module.exports.handler = async function (event, context) {
42
+ "use strict";
43
+ const authorizationKey = process.env.NAANIDE_AUTH_KEY;
44
+
45
+ //
46
+ // OPTIONS request
47
+ //
48
+ // Allow our headers for CORS
49
+ //
50
+
51
+ if (event.httpMethod == "OPTIONS")
52
+ return {
53
+ statusCode: 200,
54
+ headers: {
55
+ "Access-Control-Allow-Headers": "*"
56
+ }
57
+ };
58
+
59
+ //
60
+ // Failed authentication
61
+ //
62
+
63
+ if (event.headers["X-Naanide-Auth"] != authorizationKey) {
64
+ return {
65
+ statusCode: 401
66
+ };
67
+ }
68
+
69
+ //
70
+ // Authenticated
71
+ //
72
+
73
+ let https = require("https");
74
+ let url = event.headers["X-Naanide-Ep"];
75
+ let headers = event.headers["X-Naanide-Hdrs"];
76
+ if (headers) {
77
+ try {
78
+ headers = JSON.parse(headers);
79
+ } catch (e) {
80
+ console.log("X-Naanide-Hdrs parse error", e);
81
+ headers = false;
82
+ }
83
+ }
84
+ if (!headers)
85
+ headers = { };
86
+ if (!headers[Object.keys(headers).find(key => key.toLowerCase() === "authorization")])
87
+ headers.Authorization = context.token.token_type.concat(" ", context.token.access_token);
88
+ let options = {
89
+ method: event.httpMethod,
90
+ headers: headers
91
+ };
92
+ let chunks = [];
93
+ let content = false;
94
+ let finalResponse = {
95
+ statusCode: 500
96
+ };
97
+
98
+ //
99
+ // forward_request
100
+ //
101
+ async function forward_request() {
102
+ return new Promise(function(resolve, reject) {
103
+ let req = https.request(url, options, function(resp) {
104
+ finalResponse.statusCode = resp.statusCode;
105
+ // data event
106
+ resp.on("data", function (chunk) {
107
+ chunks.push(chunk);
108
+ });
109
+ // end event
110
+ resp.on("end", function () {
111
+ if (resp.complete)
112
+ {
113
+ let content = Buffer.concat(chunks);
114
+ let contentType = resp.headers["content-type"];
115
+ finalResponse.body = content.toString();
116
+ if (resp.headers["x-request-id"]) {
117
+ resp.headers["x-upstream-request-id"] = resp.headers["x-request-id"];
118
+ delete resp.headers["x-request-id"];
119
+ }
120
+ finalResponse.headers = resp.headers;
121
+ }
122
+ else {
123
+ console.log("request terminated before full response received");
124
+ finalResponse.statusCode = 502;
125
+ }
126
+ resolve();
127
+ });
128
+ });
129
+ // error event
130
+ req.on("error", function (err) {
131
+ console.log("upstream request error:", err);
132
+ finalResponse.statusCode = 502;
133
+ reject(err);
134
+ });
135
+ console.log("event.body", event.body, event.isBase64Encoded);
136
+ if (event.body) {
137
+ if (event.isBase64Encoded)
138
+ req.write(decodeURIComponent(escape(atob(event.body))));
139
+ else
140
+ req.write(event.body);
141
+ }
142
+ req.end();
143
+ });
144
+ }
145
+
146
+ await forward_request();
147
+ return finalResponse;
148
+ }
@@ -0,0 +1,59 @@
1
+ /*
2
+ * serviceYC.nlg
3
+ * serviceYC
4
+ *
5
+ * ServiceYC module configuration and management for browser and NodeJS.
6
+ *
7
+ * column positioning: // // !
8
+ *
9
+ * Copyright (c) 2022 by Richard C. Zulch
10
+ *
11
+ */
12
+
13
+
14
+ /*
15
+ * YcRequest
16
+ *
17
+ * Make a request to a Yandex Cloud API using a Yandex Cloud Function acting as a relay proxy.
18
+ * This works like frameworks/browser/HttpsApiRequest and frameworks/node/HttpsApiRequest except
19
+ * that it takes a credentials argument for access to the relay. Technically this is not required
20
+ * when we are going from node, but I'm keeping it for consistency.
21
+ *
22
+ */
23
+
24
+ closure YcRequest(url, creds, options, local headers) {
25
+ if !options
26
+ options = { }
27
+ else
28
+ options = new(options)
29
+ headers = [
30
+ list("x-naanide-auth", creds.relayAuthKey)
31
+ list("x-naanide-ep", url)
32
+ ]
33
+ if options.headers
34
+ headers.push(list("x-naanide-hdrs", options.headers.join("\n")))
35
+ options.headers = headers
36
+ https.HttpsApiRequest(creds.relayURL, options)
37
+ };
38
+
39
+
40
+ /*
41
+ * seycInit
42
+ *
43
+ * Initialize the YC module.
44
+ *
45
+ */
46
+
47
+ function seycInit(local manifest) {
48
+ manifest = `(YcRequest, seycInit)
49
+
50
+ Naan.module.build(module.id, "serviceYC", function(modobj, compobj) {
51
+ compobj.manifest = manifest
52
+ require("frameworks/common").LiveImport()
53
+ if js.g
54
+ https = require("frameworks/node/https_request.nlg")
55
+ else
56
+ https = require("frameworks/browser/https_request.nlg")
57
+ module.exports.YcRequest = YcRequest
58
+ })
59
+ } ();