@arkadia/ai-data-format 0.1.4
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/LICENSE +21 -0
- package/README.md +198 -0
- package/dist/config.d.ts +75 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +28 -0
- package/dist/config.js.map +1 -0
- package/dist/core/Decoder.d.ts +86 -0
- package/dist/core/Decoder.d.ts.map +1 -0
- package/dist/core/Decoder.js +951 -0
- package/dist/core/Decoder.js.map +1 -0
- package/dist/core/Encoder.d.ts +26 -0
- package/dist/core/Encoder.d.ts.map +1 -0
- package/dist/core/Encoder.js +368 -0
- package/dist/core/Encoder.js.map +1 -0
- package/dist/core/Parser.d.ts +6 -0
- package/dist/core/Parser.d.ts.map +1 -0
- package/dist/core/Parser.js +132 -0
- package/dist/core/Parser.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +46 -0
- package/dist/index.js.map +1 -0
- package/dist/models/Meta.d.ts +48 -0
- package/dist/models/Meta.d.ts.map +1 -0
- package/dist/models/Meta.js +113 -0
- package/dist/models/Meta.js.map +1 -0
- package/dist/models/Node.d.ts +42 -0
- package/dist/models/Node.d.ts.map +1 -0
- package/dist/models/Node.js +179 -0
- package/dist/models/Node.js.map +1 -0
- package/dist/models/Schema.d.ts +55 -0
- package/dist/models/Schema.d.ts.map +1 -0
- package/dist/models/Schema.js +175 -0
- package/dist/models/Schema.js.map +1 -0
- package/package.json +32 -0
- package/scripts/verify-build.js +202 -0
- package/src/config.ts +102 -0
- package/src/core/Decoder.ts +1057 -0
- package/src/core/Encoder.ts +443 -0
- package/src/core/Parser.ts +150 -0
- package/src/index.ts +46 -0
- package/src/models/Meta.ts +135 -0
- package/src/models/Node.ts +212 -0
- package/src/models/Schema.ts +222 -0
- package/tests/00.meta.test.ts +31 -0
- package/tests/00.node.test.ts +54 -0
- package/tests/00.primitive.test.ts +108 -0
- package/tests/00.schema.test.ts +41 -0
- package/tests/01.schema.test.ts +70 -0
- package/tests/02.data.test.ts +89 -0
- package/tests/03.errors.test.ts +71 -0
- package/tests/04.list.test.ts +225 -0
- package/tests/05.record.test.ts +82 -0
- package/tests/06.meta.test.ts +506 -0
- package/tests/utils.ts +69 -0
- package/tsconfig.json +46 -0
- package/vitest.config.ts +9 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Schema = exports.SchemaKind = void 0;
|
|
4
|
+
const Meta_1 = require("./Meta");
|
|
5
|
+
var SchemaKind;
|
|
6
|
+
(function (SchemaKind) {
|
|
7
|
+
SchemaKind["PRIMITIVE"] = "PRIMITIVE";
|
|
8
|
+
SchemaKind["RECORD"] = "RECORD";
|
|
9
|
+
SchemaKind["LIST"] = "LIST";
|
|
10
|
+
SchemaKind["DICT"] = "DICT";
|
|
11
|
+
SchemaKind["ANY"] = "ANY"; // Fallback
|
|
12
|
+
})(SchemaKind || (exports.SchemaKind = SchemaKind = {}));
|
|
13
|
+
class Schema extends Meta_1.Meta {
|
|
14
|
+
constructor(kind, props = {}) {
|
|
15
|
+
super(props);
|
|
16
|
+
// Internal fields storage
|
|
17
|
+
this._fieldsList = [];
|
|
18
|
+
this._fieldsMap = new Map();
|
|
19
|
+
this.kind = kind;
|
|
20
|
+
this.typeName = props.typeName || "any";
|
|
21
|
+
this.name = props.name || "";
|
|
22
|
+
this.element = props.element || null;
|
|
23
|
+
this.key = props.key || null;
|
|
24
|
+
this.value = props.value || null;
|
|
25
|
+
this.required = props.required || false;
|
|
26
|
+
if (props.fields) {
|
|
27
|
+
props.fields.forEach(f => this.addField(f));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
// -----------------------------------------------------------
|
|
31
|
+
// Properties (Is...)
|
|
32
|
+
// -----------------------------------------------------------
|
|
33
|
+
get isPrimitive() { return this.kind === SchemaKind.PRIMITIVE; }
|
|
34
|
+
get isRecord() { return this.kind === SchemaKind.RECORD; }
|
|
35
|
+
get isList() { return this.kind === SchemaKind.LIST; }
|
|
36
|
+
get isAny() {
|
|
37
|
+
return (this.kind === SchemaKind.ANY ||
|
|
38
|
+
(this.typeName === "any" && this.kind === SchemaKind.PRIMITIVE) ||
|
|
39
|
+
(this.typeName === "any" && this.kind === SchemaKind.RECORD));
|
|
40
|
+
}
|
|
41
|
+
get fields() {
|
|
42
|
+
return this._fieldsList;
|
|
43
|
+
}
|
|
44
|
+
// -----------------------------------------------------------
|
|
45
|
+
// Field Management
|
|
46
|
+
// -----------------------------------------------------------
|
|
47
|
+
clearFields() {
|
|
48
|
+
this._fieldsList = [];
|
|
49
|
+
this._fieldsMap.clear();
|
|
50
|
+
}
|
|
51
|
+
addField(field) {
|
|
52
|
+
// Python logic: Auto-switch to RECORD if adding fields
|
|
53
|
+
if (this.kind !== SchemaKind.RECORD) {
|
|
54
|
+
this.kind = SchemaKind.RECORD;
|
|
55
|
+
}
|
|
56
|
+
// Auto-naming if missing
|
|
57
|
+
const fName = field.name || String(this._fieldsList.length);
|
|
58
|
+
field.name = fName;
|
|
59
|
+
this._fieldsList.push(field);
|
|
60
|
+
this._fieldsMap.set(fName, field);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Equivalent to Python's __getitem__.
|
|
64
|
+
* Allows access by numeric index or field name string.
|
|
65
|
+
*/
|
|
66
|
+
getField(key) {
|
|
67
|
+
if (!this.isRecord) {
|
|
68
|
+
throw new Error(`Schema kind ${this.kind} is not subscriptable (not a RECORD).`);
|
|
69
|
+
}
|
|
70
|
+
if (typeof key === 'number') {
|
|
71
|
+
return this._fieldsList[key];
|
|
72
|
+
}
|
|
73
|
+
return this._fieldsMap.get(key);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Replaces an existing field with a new definition based on field.name.
|
|
77
|
+
* Preserves the original order in the fields list.
|
|
78
|
+
* If the field does not exist, it appends it (like addField).
|
|
79
|
+
*/
|
|
80
|
+
replaceField(field) {
|
|
81
|
+
const fName = field.name;
|
|
82
|
+
if (!fName) {
|
|
83
|
+
throw new Error("Cannot replace a field without a name.");
|
|
84
|
+
}
|
|
85
|
+
if (this._fieldsMap.has(fName)) {
|
|
86
|
+
// 1. Retrieve the old object to find its index
|
|
87
|
+
const oldField = this._fieldsMap.get(fName);
|
|
88
|
+
const idx = this._fieldsList.indexOf(oldField);
|
|
89
|
+
if (idx !== -1) {
|
|
90
|
+
// 2. Replace in list (preserve order)
|
|
91
|
+
this._fieldsList[idx] = field;
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
// Fallback safety (should not happen if map/list synced)
|
|
95
|
+
this._fieldsList.push(field);
|
|
96
|
+
}
|
|
97
|
+
// 3. Update map
|
|
98
|
+
this._fieldsMap.set(fName, field);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
// Field doesn't exist, treat as add
|
|
102
|
+
this.addField(field);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// -----------------------------------------------------------
|
|
106
|
+
// Meta Management
|
|
107
|
+
// -----------------------------------------------------------
|
|
108
|
+
clearMeta() {
|
|
109
|
+
this.clearCommonMeta();
|
|
110
|
+
this.required = false;
|
|
111
|
+
}
|
|
112
|
+
applyMeta(info) {
|
|
113
|
+
if (!info)
|
|
114
|
+
return;
|
|
115
|
+
// 1. Apply common stuff (meta dict, comments, tags)
|
|
116
|
+
this.applyCommonMeta(info);
|
|
117
|
+
// 2. Apply Schema-specific constraints
|
|
118
|
+
if (info.required) {
|
|
119
|
+
this.required = true;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// -----------------------------------------------------------
|
|
123
|
+
// Debug / Representation
|
|
124
|
+
// -----------------------------------------------------------
|
|
125
|
+
/**
|
|
126
|
+
* Technical debug representation.
|
|
127
|
+
* Format: <Schema(KIND:type_name) name='...' details...>
|
|
128
|
+
*/
|
|
129
|
+
toString() {
|
|
130
|
+
// 1. Basic Info: Kind and TypeName
|
|
131
|
+
const kindStr = this.kind;
|
|
132
|
+
let typeLabel = "";
|
|
133
|
+
if (this.typeName && this.typeName !== "any" && this.typeName !== this.kind) {
|
|
134
|
+
typeLabel = `:${this.typeName}`;
|
|
135
|
+
}
|
|
136
|
+
const header = `<Schema(${kindStr}${typeLabel})`;
|
|
137
|
+
// 2. Field Name
|
|
138
|
+
const nameStr = this.name ? ` name="${this.name}"` : "";
|
|
139
|
+
// 3. Details
|
|
140
|
+
const details = [];
|
|
141
|
+
if (this.required)
|
|
142
|
+
details.push("!required");
|
|
143
|
+
const attrKeys = Object.keys(this.attr);
|
|
144
|
+
if (attrKeys.length > 0)
|
|
145
|
+
details.push(`attr=[${attrKeys.map(a => '"' + a + '"').join(', ')}]`);
|
|
146
|
+
if (this.tags.length > 0)
|
|
147
|
+
details.push(`tags=[${this.tags.join(', ')}]`);
|
|
148
|
+
if (this.comments.length > 0)
|
|
149
|
+
details.push(`comments=${this.comments.length}`);
|
|
150
|
+
// Structure: Record
|
|
151
|
+
if (this.isRecord) {
|
|
152
|
+
const count = this._fieldsList.length;
|
|
153
|
+
if (count > 0) {
|
|
154
|
+
const limit = 3;
|
|
155
|
+
const fieldNames = this._fieldsList.slice(0, limit).map(f => f.name);
|
|
156
|
+
if (count > limit)
|
|
157
|
+
fieldNames.push("...");
|
|
158
|
+
details.push(`fields(${count})=[${fieldNames.join(', ')}]`);
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
details.push("fields=[]");
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// Structure: List
|
|
165
|
+
else if (this.isList) {
|
|
166
|
+
const elType = this.element ? (this.element.typeName || "None") : "None";
|
|
167
|
+
const elKind = this.element ? this.element.kind : "ANY";
|
|
168
|
+
details.push(`element=${elKind}:${elType}`);
|
|
169
|
+
}
|
|
170
|
+
const detailsStr = details.length > 0 ? " " + details.join(" ") : "";
|
|
171
|
+
return `${header}${nameStr}${detailsStr}>`;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
exports.Schema = Schema;
|
|
175
|
+
//# sourceMappingURL=Schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Schema.js","sourceRoot":"","sources":["../../src/models/Schema.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@arkadia/ai-data-format",
|
|
3
|
+
"version": "0.1.4",
|
|
4
|
+
"description": "Parser and Stringifier for Arkadia AI Data Format (AID)",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"clean": "rimraf dist",
|
|
9
|
+
"build": "npm run clean && tsc",
|
|
10
|
+
"verify": "node scripts/verify-build.js",
|
|
11
|
+
"watch": "tsc -w",
|
|
12
|
+
"prepublishOnly": "npm run build",
|
|
13
|
+
"test": "vitest run",
|
|
14
|
+
"test:watch": "vitest"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"ai",
|
|
18
|
+
"data",
|
|
19
|
+
"format",
|
|
20
|
+
"parser",
|
|
21
|
+
"schema",
|
|
22
|
+
"arkadia"
|
|
23
|
+
],
|
|
24
|
+
"author": "Arkadia AI",
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/node": "^20.19.31",
|
|
28
|
+
"rimraf": "^6.1.2",
|
|
29
|
+
"typescript": "^5.9.3",
|
|
30
|
+
"vitest": "^3.2.4"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
const { execSync } = require('child_process');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
|
|
5
|
+
// Load package.json to get the real package name (e.g., @arkadia/ai-data-format)
|
|
6
|
+
const pkg = require('../package.json');
|
|
7
|
+
const PACKAGE_NAME = pkg.name;
|
|
8
|
+
|
|
9
|
+
// --- CONFIGURATION ---
|
|
10
|
+
const ROOT_DIR = path.resolve(__dirname, '..');
|
|
11
|
+
const TEMP_DIR = path.join(ROOT_DIR, 'temp_smoke_test');
|
|
12
|
+
const DIST_DIR = path.join(ROOT_DIR, 'dist');
|
|
13
|
+
|
|
14
|
+
// Node.js modules we DO NOT want in the browser build
|
|
15
|
+
const FORBIDDEN_IMPORTS = ['util', 'fs', 'path', 'child_process', 'os'];
|
|
16
|
+
|
|
17
|
+
// --- HELPERS ---
|
|
18
|
+
const log = (msg) => console.log(`\x1b[36m[VERIFY]\x1b[0m ${msg}`);
|
|
19
|
+
const success = (msg) => console.log(`\x1b[32m[SUCCESS]\x1b[0m ${msg}`);
|
|
20
|
+
const error = (msg) => console.error(`\x1b[31m[ERROR]\x1b[0m ${msg}`);
|
|
21
|
+
|
|
22
|
+
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
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// --- MAIN PROCESS ---
|
|
51
|
+
|
|
52
|
+
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' });
|
|
90
|
+
|
|
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 = `
|
|
97
|
+
const { decode, encode } = require('${PACKAGE_NAME}');
|
|
98
|
+
|
|
99
|
+
console.log(" 🧪 Running functional tests...");
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
// --- 1. INPUT DATA ---
|
|
103
|
+
const inputData = {
|
|
104
|
+
msg: "Hello World",
|
|
105
|
+
status: "OK",
|
|
106
|
+
count: 123
|
|
107
|
+
};
|
|
108
|
+
console.log("\\n 🔹 [INPUT]:", JSON.stringify(inputData));
|
|
109
|
+
|
|
110
|
+
// --- 2. ENCODE ---
|
|
111
|
+
if (typeof encode !== 'function') {
|
|
112
|
+
throw new Error("Export 'encode' is not a function!");
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const encoded = encode(inputData);
|
|
116
|
+
|
|
117
|
+
if (!encoded) throw new Error("Encode returned empty result");
|
|
118
|
+
|
|
119
|
+
// DISPLAY ENCODE RESULT
|
|
120
|
+
console.log(" 🔸 [ENCODED]:", encoded);
|
|
121
|
+
|
|
122
|
+
// --- 3. DECODE ---
|
|
123
|
+
if (typeof decode !== 'function') {
|
|
124
|
+
throw new Error("Export 'decode' is not a function!");
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const result = decode(encoded);
|
|
128
|
+
|
|
129
|
+
if (!result) throw new Error("Decode returned empty result");
|
|
130
|
+
|
|
131
|
+
// --- 4. EXTRACT DATA FOR VERIFICATION ---
|
|
132
|
+
// We handle two cases:
|
|
133
|
+
// A) decode() returns raw data directly
|
|
134
|
+
// B) decode() returns a result wrapper (e.g. { node: ... })
|
|
135
|
+
|
|
136
|
+
let decodedOutput = result;
|
|
137
|
+
|
|
138
|
+
if (result.node && result.node.fields) {
|
|
139
|
+
// It's likely a Wrapper Object -> Extract values to a simple JS object for comparison
|
|
140
|
+
decodedOutput = {};
|
|
141
|
+
for (const key in result.node.fields) {
|
|
142
|
+
// Assuming field has .value
|
|
143
|
+
decodedOutput[key] = result.node.fields[key].value !== undefined
|
|
144
|
+
? result.node.fields[key].value
|
|
145
|
+
: result.node.fields[key];
|
|
146
|
+
}
|
|
147
|
+
} else if (result.node && result.node.value) {
|
|
148
|
+
decodedOutput = result.node.value;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// DISPLAY DECODE RESULT
|
|
152
|
+
console.log(" 🔹 [DECODED RAW]:", JSON.stringify(result));
|
|
153
|
+
console.log(" 🔹 [DECODED EXTRACTED]:", JSON.stringify(decodedOutput));
|
|
154
|
+
|
|
155
|
+
// --- 5. INTEGRITY CHECK ---
|
|
156
|
+
if (decodedOutput.msg === "Hello World" && decodedOutput.count === 123) {
|
|
157
|
+
console.log("\\n ✅ INTEGRITY CHECK PASSED");
|
|
158
|
+
} else {
|
|
159
|
+
console.log("\\n ⚠️ Integrity check failed or structure mismatch.");
|
|
160
|
+
console.log(" Expected:", JSON.stringify(inputData));
|
|
161
|
+
console.log(" Got:", JSON.stringify(decodedOutput));
|
|
162
|
+
// We don't fail here to allow you to inspect the output,
|
|
163
|
+
// but strictly strictly speaking it should throw.
|
|
164
|
+
// throw new Error("Data mismatch");
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
} catch (e) {
|
|
168
|
+
console.error("\\n ❌ Functional Test Failed:", e.message);
|
|
169
|
+
if (e.stack) console.error(e.stack);
|
|
170
|
+
process.exit(1);
|
|
171
|
+
}
|
|
172
|
+
`;
|
|
173
|
+
|
|
174
|
+
fs.writeFileSync(path.join(TEMP_DIR, 'verify_script.js'), verifyScript);
|
|
175
|
+
|
|
176
|
+
// 8. Run Verification
|
|
177
|
+
log('6. Running functional verification...');
|
|
178
|
+
execSync('node verify_script.js', { cwd: TEMP_DIR, stdio: 'inherit' });
|
|
179
|
+
|
|
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');
|
|
190
|
+
|
|
191
|
+
} catch (e) {
|
|
192
|
+
console.log('\n');
|
|
193
|
+
error('VERIFICATION FAILED!');
|
|
194
|
+
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
|
+
}
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration options for the AI Data Format Encoder.
|
|
3
|
+
*/
|
|
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;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Number of spaces used for indentation.
|
|
14
|
+
* Default: 2
|
|
15
|
+
*/
|
|
16
|
+
indent: number;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Initial indentation offset (level).
|
|
20
|
+
* Default: 0
|
|
21
|
+
*/
|
|
22
|
+
startIndent: number;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Enable compact formatting. Removes unnecessary spaces and newlines.
|
|
26
|
+
* Default: false
|
|
27
|
+
*/
|
|
28
|
+
compact: boolean;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Escape newline characters in strings as literal \n and \r.
|
|
32
|
+
* Default: false
|
|
33
|
+
*/
|
|
34
|
+
escapeNewLines: boolean;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* purely removes new lines from strings.
|
|
38
|
+
* Default: false
|
|
39
|
+
*/
|
|
40
|
+
removeNewLines: boolean;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Enable ANSI colorized output for terminal debugging.
|
|
44
|
+
* Default: false
|
|
45
|
+
*/
|
|
46
|
+
colorize: boolean;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Include comments in the output ).
|
|
50
|
+
* Default: true
|
|
51
|
+
*/
|
|
52
|
+
includeComments: boolean;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Include array size information (e.g. [ $size=5 : ... ]).
|
|
56
|
+
* Default: false
|
|
57
|
+
*/
|
|
58
|
+
includeArraySize: boolean;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Include the schema definition header (e.g. <name: string>).
|
|
62
|
+
* Default: true
|
|
63
|
+
*/
|
|
64
|
+
includeSchema: boolean;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Include metadata attributes and tags ($attr=1 #tag).
|
|
68
|
+
* Default: true
|
|
69
|
+
*/
|
|
70
|
+
includeMeta: boolean;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Include type signature after field names (e.g. name: string vs name).
|
|
74
|
+
* Default: true
|
|
75
|
+
*/
|
|
76
|
+
includeType: boolean;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Default configuration values.
|
|
81
|
+
*/
|
|
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,
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Helper to merge partial user config with defaults.
|
|
99
|
+
*/
|
|
100
|
+
export function resolveConfig(config?: Partial<EncoderConfig>): EncoderConfig {
|
|
101
|
+
return { ...DEFAULT_CONFIG, ...config };
|
|
102
|
+
}
|