ms_azure_helper 1.0.1
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/index.js +153 -0
- package/package.json +17 -0
package/index.js
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
const { BlobServiceClient } = require('@azure/storage-blob');
|
|
2
|
+
const { ClientSecretCredential } = require('@azure/identity');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Reads authentication parameters from Switch flow element properties.
|
|
6
|
+
*
|
|
7
|
+
* @param {SwitchHelper} sw
|
|
8
|
+
* @returns {Promise<object>}
|
|
9
|
+
*/
|
|
10
|
+
async function getAuthParams(sw) {
|
|
11
|
+
const useServicePrincipal = (await sw.getPropertyStringValue('tagUseServicePrincipal', 'No')) === 'Yes';
|
|
12
|
+
if (useServicePrincipal) {
|
|
13
|
+
return {
|
|
14
|
+
method: 'servicePrincipal',
|
|
15
|
+
accountName: await sw.getPropertyStringValue('tagAccountName'),
|
|
16
|
+
tenantId: await sw.getPropertyStringValue('tagTenantId'),
|
|
17
|
+
clientId: await sw.getPropertyStringValue('tagClientId'),
|
|
18
|
+
clientSecret: await sw.getPropertyStringValue('tagClientSecret'),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
method: 'connectionString',
|
|
23
|
+
connectionString: await sw.getPropertyStringValue('tagAuth'),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Creates a BlobServiceClient using the provided auth parameters.
|
|
29
|
+
*
|
|
30
|
+
* @param {object} authParams - Result of getAuthParams()
|
|
31
|
+
* @returns {BlobServiceClient}
|
|
32
|
+
*/
|
|
33
|
+
function createBlobServiceClient(authParams) {
|
|
34
|
+
if (authParams.method === 'servicePrincipal') {
|
|
35
|
+
const credential = new ClientSecretCredential(
|
|
36
|
+
authParams.tenantId,
|
|
37
|
+
authParams.clientId,
|
|
38
|
+
authParams.clientSecret
|
|
39
|
+
);
|
|
40
|
+
return new BlobServiceClient(
|
|
41
|
+
`https://${authParams.accountName}.blob.core.windows.net`,
|
|
42
|
+
credential
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
return BlobServiceClient.fromConnectionString(authParams.connectionString);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Returns all container names for the authenticated Azure account.
|
|
50
|
+
*
|
|
51
|
+
* @param {BlobServiceClient} blobServiceClient
|
|
52
|
+
* @returns {Promise<string[]>}
|
|
53
|
+
*/
|
|
54
|
+
async function listContainers(blobServiceClient) {
|
|
55
|
+
const containerNames = [];
|
|
56
|
+
for await (const container of blobServiceClient.listContainers()) {
|
|
57
|
+
containerNames.push(container.name);
|
|
58
|
+
}
|
|
59
|
+
return containerNames;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Normalizes a blob path prefix: removes leading slash, ensures trailing slash.
|
|
64
|
+
* Returns an empty string if the input is empty.
|
|
65
|
+
*
|
|
66
|
+
* @param {string} rawPath
|
|
67
|
+
* @returns {string}
|
|
68
|
+
*/
|
|
69
|
+
function normalizeBlobPath(rawPath) {
|
|
70
|
+
let p = rawPath || '';
|
|
71
|
+
if (p.startsWith('/')) p = p.substring(1);
|
|
72
|
+
if (p.length > 0 && !p.endsWith('/')) p += '/';
|
|
73
|
+
return p;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Extracts the blob name from a full Azure Blob Storage URL.
|
|
78
|
+
*
|
|
79
|
+
* The upload script stores URLs like:
|
|
80
|
+
* https://account.blob.core.windows.net/containername/folder/file.pdf
|
|
81
|
+
* This function returns: folder/file.pdf
|
|
82
|
+
*
|
|
83
|
+
* @param {string} storedUrl - The full Azure blob URL
|
|
84
|
+
* @param {string} containerName - The container name to strip from the path
|
|
85
|
+
* @returns {string}
|
|
86
|
+
*/
|
|
87
|
+
function extractBlobNameFromUrl(storedUrl, containerName) {
|
|
88
|
+
const { pathname } = new URL(storedUrl);
|
|
89
|
+
// pathname: /containername/folder/file.pdf
|
|
90
|
+
const prefix = '/' + containerName + '/';
|
|
91
|
+
if (pathname.startsWith(prefix)) {
|
|
92
|
+
return pathname.substring(prefix.length);
|
|
93
|
+
}
|
|
94
|
+
// Fallback: strip leading slash and first path segment
|
|
95
|
+
const parts = pathname.replace(/^\//, '').split('/');
|
|
96
|
+
parts.shift();
|
|
97
|
+
return parts.join('/');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Resolves the blob name to operate on from Switch flow element properties.
|
|
102
|
+
* Reads from job private data (when tagBlobPathSource = 'Yes') or from
|
|
103
|
+
* the tagBlobPath property directly.
|
|
104
|
+
*
|
|
105
|
+
* @param {SwitchHelper} sw
|
|
106
|
+
* @param {string} containerName
|
|
107
|
+
* @returns {Promise<string>}
|
|
108
|
+
*/
|
|
109
|
+
async function resolveBlobName(sw, containerName) {
|
|
110
|
+
const usePrivateData = (await sw.getPropertyStringValue('tagBlobPathSource', 'No')) === 'Yes';
|
|
111
|
+
if (usePrivateData) {
|
|
112
|
+
const privateDataField = await sw.getPropertyStringValue('tagPrivateDataName', 'fpAzureUpload');
|
|
113
|
+
const storedUrl = await sw.getPrivateData(privateDataField);
|
|
114
|
+
if (!storedUrl) throw new Error(`Private data field "${privateDataField}" is empty — cannot resolve blob path`);
|
|
115
|
+
return extractBlobNameFromUrl(storedUrl, containerName);
|
|
116
|
+
}
|
|
117
|
+
const blobName = await sw.getPropertyStringValue('tagBlobPath');
|
|
118
|
+
if (!blobName) throw new Error('Blob path is empty — check the "Blob path" property or private data field');
|
|
119
|
+
return blobName;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Handles the Switch getLibraryForProperty callback.
|
|
124
|
+
* Supports the tagContainer property by listing available Azure containers.
|
|
125
|
+
* Import and call this inside each script's getLibraryForProperty entry point.
|
|
126
|
+
*
|
|
127
|
+
* @param {SwitchHelper} sw
|
|
128
|
+
* @param {string} tag
|
|
129
|
+
* @returns {Promise<string[]>}
|
|
130
|
+
*/
|
|
131
|
+
async function handleLibraryProperty(sw, tag) {
|
|
132
|
+
switch (tag) {
|
|
133
|
+
case 'tagContainer': {
|
|
134
|
+
await sw.logDebug('getLibraryForProperty called for tagContainer, fetching containers from Azure...');
|
|
135
|
+
const authParams = await getAuthParams(sw);
|
|
136
|
+
const blobServiceClient = createBlobServiceClient(authParams);
|
|
137
|
+
return await listContainers(blobServiceClient);
|
|
138
|
+
}
|
|
139
|
+
default:
|
|
140
|
+
await sw.logError('getLibraryForProperty called with an invalid property tag (%1)', [tag]);
|
|
141
|
+
return [];
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
module.exports = {
|
|
146
|
+
getAuthParams,
|
|
147
|
+
createBlobServiceClient,
|
|
148
|
+
listContainers,
|
|
149
|
+
normalizeBlobPath,
|
|
150
|
+
extractBlobNameFromUrl,
|
|
151
|
+
resolveBlobName,
|
|
152
|
+
handleLibraryProperty,
|
|
153
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ms_azure_helper",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Shared Azure Blob Storage utilities for Enfocus Switch scripts",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"keywords": [],
|
|
7
|
+
"author": "",
|
|
8
|
+
"license": "ISC",
|
|
9
|
+
"scripts": {
|
|
10
|
+
"upload": "npm version patch && npm publish"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@azure/identity": "^4.0.0",
|
|
14
|
+
"@azure/storage-blob": "^12.27.0",
|
|
15
|
+
"lodash": "^4.17.21"
|
|
16
|
+
}
|
|
17
|
+
}
|