@digicatapult/sqnc-process-management 2.2.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.
- package/LICENSE +190 -0
- package/README.md +213 -0
- package/build/package.json +64 -0
- package/build/src/index.d.ts +2 -0
- package/build/src/index.js +127 -0
- package/build/src/lib/process/_tests_/unit.test.d.ts +1 -0
- package/build/src/lib/process/_tests_/unit.test.js +112 -0
- package/build/src/lib/process/api.d.ts +7 -0
- package/build/src/lib/process/api.js +112 -0
- package/build/src/lib/process/constants.d.ts +3 -0
- package/build/src/lib/process/constants.js +3 -0
- package/build/src/lib/process/hex.d.ts +2 -0
- package/build/src/lib/process/hex.js +9 -0
- package/build/src/lib/process/index.d.ts +21 -0
- package/build/src/lib/process/index.js +205 -0
- package/build/src/lib/types/error.d.ts +14 -0
- package/build/src/lib/types/error.js +26 -0
- package/build/src/lib/types/validation.d.ts +5472 -0
- package/build/src/lib/types/validation.js +128 -0
- package/build/src/lib/utils/polkadot.d.ts +1 -0
- package/build/src/lib/utils/polkadot.js +25 -0
- package/build/src/version.d.ts +2 -0
- package/build/src/version.js +3 -0
- package/build/tests/fixtures/processes.d.ts +281 -0
- package/build/tests/fixtures/processes.js +1066 -0
- package/build/tests/fixtures/programs.d.ts +14 -0
- package/build/tests/fixtures/programs.js +211 -0
- package/build/tests/helpers/substrateHelper.d.ts +2 -0
- package/build/tests/helpers/substrateHelper.js +25 -0
- package/build/tests/integration/command-functions.test.d.ts +1 -0
- package/build/tests/integration/command-functions.test.js +327 -0
- package/package.json +64 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const simple: Process.Program;
|
|
2
|
+
export declare const simple2: {
|
|
3
|
+
Restriction: {
|
|
4
|
+
SenderHasInputRole: {
|
|
5
|
+
index: number;
|
|
6
|
+
role_key: string;
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
}[];
|
|
10
|
+
export declare const invalidPOSIX: Process.Program;
|
|
11
|
+
export declare const validAllRestrictions: Process.Program;
|
|
12
|
+
export declare const invalidRestrictionKey: Process.Program;
|
|
13
|
+
export declare const invalidRestrictionValue: Process.Program;
|
|
14
|
+
export declare const multiple: (process1Name: string, process1BumpedV: number, process2Name: string, process2BumpedV: number) => string;
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
export const simple = [{ Restriction: 'None' }];
|
|
2
|
+
export const simple2 = [
|
|
3
|
+
{
|
|
4
|
+
Restriction: {
|
|
5
|
+
SenderHasInputRole: {
|
|
6
|
+
index: 0,
|
|
7
|
+
role_key: 'Supplier',
|
|
8
|
+
},
|
|
9
|
+
},
|
|
10
|
+
},
|
|
11
|
+
];
|
|
12
|
+
export const invalidPOSIX = [
|
|
13
|
+
{ Restriction: 'None' },
|
|
14
|
+
{
|
|
15
|
+
Restriction: {
|
|
16
|
+
SenderHasInputRole: {
|
|
17
|
+
index: 0,
|
|
18
|
+
role_key: 'Supplier',
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
{ Op: 'Or' },
|
|
23
|
+
{
|
|
24
|
+
Restriction: {
|
|
25
|
+
SenderHasOutputRole: {
|
|
26
|
+
index: 0,
|
|
27
|
+
role_key: 'Supplier',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
];
|
|
32
|
+
export const validAllRestrictions = [
|
|
33
|
+
{ Restriction: 'None' },
|
|
34
|
+
{
|
|
35
|
+
Restriction: {
|
|
36
|
+
SenderHasInputRole: {
|
|
37
|
+
index: 0,
|
|
38
|
+
role_key: 'Supplier',
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
{ Op: 'Or' },
|
|
43
|
+
{
|
|
44
|
+
Restriction: {
|
|
45
|
+
SenderHasOutputRole: {
|
|
46
|
+
index: 0,
|
|
47
|
+
role_key: 'Supplier',
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
{ Op: 'And' },
|
|
52
|
+
{
|
|
53
|
+
Restriction: {
|
|
54
|
+
OutputHasRole: {
|
|
55
|
+
index: 0,
|
|
56
|
+
role_key: 'Supplier',
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
{ Op: 'And' },
|
|
61
|
+
{
|
|
62
|
+
Restriction: {
|
|
63
|
+
OutputHasMetadata: {
|
|
64
|
+
index: 0,
|
|
65
|
+
metadata_key: 'SomeMetadataKey',
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
{ Op: 'And' },
|
|
70
|
+
{
|
|
71
|
+
Restriction: {
|
|
72
|
+
InputHasRole: {
|
|
73
|
+
index: 0,
|
|
74
|
+
role_key: 'Supplier',
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
{ Op: 'And' },
|
|
79
|
+
{
|
|
80
|
+
Restriction: {
|
|
81
|
+
InputHasMetadata: {
|
|
82
|
+
index: 0,
|
|
83
|
+
metadata_key: 'SomeMetadataKey',
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
{ Op: 'And' },
|
|
88
|
+
{
|
|
89
|
+
Restriction: {
|
|
90
|
+
MatchInputOutputRole: {
|
|
91
|
+
input_index: 0,
|
|
92
|
+
input_role_key: 'Supplier',
|
|
93
|
+
output_index: 0,
|
|
94
|
+
output_role_key: 'Supplier',
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
{ Op: 'And' },
|
|
99
|
+
{
|
|
100
|
+
Restriction: {
|
|
101
|
+
MatchInputOutputMetadataValue: {
|
|
102
|
+
input_index: 0,
|
|
103
|
+
input_metadata_key: 'SomeMetadataKey',
|
|
104
|
+
output_index: 0,
|
|
105
|
+
output_metadata_key: 'SomeMetadataKey',
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
{ Op: 'And' },
|
|
110
|
+
{
|
|
111
|
+
Restriction: {
|
|
112
|
+
MatchInputIdOutputMetadataValue: {
|
|
113
|
+
input_index: 0,
|
|
114
|
+
output_index: 0,
|
|
115
|
+
output_metadata_key: 'SomeMetadataKey',
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
{ Op: 'And' },
|
|
120
|
+
{
|
|
121
|
+
Restriction: {
|
|
122
|
+
FixedNumberOfInputs: {
|
|
123
|
+
num_inputs: 0,
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
{ Op: 'And' },
|
|
128
|
+
{
|
|
129
|
+
Restriction: {
|
|
130
|
+
FixedNumberOfOutputs: {
|
|
131
|
+
num_outputs: 0,
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
{ Op: 'And' },
|
|
136
|
+
{
|
|
137
|
+
Restriction: {
|
|
138
|
+
FixedInputMetadataValue: {
|
|
139
|
+
index: 0,
|
|
140
|
+
metadata_key: 'SomeMetadataKey',
|
|
141
|
+
metadata_value: {
|
|
142
|
+
Literal: 'a',
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
{ Op: 'And' },
|
|
148
|
+
{
|
|
149
|
+
Restriction: {
|
|
150
|
+
FixedOutputMetadataValue: {
|
|
151
|
+
index: 0,
|
|
152
|
+
metadata_key: 'SomeMetadataKey',
|
|
153
|
+
metadata_value: {
|
|
154
|
+
Literal: 'a',
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
{ Op: 'And' },
|
|
160
|
+
{
|
|
161
|
+
Restriction: {
|
|
162
|
+
FixedOutputMetadataValueType: {
|
|
163
|
+
index: 0,
|
|
164
|
+
metadata_key: 'SomeMetadataKey',
|
|
165
|
+
metadata_value_type: 'Literal',
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
{ Op: 'And' },
|
|
170
|
+
];
|
|
171
|
+
export const invalidRestrictionKey = [{ Restriction: { NotARestriction: {} } }];
|
|
172
|
+
export const invalidRestrictionValue = [
|
|
173
|
+
{
|
|
174
|
+
Restriction: {
|
|
175
|
+
FixedInputMetadataValue: {
|
|
176
|
+
invalid: 0,
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
];
|
|
181
|
+
// WHY not to use simple/etc? why not name1 name2?
|
|
182
|
+
export const multiple = (process1Name, process1BumpedV, process2Name, process2BumpedV) => JSON.stringify([
|
|
183
|
+
{
|
|
184
|
+
name: process1Name,
|
|
185
|
+
version: process1BumpedV,
|
|
186
|
+
program: [
|
|
187
|
+
{
|
|
188
|
+
Restriction: {
|
|
189
|
+
SenderHasInputRole: {
|
|
190
|
+
index: 0,
|
|
191
|
+
role_key: 'Supplier',
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
],
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
name: process2Name,
|
|
199
|
+
version: process2BumpedV,
|
|
200
|
+
program: [
|
|
201
|
+
{
|
|
202
|
+
Restriction: {
|
|
203
|
+
SenderHasInputRole: {
|
|
204
|
+
index: 0,
|
|
205
|
+
role_key: 'Supplier',
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
],
|
|
210
|
+
},
|
|
211
|
+
]);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { createNodeApi } from '../../src/lib/utils/polkadot.js';
|
|
11
|
+
import { getVersion, getProcess } from '../../src/lib/process/api.js';
|
|
12
|
+
import { defaultOptions } from '../../src/lib/process/index.js';
|
|
13
|
+
import { utf8ToHex } from '../../src/lib/process/hex.js';
|
|
14
|
+
export const getVersionHelper = (name) => __awaiter(void 0, void 0, void 0, function* () {
|
|
15
|
+
const polkadot = yield createNodeApi(defaultOptions);
|
|
16
|
+
const version = yield getVersion(polkadot, utf8ToHex(name));
|
|
17
|
+
yield polkadot.api.disconnect();
|
|
18
|
+
return version;
|
|
19
|
+
});
|
|
20
|
+
export const Helper = (processId, version) => __awaiter(void 0, void 0, void 0, function* () {
|
|
21
|
+
const polkadot = yield createNodeApi(defaultOptions);
|
|
22
|
+
const process = yield getProcess(polkadot, processId, version);
|
|
23
|
+
yield polkadot.api.disconnect();
|
|
24
|
+
return process;
|
|
25
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { default as chai, expect, assert } from 'chai';
|
|
11
|
+
import chaiAsPromised from 'chai-as-promised';
|
|
12
|
+
chai.use(chaiAsPromised);
|
|
13
|
+
import { createProcess, disableProcess, loadProcesses } from '../../src/lib/process/index.js';
|
|
14
|
+
import { validAllRestrictions, invalidPOSIX, multiple, simple2, simple, invalidRestrictionKey, invalidRestrictionValue, } from '../fixtures/programs.js';
|
|
15
|
+
import { Constants } from '../../src/lib/process/constants.js';
|
|
16
|
+
import { getVersionHelper } from '../helpers/substrateHelper.js';
|
|
17
|
+
import { ZodError } from 'zod';
|
|
18
|
+
import { DisableError, ProgramError, VersionError } from '../../src/lib/types/error.js';
|
|
19
|
+
import { getAll } from '../../src/lib/process/api.js';
|
|
20
|
+
/* fixtures */
|
|
21
|
+
import processesExample from '../fixtures/processes.js';
|
|
22
|
+
const polkadotOptions = { API_HOST: 'localhost', API_PORT: 9944, USER_URI: '//Alice', MANUAL_SEAL: true };
|
|
23
|
+
describe('Process creation and deletion, listing', () => {
|
|
24
|
+
describe('Happy path', () => {
|
|
25
|
+
describe('Multiple processes', () => {
|
|
26
|
+
it('skips already created processes and creates new ones', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
27
|
+
yield createProcess({
|
|
28
|
+
name: 'existing-process-test',
|
|
29
|
+
version: 1,
|
|
30
|
+
program: simple2,
|
|
31
|
+
}, false, polkadotOptions);
|
|
32
|
+
const process2Name = 'process-to-be-created';
|
|
33
|
+
const process2BumpedV = (yield getVersionHelper(process2Name)) + 1;
|
|
34
|
+
const newProcesses = yield loadProcesses({
|
|
35
|
+
options: polkadotOptions,
|
|
36
|
+
data: multiple('existing-process-test', 1, process2Name, process2BumpedV),
|
|
37
|
+
});
|
|
38
|
+
if (newProcesses.type !== 'ok') {
|
|
39
|
+
expect.fail('Expected new process creation to succeed');
|
|
40
|
+
}
|
|
41
|
+
expect(newProcesses.result['existing-process-test'].type).to.equal('ok');
|
|
42
|
+
expect(newProcesses.result['existing-process-test']).to.deep.contain({
|
|
43
|
+
message: 'Skipping: process existing-process-test is already created.',
|
|
44
|
+
result: {
|
|
45
|
+
name: 'existing-process-test',
|
|
46
|
+
version: 1,
|
|
47
|
+
status: 'Enabled',
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
const process2Result = newProcesses.result[process2Name];
|
|
51
|
+
if (process2Result.type !== 'ok') {
|
|
52
|
+
expect.fail('Expected process create for process2 to succeed');
|
|
53
|
+
}
|
|
54
|
+
expect(process2Result.message).to.deep.equal('Transaction for new process process-to-be-created has been successfully submitted');
|
|
55
|
+
expect(process2Result.result).to.deep.contain({
|
|
56
|
+
version: process2BumpedV,
|
|
57
|
+
status: 'Enabled',
|
|
58
|
+
});
|
|
59
|
+
}));
|
|
60
|
+
it('creates multiple processes', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
61
|
+
const process1Name = 'process-1';
|
|
62
|
+
const process1BumpedV = (yield getVersionHelper(process1Name)) + 1;
|
|
63
|
+
const process2Name = 'process-2';
|
|
64
|
+
const process2BumpedV = (yield getVersionHelper(process2Name)) + 1;
|
|
65
|
+
const newProcesses = yield loadProcesses({
|
|
66
|
+
options: polkadotOptions,
|
|
67
|
+
data: multiple(process1Name, process1BumpedV, process2Name, process2BumpedV),
|
|
68
|
+
});
|
|
69
|
+
if (newProcesses.type !== 'ok') {
|
|
70
|
+
expect.fail('Expected new process creation to succeed');
|
|
71
|
+
}
|
|
72
|
+
expect(newProcesses.result[process1Name].message).to.deep.equal('Transaction for new process process-1 has been successfully submitted');
|
|
73
|
+
const process1Result = newProcesses.result[process1Name];
|
|
74
|
+
if (process1Result.type !== 'ok') {
|
|
75
|
+
expect.fail('Expected process1 creation to succeed');
|
|
76
|
+
}
|
|
77
|
+
expect(process1Result.result).to.deep.contain({
|
|
78
|
+
version: process1BumpedV,
|
|
79
|
+
status: 'Enabled',
|
|
80
|
+
});
|
|
81
|
+
const process2Result = newProcesses.result[process2Name];
|
|
82
|
+
if (process2Result.type !== 'ok') {
|
|
83
|
+
expect.fail('Expected process2 creation to succeed');
|
|
84
|
+
}
|
|
85
|
+
expect(process2Result.message).to.deep.equal('Transaction for new process process-2 has been successfully submitted');
|
|
86
|
+
expect(process2Result.result).to.deep.contain({
|
|
87
|
+
version: process2BumpedV,
|
|
88
|
+
status: 'Enabled',
|
|
89
|
+
});
|
|
90
|
+
}));
|
|
91
|
+
it('loads and skips multiple processes using number values', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
92
|
+
yield loadProcesses({ options: polkadotOptions, data: JSON.stringify(processesExample) });
|
|
93
|
+
const res = yield loadProcesses({ options: polkadotOptions, data: JSON.stringify(processesExample) });
|
|
94
|
+
if (res.type !== 'ok') {
|
|
95
|
+
expect.fail('Expected process create to succeed');
|
|
96
|
+
}
|
|
97
|
+
const process1Result = res.result['test-program-create'];
|
|
98
|
+
const process2Result = res.result['test-program-propose'];
|
|
99
|
+
const process3Result = res.result['test-program-strings-and-numbers'];
|
|
100
|
+
if (process1Result.type !== 'ok') {
|
|
101
|
+
expect.fail('Expected test-program-create to be already created and succeed');
|
|
102
|
+
}
|
|
103
|
+
if (process2Result.type !== 'ok') {
|
|
104
|
+
expect.fail('Expected test-program-propose to be already created and succeed');
|
|
105
|
+
}
|
|
106
|
+
if (process2Result.type !== 'ok') {
|
|
107
|
+
expect.fail('Expected test-program-strings-and-numbers to be already created and succeed');
|
|
108
|
+
}
|
|
109
|
+
expect(process1Result.message).to.equal('Skipping: process test-program-create is already created.');
|
|
110
|
+
expect(process2Result.message).to.equal('Skipping: process test-program-propose is already created.');
|
|
111
|
+
expect(process3Result.message).to.equal('Skipping: process test-program-strings-and-numbers is already created.');
|
|
112
|
+
})).timeout(60000);
|
|
113
|
+
});
|
|
114
|
+
it('creates then disables a process', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
115
|
+
const processName = '0';
|
|
116
|
+
const currentVersion = yield getVersionHelper(processName);
|
|
117
|
+
const bumpedVersion = currentVersion + 1;
|
|
118
|
+
const newProcess = yield createProcess({ name: processName, version: bumpedVersion, program: simple }, false, polkadotOptions);
|
|
119
|
+
if (newProcess.type !== 'ok') {
|
|
120
|
+
expect.fail('Expected process creation to succeed');
|
|
121
|
+
}
|
|
122
|
+
expect(newProcess.result).to.deep.equal({
|
|
123
|
+
name: processName,
|
|
124
|
+
version: bumpedVersion,
|
|
125
|
+
status: 'Enabled',
|
|
126
|
+
});
|
|
127
|
+
const disabledProcess = yield disableProcess(processName, bumpedVersion, false, polkadotOptions);
|
|
128
|
+
if (disabledProcess.type !== 'ok') {
|
|
129
|
+
expect.fail('Expected process disable to succeed');
|
|
130
|
+
}
|
|
131
|
+
expect(disabledProcess.message).to.equal('Process has been disabled');
|
|
132
|
+
expect(disabledProcess.result).to.deep.equal({
|
|
133
|
+
name: processName,
|
|
134
|
+
version: bumpedVersion,
|
|
135
|
+
status: 'Disabled',
|
|
136
|
+
});
|
|
137
|
+
}));
|
|
138
|
+
it('does not create process if dry run', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
139
|
+
const processName = '0';
|
|
140
|
+
const currentVersion = yield getVersionHelper(processName);
|
|
141
|
+
const bumpedVersion = currentVersion + 1;
|
|
142
|
+
const newProcess = yield createProcess({ name: processName, version: bumpedVersion, program: validAllRestrictions }, true, polkadotOptions);
|
|
143
|
+
if (newProcess.type !== 'ok') {
|
|
144
|
+
expect.fail('Expected process create to succeed');
|
|
145
|
+
}
|
|
146
|
+
expect(newProcess.message).to.equal('Dry run: transaction has not been created');
|
|
147
|
+
expect(newProcess.result).to.deep.equal({
|
|
148
|
+
name: processName,
|
|
149
|
+
version: bumpedVersion,
|
|
150
|
+
status: 'Enabled (dry-run)',
|
|
151
|
+
});
|
|
152
|
+
}));
|
|
153
|
+
it('does not disable process if dry run', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
154
|
+
const processName = '0';
|
|
155
|
+
const currentVersion = yield getVersionHelper(processName);
|
|
156
|
+
const bumpedVersion = currentVersion + 1;
|
|
157
|
+
const newProcess = yield createProcess({ name: processName, version: bumpedVersion, program: validAllRestrictions }, false, polkadotOptions);
|
|
158
|
+
expect(newProcess.type).to.equal('ok');
|
|
159
|
+
const disabledProcess = yield disableProcess(processName, bumpedVersion, true, polkadotOptions);
|
|
160
|
+
if (disabledProcess.type !== 'ok') {
|
|
161
|
+
expect.fail('Expected disable process to succeed');
|
|
162
|
+
}
|
|
163
|
+
expect(disabledProcess.result).to.deep.contain({
|
|
164
|
+
name: processName,
|
|
165
|
+
status: 'Disabled (dry-run)',
|
|
166
|
+
});
|
|
167
|
+
expect(disabledProcess).to.deep.contain({
|
|
168
|
+
message: `This will DISABLE the following process ${processName}`,
|
|
169
|
+
});
|
|
170
|
+
}));
|
|
171
|
+
// it('returns a list of raw processes when with --verbose flag', () => {
|
|
172
|
+
it('returns a list of processes', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
173
|
+
const res = yield getAll(polkadotOptions);
|
|
174
|
+
expect(res).to.be.an('array');
|
|
175
|
+
expect(res[0])
|
|
176
|
+
.to.be.an('object')
|
|
177
|
+
.that.has.keys(['name', 'createdAtHash', 'initialU8aLength', 'program', 'status', 'version']);
|
|
178
|
+
}));
|
|
179
|
+
});
|
|
180
|
+
describe('Sad path', () => {
|
|
181
|
+
const validProcessName = '0';
|
|
182
|
+
let validVersionNumber;
|
|
183
|
+
before(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
184
|
+
const currentVersion = yield getVersionHelper(validProcessName);
|
|
185
|
+
validVersionNumber = currentVersion + 1;
|
|
186
|
+
}));
|
|
187
|
+
describe('If process already exists', () => {
|
|
188
|
+
describe('Multiple uploads', () => {
|
|
189
|
+
// TODO could prestage in before if more scenarios
|
|
190
|
+
it('skips and notifies if process programs are different', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
191
|
+
yield createProcess({ name: 'existing-length', version: 1, program: validAllRestrictions }, false, polkadotOptions);
|
|
192
|
+
const process2Name = 'should-create-1';
|
|
193
|
+
const process2BumpedV = (yield getVersionHelper(process2Name)) + 1;
|
|
194
|
+
const res = yield loadProcesses({
|
|
195
|
+
options: polkadotOptions,
|
|
196
|
+
data: multiple('existing-length', 1, process2Name, process2BumpedV),
|
|
197
|
+
});
|
|
198
|
+
if (res.type !== 'ok') {
|
|
199
|
+
expect.fail('Expected overall create to succeed');
|
|
200
|
+
}
|
|
201
|
+
const failResult = res.result['existing-length'];
|
|
202
|
+
if (failResult.type !== 'error') {
|
|
203
|
+
expect.fail('Expected existing-length creation to fail');
|
|
204
|
+
}
|
|
205
|
+
expect(failResult.message).to.equal('existing: programs are different lengths');
|
|
206
|
+
const process2Res = res.result[process2Name];
|
|
207
|
+
if (process2Res.type !== 'ok') {
|
|
208
|
+
expect.fail(`Expected ${process2Name} creation to succeed`);
|
|
209
|
+
}
|
|
210
|
+
expect(process2Res.message).to.equal('Transaction for new process should-create-1 has been successfully submitted');
|
|
211
|
+
}));
|
|
212
|
+
it('also fails if number of steps matches but POSTFIX does not', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
213
|
+
yield createProcess({ name: 'existing-steps', version: 1, program: simple }, false, polkadotOptions);
|
|
214
|
+
const process2Name = 'should-create-2';
|
|
215
|
+
const process2BumpedV = (yield getVersionHelper(process2Name)) + 1;
|
|
216
|
+
const res = yield loadProcesses({
|
|
217
|
+
options: polkadotOptions,
|
|
218
|
+
data: multiple('existing-steps', 1, process2Name, process2BumpedV),
|
|
219
|
+
});
|
|
220
|
+
// TODO: should this fail
|
|
221
|
+
if (res.type !== 'ok') {
|
|
222
|
+
expect.fail('Expected overall process create to succeed');
|
|
223
|
+
}
|
|
224
|
+
expect(res.result['existing-steps'].message).to.equal('existing: program steps did not match');
|
|
225
|
+
expect(res.result[process2Name].message).to.equal('Transaction for new process should-create-2 has been successfully submitted');
|
|
226
|
+
}));
|
|
227
|
+
});
|
|
228
|
+
it('does not create new one and notifies if programs are different length', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
229
|
+
yield createProcess({ name: 'existing-single', version: 1, program: validAllRestrictions }, false, polkadotOptions);
|
|
230
|
+
const res = yield createProcess({ name: 'existing-single', version: 1, program: simple }, false, polkadotOptions);
|
|
231
|
+
if (res.type !== 'error') {
|
|
232
|
+
expect.fail('Expected program create with different lengths to fail');
|
|
233
|
+
}
|
|
234
|
+
expect(res.message).to.equal('existing: programs are different lengths');
|
|
235
|
+
expect(res.error).to.instanceOf(ProgramError);
|
|
236
|
+
}));
|
|
237
|
+
it('does not create new one and notifies if programs same are length but do not match', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
238
|
+
yield createProcess({ name: 'existing-steps-single', version: 1, program: simple2 }, false, polkadotOptions);
|
|
239
|
+
const res = yield createProcess({ name: 'existing-steps-single', version: 1, program: [{ Restriction: 'None' }] }, false, polkadotOptions);
|
|
240
|
+
if (res.type !== 'error') {
|
|
241
|
+
expect.fail('Expected program create with different lengths to fail');
|
|
242
|
+
}
|
|
243
|
+
expect(res.message).to.equal('existing: program steps did not match');
|
|
244
|
+
expect(res.error).to.instanceOf(ProgramError);
|
|
245
|
+
const error = res.error;
|
|
246
|
+
expect(error.process).to.deep.contain({
|
|
247
|
+
name: 'existing-steps-single',
|
|
248
|
+
version: 1,
|
|
249
|
+
status: 'Enabled',
|
|
250
|
+
});
|
|
251
|
+
}));
|
|
252
|
+
});
|
|
253
|
+
it('fails for invalid POSTFIX notation', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
254
|
+
const res = yield createProcess({ name: validProcessName, version: validVersionNumber, program: invalidPOSIX }, false, polkadotOptions);
|
|
255
|
+
if (res.type !== 'error') {
|
|
256
|
+
expect.fail('Expected process create to fail');
|
|
257
|
+
}
|
|
258
|
+
expect(res.error).to.be.instanceOf(ProgramError);
|
|
259
|
+
expect(res.message).to.equal('invalid program');
|
|
260
|
+
}));
|
|
261
|
+
it('fails for invalid restriction key', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
262
|
+
const res = yield createProcess({
|
|
263
|
+
name: validProcessName,
|
|
264
|
+
version: validVersionNumber,
|
|
265
|
+
program: invalidRestrictionKey,
|
|
266
|
+
}, false, polkadotOptions);
|
|
267
|
+
if (res.type !== 'error') {
|
|
268
|
+
expect.fail('Expected process create to fail');
|
|
269
|
+
}
|
|
270
|
+
expect(res.error).to.be.instanceOf(ZodError);
|
|
271
|
+
const zError = res.error;
|
|
272
|
+
expect(zError.issues[0]).to.deep.contain({
|
|
273
|
+
code: 'invalid_union',
|
|
274
|
+
message: 'Invalid input',
|
|
275
|
+
});
|
|
276
|
+
}));
|
|
277
|
+
it('fails for invalid restriction value', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
278
|
+
const res = yield createProcess({ name: validProcessName, version: validVersionNumber, program: invalidRestrictionValue }, false, polkadotOptions);
|
|
279
|
+
if (res.type !== 'error') {
|
|
280
|
+
expect.fail('Expected process create to fail');
|
|
281
|
+
}
|
|
282
|
+
expect(res.error).to.be.instanceOf(ZodError);
|
|
283
|
+
}));
|
|
284
|
+
it('fails for invalid json', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
285
|
+
const res = yield createProcess({ name: validProcessName, version: validVersionNumber, program: 'invalidJson' }, false, polkadotOptions);
|
|
286
|
+
if (res.type !== 'error') {
|
|
287
|
+
expect.fail('Expected process create to fail');
|
|
288
|
+
}
|
|
289
|
+
expect(res.error).to.be.instanceOf(ZodError);
|
|
290
|
+
}));
|
|
291
|
+
it('fails to create for too low version', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
292
|
+
// - 2 because -1 would make current = valid
|
|
293
|
+
const res = yield createProcess({ name: validProcessName, version: validVersionNumber - 2, program: validAllRestrictions }, false, polkadotOptions);
|
|
294
|
+
if (res.type !== 'error') {
|
|
295
|
+
expect.fail('Expected process create to fail');
|
|
296
|
+
}
|
|
297
|
+
expect(res.message).to.equal(`Process version ${validVersionNumber - 2} is invalid. If you are trying to create a new version of process ${validProcessName} version should be ${validVersionNumber}`);
|
|
298
|
+
expect(res.error).to.be.instanceOf(VersionError);
|
|
299
|
+
}));
|
|
300
|
+
it('fails to create for too high version', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
301
|
+
const res = yield createProcess({ name: validProcessName, version: validVersionNumber + 1, program: validAllRestrictions }, false, polkadotOptions);
|
|
302
|
+
if (res.type !== 'error') {
|
|
303
|
+
expect.fail('Expected process create to fail');
|
|
304
|
+
}
|
|
305
|
+
expect(res.message).to.equal(`Process version ${validVersionNumber + 1} is invalid. If you are trying to create a new version of process ${validProcessName} version should be ${validVersionNumber}`);
|
|
306
|
+
expect(res.error).to.be.instanceOf(VersionError);
|
|
307
|
+
}));
|
|
308
|
+
it('fails to create with too long process id', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
309
|
+
const processName = '0'.repeat(Constants.PROCESS_ID_LENGTH + 1);
|
|
310
|
+
const res = yield createProcess({ name: processName, version: 1, program: validAllRestrictions }, false, polkadotOptions);
|
|
311
|
+
if (res.type !== 'error') {
|
|
312
|
+
expect.fail('Expected process create to fail');
|
|
313
|
+
}
|
|
314
|
+
expect(res.error).to.be.instanceOf(ZodError);
|
|
315
|
+
}));
|
|
316
|
+
it('fails to disable process that does not exist', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
317
|
+
return assert.isRejected(disableProcess('incorrectProcessName', 1, false, polkadotOptions), DisableError);
|
|
318
|
+
}));
|
|
319
|
+
it('fails to disable process a second time', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
320
|
+
const newProcess = yield createProcess({ name: validProcessName, version: validVersionNumber, program: simple }, false, polkadotOptions);
|
|
321
|
+
expect(newProcess.type).to.equal('ok');
|
|
322
|
+
const firstDisable = yield disableProcess(validProcessName, validVersionNumber, false, polkadotOptions);
|
|
323
|
+
expect(firstDisable.type).to.equal('ok');
|
|
324
|
+
return assert.isRejected(disableProcess(validProcessName, validVersionNumber, false, polkadotOptions), DisableError);
|
|
325
|
+
}));
|
|
326
|
+
});
|
|
327
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@digicatapult/sqnc-process-management",
|
|
3
|
+
"version": "2.2.0",
|
|
4
|
+
"description": "SQNC Process Management Flow",
|
|
5
|
+
"main": "./lib/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"process-management": "./build/src/index.js"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"start": "node --loader ts-node/esm src/index.ts",
|
|
12
|
+
"local": "npm i -g && process-management",
|
|
13
|
+
"dev": "nodemon --watch 'src/**/*.ts' --exec node --loader ts-node/esm src/index.ts",
|
|
14
|
+
"lint": "eslint . --ext .ts",
|
|
15
|
+
"build": "tsc --build",
|
|
16
|
+
"depcheck": "depcheck",
|
|
17
|
+
"test": "ts-mocha --config ./tests/mocharc.json -n loader=ts-node/esm -p tsconfig.json tests/**/*.test.ts --exit",
|
|
18
|
+
"test:unit": "ts-mocha --config ./tests/mocharc.json -n loader=ts-node/esm -p tsconfig.json src/**/*.test.ts --exit",
|
|
19
|
+
"prettier": "npx prettier --write ."
|
|
20
|
+
},
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/digicatapult/sqnc-process-management.git"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"/build"
|
|
27
|
+
],
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=20.x.x",
|
|
30
|
+
"npm": ">=10.x.x"
|
|
31
|
+
},
|
|
32
|
+
"author": "Digital Catapult",
|
|
33
|
+
"license": "Apache-2.0",
|
|
34
|
+
"bugs": {
|
|
35
|
+
"url": "https://github.com/digicatapult/sqnc-process-management/issues"
|
|
36
|
+
},
|
|
37
|
+
"homepage": "https://github.com/digicatapult/sqnc-process-management#readme",
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@types/chai": "^4.3.11",
|
|
40
|
+
"@types/chai-as-promised": "^7.1.8",
|
|
41
|
+
"@types/mocha": "^10.0.6",
|
|
42
|
+
"@types/node": "^18.19.4",
|
|
43
|
+
"@typescript-eslint/eslint-plugin": "^6.17.0",
|
|
44
|
+
"@typescript-eslint/parser": "^6.17.0",
|
|
45
|
+
"chai": "^4.3.10",
|
|
46
|
+
"chai-as-promised": "^7.1.1",
|
|
47
|
+
"depcheck": "^1.4.7",
|
|
48
|
+
"eslint": "^8.56.0",
|
|
49
|
+
"eslint-config-prettier": "^9.1.0",
|
|
50
|
+
"eslint-plugin-prettier": "^5.1.2",
|
|
51
|
+
"mocha": "^10.2.0",
|
|
52
|
+
"nodemon": "^3.0.2",
|
|
53
|
+
"prettier": "^3.1.1",
|
|
54
|
+
"ts-mocha": "^10.0.0",
|
|
55
|
+
"ts-node": "^10.9.2"
|
|
56
|
+
},
|
|
57
|
+
"dependencies": {
|
|
58
|
+
"@polkadot/api": "^10.11.2",
|
|
59
|
+
"chalk": "^5.3.0",
|
|
60
|
+
"commander": "^11.1.0",
|
|
61
|
+
"typescript": "^5.3.3",
|
|
62
|
+
"zod": "^3.22.4"
|
|
63
|
+
}
|
|
64
|
+
}
|