@langapi/mcp-server 1.1.1 → 1.2.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/README.md +6 -42
- package/dist/api/client.d.ts +9 -0
- package/dist/api/client.d.ts.map +1 -1
- package/dist/api/client.js +14 -1
- package/dist/api/client.js.map +1 -1
- package/dist/api/types.d.ts +1 -0
- package/dist/api/types.d.ts.map +1 -1
- package/dist/handlers/xcstrings-sync-handler.d.ts +2 -4
- package/dist/handlers/xcstrings-sync-handler.d.ts.map +1 -1
- package/dist/handlers/xcstrings-sync-handler.js +6 -12
- package/dist/handlers/xcstrings-sync-handler.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +0 -2
- package/dist/server.js.map +1 -1
- package/dist/tools/sync-translations.d.ts +30 -1
- package/dist/tools/sync-translations.d.ts.map +1 -1
- package/dist/tools/sync-translations.js +105 -47
- package/dist/tools/sync-translations.js.map +1 -1
- package/dist/utils/format-preserve.d.ts +5 -1
- package/dist/utils/format-preserve.d.ts.map +1 -1
- package/dist/utils/format-preserve.js +109 -4
- package/dist/utils/format-preserve.js.map +1 -1
- package/package.json +1 -1
- package/dist/tools/get-diff.d.ts +0 -23
- package/dist/tools/get-diff.js +0 -88
- package/dist/tools/get-diff.js.map +0 -1
- package/dist/utils/sync-cache.d.ts +0 -40
- package/dist/utils/sync-cache.js +0 -140
- package/dist/utils/sync-cache.js.map +0 -1
- package/dist/utils/sync-cache.test.js +0 -205
- package/dist/utils/sync-cache.test.js.map +0 -1
|
@@ -1,10 +1,39 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Utilities for detecting and preserving JSON file formatting
|
|
3
3
|
*/
|
|
4
|
+
/**
|
|
5
|
+
* Detect if a JSON object uses flat keys (keys containing dots at root level)
|
|
6
|
+
*/
|
|
7
|
+
function detectKeyStructure(data) {
|
|
8
|
+
for (const key of Object.keys(data)) {
|
|
9
|
+
// If any root-level key contains a dot and maps to a non-object value, it's flat
|
|
10
|
+
if (key.includes(".") && typeof data[key] !== "object") {
|
|
11
|
+
return "flat";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return "nested";
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Get all keys from an object recursively (flattened with dot notation)
|
|
18
|
+
*/
|
|
19
|
+
function getAllKeysInOrder(obj, prefix = "") {
|
|
20
|
+
const keys = [];
|
|
21
|
+
for (const key of Object.keys(obj)) {
|
|
22
|
+
const fullKey = prefix ? `${prefix}.${key}` : key;
|
|
23
|
+
const value = obj[key];
|
|
24
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
25
|
+
keys.push(...getAllKeysInOrder(value, fullKey));
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
keys.push(fullKey);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return keys;
|
|
32
|
+
}
|
|
4
33
|
/**
|
|
5
34
|
* Detect the formatting used in a JSON file
|
|
6
35
|
*/
|
|
7
|
-
export function detectJsonFormat(content) {
|
|
36
|
+
export function detectJsonFormat(content, data) {
|
|
8
37
|
const lines = content.split("\n");
|
|
9
38
|
// Detect indent by finding first indented line
|
|
10
39
|
let indent = " "; // default: 2 spaces
|
|
@@ -25,13 +54,89 @@ export function detectJsonFormat(content) {
|
|
|
25
54
|
}
|
|
26
55
|
// Detect trailing newline
|
|
27
56
|
const trailingNewline = content.endsWith("\n");
|
|
28
|
-
|
|
57
|
+
// Detect key structure and order if data is provided
|
|
58
|
+
let keyStructure = "nested";
|
|
59
|
+
let keyOrder;
|
|
60
|
+
if (data) {
|
|
61
|
+
keyStructure = detectKeyStructure(data);
|
|
62
|
+
keyOrder = keyStructure === "flat"
|
|
63
|
+
? Object.keys(data) // For flat files, use root keys directly
|
|
64
|
+
: getAllKeysInOrder(data); // For nested, flatten to get all keys
|
|
65
|
+
}
|
|
66
|
+
return { indent, trailingNewline, keyStructure, keyOrder };
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Reorder object keys to match the specified order
|
|
70
|
+
*/
|
|
71
|
+
function reorderKeys(obj, keyOrder, isFlat) {
|
|
72
|
+
if (isFlat) {
|
|
73
|
+
// For flat structure, just reorder root keys
|
|
74
|
+
const result = {};
|
|
75
|
+
// First add keys in order
|
|
76
|
+
for (const key of keyOrder) {
|
|
77
|
+
if (key in obj) {
|
|
78
|
+
result[key] = obj[key];
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// Then add any new keys not in the original order
|
|
82
|
+
for (const key of Object.keys(obj)) {
|
|
83
|
+
if (!(key in result)) {
|
|
84
|
+
result[key] = obj[key];
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return result;
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
// For nested structure, recursively reorder
|
|
91
|
+
return reorderNestedKeys(obj, keyOrder);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Recursively reorder nested object keys based on flattened key order
|
|
96
|
+
*/
|
|
97
|
+
function reorderNestedKeys(obj, flatKeyOrder) {
|
|
98
|
+
// Build a map of prefix -> order index (use first occurrence)
|
|
99
|
+
const prefixOrder = new Map();
|
|
100
|
+
for (let i = 0; i < flatKeyOrder.length; i++) {
|
|
101
|
+
const key = flatKeyOrder[i];
|
|
102
|
+
const parts = key.split(".");
|
|
103
|
+
// Add all prefixes to maintain hierarchy order
|
|
104
|
+
for (let j = 1; j <= parts.length; j++) {
|
|
105
|
+
const prefix = parts.slice(0, j).join(".");
|
|
106
|
+
if (!prefixOrder.has(prefix)) {
|
|
107
|
+
prefixOrder.set(prefix, i);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Sort root keys by their order in the flattened key list
|
|
112
|
+
const sortedKeys = Object.keys(obj).sort((a, b) => {
|
|
113
|
+
const orderA = prefixOrder.get(a) ?? Infinity;
|
|
114
|
+
const orderB = prefixOrder.get(b) ?? Infinity;
|
|
115
|
+
return orderA - orderB;
|
|
116
|
+
});
|
|
117
|
+
const result = {};
|
|
118
|
+
for (const key of sortedKeys) {
|
|
119
|
+
const value = obj[key];
|
|
120
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
121
|
+
// Recursively reorder nested objects
|
|
122
|
+
result[key] = reorderNestedKeys(value, flatKeyOrder.map((k) => k.startsWith(key + ".") ? k.slice(key.length + 1) : k));
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
result[key] = value;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return result;
|
|
29
129
|
}
|
|
30
130
|
/**
|
|
31
131
|
* Stringify a JSON object with specific formatting
|
|
32
132
|
*/
|
|
33
133
|
export function stringifyWithFormat(obj, format) {
|
|
34
|
-
let
|
|
134
|
+
let objToStringify = obj;
|
|
135
|
+
// Reorder keys if keyOrder is provided
|
|
136
|
+
if (format.keyOrder && typeof obj === "object" && obj !== null && !Array.isArray(obj)) {
|
|
137
|
+
objToStringify = reorderKeys(obj, format.keyOrder, format.keyStructure === "flat");
|
|
138
|
+
}
|
|
139
|
+
let result = JSON.stringify(objToStringify, null, format.indent);
|
|
35
140
|
if (format.trailingNewline && !result.endsWith("\n")) {
|
|
36
141
|
result += "\n";
|
|
37
142
|
}
|
|
@@ -46,7 +151,7 @@ export function parseJsonWithFormat(content) {
|
|
|
46
151
|
if (typeof data !== "object" || data === null || Array.isArray(data)) {
|
|
47
152
|
return null;
|
|
48
153
|
}
|
|
49
|
-
const format = detectJsonFormat(content);
|
|
154
|
+
const format = detectJsonFormat(content, data);
|
|
50
155
|
return { data: data, format };
|
|
51
156
|
}
|
|
52
157
|
catch {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format-preserve.js","sourceRoot":"","sources":["../../src/utils/format-preserve.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"format-preserve.js","sourceRoot":"","sources":["../../src/utils/format-preserve.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/dist/tools/get-diff.d.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* get_diff MCP Tool
|
|
3
|
-
* Compare source locale against sync cache to identify new/changed/removed keys
|
|
4
|
-
*/
|
|
5
|
-
import { z } from "zod";
|
|
6
|
-
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
7
|
-
declare const GetDiffSchema: z.ZodObject<{
|
|
8
|
-
source_lang: z.ZodString;
|
|
9
|
-
project_path: z.ZodOptional<z.ZodString>;
|
|
10
|
-
}, "strip", z.ZodTypeAny, {
|
|
11
|
-
source_lang: string;
|
|
12
|
-
project_path?: string | undefined;
|
|
13
|
-
}, {
|
|
14
|
-
source_lang: string;
|
|
15
|
-
project_path?: string | undefined;
|
|
16
|
-
}>;
|
|
17
|
-
export type GetDiffInput = z.infer<typeof GetDiffSchema>;
|
|
18
|
-
/**
|
|
19
|
-
* Register the get_diff tool with the MCP server
|
|
20
|
-
*/
|
|
21
|
-
export declare function registerGetDiff(server: McpServer): void;
|
|
22
|
-
export {};
|
|
23
|
-
//# sourceMappingURL=get-diff.d.ts.map
|
package/dist/tools/get-diff.js
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* get_diff MCP Tool
|
|
3
|
-
* Compare source locale against sync cache to identify new/changed/removed keys
|
|
4
|
-
*/
|
|
5
|
-
import { z } from "zod";
|
|
6
|
-
import { readFile } from "fs/promises";
|
|
7
|
-
import { detectLocales } from "../locale-detection/index.js";
|
|
8
|
-
import { flattenJson, parseJsonSafe } from "../utils/json-parser.js";
|
|
9
|
-
import { languageCodeSchema } from "../utils/validation.js";
|
|
10
|
-
import { readSyncCache, getFullDiff } from "../utils/sync-cache.js";
|
|
11
|
-
// Input schema
|
|
12
|
-
const GetDiffSchema = z.object({
|
|
13
|
-
source_lang: languageCodeSchema.describe("Source language code (e.g., 'en', 'pt-BR')"),
|
|
14
|
-
project_path: z
|
|
15
|
-
.string()
|
|
16
|
-
.optional()
|
|
17
|
-
.describe("Root path of the project. Defaults to current working directory."),
|
|
18
|
-
});
|
|
19
|
-
/**
|
|
20
|
-
* Register the get_diff tool with the MCP server
|
|
21
|
-
*/
|
|
22
|
-
export function registerGetDiff(server) {
|
|
23
|
-
server.tool("get_diff", "Compare current source locale content against the sync cache to see what's new, changed, unchanged, or removed since the last sync.", GetDiffSchema.shape, async (args) => {
|
|
24
|
-
const input = GetDiffSchema.parse(args);
|
|
25
|
-
const projectPath = input.project_path || process.cwd();
|
|
26
|
-
// Detect locales
|
|
27
|
-
const detection = await detectLocales(projectPath, false);
|
|
28
|
-
// Find source locale
|
|
29
|
-
const sourceLocale = detection.locales.find((l) => l.lang === input.source_lang);
|
|
30
|
-
if (!sourceLocale) {
|
|
31
|
-
const output = {
|
|
32
|
-
success: false,
|
|
33
|
-
error: {
|
|
34
|
-
code: "SOURCE_NOT_FOUND",
|
|
35
|
-
message: `Source language '${input.source_lang}' not found in project`,
|
|
36
|
-
},
|
|
37
|
-
};
|
|
38
|
-
return {
|
|
39
|
-
content: [{ type: "text", text: JSON.stringify(output, null, 2) }],
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
// Read and parse source files
|
|
43
|
-
const sourceContent = {};
|
|
44
|
-
for (const file of sourceLocale.files) {
|
|
45
|
-
const content = await readFile(file.path, "utf-8");
|
|
46
|
-
const parsed = parseJsonSafe(content);
|
|
47
|
-
if (parsed) {
|
|
48
|
-
Object.assign(sourceContent, parsed);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
// Flatten source content
|
|
52
|
-
const flatContent = flattenJson(sourceContent);
|
|
53
|
-
// Read cache
|
|
54
|
-
const cachedContent = await readSyncCache(projectPath, input.source_lang);
|
|
55
|
-
// Get full diff
|
|
56
|
-
const diff = getFullDiff(flatContent, cachedContent);
|
|
57
|
-
const totalCached = cachedContent ? Object.keys(cachedContent).length : 0;
|
|
58
|
-
const output = {
|
|
59
|
-
success: true,
|
|
60
|
-
cache_exists: cachedContent !== null,
|
|
61
|
-
diff: {
|
|
62
|
-
new_keys: diff.newKeys,
|
|
63
|
-
changed_keys: diff.changedKeys.map((c) => ({
|
|
64
|
-
key: c.key,
|
|
65
|
-
old_value: c.oldValue,
|
|
66
|
-
new_value: c.newValue,
|
|
67
|
-
})),
|
|
68
|
-
unchanged_keys: diff.unchangedKeys,
|
|
69
|
-
removed_keys: diff.removedKeys,
|
|
70
|
-
},
|
|
71
|
-
summary: {
|
|
72
|
-
total_current: flatContent.length,
|
|
73
|
-
total_cached: totalCached,
|
|
74
|
-
new_count: diff.newKeys.length,
|
|
75
|
-
changed_count: diff.changedKeys.length,
|
|
76
|
-
unchanged_count: diff.unchangedKeys.length,
|
|
77
|
-
removed_count: diff.removedKeys.length,
|
|
78
|
-
},
|
|
79
|
-
message: cachedContent
|
|
80
|
-
? `Found ${diff.newKeys.length} new, ${diff.changedKeys.length} changed, ${diff.unchangedKeys.length} unchanged, ${diff.removedKeys.length} removed keys.`
|
|
81
|
-
: `No sync cache found. All ${flatContent.length} keys will be treated as new on first sync.`,
|
|
82
|
-
};
|
|
83
|
-
return {
|
|
84
|
-
content: [{ type: "text", text: JSON.stringify(output, null, 2) }],
|
|
85
|
-
};
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
//# sourceMappingURL=get-diff.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"get-diff.js","sourceRoot":"","sources":["../../src/tools/get-diff.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sync cache utility for delta detection
|
|
3
|
-
* Stores previous source content to detect new/changed keys
|
|
4
|
-
*/
|
|
5
|
-
import type { KeyValue } from "../api/types.js";
|
|
6
|
-
interface SyncDelta {
|
|
7
|
-
newKeys: string[];
|
|
8
|
-
changedKeys: string[];
|
|
9
|
-
unchangedKeys: string[];
|
|
10
|
-
contentToSync: KeyValue[];
|
|
11
|
-
}
|
|
12
|
-
export interface KeyChange {
|
|
13
|
-
key: string;
|
|
14
|
-
oldValue: string;
|
|
15
|
-
newValue: string;
|
|
16
|
-
}
|
|
17
|
-
export interface FullDiff {
|
|
18
|
-
newKeys: string[];
|
|
19
|
-
changedKeys: KeyChange[];
|
|
20
|
-
unchangedKeys: string[];
|
|
21
|
-
removedKeys: string[];
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Read the sync cache for a project
|
|
25
|
-
*/
|
|
26
|
-
export declare function readSyncCache(projectPath: string, sourceLang: string): Promise<Record<string, string> | null>;
|
|
27
|
-
/**
|
|
28
|
-
* Write the sync cache after a successful sync
|
|
29
|
-
*/
|
|
30
|
-
export declare function writeSyncCache(projectPath: string, sourceLang: string, content: KeyValue[]): Promise<void>;
|
|
31
|
-
/**
|
|
32
|
-
* Detect delta between current content and cached content
|
|
33
|
-
*/
|
|
34
|
-
export declare function detectLocalDelta(currentContent: KeyValue[], cachedContent: Record<string, string> | null): SyncDelta;
|
|
35
|
-
/**
|
|
36
|
-
* Get full diff including removed keys
|
|
37
|
-
*/
|
|
38
|
-
export declare function getFullDiff(currentContent: KeyValue[], cachedContent: Record<string, string> | null): FullDiff;
|
|
39
|
-
export {};
|
|
40
|
-
//# sourceMappingURL=sync-cache.d.ts.map
|
package/dist/utils/sync-cache.js
DELETED
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sync cache utility for delta detection
|
|
3
|
-
* Stores previous source content to detect new/changed keys
|
|
4
|
-
*/
|
|
5
|
-
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
6
|
-
import { join, dirname } from "path";
|
|
7
|
-
const CACHE_DIR = ".langapi";
|
|
8
|
-
const CACHE_FILE = "sync-cache.json";
|
|
9
|
-
function getCachePath(projectPath) {
|
|
10
|
-
return join(projectPath, CACHE_DIR, CACHE_FILE);
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* Read the sync cache for a project
|
|
14
|
-
*/
|
|
15
|
-
export async function readSyncCache(projectPath, sourceLang) {
|
|
16
|
-
const cachePath = getCachePath(projectPath);
|
|
17
|
-
try {
|
|
18
|
-
const content = await readFile(cachePath, "utf-8");
|
|
19
|
-
const cache = JSON.parse(content);
|
|
20
|
-
// Only return cache if source language matches
|
|
21
|
-
if (cache.sourceLang === sourceLang) {
|
|
22
|
-
return cache.content;
|
|
23
|
-
}
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
|
-
catch {
|
|
27
|
-
// Cache doesn't exist or is invalid
|
|
28
|
-
return null;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Write the sync cache after a successful sync
|
|
33
|
-
*/
|
|
34
|
-
export async function writeSyncCache(projectPath, sourceLang, content) {
|
|
35
|
-
const cachePath = getCachePath(projectPath);
|
|
36
|
-
// Ensure cache directory exists
|
|
37
|
-
await mkdir(dirname(cachePath), { recursive: true });
|
|
38
|
-
// Convert KeyValue array to map
|
|
39
|
-
const contentMap = {};
|
|
40
|
-
for (const item of content) {
|
|
41
|
-
contentMap[item.key] = item.value;
|
|
42
|
-
}
|
|
43
|
-
const cache = {
|
|
44
|
-
sourceLang,
|
|
45
|
-
content: contentMap,
|
|
46
|
-
lastSync: new Date().toISOString(),
|
|
47
|
-
};
|
|
48
|
-
await writeFile(cachePath, JSON.stringify(cache, null, 2), "utf-8");
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Detect delta between current content and cached content
|
|
52
|
-
*/
|
|
53
|
-
export function detectLocalDelta(currentContent, cachedContent) {
|
|
54
|
-
const newKeys = [];
|
|
55
|
-
const changedKeys = [];
|
|
56
|
-
const unchangedKeys = [];
|
|
57
|
-
const contentToSync = [];
|
|
58
|
-
// If no cache, all keys are new
|
|
59
|
-
if (!cachedContent) {
|
|
60
|
-
return {
|
|
61
|
-
newKeys: currentContent.map((c) => c.key),
|
|
62
|
-
changedKeys: [],
|
|
63
|
-
unchangedKeys: [],
|
|
64
|
-
contentToSync: currentContent,
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
for (const item of currentContent) {
|
|
68
|
-
const cachedValue = cachedContent[item.key];
|
|
69
|
-
if (cachedValue === undefined) {
|
|
70
|
-
// Key doesn't exist in cache - it's new
|
|
71
|
-
newKeys.push(item.key);
|
|
72
|
-
contentToSync.push(item);
|
|
73
|
-
}
|
|
74
|
-
else if (cachedValue !== item.value) {
|
|
75
|
-
// Key exists but value changed
|
|
76
|
-
changedKeys.push(item.key);
|
|
77
|
-
contentToSync.push(item);
|
|
78
|
-
}
|
|
79
|
-
else {
|
|
80
|
-
// Key exists and value is the same - unchanged
|
|
81
|
-
unchangedKeys.push(item.key);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
return {
|
|
85
|
-
newKeys,
|
|
86
|
-
changedKeys,
|
|
87
|
-
unchangedKeys,
|
|
88
|
-
contentToSync,
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Get full diff including removed keys
|
|
93
|
-
*/
|
|
94
|
-
export function getFullDiff(currentContent, cachedContent) {
|
|
95
|
-
const newKeys = [];
|
|
96
|
-
const changedKeys = [];
|
|
97
|
-
const unchangedKeys = [];
|
|
98
|
-
const removedKeys = [];
|
|
99
|
-
// If no cache, all keys are new
|
|
100
|
-
if (!cachedContent) {
|
|
101
|
-
return {
|
|
102
|
-
newKeys: currentContent.map((c) => c.key),
|
|
103
|
-
changedKeys: [],
|
|
104
|
-
unchangedKeys: [],
|
|
105
|
-
removedKeys: [],
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
// Track which cached keys we've seen
|
|
109
|
-
const seenCachedKeys = new Set();
|
|
110
|
-
for (const item of currentContent) {
|
|
111
|
-
const cachedValue = cachedContent[item.key];
|
|
112
|
-
seenCachedKeys.add(item.key);
|
|
113
|
-
if (cachedValue === undefined) {
|
|
114
|
-
newKeys.push(item.key);
|
|
115
|
-
}
|
|
116
|
-
else if (cachedValue !== item.value) {
|
|
117
|
-
changedKeys.push({
|
|
118
|
-
key: item.key,
|
|
119
|
-
oldValue: cachedValue,
|
|
120
|
-
newValue: item.value,
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
unchangedKeys.push(item.key);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
// Find removed keys (in cache but not in current)
|
|
128
|
-
for (const key of Object.keys(cachedContent)) {
|
|
129
|
-
if (!seenCachedKeys.has(key)) {
|
|
130
|
-
removedKeys.push(key);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
return {
|
|
134
|
-
newKeys,
|
|
135
|
-
changedKeys,
|
|
136
|
-
unchangedKeys,
|
|
137
|
-
removedKeys,
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
//# sourceMappingURL=sync-cache.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sync-cache.js","sourceRoot":"","sources":["../../src/utils/sync-cache.ts"],"names":[],"mappings":"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"}
|