@aikdna/kdna-cli 0.20.4 → 0.21.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/package-store.js +3 -47
- package/src/verify.js +27 -69
package/package.json
CHANGED
package/src/package-store.js
CHANGED
|
@@ -11,25 +11,6 @@ if (typeof core.createKdnaAssetReader !== 'function') {
|
|
|
11
11
|
|
|
12
12
|
const assetReader = core.createKdnaAssetReader();
|
|
13
13
|
|
|
14
|
-
const V1_ENTRIES = [
|
|
15
|
-
'KDNA_Core.json',
|
|
16
|
-
'KDNA_Patterns.json',
|
|
17
|
-
'KDNA_Scenarios.json',
|
|
18
|
-
'KDNA_Cases.json',
|
|
19
|
-
'KDNA_Reasoning.json',
|
|
20
|
-
'KDNA_Evolution.json',
|
|
21
|
-
];
|
|
22
|
-
|
|
23
|
-
function validateContainerV2(asset, assetPath) {
|
|
24
|
-
const hasPayload = asset.entries.has('payload.kdnab');
|
|
25
|
-
if (hasPayload) return; // v2, OK
|
|
26
|
-
const hasV1 = V1_ENTRIES.some((e) => asset.entries.has(e));
|
|
27
|
-
if (!hasV1) return; // neither v1 nor v2, probably empty — let caller decide
|
|
28
|
-
const found = V1_ENTRIES.filter((e) => asset.entries.has(e));
|
|
29
|
-
const msg = `ERR_LEGACY_PLAINTEXT_CONTAINER: This .kdna uses the removed v1 plaintext ZIP format (found: ${found.join(', ')}). Rebuild from source with KDNA Container v2.`;
|
|
30
|
-
throw Object.assign(new Error(msg), { code: 'ERR_LEGACY_PLAINTEXT_CONTAINER' });
|
|
31
|
-
}
|
|
32
|
-
|
|
33
14
|
const INDEX_VERSION = 2;
|
|
34
15
|
|
|
35
16
|
function ensureDir(dir) {
|
|
@@ -87,33 +68,9 @@ function readContainerJson(kdnaPath, fileName, options = {}) {
|
|
|
87
68
|
|
|
88
69
|
function readContainerDataMap(kdnaPath, options = {}) {
|
|
89
70
|
const asset = assetReader.openSync(kdnaPath);
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if (asset.entries.has('kdna.json')) {
|
|
94
|
-
dataMap['kdna.json'] = assetReader.readJsonSync(asset, 'kdna.json', options);
|
|
95
|
-
}
|
|
96
|
-
return dataMap;
|
|
97
|
-
}
|
|
98
|
-
// v1 fallback: read individual JSON files
|
|
99
|
-
const dataMap = {};
|
|
100
|
-
const v1Files = [
|
|
101
|
-
'kdna.json',
|
|
102
|
-
'KDNA_Core.json',
|
|
103
|
-
'KDNA_Patterns.json',
|
|
104
|
-
'KDNA_Scenarios.json',
|
|
105
|
-
'KDNA_Cases.json',
|
|
106
|
-
'KDNA_Reasoning.json',
|
|
107
|
-
'KDNA_Evolution.json',
|
|
108
|
-
];
|
|
109
|
-
for (const f of v1Files) {
|
|
110
|
-
if (asset.entries.has(f)) {
|
|
111
|
-
try {
|
|
112
|
-
dataMap[f] = assetReader.readJsonSync(asset, f, options);
|
|
113
|
-
} catch {
|
|
114
|
-
/* skip */
|
|
115
|
-
}
|
|
116
|
-
}
|
|
71
|
+
const dataMap = assetReader.readDataMapSync(asset, undefined, options);
|
|
72
|
+
if (asset.entries.has('kdna.json')) {
|
|
73
|
+
dataMap['kdna.json'] = assetReader.readJsonSync(asset, 'kdna.json', options);
|
|
117
74
|
}
|
|
118
75
|
return dataMap;
|
|
119
76
|
}
|
|
@@ -130,7 +87,6 @@ function listContainerEntries(kdnaPath) {
|
|
|
130
87
|
|
|
131
88
|
function readContainer(kdnaPath, options = {}) {
|
|
132
89
|
const asset = assetReader.openSync(kdnaPath);
|
|
133
|
-
validateContainerV2(asset, kdnaPath);
|
|
134
90
|
const dataMap = assetReader.readDataMapSync(asset, undefined, options);
|
|
135
91
|
return {
|
|
136
92
|
manifest: dataMap['kdna.json'] || {},
|
package/src/verify.js
CHANGED
|
@@ -62,7 +62,11 @@ function validateManifestFn(manifest) {
|
|
|
62
62
|
if (manifest.format && manifest.format !== 'kdna') {
|
|
63
63
|
errors.push(`kdna.json.format: invalid value "${manifest.format}". Expected "kdna".`);
|
|
64
64
|
}
|
|
65
|
-
if (
|
|
65
|
+
if (
|
|
66
|
+
manifest.format_version &&
|
|
67
|
+
manifest.format_version !== '1.0' &&
|
|
68
|
+
manifest.format_version !== '2.0'
|
|
69
|
+
) {
|
|
66
70
|
errors.push(
|
|
67
71
|
`kdna.json.format_version: invalid value "${manifest.format_version}". Expected "1.0" or "2.0".`,
|
|
68
72
|
);
|
|
@@ -109,87 +113,41 @@ function directoryView(root) {
|
|
|
109
113
|
|
|
110
114
|
function assetView(kdnaPath, options = {}) {
|
|
111
115
|
const entries = new Set(listContainerEntries(kdnaPath));
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
const v2Entries = new Set(entries);
|
|
122
|
-
v2Entries.add('KDNA_Core.json');
|
|
123
|
-
v2Entries.add('KDNA_Patterns.json');
|
|
124
|
-
if (dataMap) {
|
|
125
|
-
for (const k of [
|
|
126
|
-
'KDNA_Scenarios.json',
|
|
127
|
-
'KDNA_Cases.json',
|
|
128
|
-
'KDNA_Reasoning.json',
|
|
129
|
-
'KDNA_Evolution.json',
|
|
130
|
-
]) {
|
|
131
|
-
if (dataMap[k]) v2Entries.add(k);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
return {
|
|
136
|
-
kind: 'asset',
|
|
137
|
-
path: kdnaPath,
|
|
138
|
-
exists(name) {
|
|
139
|
-
if (v2Entries.has(name)) return true;
|
|
140
|
-
return entries.has(name);
|
|
141
|
-
},
|
|
142
|
-
readJson(name) {
|
|
143
|
-
if (entries.has(name)) return readContainerJson(kdnaPath, name, options);
|
|
144
|
-
const dm = _ensureDataMap();
|
|
145
|
-
return dm[name] || null;
|
|
146
|
-
},
|
|
147
|
-
readText(name) {
|
|
148
|
-
if (entries.has(name)) return readContainerEntry(kdnaPath, name).toString('utf8');
|
|
149
|
-
const dm = _ensureDataMap();
|
|
150
|
-
return dm[name] ? JSON.stringify(dm[name]) : '';
|
|
151
|
-
},
|
|
152
|
-
listDirFiles(dirName) {
|
|
153
|
-
const prefix = `${dirName.replace(/\/+$/, '')}/`;
|
|
154
|
-
const files = [];
|
|
155
|
-
for (const e of entries) {
|
|
156
|
-
if (e.startsWith(prefix)) {
|
|
157
|
-
const rest = e.slice(prefix.length);
|
|
158
|
-
if (rest && !rest.includes('/')) files.push(rest);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
return files;
|
|
162
|
-
},
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// v1 container: standard ZIP entry view
|
|
116
|
+
let dataMap = null;
|
|
117
|
+
const _ensureDataMap = () => {
|
|
118
|
+
if (!dataMap) dataMap = readContainerDataMap(kdnaPath, options);
|
|
119
|
+
return dataMap;
|
|
120
|
+
};
|
|
121
|
+
const allEntries = new Set(entries);
|
|
122
|
+
allEntries.add('KDNA_Core.json');
|
|
123
|
+
allEntries.add('KDNA_Patterns.json');
|
|
167
124
|
return {
|
|
168
125
|
kind: 'asset',
|
|
169
126
|
path: kdnaPath,
|
|
170
127
|
exists(name) {
|
|
171
|
-
return entries.has(name);
|
|
128
|
+
return allEntries.has(name) || entries.has(name);
|
|
172
129
|
},
|
|
173
130
|
readJson(name) {
|
|
174
|
-
return readContainerJson(kdnaPath, name, options);
|
|
131
|
+
if (entries.has(name)) return readContainerJson(kdnaPath, name, options);
|
|
132
|
+
return _ensureDataMap()[name] || null;
|
|
175
133
|
},
|
|
176
134
|
readText(name) {
|
|
177
|
-
if (
|
|
178
|
-
|
|
135
|
+
if (entries.has(name)) return readContainerEntry(kdnaPath, name).toString('utf8');
|
|
136
|
+
const dm = _ensureDataMap();
|
|
137
|
+
return dm[name] ? JSON.stringify(dm[name]) : '';
|
|
179
138
|
},
|
|
180
139
|
listDirFiles(dirName) {
|
|
181
|
-
const prefix =
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
140
|
+
const prefix = dirName.replace(/\/+$/, '') + '/';
|
|
141
|
+
return [...entries]
|
|
142
|
+
.filter((e) => e.startsWith(prefix))
|
|
143
|
+
.map((e) => {
|
|
144
|
+
const r = e.slice(prefix.length);
|
|
145
|
+
return r.includes('/') ? null : r;
|
|
146
|
+
})
|
|
147
|
+
.filter(Boolean);
|
|
189
148
|
},
|
|
190
149
|
};
|
|
191
150
|
}
|
|
192
|
-
|
|
193
151
|
function asView(input, options = {}) {
|
|
194
152
|
if (input && typeof input.exists === 'function') return input;
|
|
195
153
|
return directoryView(input, options);
|