@accordproject/concerto-util 1.2.2-20211130213656

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.
package/LICENSE ADDED
@@ -0,0 +1,11 @@
1
+ Licensed under the Apache License, Version 2.0 (the "License");
2
+ you may not use this file except in compliance with the License.
3
+ You may obtain a copy of the License at
4
+
5
+ http://www.apache.org/licenses/LICENSE-2.0
6
+
7
+ Unless required by applicable law or agreed to in writing, software
8
+ distributed under the License is distributed on an "AS IS" BASIS,
9
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+ See the License for the specific language governing permissions and
11
+ limitations under the License.
package/README.md ADDED
@@ -0,0 +1,13 @@
1
+ # Concerto Core
2
+
3
+ Main library for Concerto models, model manager, JSON instance validation and serialization.
4
+
5
+ # Installation
6
+
7
+ ```
8
+ npm install @accordproject/concerto-core --save
9
+ ```
10
+
11
+ ## License <a name="license"></a>
12
+ Accord Project source code files are made available under the Apache License, Version 2.0 (Apache-2.0), located in the LICENSE file. Accord Project documentation files are made available under the Creative Commons Attribution 4.0 International License (CC-BY-4.0), available at http://creativecommons.org/licenses/by/4.0/.
13
+
package/changelog.txt ADDED
@@ -0,0 +1,109 @@
1
+ #
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+ #
14
+ # This is the changelog for Hyperledger Concerto. It lists all significant changes to
15
+ # functionality and public API.
16
+ #
17
+ # The most recent entry in the changelog should be at the top of this file
18
+ # and must follow the format: Version <number> {public api digest} <date>. The version
19
+ # number must match that specified in package.json. The public api digest is computed
20
+ # and validated using ./scripts/api-changelog.sh
21
+ #
22
+ # Any changes to the public API must have an associated changelog entry.
23
+ #
24
+ # Note that the latest public API is documented using JSDocs and is available in api.txt.
25
+ #
26
+
27
+ Version 1.2.2 {a17601f3c2c7e81f521c8779093b03fa} 2021-11-24
28
+ - Remove custom instanceof and add methods to check runtime type
29
+ - Remove support for Node 12
30
+ - Generate Typescript definitions from JSDoc
31
+ - Parser directly constructs metamodel instance
32
+ - Convert MetaModel to a class for Typescript + Webpack compatability
33
+ - Update Acorn to latest and refactor the JavaScript parser so we can use static class members
34
+
35
+ Version 1.2.2 {b19318bb094e5da7bdff192cf9a3b4f2} 2021-08-12
36
+ - Fixes to metamodel, including terminology changes
37
+ - Ability to roundtrip model manager to metamodel
38
+ - Expose name resolution to MetaModel API
39
+
40
+ Version 1.1.2 {2c9512d9d90bde289b47942937d252ca} 2021-08-12
41
+ - Add Factory.newId for creating new unique IDs
42
+
43
+ Version 1.1.0 {16fb2d5684ec917532a19428c74f1ebf} 2021-07-13
44
+ - Add support for Concerto metamodel with import/export to CTO
45
+
46
+ Version 1.0.3 {1fe469fe1a79af5d5a4f5ec7dee6b7d4} 2021-06-25
47
+ - Aligns JSDoc and the TypeScript interface
48
+
49
+ Version 1.0.0-alpha.8 {08b0c809336354e7d1b17a2e44fca8b0} 2021-04-22
50
+ - Add datetimeutil & Consolidate UTC offset support
51
+ - Delete Concerto.instanceOf replace by ModelManager.derivesFrom
52
+
53
+ Version 1.0.0-alpha.7 {aec0f0d4e25be4dab03d6b94be60767b} 2021-04-17
54
+ - Remove unused systemtime options in modelfile API
55
+ - Fixes to the validation option targeting the ergo ES6 runtime
56
+
57
+ Version 1.0.0-alpha.5 {446997953e3ac90783ff9d492a8e7fdc} 2021-04-08
58
+ - Support Concerto version pragma at the beginning of model files
59
+ - Remove allowEmptyId option in factory API
60
+
61
+ Version 1.0.0-alpha.4 {3b7ebc06a536a5e81624225c7b0079ee} 2021-04-08
62
+ - Allow optional UTC offset for validating DateTime values
63
+
64
+ Version 1.0.0-alpha.3 {7b8763c243f937d84579350aef348c3c} 2020-12-25
65
+ - Concepts may now be identified
66
+ - assets/participants have a system identifier created ($identifier) automatically
67
+ - /transaction/events have a system timestamp created ($timestamp) automatically
68
+ - Can no longer redefine the identifier declared by a super type
69
+ - 'concerto' namespace is now reserved and cannot be used by user code
70
+ - All types extend concerto.Concept
71
+ - Removed System Models APIs
72
+ - Remove notion of system table
73
+ - Remove user ability to change system model
74
+ - Update JsDoc for ModelManager.addModelFiles
75
+ - Add Logger API
76
+ - Add instanceof alternatives to Factory and Serializer
77
+ - Add new Concerto API (experimental)
78
+
79
+ Version 0.82.9 {c96bafdd4a2bb7402f6b520a0cefe537} 2020-09-09
80
+ - Add option parameters to ModelLoader
81
+
82
+ Version 0.82.6 {03fa6481ffdf0e58cb110c6f24009d18} 2020-02-26
83
+ - Update JsDoc for ModelManager.addModelFiles
84
+
85
+ Version 0.82.1 {dee013e99a3c2d6acc4eddfb00aad2a2} 2019-10-22
86
+ - Make several constructors public
87
+ - Add model loader utility class
88
+
89
+ Version 0.80.3 {6f5a9ab45943cb76732c14b11f47d044} 2019-08-24
90
+ - Add Ergo option to serializer
91
+
92
+ Version 0.80.1 {297c88d29ce911ec6efc0f28ceeeb660} 2019-08-24
93
+ - Adds getModels and writeModelsToFileSystem functions to ModelManager
94
+ - Fixes API generation for hasSymbol function
95
+
96
+ Version 0.71.7 {2b5649f2b8f13d52241959f613cbfdd7} 2019-07-29
97
+ - Add static hasInstance as alternative instanceof implementation for AssetDeclaration, ClassDeclaration, EnumDeclaration, ConceptDeclaration, EnumValueDeclaration, Field, ModelFile, ModelManager, RelationshipDeclaration, TransactionDeclaration
98
+
99
+ Version 0.70.5 {db48b7eb8404d9206e9bc8efb3de0009} 2019-06-23
100
+ - Update exception triggered when creating EventDeclaration class
101
+
102
+ Version 0.31.0 {82c0c10648bd10fb79b84db3fcda1776} 2018-10-03
103
+ - Remove built-in system model file
104
+
105
+ Version 0.30.1 {fd4b813bc0bda4042db3c4657893593f} 2018-10-03
106
+ - Remove Wallet
107
+
108
+ Version 0.30.0 {785896a0c4c91e70dcbbfcc5bab33938} 2018-10-02
109
+ - Refactor to make model manager its own module
package/index.js ADDED
@@ -0,0 +1,40 @@
1
+ /*
2
+ * Licensed under the Apache License, Version 2.0 (the "License");
3
+ * you may not use this file except in compliance with the License.
4
+ * You may obtain a copy of the License at
5
+ *
6
+ * http://www.apache.org/licenses/LICENSE-2.0
7
+ *
8
+ * Unless required by applicable law or agreed to in writing, software
9
+ * distributed under the License is distributed on an "AS IS" BASIS,
10
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ * See the License for the specific language governing permissions and
12
+ * limitations under the License.
13
+ */
14
+
15
+ 'use strict';
16
+
17
+ /**
18
+ * Concerto module. Concerto is a framework for defining domain
19
+ * specific models.
20
+ *
21
+ * @module concerto-util
22
+ */
23
+
24
+ // Transitive closure downloader
25
+ module.exports.FileDownloader = require('./lib/filedownloader');
26
+
27
+ // File Loaders
28
+ module.exports.CompositeFileLoader = require('./lib/loaders/compositefileloader');
29
+ module.exports.DefaultFileLoader = require('./lib/loaders/defaultfileloader');
30
+ module.exports.GitHubFileLoader = require('./lib/loaders/githubfileloader');
31
+ module.exports.HTTPFileLoader = require('./lib/loaders/httpfileloader');
32
+
33
+ // Writers
34
+ module.exports.Writer = require('./lib/writer');
35
+
36
+ // Logger
37
+ module.exports.Logger = require('./lib/logger');
38
+
39
+ // TypedStack
40
+ module.exports.TypedStack = require('./lib/typedstack');
@@ -0,0 +1,135 @@
1
+ /*
2
+ * Licensed under the Apache License, Version 2.0 (the "License");
3
+ * you may not use this file except in compliance with the License.
4
+ * You may obtain a copy of the License at
5
+ *
6
+ * http://www.apache.org/licenses/LICENSE-2.0
7
+ *
8
+ * Unless required by applicable law or agreed to in writing, software
9
+ * distributed under the License is distributed on an "AS IS" BASIS,
10
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ * See the License for the specific language governing permissions and
12
+ * limitations under the License.
13
+ */
14
+
15
+ 'use strict';
16
+
17
+ const debug = require('debug')('concerto:FileDownloader');
18
+ const PromisePool = require('@supercharge/promise-pool');
19
+
20
+ const flatten = arr => [].concat(...arr);
21
+ const filterUndefined = arr => arr.filter(Boolean);
22
+
23
+ const handleJobError = async (error, job) => {
24
+ const badHttpResponse = error.response && error.response.status && error.response.status !== 200;
25
+ const dnsFailure = error.code && error.code === 'ENOTFOUND';
26
+ if(badHttpResponse || dnsFailure){
27
+ const err = new Error(`Unable to download external model dependency '${job.url}'`);
28
+ err.code = 'MISSING_DEPENDENCY';
29
+ throw err;
30
+ }
31
+ throw new Error('Failed to load model file. Job: ' + job.url + ' Details: ' + error);
32
+ };
33
+
34
+ /**
35
+ * Downloads the transitive closure of a set of model files.
36
+ * @class
37
+ * @memberof module:concerto-core
38
+ */
39
+ class FileDownloader {
40
+ /**
41
+ * Create a FileDownloader and bind to a FileLoader.
42
+ * @param {fileLoader} fileLoader - the loader to use to download model files
43
+ * @param {*} getExternalImports - a function taking a file and returning new files
44
+ * @param {Number} concurrency - the number of model files to download concurrently
45
+ */
46
+ constructor(fileLoader, getExternalImports, concurrency = 10) {
47
+ this.fileLoader = fileLoader;
48
+ this.concurrency = concurrency;
49
+ this.getExternalImports = getExternalImports;
50
+ }
51
+
52
+ /**
53
+ * Download all external dependencies for an array of model files
54
+ * @param {File[]} files - the model files
55
+ * @param {Object} [options] - Options object passed to FileLoaders
56
+ * @return {Promise} a promise that resolves to Files[] for the external model files
57
+ */
58
+ downloadExternalDependencies(files, options) {
59
+ const method = 'downloadExternalDependencies';
60
+ debug(method);
61
+
62
+ const downloadedUris = new Set();
63
+
64
+ if (!options) {
65
+ options = {};
66
+ }
67
+
68
+ const jobs = flatten(files.map(file => {
69
+ const externalImports = this.getExternalImports(file);
70
+ return Object.keys(externalImports).map(importDeclaration => ({
71
+ downloadedUris: downloadedUris,
72
+ url: externalImports[importDeclaration],
73
+ options: options
74
+ }));
75
+ }));
76
+
77
+ return PromisePool
78
+ .withConcurrency(this.concurrency)
79
+ .for(jobs)
80
+ .handleError(handleJobError)
81
+ .process(x => this.runJob(x, this.fileLoader))
82
+ .then(({ results }) => filterUndefined(flatten(results)));
83
+ }
84
+
85
+ /**
86
+ * Execute a Job
87
+ * @param {Object} job - the job to execute
88
+ * @param {Object} fileLoader - the loader to use to download model files.
89
+ * @return {Promise} a promise to the job results
90
+ */
91
+ runJob(job, fileLoader) {
92
+ const downloadedUris = job.downloadedUris;
93
+ const options = job.options;
94
+ const url = job.url;
95
+
96
+ // cache the URI, so we don't download it again
97
+ downloadedUris.add(url);
98
+
99
+ debug('runJob', 'Loading', url);
100
+ return fileLoader.load(url, options).
101
+ then(async file => {
102
+ debug('runJob', 'Loaded', url, );
103
+
104
+ // get the external imports
105
+ const externalImports = this.getExternalImports(file);
106
+ const importedUris = Array.from(
107
+ new Set(
108
+ Object.keys(externalImports)
109
+ .map((importDeclaration) => externalImports[importDeclaration])
110
+ )
111
+ );
112
+ debug('runJob', 'importedUris', importedUris);
113
+
114
+ const externalImportsFiles = await PromisePool
115
+ .withConcurrency(this.concurrency)
116
+ .for(importedUris)
117
+ .handleError(handleJobError)
118
+ .process(uri => {
119
+ if (!downloadedUris.has(uri)) {
120
+ // recurse and add a new job for the referenced URI
121
+ return this.runJob({
122
+ options: options,
123
+ url: uri,
124
+ downloadedUris: downloadedUris
125
+ }, fileLoader);
126
+ }
127
+ })
128
+ .then(({ results }) => filterUndefined(flatten(results)));
129
+
130
+ return externalImportsFiles.concat([file]);
131
+ });
132
+ }
133
+ }
134
+
135
+ module.exports = FileDownloader;
@@ -0,0 +1,95 @@
1
+ /*
2
+ * Licensed under the Apache License, Version 2.0 (the "License");
3
+ * you may not use this file except in compliance with the License.
4
+ * You may obtain a copy of the License at
5
+ *
6
+ * http://www.apache.org/licenses/LICENSE-2.0
7
+ *
8
+ * Unless required by applicable law or agreed to in writing, software
9
+ * distributed under the License is distributed on an "AS IS" BASIS,
10
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ * See the License for the specific language governing permissions and
12
+ * limitations under the License.
13
+ */
14
+
15
+ 'use strict';
16
+
17
+ /**
18
+ * <p>
19
+ * Manages a set of model file loaders, delegating to the first model file
20
+ * loader that accepts a URL.
21
+ * </p>
22
+ * @private
23
+ * @class
24
+ * @memberof module:concerto-util
25
+ */
26
+ class CompositeFileLoader {
27
+ /**
28
+ * Create the CompositeFileLoader. Used to delegate to a set of FileLoaders.
29
+ */
30
+ constructor() {
31
+ this.fileLoaders = [];
32
+ }
33
+
34
+ /**
35
+ * Adds a FileLoader implemenetation to the FileLoader
36
+ * @param {FileLoader} fileLoader - The script to add to the ScriptManager
37
+ */
38
+ addFileLoader(fileLoader) {
39
+ this.fileLoaders.push(fileLoader);
40
+ }
41
+
42
+ /**
43
+ * Get the array of FileLoader instances
44
+ * @return {FileLoaders[]} The FileLoader registered
45
+ * @private
46
+ */
47
+ getFileLoaders() {
48
+ return this.fileLoaders;
49
+ }
50
+
51
+ /**
52
+ * Remove all registered FileLoaders
53
+ */
54
+ clearFileLoaders() {
55
+ this.fileLoaders = [];
56
+ }
57
+
58
+ /**
59
+ * Returns true if this ModelLoader can process the URL
60
+ * @param {string} url - the URL
61
+ * @return {boolean} true if this ModelLoader accepts the URL
62
+ * @abstract
63
+ */
64
+ accepts(url) {
65
+ for (let n = 0; n < this.fileLoaders.length; n++) {
66
+ const ml = this.fileLoaders[n];
67
+
68
+ if (ml.accepts(url)) {
69
+ return true;
70
+ }
71
+ }
72
+
73
+ return false;
74
+ }
75
+
76
+ /**
77
+ * Load a File from a URL and return it
78
+ * @param {string} url - the url to get
79
+ * @param {object} options - additional options
80
+ * @return {Promise} a promise to the File
81
+ */
82
+ load(url, options) {
83
+ for (let n = 0; n < this.fileLoaders.length; n++) {
84
+ const ml = this.fileLoaders[n];
85
+
86
+ if (ml.accepts(url)) {
87
+ return ml.load(url, options);
88
+ }
89
+ }
90
+
91
+ throw new Error('Failed to find a model file loader that can handle: ' + url);
92
+ }
93
+ }
94
+
95
+ module.exports = CompositeFileLoader;
@@ -0,0 +1,45 @@
1
+ /*
2
+ * Licensed under the Apache License, Version 2.0 (the "License");
3
+ * you may not use this file except in compliance with the License.
4
+ * You may obtain a copy of the License at
5
+ *
6
+ * http://www.apache.org/licenses/LICENSE-2.0
7
+ *
8
+ * Unless required by applicable law or agreed to in writing, software
9
+ * distributed under the License is distributed on an "AS IS" BASIS,
10
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ * See the License for the specific language governing permissions and
12
+ * limitations under the License.
13
+ */
14
+
15
+ 'use strict';
16
+
17
+ const CompositeFileLoader = require('./compositefileloader');
18
+ const HTTPFileLoader = require('./httpfileloader');
19
+ const GitHubFileLoader = require('./githubfileloader');
20
+
21
+ /**
22
+ * <p>
23
+ * A default CompositeFileLoader implementation which supports
24
+ * github://, http:// and https:// URLs.
25
+ * </p>
26
+ * @private
27
+ * @class
28
+ * @see See {@link CompositeFileLoader}
29
+ * @memberof module:concerto-util
30
+ */
31
+ class DefaultFileLoader extends CompositeFileLoader {
32
+ /**
33
+ * Create the DefaultFileLoader.
34
+ * @param {*} processFile - a function to apply to the content of the file
35
+ */
36
+ constructor(processFile) {
37
+ super();
38
+ const http = new HTTPFileLoader(processFile);
39
+ const github = new GitHubFileLoader(processFile);
40
+ this.addFileLoader(github);
41
+ this.addFileLoader(http);
42
+ }
43
+ }
44
+
45
+ module.exports = DefaultFileLoader;
@@ -0,0 +1,58 @@
1
+ /*
2
+ * Licensed under the Apache License, Version 2.0 (the "License");
3
+ * you may not use this file except in compliance with the License.
4
+ * You may obtain a copy of the License at
5
+ *
6
+ * http://www.apache.org/licenses/LICENSE-2.0
7
+ *
8
+ * Unless required by applicable law or agreed to in writing, software
9
+ * distributed under the License is distributed on an "AS IS" BASIS,
10
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ * See the License for the specific language governing permissions and
12
+ * limitations under the License.
13
+ */
14
+
15
+ 'use strict';
16
+
17
+ const HTTPFileLoader = require('./httpfileloader');
18
+
19
+ /**
20
+ * Loads Files from an external source, such as a URL.
21
+ *
22
+ * @class
23
+ * @private
24
+ * @memberof module:concerto-util
25
+ */
26
+ class GitHubFileLoader extends HTTPFileLoader {
27
+ /**
28
+ * Create the GitHubFileLoader.
29
+ * @param {*} processFile - a function to apply to the content of the file
30
+ */
31
+ constructor(processFile) {
32
+ super(processFile);
33
+ }
34
+
35
+ /**
36
+ * Returns true if this ModelLoader can process the URL
37
+ * @param {string} url - the URL
38
+ * @return {boolean} true if this ModelLoader accepts the URL
39
+ * @abstract
40
+ */
41
+ accepts(url) {
42
+ return url.startsWith('github://');
43
+ }
44
+
45
+ /**
46
+ * Load a File from a URL and return it
47
+ * @param {string} url - the url to get
48
+ * @param {object} options - additional options
49
+ * @return {Promise} a promise to the File
50
+ */
51
+ load(url, options) {
52
+ const rewrittenUrl = 'https://raw.githubusercontent.com/' + url.substring(9);
53
+ const result = super.load(rewrittenUrl, options);
54
+ return result;
55
+ }
56
+ }
57
+
58
+ module.exports = GitHubFileLoader;
@@ -0,0 +1,73 @@
1
+ /*
2
+ * Licensed under the Apache License, Version 2.0 (the "License");
3
+ * you may not use this file except in compliance with the License.
4
+ * You may obtain a copy of the License at
5
+ *
6
+ * http://www.apache.org/licenses/LICENSE-2.0
7
+ *
8
+ * Unless required by applicable law or agreed to in writing, software
9
+ * distributed under the License is distributed on an "AS IS" BASIS,
10
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ * See the License for the specific language governing permissions and
12
+ * limitations under the License.
13
+ */
14
+
15
+ 'use strict';
16
+
17
+ const axios = require('axios');
18
+ const url = require('url');
19
+
20
+ /**
21
+ * Loads Files from an HTTP(S) URL using the axios library.
22
+ * @class
23
+ * @private
24
+ * @memberof module:concerto-util
25
+ */
26
+ class HTTPFileLoader {
27
+ /**
28
+ * Create the HTTPFileLoader.
29
+ * @param {*} processFile - a function to apply to the content of the file
30
+ */
31
+ constructor(processFile) {
32
+ this.processFile = processFile;
33
+ }
34
+
35
+ /**
36
+ * Returns true if this ModelLoader can process the URL
37
+ * @param {string} url - the URL
38
+ * @return {boolean} true if this ModelLoader accepts the URL
39
+ * @abstract
40
+ */
41
+ accepts(url) {
42
+ return url.startsWith('http://') || url.startsWith('https://');
43
+ }
44
+
45
+ /**
46
+ * Load a File from a URL and return it
47
+ * @param {string} requestUrl - the url to get
48
+ * @param {object} options - additional options
49
+ * @return {Promise} a promise to the File
50
+ */
51
+ load(requestUrl, options) {
52
+
53
+ if(!options) {
54
+ options = {};
55
+ }
56
+
57
+ const request = JSON.parse(JSON.stringify(options));
58
+ request.url = requestUrl;
59
+ request.method = 'get';
60
+ request.responseType = 'text';
61
+
62
+ return axios(request)
63
+ .then((response) => {
64
+ let parsedUrl = url.parse(requestUrl);
65
+ // external Files have a name that starts with '@'
66
+ // (so that they are identified as external when an archive is read back in)
67
+ const name = '@' + (parsedUrl.host + parsedUrl.pathname).replace(/\//g, '.');
68
+ return this.processFile(name, response.data);
69
+ });
70
+ }
71
+ }
72
+
73
+ module.exports = HTTPFileLoader;
package/lib/logger.js ADDED
@@ -0,0 +1,250 @@
1
+ /*
2
+ * Licensed under the Apache License, Version 2.0 (the "License");
3
+ * you may not use this file except in compliance with the License.
4
+ * You may obtain a copy of the License at
5
+ *
6
+ * http://www.apache.org/licenses/LICENSE-2.0
7
+ *
8
+ * Unless required by applicable law or agreed to in writing, software
9
+ * distributed under the License is distributed on an "AS IS" BASIS,
10
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ * See the License for the specific language governing permissions and
12
+ * limitations under the License.
13
+ */
14
+
15
+ 'use strict';
16
+
17
+ /* eslint-disable no-console */
18
+ /* eslint-disable no-use-before-define */
19
+
20
+ const colors = require('colors/safe');
21
+ const jsonColorize = require('json-colorizer');
22
+
23
+ /**
24
+ * Default levels for the npm configuration.
25
+ * @type {Object}
26
+ */
27
+ const levels = {
28
+ error: 0,
29
+ warn: 1,
30
+ info: 2,
31
+ http: 3,
32
+ verbose: 4,
33
+ debug: 5,
34
+ silly: 6
35
+ };
36
+
37
+ /**
38
+ * Default levels for the npm configuration.
39
+ * @type {Object}
40
+ */
41
+ const colorMap = {
42
+ error: 'red',
43
+ warn: 'yellow',
44
+ info: 'green',
45
+ verbose: 'cyan',
46
+ debug: 'blue',
47
+ silly: 'magenta'
48
+ };
49
+
50
+ const timestamp = () => (new Date()).toLocaleTimeString();
51
+ const colorize = level => colors[colorMap[level]](level.toUpperCase());
52
+
53
+ /**
54
+ * Helper function to test if a string is a stringified version of a JSON object
55
+ * @param {string} str - the input string to test
56
+ * @returns {boolean} - true iff the string can be parsed as JSON
57
+ * @private
58
+ */
59
+ const isJson = (str) => {
60
+ try {
61
+ return (JSON.parse(str) && !!str);
62
+ } catch (e) {
63
+ return false;
64
+ }
65
+ };
66
+
67
+ /**
68
+ * Helper function to color and format JSON objects
69
+ * @param {any} obj - the input obj to prettify
70
+ * @returns {any} - the prettified object
71
+ * @private
72
+ */
73
+ const prettifyJson = (obj) => {
74
+ if(typeof obj === 'object' || isJson(obj)) {
75
+ return jsonColorize(obj, { pretty: true, colors });
76
+ }
77
+ return obj;
78
+ };
79
+
80
+ /**
81
+ * The default transport for logging at multiple levels to the console
82
+ * @param {string} level - the required log level. e.g. error, warn, info, debug, etc.
83
+ * @param {any} obj - the input obj to prettify
84
+ * @returns {void} -
85
+ * @private
86
+ */
87
+ const defaultTransportShim = (level, ...args) => {
88
+ let mutatedLevel = level;
89
+ let data = args;
90
+ let first = data.shift();
91
+
92
+ // Flatten log object
93
+ if(first && typeof first === 'object' && first.level && first.message){
94
+ const padding = first.padding && first.padding[first.level];
95
+ if (first.level === 'error' && first.stack) {
96
+ mutatedLevel = 'error';
97
+ first = `${first.message}\n${first.stack}`;
98
+ } else if (Object.keys(levels).includes(first.level)) {
99
+ mutatedLevel = first.level;
100
+ first = first.message;
101
+ }
102
+ first = padding ? `${padding} ${first}` : first;
103
+ }
104
+
105
+ data.unshift(first);
106
+
107
+ const stream = ['error', 'warn'].includes(mutatedLevel) ? console.error : console.log;
108
+
109
+ stream(
110
+ `${timestamp()} - ${colorize(mutatedLevel)}:`,
111
+ ...data
112
+ .map(obj => obj instanceof Error ? `${obj.message}\n${obj.stack}`: obj)
113
+ .map(prettifyJson)
114
+ );
115
+ };
116
+ const defaultTransport = {};
117
+ Object.keys(levels).forEach(level => {
118
+ defaultTransport[level] = (...args) => defaultTransportShim(level, ...args);
119
+ });
120
+
121
+ /**
122
+ * A utility class with static function that print to the console
123
+ * @private
124
+ */
125
+ class Logger {
126
+ /**
127
+ * A reusable function for logging at multiple levels
128
+ * @param {string} level - the required log level. e.g. error, warn, info, debug, etc.
129
+ * @param {any} obj - the input obj to prettify
130
+ * @returns {void} -
131
+ * @private
132
+ */
133
+ static dispatch(level, ...args) {
134
+ if (levels[level] > levels[this.level]){
135
+ return;
136
+ }
137
+
138
+ this.transports.forEach(t => {
139
+ if(t[level]){
140
+ t[level](...args);
141
+ }
142
+ });
143
+ }
144
+
145
+ /**
146
+ * Add a custom transport for logging
147
+ * @param {Object} transport - The transport object should have function for the usual logging operations e.g. error, warn, info, debug, etc.
148
+ * @returns {void} -
149
+ * @private
150
+ */
151
+ static add(transport) {
152
+ this.transports.push(transport);
153
+ }
154
+
155
+ /**
156
+ * Write an error statement to the console.
157
+ *
158
+ * Prints to `stderr` with newline.
159
+ * @param {any|object} data - if this is an object with properties `level` and `message` it will be flattened first
160
+ * @param {any} args -
161
+ * @returns {void} -
162
+ * @private
163
+ */
164
+ static error(...args){ return this.dispatch('error', ...args); }
165
+
166
+ /**
167
+ * Write a warning statement to the console.
168
+ *
169
+ * Prints to `stderr` with newline.
170
+ * @param {any|object} data - if this is an object with properties `level` and `message` it will be flattened first
171
+ * @param {any} args -
172
+ * @returns {void} -
173
+ * @private
174
+ */
175
+ static warn(...args){ return this.dispatch('warn', ...args); }
176
+
177
+ /**
178
+ * Write an info statement to the console.
179
+ *
180
+ * Prints to `stdout` with newline.
181
+ * @param {any|object} data - if this is an object with properties `level` and `message` it will be flattened first
182
+ * @param {any} args -
183
+ * @returns {void} -
184
+ * @private
185
+ */
186
+ static info(...args){ return this.dispatch('info', ...args); }
187
+
188
+ /**
189
+ * Write an info statement to the console. Alias for `logger.log`
190
+ *
191
+ * Prints to `stdout` with newline.
192
+ * @param {any|object} data - if this is an object with properties `level` and `message` it will be flattened first
193
+ * @param {any} args -
194
+ * @returns {void} -
195
+ * @private
196
+ */
197
+ static log(...args){ return this.info(...args); }
198
+
199
+ /**
200
+ * Write an http statement to the console.
201
+ *
202
+ * Prints to `stdout` with newline.
203
+ * @param {any|object} data - if this is an object with properties `level` and `message` it will be flattened first
204
+ * @param {any} args -
205
+ * @returns {void} -
206
+ * @private
207
+ */
208
+ static http(...args){ return this.dispatch('http', ...args); }
209
+
210
+ /**
211
+ * Write a verbose log statement to the console.
212
+ *
213
+ * Prints to `stdout` with newline.
214
+ * @param {any|object} data - if this is an object with properties `level` and `message` it will be flattened first
215
+ * @param {any} args -
216
+ * @returns {void} -
217
+ * @private
218
+ */
219
+ static verbose(...args){ return this.dispatch('verbose', ...args); }
220
+
221
+ /**
222
+ * Write a debug statement to the console.
223
+ *
224
+ * Prints to `stdout` with newline.
225
+ * @param {any|object} data - if this is an object with properties `level` and `message` it will be flattened first
226
+ * @param {any} args -
227
+ * @returns {void} -
228
+ * @private
229
+ */
230
+ static debug(...args){ return this.dispatch('debug', ...args); }
231
+
232
+ /**
233
+ * Write a silly level statement to the console.
234
+ *
235
+ * Prints to `stdout` with newline.
236
+ * @param {any|object} data - if this is an object with properties `level` and `message` it will be flattened first
237
+ * @param {any} args -
238
+ * @returns {void} -
239
+ * @private
240
+ */
241
+ static silly(...args){ return this.dispatch('silly', ...args); }
242
+ }
243
+
244
+ // Set the default logging level
245
+ Logger.level = 'info';
246
+
247
+ // A list of user-provided logging tranports
248
+ Logger.transports = [ defaultTransport ];
249
+
250
+ module.exports = Logger;
@@ -0,0 +1,88 @@
1
+ /*
2
+ * Licensed under the Apache License, Version 2.0 (the "License");
3
+ * you may not use this file except in compliance with the License.
4
+ * You may obtain a copy of the License at
5
+ *
6
+ * http://www.apache.org/licenses/LICENSE-2.0
7
+ *
8
+ * Unless required by applicable law or agreed to in writing, software
9
+ * distributed under the License is distributed on an "AS IS" BASIS,
10
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ * See the License for the specific language governing permissions and
12
+ * limitations under the License.
13
+ */
14
+
15
+ 'use strict';
16
+
17
+ /**
18
+ * Tracks a stack of typed instances. The type information is used to detect
19
+ * overflow / underflow bugs by the caller. It also performs basic sanity
20
+ * checking on push/pop to make detecting bugs easier.
21
+ * @class
22
+ * @memberof module:concerto-core
23
+ */
24
+ class TypedStack {
25
+
26
+ /**
27
+ * Create the Stack with the resource at the head.
28
+ * @param {Object} resource - the resource to be put at the head of the stack
29
+ */
30
+ constructor(resource) {
31
+ this.stack = [];
32
+ this.push(resource);
33
+ }
34
+
35
+ /**
36
+ * Push a new object.
37
+ * @param {Object} obj - the object being visited
38
+ * @param {Object} expectedType - the expected type of the object being pushed
39
+ */
40
+ push(obj, expectedType) {
41
+ if(expectedType && !(obj instanceof expectedType)) {
42
+ throw new Error('Did not find expected type ' + expectedType.constructor.name + ' as argument to push. Found: ' + obj.toString());
43
+ }
44
+
45
+ this.stack.push(obj);
46
+ //console.log('Push depth is: ' + this.stack.length + ', contents: ' + this.stack.toString() );
47
+ }
48
+
49
+ /**
50
+ * Push a new object.
51
+ * @param {Object} expectedType - the type that should be the result of pop
52
+ * @return {Object} the result of pop
53
+ */
54
+ pop(expectedType) {
55
+ this.peek(expectedType);
56
+ return this.stack.pop();
57
+ }
58
+
59
+ /**
60
+ * Peek the top of the stack
61
+ * @param {Object} expectedType - the type that should be the result of pop
62
+ * @return {Object} the result of peek
63
+ */
64
+ peek(expectedType) {
65
+
66
+ //console.log( 'pop ' );
67
+
68
+ if(this.stack.length < 1) {
69
+ throw new Error('Stack is empty!');
70
+ }
71
+
72
+ const result = this.stack[this.stack.length-1];
73
+ if(expectedType && !(result instanceof expectedType)) {
74
+ throw new Error('Did not find expected type ' + expectedType + ' on head of stack. Found: ' + result);
75
+ }
76
+
77
+ return result;
78
+ }
79
+
80
+ /**
81
+ * Clears the stack
82
+ */
83
+ clear() {
84
+ this.stack = [];
85
+ }
86
+ }
87
+
88
+ module.exports = TypedStack;
package/lib/writer.js ADDED
@@ -0,0 +1,116 @@
1
+ /*
2
+ * Licensed under the Apache License, Version 2.0 (the "License");
3
+ * you may not use this file except in compliance with the License.
4
+ * You may obtain a copy of the License at
5
+ *
6
+ * http://www.apache.org/licenses/LICENSE-2.0
7
+ *
8
+ * Unless required by applicable law or agreed to in writing, software
9
+ * distributed under the License is distributed on an "AS IS" BASIS,
10
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ * See the License for the specific language governing permissions and
12
+ * limitations under the License.
13
+ */
14
+
15
+ 'use strict';
16
+
17
+ /**
18
+ * Writer buffers text to be written in memory. It handles simple
19
+ * indentation and tracks the number of lines written.
20
+ * @private
21
+ * @class
22
+ * @memberof module:concerto-util
23
+ */
24
+ class Writer {
25
+ /**
26
+ * Create a Writer.
27
+ */
28
+ constructor() {
29
+ this.beforeBuffer = '';
30
+ this.buffer = '';
31
+ this.linesWritten = 0;
32
+ }
33
+
34
+ /**
35
+ * Writes text to the start of the buffer
36
+ * @param {int} tabs - the number of tabs to use
37
+ * @param {string} text - the text to write
38
+ */
39
+ writeBeforeLine(tabs, text) {
40
+ for(let n=0; n < tabs; n++) {
41
+ this.beforeBuffer += ' ';
42
+ }
43
+ this.beforeBuffer += text;
44
+ this.beforeBuffer += '\n';
45
+ this.linesWritten++;
46
+ }
47
+
48
+ /**
49
+ * Append text to the buffer
50
+ * @param {int} tabs - the number of tabs to use
51
+ * @param {string} text - the text to write
52
+ */
53
+ writeLine(tabs, text) {
54
+ for(let n=0; n < tabs; n++) {
55
+ this.write(' ');
56
+ }
57
+ this.write(text);
58
+ this.write('\n');
59
+ this.linesWritten++;
60
+ }
61
+
62
+ /**
63
+ * Returns the number of lines that have been written to the buffer.
64
+ * @return {int} the number of lines written to the buffer.
65
+ */
66
+ getLineCount() {
67
+ return this.linesWritten;
68
+ }
69
+
70
+
71
+ /**
72
+ * Append text to the buffer, prepending tabs
73
+ * @param {int} tabs - the number of tabs to use
74
+ * @param {string} text - the text to write
75
+ */
76
+ writeIndented(tabs,text) {
77
+ for(let n=0; n < tabs; n++) {
78
+ this.write(' ');
79
+ }
80
+ this.write(text);
81
+ }
82
+
83
+ /**
84
+ * Append text to the buffer (no automatic newline). The
85
+ * text may contain newline, and these will increment the linesWritten
86
+ * counter.
87
+ * @param {string} msg - the text to write
88
+ */
89
+ write(msg) {
90
+ if(typeof msg !== 'string' ) {
91
+ throw new Error('Can only append strings. Argument ' + msg + ' has type ' + typeof msg);
92
+ }
93
+
94
+ this.buffer += msg;
95
+ this.linesWritten += msg.split(/\r\n|\r|\n/).length;
96
+ }
97
+
98
+ /**
99
+ * Returns the text that has been buffered in this Writer.
100
+ * @return {string} the buffered text.
101
+ */
102
+ getBuffer() {
103
+ return this.beforeBuffer + this.buffer;
104
+ }
105
+
106
+ /**
107
+ * Empties the underyling buffer and resets the line count.
108
+ */
109
+ clearBuffer() {
110
+ this.beforeBuffer = '';
111
+ this.buffer = '';
112
+ this.linesWritten = 0;
113
+ }
114
+ }
115
+
116
+ module.exports = Writer;
package/package.json ADDED
@@ -0,0 +1,119 @@
1
+ {
2
+ "name": "@accordproject/concerto-util",
3
+ "version": "1.2.2-20211130213656",
4
+ "description": "Utilities for Concerto Modeling Language",
5
+ "homepage": "https://github.com/accordproject/concerto",
6
+ "engines": {
7
+ "node": ">=12",
8
+ "npm": ">=6"
9
+ },
10
+ "main": "index.js",
11
+ "scripts": {
12
+ "pretest": "npm run lint",
13
+ "lint": "eslint .",
14
+ "postlint": "npm run licchk",
15
+ "licchk": "license-check-and-add",
16
+ "postlicchk": "npm run doc",
17
+ "doc": "jsdoc --pedantic --recurse -c jsdoc.json",
18
+ "test": "nyc mocha --recursive -t 10000",
19
+ "test:watch": "nyc mocha --watch --recursive -t 10000",
20
+ "mocha": "mocha --recursive -t 10000",
21
+ "nyc": "nyc mocha --recursive -t 10000"
22
+ },
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "https://github.com/accordproject/concerto.git",
26
+ "directory": "packages/concerto-util"
27
+ },
28
+ "keywords": [
29
+ "blockchain",
30
+ "hyperledger",
31
+ "solutions"
32
+ ],
33
+ "author": "accordproject.org",
34
+ "license": "Apache-2.0",
35
+ "devDependencies": {
36
+ "chai": "4.3.4",
37
+ "chai-as-promised": "7.1.1",
38
+ "chai-things": "0.2.0",
39
+ "eslint": "8.2.0",
40
+ "jsdoc": "^3.6.7",
41
+ "license-check-and-add": "2.3.6",
42
+ "mocha": "8.3.2",
43
+ "moxios": "0.4.0",
44
+ "nyc": "15.1.0",
45
+ "sinon": "10.0.0",
46
+ "sinon-chai": "3.6.0"
47
+ },
48
+ "dependencies": {
49
+ "@supercharge/promise-pool": "1.7.0",
50
+ "axios": "0.23.0",
51
+ "colors": "1.4.0",
52
+ "debug": "4.3.1",
53
+ "json-colorizer": "2.2.2"
54
+ },
55
+ "browserslist": "> 0.25%, not dead",
56
+ "license-check-and-add-config": {
57
+ "folder": "./lib",
58
+ "license": "HEADER",
59
+ "exact_paths_method": "EXCLUDE",
60
+ "exact_paths": [
61
+ "api.txt",
62
+ "composer-logs",
63
+ "coverage",
64
+ "./parser.js",
65
+ "LICENSE",
66
+ "node_modules",
67
+ ".nyc-output",
68
+ "out",
69
+ ".tern-project"
70
+ ],
71
+ "file_type_method": "EXCLUDE",
72
+ "file_types": [
73
+ ".yml",
74
+ ".yaml",
75
+ ".zip",
76
+ ".tgz"
77
+ ],
78
+ "insert_license": false,
79
+ "license_formats": {
80
+ "js|njk|pegjs|cto|acl|qry": {
81
+ "prepend": "/*",
82
+ "append": " */",
83
+ "eachLine": {
84
+ "prepend": " * "
85
+ }
86
+ },
87
+ "npmrc|editorconfig|txt": {
88
+ "eachLine": {
89
+ "prepend": "# "
90
+ }
91
+ },
92
+ "md": {
93
+ "file": "HEADER.md"
94
+ }
95
+ }
96
+ },
97
+ "nyc": {
98
+ "produce-source-map": "true",
99
+ "sourceMap": "inline",
100
+ "reporter": [
101
+ "lcov",
102
+ "text-summary",
103
+ "html",
104
+ "json"
105
+ ],
106
+ "include": [
107
+ "lib/**/*.js"
108
+ ],
109
+ "exclude": [
110
+ "lib/parser.js"
111
+ ],
112
+ "all": true,
113
+ "check-coverage": true,
114
+ "statements": 99,
115
+ "branches": 93,
116
+ "functions": 98,
117
+ "lines": 99
118
+ }
119
+ }