prompt-identifiers-baml 0.1.2 → 0.1.3
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 +14 -13
- package/dist/index.cjs +248 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +137 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +68 -75
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +227 -187
- package/dist/index.mjs.map +1 -0
- package/package.json +17 -17
- package/src/index.ts +460 -0
- package/dist/index.d.ts +0 -144
- package/dist/index.js +0 -232
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
BAML wrapper for automatic ID encoding/decoding in LLM function calls. Reduces token usage by up to 90% for UUIDs and ULIDs.
|
|
4
4
|
|
|
5
|
+
> **Experimental:** This package has not been tested in production. The API works and passes tests, but real-world BAML integration may surface edge cases. Please [report issues](https://github.com/fogx/prompt-identifiers/issues) if you encounter any.
|
|
6
|
+
|
|
5
7
|
## Installation
|
|
6
8
|
|
|
7
9
|
```bash
|
|
@@ -63,12 +65,16 @@ wrapBamlFunction(fn, {
|
|
|
63
65
|
console.log("Mapping:", result.mapping);
|
|
64
66
|
// debugData is only present when debug: true
|
|
65
67
|
if (result.debugData) {
|
|
66
|
-
console.log(
|
|
68
|
+
console.log(
|
|
69
|
+
`Encoded ${result.debugData.encodedCount} IDs in ${result.debugData.durationMs}ms`
|
|
70
|
+
);
|
|
67
71
|
}
|
|
68
72
|
},
|
|
69
73
|
onDecode: (result) => {
|
|
70
74
|
if (result.debugData) {
|
|
71
|
-
console.log(
|
|
75
|
+
console.log(
|
|
76
|
+
`Decoded ${result.debugData.decodedCount} placeholders in ${result.debugData.durationMs}ms`
|
|
77
|
+
);
|
|
72
78
|
}
|
|
73
79
|
},
|
|
74
80
|
});
|
|
@@ -95,12 +101,12 @@ The `encodeFields` option supports dot notation and array wildcards:
|
|
|
95
101
|
|
|
96
102
|
### Output Formats
|
|
97
103
|
|
|
98
|
-
| Format | Description
|
|
99
|
-
| --------------------- |
|
|
100
|
-
| `'SafeNumeric'` | Collision-safe with tildes (recommended)
|
|
101
|
-
| `'Numeric'` | Simple numeric with smart triplet expansion
|
|
102
|
-
| `'IdToken'` | Base62 encoding
|
|
103
|
-
| `{ template: '...' }` | Custom template
|
|
104
|
+
| Format | Description | Example |
|
|
105
|
+
| --------------------- | ------------------------------------------- | ------------------------------------- |
|
|
106
|
+
| `'SafeNumeric'` | Collision-safe with tildes (recommended) | `~000~`, `~001~` |
|
|
107
|
+
| `'Numeric'` | Simple numeric with smart triplet expansion | `000`, `001` |
|
|
108
|
+
| `'IdToken'` | Base62 encoding | `0`, `A`, `z`, `10` |
|
|
109
|
+
| `{ template: '...' }` | Custom template | `{ template: '[ID:{i}]' }` → `[ID:0]` |
|
|
104
110
|
|
|
105
111
|
## Streaming Support
|
|
106
112
|
|
|
@@ -195,11 +201,6 @@ const wrapped2 = wrapBamlFunction(fn, {
|
|
|
195
201
|
});
|
|
196
202
|
```
|
|
197
203
|
|
|
198
|
-
## Peer Dependencies
|
|
199
|
-
|
|
200
|
-
- `prompt-identifiers` >= 0.1.0
|
|
201
|
-
- `@boundaryml/baml` >= 0.70.0 (optional)
|
|
202
|
-
|
|
203
204
|
## License
|
|
204
205
|
|
|
205
206
|
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
let prompt_identifiers = require("prompt-identifiers");
|
|
3
|
+
//#region src/index.ts
|
|
4
|
+
/**
|
|
5
|
+
* prompt-identifiers-baml - BAML wrapper for automatic ID encoding/decoding
|
|
6
|
+
*
|
|
7
|
+
* Wraps BAML-generated TypeScript functions to automatically encode IDs
|
|
8
|
+
* in inputs and decode them in outputs.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Parse a field path into segments.
|
|
12
|
+
* 'items[].id' -> ['items', '[]', 'id']
|
|
13
|
+
*/
|
|
14
|
+
function parseFieldPath(path) {
|
|
15
|
+
const segments = [];
|
|
16
|
+
let current = "";
|
|
17
|
+
for (let i = 0; i < path.length; i++) {
|
|
18
|
+
const char = path[i];
|
|
19
|
+
if (char === ".") {
|
|
20
|
+
if (current) {
|
|
21
|
+
segments.push(current);
|
|
22
|
+
current = "";
|
|
23
|
+
}
|
|
24
|
+
} else if (char === "[" && path[i + 1] === "]") {
|
|
25
|
+
if (current) {
|
|
26
|
+
segments.push(current);
|
|
27
|
+
current = "";
|
|
28
|
+
}
|
|
29
|
+
segments.push("[]");
|
|
30
|
+
i++;
|
|
31
|
+
} else current += char;
|
|
32
|
+
}
|
|
33
|
+
if (current) segments.push(current);
|
|
34
|
+
return segments;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Check if a value at the given path should be encoded.
|
|
38
|
+
*/
|
|
39
|
+
function matchesFieldPath(currentPath, targetSegments) {
|
|
40
|
+
if (currentPath.length !== targetSegments.length) return false;
|
|
41
|
+
for (let i = 0; i < targetSegments.length; i++) {
|
|
42
|
+
const target = targetSegments[i];
|
|
43
|
+
const current = currentPath[i];
|
|
44
|
+
if (target === "[]") {
|
|
45
|
+
if (!/^\d+$/.test(current)) return false;
|
|
46
|
+
} else if (target !== current) return false;
|
|
47
|
+
}
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Deep traverse and encode IDs in an object.
|
|
52
|
+
* Returns a new object with IDs replaced by placeholders.
|
|
53
|
+
*/
|
|
54
|
+
function deepEncode(value, ctx, path = []) {
|
|
55
|
+
if (value === null || value === void 0) return value;
|
|
56
|
+
if (typeof value === "string") {
|
|
57
|
+
if (!(ctx.fieldPaths === null || ctx.fieldPaths.some((fp) => matchesFieldPath(path, fp)))) return value;
|
|
58
|
+
return (0, prompt_identifiers.encode)(value, ctx.config, ctx.state).encoded;
|
|
59
|
+
}
|
|
60
|
+
if (Array.isArray(value)) return value.map((item, index) => deepEncode(item, ctx, [...path, String(index)]));
|
|
61
|
+
if (typeof value === "object") {
|
|
62
|
+
const result = {};
|
|
63
|
+
for (const [key, val] of Object.entries(value)) result[key] = deepEncode(val, ctx, [...path, key]);
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
return value;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Deep traverse and decode placeholders in an object.
|
|
70
|
+
* Returns a new object with placeholders replaced by original IDs.
|
|
71
|
+
*/
|
|
72
|
+
function deepDecode(value, mapping, countRef) {
|
|
73
|
+
if (value === null || value === void 0) return value;
|
|
74
|
+
if (typeof value === "string") {
|
|
75
|
+
const decoded = (0, prompt_identifiers.decode)(value, mapping);
|
|
76
|
+
if (decoded !== value) countRef.count++;
|
|
77
|
+
return decoded;
|
|
78
|
+
}
|
|
79
|
+
if (Array.isArray(value)) return value.map((item) => deepDecode(item, mapping, countRef));
|
|
80
|
+
if (typeof value === "object") {
|
|
81
|
+
const result = {};
|
|
82
|
+
for (const [key, val] of Object.entries(value)) result[key] = deepDecode(val, mapping, countRef);
|
|
83
|
+
return result;
|
|
84
|
+
}
|
|
85
|
+
return value;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Wrap a BAML function to automatically encode IDs in inputs and decode them in outputs.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```typescript
|
|
92
|
+
* import { wrapBamlFunction } from 'prompt-identifiers-baml';
|
|
93
|
+
* import { b } from './baml_client';
|
|
94
|
+
*
|
|
95
|
+
* const analyzeUser = wrapBamlFunction(b.AnalyzeUser, {
|
|
96
|
+
* config: { inputFormat: 'UUID', outputFormat: 'SafeNumeric' },
|
|
97
|
+
* encodeFields: ['user_id', 'items[].id'], // Optional: specific fields
|
|
98
|
+
* });
|
|
99
|
+
*
|
|
100
|
+
* // Use normally - IDs are auto-encoded/decoded
|
|
101
|
+
* const result = await analyzeUser({
|
|
102
|
+
* user_id: '123e4567-e89b-42d3-a456-426655440000',
|
|
103
|
+
* items: [{ id: '987fcdeb-51a2-43f7-8d9c-0123456789ab', name: 'test' }]
|
|
104
|
+
* });
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
function wrapBamlFunction(fn, options) {
|
|
108
|
+
const { config, encodeFields, onEncode, onDecode, debug } = options;
|
|
109
|
+
const fieldPaths = encodeFields ? encodeFields.map(parseFieldPath) : null;
|
|
110
|
+
return async (input) => {
|
|
111
|
+
const ctx = {
|
|
112
|
+
config,
|
|
113
|
+
fieldPaths,
|
|
114
|
+
state: (0, prompt_identifiers.createEncodeState)()
|
|
115
|
+
};
|
|
116
|
+
const startEncode = debug ? performance.now() : 0;
|
|
117
|
+
const encodedInput = deepEncode(input, ctx);
|
|
118
|
+
const encodeDurationMs = debug ? performance.now() - startEncode : 0;
|
|
119
|
+
onEncode?.({
|
|
120
|
+
mapping: ctx.state.mapping,
|
|
121
|
+
...debug && { debugData: {
|
|
122
|
+
encodedCount: Object.keys(ctx.state.mapping).length,
|
|
123
|
+
input,
|
|
124
|
+
output: encodedInput,
|
|
125
|
+
durationMs: encodeDurationMs
|
|
126
|
+
} }
|
|
127
|
+
});
|
|
128
|
+
const output = await fn(encodedInput);
|
|
129
|
+
const countRef = { count: 0 };
|
|
130
|
+
const startDecode = debug ? performance.now() : 0;
|
|
131
|
+
const decodedOutput = deepDecode(output, ctx.state.mapping, countRef);
|
|
132
|
+
const decodeDurationMs = debug ? performance.now() - startDecode : 0;
|
|
133
|
+
onDecode?.({ ...debug && { debugData: {
|
|
134
|
+
decodedCount: countRef.count,
|
|
135
|
+
input: output,
|
|
136
|
+
output: decodedOutput,
|
|
137
|
+
durationMs: decodeDurationMs
|
|
138
|
+
} } });
|
|
139
|
+
return decodedOutput;
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Wrap a BAML streaming function to automatically encode IDs in inputs
|
|
144
|
+
* and decode them in outputs (both partial and final).
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```typescript
|
|
148
|
+
* import { wrapBamlStreamingFunction } from 'prompt-identifiers-baml';
|
|
149
|
+
* import { b } from './baml_client';
|
|
150
|
+
*
|
|
151
|
+
* const streamAnalysis = wrapBamlStreamingFunction(b.stream.AnalyzeUser, {
|
|
152
|
+
* config: { inputFormat: 'UUID', outputFormat: 'SafeNumeric' },
|
|
153
|
+
* });
|
|
154
|
+
*
|
|
155
|
+
* for await (const partial of streamAnalysis({ user_id: 'uuid-here' })) {
|
|
156
|
+
* console.log(partial); // IDs decoded in real-time
|
|
157
|
+
* }
|
|
158
|
+
* ```
|
|
159
|
+
*/
|
|
160
|
+
function wrapBamlStreamingFunction(fn, options) {
|
|
161
|
+
const { config, encodeFields, onEncode, onDecode, debug } = options;
|
|
162
|
+
const fieldPaths = encodeFields ? encodeFields.map(parseFieldPath) : null;
|
|
163
|
+
return async function* (input) {
|
|
164
|
+
const ctx = {
|
|
165
|
+
config,
|
|
166
|
+
fieldPaths,
|
|
167
|
+
state: (0, prompt_identifiers.createEncodeState)()
|
|
168
|
+
};
|
|
169
|
+
const startEncode = debug ? performance.now() : 0;
|
|
170
|
+
const encodedInput = deepEncode(input, ctx);
|
|
171
|
+
const encodeDurationMs = debug ? performance.now() - startEncode : 0;
|
|
172
|
+
onEncode?.({
|
|
173
|
+
mapping: ctx.state.mapping,
|
|
174
|
+
...debug && { debugData: {
|
|
175
|
+
encodedCount: Object.keys(ctx.state.mapping).length,
|
|
176
|
+
input,
|
|
177
|
+
output: encodedInput,
|
|
178
|
+
durationMs: encodeDurationMs
|
|
179
|
+
} }
|
|
180
|
+
});
|
|
181
|
+
const generator = fn(encodedInput);
|
|
182
|
+
let totalDecoded = 0;
|
|
183
|
+
const startDecode = debug ? performance.now() : 0;
|
|
184
|
+
while (true) {
|
|
185
|
+
const { value, done } = await generator.next();
|
|
186
|
+
if (done) {
|
|
187
|
+
const countRef = { count: 0 };
|
|
188
|
+
const decodedValue = deepDecode(value, ctx.state.mapping, countRef);
|
|
189
|
+
totalDecoded += countRef.count;
|
|
190
|
+
const decodeDurationMs = debug ? performance.now() - startDecode : 0;
|
|
191
|
+
onDecode?.({ ...debug && { debugData: {
|
|
192
|
+
decodedCount: totalDecoded,
|
|
193
|
+
input: value,
|
|
194
|
+
output: decodedValue,
|
|
195
|
+
durationMs: decodeDurationMs
|
|
196
|
+
} } });
|
|
197
|
+
return decodedValue;
|
|
198
|
+
}
|
|
199
|
+
const countRef = { count: 0 };
|
|
200
|
+
const decodedValue = deepDecode(value, ctx.state.mapping, countRef);
|
|
201
|
+
totalDecoded += countRef.count;
|
|
202
|
+
yield decodedValue;
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Utility function to encode a plain object (useful for manual encoding).
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* ```typescript
|
|
211
|
+
* const { encoded, mapping } = encodeObject(
|
|
212
|
+
* { user_id: 'uuid-here', data: { owner: 'other-uuid' } },
|
|
213
|
+
* { inputFormat: 'UUID', outputFormat: 'SafeNumeric' }
|
|
214
|
+
* );
|
|
215
|
+
* ```
|
|
216
|
+
*/
|
|
217
|
+
function encodeObject(obj, config, encodeFields) {
|
|
218
|
+
const ctx = {
|
|
219
|
+
config,
|
|
220
|
+
fieldPaths: encodeFields ? encodeFields.map(parseFieldPath) : null,
|
|
221
|
+
state: (0, prompt_identifiers.createEncodeState)()
|
|
222
|
+
};
|
|
223
|
+
return {
|
|
224
|
+
encoded: deepEncode(obj, ctx),
|
|
225
|
+
mapping: ctx.state.mapping
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Utility function to decode a plain object (useful for manual decoding).
|
|
230
|
+
*
|
|
231
|
+
* @example
|
|
232
|
+
* ```typescript
|
|
233
|
+
* const decoded = decodeObject(
|
|
234
|
+
* { user_id: '«000»', summary: 'User «000» is active' },
|
|
235
|
+
* { '«000»': 'uuid-here' }
|
|
236
|
+
* );
|
|
237
|
+
* ```
|
|
238
|
+
*/
|
|
239
|
+
function decodeObject(obj, mapping) {
|
|
240
|
+
return deepDecode(obj, mapping, { count: 0 });
|
|
241
|
+
}
|
|
242
|
+
//#endregion
|
|
243
|
+
exports.decodeObject = decodeObject;
|
|
244
|
+
exports.encodeObject = encodeObject;
|
|
245
|
+
exports.wrapBamlFunction = wrapBamlFunction;
|
|
246
|
+
exports.wrapBamlStreamingFunction = wrapBamlStreamingFunction;
|
|
247
|
+
|
|
248
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["encode","decode","createEncodeState"],"sources":["../src/index.ts"],"sourcesContent":["/**\n * prompt-identifiers-baml - BAML wrapper for automatic ID encoding/decoding\n *\n * Wraps BAML-generated TypeScript functions to automatically encode IDs\n * in inputs and decode them in outputs.\n */\n\nimport { createEncodeState, decode, encode, EncodeConfig, EncodeState } from \"prompt-identifiers\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/** Debug data included in onEncode callback when debug is true */\nexport interface EncodeDebugData {\n /** Number of unique IDs encoded */\n encodedCount: number;\n /** Original input object before encoding */\n input: unknown;\n /** Encoded input object */\n output: unknown;\n /** Time spent encoding in milliseconds */\n durationMs: number;\n}\n\n/** Debug data included in onDecode callback when debug is true */\nexport interface DecodeDebugData {\n /** Number of fields containing decoded placeholders */\n decodedCount: number;\n /** Raw output from LLM (encoded) */\n input: unknown;\n /** Decoded output with original IDs restored */\n output: unknown;\n /** Time spent decoding in milliseconds */\n durationMs: number;\n}\n\n/** Configuration options for the BAML wrapper */\nexport interface WrapBamlFunctionOptions {\n /** Encoding configuration (inputFormat and outputFormat) */\n config: EncodeConfig;\n\n /**\n * Optional: specific field paths to encode.\n * If not provided, all string fields matching the input pattern are encoded.\n *\n * Supports dot notation and array wildcards:\n * - 'user_id' - top-level field\n * - 'data.user_id' - nested field\n * - 'items[].id' - all 'id' fields in 'items' array\n * - 'data.users[].profile.id' - deeply nested array field\n *\n * @example\n * encodeFields: ['user_id', 'items[].id', 'metadata.owner_id']\n */\n encodeFields?: string[];\n\n /**\n * Enable debug mode to populate debugData in callbacks with\n * input/output snapshots, counts, and timing information.\n */\n debug?: boolean;\n\n /**\n * Optional callback fired after encoding IDs in the input.\n * Receives the placeholder→ID mapping. When debug is true,\n * also receives debugData with input, output, counts, and timing.\n */\n onEncode?: (result: { mapping: Record<string, string>; debugData?: EncodeDebugData }) => void;\n\n /**\n * Optional callback fired after decoding IDs in the output.\n * When debug is true, receives debugData with input, output, counts, and timing.\n */\n onDecode?: (result: { debugData?: DecodeDebugData }) => void;\n}\n\n/** A BAML function type (sync or async) */\nexport type BamlFunction<TInput, TOutput> = (input: TInput) => Promise<TOutput>;\n\n/** A BAML streaming function type */\nexport type BamlStreamingFunction<TInput, TPartial, TFinal> = (\n input: TInput\n) => AsyncGenerator<TPartial, TFinal, unknown>;\n\n// =============================================================================\n// Field Path Matching\n// =============================================================================\n\n/**\n * Parse a field path into segments.\n * 'items[].id' -> ['items', '[]', 'id']\n */\nfunction parseFieldPath(path: string): string[] {\n const segments: string[] = [];\n let current = \"\";\n\n for (let i = 0; i < path.length; i++) {\n const char = path[i];\n\n if (char === \".\") {\n if (current) {\n segments.push(current);\n current = \"\";\n }\n } else if (char === \"[\" && path[i + 1] === \"]\") {\n if (current) {\n segments.push(current);\n current = \"\";\n }\n segments.push(\"[]\");\n i++; // skip ']'\n } else {\n current += char;\n }\n }\n\n if (current) {\n segments.push(current);\n }\n\n return segments;\n}\n\n/**\n * Check if a value at the given path should be encoded.\n */\nfunction matchesFieldPath(currentPath: string[], targetSegments: string[]): boolean {\n if (currentPath.length !== targetSegments.length) {\n return false;\n }\n\n for (let i = 0; i < targetSegments.length; i++) {\n const target = targetSegments[i];\n const current = currentPath[i];\n\n // '[]' matches any array index\n if (target === \"[]\") {\n if (!/^\\d+$/.test(current)) {\n return false;\n }\n } else if (target !== current) {\n return false;\n }\n }\n\n return true;\n}\n\n// =============================================================================\n// Deep Object Traversal\n// =============================================================================\n\n/**\n * Context for encoding operations - tracks state across recursive calls.\n * Delegates to core's encode() with shared EncodeState for consistent placeholder assignment.\n */\ninterface EncodeContext {\n config: EncodeConfig;\n fieldPaths: string[][] | null; // null means auto-detect mode\n state: EncodeState;\n}\n\n/**\n * Deep traverse and encode IDs in an object.\n * Returns a new object with IDs replaced by placeholders.\n */\nfunction deepEncode<T>(value: T, ctx: EncodeContext, path: string[] = []): T {\n // Handle null/undefined\n if (value === null || value === undefined) {\n return value;\n }\n\n // Handle strings - the primary encoding target\n if (typeof value === \"string\") {\n // Check if this field should be encoded\n const shouldEncode =\n ctx.fieldPaths === null || ctx.fieldPaths.some((fp) => matchesFieldPath(path, fp));\n\n if (!shouldEncode) {\n return value;\n }\n\n // Encode the string using core's encode() with shared state\n return encode(value, ctx.config, ctx.state).encoded as T;\n }\n\n // Handle arrays\n if (Array.isArray(value)) {\n return value.map((item, index) => deepEncode(item, ctx, [...path, String(index)])) as T;\n }\n\n // Handle objects\n if (typeof value === \"object\") {\n const result: Record<string, unknown> = {};\n\n for (const [key, val] of Object.entries(value)) {\n result[key] = deepEncode(val, ctx, [...path, key]);\n }\n\n return result as T;\n }\n\n // Primitives (numbers, booleans) - return as-is\n return value;\n}\n\n/**\n * Deep traverse and decode placeholders in an object.\n * Returns a new object with placeholders replaced by original IDs.\n */\nfunction deepDecode<T>(value: T, mapping: Record<string, string>, countRef: { count: number }): T {\n // Handle null/undefined\n if (value === null || value === undefined) {\n return value;\n }\n\n // Handle strings\n if (typeof value === \"string\") {\n const decoded = decode(value, mapping);\n // Count replacements\n if (decoded !== value) {\n countRef.count++;\n }\n return decoded as T;\n }\n\n // Handle arrays\n if (Array.isArray(value)) {\n return value.map((item) => deepDecode(item, mapping, countRef)) as T;\n }\n\n // Handle objects\n if (typeof value === \"object\") {\n const result: Record<string, unknown> = {};\n\n for (const [key, val] of Object.entries(value)) {\n result[key] = deepDecode(val, mapping, countRef);\n }\n\n return result as T;\n }\n\n // Primitives - return as-is\n return value;\n}\n\n// =============================================================================\n// Public API\n// =============================================================================\n\n/**\n * Wrap a BAML function to automatically encode IDs in inputs and decode them in outputs.\n *\n * @example\n * ```typescript\n * import { wrapBamlFunction } from 'prompt-identifiers-baml';\n * import { b } from './baml_client';\n *\n * const analyzeUser = wrapBamlFunction(b.AnalyzeUser, {\n * config: { inputFormat: 'UUID', outputFormat: 'SafeNumeric' },\n * encodeFields: ['user_id', 'items[].id'], // Optional: specific fields\n * });\n *\n * // Use normally - IDs are auto-encoded/decoded\n * const result = await analyzeUser({\n * user_id: '123e4567-e89b-42d3-a456-426655440000',\n * items: [{ id: '987fcdeb-51a2-43f7-8d9c-0123456789ab', name: 'test' }]\n * });\n * ```\n */\nexport function wrapBamlFunction<TInput, TOutput>(\n fn: BamlFunction<TInput, TOutput>,\n options: WrapBamlFunctionOptions\n): BamlFunction<TInput, TOutput> {\n const { config, encodeFields, onEncode, onDecode, debug } = options;\n\n // Pre-parse field paths if provided\n const fieldPaths = encodeFields ? encodeFields.map(parseFieldPath) : null;\n\n return async (input: TInput): Promise<TOutput> => {\n // Encode input\n const ctx: EncodeContext = {\n config,\n fieldPaths,\n state: createEncodeState(),\n };\n\n const startEncode = debug ? performance.now() : 0;\n const encodedInput = deepEncode(input, ctx);\n const encodeDurationMs = debug ? performance.now() - startEncode : 0;\n\n onEncode?.({\n mapping: ctx.state.mapping,\n ...(debug && {\n debugData: {\n encodedCount: Object.keys(ctx.state.mapping).length,\n input,\n output: encodedInput,\n durationMs: encodeDurationMs,\n },\n }),\n });\n\n // Call the original function\n const output = await fn(encodedInput);\n\n // Decode output\n const countRef = { count: 0 };\n const startDecode = debug ? performance.now() : 0;\n const decodedOutput = deepDecode(output, ctx.state.mapping, countRef);\n const decodeDurationMs = debug ? performance.now() - startDecode : 0;\n\n onDecode?.({\n ...(debug && {\n debugData: {\n decodedCount: countRef.count,\n input: output,\n output: decodedOutput,\n durationMs: decodeDurationMs,\n },\n }),\n });\n\n return decodedOutput;\n };\n}\n\n/**\n * Wrap a BAML streaming function to automatically encode IDs in inputs\n * and decode them in outputs (both partial and final).\n *\n * @example\n * ```typescript\n * import { wrapBamlStreamingFunction } from 'prompt-identifiers-baml';\n * import { b } from './baml_client';\n *\n * const streamAnalysis = wrapBamlStreamingFunction(b.stream.AnalyzeUser, {\n * config: { inputFormat: 'UUID', outputFormat: 'SafeNumeric' },\n * });\n *\n * for await (const partial of streamAnalysis({ user_id: 'uuid-here' })) {\n * console.log(partial); // IDs decoded in real-time\n * }\n * ```\n */\nexport function wrapBamlStreamingFunction<TInput, TPartial, TFinal>(\n fn: BamlStreamingFunction<TInput, TPartial, TFinal>,\n options: WrapBamlFunctionOptions\n): BamlStreamingFunction<TInput, TPartial, TFinal> {\n const { config, encodeFields, onEncode, onDecode, debug } = options;\n\n // Pre-parse field paths if provided\n const fieldPaths = encodeFields ? encodeFields.map(parseFieldPath) : null;\n\n return async function* (input: TInput): AsyncGenerator<TPartial, TFinal, unknown> {\n // Encode input\n const ctx: EncodeContext = {\n config,\n fieldPaths,\n state: createEncodeState(),\n };\n\n const startEncode = debug ? performance.now() : 0;\n const encodedInput = deepEncode(input, ctx);\n const encodeDurationMs = debug ? performance.now() - startEncode : 0;\n\n onEncode?.({\n mapping: ctx.state.mapping,\n ...(debug && {\n debugData: {\n encodedCount: Object.keys(ctx.state.mapping).length,\n input,\n output: encodedInput,\n durationMs: encodeDurationMs,\n },\n }),\n });\n\n // Call the original streaming function\n const generator = fn(encodedInput);\n let totalDecoded = 0;\n const startDecode = debug ? performance.now() : 0;\n\n while (true) {\n const { value, done } = await generator.next();\n\n if (done) {\n // Final value\n const countRef = { count: 0 };\n const decodedValue = deepDecode(value, ctx.state.mapping, countRef);\n totalDecoded += countRef.count;\n const decodeDurationMs = debug ? performance.now() - startDecode : 0;\n\n onDecode?.({\n ...(debug && {\n debugData: {\n decodedCount: totalDecoded,\n input: value,\n output: decodedValue,\n durationMs: decodeDurationMs,\n },\n }),\n });\n return decodedValue;\n }\n\n // Partial value\n const countRef = { count: 0 };\n const decodedValue = deepDecode(value, ctx.state.mapping, countRef);\n totalDecoded += countRef.count;\n yield decodedValue;\n }\n };\n}\n\n/**\n * Utility function to encode a plain object (useful for manual encoding).\n *\n * @example\n * ```typescript\n * const { encoded, mapping } = encodeObject(\n * { user_id: 'uuid-here', data: { owner: 'other-uuid' } },\n * { inputFormat: 'UUID', outputFormat: 'SafeNumeric' }\n * );\n * ```\n */\nexport function encodeObject<T>(\n obj: T,\n config: EncodeConfig,\n encodeFields?: string[]\n): { encoded: T; mapping: Record<string, string> } {\n const fieldPaths = encodeFields ? encodeFields.map(parseFieldPath) : null;\n\n const ctx: EncodeContext = {\n config,\n fieldPaths,\n state: createEncodeState(),\n };\n\n const encoded = deepEncode(obj, ctx);\n\n return { encoded, mapping: ctx.state.mapping };\n}\n\n/**\n * Utility function to decode a plain object (useful for manual decoding).\n *\n * @example\n * ```typescript\n * const decoded = decodeObject(\n * { user_id: '«000»', summary: 'User «000» is active' },\n * { '«000»': 'uuid-here' }\n * );\n * ```\n */\nexport function decodeObject<T>(obj: T, mapping: Record<string, string>): T {\n const countRef = { count: 0 };\n return deepDecode(obj, mapping, countRef);\n}\n"],"mappings":"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"}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { EncodeConfig } from "prompt-identifiers";
|
|
2
|
+
//#region src/index.d.ts
|
|
3
|
+
/** Debug data included in onEncode callback when debug is true */
|
|
4
|
+
export interface EncodeDebugData {
|
|
5
|
+
/** Number of unique IDs encoded */
|
|
6
|
+
encodedCount: number;
|
|
7
|
+
/** Original input object before encoding */
|
|
8
|
+
input: unknown;
|
|
9
|
+
/** Encoded input object */
|
|
10
|
+
output: unknown;
|
|
11
|
+
/** Time spent encoding in milliseconds */
|
|
12
|
+
durationMs: number;
|
|
13
|
+
}
|
|
14
|
+
/** Debug data included in onDecode callback when debug is true */
|
|
15
|
+
export interface DecodeDebugData {
|
|
16
|
+
/** Number of fields containing decoded placeholders */
|
|
17
|
+
decodedCount: number;
|
|
18
|
+
/** Raw output from LLM (encoded) */
|
|
19
|
+
input: unknown;
|
|
20
|
+
/** Decoded output with original IDs restored */
|
|
21
|
+
output: unknown;
|
|
22
|
+
/** Time spent decoding in milliseconds */
|
|
23
|
+
durationMs: number;
|
|
24
|
+
}
|
|
25
|
+
/** Configuration options for the BAML wrapper */
|
|
26
|
+
export interface WrapBamlFunctionOptions {
|
|
27
|
+
/** Encoding configuration (inputFormat and outputFormat) */
|
|
28
|
+
config: EncodeConfig;
|
|
29
|
+
/**
|
|
30
|
+
* Optional: specific field paths to encode.
|
|
31
|
+
* If not provided, all string fields matching the input pattern are encoded.
|
|
32
|
+
*
|
|
33
|
+
* Supports dot notation and array wildcards:
|
|
34
|
+
* - 'user_id' - top-level field
|
|
35
|
+
* - 'data.user_id' - nested field
|
|
36
|
+
* - 'items[].id' - all 'id' fields in 'items' array
|
|
37
|
+
* - 'data.users[].profile.id' - deeply nested array field
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* encodeFields: ['user_id', 'items[].id', 'metadata.owner_id']
|
|
41
|
+
*/
|
|
42
|
+
encodeFields?: string[];
|
|
43
|
+
/**
|
|
44
|
+
* Enable debug mode to populate debugData in callbacks with
|
|
45
|
+
* input/output snapshots, counts, and timing information.
|
|
46
|
+
*/
|
|
47
|
+
debug?: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Optional callback fired after encoding IDs in the input.
|
|
50
|
+
* Receives the placeholder→ID mapping. When debug is true,
|
|
51
|
+
* also receives debugData with input, output, counts, and timing.
|
|
52
|
+
*/
|
|
53
|
+
onEncode?: (result: {
|
|
54
|
+
mapping: Record<string, string>;
|
|
55
|
+
debugData?: EncodeDebugData;
|
|
56
|
+
}) => void;
|
|
57
|
+
/**
|
|
58
|
+
* Optional callback fired after decoding IDs in the output.
|
|
59
|
+
* When debug is true, receives debugData with input, output, counts, and timing.
|
|
60
|
+
*/
|
|
61
|
+
onDecode?: (result: {
|
|
62
|
+
debugData?: DecodeDebugData;
|
|
63
|
+
}) => void;
|
|
64
|
+
}
|
|
65
|
+
/** A BAML function type (sync or async) */
|
|
66
|
+
export type BamlFunction<TInput, TOutput> = (input: TInput) => Promise<TOutput>;
|
|
67
|
+
/** A BAML streaming function type */
|
|
68
|
+
export type BamlStreamingFunction<TInput, TPartial, TFinal> = (input: TInput) => AsyncGenerator<TPartial, TFinal, unknown>;
|
|
69
|
+
/**
|
|
70
|
+
* Wrap a BAML function to automatically encode IDs in inputs and decode them in outputs.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```typescript
|
|
74
|
+
* import { wrapBamlFunction } from 'prompt-identifiers-baml';
|
|
75
|
+
* import { b } from './baml_client';
|
|
76
|
+
*
|
|
77
|
+
* const analyzeUser = wrapBamlFunction(b.AnalyzeUser, {
|
|
78
|
+
* config: { inputFormat: 'UUID', outputFormat: 'SafeNumeric' },
|
|
79
|
+
* encodeFields: ['user_id', 'items[].id'], // Optional: specific fields
|
|
80
|
+
* });
|
|
81
|
+
*
|
|
82
|
+
* // Use normally - IDs are auto-encoded/decoded
|
|
83
|
+
* const result = await analyzeUser({
|
|
84
|
+
* user_id: '123e4567-e89b-42d3-a456-426655440000',
|
|
85
|
+
* items: [{ id: '987fcdeb-51a2-43f7-8d9c-0123456789ab', name: 'test' }]
|
|
86
|
+
* });
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
export declare function wrapBamlFunction<TInput, TOutput>(fn: BamlFunction<TInput, TOutput>, options: WrapBamlFunctionOptions): BamlFunction<TInput, TOutput>;
|
|
90
|
+
/**
|
|
91
|
+
* Wrap a BAML streaming function to automatically encode IDs in inputs
|
|
92
|
+
* and decode them in outputs (both partial and final).
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```typescript
|
|
96
|
+
* import { wrapBamlStreamingFunction } from 'prompt-identifiers-baml';
|
|
97
|
+
* import { b } from './baml_client';
|
|
98
|
+
*
|
|
99
|
+
* const streamAnalysis = wrapBamlStreamingFunction(b.stream.AnalyzeUser, {
|
|
100
|
+
* config: { inputFormat: 'UUID', outputFormat: 'SafeNumeric' },
|
|
101
|
+
* });
|
|
102
|
+
*
|
|
103
|
+
* for await (const partial of streamAnalysis({ user_id: 'uuid-here' })) {
|
|
104
|
+
* console.log(partial); // IDs decoded in real-time
|
|
105
|
+
* }
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
export declare function wrapBamlStreamingFunction<TInput, TPartial, TFinal>(fn: BamlStreamingFunction<TInput, TPartial, TFinal>, options: WrapBamlFunctionOptions): BamlStreamingFunction<TInput, TPartial, TFinal>;
|
|
109
|
+
/**
|
|
110
|
+
* Utility function to encode a plain object (useful for manual encoding).
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* ```typescript
|
|
114
|
+
* const { encoded, mapping } = encodeObject(
|
|
115
|
+
* { user_id: 'uuid-here', data: { owner: 'other-uuid' } },
|
|
116
|
+
* { inputFormat: 'UUID', outputFormat: 'SafeNumeric' }
|
|
117
|
+
* );
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
export declare function encodeObject<T>(obj: T, config: EncodeConfig, encodeFields?: string[]): {
|
|
121
|
+
encoded: T;
|
|
122
|
+
mapping: Record<string, string>;
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* Utility function to decode a plain object (useful for manual decoding).
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```typescript
|
|
129
|
+
* const decoded = decodeObject(
|
|
130
|
+
* { user_id: '«000»', summary: 'User «000» is active' },
|
|
131
|
+
* { '«000»': 'uuid-here' }
|
|
132
|
+
* );
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
export declare function decodeObject<T>(obj: T, mapping: Record<string, string>): T;
|
|
136
|
+
//#endregion
|
|
137
|
+
//# sourceMappingURL=index.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/index.ts"],"mappings":";;;iBAciB;;EAEf;;EAEA;;EAEA;;EAEA;;;iBAIe;;EAEf;;EAEA;;EAEA;;EAEA;;;iBAIe;;EAEf,QAAQ;;;;;;;;;;;;;;EAeR;;;;;EAMA;;;;;;EAOA,YAAY;IAAU,SAAS;IAAwB,YAAY;;;;;;EAMnE,YAAY;IAAU,YAAY;;;;YAIxB,aAAa,QAAQ,YAAY,OAAO,WAAW,QAAQ;;YAG3D,sBAAsB,QAAQ,UAAU,WAClD,OAAO,WACJ,eAAe,UAAU;;;;;;;;;;;;;;;;;;;;;wBA4Ld,iBAAiB,QAAQ,SACvC,IAAI,aAAa,QAAQ,UACzB,SAAS,0BACR,aAAa,QAAQ;;;;;;;;;;;;;;;;;;;wBAwER,0BAA0B,QAAQ,UAAU,QAC1D,IAAI,sBAAsB,QAAQ,UAAU,SAC5C,SAAS,0BACR,sBAAsB,QAAQ,UAAU;;;;;;;;;;;;wBA8E3B,aAAa,GAC3B,KAAK,GACL,QAAQ,cACR;EACG,SAAS;EAAG,SAAS;;;;;;;;;;;;;wBAyBV,aAAa,GAAG,KAAK,GAAG,SAAS,yBAAyB"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,78 +1,71 @@
|
|
|
1
|
-
import { EncodeConfig } from
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* prompt-identifiers-baml - BAML wrapper for automatic ID encoding/decoding
|
|
5
|
-
*
|
|
6
|
-
* Wraps BAML-generated TypeScript functions to automatically encode IDs
|
|
7
|
-
* in inputs and decode them in outputs.
|
|
8
|
-
*/
|
|
9
|
-
|
|
1
|
+
import { EncodeConfig } from "prompt-identifiers";
|
|
2
|
+
//#region src/index.d.ts
|
|
10
3
|
/** Debug data included in onEncode callback when debug is true */
|
|
11
|
-
interface EncodeDebugData {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
4
|
+
export interface EncodeDebugData {
|
|
5
|
+
/** Number of unique IDs encoded */
|
|
6
|
+
encodedCount: number;
|
|
7
|
+
/** Original input object before encoding */
|
|
8
|
+
input: unknown;
|
|
9
|
+
/** Encoded input object */
|
|
10
|
+
output: unknown;
|
|
11
|
+
/** Time spent encoding in milliseconds */
|
|
12
|
+
durationMs: number;
|
|
20
13
|
}
|
|
21
14
|
/** Debug data included in onDecode callback when debug is true */
|
|
22
|
-
interface DecodeDebugData {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
15
|
+
export interface DecodeDebugData {
|
|
16
|
+
/** Number of fields containing decoded placeholders */
|
|
17
|
+
decodedCount: number;
|
|
18
|
+
/** Raw output from LLM (encoded) */
|
|
19
|
+
input: unknown;
|
|
20
|
+
/** Decoded output with original IDs restored */
|
|
21
|
+
output: unknown;
|
|
22
|
+
/** Time spent decoding in milliseconds */
|
|
23
|
+
durationMs: number;
|
|
31
24
|
}
|
|
32
25
|
/** Configuration options for the BAML wrapper */
|
|
33
|
-
interface WrapBamlFunctionOptions {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
26
|
+
export interface WrapBamlFunctionOptions {
|
|
27
|
+
/** Encoding configuration (inputFormat and outputFormat) */
|
|
28
|
+
config: EncodeConfig;
|
|
29
|
+
/**
|
|
30
|
+
* Optional: specific field paths to encode.
|
|
31
|
+
* If not provided, all string fields matching the input pattern are encoded.
|
|
32
|
+
*
|
|
33
|
+
* Supports dot notation and array wildcards:
|
|
34
|
+
* - 'user_id' - top-level field
|
|
35
|
+
* - 'data.user_id' - nested field
|
|
36
|
+
* - 'items[].id' - all 'id' fields in 'items' array
|
|
37
|
+
* - 'data.users[].profile.id' - deeply nested array field
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* encodeFields: ['user_id', 'items[].id', 'metadata.owner_id']
|
|
41
|
+
*/
|
|
42
|
+
encodeFields?: string[];
|
|
43
|
+
/**
|
|
44
|
+
* Enable debug mode to populate debugData in callbacks with
|
|
45
|
+
* input/output snapshots, counts, and timing information.
|
|
46
|
+
*/
|
|
47
|
+
debug?: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Optional callback fired after encoding IDs in the input.
|
|
50
|
+
* Receives the placeholder→ID mapping. When debug is true,
|
|
51
|
+
* also receives debugData with input, output, counts, and timing.
|
|
52
|
+
*/
|
|
53
|
+
onEncode?: (result: {
|
|
54
|
+
mapping: Record<string, string>;
|
|
55
|
+
debugData?: EncodeDebugData;
|
|
56
|
+
}) => void;
|
|
57
|
+
/**
|
|
58
|
+
* Optional callback fired after decoding IDs in the output.
|
|
59
|
+
* When debug is true, receives debugData with input, output, counts, and timing.
|
|
60
|
+
*/
|
|
61
|
+
onDecode?: (result: {
|
|
62
|
+
debugData?: DecodeDebugData;
|
|
63
|
+
}) => void;
|
|
71
64
|
}
|
|
72
65
|
/** A BAML function type (sync or async) */
|
|
73
|
-
type BamlFunction<TInput, TOutput> = (input: TInput) => Promise<TOutput>;
|
|
66
|
+
export type BamlFunction<TInput, TOutput> = (input: TInput) => Promise<TOutput>;
|
|
74
67
|
/** A BAML streaming function type */
|
|
75
|
-
type BamlStreamingFunction<TInput, TPartial, TFinal> = (input: TInput) => AsyncGenerator<TPartial, TFinal, unknown>;
|
|
68
|
+
export type BamlStreamingFunction<TInput, TPartial, TFinal> = (input: TInput) => AsyncGenerator<TPartial, TFinal, unknown>;
|
|
76
69
|
/**
|
|
77
70
|
* Wrap a BAML function to automatically encode IDs in inputs and decode them in outputs.
|
|
78
71
|
*
|
|
@@ -93,7 +86,7 @@ type BamlStreamingFunction<TInput, TPartial, TFinal> = (input: TInput) => AsyncG
|
|
|
93
86
|
* });
|
|
94
87
|
* ```
|
|
95
88
|
*/
|
|
96
|
-
declare function wrapBamlFunction<TInput, TOutput>(fn: BamlFunction<TInput, TOutput>, options: WrapBamlFunctionOptions): BamlFunction<TInput, TOutput>;
|
|
89
|
+
export declare function wrapBamlFunction<TInput, TOutput>(fn: BamlFunction<TInput, TOutput>, options: WrapBamlFunctionOptions): BamlFunction<TInput, TOutput>;
|
|
97
90
|
/**
|
|
98
91
|
* Wrap a BAML streaming function to automatically encode IDs in inputs
|
|
99
92
|
* and decode them in outputs (both partial and final).
|
|
@@ -112,7 +105,7 @@ declare function wrapBamlFunction<TInput, TOutput>(fn: BamlFunction<TInput, TOut
|
|
|
112
105
|
* }
|
|
113
106
|
* ```
|
|
114
107
|
*/
|
|
115
|
-
declare function wrapBamlStreamingFunction<TInput, TPartial, TFinal>(fn: BamlStreamingFunction<TInput, TPartial, TFinal>, options: WrapBamlFunctionOptions): BamlStreamingFunction<TInput, TPartial, TFinal>;
|
|
108
|
+
export declare function wrapBamlStreamingFunction<TInput, TPartial, TFinal>(fn: BamlStreamingFunction<TInput, TPartial, TFinal>, options: WrapBamlFunctionOptions): BamlStreamingFunction<TInput, TPartial, TFinal>;
|
|
116
109
|
/**
|
|
117
110
|
* Utility function to encode a plain object (useful for manual encoding).
|
|
118
111
|
*
|
|
@@ -124,9 +117,9 @@ declare function wrapBamlStreamingFunction<TInput, TPartial, TFinal>(fn: BamlStr
|
|
|
124
117
|
* );
|
|
125
118
|
* ```
|
|
126
119
|
*/
|
|
127
|
-
declare function encodeObject<T>(obj: T, config: EncodeConfig, encodeFields?: string[]): {
|
|
128
|
-
|
|
129
|
-
|
|
120
|
+
export declare function encodeObject<T>(obj: T, config: EncodeConfig, encodeFields?: string[]): {
|
|
121
|
+
encoded: T;
|
|
122
|
+
mapping: Record<string, string>;
|
|
130
123
|
};
|
|
131
124
|
/**
|
|
132
125
|
* Utility function to decode a plain object (useful for manual decoding).
|
|
@@ -139,6 +132,6 @@ declare function encodeObject<T>(obj: T, config: EncodeConfig, encodeFields?: st
|
|
|
139
132
|
* );
|
|
140
133
|
* ```
|
|
141
134
|
*/
|
|
142
|
-
declare function decodeObject<T>(obj: T, mapping: Record<string, string>): T;
|
|
143
|
-
|
|
144
|
-
|
|
135
|
+
export declare function decodeObject<T>(obj: T, mapping: Record<string, string>): T;
|
|
136
|
+
//#endregion
|
|
137
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":";;;iBAciB;;EAEf;;EAEA;;EAEA;;EAEA;;;iBAIe;;EAEf;;EAEA;;EAEA;;EAEA;;;iBAIe;;EAEf,QAAQ;;;;;;;;;;;;;;EAeR;;;;;EAMA;;;;;;EAOA,YAAY;IAAU,SAAS;IAAwB,YAAY;;;;;;EAMnE,YAAY;IAAU,YAAY;;;;YAIxB,aAAa,QAAQ,YAAY,OAAO,WAAW,QAAQ;;YAG3D,sBAAsB,QAAQ,UAAU,WAClD,OAAO,WACJ,eAAe,UAAU;;;;;;;;;;;;;;;;;;;;;wBA4Ld,iBAAiB,QAAQ,SACvC,IAAI,aAAa,QAAQ,UACzB,SAAS,0BACR,aAAa,QAAQ;;;;;;;;;;;;;;;;;;;wBAwER,0BAA0B,QAAQ,UAAU,QAC1D,IAAI,sBAAsB,QAAQ,UAAU,SAC5C,SAAS,0BACR,sBAAsB,QAAQ,UAAU;;;;;;;;;;;;wBA8E3B,aAAa,GAC3B,KAAK,GACL,QAAQ,cACR;EACG,SAAS;EAAG,SAAS;;;;;;;;;;;;;wBAyBV,aAAa,GAAG,KAAK,GAAG,SAAS,yBAAyB"}
|