@onlineapps/cookbook-template-helpers 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/README.md ADDED
@@ -0,0 +1,188 @@
1
+ # @onlineapps/cookbook-template-helpers
2
+
3
+ Template helper functions for cookbook variable resolution. Helper functions enable data transformations directly in cookbook template variables.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @onlineapps/cookbook-template-helpers
9
+ ```
10
+
11
+ ## Overview
12
+
13
+ Helper functions can be used in cookbook template variables using the syntax:
14
+ ```
15
+ {{helper_name(argument)}}
16
+ ```
17
+
18
+ Arguments can be template variables themselves:
19
+ ```
20
+ {{helper_name(steps.step_id.output.field)}}
21
+ ```
22
+
23
+ ## Available Helpers
24
+
25
+ ### string2file
26
+
27
+ Converts string content or inline descriptor to file descriptor. Uploads content to MinIO storage.
28
+
29
+ **Signature:**
30
+ ```javascript
31
+ async function string2file(input, context)
32
+ ```
33
+
34
+ **Parameters:**
35
+ - `input` (string|Object) - String content or inline descriptor
36
+ - `context` (Object) - Workflow context (for storage access)
37
+
38
+ **Returns:**
39
+ - `Promise<Object>` - File descriptor
40
+
41
+ **Examples:**
42
+
43
+ ```json
44
+ {
45
+ "input": {
46
+ "file": "{{string2file(steps.markdown.output.content)}}"
47
+ }
48
+ }
49
+ ```
50
+
51
+ ```json
52
+ {
53
+ "input": {
54
+ "file": "{{string2file('Hello world')}}"
55
+ }
56
+ }
57
+ ```
58
+
59
+ ### file2string
60
+
61
+ Converts file descriptor to string. Downloads content from MinIO if needed.
62
+
63
+ **Signature:**
64
+ ```javascript
65
+ async function file2string(descriptor, context)
66
+ ```
67
+
68
+ **Parameters:**
69
+ - `descriptor` (Object|string) - File descriptor or string
70
+ - `context` (Object) - Workflow context (for storage access)
71
+
72
+ **Returns:**
73
+ - `Promise<string>` - String content
74
+
75
+ **Examples:**
76
+
77
+ ```json
78
+ {
79
+ "input": {
80
+ "markdown": "{{file2string(steps.pdf.output.file_descriptor)}}"
81
+ }
82
+ }
83
+ ```
84
+
85
+ ## Usage in Cookbook
86
+
87
+ Helper functions are integrated into the cookbook executor. They are automatically available when resolving template variables.
88
+
89
+ **Example cookbook:**
90
+
91
+ ```json
92
+ {
93
+ "version": "2.0.0",
94
+ "steps": [
95
+ {
96
+ "step_id": "get_markdown",
97
+ "type": "task",
98
+ "service": "hello-service",
99
+ "operation": "generate-markdown",
100
+ "input": { "name": "Karel" }
101
+ },
102
+ {
103
+ "step_id": "create_pdf",
104
+ "type": "task",
105
+ "service": "pdfgen-service",
106
+ "operation": "md2pdf",
107
+ "depends_on": ["get_markdown"],
108
+ "input": {
109
+ "markdown": "{{file2string(steps.get_markdown.output.file_descriptor)}}"
110
+ }
111
+ }
112
+ ]
113
+ }
114
+ ```
115
+
116
+ ## Integration
117
+
118
+ Helper functions are passed to the cookbook executor:
119
+
120
+ ```javascript
121
+ const templateHelpers = require('@onlineapps/cookbook-template-helpers');
122
+ const { CookbookExecutor } = require('@onlineapps/cookbook-executor');
123
+
124
+ const executor = new CookbookExecutor(cookbook, {
125
+ helpers: templateHelpers
126
+ });
127
+ ```
128
+
129
+ ## Adding Custom Helpers
130
+
131
+ You can combine global helpers with custom helpers:
132
+
133
+ ```javascript
134
+ const templateHelpers = require('@onlineapps/cookbook-template-helpers');
135
+ const customHelpers = require('./customHelpers');
136
+
137
+ const allHelpers = {
138
+ ...templateHelpers,
139
+ ...customHelpers
140
+ };
141
+
142
+ const executor = new CookbookExecutor(cookbook, {
143
+ helpers: allHelpers
144
+ });
145
+ ```
146
+
147
+ ## Helper Function Requirements
148
+
149
+ - **Async**: All helpers must be async functions (return Promise)
150
+ - **Context**: Helpers receive workflow context as last parameter
151
+ - **Idempotent**: Same input should produce same output
152
+ - **Error handling**: Should throw descriptive errors
153
+
154
+ ## Dependencies
155
+
156
+ - `@onlineapps/conn-base-storage` - For MinIO storage operations
157
+
158
+ ## Environment Variables
159
+
160
+ Helper functions use the following environment variables for storage access:
161
+
162
+ - `MINIO_HOST` - MinIO endpoint (default: `api_shared_storage`)
163
+ - `MINIO_PORT` - MinIO port (default: `9000`)
164
+ - `MINIO_ACCESS_KEY` - MinIO access key (default: `minioadmin`)
165
+ - `MINIO_SECRET_KEY` - MinIO secret key (default: `minioadmin`)
166
+ - `MINIO_USE_SSL` - Use SSL (default: `false`)
167
+
168
+ ## File Descriptor Format
169
+
170
+ File descriptors have the following structure:
171
+
172
+ ```javascript
173
+ {
174
+ _descriptor: true,
175
+ type: 'file', // or 'inline'
176
+ storage_ref: 'minio://workflow/path/to/file', // for type='file'
177
+ content: '...', // for type='inline'
178
+ filename: 'document.txt',
179
+ content_type: 'text/plain',
180
+ size: 1234,
181
+ fingerprint: 'sha256...'
182
+ }
183
+ ```
184
+
185
+ ## License
186
+
187
+ PROPRIETARY
188
+
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@onlineapps/cookbook-template-helpers",
3
+ "version": "1.0.1",
4
+ "description": "Template helper functions for cookbook variable resolution - string2file, file2string, and more",
5
+ "main": "src/index.js",
6
+ "scripts": {
7
+ "test": "jest",
8
+ "test:watch": "jest --watch",
9
+ "test:coverage": "jest --coverage",
10
+ "docs": "jsdoc2md --files src/**/*.js > API.md"
11
+ },
12
+ "keywords": [
13
+ "cookbook",
14
+ "workflow",
15
+ "template",
16
+ "helpers",
17
+ "functions"
18
+ ],
19
+ "author": "OnlineApps",
20
+ "license": "PROPRIETARY",
21
+ "dependencies": {
22
+ "@onlineapps/conn-base-storage": "^1.0.0"
23
+ },
24
+ "devDependencies": {
25
+ "jest": "^29.7.0"
26
+ },
27
+ "engines": {
28
+ "node": ">=18.0.0"
29
+ },
30
+ "files": [
31
+ "src"
32
+ ],
33
+ "publishConfig": {
34
+ "access": "public"
35
+ }
36
+ }
@@ -0,0 +1,201 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * File helper functions for cookbook template resolution
5
+ * Converts between string content and file descriptors
6
+ */
7
+
8
+ const StorageConnector = require('@onlineapps/conn-base-storage');
9
+
10
+ /**
11
+ * Get storage instance from context or create new one
12
+ * @private
13
+ * @param {Object} context - Workflow context
14
+ * @returns {Promise<Object>} Storage connector instance
15
+ */
16
+ async function getStorageFromContext(context) {
17
+ // If storage is already in context, use it
18
+ if (context._storage) {
19
+ return context._storage;
20
+ }
21
+
22
+ // Otherwise create new storage instance
23
+ const storage = new StorageConnector({
24
+ endpoint: process.env.MINIO_HOST || 'api_shared_storage',
25
+ port: parseInt(process.env.MINIO_PORT || '9000', 10),
26
+ accessKey: process.env.MINIO_ACCESS_KEY || 'minioadmin',
27
+ secretKey: process.env.MINIO_SECRET_KEY || 'minioadmin',
28
+ useSSL: process.env.MINIO_USE_SSL === 'true'
29
+ });
30
+
31
+ // Cache in context for reuse
32
+ context._storage = storage;
33
+ return storage;
34
+ }
35
+
36
+ /**
37
+ * Convert string or inline descriptor to file descriptor
38
+ * Uploads content to MinIO and returns file descriptor
39
+ *
40
+ * @param {string|Object} input - String content or inline descriptor
41
+ * @param {Object} context - Workflow context (for storage access)
42
+ * @returns {Promise<Object>} File descriptor
43
+ *
44
+ * @example
45
+ * // String input
46
+ * const descriptor = await string2file('Hello world', context);
47
+ *
48
+ * @example
49
+ * // Inline descriptor input
50
+ * const descriptor = await string2file({
51
+ * _descriptor: true,
52
+ * type: 'inline',
53
+ * content: 'Hello world',
54
+ * filename: 'greeting.txt'
55
+ * }, context);
56
+ */
57
+ async function string2file(input, context) {
58
+ if (!input) {
59
+ throw new Error('[string2file] Input is required');
60
+ }
61
+
62
+ // Pokud už je file descriptor, vrať ho
63
+ if (input._descriptor && input.type === 'file') {
64
+ return input;
65
+ }
66
+
67
+ // Pokud je inline descriptor, převeď na file
68
+ if (input._descriptor && input.type === 'inline') {
69
+ const content = input.content;
70
+ if (typeof content !== 'string') {
71
+ throw new Error('[string2file] Inline descriptor content must be a string');
72
+ }
73
+
74
+ const storage = await getStorageFromContext(context);
75
+ const encoding = input.encoding || 'utf-8';
76
+ const buffer = Buffer.from(content, encoding);
77
+
78
+ // Upload do MinIO
79
+ const workflowId = context.workflow_id || context.workflowId || 'temp';
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
+ };
98
+ }
99
+
100
+ // Pokud je string, vytvoř file descriptor
101
+ if (typeof input === 'string') {
102
+ const storage = await getStorageFromContext(context);
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}`,
119
+ filename: 'content.txt',
120
+ content_type: 'text/plain',
121
+ size: buffer.length,
122
+ fingerprint: result.fingerprint
123
+ };
124
+ }
125
+
126
+ throw new Error('[string2file] Invalid input - expected string or descriptor');
127
+ }
128
+
129
+ /**
130
+ * Convert file descriptor to string
131
+ * Downloads content from MinIO if needed
132
+ *
133
+ * @param {Object|string} descriptor - File descriptor or string
134
+ * @param {Object} context - Workflow context (for storage access)
135
+ * @returns {Promise<string>} String content
136
+ *
137
+ * @example
138
+ * // File descriptor input
139
+ * const content = await file2string({
140
+ * _descriptor: true,
141
+ * type: 'file',
142
+ * storage_ref: 'minio://workflow/path/to/file',
143
+ * fingerprint: 'abc123...'
144
+ * }, context);
145
+ *
146
+ * @example
147
+ * // Inline descriptor input
148
+ * const content = await file2string({
149
+ * _descriptor: true,
150
+ * type: 'inline',
151
+ * content: 'Hello world'
152
+ * }, context);
153
+ */
154
+ async function file2string(descriptor, context) {
155
+ // Pokud není descriptor, vrať jak je (pokud je string)
156
+ if (!descriptor || !descriptor._descriptor) {
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}`);
195
+ }
196
+
197
+ module.exports = {
198
+ string2file,
199
+ file2string
200
+ };
201
+
package/src/index.js ADDED
@@ -0,0 +1,21 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * @module @onlineapps/cookbook-template-helpers
5
+ * @description Template helper functions for cookbook variable resolution
6
+ *
7
+ * Helper functions can be used in cookbook template variables:
8
+ * {{helper_name(arg)}}
9
+ *
10
+ * Example:
11
+ * {{string2file(steps.markdown.output.content)}}
12
+ * {{file2string(steps.pdf.output.file_descriptor)}}
13
+ */
14
+
15
+ const fileHelpers = require('./helpers/fileHelpers');
16
+
17
+ module.exports = {
18
+ string2file: fileHelpers.string2file,
19
+ file2string: fileHelpers.file2string
20
+ };
21
+