@arkadia/data 0.1.7 → 0.1.9

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.
Files changed (54) hide show
  1. package/.prettierrc +8 -0
  2. package/README.md +159 -112
  3. package/dist/config.d.ts.map +1 -1
  4. package/dist/config.js.map +1 -1
  5. package/dist/core/Decoder.d.ts.map +1 -1
  6. package/dist/core/Decoder.js +123 -97
  7. package/dist/core/Decoder.js.map +1 -1
  8. package/dist/core/Encoder.d.ts +1 -2
  9. package/dist/core/Encoder.d.ts.map +1 -1
  10. package/dist/core/Encoder.js +74 -76
  11. package/dist/core/Encoder.js.map +1 -1
  12. package/dist/core/Parser.d.ts +1 -1
  13. package/dist/core/Parser.d.ts.map +1 -1
  14. package/dist/core/Parser.js +11 -11
  15. package/dist/core/Parser.js.map +1 -1
  16. package/dist/index.d.ts +4 -4
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +7 -8
  19. package/dist/index.js.map +1 -1
  20. package/dist/models/Meta.d.ts +3 -2
  21. package/dist/models/Meta.d.ts.map +1 -1
  22. package/dist/models/Meta.js +3 -3
  23. package/dist/models/Meta.js.map +1 -1
  24. package/dist/models/Node.d.ts +4 -3
  25. package/dist/models/Node.d.ts.map +1 -1
  26. package/dist/models/Node.js +29 -23
  27. package/dist/models/Node.js.map +1 -1
  28. package/dist/models/Schema.d.ts.map +1 -1
  29. package/dist/models/Schema.js +27 -21
  30. package/dist/models/Schema.js.map +1 -1
  31. package/eslint.config.mjs +42 -0
  32. package/package.json +11 -1
  33. package/scripts/verify-build.js +95 -92
  34. package/src/config.ts +75 -75
  35. package/src/core/Decoder.ts +984 -922
  36. package/src/core/Encoder.ts +364 -371
  37. package/src/core/Parser.ts +112 -112
  38. package/src/index.ts +18 -20
  39. package/src/models/Meta.ts +107 -107
  40. package/src/models/Node.ts +190 -185
  41. package/src/models/Schema.ts +198 -193
  42. package/tests/00.meta.test.ts +19 -25
  43. package/tests/00.node.test.ts +40 -48
  44. package/tests/00.primitive.test.ts +121 -95
  45. package/tests/00.schema.test.ts +28 -35
  46. package/tests/01.schema.test.ts +42 -52
  47. package/tests/02.data.test.ts +69 -75
  48. package/tests/03.errors.test.ts +53 -55
  49. package/tests/04.list.test.ts +192 -193
  50. package/tests/05.record.test.ts +54 -56
  51. package/tests/06.meta.test.ts +393 -389
  52. package/tests/utils.ts +47 -44
  53. package/tsconfig.json +27 -29
  54. package/vitest.config.ts +1 -1
@@ -0,0 +1,42 @@
1
+ import globals from 'globals';
2
+ import pluginJs from '@eslint/js';
3
+ import tseslint from 'typescript-eslint';
4
+ import eslintConfigPrettier from 'eslint-config-prettier';
5
+
6
+ /** @type {import('eslint').Linter.Config[]} */
7
+ export default [
8
+ // 1. Global ignores (equivalent to .eslintignore)
9
+ {
10
+ ignores: ['dist/', 'node_modules/', 'coverage/'],
11
+ },
12
+
13
+ // 2. Base configuration for all files
14
+ {
15
+ files: ['**/*.{js,mjs,cjs,ts}'],
16
+ languageOptions: {
17
+ globals: globals.node,
18
+ },
19
+ },
20
+
21
+ // 3. Recommended JS rules
22
+ pluginJs.configs.recommended,
23
+
24
+ // 4. Recommended TypeScript rules
25
+ ...tseslint.configs.recommended,
26
+
27
+ // 5. Custom Rules (Overrides)
28
+ {
29
+ rules: {
30
+ // Allow unused vars if they start with underscore (like Python setup)
31
+ '@typescript-eslint/no-unused-vars': [
32
+ 'warn',
33
+ { argsIgnorePattern: '^_', varsIgnorePattern: '^_' },
34
+ ],
35
+ // Allow 'any' type but warn about it (optional)
36
+ '@typescript-eslint/no-explicit-any': 'warn',
37
+ },
38
+ },
39
+
40
+ // 6. Prettier integration (Must be last to override other configs)
41
+ eslintConfigPrettier,
42
+ ];
package/package.json CHANGED
@@ -1,10 +1,14 @@
1
1
  {
2
2
  "name": "@arkadia/data",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "Parser and Stringifier for Arkadia Data Format (AKD)",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "scripts": {
8
+ "lint": "eslint .",
9
+ "lint:fix": "eslint . --fix",
10
+ "format": "prettier --write .",
11
+ "check": "prettier --check . && eslint .",
8
12
  "clean": "rimraf dist",
9
13
  "build": "npm run clean && tsc",
10
14
  "verify": "node scripts/verify-build.js",
@@ -24,9 +28,15 @@
24
28
  "author": "Arkadia Solutions",
25
29
  "license": "MIT",
26
30
  "devDependencies": {
31
+ "@eslint/js": "^9.39.2",
27
32
  "@types/node": "^20.19.31",
33
+ "eslint": "^9.39.2",
34
+ "eslint-config-prettier": "^10.1.9",
35
+ "globals": "^17.3.0",
36
+ "prettier": "^3.8.1",
28
37
  "rimraf": "^6.1.2",
29
38
  "typescript": "^5.9.3",
39
+ "typescript-eslint": "^8.56.0",
30
40
  "vitest": "^3.2.4"
31
41
  }
32
42
  }
@@ -1,15 +1,17 @@
1
+ /* eslint-disable @typescript-eslint/no-require-imports */
2
+
1
3
  const { execSync } = require('child_process');
2
4
  const fs = require('fs');
3
5
  const path = require('path');
4
6
 
5
7
  // Load package.json to get the real package name (e.g., @arkadia/data)
6
8
  const pkg = require('../package.json');
7
- const PACKAGE_NAME = pkg.name;
9
+ const PACKAGE_NAME = pkg.name;
8
10
 
9
11
  // --- CONFIGURATION ---
10
12
  const ROOT_DIR = path.resolve(__dirname, '..');
11
13
  const TEMP_DIR = path.join(ROOT_DIR, 'temp_smoke_test');
12
- const DIST_DIR = path.join(ROOT_DIR, 'dist');
14
+ const DIST_DIR = path.join(ROOT_DIR, 'dist');
13
15
 
14
16
  // Node.js modules we DO NOT want in the browser build
15
17
  const FORBIDDEN_IMPORTS = ['util', 'fs', 'path', 'child_process', 'os'];
@@ -20,80 +22,80 @@ const success = (msg) => console.log(`\x1b[32m[SUCCESS]\x1b[0m ${msg}`);
20
22
  const error = (msg) => console.error(`\x1b[31m[ERROR]\x1b[0m ${msg}`);
21
23
 
22
24
  function scanDirForForbiddenImports(dir) {
23
- if (!fs.existsSync(dir)) return;
24
-
25
- const files = fs.readdirSync(dir);
26
-
27
- for (const file of files) {
28
- const fullPath = path.join(dir, file);
29
- const stat = fs.statSync(fullPath);
30
-
31
- if (stat.isDirectory()) {
32
- scanDirForForbiddenImports(fullPath);
33
- } else if (file.endsWith('.js') || file.endsWith('.mjs')) {
34
- const content = fs.readFileSync(fullPath, 'utf-8');
35
-
36
- FORBIDDEN_IMPORTS.forEach(mod => {
37
- // Regex looks for: require('util') OR from 'util'
38
- const regex = new RegExp(`(require\\(['"]${mod}['"]\\)|from\\s+['"]${mod}['"])`);
39
- if (regex.test(content)) {
40
- throw new Error(
41
- `Found Node.js specific module '${mod}' in file: ${file}\n` +
42
- `This will crash in the browser! Please remove the import or use a polyfill.`
43
- );
44
- }
45
- });
25
+ if (!fs.existsSync(dir)) return;
26
+
27
+ const files = fs.readdirSync(dir);
28
+
29
+ for (const file of files) {
30
+ const fullPath = path.join(dir, file);
31
+ const stat = fs.statSync(fullPath);
32
+
33
+ if (stat.isDirectory()) {
34
+ scanDirForForbiddenImports(fullPath);
35
+ } else if (file.endsWith('.js') || file.endsWith('.mjs')) {
36
+ const content = fs.readFileSync(fullPath, 'utf-8');
37
+
38
+ FORBIDDEN_IMPORTS.forEach((mod) => {
39
+ // Regex looks for: require('util') OR from 'util'
40
+ const regex = new RegExp(`(require\\(['"]${mod}['"]\\)|from\\s+['"]${mod}['"])`);
41
+ if (regex.test(content)) {
42
+ throw new Error(
43
+ `Found Node.js specific module '${mod}' in file: ${file}\n` +
44
+ `This will crash in the browser! Please remove the import or use a polyfill.`,
45
+ );
46
46
  }
47
+ });
47
48
  }
49
+ }
48
50
  }
49
51
 
50
52
  // --- MAIN PROCESS ---
51
53
 
52
54
  try {
53
- log(`🚀 Starting verification process for: ${PACKAGE_NAME}...`);
54
-
55
- // 1. Cleanup
56
- if (fs.existsSync(TEMP_DIR)) {
57
- log('Cleaning up old test artifacts...');
58
- fs.rmSync(TEMP_DIR, { recursive: true, force: true });
59
- }
60
-
61
- // 2. Build Project
62
- log('1. Building project (npm run build)...');
63
- try {
64
- execSync('npm run build', { stdio: 'inherit', cwd: ROOT_DIR });
65
- } catch (e) {
66
- throw new Error("Build failed. Fix compilation errors first.");
67
- }
68
-
69
- // 3. BROWSER COMPATIBILITY CHECK
70
- log('2. Checking for browser compatibility (No Node.js built-ins)...');
71
- scanDirForForbiddenImports(DIST_DIR);
72
- success('Browser compatibility check passed! No forbidden imports found.');
73
-
74
- // 4. Pack Project
75
- log('3. Packaging (npm pack)...');
76
- const packOutput = execSync('npm pack', { cwd: ROOT_DIR }).toString().trim();
77
- // npm pack output might have multiple lines, take the last one (filename)
78
- const tgzFileName = packOutput.split('\n').pop().trim();
79
- const tgzPath = path.join(ROOT_DIR, tgzFileName);
80
-
81
- if (!fs.existsSync(tgzPath)) {
82
- throw new Error(`Could not find packed file: ${tgzFileName}`);
83
- }
84
- log(` 📦 Created: ${tgzFileName}`);
85
-
86
- // 5. Create Temp Environment
87
- log('4. Creating temporary test environment...');
88
- fs.mkdirSync(TEMP_DIR);
89
- execSync('npm init -y', { cwd: TEMP_DIR, stdio: 'ignore' });
55
+ log(`🚀 Starting verification process for: ${PACKAGE_NAME}...`);
90
56
 
91
- // 6. Install Tarball
92
- log(`5. Installing tarball into temp env...`);
93
- execSync(`npm install "${tgzPath}"`, { cwd: TEMP_DIR, stdio: 'ignore' });
94
-
95
- // 7. Verify Script - USING FUNCTIONAL IMPORTS { decode, encode }
96
- const verifyScript = `
57
+ // 1. Cleanup
58
+ if (fs.existsSync(TEMP_DIR)) {
59
+ log('Cleaning up old test artifacts...');
60
+ fs.rmSync(TEMP_DIR, { recursive: true, force: true });
61
+ }
62
+
63
+ // 2. Build Project
64
+ log('1. Building project (npm run build)...');
65
+ try {
66
+ execSync('npm run build', { stdio: 'inherit', cwd: ROOT_DIR });
67
+ } catch {
68
+ throw new Error('Build failed. Fix compilation errors first.');
69
+ }
70
+
71
+ // 3. BROWSER COMPATIBILITY CHECK
72
+ log('2. Checking for browser compatibility (No Node.js built-ins)...');
73
+ scanDirForForbiddenImports(DIST_DIR);
74
+ success('Browser compatibility check passed! No forbidden imports found.');
75
+
76
+ // 4. Pack Project
77
+ log('3. Packaging (npm pack)...');
78
+ const packOutput = execSync('npm pack', { cwd: ROOT_DIR }).toString().trim();
79
+ // npm pack output might have multiple lines, take the last one (filename)
80
+ const tgzFileName = packOutput.split('\n').pop().trim();
81
+ const tgzPath = path.join(ROOT_DIR, tgzFileName);
82
+
83
+ if (!fs.existsSync(tgzPath)) {
84
+ throw new Error(`Could not find packed file: ${tgzFileName}`);
85
+ }
86
+ log(` 📦 Created: ${tgzFileName}`);
87
+
88
+ // 5. Create Temp Environment
89
+ log('4. Creating temporary test environment...');
90
+ fs.mkdirSync(TEMP_DIR);
91
+ execSync('npm init -y', { cwd: TEMP_DIR, stdio: 'ignore' });
92
+
93
+ // 6. Install Tarball
94
+ log(`5. Installing tarball into temp env...`);
95
+ execSync(`npm install "${tgzPath}"`, { cwd: TEMP_DIR, stdio: 'ignore' });
96
+
97
+ // 7. Verify Script - USING FUNCTIONAL IMPORTS { decode, encode }
98
+ const verifyScript = `
97
99
  const { decode, encode } = require('${PACKAGE_NAME}');
98
100
 
99
101
  console.log(" 🧪 Running functional tests...");
@@ -171,32 +173,33 @@ try {
171
173
  }
172
174
  `;
173
175
 
174
- fs.writeFileSync(path.join(TEMP_DIR, 'verify_script.js'), verifyScript);
176
+ fs.writeFileSync(path.join(TEMP_DIR, 'verify_script.js'), verifyScript);
175
177
 
176
- // 8. Run Verification
177
- log('6. Running functional verification...');
178
- execSync('node verify_script.js', { cwd: TEMP_DIR, stdio: 'inherit' });
178
+ // 8. Run Verification
179
+ log('6. Running functional verification...');
180
+ execSync('node verify_script.js', { cwd: TEMP_DIR, stdio: 'inherit' });
179
181
 
180
- // 9. Cleanup
181
- log('7. Cleanup...');
182
- fs.rmSync(TEMP_DIR, { recursive: true, force: true });
183
- fs.unlinkSync(tgzPath);
184
-
185
- console.log('\n');
186
- success('READY FOR PUBLISH! 🚀');
187
- console.log(` - Package: ${PACKAGE_NAME}`);
188
- console.log(' - Browser Compatible: YES');
189
- console.log('\n');
182
+ // 9. Cleanup
183
+ log('7. Cleanup...');
184
+ fs.rmSync(TEMP_DIR, { recursive: true, force: true });
185
+ fs.unlinkSync(tgzPath);
190
186
 
187
+ console.log('\n');
188
+ success('READY FOR PUBLISH! 🚀');
189
+ console.log(` - Package: ${PACKAGE_NAME}`);
190
+ console.log(' - Browser Compatible: YES');
191
+ console.log('\n');
191
192
  } catch (e) {
192
- console.log('\n');
193
- error('VERIFICATION FAILED!');
193
+ console.log('\n');
194
+ error('VERIFICATION FAILED!');
195
+ console.error(e.message || e);
196
+
197
+ try {
198
+ const tgzFiles = fs.readdirSync(ROOT_DIR).filter((f) => f.endsWith('.tgz'));
199
+ tgzFiles.forEach((f) => fs.unlinkSync(path.join(ROOT_DIR, f)));
200
+ } catch (e) {
194
201
  console.error(e.message || e);
195
-
196
- try {
197
- const tgzFiles = fs.readdirSync(ROOT_DIR).filter(f => f.endsWith('.tgz'));
198
- tgzFiles.forEach(f => fs.unlinkSync(path.join(ROOT_DIR, f)));
199
- } catch (cleanupErr) {}
200
-
201
- process.exit(1);
202
- }
202
+ }
203
+
204
+ process.exit(1);
205
+ }
package/src/config.ts CHANGED
@@ -2,101 +2,101 @@
2
2
  * Configuration options for the AK Data Format Encoder.
3
3
  */
4
4
  export interface EncoderConfig {
5
- /**
6
- * Embed schema directly inside sample data (useful for LLM prompting).
7
- * Example: [ (name: string /name of user/, age: int) ]
8
- * Default: false
9
- */
10
- promptOutput: boolean;
5
+ /**
6
+ * Embed schema directly inside sample data (useful for LLM prompting).
7
+ * Example: [ (name: string /name of user/, age: int) ]
8
+ * Default: false
9
+ */
10
+ promptOutput: boolean;
11
11
 
12
- /**
13
- * Number of spaces used for indentation.
14
- * Default: 2
15
- */
16
- indent: number;
12
+ /**
13
+ * Number of spaces used for indentation.
14
+ * Default: 2
15
+ */
16
+ indent: number;
17
17
 
18
- /**
19
- * Initial indentation offset (level).
20
- * Default: 0
21
- */
22
- startIndent: number;
18
+ /**
19
+ * Initial indentation offset (level).
20
+ * Default: 0
21
+ */
22
+ startIndent: number;
23
23
 
24
- /**
25
- * Enable compact formatting. Removes unnecessary spaces and newlines.
26
- * Default: false
27
- */
28
- compact: boolean;
24
+ /**
25
+ * Enable compact formatting. Removes unnecessary spaces and newlines.
26
+ * Default: false
27
+ */
28
+ compact: boolean;
29
29
 
30
- /**
31
- * Escape newline characters in strings as literal \n and \r.
32
- * Default: false
33
- */
34
- escapeNewLines: boolean;
30
+ /**
31
+ * Escape newline characters in strings as literal \n and \r.
32
+ * Default: false
33
+ */
34
+ escapeNewLines: boolean;
35
35
 
36
- /**
37
- * purely removes new lines from strings.
38
- * Default: false
39
- */
40
- removeNewLines: boolean;
36
+ /**
37
+ * purely removes new lines from strings.
38
+ * Default: false
39
+ */
40
+ removeNewLines: boolean;
41
41
 
42
- /**
43
- * Enable ANSI colorized output for terminal debugging.
44
- * Default: false
45
- */
46
- colorize: boolean;
42
+ /**
43
+ * Enable ANSI colorized output for terminal debugging.
44
+ * Default: false
45
+ */
46
+ colorize: boolean;
47
47
 
48
- /**
49
- * Include comments in the output ).
50
- * Default: true
51
- */
52
- includeComments: boolean;
48
+ /**
49
+ * Include comments in the output ).
50
+ * Default: true
51
+ */
52
+ includeComments: boolean;
53
53
 
54
- /**
55
- * Include array size information (e.g. [ $size=5 : ... ]).
56
- * Default: false
57
- */
58
- includeArraySize: boolean;
54
+ /**
55
+ * Include array size information (e.g. [ $size=5 : ... ]).
56
+ * Default: false
57
+ */
58
+ includeArraySize: boolean;
59
59
 
60
- /**
61
- * Include the schema definition header (e.g. <name: string>).
62
- * Default: true
63
- */
64
- includeSchema: boolean;
60
+ /**
61
+ * Include the schema definition header (e.g. <name: string>).
62
+ * Default: true
63
+ */
64
+ includeSchema: boolean;
65
65
 
66
- /**
67
- * Include metadata attributes and tags ($attr=1 #tag).
68
- * Default: true
69
- */
70
- includeMeta: boolean;
66
+ /**
67
+ * Include metadata attributes and tags ($attr=1 #tag).
68
+ * Default: true
69
+ */
70
+ includeMeta: boolean;
71
71
 
72
- /**
73
- * Include type signature after field names (e.g. name: string vs name).
74
- * Default: true
75
- */
76
- includeType: boolean;
72
+ /**
73
+ * Include type signature after field names (e.g. name: string vs name).
74
+ * Default: true
75
+ */
76
+ includeType: boolean;
77
77
  }
78
78
 
79
79
  /**
80
80
  * Default configuration values.
81
81
  */
82
82
  export const DEFAULT_CONFIG: EncoderConfig = {
83
- indent: 2,
84
- startIndent: 0,
85
- compact: false,
86
- escapeNewLines: false,
87
- removeNewLines: false,
88
- colorize: false,
89
- includeComments: true,
90
- includeArraySize: false,
91
- includeSchema: true,
92
- includeMeta: true,
93
- includeType: true,
94
- promptOutput: false,
83
+ indent: 2,
84
+ startIndent: 0,
85
+ compact: false,
86
+ escapeNewLines: false,
87
+ removeNewLines: false,
88
+ colorize: false,
89
+ includeComments: true,
90
+ includeArraySize: false,
91
+ includeSchema: true,
92
+ includeMeta: true,
93
+ includeType: true,
94
+ promptOutput: false,
95
95
  };
96
96
 
97
97
  /**
98
98
  * Helper to merge partial user config with defaults.
99
99
  */
100
100
  export function resolveConfig(config?: Partial<EncoderConfig>): EncoderConfig {
101
- return { ...DEFAULT_CONFIG, ...config };
102
- }
101
+ return { ...DEFAULT_CONFIG, ...config };
102
+ }