@aikdna/kdna-cli 0.20.3 → 0.21.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.
- package/package.json +1 -1
- package/src/cmds/domain.js +19 -3
- package/src/package-store.js +3 -47
- package/src/verify.js +16 -72
package/package.json
CHANGED
package/src/cmds/domain.js
CHANGED
|
@@ -493,7 +493,11 @@ function inspectKdnaFile(filePath, jsonMode = false) {
|
|
|
493
493
|
const isZip = head[0] === 0x50 && head[1] === 0x4b;
|
|
494
494
|
if (!isZip) error('Invalid .kdna asset: expected ZIP container');
|
|
495
495
|
|
|
496
|
-
const {
|
|
496
|
+
const {
|
|
497
|
+
listContainerEntries,
|
|
498
|
+
readContainerJson,
|
|
499
|
+
readContainerDataMap,
|
|
500
|
+
} = require('../package-store');
|
|
497
501
|
const { licenseDecryptOptionsForManifest } = require('./license');
|
|
498
502
|
const presentFiles = listContainerEntries(abs).filter(
|
|
499
503
|
(f) => (f.startsWith('KDNA_') && f.endsWith('.json')) || f === 'README.md' || f === 'LICENSE',
|
|
@@ -513,8 +517,20 @@ function inspectKdnaFile(filePath, jsonMode = false) {
|
|
|
513
517
|
let core = null;
|
|
514
518
|
let patterns = null;
|
|
515
519
|
try {
|
|
516
|
-
|
|
517
|
-
|
|
520
|
+
if (decryptError) {
|
|
521
|
+
/* skip */
|
|
522
|
+
}
|
|
523
|
+
// v2 container: use readDataMap
|
|
524
|
+
else if (listContainerEntries(abs).includes('payload.kdnab')) {
|
|
525
|
+
const dm = readContainerDataMap(abs, decryptOptions);
|
|
526
|
+
core = dm['KDNA_Core.json'] || null;
|
|
527
|
+
patterns = dm['KDNA_Patterns.json'] || null;
|
|
528
|
+
}
|
|
529
|
+
// v1 container: read individual files
|
|
530
|
+
else {
|
|
531
|
+
core = readContainerJson(abs, 'KDNA_Core.json', decryptOptions);
|
|
532
|
+
patterns = readContainerJson(abs, 'KDNA_Patterns.json', decryptOptions);
|
|
533
|
+
}
|
|
518
534
|
} catch (e) {
|
|
519
535
|
if (!encryptedEntries.length) error(`Cannot inspect .kdna asset: ${e.message}`);
|
|
520
536
|
decryptError = e.message;
|
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
|
@@ -109,87 +109,31 @@ function directoryView(root) {
|
|
|
109
109
|
|
|
110
110
|
function assetView(kdnaPath, options = {}) {
|
|
111
111
|
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
|
|
112
|
+
let dataMap = null;
|
|
113
|
+
const _ensureDataMap = () => {
|
|
114
|
+
if (!dataMap) dataMap = readContainerDataMap(kdnaPath, options);
|
|
115
|
+
return dataMap;
|
|
116
|
+
};
|
|
117
|
+
const allEntries = new Set(entries);
|
|
118
|
+
allEntries.add('KDNA_Core.json');
|
|
119
|
+
allEntries.add('KDNA_Patterns.json');
|
|
167
120
|
return {
|
|
168
|
-
kind: 'asset',
|
|
169
|
-
|
|
170
|
-
exists(name) {
|
|
171
|
-
return entries.has(name);
|
|
172
|
-
},
|
|
121
|
+
kind: 'asset', path: kdnaPath,
|
|
122
|
+
exists(name) { return allEntries.has(name) || entries.has(name); },
|
|
173
123
|
readJson(name) {
|
|
174
|
-
return readContainerJson(kdnaPath, name, options);
|
|
124
|
+
if (entries.has(name)) return readContainerJson(kdnaPath, name, options);
|
|
125
|
+
return _ensureDataMap()[name] || null;
|
|
175
126
|
},
|
|
176
127
|
readText(name) {
|
|
177
|
-
if (
|
|
178
|
-
|
|
128
|
+
if (entries.has(name)) return readContainerEntry(kdnaPath, name).toString('utf8');
|
|
129
|
+
const dm = _ensureDataMap();
|
|
130
|
+
return dm[name] ? JSON.stringify(dm[name]) : '';
|
|
179
131
|
},
|
|
180
132
|
listDirFiles(dirName) {
|
|
181
|
-
const
|
|
182
|
-
const files = [];
|
|
183
|
-
for (const entryName of entries) {
|
|
184
|
-
if (!entryName.startsWith(prefix)) continue;
|
|
185
|
-
const rest = entryName.slice(prefix.length);
|
|
186
|
-
if (rest && !rest.includes('/')) files.push(rest);
|
|
187
|
-
}
|
|
188
|
-
return files;
|
|
133
|
+
return [...entries].filter(e => e.startsWith(dirName.replace(//+$/,'')+'/')).map(e => { const r = e.slice(dirName.length+1); return r.includes('/') ? null : r; }).filter(Boolean);
|
|
189
134
|
},
|
|
190
135
|
};
|
|
191
136
|
}
|
|
192
|
-
|
|
193
137
|
function asView(input, options = {}) {
|
|
194
138
|
if (input && typeof input.exists === 'function') return input;
|
|
195
139
|
return directoryView(input, options);
|