dataverse-utils 2.2.10 → 2.2.13
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/README.md +24 -0
- package/lib/assemblyDeploy.js +29 -0
- package/lib/auth.js +44 -0
- package/lib/cachePlugin.js +97 -0
- package/lib/dataverse.service.js +68 -0
- package/lib/deploy.js +79 -0
- package/lib/generate.js +99 -0
- package/lib/index.js +44 -0
- package/lib/logger.js +37 -0
- package/lib/models/pluginAssembly.js +96 -0
- package/lib/models/pluginImage.js +61 -0
- package/lib/models/pluginStep.js +98 -0
- package/lib/models/pluginType.js +63 -0
- package/lib/models/webResource.js +131 -0
- package/lib/webResourceDeploy.js +29 -0
- package/license +21 -0
- package/package.json +5 -5
package/README.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# dataverse-utils
|
|
2
|
+
| NPM |
|
|
3
|
+
| --- |
|
|
4
|
+
| [](https://www.npmjs.com/package/dataverse-utils) |
|
|
5
|
+
|
|
6
|
+
Utilities for interacting with Dataverse environments
|
|
7
|
+
|
|
8
|
+
# Deploy
|
|
9
|
+
|
|
10
|
+
Deployment configuration is stored in dataverse.config.json. Access token will be acquired via device-code flow.
|
|
11
|
+
|
|
12
|
+
```sh
|
|
13
|
+
dataverse-utils deploy webresource
|
|
14
|
+
|
|
15
|
+
dataverse-utils deploy assembly
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
# Generate Early-Bound TS Files
|
|
19
|
+
|
|
20
|
+
Generate early bound TypeScript files for tables. Access token will be acquired via device-code flow.
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
dataverse-utils generate account
|
|
24
|
+
```
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.deployAssembly = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const pluginAssembly_1 = require("./models/pluginAssembly");
|
|
10
|
+
const logger_1 = require("./logger");
|
|
11
|
+
async function deployAssembly(creds, apiConfig) {
|
|
12
|
+
const currentPath = '.';
|
|
13
|
+
const configFile = await fs_1.default.promises.readFile(path_1.default.resolve(currentPath, 'dataverse.config.json'), 'utf8');
|
|
14
|
+
if (configFile == null) {
|
|
15
|
+
logger_1.logger.warn('unable to find dataverse.config.json file');
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const config = JSON.parse(configFile);
|
|
19
|
+
logger_1.logger.info('deploy assembly');
|
|
20
|
+
try {
|
|
21
|
+
await (0, pluginAssembly_1.deploy)(config, apiConfig, creds.solution);
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
logger_1.logger.error(error.message);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
logger_1.logger.done(`deployed assembly ${config.name}\r\n`);
|
|
28
|
+
}
|
|
29
|
+
exports.deployAssembly = deployAssembly;
|
package/lib/auth.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getAccessToken = void 0;
|
|
4
|
+
const cachePlugin_1 = require("./cachePlugin");
|
|
5
|
+
const msal_node_1 = require("@azure/msal-node");
|
|
6
|
+
const logger_1 = require("./logger");
|
|
7
|
+
const clientId = '51f81489-12ee-4a9e-aaae-a2591f45987d';
|
|
8
|
+
const getAccessToken = async (tenant, url) => {
|
|
9
|
+
const config = {
|
|
10
|
+
auth: {
|
|
11
|
+
clientId: clientId,
|
|
12
|
+
authority: `https://login.microsoftonline.com/${tenant}/`
|
|
13
|
+
},
|
|
14
|
+
cache: {
|
|
15
|
+
cachePlugin: (0, cachePlugin_1.cachePlugin)(url)
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
const pca = new msal_node_1.PublicClientApplication(config);
|
|
19
|
+
const cache = pca.getTokenCache();
|
|
20
|
+
const accounts = await cache?.getAllAccounts().catch(ex => {
|
|
21
|
+
throw new Error(ex.message);
|
|
22
|
+
});
|
|
23
|
+
// Try to get token silently
|
|
24
|
+
if (accounts.length > 0) {
|
|
25
|
+
const silentToken = await pca.acquireTokenSilent({
|
|
26
|
+
account: accounts[0],
|
|
27
|
+
scopes: [`${url}/.default`]
|
|
28
|
+
}).catch(ex => {
|
|
29
|
+
throw new Error(ex.message);
|
|
30
|
+
});
|
|
31
|
+
if (silentToken) {
|
|
32
|
+
return silentToken;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// Acquire token by device code
|
|
36
|
+
const token = await pca.acquireTokenByDeviceCode({
|
|
37
|
+
scopes: [`${url}/.default`],
|
|
38
|
+
deviceCodeCallback: (response) => logger_1.logger.info(response.message)
|
|
39
|
+
}).catch(ex => {
|
|
40
|
+
throw new Error(ex.message);
|
|
41
|
+
});
|
|
42
|
+
return token;
|
|
43
|
+
};
|
|
44
|
+
exports.getAccessToken = getAccessToken;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.cachePlugin = exports.deleteCache = exports.cacheExists = exports.getCachePath = void 0;
|
|
7
|
+
const os_1 = __importDefault(require("os"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const cryptr_1 = __importDefault(require("cryptr"));
|
|
11
|
+
const encrypt = (text) => {
|
|
12
|
+
const user = os_1.default.userInfo().username;
|
|
13
|
+
const cryptr = new cryptr_1.default(user);
|
|
14
|
+
const encrypted = cryptr.encrypt(text);
|
|
15
|
+
return encrypted;
|
|
16
|
+
};
|
|
17
|
+
const decrypt = (text) => {
|
|
18
|
+
const user = os_1.default.userInfo().username;
|
|
19
|
+
const cryptr = new cryptr_1.default(user);
|
|
20
|
+
const decrypted = cryptr.decrypt(text);
|
|
21
|
+
return decrypted;
|
|
22
|
+
};
|
|
23
|
+
const getCachePath = (url) => {
|
|
24
|
+
const org = url.replace('https://', '').split('.')[0];
|
|
25
|
+
if (!fs_1.default.existsSync(path_1.default.join(os_1.default.homedir(), './.dataverse-utils/'))) {
|
|
26
|
+
fs_1.default.mkdirSync(path_1.default.join(os_1.default.homedir(), './.dataverse-utils/'));
|
|
27
|
+
}
|
|
28
|
+
return path_1.default.join(os_1.default.homedir(), `./.dataverse-utils/${org}.json`);
|
|
29
|
+
};
|
|
30
|
+
exports.getCachePath = getCachePath;
|
|
31
|
+
const cacheExists = (url) => {
|
|
32
|
+
const cacheLocation = (0, exports.getCachePath)(url);
|
|
33
|
+
return fs_1.default.existsSync(cacheLocation);
|
|
34
|
+
};
|
|
35
|
+
exports.cacheExists = cacheExists;
|
|
36
|
+
const deleteCache = (url) => {
|
|
37
|
+
const cacheLocation = (0, exports.getCachePath)(url);
|
|
38
|
+
if (fs_1.default.existsSync(cacheLocation)) {
|
|
39
|
+
fs_1.default.unlinkSync(cacheLocation);
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
exports.deleteCache = deleteCache;
|
|
47
|
+
const cachePlugin = (url) => {
|
|
48
|
+
const cacheLocation = (0, exports.getCachePath)(url);
|
|
49
|
+
const beforeCacheAccess = (tokenCacheContext) => {
|
|
50
|
+
return new Promise((resolve, reject) => {
|
|
51
|
+
if (fs_1.default.existsSync(cacheLocation)) {
|
|
52
|
+
fs_1.default.readFile(cacheLocation, 'utf-8', (err, data) => {
|
|
53
|
+
if (err) {
|
|
54
|
+
reject();
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
const decrypted = decrypt(data);
|
|
58
|
+
tokenCacheContext.tokenCache.deserialize(decrypted);
|
|
59
|
+
resolve();
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
const encrypted = encrypt(tokenCacheContext.tokenCache.serialize());
|
|
65
|
+
fs_1.default.writeFile(cacheLocation, encrypted, (err) => {
|
|
66
|
+
if (err) {
|
|
67
|
+
reject();
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
resolve();
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
const afterCacheAccess = (tokenCacheContext) => {
|
|
77
|
+
return new Promise((resolve, reject) => {
|
|
78
|
+
if (tokenCacheContext.cacheHasChanged) {
|
|
79
|
+
const encrypted = encrypt(tokenCacheContext.tokenCache.serialize());
|
|
80
|
+
fs_1.default.writeFile(cacheLocation, encrypted, (err) => {
|
|
81
|
+
if (err) {
|
|
82
|
+
reject(err);
|
|
83
|
+
}
|
|
84
|
+
resolve();
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
resolve();
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
};
|
|
92
|
+
return {
|
|
93
|
+
beforeCacheAccess,
|
|
94
|
+
afterCacheAccess
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
exports.cachePlugin = cachePlugin;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getTableMetadata = exports.publish = exports.addToSolution = exports.ComponentType = void 0;
|
|
4
|
+
const node_1 = require("dataverse-webapi/lib/node");
|
|
5
|
+
var ComponentType;
|
|
6
|
+
(function (ComponentType) {
|
|
7
|
+
ComponentType[ComponentType["WebResource"] = 61] = "WebResource";
|
|
8
|
+
ComponentType[ComponentType["PluginType"] = 90] = "PluginType";
|
|
9
|
+
ComponentType[ComponentType["PluginAssembly"] = 91] = "PluginAssembly";
|
|
10
|
+
ComponentType[ComponentType["SDKMessageProcessingStep"] = 92] = "SDKMessageProcessingStep";
|
|
11
|
+
ComponentType[ComponentType["SDKMessageProcessingStepImage"] = 93] = "SDKMessageProcessingStepImage";
|
|
12
|
+
})(ComponentType = exports.ComponentType || (exports.ComponentType = {}));
|
|
13
|
+
async function addToSolution(id, solution, type, apiConfig) {
|
|
14
|
+
const data = {
|
|
15
|
+
ComponentId: id,
|
|
16
|
+
ComponentType: type,
|
|
17
|
+
SolutionUniqueName: solution,
|
|
18
|
+
AddRequiredComponents: false,
|
|
19
|
+
IncludedComponentSettingsValues: null
|
|
20
|
+
};
|
|
21
|
+
await (0, node_1.unboundAction)(apiConfig, 'AddSolutionComponent', data);
|
|
22
|
+
}
|
|
23
|
+
exports.addToSolution = addToSolution;
|
|
24
|
+
async function publish(publishXml, apiConfig) {
|
|
25
|
+
const data = {
|
|
26
|
+
ParameterXml: `<importexportxml><webresources>${publishXml}</webresources></importexportxml>`
|
|
27
|
+
};
|
|
28
|
+
await (0, node_1.unboundAction)(apiConfig, 'PublishXml', data);
|
|
29
|
+
}
|
|
30
|
+
exports.publish = publish;
|
|
31
|
+
async function getTableMetadata(table, apiConfig) {
|
|
32
|
+
const options = [
|
|
33
|
+
'?$select=DisplayName,LogicalName,EntitySetName,SchemaName',
|
|
34
|
+
'&$expand=Attributes($select=LogicalName,SchemaName)'
|
|
35
|
+
].join('');
|
|
36
|
+
const metadata = await (0, node_1.retrieveMultiple)(apiConfig, `EntityDefinitions(LogicalName='${table}')`, options);
|
|
37
|
+
if (metadata == null) {
|
|
38
|
+
throw Error(`Table ${table} not found in metadata cache`);
|
|
39
|
+
}
|
|
40
|
+
const choiceOptions = [
|
|
41
|
+
'?$select=attributevalue,value,attributename',
|
|
42
|
+
`&$filter=objecttypecode eq '${table}'`
|
|
43
|
+
].join('');
|
|
44
|
+
const choiceMetadata = await (0, node_1.retrieveMultiple)(apiConfig, 'stringmaps', choiceOptions);
|
|
45
|
+
const tableMetadata = {
|
|
46
|
+
logicalName: metadata.LogicalName,
|
|
47
|
+
schemaName: metadata.SchemaName,
|
|
48
|
+
entitySetName: metadata.EntitySetName,
|
|
49
|
+
choices: [],
|
|
50
|
+
fields: metadata.Attributes.map((a) => {
|
|
51
|
+
return {
|
|
52
|
+
logicalName: a.LogicalName,
|
|
53
|
+
schemaName: a.SchemaName
|
|
54
|
+
};
|
|
55
|
+
})
|
|
56
|
+
};
|
|
57
|
+
choiceMetadata.value.forEach((c) => {
|
|
58
|
+
const index = tableMetadata.choices.findIndex(x => x.column === c.attributename);
|
|
59
|
+
if (index === -1) {
|
|
60
|
+
tableMetadata.choices.push({ column: c.attributename, options: [{ text: c.value, value: c.attributevalue }] });
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
tableMetadata.choices[index].options.push({ text: c.value, value: c.attributevalue });
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
return tableMetadata;
|
|
67
|
+
}
|
|
68
|
+
exports.getTableMetadata = getTableMetadata;
|
package/lib/deploy.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const prompts_1 = __importDefault(require("prompts"));
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const logger_1 = require("./logger");
|
|
10
|
+
const assemblyDeploy_1 = require("./assemblyDeploy");
|
|
11
|
+
const webResourceDeploy_1 = require("./webResourceDeploy");
|
|
12
|
+
const node_1 = require("dataverse-webapi/lib/node");
|
|
13
|
+
const auth_1 = require("./auth");
|
|
14
|
+
const cachePlugin_1 = require("./cachePlugin");
|
|
15
|
+
const onTokenFailure = async (url, error) => {
|
|
16
|
+
if (error) {
|
|
17
|
+
logger_1.logger.error(`failed to acquire access token: ${error}`);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
logger_1.logger.error('failed to acquire access token');
|
|
21
|
+
}
|
|
22
|
+
if ((0, cachePlugin_1.cacheExists)(url)) {
|
|
23
|
+
const { deleteToken } = await (0, prompts_1.default)({
|
|
24
|
+
type: 'confirm',
|
|
25
|
+
name: 'deleteToken',
|
|
26
|
+
message: `delete current token cache for ${url}?`
|
|
27
|
+
});
|
|
28
|
+
if (deleteToken) {
|
|
29
|
+
(0, cachePlugin_1.deleteCache)(url);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
async function deploy(type, files) {
|
|
34
|
+
if (!type || (type !== 'webresource' && type !== 'assembly')) {
|
|
35
|
+
const invalid = type !== undefined && type !== 'webresource' && type !== 'assembly';
|
|
36
|
+
const invalidMessage = invalid ? `${type} is not a valid project type.` : '';
|
|
37
|
+
const { typePrompt } = await (0, prompts_1.default)({
|
|
38
|
+
type: 'select',
|
|
39
|
+
name: 'typePrompt',
|
|
40
|
+
message: `${invalidMessage} select project type to deploy`,
|
|
41
|
+
choices: [
|
|
42
|
+
{ title: 'web resource', value: 'webresource' },
|
|
43
|
+
{ title: 'plugin or workflow activity', value: 'assembly' }
|
|
44
|
+
]
|
|
45
|
+
});
|
|
46
|
+
type = typePrompt;
|
|
47
|
+
}
|
|
48
|
+
const currentPath = '.';
|
|
49
|
+
const credsFile = await fs_1.default.promises.readFile(path_1.default.resolve(currentPath, 'dataverse.config.json'), 'utf8');
|
|
50
|
+
if (credsFile == null) {
|
|
51
|
+
logger_1.logger.warn('unable to find dataverse.config.json file');
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const creds = JSON.parse(credsFile).connection;
|
|
55
|
+
let token = null;
|
|
56
|
+
try {
|
|
57
|
+
token = await (0, auth_1.getAccessToken)(creds.tenant, creds.server);
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
onTokenFailure(creds.server, error.message);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (token == null || token.accessToken == null) {
|
|
64
|
+
onTokenFailure(creds.server);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const apiConfig = new node_1.WebApiConfig('8.2', token.accessToken, creds.server);
|
|
68
|
+
switch (type) {
|
|
69
|
+
case 'webresource':
|
|
70
|
+
await (0, webResourceDeploy_1.deployWebResource)(creds, apiConfig, files);
|
|
71
|
+
break;
|
|
72
|
+
case 'assembly':
|
|
73
|
+
await (0, assemblyDeploy_1.deployAssembly)(creds, apiConfig);
|
|
74
|
+
break;
|
|
75
|
+
default:
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
exports.default = deploy;
|
package/lib/generate.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const prompts_1 = __importDefault(require("prompts"));
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const logger_1 = require("./logger");
|
|
10
|
+
const dataverse_service_1 = require("./dataverse.service");
|
|
11
|
+
const node_1 = require("dataverse-webapi/lib/node");
|
|
12
|
+
const auth_1 = require("./auth");
|
|
13
|
+
async function generate(table) {
|
|
14
|
+
while (!table) {
|
|
15
|
+
const { tablePrompt } = await (0, prompts_1.default)({
|
|
16
|
+
type: 'text',
|
|
17
|
+
name: 'tablePrompt',
|
|
18
|
+
message: `enter table to generate`
|
|
19
|
+
});
|
|
20
|
+
table = tablePrompt;
|
|
21
|
+
}
|
|
22
|
+
const currentPath = '.';
|
|
23
|
+
const credsFile = await fs_1.default.promises.readFile(path_1.default.resolve(currentPath, 'dataverse.config.json'), 'utf8');
|
|
24
|
+
if (credsFile == null) {
|
|
25
|
+
logger_1.logger.warn('unable to find dataverse.config.json file');
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const creds = JSON.parse(credsFile).connection;
|
|
29
|
+
let token = null;
|
|
30
|
+
try {
|
|
31
|
+
token = await (0, auth_1.getAccessToken)(creds.tenant, creds.server);
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
logger_1.logger.error(`failed to acquire access token: ${error.message}`);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (token == null || token.accessToken == null) {
|
|
38
|
+
logger_1.logger.error('failed to acquire access token');
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const apiConfig = new node_1.WebApiConfig('8.2', token.accessToken, creds.server);
|
|
42
|
+
let metadata = {};
|
|
43
|
+
logger_1.logger.info('Retrieve table metadata');
|
|
44
|
+
try {
|
|
45
|
+
metadata = await (0, dataverse_service_1.getTableMetadata)(table, apiConfig);
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
logger_1.logger.error(error.message);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
// Build code file from metadata
|
|
52
|
+
const codeFile = [
|
|
53
|
+
`class ${metadata.schemaName} {`,
|
|
54
|
+
'\r\n',
|
|
55
|
+
` LogicalName = '${metadata.logicalName}';`,
|
|
56
|
+
'\r\n',
|
|
57
|
+
` SchemaName = '${metadata.schemaName}';`,
|
|
58
|
+
'\r\n',
|
|
59
|
+
` EntitySetName = '${metadata.entitySetName}';`,
|
|
60
|
+
'\r\n',
|
|
61
|
+
'\r\n',
|
|
62
|
+
' Fields = {',
|
|
63
|
+
'\r\n',
|
|
64
|
+
metadata.fields.map(f => {
|
|
65
|
+
return ` '${f.schemaName}': '${f.logicalName}'`;
|
|
66
|
+
}).join(',\r\n'),
|
|
67
|
+
'\r\n',
|
|
68
|
+
' }',
|
|
69
|
+
'\r\n',
|
|
70
|
+
'\r\n',
|
|
71
|
+
metadata.choices.map(c => {
|
|
72
|
+
const field = metadata.fields.find(f => f.logicalName === c.column);
|
|
73
|
+
return ` ${field?.schemaName ?? c.column} = ${metadata.schemaName}_${field?.schemaName ?? c.column};`;
|
|
74
|
+
}).join('\r\n'),
|
|
75
|
+
'\r\n',
|
|
76
|
+
'}',
|
|
77
|
+
'\r\n',
|
|
78
|
+
'\r\n',
|
|
79
|
+
metadata.choices.map(c => {
|
|
80
|
+
const field = metadata.fields.find(f => f.logicalName === c.column);
|
|
81
|
+
return [
|
|
82
|
+
`export enum ${metadata.schemaName}_${field?.schemaName ?? c.column} {`,
|
|
83
|
+
'\r\n',
|
|
84
|
+
c.options.map(x => ` '${x.text.replace(`'`, `\\'`)}' = ${x.value}`).join(',\r\n'),
|
|
85
|
+
'\r\n',
|
|
86
|
+
'}'
|
|
87
|
+
].join('');
|
|
88
|
+
}).join('\r\n\r\n'),
|
|
89
|
+
'\r\n',
|
|
90
|
+
'\r\n',
|
|
91
|
+
`export default new ${metadata.schemaName}();`
|
|
92
|
+
].join('');
|
|
93
|
+
if (!fs_1.default.existsSync(path_1.default.resolve(currentPath, 'src', 'scripts', 'models'))) {
|
|
94
|
+
fs_1.default.mkdirSync(path_1.default.resolve(currentPath, 'src', 'scripts', 'models'));
|
|
95
|
+
}
|
|
96
|
+
fs_1.default.writeFileSync(path_1.default.resolve(currentPath, 'src', 'scripts', 'models', `${metadata.schemaName}.ts`), codeFile);
|
|
97
|
+
logger_1.logger.done(`Table metadata output to models/${metadata.schemaName}.ts`);
|
|
98
|
+
}
|
|
99
|
+
exports.default = generate;
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const deploy_1 = __importDefault(require("./deploy"));
|
|
9
|
+
const generate_1 = __importDefault(require("./generate"));
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
11
|
+
const packageJson = require('../package.json');
|
|
12
|
+
commander_1.program
|
|
13
|
+
.version(packageJson.version)
|
|
14
|
+
.usage('<command> [options]');
|
|
15
|
+
// Deploy command
|
|
16
|
+
commander_1.program
|
|
17
|
+
.command('deploy')
|
|
18
|
+
.description('Deploy file(s) to dataverse (webresource, plugin, workflow)')
|
|
19
|
+
.argument('[type]', 'Type of project to deploy')
|
|
20
|
+
.argument('[files]', 'Comma separate list of files to deploy')
|
|
21
|
+
.action((type, files) => {
|
|
22
|
+
(0, deploy_1.default)(type, files);
|
|
23
|
+
});
|
|
24
|
+
// Generate command
|
|
25
|
+
commander_1.program
|
|
26
|
+
.command('generate')
|
|
27
|
+
.description('Generate early-bound TypeScript file for specified table')
|
|
28
|
+
.argument('[table]', 'Table to generate')
|
|
29
|
+
.action((table) => {
|
|
30
|
+
(0, generate_1.default)(table);
|
|
31
|
+
});
|
|
32
|
+
// Show help on unknown command
|
|
33
|
+
commander_1.program
|
|
34
|
+
.arguments('<command>')
|
|
35
|
+
.action((cmd) => {
|
|
36
|
+
commander_1.program.outputHelp();
|
|
37
|
+
console.log();
|
|
38
|
+
console.log(`Unknown command ${cmd}.`);
|
|
39
|
+
console.log();
|
|
40
|
+
});
|
|
41
|
+
commander_1.program.parse(process.argv);
|
|
42
|
+
if (!process.argv.slice(2).length) {
|
|
43
|
+
commander_1.program.outputHelp();
|
|
44
|
+
}
|
package/lib/logger.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.logger = exports.icons = void 0;
|
|
7
|
+
const kleur_1 = __importDefault(require("kleur"));
|
|
8
|
+
const figures_1 = __importDefault(require("figures"));
|
|
9
|
+
const isTest = process.env.JEST_WORKER_ID !== undefined;
|
|
10
|
+
exports.icons = {
|
|
11
|
+
done: kleur_1.default.green(figures_1.default.tick),
|
|
12
|
+
info: kleur_1.default.cyan(figures_1.default.pointer),
|
|
13
|
+
error: kleur_1.default.red(figures_1.default.cross),
|
|
14
|
+
warn: kleur_1.default.yellow(figures_1.default.warning)
|
|
15
|
+
};
|
|
16
|
+
exports.logger = {
|
|
17
|
+
info(...args) {
|
|
18
|
+
if (!isTest) {
|
|
19
|
+
console.info(exports.icons.info, ...args);
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
warn(...args) {
|
|
23
|
+
if (!isTest) {
|
|
24
|
+
console.warn(exports.icons.warn, ...args);
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
error(...args) {
|
|
28
|
+
if (!isTest) {
|
|
29
|
+
console.error(exports.icons.error, ...args);
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
done(...args) {
|
|
33
|
+
if (!isTest) {
|
|
34
|
+
console.info(exports.icons.done, ...args);
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.deploy = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const glob_1 = __importDefault(require("glob"));
|
|
9
|
+
const node_1 = require("dataverse-webapi/lib/node");
|
|
10
|
+
const pluginType_1 = require("./pluginType");
|
|
11
|
+
const dataverse_service_1 = require("../dataverse.service");
|
|
12
|
+
const logger_1 = require("../logger");
|
|
13
|
+
async function deploy(config, apiConfig, solution) {
|
|
14
|
+
const files = glob_1.default.sync(`**/${config.name}.dll`);
|
|
15
|
+
if (files.length === 0) {
|
|
16
|
+
logger_1.logger.warn(`assembly ${config.name}.dll not found`);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const content = (await fs_1.default.promises.readFile(files[0])).toString('base64');
|
|
20
|
+
let assemblyId = '';
|
|
21
|
+
try {
|
|
22
|
+
assemblyId = await retrieveAssembly(config.name, apiConfig);
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
logger_1.logger.error(`failed to retrieve assembly ${config.name}: ${error.message}`);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (assemblyId != '') {
|
|
29
|
+
try {
|
|
30
|
+
await updateAssembly(assemblyId, config, content, apiConfig);
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
throw new Error(`failed to update assembly: ${error.message}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
try {
|
|
38
|
+
assemblyId = await createAssembly(config, content, apiConfig);
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
throw new Error(`failed to create assembly: ${error.message}`);
|
|
42
|
+
}
|
|
43
|
+
if (solution != undefined) {
|
|
44
|
+
try {
|
|
45
|
+
await (0, dataverse_service_1.addToSolution)(assemblyId, solution, dataverse_service_1.ComponentType.PluginAssembly, apiConfig);
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
logger_1.logger.error(`failed to add to solution: ${error.message}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (config.types != null) {
|
|
53
|
+
try {
|
|
54
|
+
const promises = config.types.map(async (type) => {
|
|
55
|
+
type['pluginassemblyid@odata.bind'] = `/pluginassemblies(${assemblyId})`;
|
|
56
|
+
await (0, pluginType_1.deployType)(type, assemblyId, apiConfig, solution);
|
|
57
|
+
});
|
|
58
|
+
await Promise.all(promises);
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
logger_1.logger.error(error.message);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
exports.deploy = deploy;
|
|
67
|
+
async function retrieveAssembly(name, apiConfig) {
|
|
68
|
+
const options = `$select=pluginassemblyid&$filter=name eq '${name}'`;
|
|
69
|
+
const result = await (0, node_1.retrieveMultiple)(apiConfig, 'pluginassemblies', options);
|
|
70
|
+
return result.value.length > 0 ? result.value[0].pluginassemblyid : '';
|
|
71
|
+
}
|
|
72
|
+
async function createAssembly(config, content, apiConfig) {
|
|
73
|
+
logger_1.logger.info(`create assembly ${config.name}`);
|
|
74
|
+
const assembly = {
|
|
75
|
+
name: config.name,
|
|
76
|
+
content: content,
|
|
77
|
+
isolationmode: config.isolationmode,
|
|
78
|
+
version: config.version,
|
|
79
|
+
publickeytoken: config.name,
|
|
80
|
+
sourcetype: 0,
|
|
81
|
+
culture: ''
|
|
82
|
+
};
|
|
83
|
+
const result = await (0, node_1.createWithReturnData)(apiConfig, 'pluginassemblies', assembly, '$select=pluginassemblyid');
|
|
84
|
+
if (result.error) {
|
|
85
|
+
throw new Error(result.error.message);
|
|
86
|
+
}
|
|
87
|
+
return result.pluginassemblyid;
|
|
88
|
+
}
|
|
89
|
+
async function updateAssembly(id, config, content, apiConfig) {
|
|
90
|
+
logger_1.logger.info(`update assembly ${config.name}`);
|
|
91
|
+
const assembly = {
|
|
92
|
+
content: content,
|
|
93
|
+
version: config.version
|
|
94
|
+
};
|
|
95
|
+
return (0, node_1.update)(apiConfig, 'pluginassemblies', id, assembly);
|
|
96
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.deployImage = void 0;
|
|
4
|
+
const logger_1 = require("../logger");
|
|
5
|
+
const node_1 = require("dataverse-webapi/lib/node");
|
|
6
|
+
async function deployImage(stepId, image, message, apiConfig) {
|
|
7
|
+
image['sdkmessageprocessingstepid@odata.bind'] = `/sdkmessageprocessingsteps(${stepId})`;
|
|
8
|
+
switch (message) {
|
|
9
|
+
case 'Create':
|
|
10
|
+
image.messagepropertyname = 'Id';
|
|
11
|
+
break;
|
|
12
|
+
case 'SetState':
|
|
13
|
+
case 'SetStateDynamicEntity':
|
|
14
|
+
image.messagepropertyname = 'EntityMoniker';
|
|
15
|
+
break;
|
|
16
|
+
case 'Send':
|
|
17
|
+
case 'DeliverIncoming':
|
|
18
|
+
case 'DeliverPromote':
|
|
19
|
+
image.messagepropertyname = 'EmailId';
|
|
20
|
+
break;
|
|
21
|
+
default:
|
|
22
|
+
image.messagepropertyname = 'Target';
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
let imageId = await retrieveImage(stepId, image, apiConfig);
|
|
26
|
+
if (imageId != '') {
|
|
27
|
+
try {
|
|
28
|
+
await updateImage(imageId, image, apiConfig);
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
throw new Error(`failed to update plugin image: ${error.message}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
try {
|
|
36
|
+
imageId = await createImage(image, apiConfig);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
throw new Error(`failed to create plugin image: ${error.message}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return imageId;
|
|
43
|
+
}
|
|
44
|
+
exports.deployImage = deployImage;
|
|
45
|
+
async function retrieveImage(stepId, image, apiConfig) {
|
|
46
|
+
const options = `$select=sdkmessageprocessingstepimageid&$filter=name eq '${image.name}' and _sdkmessageprocessingstepid_value eq ${stepId}`;
|
|
47
|
+
const result = await (0, node_1.retrieveMultiple)(apiConfig, 'sdkmessageprocessingstepimages', options);
|
|
48
|
+
return result.value.length > 0 ? result.value[0].sdkmessageprocessingstepimageid : '';
|
|
49
|
+
}
|
|
50
|
+
async function createImage(image, apiConfig) {
|
|
51
|
+
logger_1.logger.info(`create plugin image ${image.name}`);
|
|
52
|
+
const result = await (0, node_1.createWithReturnData)(apiConfig, 'sdkmessageprocessingstepimages', image, '$select=sdkmessageprocessingstepimageid');
|
|
53
|
+
if (result.error) {
|
|
54
|
+
throw new Error(result.error.message);
|
|
55
|
+
}
|
|
56
|
+
return result.sdkmessageprocessingstepimageid;
|
|
57
|
+
}
|
|
58
|
+
async function updateImage(id, image, apiConfig) {
|
|
59
|
+
logger_1.logger.info(`update plugin image ${image.name}`);
|
|
60
|
+
return (0, node_1.update)(apiConfig, 'sdkmessageprocessingstepimages', id, image);
|
|
61
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.deployStep = void 0;
|
|
4
|
+
const node_1 = require("dataverse-webapi/lib/node");
|
|
5
|
+
const dataverse_service_1 = require("../dataverse.service");
|
|
6
|
+
const logger_1 = require("../logger");
|
|
7
|
+
const pluginImage_1 = require("./pluginImage");
|
|
8
|
+
async function deployStep(step, typeId, apiConfig, solution) {
|
|
9
|
+
let stepId = await retrieveStep(step.name, typeId, apiConfig);
|
|
10
|
+
const messageId = await getSdkMessageId(step.message ?? '', apiConfig);
|
|
11
|
+
if (messageId == '') {
|
|
12
|
+
logger_1.logger.warn(`sdk message ${step.message} not found`);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const filterId = await getSdkMessageFilterId(messageId, step.entity ?? '', apiConfig);
|
|
16
|
+
if (filterId == '') {
|
|
17
|
+
logger_1.logger.warn(`sdk message ${step.message} for entity ${step.entity} not found`);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
step['sdkmessagefilterid@odata.bind'] = `/sdkmessagefilters(${filterId})`;
|
|
21
|
+
step['sdkmessageid@odata.bind'] = `/sdkmessages(${messageId})`;
|
|
22
|
+
if (step.mode === 1) {
|
|
23
|
+
step.asyncautodelete = true;
|
|
24
|
+
}
|
|
25
|
+
const images = step.images;
|
|
26
|
+
const message = step.message;
|
|
27
|
+
delete step.images;
|
|
28
|
+
delete step.message;
|
|
29
|
+
delete step.entity;
|
|
30
|
+
if (stepId != '') {
|
|
31
|
+
try {
|
|
32
|
+
await updateStep(stepId, step, apiConfig);
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
throw new Error(`failed to update plugin step: ${error.message}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
try {
|
|
40
|
+
stepId = await createStep(step, apiConfig);
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
throw new Error(`failed to create plugin step: ${error.message}`);
|
|
44
|
+
}
|
|
45
|
+
if (solution != undefined) {
|
|
46
|
+
try {
|
|
47
|
+
await (0, dataverse_service_1.addToSolution)(stepId, solution, dataverse_service_1.ComponentType.SDKMessageProcessingStep, apiConfig);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
throw new Error(`failed to add to solution: ${error.message}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (images && images.length > 0) {
|
|
55
|
+
try {
|
|
56
|
+
const promises = images.map(image => (0, pluginImage_1.deployImage)(stepId, image, message, apiConfig));
|
|
57
|
+
await Promise.all(promises);
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
throw new Error(error.message);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return stepId;
|
|
64
|
+
}
|
|
65
|
+
exports.deployStep = deployStep;
|
|
66
|
+
async function retrieveStep(name, typeId, apiConfig) {
|
|
67
|
+
const options = `$select=sdkmessageprocessingstepid&$filter=name eq '${name}' and _plugintypeid_value eq ${typeId}`;
|
|
68
|
+
const result = await (0, node_1.retrieveMultiple)(apiConfig, 'sdkmessageprocessingsteps', options);
|
|
69
|
+
return result.value.length > 0 ? result.value[0].sdkmessageprocessingstepid : '';
|
|
70
|
+
}
|
|
71
|
+
async function getSdkMessageFilterId(messageId, entityName, apiConfig) {
|
|
72
|
+
const options = [
|
|
73
|
+
`?$filter=primaryobjecttypecode eq '${entityName}' and _sdkmessageid_value eq ${messageId}`,
|
|
74
|
+
'&$select=sdkmessagefilterid'
|
|
75
|
+
].join('');
|
|
76
|
+
const message = await (0, node_1.retrieveMultiple)(apiConfig, 'sdkmessagefilters', options);
|
|
77
|
+
return message.value.length > 0 ? message.value[0].sdkmessagefilterid : '';
|
|
78
|
+
}
|
|
79
|
+
async function getSdkMessageId(name, apiConfig) {
|
|
80
|
+
const options = [
|
|
81
|
+
`?$filter=name eq '${name}'`,
|
|
82
|
+
'&$select=sdkmessageid'
|
|
83
|
+
].join('');
|
|
84
|
+
const message = await (0, node_1.retrieveMultiple)(apiConfig, 'sdkmessages', options);
|
|
85
|
+
return message.value.length > 0 ? message.value[0].sdkmessageid : '';
|
|
86
|
+
}
|
|
87
|
+
async function createStep(step, apiConfig) {
|
|
88
|
+
logger_1.logger.info(`create plugin step ${step.name}`);
|
|
89
|
+
const result = await (0, node_1.createWithReturnData)(apiConfig, 'sdkmessageprocessingsteps', step, '$select=sdkmessageprocessingstepid');
|
|
90
|
+
if (result.error) {
|
|
91
|
+
throw new Error(result.error.message);
|
|
92
|
+
}
|
|
93
|
+
return result.sdkmessageprocessingstepid;
|
|
94
|
+
}
|
|
95
|
+
async function updateStep(id, step, apiConfig) {
|
|
96
|
+
logger_1.logger.info(`update plugin step ${step.name}`);
|
|
97
|
+
return (0, node_1.update)(apiConfig, 'sdkmessageprocessingsteps', id, step);
|
|
98
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.deployType = void 0;
|
|
4
|
+
const node_1 = require("dataverse-webapi/lib/node");
|
|
5
|
+
const pluginStep_1 = require("./pluginStep");
|
|
6
|
+
const logger_1 = require("../logger");
|
|
7
|
+
async function deployType(type, assemblyId, apiConfig, solution) {
|
|
8
|
+
let typeId = await retrieveType(type.typename, assemblyId, apiConfig);
|
|
9
|
+
const record = {
|
|
10
|
+
name: type.name,
|
|
11
|
+
friendlyname: type.friendlyname,
|
|
12
|
+
typename: type.typename,
|
|
13
|
+
'pluginassemblyid@odata.bind': type['pluginassemblyid@odata.bind'],
|
|
14
|
+
workflowactivitygroupname: type.workflowactivitygroupname
|
|
15
|
+
};
|
|
16
|
+
if (typeId != '') {
|
|
17
|
+
try {
|
|
18
|
+
await updateType(typeId, record, apiConfig);
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
throw new Error(`failed to update plugin type: ${error.message}`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
try {
|
|
26
|
+
typeId = await createType(record, apiConfig);
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
throw new Error(`failed to create plugin type: ${error.message}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
if (type.steps) {
|
|
34
|
+
const promises = type.steps.map(async (step) => {
|
|
35
|
+
step['plugintypeid@odata.bind'] = `/plugintypes(${typeId})`;
|
|
36
|
+
await (0, pluginStep_1.deployStep)(step, typeId, apiConfig, solution);
|
|
37
|
+
});
|
|
38
|
+
await Promise.all(promises);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
throw new Error(error.message);
|
|
43
|
+
}
|
|
44
|
+
return typeId;
|
|
45
|
+
}
|
|
46
|
+
exports.deployType = deployType;
|
|
47
|
+
async function retrieveType(name, assemblyId, apiConfig) {
|
|
48
|
+
const options = `$select=plugintypeid&$filter=typename eq '${name}' and _pluginassemblyid_value eq ${assemblyId}`;
|
|
49
|
+
const result = await (0, node_1.retrieveMultiple)(apiConfig, 'plugintypes', options);
|
|
50
|
+
return result.value.length > 0 ? result.value[0].plugintypeid : '';
|
|
51
|
+
}
|
|
52
|
+
async function createType(type, apiConfig) {
|
|
53
|
+
logger_1.logger.info(`create assembly type ${type.name}`);
|
|
54
|
+
const result = await (0, node_1.createWithReturnData)(apiConfig, 'plugintypes', type, '$select=plugintypeid');
|
|
55
|
+
if (result.error) {
|
|
56
|
+
throw new Error(result.error.message);
|
|
57
|
+
}
|
|
58
|
+
return result.plugintypeid;
|
|
59
|
+
}
|
|
60
|
+
async function updateType(id, type, apiConfig) {
|
|
61
|
+
logger_1.logger.info(`update assembly type ${type.name}`);
|
|
62
|
+
return (0, node_1.update)(apiConfig, 'plugintypes', id, type);
|
|
63
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.deploy = void 0;
|
|
7
|
+
const dataverse_service_1 = require("../dataverse.service");
|
|
8
|
+
const node_1 = require("dataverse-webapi/lib/node");
|
|
9
|
+
const logger_1 = require("../logger");
|
|
10
|
+
const fs_1 = __importDefault(require("fs"));
|
|
11
|
+
function getWebResourceType(type) {
|
|
12
|
+
switch (type) {
|
|
13
|
+
case 'HTML':
|
|
14
|
+
return 1;
|
|
15
|
+
case 'CSS':
|
|
16
|
+
return 2;
|
|
17
|
+
case 'JavaScript':
|
|
18
|
+
return 3;
|
|
19
|
+
case 'XML':
|
|
20
|
+
return 4;
|
|
21
|
+
case 'PNG':
|
|
22
|
+
return 5;
|
|
23
|
+
case 'JPG':
|
|
24
|
+
return 6;
|
|
25
|
+
case 'GIF':
|
|
26
|
+
return 7;
|
|
27
|
+
case 'XAP':
|
|
28
|
+
return 8;
|
|
29
|
+
case 'XSL':
|
|
30
|
+
return 9;
|
|
31
|
+
case 'ICO':
|
|
32
|
+
return 10;
|
|
33
|
+
case 'SVG':
|
|
34
|
+
return 11;
|
|
35
|
+
case 'RESX':
|
|
36
|
+
return 12;
|
|
37
|
+
default:
|
|
38
|
+
return 0;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async function deploy(webResources, apiConfig, solution, files) {
|
|
42
|
+
const publishXml = [];
|
|
43
|
+
let resources = webResources;
|
|
44
|
+
// Use list of files if provided
|
|
45
|
+
if (files) {
|
|
46
|
+
resources = [];
|
|
47
|
+
for (const file of files.split(',')) {
|
|
48
|
+
const resource = webResources.filter(r => r.path?.endsWith(file));
|
|
49
|
+
if (resource.length === 0) {
|
|
50
|
+
logger_1.logger.warn(`web resource ${file} not found in dataverse.config.json`);
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
resources.push(resource[0]);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const promises = resources.map(async (resource) => {
|
|
57
|
+
let resourceId = '';
|
|
58
|
+
try {
|
|
59
|
+
resourceId = await retrieveResource(resource.name, apiConfig);
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
logger_1.logger.error(`failed to retrieve resource ${resource.name}: ${error.message}`);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const fileContent = await fs_1.default.promises.readFile(resource.path, 'utf8');
|
|
66
|
+
const content = Buffer.from(fileContent).toString('base64');
|
|
67
|
+
if (resourceId != '') {
|
|
68
|
+
try {
|
|
69
|
+
const updated = await updateResource(resourceId, resource, content, apiConfig);
|
|
70
|
+
publishXml.push(updated);
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
logger_1.logger.error(`failed to update resource: ${error.message}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
try {
|
|
78
|
+
resourceId = await createResource(resource, content, apiConfig);
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
logger_1.logger.error(`failed to create resource: ${error.message}`);
|
|
82
|
+
}
|
|
83
|
+
if (solution != undefined) {
|
|
84
|
+
try {
|
|
85
|
+
await (0, dataverse_service_1.addToSolution)(resourceId, solution, dataverse_service_1.ComponentType.WebResource, apiConfig);
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
logger_1.logger.error(`failed to add to solution: ${error.message}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
await Promise.all(promises);
|
|
94
|
+
// publish resources
|
|
95
|
+
if (publishXml.length > 0) {
|
|
96
|
+
try {
|
|
97
|
+
await (0, dataverse_service_1.publish)(publishXml.join(''), apiConfig);
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
logger_1.logger.error(error.message);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
exports.deploy = deploy;
|
|
105
|
+
async function retrieveResource(name, apiConfig) {
|
|
106
|
+
const options = `$select=webresourceid&$filter=name eq '${name}'`;
|
|
107
|
+
const result = await (0, node_1.retrieveMultiple)(apiConfig, 'webresourceset', options);
|
|
108
|
+
return result.value.length > 0 ? result.value[0].webresourceid : '';
|
|
109
|
+
}
|
|
110
|
+
async function createResource(resource, content, apiConfig) {
|
|
111
|
+
logger_1.logger.info(`create web resource ${resource.name}`);
|
|
112
|
+
const webResource = {
|
|
113
|
+
webresourcetype: getWebResourceType(resource.type),
|
|
114
|
+
name: resource.name,
|
|
115
|
+
displayname: resource.displayname || resource.name,
|
|
116
|
+
content: content
|
|
117
|
+
};
|
|
118
|
+
const result = await (0, node_1.createWithReturnData)(apiConfig, 'webresourceset', webResource, '$select=webresourceid');
|
|
119
|
+
if (result.error) {
|
|
120
|
+
throw new Error(result.error.message);
|
|
121
|
+
}
|
|
122
|
+
return result.webresourceid;
|
|
123
|
+
}
|
|
124
|
+
async function updateResource(id, resource, content, apiConfig) {
|
|
125
|
+
logger_1.logger.info(`update web resource ${resource.name}`);
|
|
126
|
+
const webResource = {
|
|
127
|
+
content: content
|
|
128
|
+
};
|
|
129
|
+
await (0, node_1.update)(apiConfig, 'webresourceset', id, webResource);
|
|
130
|
+
return `<webresource>{${id}}</webresource>`;
|
|
131
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.deployWebResource = void 0;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const logger_1 = require("./logger");
|
|
10
|
+
const webResource_1 = require("./models/webResource");
|
|
11
|
+
async function deployWebResource(creds, apiConfig, files) {
|
|
12
|
+
const currentPath = '.';
|
|
13
|
+
const configFile = await fs_1.default.promises.readFile(path_1.default.resolve(currentPath, 'dataverse.config.json'), 'utf8');
|
|
14
|
+
if (configFile == null) {
|
|
15
|
+
logger_1.logger.warn('unable to find dataverse.config.json file');
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const config = JSON.parse(configFile).webResources;
|
|
19
|
+
logger_1.logger.info('deploy web resources');
|
|
20
|
+
try {
|
|
21
|
+
await (0, webResource_1.deploy)(config, apiConfig, creds.solution, files);
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
logger_1.logger.error(error.message);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
logger_1.logger.done('deployed web resources');
|
|
28
|
+
}
|
|
29
|
+
exports.deployWebResource = deployWebResource;
|
package/license
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021 Derek Finlinson
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dataverse-utils",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.13",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Utilities for interacting with Dataverse environments",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -20,14 +20,14 @@
|
|
|
20
20
|
"clean": "rimraf lib"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@azure/msal-node": "^1.
|
|
23
|
+
"@azure/msal-node": "^1.12.0",
|
|
24
24
|
"commander": "^8.3.0",
|
|
25
|
-
"cryptr": "^6.0.
|
|
26
|
-
"dataverse-webapi": "^2.0
|
|
25
|
+
"cryptr": "^6.0.3",
|
|
26
|
+
"dataverse-webapi": "^2.1.0",
|
|
27
27
|
"envinfo": "^7.8.1",
|
|
28
28
|
"figures": "^3.2.0",
|
|
29
29
|
"glob": "^7.2.0",
|
|
30
|
-
"kleur": "^4.1.
|
|
30
|
+
"kleur": "^4.1.5",
|
|
31
31
|
"prompts": "^2.4.2"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|