@synet/encoder 1.0.0

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.
@@ -0,0 +1,243 @@
1
+ "use strict";
2
+ /**
3
+ * Pure Encoding Functions - Serverless Ready
4
+ *
5
+ * Simple, stateless functions for encoding/decoding operations.
6
+ * These throw on error (simple operations) following Doctrine #14.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.encodeBase64 = encodeBase64;
10
+ exports.decodeBase64 = decodeBase64;
11
+ exports.encodeBase64URL = encodeBase64URL;
12
+ exports.decodeBase64URL = decodeBase64URL;
13
+ exports.encodeHex = encodeHex;
14
+ exports.decodeHex = decodeHex;
15
+ exports.encodeURIString = encodeURIString;
16
+ exports.decodeURIString = decodeURIString;
17
+ exports.encodeASCII = encodeASCII;
18
+ exports.decodeASCII = decodeASCII;
19
+ exports.encode = encode;
20
+ exports.decode = decode;
21
+ exports.detectFormat = detectFormat;
22
+ exports.validateFormat = validateFormat;
23
+ exports.chain = chain;
24
+ exports.reverseChain = reverseChain;
25
+ /**
26
+ * Encode string to Base64
27
+ */
28
+ function encodeBase64(data) {
29
+ if (typeof Buffer !== 'undefined') {
30
+ return Buffer.from(data, 'utf8').toString('base64');
31
+ }
32
+ if (typeof btoa !== 'undefined') {
33
+ // Modern Unicode-safe base64 encoding without deprecated unescape()
34
+ const bytes = new TextEncoder().encode(data);
35
+ const binaryString = Array.from(bytes, byte => String.fromCharCode(byte)).join('');
36
+ return btoa(binaryString);
37
+ }
38
+ throw new Error('No base64 encoding available');
39
+ }
40
+ /**
41
+ * Decode Base64 string
42
+ */
43
+ function decodeBase64(data) {
44
+ if (typeof Buffer !== 'undefined') {
45
+ return Buffer.from(data, 'base64').toString('utf8');
46
+ }
47
+ if (typeof atob !== 'undefined') {
48
+ // Modern Unicode-safe base64 decoding without deprecated escape()
49
+ const binaryString = atob(data);
50
+ const bytes = new Uint8Array(binaryString.length);
51
+ for (let i = 0; i < binaryString.length; i++) {
52
+ bytes[i] = binaryString.charCodeAt(i);
53
+ }
54
+ return new TextDecoder('utf-8').decode(bytes);
55
+ }
56
+ throw new Error('No base64 decoding available');
57
+ }
58
+ /**
59
+ * Encode string to Base64URL (URL-safe)
60
+ */
61
+ function encodeBase64URL(data) {
62
+ return encodeBase64(data)
63
+ .replace(/\+/g, '-')
64
+ .replace(/\//g, '_')
65
+ .replace(/=/g, '');
66
+ }
67
+ /**
68
+ * Decode Base64URL string
69
+ */
70
+ function decodeBase64URL(data) {
71
+ let base64 = data.replace(/-/g, '+').replace(/_/g, '/');
72
+ while (base64.length % 4) {
73
+ base64 += '=';
74
+ }
75
+ return decodeBase64(base64);
76
+ }
77
+ /**
78
+ * Encode string to hexadecimal
79
+ */
80
+ function encodeHex(data) {
81
+ return Array.from(data)
82
+ .map(char => char.charCodeAt(0).toString(16).padStart(2, '0'))
83
+ .join('');
84
+ }
85
+ /**
86
+ * Decode hexadecimal string
87
+ */
88
+ function decodeHex(data) {
89
+ if (data.length % 2 !== 0) {
90
+ throw new Error('Invalid hex string: length must be even');
91
+ }
92
+ if (!/^[0-9a-fA-F]*$/.test(data)) {
93
+ throw new Error('Invalid hex string: contains non-hex characters');
94
+ }
95
+ let result = '';
96
+ for (let i = 0; i < data.length; i += 2) {
97
+ result += String.fromCharCode(Number.parseInt(data.slice(i, i + 2), 16));
98
+ }
99
+ return result;
100
+ }
101
+ /**
102
+ * Encode string for URI
103
+ */
104
+ function encodeURIString(data) {
105
+ return encodeURIComponent(data);
106
+ }
107
+ /**
108
+ * Decode URI-encoded string
109
+ */
110
+ function decodeURIString(data) {
111
+ return decodeURIComponent(data);
112
+ }
113
+ /**
114
+ * Encode string as ASCII (validates ASCII-only)
115
+ */
116
+ function encodeASCII(data) {
117
+ for (let i = 0; i < data.length; i++) {
118
+ const code = data.charCodeAt(i);
119
+ if (code > 127) {
120
+ throw new Error(`Non-ASCII character found at position ${i}: '${data[i]}' (code: ${code})`);
121
+ }
122
+ }
123
+ return data;
124
+ }
125
+ /**
126
+ * Decode ASCII string (no-op, validates printable ASCII)
127
+ */
128
+ function decodeASCII(data) {
129
+ for (let i = 0; i < data.length; i++) {
130
+ const code = data.charCodeAt(i);
131
+ if (code < 32 || code > 126) {
132
+ throw new Error(`Non-printable ASCII character at position ${i}: code ${code}`);
133
+ }
134
+ }
135
+ return data;
136
+ }
137
+ /**
138
+ * Generic encode function
139
+ */
140
+ function encode(data, format) {
141
+ switch (format) {
142
+ case 'base64':
143
+ return encodeBase64(data);
144
+ case 'base64url':
145
+ return encodeBase64URL(data);
146
+ case 'hex':
147
+ return encodeHex(data);
148
+ case 'uri':
149
+ return encodeURIString(data);
150
+ case 'ascii':
151
+ return encodeASCII(data);
152
+ default:
153
+ throw new Error(`Unsupported encoding format: ${format}`);
154
+ }
155
+ }
156
+ /**
157
+ * Generic decode function
158
+ */
159
+ function decode(data, format) {
160
+ switch (format) {
161
+ case 'base64':
162
+ return decodeBase64(data);
163
+ case 'base64url':
164
+ return decodeBase64URL(data);
165
+ case 'hex':
166
+ return decodeHex(data);
167
+ case 'uri':
168
+ return decodeURIString(data);
169
+ case 'ascii':
170
+ return decodeASCII(data);
171
+ default:
172
+ throw new Error(`Unsupported decoding format: ${format}`);
173
+ }
174
+ }
175
+ /**
176
+ * Auto-detect encoding format
177
+ */
178
+ function detectFormat(data) {
179
+ // Test patterns in order of specificity/confidence
180
+ if (/^[0-9a-fA-F]+$/.test(data) && data.length % 2 === 0) {
181
+ return 'hex';
182
+ }
183
+ // Base64url should be tested before base64 since it's more restrictive
184
+ if (/^[A-Za-z0-9\-_]*$/.test(data) && !data.includes('+') && !data.includes('/') && !data.includes('=') && data.length > 0) {
185
+ return 'base64url';
186
+ }
187
+ // Base64 with standard characters or padding
188
+ if (/^[A-Za-z0-9+/]*={0,2}$/.test(data) && data.length % 4 === 0 && (data.includes('+') || data.includes('/') || data.includes('='))) {
189
+ return 'base64';
190
+ }
191
+ if (data.includes('%') && /^[A-Za-z0-9\-_.~%!*'()]+$/.test(data)) {
192
+ return 'uri';
193
+ }
194
+ if (/^[\x20-\x7E]*$/.test(data)) {
195
+ return 'ascii';
196
+ }
197
+ throw new Error(`Cannot detect encoding format for: ${data.slice(0, 50)}...`);
198
+ }
199
+ /**
200
+ * Validate format of encoded data
201
+ */
202
+ function validateFormat(data, format) {
203
+ try {
204
+ switch (format) {
205
+ case 'base64':
206
+ return /^[A-Za-z0-9+/]*={0,2}$/.test(data) && data.length % 4 === 0;
207
+ case 'base64url':
208
+ return /^[A-Za-z0-9\-_]*$/.test(data);
209
+ case 'hex':
210
+ return /^[0-9a-fA-F]*$/.test(data) && data.length % 2 === 0;
211
+ case 'uri':
212
+ decodeURIComponent(data);
213
+ return true;
214
+ case 'ascii':
215
+ return /^[\x20-\x7E]*$/.test(data);
216
+ default:
217
+ return false;
218
+ }
219
+ }
220
+ catch {
221
+ return false;
222
+ }
223
+ }
224
+ /**
225
+ * Chain multiple encodings
226
+ */
227
+ function chain(data, formats) {
228
+ let result = data;
229
+ for (const format of formats) {
230
+ result = encode(result, format);
231
+ }
232
+ return result;
233
+ }
234
+ /**
235
+ * Reverse chain decodings
236
+ */
237
+ function reverseChain(data, formats) {
238
+ let result = data;
239
+ for (const format of [...formats].reverse()) {
240
+ result = decode(result, format);
241
+ }
242
+ return result;
243
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @synet/encoder - Conscious Encoding/Decoding Unit
3
+ *
4
+ * Zero-dependency encoding operations following Unit Architecture doctrine.
5
+ *
6
+ * EXPORTS:
7
+ * - Encoder: Complete conscious encoder unit with teach/learn capabilities
8
+ * - Pure functions: Simple functional encoding operations
9
+ * - Result: Foundational error handling pattern
10
+ * - Types: All encoding-related interfaces
11
+ */
12
+ export { Encoder } from './encoder.unit.js';
13
+ export { Result } from './result.js';
14
+ export type { EncoderConfig, EncoderProps, EncodingFormat, EncodingResult, DecodingResult, DetectionResult, ValidationResult } from './encoder.unit.js';
15
+ export { encode, decode, encodeBase64, decodeBase64, encodeBase64URL, decodeBase64URL, encodeHex, decodeHex, encodeURIString, decodeURIString, encodeASCII, decodeASCII, detectFormat, validateFormat, chain, reverseChain, type EncodingFormat as FunctionEncodingFormat } from './functions.js';
package/dist/index.js ADDED
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ /**
3
+ * @synet/encoder - Conscious Encoding/Decoding Unit
4
+ *
5
+ * Zero-dependency encoding operations following Unit Architecture doctrine.
6
+ *
7
+ * EXPORTS:
8
+ * - Encoder: Complete conscious encoder unit with teach/learn capabilities
9
+ * - Pure functions: Simple functional encoding operations
10
+ * - Result: Foundational error handling pattern
11
+ * - Types: All encoding-related interfaces
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.reverseChain = exports.chain = exports.validateFormat = exports.detectFormat = exports.decodeASCII = exports.encodeASCII = exports.decodeURIString = exports.encodeURIString = exports.decodeHex = exports.encodeHex = exports.decodeBase64URL = exports.encodeBase64URL = exports.decodeBase64 = exports.encodeBase64 = exports.decode = exports.encode = exports.Result = exports.Encoder = void 0;
15
+ // Core Unit
16
+ var encoder_unit_js_1 = require("./encoder.unit.js");
17
+ Object.defineProperty(exports, "Encoder", { enumerable: true, get: function () { return encoder_unit_js_1.Encoder; } });
18
+ // Result pattern (foundational)
19
+ var result_js_1 = require("./result.js");
20
+ Object.defineProperty(exports, "Result", { enumerable: true, get: function () { return result_js_1.Result; } });
21
+ // Pure function exports for simple use cases
22
+ var functions_js_1 = require("./functions.js");
23
+ Object.defineProperty(exports, "encode", { enumerable: true, get: function () { return functions_js_1.encode; } });
24
+ Object.defineProperty(exports, "decode", { enumerable: true, get: function () { return functions_js_1.decode; } });
25
+ Object.defineProperty(exports, "encodeBase64", { enumerable: true, get: function () { return functions_js_1.encodeBase64; } });
26
+ Object.defineProperty(exports, "decodeBase64", { enumerable: true, get: function () { return functions_js_1.decodeBase64; } });
27
+ Object.defineProperty(exports, "encodeBase64URL", { enumerable: true, get: function () { return functions_js_1.encodeBase64URL; } });
28
+ Object.defineProperty(exports, "decodeBase64URL", { enumerable: true, get: function () { return functions_js_1.decodeBase64URL; } });
29
+ Object.defineProperty(exports, "encodeHex", { enumerable: true, get: function () { return functions_js_1.encodeHex; } });
30
+ Object.defineProperty(exports, "decodeHex", { enumerable: true, get: function () { return functions_js_1.decodeHex; } });
31
+ Object.defineProperty(exports, "encodeURIString", { enumerable: true, get: function () { return functions_js_1.encodeURIString; } });
32
+ Object.defineProperty(exports, "decodeURIString", { enumerable: true, get: function () { return functions_js_1.decodeURIString; } });
33
+ Object.defineProperty(exports, "encodeASCII", { enumerable: true, get: function () { return functions_js_1.encodeASCII; } });
34
+ Object.defineProperty(exports, "decodeASCII", { enumerable: true, get: function () { return functions_js_1.decodeASCII; } });
35
+ Object.defineProperty(exports, "detectFormat", { enumerable: true, get: function () { return functions_js_1.detectFormat; } });
36
+ Object.defineProperty(exports, "validateFormat", { enumerable: true, get: function () { return functions_js_1.validateFormat; } });
37
+ Object.defineProperty(exports, "chain", { enumerable: true, get: function () { return functions_js_1.chain; } });
38
+ Object.defineProperty(exports, "reverseChain", { enumerable: true, get: function () { return functions_js_1.reverseChain; } });
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Foundational Result Pattern for Encoder Operations
3
+ *
4
+ * Local copy following Unit Architecture Doctrine #14: ERROR BOUNDARY CLARITY
5
+ * Simple operations throw, complex operations use Result pattern
6
+ */
7
+ export declare class Result<T> {
8
+ private readonly _value;
9
+ private readonly _error;
10
+ private readonly _errorCause?;
11
+ private constructor();
12
+ static success<T>(value: T): Result<T>;
13
+ static fail<T>(message: string, cause?: unknown): Result<T>;
14
+ get isSuccess(): boolean;
15
+ get isFailure(): boolean;
16
+ get value(): T;
17
+ get error(): string;
18
+ get errorCause(): unknown;
19
+ map<U>(fn: (value: T) => U): Result<U>;
20
+ flatMap<U>(fn: (value: T) => Result<U>): Result<U>;
21
+ getOrElse(defaultValue: T): T;
22
+ match<U>(onSuccess: (value: T) => U, onFailure: (error: string) => U): U;
23
+ }
package/dist/result.js ADDED
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ /**
3
+ * Foundational Result Pattern for Encoder Operations
4
+ *
5
+ * Local copy following Unit Architecture Doctrine #14: ERROR BOUNDARY CLARITY
6
+ * Simple operations throw, complex operations use Result pattern
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.Result = void 0;
10
+ class Result {
11
+ constructor(_value, _error, _errorCause) {
12
+ this._value = _value;
13
+ this._error = _error;
14
+ this._errorCause = _errorCause;
15
+ }
16
+ static success(value) {
17
+ return new Result(value, null);
18
+ }
19
+ static fail(message, cause) {
20
+ return new Result(null, message, cause);
21
+ }
22
+ get isSuccess() {
23
+ return this._error === null;
24
+ }
25
+ get isFailure() {
26
+ return this._error !== null;
27
+ }
28
+ get value() {
29
+ if (this._error !== null) {
30
+ throw new Error(`Attempted to get value from failed Result: ${this._error}`);
31
+ }
32
+ return this._value;
33
+ }
34
+ get error() {
35
+ return this._error || '';
36
+ }
37
+ get errorCause() {
38
+ return this._errorCause;
39
+ }
40
+ map(fn) {
41
+ if (this.isFailure) {
42
+ return Result.fail(this._error || 'Unknown error', this._errorCause);
43
+ }
44
+ try {
45
+ return Result.success(fn(this.value));
46
+ }
47
+ catch (error) {
48
+ return Result.fail(`Map operation failed: ${error instanceof Error ? error.message : String(error)}`, error);
49
+ }
50
+ }
51
+ flatMap(fn) {
52
+ if (this.isFailure) {
53
+ return Result.fail(this._error || 'Unknown error', this._errorCause);
54
+ }
55
+ try {
56
+ return fn(this.value);
57
+ }
58
+ catch (error) {
59
+ return Result.fail(`FlatMap operation failed: ${error instanceof Error ? error.message : String(error)}`, error);
60
+ }
61
+ }
62
+ getOrElse(defaultValue) {
63
+ return this.isSuccess ? this.value : defaultValue;
64
+ }
65
+ match(onSuccess, onFailure) {
66
+ return this.isSuccess ? onSuccess(this.value) : onFailure(this.error);
67
+ }
68
+ }
69
+ exports.Result = Result;
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@synet/encoder",
3
+ "version": "1.0.0",
4
+ "description": "Unit Architecture compliant encoding/decoding operations",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "private": false,
8
+ "publishConfig": {
9
+ "access": "public"
10
+ },
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/synthetism/encoder.git"
14
+ },
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "test": "vitest run",
18
+ "dev:test": "vitest",
19
+ "clean": "rm -rf dist",
20
+ "prebuild": "npm run clean",
21
+ "coverage": "vitest run --coverage",
22
+ "lint": "biome lint ./src",
23
+ "lint:fix": "biome lint --write ./src",
24
+ "format": "biome format --write './src'",
25
+ "prepublishOnly": "npm run lint:fix && npm run test && npm run build",
26
+ "version:dev": "npm version --no-git-tag-version prerelease --preid=dev",
27
+ "version:patch": "npm version --no-git-tag-version patch",
28
+ "version:minor": "npm version --no-git-tag-version minor",
29
+ "version:major": "npm version --no-git-tag-version major",
30
+ "publish:dev": "npm publish --registry=https://registry.dig.run/ --tag dev",
31
+ "publish:prod": "npm publish --registry=https://registry.npmjs.org/",
32
+ "release:dev": "npm run version:dev && npm run publish:dev",
33
+ "release:patch": "npm run version:patch && npm run publish:prod",
34
+ "release:minor": "npm run version:minor && npm run publish:prod",
35
+ "release:major": "npm run version:major && npm run publish:prod"
36
+ },
37
+ "devDependencies": {
38
+ "@biomejs/biome": "^1.9.4",
39
+ "@types/node": "^22.15.31",
40
+ "@vitest/coverage-v8": "^3.1.3",
41
+ "typescript": "^5.8.3",
42
+ "vitest": "^3.2.3"
43
+ },
44
+ "keywords": [
45
+ "Synet",
46
+ "Unit Architecture",
47
+ "Living beings in code"
48
+ ],
49
+ "author": "Synet Team",
50
+ "homepage": "https://synthetism.ai",
51
+ "license": "MIT",
52
+ "dependencies": {
53
+ "@synet/unit": "^1.0.6"
54
+ }
55
+ }