@onlineapps/cookbook-template-helpers 1.0.1 → 1.0.2
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 +5 -6
- package/package.json +3 -3
- package/src/helpers/fileHelpers.js +49 -108
package/README.md
CHANGED
|
@@ -153,17 +153,16 @@ const executor = new CookbookExecutor(cookbook, {
|
|
|
153
153
|
|
|
154
154
|
## Dependencies
|
|
155
155
|
|
|
156
|
-
- `@onlineapps/
|
|
156
|
+
- `@onlineapps/content-resolver` - Unified access to Content Descriptors (MinIO download/upload)
|
|
157
157
|
|
|
158
158
|
## Environment Variables
|
|
159
159
|
|
|
160
160
|
Helper functions use the following environment variables for storage access:
|
|
161
161
|
|
|
162
|
-
- `MINIO_HOST` - MinIO endpoint (
|
|
163
|
-
- `MINIO_PORT` - MinIO port (
|
|
164
|
-
- `MINIO_ACCESS_KEY` - MinIO access key (
|
|
165
|
-
- `MINIO_SECRET_KEY` - MinIO secret key (
|
|
166
|
-
- `MINIO_USE_SSL` - Use SSL (default: `false`)
|
|
162
|
+
- `MINIO_HOST` - MinIO endpoint (required unless you inject `contentResolver`)
|
|
163
|
+
- `MINIO_PORT` - MinIO port (required unless you inject `contentResolver`)
|
|
164
|
+
- `MINIO_ACCESS_KEY` - MinIO access key (required unless you inject `contentResolver`)
|
|
165
|
+
- `MINIO_SECRET_KEY` - MinIO secret key (required unless you inject `contentResolver`)
|
|
167
166
|
|
|
168
167
|
## File Descriptor Format
|
|
169
168
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onlineapps/cookbook-template-helpers",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Template helper functions for cookbook variable resolution - string2file, file2string, and more",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -19,10 +19,10 @@
|
|
|
19
19
|
"author": "OnlineApps",
|
|
20
20
|
"license": "PROPRIETARY",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@onlineapps/
|
|
22
|
+
"@onlineapps/content-resolver": "1.1.6"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
|
-
"jest": "
|
|
25
|
+
"jest": "29.7.0"
|
|
26
26
|
},
|
|
27
27
|
"engines": {
|
|
28
28
|
"node": ">=18.0.0"
|
|
@@ -5,32 +5,43 @@
|
|
|
5
5
|
* Converts between string content and file descriptors
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
const
|
|
8
|
+
const ContentResolver = require('@onlineapps/content-resolver');
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* Get
|
|
11
|
+
* Get ContentResolver instance from helper context.
|
|
12
|
+
* Uses DI if provided; otherwise relies on required MINIO_* env vars enforced by ContentResolver.
|
|
12
13
|
* @private
|
|
13
|
-
* @param {Object}
|
|
14
|
-
* @returns {
|
|
14
|
+
* @param {Object} helperContext - Helper context
|
|
15
|
+
* @returns {ContentResolver}
|
|
15
16
|
*/
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
return context._storage;
|
|
17
|
+
function getContentResolverFromContext(helperContext) {
|
|
18
|
+
if (!helperContext || typeof helperContext !== 'object') {
|
|
19
|
+
throw new Error('[cookbook-template-helpers] Helper context is required - Expected { data, workflow_id, step_id, contentResolver? }');
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
22
|
+
if (
|
|
23
|
+
helperContext.contentResolver &&
|
|
24
|
+
typeof helperContext.contentResolver.getAsString === 'function' &&
|
|
25
|
+
typeof helperContext.contentResolver.createDescriptor === 'function'
|
|
26
|
+
) {
|
|
27
|
+
return helperContext.contentResolver;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const workflow_id =
|
|
31
|
+
helperContext.workflow_id ||
|
|
32
|
+
helperContext.data?.variables?.workflow_id ||
|
|
33
|
+
helperContext.data?.workflow_id ||
|
|
34
|
+
null;
|
|
30
35
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
36
|
+
const step_id =
|
|
37
|
+
helperContext.step_id ||
|
|
38
|
+
helperContext.data?.variables?.step_id ||
|
|
39
|
+
helperContext.data?.step_id ||
|
|
40
|
+
null;
|
|
41
|
+
|
|
42
|
+
return new ContentResolver({
|
|
43
|
+
context: { workflow_id, step_id }
|
|
44
|
+
});
|
|
34
45
|
}
|
|
35
46
|
|
|
36
47
|
/**
|
|
@@ -55,72 +66,40 @@ async function getStorageFromContext(context) {
|
|
|
55
66
|
* }, context);
|
|
56
67
|
*/
|
|
57
68
|
async function string2file(input, context) {
|
|
58
|
-
|
|
59
|
-
throw new Error('[string2file] Input is required');
|
|
60
|
-
}
|
|
69
|
+
const resolver = getContentResolverFromContext(context);
|
|
61
70
|
|
|
62
71
|
// Pokud už je file descriptor, vrať ho
|
|
63
|
-
if (input._descriptor && input.type === 'file') {
|
|
72
|
+
if (input && input._descriptor === true && input.type === 'file') {
|
|
64
73
|
return input;
|
|
65
74
|
}
|
|
66
75
|
|
|
67
76
|
// Pokud je inline descriptor, převeď na file
|
|
68
|
-
if (input._descriptor && input.type === 'inline') {
|
|
77
|
+
if (input && input._descriptor === true && input.type === 'inline') {
|
|
69
78
|
const content = input.content;
|
|
70
79
|
if (typeof content !== 'string') {
|
|
71
80
|
throw new Error('[string2file] Inline descriptor content must be a string');
|
|
72
81
|
}
|
|
73
82
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const stepId = context.step_id || context.stepId || 'helpers';
|
|
81
|
-
const pathPrefix = `helpers/${workflowId}/${stepId}`;
|
|
82
|
-
|
|
83
|
-
const result = await storage.uploadWithFingerprint(
|
|
84
|
-
'workflow',
|
|
85
|
-
buffer,
|
|
86
|
-
pathPrefix
|
|
87
|
-
);
|
|
88
|
-
|
|
89
|
-
return {
|
|
90
|
-
_descriptor: true,
|
|
91
|
-
type: 'file',
|
|
92
|
-
storage_ref: `minio://workflow/${result.path}`,
|
|
93
|
-
filename: input.filename || 'content.txt',
|
|
94
|
-
content_type: input.content_type || 'text/plain',
|
|
95
|
-
size: buffer.length,
|
|
96
|
-
fingerprint: result.fingerprint
|
|
97
|
-
};
|
|
83
|
+
return await resolver.createDescriptor(content, {
|
|
84
|
+
filename: input.filename,
|
|
85
|
+
content_type: input.content_type,
|
|
86
|
+
context: { workflow_id: context.workflow_id, step_id: context.step_id },
|
|
87
|
+
forceFile: true
|
|
88
|
+
});
|
|
98
89
|
}
|
|
99
90
|
|
|
100
91
|
// Pokud je string, vytvoř file descriptor
|
|
101
92
|
if (typeof input === 'string') {
|
|
102
|
-
|
|
103
|
-
const buffer = Buffer.from(input, 'utf-8');
|
|
104
|
-
|
|
105
|
-
const workflowId = context.workflow_id || context.workflowId || 'temp';
|
|
106
|
-
const stepId = context.step_id || context.stepId || 'helpers';
|
|
107
|
-
const pathPrefix = `helpers/${workflowId}/${stepId}`;
|
|
108
|
-
|
|
109
|
-
const result = await storage.uploadWithFingerprint(
|
|
110
|
-
'workflow',
|
|
111
|
-
buffer,
|
|
112
|
-
pathPrefix
|
|
113
|
-
);
|
|
114
|
-
|
|
115
|
-
return {
|
|
116
|
-
_descriptor: true,
|
|
117
|
-
type: 'file',
|
|
118
|
-
storage_ref: `minio://workflow/${result.path}`,
|
|
93
|
+
return await resolver.createDescriptor(input, {
|
|
119
94
|
filename: 'content.txt',
|
|
120
95
|
content_type: 'text/plain',
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
};
|
|
96
|
+
context: { workflow_id: context.workflow_id, step_id: context.step_id },
|
|
97
|
+
forceFile: true
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (input === null || input === undefined) {
|
|
102
|
+
throw new Error('[string2file] Input is required');
|
|
124
103
|
}
|
|
125
104
|
|
|
126
105
|
throw new Error('[string2file] Invalid input - expected string or descriptor');
|
|
@@ -152,46 +131,8 @@ async function string2file(input, context) {
|
|
|
152
131
|
* }, context);
|
|
153
132
|
*/
|
|
154
133
|
async function file2string(descriptor, context) {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
if (typeof descriptor === 'string') {
|
|
158
|
-
return descriptor;
|
|
159
|
-
}
|
|
160
|
-
return String(descriptor || '');
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
// Pokud je inline, vrať content
|
|
164
|
-
if (descriptor.type === 'inline') {
|
|
165
|
-
return descriptor.content || '';
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// Pokud je file, stáhni z MinIO
|
|
169
|
-
if (descriptor.type === 'file') {
|
|
170
|
-
if (!descriptor.storage_ref) {
|
|
171
|
-
throw new Error('[file2string] File descriptor missing storage_ref');
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
const storage = await getStorageFromContext(context);
|
|
175
|
-
|
|
176
|
-
// Parse storage_ref: minio://workflow/path/to/file
|
|
177
|
-
const match = descriptor.storage_ref.match(/^minio:\/\/([^\/]+)\/(.+)$/);
|
|
178
|
-
if (!match) {
|
|
179
|
-
throw new Error(`[file2string] Invalid storage_ref format: ${descriptor.storage_ref}`);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
const [, bucket, path] = match;
|
|
183
|
-
|
|
184
|
-
// Download with fingerprint verification
|
|
185
|
-
const content = await storage.downloadWithVerification(
|
|
186
|
-
bucket,
|
|
187
|
-
path,
|
|
188
|
-
descriptor.fingerprint
|
|
189
|
-
);
|
|
190
|
-
|
|
191
|
-
return content.toString('utf-8');
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
throw new Error(`[file2string] Invalid descriptor type: ${descriptor.type}`);
|
|
134
|
+
const resolver = getContentResolverFromContext(context);
|
|
135
|
+
return await resolver.getAsString(descriptor);
|
|
195
136
|
}
|
|
196
137
|
|
|
197
138
|
module.exports = {
|