@remnic/import-supermemory 0.1.1 → 9.3.515
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 +94 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +39 -12
- package/dist/index.js.map +1 -1
- package/package.json +6 -5
package/README.md
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# @remnic/import-supermemory
|
|
2
|
+
|
|
3
|
+
Import a Supermemory JSON export into Remnic.
|
|
4
|
+
|
|
5
|
+
This package is an optional companion for `@remnic/cli`. Install it only when
|
|
6
|
+
you want to migrate memories out of Supermemory and into Remnic's local memory
|
|
7
|
+
store.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install -g @remnic/cli
|
|
13
|
+
npm install -g @remnic/import-supermemory
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
If you use Remnic from a project instead of globally, add both packages to the
|
|
17
|
+
same project:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pnpm add @remnic/cli @remnic/import-supermemory
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Export From Supermemory
|
|
24
|
+
|
|
25
|
+
Export or collect your Supermemory memories as JSON. The importer accepts:
|
|
26
|
+
|
|
27
|
+
- A flat JSON array of memory objects.
|
|
28
|
+
- An object with one of these array keys: `memoryEntries`, `memories`,
|
|
29
|
+
`results`, or `data`.
|
|
30
|
+
|
|
31
|
+
Each memory can provide content in `content`, `memory`, `summary`, or `title`.
|
|
32
|
+
Remnic keeps Supermemory IDs, timestamps, container tags, source metadata, and
|
|
33
|
+
the source file path when they are present.
|
|
34
|
+
|
|
35
|
+
If your Supermemory export is paginated, combine the pages into one flat array
|
|
36
|
+
or into an object like this:
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"memories": [
|
|
41
|
+
{
|
|
42
|
+
"id": "mem_123",
|
|
43
|
+
"content": "The user prefers short release notes.",
|
|
44
|
+
"updatedAt": "2026-05-05T12:00:00Z",
|
|
45
|
+
"containerTags": ["product"]
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Dry Run First
|
|
52
|
+
|
|
53
|
+
Run a dry run before writing anything:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
remnic import --adapter supermemory --file ./supermemory-memories.json --dry-run
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
When the count and warnings look right, run the import:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
remnic import --adapter supermemory --file ./supermemory-memories.json
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
The importer writes records with `sourceLabel: "supermemory"` and
|
|
66
|
+
`metadata.kind: "supermemory_memory"` so you can audit where imported memories
|
|
67
|
+
came from later.
|
|
68
|
+
|
|
69
|
+
## Privacy
|
|
70
|
+
|
|
71
|
+
Parsing and writing run locally. If your Remnic extraction or consolidation
|
|
72
|
+
pipeline is configured to use a remote model provider, imported content may be
|
|
73
|
+
sent to that provider during normal Remnic processing. Use local model routing
|
|
74
|
+
or gateway settings if you need the full migration path to stay local.
|
|
75
|
+
|
|
76
|
+
## API
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
import { adapter, supermemoryAdapter } from "@remnic/import-supermemory";
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Both exports expose the same Remnic importer adapter:
|
|
83
|
+
|
|
84
|
+
- `name: "supermemory"`
|
|
85
|
+
- `sourceLabel: "supermemory"`
|
|
86
|
+
- `parse(input, options)`
|
|
87
|
+
- `transform(parsed)`
|
|
88
|
+
- `writeTo(target, memories)`
|
|
89
|
+
|
|
90
|
+
## More Documentation
|
|
91
|
+
|
|
92
|
+
- Remnic importer docs: https://github.com/joshuaswarren/remnic/blob/main/docs/importers.md
|
|
93
|
+
- Supermemory migration guide: https://remnic.ai/guides/import-supermemory/
|
|
94
|
+
- Package source: https://github.com/joshuaswarren/remnic/tree/main/packages/import-supermemory
|
package/dist/index.d.ts
CHANGED
|
@@ -21,6 +21,10 @@ declare function parseSupermemoryExport(input: unknown, filePath?: string): Pars
|
|
|
21
21
|
declare const adapter: ImporterAdapter<ParsedSupermemoryExport>;
|
|
22
22
|
declare const supermemoryAdapter: ImporterAdapter<ParsedSupermemoryExport>;
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
interface SupermemoryTransformOptions {
|
|
25
|
+
/** Optional cap on total memories emitted — primarily for tests. */
|
|
26
|
+
maxMemories?: number;
|
|
27
|
+
}
|
|
28
|
+
declare function transformSupermemoryExport(parsed: ParsedSupermemoryExport, options?: SupermemoryTransformOptions): ImportedMemory[];
|
|
25
29
|
|
|
26
30
|
export { adapter, parseSupermemoryExport, supermemoryAdapter, transformSupermemoryExport };
|
package/dist/index.js
CHANGED
|
@@ -11,7 +11,7 @@ function parseSupermemoryExport(input, filePath) {
|
|
|
11
11
|
const raw = coerceJson(input);
|
|
12
12
|
const memories = [];
|
|
13
13
|
if (Array.isArray(raw)) {
|
|
14
|
-
append(memories, raw);
|
|
14
|
+
append(memories, raw, "");
|
|
15
15
|
return { memories, ...filePath ? { importedFromPath: filePath } : {} };
|
|
16
16
|
} else if (raw && typeof raw === "object") {
|
|
17
17
|
const obj = raw;
|
|
@@ -22,7 +22,7 @@ function parseSupermemoryExport(input, filePath) {
|
|
|
22
22
|
if (!Array.isArray(obj[key])) {
|
|
23
23
|
throw new Error(`Supermemory export key '${key}' must be an array.`);
|
|
24
24
|
}
|
|
25
|
-
append(memories, obj[key]);
|
|
25
|
+
append(memories, obj[key], key);
|
|
26
26
|
return { memories, ...filePath ? { importedFromPath: filePath } : {} };
|
|
27
27
|
}
|
|
28
28
|
}
|
|
@@ -34,9 +34,15 @@ function parseSupermemoryExport(input, filePath) {
|
|
|
34
34
|
}
|
|
35
35
|
throw new Error(`Supermemory export must be a JSON array or object; received ${describeType(raw)}.`);
|
|
36
36
|
}
|
|
37
|
-
function append(dest, src) {
|
|
38
|
-
for (const item of src) {
|
|
39
|
-
if (item
|
|
37
|
+
function append(dest, src, key) {
|
|
38
|
+
for (const [index, item] of src.entries()) {
|
|
39
|
+
if (!item || typeof item !== "object" || Array.isArray(item)) {
|
|
40
|
+
const location = key ? `${key}[${index}]` : `[${index}]`;
|
|
41
|
+
throw new Error(
|
|
42
|
+
`Supermemory export entry ${location} must be an object record; received ${describeType(item)}.`
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
dest.push(item);
|
|
40
46
|
}
|
|
41
47
|
}
|
|
42
48
|
function coerceJson(input) {
|
|
@@ -51,14 +57,17 @@ function coerceJson(input) {
|
|
|
51
57
|
}
|
|
52
58
|
function describeType(value) {
|
|
53
59
|
if (value === null) return "null";
|
|
60
|
+
if (Array.isArray(value)) return "array";
|
|
54
61
|
return typeof value;
|
|
55
62
|
}
|
|
56
63
|
|
|
57
64
|
// src/transform.ts
|
|
58
65
|
var SUPERMEMORY_SOURCE_LABEL = "supermemory";
|
|
59
|
-
function transformSupermemoryExport(parsed) {
|
|
66
|
+
function transformSupermemoryExport(parsed, options = {}) {
|
|
60
67
|
const out = [];
|
|
68
|
+
const cap = options.maxMemories;
|
|
61
69
|
for (const row of parsed.memories) {
|
|
70
|
+
if (cap !== void 0 && out.length >= cap) return out;
|
|
62
71
|
const m = toImported(row, parsed.importedFromPath);
|
|
63
72
|
if (m) out.push(m);
|
|
64
73
|
}
|
|
@@ -67,12 +76,12 @@ function transformSupermemoryExport(parsed) {
|
|
|
67
76
|
function toImported(row, importedFromPath) {
|
|
68
77
|
const content = pickContent(row);
|
|
69
78
|
if (!content) return void 0;
|
|
70
|
-
const sourceId = pickSourceId(row.id)
|
|
79
|
+
const sourceId = pickSourceId(row.id);
|
|
71
80
|
const sourceTimestamp = pickTimestamp(row);
|
|
72
81
|
return {
|
|
73
82
|
content,
|
|
74
83
|
sourceLabel: SUPERMEMORY_SOURCE_LABEL,
|
|
75
|
-
sourceId,
|
|
84
|
+
...sourceId ? { sourceId } : {},
|
|
76
85
|
...sourceTimestamp ? { sourceTimestamp } : {},
|
|
77
86
|
...importedFromPath ? { importedFromPath } : {},
|
|
78
87
|
metadata: {
|
|
@@ -84,12 +93,28 @@ function toImported(row, importedFromPath) {
|
|
|
84
93
|
}
|
|
85
94
|
function pickTimestamp(row) {
|
|
86
95
|
for (const timestamp of [row.updatedAt, row.createdAt]) {
|
|
87
|
-
|
|
88
|
-
|
|
96
|
+
const parsed = pickValidTimestamp(timestamp);
|
|
97
|
+
if (parsed) {
|
|
98
|
+
return parsed;
|
|
89
99
|
}
|
|
90
100
|
}
|
|
91
101
|
return void 0;
|
|
92
102
|
}
|
|
103
|
+
function pickValidTimestamp(value) {
|
|
104
|
+
if (typeof value !== "string") return void 0;
|
|
105
|
+
const trimmed = value.trim();
|
|
106
|
+
if (trimmed.length === 0) return void 0;
|
|
107
|
+
const match = /^(\d{4})-(\d{2})-(\d{2})T/.exec(trimmed);
|
|
108
|
+
if (!match) return void 0;
|
|
109
|
+
const parsed = Date.parse(trimmed);
|
|
110
|
+
if (!Number.isFinite(parsed)) return void 0;
|
|
111
|
+
const date = new Date(parsed);
|
|
112
|
+
const [, year, month, day] = match;
|
|
113
|
+
if (date.getUTCFullYear() !== Number(year) || date.getUTCMonth() + 1 !== Number(month) || date.getUTCDate() !== Number(day)) {
|
|
114
|
+
return void 0;
|
|
115
|
+
}
|
|
116
|
+
return trimmed;
|
|
117
|
+
}
|
|
93
118
|
function pickSourceId(value) {
|
|
94
119
|
if (typeof value === "string") {
|
|
95
120
|
const trimmed = value.trim();
|
|
@@ -114,8 +139,10 @@ var adapter = {
|
|
|
114
139
|
parse(input, options) {
|
|
115
140
|
return parseSupermemoryExport(input, options?.filePath);
|
|
116
141
|
},
|
|
117
|
-
transform(parsed) {
|
|
118
|
-
return transformSupermemoryExport(parsed
|
|
142
|
+
transform(parsed, options) {
|
|
143
|
+
return transformSupermemoryExport(parsed, {
|
|
144
|
+
...options?.maxMemories !== void 0 ? { maxMemories: options.maxMemories } : {}
|
|
145
|
+
});
|
|
119
146
|
},
|
|
120
147
|
writeTo(target, memories) {
|
|
121
148
|
return defaultWriteMemoriesToOrchestrator(target, memories);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/adapter.ts","../src/parser.ts","../src/transform.ts"],"sourcesContent":["import type { ImporterAdapter } from \"@remnic/core\";\nimport { defaultWriteMemoriesToOrchestrator } from \"@remnic/core\";\n\nimport { parseSupermemoryExport, type ParsedSupermemoryExport } from \"./parser.js\";\nimport { SUPERMEMORY_SOURCE_LABEL, transformSupermemoryExport } from \"./transform.js\";\n\nexport const adapter: ImporterAdapter<ParsedSupermemoryExport> = {\n name: \"supermemory\",\n sourceLabel: SUPERMEMORY_SOURCE_LABEL,\n parse(input, options) {\n return parseSupermemoryExport(input, options?.filePath);\n },\n transform(parsed) {\n return transformSupermemoryExport(parsed);\n },\n writeTo(target, memories) {\n return defaultWriteMemoriesToOrchestrator(target, memories);\n },\n};\n\nexport const supermemoryAdapter = adapter;\n","export interface SupermemoryRecord {\n id?: string;\n memory?: string;\n content?: string;\n summary?: string;\n title?: string;\n createdAt?: string;\n updatedAt?: string;\n containerTags?: string[];\n metadata?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\nexport interface ParsedSupermemoryExport {\n memories: SupermemoryRecord[];\n importedFromPath?: string;\n}\n\nexport function parseSupermemoryExport(input: unknown, filePath?: string): ParsedSupermemoryExport {\n if (input == null) {\n throw new Error(\"Supermemory import requires JSON input. Pass --file <supermemory-export.json>.\");\n }\n\n const raw = coerceJson(input);\n const memories: SupermemoryRecord[] = [];\n\n if (Array.isArray(raw)) {\n append(memories, raw);\n return { memories, ...(filePath ? { importedFromPath: filePath } : {}) };\n } else if (raw && typeof raw === \"object\") {\n const obj = raw as Record<string, unknown>;\n let sawKnownKey = false;\n for (const key of [\"memoryEntries\", \"memories\", \"results\", \"data\"] as const) {\n if (key in obj) {\n sawKnownKey = true;\n if (!Array.isArray(obj[key])) {\n throw new Error(`Supermemory export key '${key}' must be an array.`);\n }\n append(memories, obj[key] as unknown[]);\n return { memories, ...(filePath ? { importedFromPath: filePath } : {}) };\n }\n }\n if (!sawKnownKey) {\n throw new Error(\n \"Supermemory export object has no recognized memory key. Expected one of 'memoryEntries', 'memories', 'results', or 'data'.\",\n );\n }\n }\n\n throw new Error(`Supermemory export must be a JSON array or object; received ${describeType(raw)}.`);\n}\n\nfunction append(dest: SupermemoryRecord[], src: unknown[]): void {\n for (const item of src) {\n if (item && typeof item === \"object\") dest.push(item as SupermemoryRecord);\n }\n}\n\nfunction coerceJson(input: unknown): unknown {\n if (typeof input !== \"string\") return input;\n\n try {\n return JSON.parse(input);\n } catch (err) {\n throw new Error(\n `Supermemory export is not valid JSON: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n}\n\nfunction describeType(value: unknown): string {\n if (value === null) return \"null\";\n return typeof value;\n}\n","import type { ImportedMemory } from \"@remnic/core\";\nimport type { ParsedSupermemoryExport, SupermemoryRecord } from \"./parser.js\";\n\nexport const SUPERMEMORY_SOURCE_LABEL = \"supermemory\";\n\nexport function transformSupermemoryExport(parsed: ParsedSupermemoryExport): ImportedMemory[] {\n const out: ImportedMemory[] = [];\n for (const row of parsed.memories) {\n const m = toImported(row, parsed.importedFromPath);\n if (m) out.push(m);\n }\n return out;\n}\n\nfunction toImported(row: SupermemoryRecord, importedFromPath?: string): ImportedMemory | undefined {\n const content = pickContent(row);\n if (!content) return undefined;\n const sourceId = pickSourceId(row.id) ?? content.slice(0, 64);\n const sourceTimestamp = pickTimestamp(row);\n return {\n content,\n sourceLabel: SUPERMEMORY_SOURCE_LABEL,\n sourceId,\n ...(sourceTimestamp ? { sourceTimestamp } : {}),\n ...(importedFromPath ? { importedFromPath } : {}),\n metadata: {\n kind: \"supermemory_memory\",\n ...(Array.isArray(row.containerTags) && row.containerTags.length > 0\n ? { containerTags: [...row.containerTags] }\n : {}),\n ...(row.metadata && typeof row.metadata === \"object\" ? { sourceMetadata: row.metadata } : {}),\n },\n };\n}\n\nfunction pickTimestamp(row: SupermemoryRecord): string | undefined {\n for (const timestamp of [row.updatedAt, row.createdAt]) {\n if (typeof timestamp === \"string\" && timestamp.trim().length > 0) {\n return timestamp.trim();\n }\n }\n return undefined;\n}\n\nfunction pickSourceId(value: unknown): string | undefined {\n if (typeof value === \"string\") {\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n }\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return String(value);\n }\n return undefined;\n}\n\nfunction pickContent(row: SupermemoryRecord): string | undefined {\n for (const c of [row.content, row.memory, row.summary, row.title]) {\n if (typeof c === \"string\" && c.trim().length > 0) return c.trim();\n }\n return undefined;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/adapter.ts","../src/parser.ts","../src/transform.ts"],"sourcesContent":["import type { ImporterAdapter, ImporterTransformOptions } from \"@remnic/core\";\nimport { defaultWriteMemoriesToOrchestrator } from \"@remnic/core\";\n\nimport { parseSupermemoryExport, type ParsedSupermemoryExport } from \"./parser.js\";\nimport { SUPERMEMORY_SOURCE_LABEL, transformSupermemoryExport } from \"./transform.js\";\n\nexport const adapter: ImporterAdapter<ParsedSupermemoryExport> = {\n name: \"supermemory\",\n sourceLabel: SUPERMEMORY_SOURCE_LABEL,\n parse(input, options) {\n return parseSupermemoryExport(input, options?.filePath);\n },\n transform(\n parsed,\n options?: ImporterTransformOptions,\n ) {\n return transformSupermemoryExport(parsed, {\n ...(options?.maxMemories !== undefined\n ? { maxMemories: options.maxMemories }\n : {}),\n });\n },\n writeTo(target, memories) {\n return defaultWriteMemoriesToOrchestrator(target, memories);\n },\n};\n\nexport const supermemoryAdapter = adapter;\n","export interface SupermemoryRecord {\n id?: string;\n memory?: string;\n content?: string;\n summary?: string;\n title?: string;\n createdAt?: string;\n updatedAt?: string;\n containerTags?: string[];\n metadata?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\nexport interface ParsedSupermemoryExport {\n memories: SupermemoryRecord[];\n importedFromPath?: string;\n}\n\nexport function parseSupermemoryExport(input: unknown, filePath?: string): ParsedSupermemoryExport {\n if (input == null) {\n throw new Error(\"Supermemory import requires JSON input. Pass --file <supermemory-export.json>.\");\n }\n\n const raw = coerceJson(input);\n const memories: SupermemoryRecord[] = [];\n\n if (Array.isArray(raw)) {\n append(memories, raw, \"\");\n return { memories, ...(filePath ? { importedFromPath: filePath } : {}) };\n } else if (raw && typeof raw === \"object\") {\n const obj = raw as Record<string, unknown>;\n let sawKnownKey = false;\n for (const key of [\"memoryEntries\", \"memories\", \"results\", \"data\"] as const) {\n if (key in obj) {\n sawKnownKey = true;\n if (!Array.isArray(obj[key])) {\n throw new Error(`Supermemory export key '${key}' must be an array.`);\n }\n append(memories, obj[key] as unknown[], key);\n return { memories, ...(filePath ? { importedFromPath: filePath } : {}) };\n }\n }\n if (!sawKnownKey) {\n throw new Error(\n \"Supermemory export object has no recognized memory key. Expected one of 'memoryEntries', 'memories', 'results', or 'data'.\",\n );\n }\n }\n\n throw new Error(`Supermemory export must be a JSON array or object; received ${describeType(raw)}.`);\n}\n\nfunction append(dest: SupermemoryRecord[], src: unknown[], key: string): void {\n for (const [index, item] of src.entries()) {\n if (!item || typeof item !== \"object\" || Array.isArray(item)) {\n const location = key ? `${key}[${index}]` : `[${index}]`;\n throw new Error(\n `Supermemory export entry ${location} must be an object record; received ${describeType(item)}.`,\n );\n }\n dest.push(item as SupermemoryRecord);\n }\n}\n\nfunction coerceJson(input: unknown): unknown {\n if (typeof input !== \"string\") return input;\n\n try {\n return JSON.parse(input);\n } catch (err) {\n throw new Error(\n `Supermemory export is not valid JSON: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n}\n\nfunction describeType(value: unknown): string {\n if (value === null) return \"null\";\n if (Array.isArray(value)) return \"array\";\n return typeof value;\n}\n","import type { ImportedMemory } from \"@remnic/core\";\nimport type { ParsedSupermemoryExport, SupermemoryRecord } from \"./parser.js\";\n\nexport const SUPERMEMORY_SOURCE_LABEL = \"supermemory\";\n\nexport interface SupermemoryTransformOptions {\n /** Optional cap on total memories emitted — primarily for tests. */\n maxMemories?: number;\n}\n\nexport function transformSupermemoryExport(\n parsed: ParsedSupermemoryExport,\n options: SupermemoryTransformOptions = {},\n): ImportedMemory[] {\n const out: ImportedMemory[] = [];\n const cap = options.maxMemories;\n for (const row of parsed.memories) {\n if (cap !== undefined && out.length >= cap) return out;\n const m = toImported(row, parsed.importedFromPath);\n if (m) out.push(m);\n }\n return out;\n}\n\nfunction toImported(row: SupermemoryRecord, importedFromPath?: string): ImportedMemory | undefined {\n const content = pickContent(row);\n if (!content) return undefined;\n const sourceId = pickSourceId(row.id);\n const sourceTimestamp = pickTimestamp(row);\n return {\n content,\n sourceLabel: SUPERMEMORY_SOURCE_LABEL,\n ...(sourceId ? { sourceId } : {}),\n ...(sourceTimestamp ? { sourceTimestamp } : {}),\n ...(importedFromPath ? { importedFromPath } : {}),\n metadata: {\n kind: \"supermemory_memory\",\n ...(Array.isArray(row.containerTags) && row.containerTags.length > 0\n ? { containerTags: [...row.containerTags] }\n : {}),\n ...(row.metadata && typeof row.metadata === \"object\" ? { sourceMetadata: row.metadata } : {}),\n },\n };\n}\n\nfunction pickTimestamp(row: SupermemoryRecord): string | undefined {\n for (const timestamp of [row.updatedAt, row.createdAt]) {\n const parsed = pickValidTimestamp(timestamp);\n if (parsed) {\n return parsed;\n }\n }\n return undefined;\n}\n\nfunction pickValidTimestamp(value: unknown): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n if (trimmed.length === 0) return undefined;\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})T/.exec(trimmed);\n if (!match) return undefined;\n const parsed = Date.parse(trimmed);\n if (!Number.isFinite(parsed)) return undefined;\n const date = new Date(parsed);\n const [, year, month, day] = match;\n if (\n date.getUTCFullYear() !== Number(year) ||\n date.getUTCMonth() + 1 !== Number(month) ||\n date.getUTCDate() !== Number(day)\n ) {\n return undefined;\n }\n return trimmed;\n}\n\nfunction pickSourceId(value: unknown): string | undefined {\n if (typeof value === \"string\") {\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n }\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return String(value);\n }\n return undefined;\n}\n\nfunction pickContent(row: SupermemoryRecord): string | undefined {\n for (const c of [row.content, row.memory, row.summary, row.title]) {\n if (typeof c === \"string\" && c.trim().length > 0) return c.trim();\n }\n return undefined;\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remnic/import-supermemory",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "9.3.515",
|
|
4
4
|
"description": "Import Supermemory exports into Remnic",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -19,13 +19,13 @@
|
|
|
19
19
|
"provenance": true
|
|
20
20
|
},
|
|
21
21
|
"peerDependencies": {
|
|
22
|
-
"@remnic/core": "^
|
|
22
|
+
"@remnic/core": "^9.3.515"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"tsup": "^8.0.0",
|
|
26
26
|
"tsx": "^4.0.0",
|
|
27
27
|
"typescript": "^5.7.0",
|
|
28
|
-
"@remnic/core": "
|
|
28
|
+
"@remnic/core": "9.3.515"
|
|
29
29
|
},
|
|
30
30
|
"license": "MIT",
|
|
31
31
|
"repository": {
|
|
@@ -40,8 +40,9 @@
|
|
|
40
40
|
"import"
|
|
41
41
|
],
|
|
42
42
|
"scripts": {
|
|
43
|
-
"build": "tsup src/index.ts --format esm --dts",
|
|
43
|
+
"build": "tsup src/index.ts --format esm --dts --clean",
|
|
44
|
+
"precheck-types": "node ../../scripts/ensure-bench-build-deps.mjs",
|
|
44
45
|
"check-types": "tsc --noEmit",
|
|
45
|
-
"test": "tsx --test src/parser.test.ts src/transform.test.ts src/adapter.test.ts"
|
|
46
|
+
"test": "tsx --test src/parser.test.ts src/transform.test.ts src/adapter.test.ts src/build-script.test.ts"
|
|
46
47
|
}
|
|
47
48
|
}
|