@platforma-sdk/workflow-tengo 1.2.6

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 (51) hide show
  1. package/README.md +6 -0
  2. package/dist/tengo/lib/assets.lib.tengo +64 -0
  3. package/dist/tengo/lib/constants.lib.tengo +75 -0
  4. package/dist/tengo/lib/exec.internal.lib.tengo +211 -0
  5. package/dist/tengo/lib/exec.lib.tengo +516 -0
  6. package/dist/tengo/lib/exec.package.lib.tengo +296 -0
  7. package/dist/tengo/lib/exec.runcmd.lib.tengo +275 -0
  8. package/dist/tengo/lib/exec.runenv.lib.tengo +221 -0
  9. package/dist/tengo/lib/exec.stream.lib.tengo +64 -0
  10. package/dist/tengo/lib/file.lib.tengo +112 -0
  11. package/dist/tengo/lib/ll.lib.tengo +233 -0
  12. package/dist/tengo/lib/maps.lib.tengo +102 -0
  13. package/dist/tengo/lib/objects.lib.tengo +22 -0
  14. package/dist/tengo/lib/oop.lib.tengo +29 -0
  15. package/dist/tengo/lib/path.lib.tengo +165 -0
  16. package/dist/tengo/lib/pframes.constants.lib.tengo +53 -0
  17. package/dist/tengo/lib/pframes.export-pcolumn.lib.tengo +47 -0
  18. package/dist/tengo/lib/pframes.lib.tengo +84 -0
  19. package/dist/tengo/lib/pframes.ll.lib.tengo +86 -0
  20. package/dist/tengo/lib/pframes.util.lib.tengo +244 -0
  21. package/dist/tengo/lib/pframes.xsv.lib.tengo +178 -0
  22. package/dist/tengo/lib/render.lib.tengo +100 -0
  23. package/dist/tengo/lib/sets.lib.tengo +93 -0
  24. package/dist/tengo/lib/slices.lib.tengo +202 -0
  25. package/dist/tengo/lib/smart.lib.tengo +1005 -0
  26. package/dist/tengo/lib/tpl.lib.tengo +535 -0
  27. package/dist/tengo/lib/tpl.state-await.lib.tengo +255 -0
  28. package/dist/tengo/lib/tpl.util.lib.tengo +19 -0
  29. package/dist/tengo/lib/validation.lib.tengo +428 -0
  30. package/dist/tengo/lib/workdir.lib.tengo +300 -0
  31. package/dist/tengo/lib/workdir.proc.lib.tengo +158 -0
  32. package/dist/tengo/lib/workdir.save.lib.tengo +158 -0
  33. package/dist/tengo/lib/workflow.bobject.lib.tengo +51 -0
  34. package/dist/tengo/lib/workflow.bquery.lib.tengo +208 -0
  35. package/dist/tengo/lib/workflow.constants.lib.tengo +8 -0
  36. package/dist/tengo/lib/workflow.context.lib.tengo +56 -0
  37. package/dist/tengo/lib/workflow.lib.tengo +298 -0
  38. package/dist/tengo/tpl/exec.create-python-venv.plj.gz +0 -0
  39. package/dist/tengo/tpl/exec.exec.plj.gz +0 -0
  40. package/dist/tengo/tpl/pframes.aggregate.plj.gz +0 -0
  41. package/dist/tengo/tpl/pframes.export-multiple-pcolumns.plj.gz +0 -0
  42. package/dist/tengo/tpl/pframes.export-pframe.plj.gz +0 -0
  43. package/dist/tengo/tpl/pframes.export-single-pcolumn.plj.gz +0 -0
  44. package/dist/tengo/tpl/pframes.import-dir.plj.gz +0 -0
  45. package/dist/tengo/tpl/pframes.import-xsv-map.plj.gz +0 -0
  46. package/dist/tengo/tpl/pframes.map-pframe.plj.gz +0 -0
  47. package/dist/tengo/tpl/workdir.save.plj.gz +0 -0
  48. package/dist/tengo/tpl/workflow.build-ctx.plj.gz +0 -0
  49. package/index.d.ts +4 -0
  50. package/index.js +13 -0
  51. package/package.json +25 -0
@@ -0,0 +1,221 @@
1
+ ll := import("@platforma-sdk/workflow-tengo:ll")
2
+ smart := import("@platforma-sdk/workflow-tengo:smart")
3
+ oop := import("@platforma-sdk/workflow-tengo:oop")
4
+ maps := import("@platforma-sdk/workflow-tengo:maps")
5
+ validation := import("@platforma-sdk/workflow-tengo:validation")
6
+ pkg := import("@platforma-sdk/workflow-tengo:exec.package")
7
+ assets := import("@platforma-sdk/workflow-tengo:assets")
8
+ render := import("@platforma-sdk/workflow-tengo:render")
9
+
10
+ _RTYPE_SAVE_RUN_ENV := { Name: "SaveRunEnv/executor", Version: "1" }
11
+ _INPUT_SETTINGS := "settings"
12
+ _INPUT_WD_IN := "workdirIn"
13
+ _INPUT_PACKAGES_MAP := "packagesMap"
14
+
15
+ _OUTPUT_RUN_ENV := "runEnv"
16
+ _OUTPUT_WD_OUT := "workdirOut"
17
+
18
+ saveBuilder := func(wd) {
19
+ self := undefined
20
+
21
+ pathsToSave := []
22
+ envType := ""
23
+
24
+ packagesMap := {}
25
+
26
+ self = {
27
+ addPath: func(path) {
28
+ validation.assertJsonSchema(path, "string", "runenv.saveBuilder.addPath: <path> must be string")
29
+
30
+ pathsToSave = append(pathsToSave, path)
31
+ return self
32
+ },
33
+
34
+ envType: func(type) {
35
+ validation.assertJsonSchema(type, "string", "runenv.saveBuilder.envType: <type> must be string")
36
+
37
+ envType = type
38
+ return self
39
+ },
40
+
41
+ /**
42
+ * Bind package to created run environment, holding it as long as run environment exists.
43
+ */
44
+ addPackage: func(key, pkgRef) {
45
+ ll.assert(!maps.containsKey(packagesMap, key), "runenv.saveBuilder.addPackage: package %q was already added to SaveRunEnv builder", key)
46
+ validation.assertJsonSchema(pkgRef, validation.reference, "runenv.saveBuilder.addPackage: <pkgRef> must be reference")
47
+
48
+ packagesMap[key] = pkgRef
49
+ return self
50
+ },
51
+
52
+ build: func() {
53
+ ll.assert(envType != "", "runenv.saveBuilder.build: environment type is not set")
54
+
55
+ envSaver := smart.ephemeralBuilder(_RTYPE_SAVE_RUN_ENV)
56
+
57
+ envSaver.getField(_INPUT_WD_IN).set(wd)
58
+
59
+ envSaver.getField(_INPUT_SETTINGS).
60
+ set(smart.createJsonResource({
61
+ paths: pathsToSave,
62
+ type: envType
63
+ }))
64
+
65
+ envSaver.getField(_INPUT_PACKAGES_MAP).
66
+ set(smart.createMapResource(packagesMap))
67
+
68
+ return oop.inherit(envSaver.lockAndBuild(), {
69
+ /**
70
+ * Run environment reference
71
+ *
72
+ * @return runEnv: smart.field - field where run environment appears
73
+ * after operation is done
74
+ */
75
+ runEnv: func() {
76
+ return envSaver.getField(_OUTPUT_RUN_ENV)
77
+ },
78
+
79
+ /**
80
+ * Working directory reference after operation is complete
81
+ *
82
+ * @return wd: smart.field - field where workdir appears after
83
+ * operation is done
84
+ */
85
+ workdir: func() {
86
+ return envSaver.getField(_OUTPUT_WD_OUT)
87
+ }
88
+ })
89
+ }
90
+ }
91
+
92
+ return self
93
+ }
94
+
95
+ pythonVenvInputSchema := {
96
+ toolset: "string",
97
+ dependencies: {"string": validation.reference},
98
+ // software: validation.reference,
99
+
100
+ pythonDescriptor: pkg.runEnvDescriptorScheme,
101
+ python: validation.reference
102
+ }
103
+
104
+ loadDependencyFiles := func(packageRef, dependencies) {
105
+ if len(dependencies) == 0 {
106
+ return {}
107
+ }
108
+
109
+ depsMap := {}
110
+
111
+ loader := pkg.assetsLoader(packageRef)
112
+ for depName, fileName in dependencies {
113
+ loader.saveFile(fileName)
114
+ }
115
+ deps := loader.load()
116
+
117
+ for depName, fileName in dependencies {
118
+ depsMap[depName] = deps.getFile(fileName)
119
+ }
120
+
121
+ return depsMap
122
+ }
123
+
124
+ pythonVenv := func() {
125
+ self := undefined
126
+
127
+ toolset := "pip"
128
+ pythonDescriptor := undefined
129
+ softwareRef := undefined
130
+ dependencies := undefined
131
+ cache := 0
132
+
133
+ self = {
134
+ useToolset: func(name) {
135
+ validation.assertJsonSchema(name, "string",
136
+ "runenv.python.useToolset: <name> must be valid name of python packaging toolset (pip, pipenv and so on)")
137
+ ll.assert(name != "", "runenv.python.useToolset: toolset name must not be empty")
138
+
139
+ toolset = name
140
+ return self
141
+ },
142
+
143
+ runEnvDescriptor: func(descriptor) {
144
+ validation.assertJsonSchema(descriptor, pkg.runEnvDescriptorScheme, "runenv.python.runEnvDescriptor: <descriptor> must be run environment specification")
145
+ ll.assert(descriptor.type == "python", "runenv.python.runEnvDescriptor: not a 'python' run environment: %q", descriptor.type)
146
+
147
+ pythonDescriptor = ll.fromStrict(descriptor)
148
+ return self
149
+ },
150
+
151
+ software: func(pkgRef) {
152
+ validation.assertJsonSchema(pkgRef, validation.reference, "runenv.python.software: <pkgRef> must be a reference to software package")
153
+
154
+ softwareRef = pkgRef
155
+ return self
156
+ },
157
+
158
+ dependencies: func(deps) {
159
+ validation.assertJsonSchema(deps, { "any": "string" }, "runenv.python.dependencies: <deps> must be map of reference file paths")
160
+
161
+ dependencies = deps
162
+ return self
163
+ },
164
+
165
+ /**
166
+ * Sets the cache time.
167
+ *
168
+ * @param time: duration - the cache time from 'times' library.
169
+ */
170
+ cache: func(time) {
171
+ ll.assert(
172
+ is_int(time),
173
+ "cache time must be an integer. " +
174
+ "Did you forget to import a standard tengo library 'time'?")
175
+ cache = time
176
+ return self
177
+ },
178
+
179
+ build: func() {
180
+ depsMap := loadDependencyFiles(softwareRef, dependencies)
181
+
182
+ archive := pkg.get(pythonDescriptor.registry, pythonDescriptor.package).archive()
183
+ pythonPkg := pkg.install(archive).package()
184
+
185
+ pyVenvInputs := {
186
+ toolset: toolset,
187
+ dependencies: smart.createMapResource(depsMap),
188
+ // software: softwareRef,
189
+ pythonDescriptor: pythonDescriptor,
190
+ python: pythonPkg
191
+ }
192
+
193
+ validation.assertJsonSchema(pyVenvInputs, pythonVenvInputSchema, "incomplete python runenv configuration")
194
+
195
+ tpl := render.create(assets.importTemplate("@platforma-sdk/workflow-tengo:exec.create-python-venv"), pyVenvInputs)
196
+
197
+ self := undefined
198
+ self = ll.toStrict(oop.inherit(tpl, {
199
+ /**
200
+ * Python virtual environment with all dependencies installed.
201
+ *
202
+ * @return venv: smart.field - a reference to the runenv with python venv inside.
203
+ */
204
+ venv: func() {
205
+ return tpl.output(_OUTPUT_RUN_ENV, cache)
206
+ }
207
+ }))
208
+
209
+ return self
210
+ }
211
+ }
212
+
213
+ return self
214
+ }
215
+
216
+ export ll.toStrict({
217
+ saveBuilder : saveBuilder,
218
+
219
+ pythonVenv : pythonVenv,
220
+ pythonVenvInputSchema : pythonVenvInputSchema
221
+ })
@@ -0,0 +1,64 @@
1
+ /**
2
+ * A library for working with streams.
3
+ */
4
+
5
+ ll := import("@platforma-sdk/workflow-tengo:ll")
6
+ smart := import("@platforma-sdk/workflow-tengo:smart")
7
+ oop := import("@platforma-sdk/workflow-tengo:oop")
8
+ file := import("@platforma-sdk/workflow-tengo:file")
9
+
10
+ _RTYPE_CREATE_STREAM := { Name: "CreateStream", Version: "2" }
11
+ _RTYPE_STREAM_MANAGER := { Name: "StreamManager", Version: "2" }
12
+
13
+ /**
14
+ * Creates a stream in the specified workdir for the given file path.
15
+ *
16
+ * @param workdir: reference - a reference to the workdir.
17
+ * @param filePath: string - the path of the file in the workdir.
18
+ * @return stream: resource - a smart.resource to the created stream with an output field.
19
+ */
20
+ _create := func(workdir, filePath) {
21
+ stream := smart.ephemeralBuilder(_RTYPE_CREATE_STREAM)
22
+ stream.getField("workdir").set(workdir)
23
+ stream.getField("filePath").setRefOrJson(filePath)
24
+
25
+ return ll.toStrict(oop.inherit(stream.lockAndBuild(), {
26
+ output: stream.outputs().stream
27
+ }))
28
+ }
29
+
30
+ /**
31
+ * Creates a special manager resource that has either a blob or a stream in the `stream` field.
32
+ *
33
+ * @param stream: reference - a reference to the stream.
34
+ * @param downloadableRef: reference - a reference to the downloadable content.
35
+ * @return manager: reference - a reference to the stream manager.
36
+ */
37
+ _manager := func(stream, downloadableRef) {
38
+ res := smart.structBuilder(_RTYPE_STREAM_MANAGER)
39
+
40
+ res.getField("downloadable").set(downloadableRef)
41
+ res.getField("stream").set(stream.output)
42
+
43
+ return res.lockAndBuild()
44
+ }
45
+
46
+ /**
47
+ * Creates a stream and manages its downloadable content.
48
+ *
49
+ * @param workdirBefore: reference - a reference to the workdir before RunCommand were executed.
50
+ * @param workdirAfter: reference - a reference to the resulted workdir field of RunCommand.
51
+ * @param filePath: string - the path of the file in the workdir.
52
+ * @return manager: reference - a reference to the stream manager.
53
+ */
54
+ create := func(workdirBefore, workdirAfter, filePath) {
55
+ stream := _create(workdirBefore, filePath)
56
+ fileFuture := workdirAfter.files.getFutureInputField(filePath)
57
+ downloadable := file.exportFile(fileFuture)
58
+
59
+ return _manager(stream, downloadable)
60
+ }
61
+
62
+ export ll.toStrict({
63
+ create: create
64
+ })
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Functions to work with blobs / files.
3
+ *
4
+ * Allowing to create resources to import files from configured storages
5
+ * as well as creation of resources to facilitate file upload from the
6
+ * users machine.
7
+ *
8
+ * This library exposes rather high level functions working with
9
+ * ImportFileHandle, encoding user intent to import a file from a pl-wide
10
+ * configured storage or to upload file from users side in a universal
11
+ * string representation.
12
+ */
13
+
14
+ ll := import("@platforma-sdk/workflow-tengo:ll")
15
+ smart := import("@platforma-sdk/workflow-tengo:smart")
16
+ validation := import("@platforma-sdk/workflow-tengo:validation")
17
+
18
+ json := import("json")
19
+
20
+ //
21
+ // Constants:
22
+ //
23
+
24
+ _RTYPE_BLOB_IMPORT_INTERNAL := { Name: "BlobImportInternal", Version: "1" }
25
+ _RTYPE_BLOB_UPLOAD := { Name: "BlobUpload", Version: "1" }
26
+ _RTYPE_BLOB_DOWNLOAD := { Name: "BlobDownload", Version: "2" }
27
+
28
+ createBlobImportInternal := func(settings) {
29
+ validation.assertJsonSchema(settings, {
30
+ "path": "string",
31
+ "storageId": "string",
32
+ "maxSpeedBytes,omitempty": "number",
33
+ "dataVersion,omitempty": "string"
34
+ })
35
+
36
+ importer := smart.structBuilder(_RTYPE_BLOB_IMPORT_INTERNAL, json.encode(settings)).lockAndBuild()
37
+
38
+ return ll.toStrict({
39
+ file: importer.getField("blob"),
40
+ handle: importer.getField("handle")
41
+ })
42
+ }
43
+
44
+ createBlobUpload := func(settings) {
45
+ validation.assertJsonSchema(settings, {
46
+ "modificationTime": "string",
47
+ "localPath": "string",
48
+ "pathSignature": "string",
49
+ "sizeBytes": "string"
50
+ })
51
+
52
+ uploader := smart.structBuilder(_RTYPE_BLOB_UPLOAD, json.encode(settings)).lockAndBuild()
53
+
54
+ return ll.toStrict({
55
+ file: uploader.getField("blob"),
56
+ handle: uploader.getField("handle")
57
+ })
58
+ }
59
+
60
+ /**
61
+ * Imports an external file into the workflow, either from pre-configured storage,
62
+ * available from the pl instance, or from the client machine via upload.
63
+ *
64
+ * @param importFileHandle string a string file import handle, in most cases obtained via the
65
+ * LS controller in UI
66
+ *
67
+ * @return a structure with two field references
68
+ * {
69
+ * file: field,
70
+ * handle: field
71
+ * }
72
+ */
73
+ importFile := func(importFileHandle) {
74
+ validation.assertJsonSchema(
75
+ importFileHandle,
76
+ `string,regex=^(upload://upload/.*|index://index/.*)`
77
+ )
78
+
79
+ url := ll.parseUrl(importFileHandle)
80
+ path := url.Path[1:] // trim "/"
81
+
82
+ settings := json.decode(path)
83
+
84
+ if url.Scheme == "upload" {
85
+ ll.assert(url.Host == "upload", "unexpected host while parsing import file handle, expected upload found ", url.Host)
86
+ return createBlobUpload(settings)
87
+ } else if url.Scheme == "index" {
88
+ ll.assert(url.Host == "index", "unexpected host while parsing import file handle, expected index found ", url.Host)
89
+ return createBlobImportInternal(settings)
90
+ } else {
91
+ ll.panic("Unknown file import handle schema: ", url.Scheme)
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Given a reference to the file, converts it into resource that can be
97
+ * downloaded from the UI side.
98
+ */
99
+ exportFile := func(blob) {
100
+ builder := smart.structBuilder(_RTYPE_BLOB_DOWNLOAD)
101
+
102
+ builder.createInputField("blob").set(blob)
103
+
104
+ downloader := builder.lockAndBuild()
105
+
106
+ return downloader.getField("downloadable")
107
+ }
108
+
109
+ export ll.toStrict({
110
+ importFile: importFile,
111
+ exportFile: exportFile
112
+ })
@@ -0,0 +1,233 @@
1
+ /* Low level pl API */
2
+
3
+ plapi := import("plapi")
4
+ json := import("json")
5
+ fmt := import("fmt")
6
+ log := import("log")
7
+ text := import("text")
8
+
9
+ /**
10
+ * Prints message to the pl log
11
+ */
12
+ print := func(txt, ...args) {
13
+ plapi.print(txt, args...)
14
+ }
15
+
16
+ /**
17
+ * Panics in a template, prints the error and
18
+ * stops the execution of the template.
19
+ * After that, the controller will set errors to outputs.
20
+ */
21
+ panic := func(msg, ...args) {
22
+ txt := fmt.sprintf(msg, args...)
23
+ plapi.print(txt)
24
+
25
+ // next statement actually terminates the execution
26
+ plapi.setTemplateError(txt)
27
+ }
28
+
29
+ /**
30
+ * Asserts a given condition and panics if it is not met
31
+ */
32
+ assert := func(condition, msg, ...args) {
33
+ if !condition {
34
+ panic("assertion error: condition failed: "+msg, args...)
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Checks whether the given object is a strict map
40
+ *
41
+ * @param obj any
42
+ * @return strict: bool - whether obj is a 'strict' map
43
+ */
44
+ isStrict := func(obj) {
45
+ return plapi.isStrictMap(obj)
46
+ }
47
+
48
+ /**
49
+ * Checks whether the given object is a map, a strict map or an immutable map.
50
+ *
51
+ * @param obj any
52
+ * @return bool whether obj is any kind of map object (map/immutable map/strict map)
53
+ */
54
+ isMap := func(obj) {
55
+ return is_map(obj) || is_immutable_map(obj) || isStrict(obj)
56
+ }
57
+
58
+ /**
59
+ * Converts 'strict' map into a normal one
60
+ *
61
+ * @param r: map|strictMap (will panic if not)
62
+ *
63
+ * @return map: std map
64
+ */
65
+ fromStrict := func(r) {
66
+ if is_map(r) {
67
+ return r
68
+ }
69
+
70
+ if !isStrict(r) {
71
+ panic("not a map", r)
72
+ }
73
+
74
+ return plapi.strictToMap(r)
75
+ }
76
+
77
+ /**
78
+ * If input is a strict map, converts it to a normal one, otherwise returns the object as is
79
+ *
80
+ * @param r: any object (possible strict map)
81
+ * @return map: tengo object
82
+ */
83
+ ensureNonStrict := func(r) {
84
+ if isStrict(r) {
85
+ return fromStrict(r)
86
+ }
87
+
88
+ return r
89
+ }
90
+
91
+ /**
92
+ * Converts map into a 'strict' map, which will panic on
93
+ * access to non-existing elements.
94
+ *
95
+ * @param m: map|strictMap
96
+ *
97
+ * @return strict: strictMap
98
+ */
99
+ toStrict := func(v) {
100
+ if isStrict(v) {
101
+ return v
102
+ }
103
+
104
+ if(!is_map(v)) {
105
+ panic("toStrict(<v>): <v> is not a map", v)
106
+ }
107
+ return plapi.mapToStrict(v)
108
+ }
109
+
110
+ /**
111
+ * Creates a field Id struct from given resource id and field name
112
+ */
113
+ fieldId := func(resourceId, fieldName) {
114
+ return plapi.newFieldID(resourceId, fieldName)
115
+ }
116
+
117
+ /**
118
+ * Returns current template renderer
119
+ */
120
+ getCurrentTemplateRenderer := func() {
121
+ return plapi.getTemplate()
122
+ }
123
+
124
+ /**
125
+ * @return isInit: bool - true when current template is initializing (executed for the first time)
126
+ */
127
+ isInitializing := func() {
128
+ return plapi.isInit
129
+ }
130
+
131
+ /**
132
+ * Get the list of executors available in current Platforma installation.
133
+ *
134
+ * @return executors: []string - list of executors, say ['executor', 'docker', ...]
135
+ */
136
+ getExecutorsList := func() {
137
+ return plapi.getExecutors()
138
+ }
139
+
140
+ /**
141
+ * Joins path elements into a single path.
142
+ *
143
+ * @param elems: ...string - any number of elements.
144
+ */
145
+ filepathJoin := func(...elems) {
146
+ return plapi.filepathJoin(elems...)
147
+ }
148
+
149
+ /**
150
+ * Like filepathJoin, joins elements to a single path,
151
+ * but can be used safely in regexps.
152
+ *
153
+ * @param elems: ...string - any number of elements.
154
+ */
155
+ filepathRegexpJoin := func(...elems) {
156
+ escapedSeparator := plapi.regexpQuoteMeta(plapi.osSeparator)
157
+ return text.join(elems, escapedSeparator)
158
+ }
159
+
160
+ /**
161
+ * Joins elements of the filepath and canonizes it, i.e.
162
+ * semantically resolves ../ and ./ and changes slash
163
+ * to a pathSeparator.
164
+ *
165
+ * @param elems: ...string - any number of elements.
166
+ */
167
+ filepathCanonize := func(...elem) {
168
+ return plapi.filepathCanonize(elem...)
169
+ }
170
+
171
+ /**
172
+ * Returns a path separator. "/" on Unix-like systems, "\\" on Windows.
173
+ *
174
+ * @return separator: string
175
+ */
176
+ pathSeparator := plapi.osSeparator
177
+
178
+ /**
179
+ * Parses URL and returns a structure containing separe parts of the URL.
180
+ *
181
+ * The general form represented is:
182
+ *
183
+ * [scheme:][//[userinfo@]host][/]path[?query][#fragment]
184
+ *
185
+ * URLs that do not start with a slash after the scheme are interpreted as:
186
+ *
187
+ * scheme:opaque[?query][#fragment]
188
+ *
189
+ * Returns the floowing structure:
190
+ *
191
+ * {
192
+ * Scheme: string,
193
+ * Host: string,
194
+ * Port: number,
195
+ * Path: string,
196
+ * RawPath: string,
197
+ * Query: string
198
+ * }
199
+ *
200
+ * @param url: string with the url
201
+ * @return url structure: (see above)
202
+ */
203
+ parseUrl := func(url) {
204
+ return plapi.urlParse(url)
205
+ }
206
+
207
+ /**
208
+ * Returns current execution context, which cab be used is a simple kv-store associated with the renderer instance.
209
+ */
210
+ getCtx := func() {
211
+ return plapi.getCtx()
212
+ }
213
+
214
+ export toStrict({
215
+ print: print,
216
+ panic: panic,
217
+ assert: assert,
218
+ isStrict: isStrict,
219
+ isMap: isMap,
220
+ fromStrict: fromStrict,
221
+ ensureNonStrict: ensureNonStrict,
222
+ toStrict: toStrict,
223
+ fieldId: fieldId,
224
+ getCurrentTemplateRenderer: getCurrentTemplateRenderer,
225
+ isInitializing: isInitializing,
226
+ getExecutorsList: getExecutorsList,
227
+ filepathJoin: filepathJoin,
228
+ filepathRegexpJoin: filepathRegexpJoin,
229
+ pathSeparator: pathSeparator,
230
+ filepathCanonize: filepathCanonize,
231
+ parseUrl: parseUrl,
232
+ getCtx: getCtx
233
+ })