@redaksjon/context 0.0.8 → 0.0.9
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/dist/index5.cjs +37 -12
- package/dist/index5.cjs.map +1 -1
- package/dist/index5.js +38 -14
- package/dist/index5.js.map +1 -1
- package/dist/storage/adapter.d.ts +7 -0
- package/dist/storage/adapter.d.ts.map +1 -1
- package/dist/storage/index.d.ts +1 -1
- package/dist/storage/index.d.ts.map +1 -1
- package/package.json +5 -2
package/dist/index5.cjs
CHANGED
|
@@ -26,6 +26,14 @@ function _interopNamespaceDefault(e) {
|
|
|
26
26
|
|
|
27
27
|
const path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
|
|
28
28
|
|
|
29
|
+
const redaksjonFilenameStrategy = (entity) => {
|
|
30
|
+
const slug = entity.slug;
|
|
31
|
+
if (slug) {
|
|
32
|
+
const prefix = entity.id.substring(0, 8);
|
|
33
|
+
return `${prefix}-${slug}`;
|
|
34
|
+
}
|
|
35
|
+
return entity.id;
|
|
36
|
+
};
|
|
29
37
|
const TYPE_TO_DIRECTORY = {
|
|
30
38
|
person: "people",
|
|
31
39
|
project: "projects",
|
|
@@ -59,12 +67,10 @@ const create = () => {
|
|
|
59
67
|
api = await overcontext.discoverOvercontext({
|
|
60
68
|
schemas: index.redaksjonSchemas,
|
|
61
69
|
pluralNames: index.redaksjonPluralNames,
|
|
62
|
-
// Use standard names without context/ prefix
|
|
63
70
|
startDir,
|
|
64
71
|
contextDirName: path__namespace.basename(lastContextDir),
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
// Limit discovery to prevent finding unrelated parent contexts
|
|
72
|
+
maxLevels: 1,
|
|
73
|
+
filenameStrategy: redaksjonFilenameStrategy
|
|
68
74
|
});
|
|
69
75
|
for (const type of ["person", "project", "company", "term", "ignored"]) {
|
|
70
76
|
const entities = await api.getAll(type);
|
|
@@ -146,19 +152,37 @@ const create = () => {
|
|
|
146
152
|
getEntityFilePath(type, id, contextDirs) {
|
|
147
153
|
const dirName = TYPE_TO_DIRECTORY[type];
|
|
148
154
|
const dirsToSearch = contextDirs.length > 0 ? contextDirs : loadedContextDirs;
|
|
155
|
+
const entity = cache.get(type)?.get(id);
|
|
149
156
|
for (const contextDir of [...dirsToSearch].reverse()) {
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
const stat = node_fs.statSync(filePath);
|
|
157
|
-
if (stat.isFile()) {
|
|
157
|
+
const entityDir = path__namespace.join(contextDir, dirName);
|
|
158
|
+
if (entity) {
|
|
159
|
+
const compoundName = redaksjonFilenameStrategy(entity);
|
|
160
|
+
for (const ext of [".yaml", ".yml"]) {
|
|
161
|
+
const filePath = path__namespace.join(entityDir, `${compoundName}${ext}`);
|
|
162
|
+
if (node_fs.existsSync(filePath) && node_fs.statSync(filePath).isFile()) {
|
|
158
163
|
return filePath;
|
|
159
164
|
}
|
|
160
165
|
}
|
|
161
166
|
}
|
|
167
|
+
for (const ext of [".yaml", ".yml"]) {
|
|
168
|
+
const filePath = path__namespace.join(entityDir, `${id}${ext}`);
|
|
169
|
+
if (node_fs.existsSync(filePath) && node_fs.statSync(filePath).isFile()) {
|
|
170
|
+
return filePath;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (node_fs.existsSync(entityDir)) {
|
|
174
|
+
const prefix = id.substring(0, 8);
|
|
175
|
+
try {
|
|
176
|
+
const files = node_fs.readdirSync(entityDir);
|
|
177
|
+
const match = files.find(
|
|
178
|
+
(f) => f.startsWith(prefix) && (f.endsWith(".yaml") || f.endsWith(".yml"))
|
|
179
|
+
);
|
|
180
|
+
if (match) {
|
|
181
|
+
return path__namespace.join(entityDir, match);
|
|
182
|
+
}
|
|
183
|
+
} catch {
|
|
184
|
+
}
|
|
185
|
+
}
|
|
162
186
|
}
|
|
163
187
|
return void 0;
|
|
164
188
|
}
|
|
@@ -166,4 +190,5 @@ const create = () => {
|
|
|
166
190
|
};
|
|
167
191
|
|
|
168
192
|
exports.create = create;
|
|
193
|
+
exports.redaksjonFilenameStrategy = redaksjonFilenameStrategy;
|
|
169
194
|
//# sourceMappingURL=index5.cjs.map
|
package/dist/index5.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index5.cjs","sources":["../src/storage/adapter.ts"],"sourcesContent":["import { \n discoverOvercontext, \n OvercontextAPI,\n} from '@utilarium/overcontext';\nimport {\n redaksjonSchemas,\n redaksjonPluralNames,\n} from '../schemas';\nimport type {\n Person,\n Project,\n Company,\n Term,\n IgnoredTerm,\n RedaksjonEntity,\n RedaksjonEntityType,\n} from '../types';\n// eslint-disable-next-line no-restricted-imports\nimport { existsSync, statSync } from 'node:fs';\nimport * as path from 'node:path';\n\n// Re-export types for backwards compatibility\nexport type { Person, Project, Company, Term, IgnoredTerm, RedaksjonEntity };\nexport type EntityType = RedaksjonEntityType;\nexport type Entity = RedaksjonEntity;\n\n/**\n * StorageInstance interface - matches protokoll's current API.\n */\nexport interface StorageInstance {\n load(contextDirs: string[]): Promise<void>;\n save(entity: Entity, targetDir: string, allowUpdate?: boolean): Promise<void>;\n delete(type: EntityType, id: string, targetDir: string): Promise<boolean>;\n get<T extends Entity>(type: EntityType, id: string): T | undefined;\n getAll<T extends Entity>(type: EntityType): T[];\n search(query: string): Entity[];\n findBySoundsLike(phonetic: string): Entity | undefined;\n clear(): void;\n getEntityFilePath(type: EntityType, id: string, contextDirs: string[]): string | undefined;\n}\n\n/**\n * Create a storage instance backed by overcontext.\n * Maintains API compatibility with protokoll's existing storage.\n */\n// Map entity types to their directory names\nconst TYPE_TO_DIRECTORY: Record<EntityType, string> = {\n person: 'people',\n project: 'projects',\n company: 'companies',\n term: 'terms',\n ignored: 'ignored',\n};\n\nexport const create = (): StorageInstance => {\n // In-memory cache for sync access (matching original behavior)\n const cache = new Map<EntityType, Map<string, Entity>>();\n let api: OvercontextAPI<typeof redaksjonSchemas> | undefined;\n let loadedContextDirs: string[] = [];\n \n const initCache = () => {\n cache.set('person', new Map());\n cache.set('project', new Map());\n cache.set('company', new Map());\n cache.set('term', new Map());\n cache.set('ignored', new Map());\n };\n \n initCache();\n \n return {\n async load(contextDirs: string[]): Promise<void> {\n initCache();\n loadedContextDirs = contextDirs;\n \n // If no context directories, leave API undefined (empty context)\n if (contextDirs.length === 0) {\n api = undefined;\n return;\n }\n \n try {\n // contextDirs are already resolved paths (e.g., /path/to/context or /path/to/.protokoll/context)\n // We need to determine the parent directory to start overcontext discovery from\n // The context directory could be at different levels depending on configuration\n \n // Take the last (most specific) context dir\n const lastContextDir = contextDirs[contextDirs.length - 1];\n \n // Get the parent directory of the context directory\n // This will be the directory containing the context/ folder\n const startDir = path.dirname(lastContextDir);\n \n // Create overcontext API with hierarchical discovery\n // Note: We use 'context' as contextDirName since we're starting from the parent\n // Use maxLevels: 1 to limit discovery - we've already done hierarchical discovery\n // in loadHierarchicalConfig and are passing the specific contextDirs we want.\n // maxLevels: 1 prevents walking too far up the tree in CI environments where\n // parent directories might contain unrelated context data.\n api = await discoverOvercontext({\n schemas: redaksjonSchemas,\n pluralNames: redaksjonPluralNames, // Use standard names without context/ prefix\n startDir,\n contextDirName: path.basename(lastContextDir), // Use actual context dir name\n maxLevels: 1, // Limit discovery to prevent finding unrelated parent contexts\n });\n \n // Load all entities into cache\n for (const type of ['person', 'project', 'company', 'term', 'ignored'] as EntityType[]) {\n const entities = await api.getAll(type);\n for (const entity of entities) {\n cache.get(type)?.set(entity.id, entity as Entity);\n }\n }\n } catch (error) {\n // If no context directory found, leave API undefined (empty context)\n if (error instanceof Error && error.message.includes('No context directory found')) {\n api = undefined;\n } else {\n throw error;\n }\n }\n },\n \n async save(entity: Entity, _targetDir: string, allowUpdate = false): Promise<void> {\n // Check if entity already exists (for duplicate detection)\n const existing = cache.get(entity.type)?.get(entity.id);\n if (existing && !allowUpdate) {\n throw new Error(`Entity with id \"${entity.id}\" already exists`);\n }\n\n // If no API (empty context), just update cache (in-memory only)\n if (!api) {\n cache.get(entity.type)?.set(entity.id, entity);\n return;\n }\n \n // Save via overcontext (upsert will create or update)\n const saved = await api.upsert(entity.type, entity);\n \n // Update cache\n cache.get(entity.type)?.set(saved.id, saved as Entity);\n },\n \n async delete(type: EntityType, id: string, _targetDir: string): Promise<boolean> {\n if (!api) return false;\n \n const deleted = await api.delete(type, id);\n if (deleted) {\n cache.get(type)?.delete(id);\n }\n return deleted;\n },\n \n get<T extends Entity>(type: EntityType, id: string): T | undefined {\n return cache.get(type)?.get(id) as T | undefined;\n },\n \n getAll<T extends Entity>(type: EntityType): T[] {\n return Array.from(cache.get(type)?.values() ?? []) as T[];\n },\n \n search(query: string): Entity[] {\n const normalizedQuery = query.toLowerCase();\n const results: Entity[] = [];\n const seen = new Set<string>();\n \n for (const entityMap of cache.values()) {\n for (const entity of entityMap.values()) {\n if (seen.has(entity.id)) continue;\n \n // Check name\n if (entity.name.toLowerCase().includes(normalizedQuery)) {\n results.push(entity);\n seen.add(entity.id);\n continue;\n }\n \n // Check sounds_like\n const sounds = (entity as Entity & { sounds_like?: string[] }).sounds_like;\n if (sounds?.some((s: string) => s.toLowerCase().includes(normalizedQuery))) {\n results.push(entity);\n seen.add(entity.id);\n }\n }\n }\n \n return results;\n },\n \n findBySoundsLike(phonetic: string): Entity | undefined {\n const normalized = phonetic.toLowerCase().trim();\n \n for (const entityMap of cache.values()) {\n for (const entity of entityMap.values()) {\n const sounds = (entity as Entity & { sounds_like?: string[] }).sounds_like;\n if (sounds?.some((s: string) => s.toLowerCase() === normalized)) {\n return entity;\n }\n }\n }\n \n return undefined;\n },\n \n clear(): void {\n initCache();\n api = undefined;\n },\n \n getEntityFilePath(type: EntityType, id: string, contextDirs: string[]): string | undefined {\n const dirName = TYPE_TO_DIRECTORY[type];\n const dirsToSearch = contextDirs.length > 0 ? contextDirs : loadedContextDirs;\n \n // Search in reverse order (closest first) to find where the entity is defined\n for (const contextDir of [...dirsToSearch].reverse()) {\n const possiblePaths = [\n path.join(contextDir, dirName, `${id}.yaml`),\n path.join(contextDir, dirName, `${id}.yml`),\n ];\n \n for (const filePath of possiblePaths) {\n // Use sync access check - this is only for CLI, not hot path\n if (existsSync(filePath)) {\n const stat = statSync(filePath);\n if (stat.isFile()) {\n return filePath;\n }\n }\n }\n }\n \n return undefined;\n },\n };\n};\n"],"names":["path","discoverOvercontext","redaksjonSchemas","redaksjonPluralNames","existsSync","statSync"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index5.cjs","sources":["../src/storage/adapter.ts"],"sourcesContent":["import { \n discoverOvercontext, \n OvercontextAPI,\n BaseEntity,\n} from '@utilarium/overcontext';\nimport {\n redaksjonSchemas,\n redaksjonPluralNames,\n} from '../schemas';\nimport type {\n Person,\n Project,\n Company,\n Term,\n IgnoredTerm,\n RedaksjonEntity,\n RedaksjonEntityType,\n} from '../types';\n// eslint-disable-next-line no-restricted-imports\nimport { existsSync, statSync, readdirSync } from 'node:fs';\nimport * as path from 'node:path';\n\n/**\n * Entity filename strategy: first 8 chars of UUID + slug.\n * Produces filenames like `d00acdc4-gerald-corson.yaml`.\n * Falls back to entity.id when no slug is present.\n */\nexport const redaksjonFilenameStrategy = (entity: BaseEntity): string => {\n const slug = (entity as RedaksjonEntity & { slug?: string }).slug;\n if (slug) {\n const prefix = entity.id.substring(0, 8);\n return `${prefix}-${slug}`;\n }\n return entity.id;\n};\n\n// Re-export types for backwards compatibility\nexport type { Person, Project, Company, Term, IgnoredTerm, RedaksjonEntity };\nexport type EntityType = RedaksjonEntityType;\nexport type Entity = RedaksjonEntity;\n\n/**\n * StorageInstance interface - matches protokoll's current API.\n */\nexport interface StorageInstance {\n load(contextDirs: string[]): Promise<void>;\n save(entity: Entity, targetDir: string, allowUpdate?: boolean): Promise<void>;\n delete(type: EntityType, id: string, targetDir: string): Promise<boolean>;\n get<T extends Entity>(type: EntityType, id: string): T | undefined;\n getAll<T extends Entity>(type: EntityType): T[];\n search(query: string): Entity[];\n findBySoundsLike(phonetic: string): Entity | undefined;\n clear(): void;\n getEntityFilePath(type: EntityType, id: string, contextDirs: string[]): string | undefined;\n}\n\n/**\n * Create a storage instance backed by overcontext.\n * Maintains API compatibility with protokoll's existing storage.\n */\n// Map entity types to their directory names\nconst TYPE_TO_DIRECTORY: Record<EntityType, string> = {\n person: 'people',\n project: 'projects',\n company: 'companies',\n term: 'terms',\n ignored: 'ignored',\n};\n\nexport const create = (): StorageInstance => {\n // In-memory cache for sync access (matching original behavior)\n const cache = new Map<EntityType, Map<string, Entity>>();\n let api: OvercontextAPI<typeof redaksjonSchemas> | undefined;\n let loadedContextDirs: string[] = [];\n \n const initCache = () => {\n cache.set('person', new Map());\n cache.set('project', new Map());\n cache.set('company', new Map());\n cache.set('term', new Map());\n cache.set('ignored', new Map());\n };\n \n initCache();\n \n return {\n async load(contextDirs: string[]): Promise<void> {\n initCache();\n loadedContextDirs = contextDirs;\n \n // If no context directories, leave API undefined (empty context)\n if (contextDirs.length === 0) {\n api = undefined;\n return;\n }\n \n try {\n // contextDirs are already resolved paths (e.g., /path/to/context or /path/to/.protokoll/context)\n // We need to determine the parent directory to start overcontext discovery from\n // The context directory could be at different levels depending on configuration\n \n // Take the last (most specific) context dir\n const lastContextDir = contextDirs[contextDirs.length - 1];\n \n // Get the parent directory of the context directory\n // This will be the directory containing the context/ folder\n const startDir = path.dirname(lastContextDir);\n \n // Create overcontext API with hierarchical discovery\n // Note: We use 'context' as contextDirName since we're starting from the parent\n // Use maxLevels: 1 to limit discovery - we've already done hierarchical discovery\n // in loadHierarchicalConfig and are passing the specific contextDirs we want.\n // maxLevels: 1 prevents walking too far up the tree in CI environments where\n // parent directories might contain unrelated context data.\n api = await discoverOvercontext({\n schemas: redaksjonSchemas,\n pluralNames: redaksjonPluralNames,\n startDir,\n contextDirName: path.basename(lastContextDir),\n maxLevels: 1,\n filenameStrategy: redaksjonFilenameStrategy,\n });\n \n // Load all entities into cache\n for (const type of ['person', 'project', 'company', 'term', 'ignored'] as EntityType[]) {\n const entities = await api.getAll(type);\n for (const entity of entities) {\n cache.get(type)?.set(entity.id, entity as Entity);\n }\n }\n } catch (error) {\n // If no context directory found, leave API undefined (empty context)\n if (error instanceof Error && error.message.includes('No context directory found')) {\n api = undefined;\n } else {\n throw error;\n }\n }\n },\n \n async save(entity: Entity, _targetDir: string, allowUpdate = false): Promise<void> {\n // Check if entity already exists (for duplicate detection)\n const existing = cache.get(entity.type)?.get(entity.id);\n if (existing && !allowUpdate) {\n throw new Error(`Entity with id \"${entity.id}\" already exists`);\n }\n\n // If no API (empty context), just update cache (in-memory only)\n if (!api) {\n cache.get(entity.type)?.set(entity.id, entity);\n return;\n }\n \n // Save via overcontext (upsert will create or update)\n const saved = await api.upsert(entity.type, entity);\n \n // Update cache\n cache.get(entity.type)?.set(saved.id, saved as Entity);\n },\n \n async delete(type: EntityType, id: string, _targetDir: string): Promise<boolean> {\n if (!api) return false;\n \n const deleted = await api.delete(type, id);\n if (deleted) {\n cache.get(type)?.delete(id);\n }\n return deleted;\n },\n \n get<T extends Entity>(type: EntityType, id: string): T | undefined {\n return cache.get(type)?.get(id) as T | undefined;\n },\n \n getAll<T extends Entity>(type: EntityType): T[] {\n return Array.from(cache.get(type)?.values() ?? []) as T[];\n },\n \n search(query: string): Entity[] {\n const normalizedQuery = query.toLowerCase();\n const results: Entity[] = [];\n const seen = new Set<string>();\n \n for (const entityMap of cache.values()) {\n for (const entity of entityMap.values()) {\n if (seen.has(entity.id)) continue;\n \n // Check name\n if (entity.name.toLowerCase().includes(normalizedQuery)) {\n results.push(entity);\n seen.add(entity.id);\n continue;\n }\n \n // Check sounds_like\n const sounds = (entity as Entity & { sounds_like?: string[] }).sounds_like;\n if (sounds?.some((s: string) => s.toLowerCase().includes(normalizedQuery))) {\n results.push(entity);\n seen.add(entity.id);\n }\n }\n }\n \n return results;\n },\n \n findBySoundsLike(phonetic: string): Entity | undefined {\n const normalized = phonetic.toLowerCase().trim();\n \n for (const entityMap of cache.values()) {\n for (const entity of entityMap.values()) {\n const sounds = (entity as Entity & { sounds_like?: string[] }).sounds_like;\n if (sounds?.some((s: string) => s.toLowerCase() === normalized)) {\n return entity;\n }\n }\n }\n \n return undefined;\n },\n \n clear(): void {\n initCache();\n api = undefined;\n },\n \n getEntityFilePath(type: EntityType, id: string, contextDirs: string[]): string | undefined {\n const dirName = TYPE_TO_DIRECTORY[type];\n const dirsToSearch = contextDirs.length > 0 ? contextDirs : loadedContextDirs;\n const entity = cache.get(type)?.get(id);\n \n for (const contextDir of [...dirsToSearch].reverse()) {\n const entityDir = path.join(contextDir, dirName);\n\n // Try compound filename first (e.g. d00acdc4-gerald-corson.yaml)\n if (entity) {\n const compoundName = redaksjonFilenameStrategy(entity as RedaksjonEntity & { slug?: string });\n for (const ext of ['.yaml', '.yml']) {\n const filePath = path.join(entityDir, `${compoundName}${ext}`);\n if (existsSync(filePath) && statSync(filePath).isFile()) {\n return filePath;\n }\n }\n }\n\n // Fall back to direct id-based filename (legacy)\n for (const ext of ['.yaml', '.yml']) {\n const filePath = path.join(entityDir, `${id}${ext}`);\n if (existsSync(filePath) && statSync(filePath).isFile()) {\n return filePath;\n }\n }\n\n // Prefix scan as last resort (handles files we haven't cached yet)\n if (existsSync(entityDir)) {\n const prefix = id.substring(0, 8);\n try {\n const files = readdirSync(entityDir);\n const match = files.find(f =>\n f.startsWith(prefix) && (f.endsWith('.yaml') || f.endsWith('.yml'))\n );\n if (match) {\n return path.join(entityDir, match);\n }\n } catch { /* directory read failed */ }\n }\n }\n \n return undefined;\n },\n };\n};\n"],"names":["path","discoverOvercontext","redaksjonSchemas","redaksjonPluralNames","existsSync","statSync","readdirSync"],"mappings":"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"}
|
package/dist/index5.js
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import { discoverOvercontext } from '@utilarium/overcontext';
|
|
2
2
|
import { redaksjonPluralNames, redaksjonSchemas } from './index2.js';
|
|
3
|
-
import { existsSync, statSync } from 'node:fs';
|
|
3
|
+
import { existsSync, statSync, readdirSync } from 'node:fs';
|
|
4
4
|
import * as path from 'node:path';
|
|
5
5
|
|
|
6
|
+
const redaksjonFilenameStrategy = (entity) => {
|
|
7
|
+
const slug = entity.slug;
|
|
8
|
+
if (slug) {
|
|
9
|
+
const prefix = entity.id.substring(0, 8);
|
|
10
|
+
return `${prefix}-${slug}`;
|
|
11
|
+
}
|
|
12
|
+
return entity.id;
|
|
13
|
+
};
|
|
6
14
|
const TYPE_TO_DIRECTORY = {
|
|
7
15
|
person: "people",
|
|
8
16
|
project: "projects",
|
|
@@ -36,12 +44,10 @@ const create = () => {
|
|
|
36
44
|
api = await discoverOvercontext({
|
|
37
45
|
schemas: redaksjonSchemas,
|
|
38
46
|
pluralNames: redaksjonPluralNames,
|
|
39
|
-
// Use standard names without context/ prefix
|
|
40
47
|
startDir,
|
|
41
48
|
contextDirName: path.basename(lastContextDir),
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
// Limit discovery to prevent finding unrelated parent contexts
|
|
49
|
+
maxLevels: 1,
|
|
50
|
+
filenameStrategy: redaksjonFilenameStrategy
|
|
45
51
|
});
|
|
46
52
|
for (const type of ["person", "project", "company", "term", "ignored"]) {
|
|
47
53
|
const entities = await api.getAll(type);
|
|
@@ -123,24 +129,42 @@ const create = () => {
|
|
|
123
129
|
getEntityFilePath(type, id, contextDirs) {
|
|
124
130
|
const dirName = TYPE_TO_DIRECTORY[type];
|
|
125
131
|
const dirsToSearch = contextDirs.length > 0 ? contextDirs : loadedContextDirs;
|
|
132
|
+
const entity = cache.get(type)?.get(id);
|
|
126
133
|
for (const contextDir of [...dirsToSearch].reverse()) {
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
const stat = statSync(filePath);
|
|
134
|
-
if (stat.isFile()) {
|
|
134
|
+
const entityDir = path.join(contextDir, dirName);
|
|
135
|
+
if (entity) {
|
|
136
|
+
const compoundName = redaksjonFilenameStrategy(entity);
|
|
137
|
+
for (const ext of [".yaml", ".yml"]) {
|
|
138
|
+
const filePath = path.join(entityDir, `${compoundName}${ext}`);
|
|
139
|
+
if (existsSync(filePath) && statSync(filePath).isFile()) {
|
|
135
140
|
return filePath;
|
|
136
141
|
}
|
|
137
142
|
}
|
|
138
143
|
}
|
|
144
|
+
for (const ext of [".yaml", ".yml"]) {
|
|
145
|
+
const filePath = path.join(entityDir, `${id}${ext}`);
|
|
146
|
+
if (existsSync(filePath) && statSync(filePath).isFile()) {
|
|
147
|
+
return filePath;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (existsSync(entityDir)) {
|
|
151
|
+
const prefix = id.substring(0, 8);
|
|
152
|
+
try {
|
|
153
|
+
const files = readdirSync(entityDir);
|
|
154
|
+
const match = files.find(
|
|
155
|
+
(f) => f.startsWith(prefix) && (f.endsWith(".yaml") || f.endsWith(".yml"))
|
|
156
|
+
);
|
|
157
|
+
if (match) {
|
|
158
|
+
return path.join(entityDir, match);
|
|
159
|
+
}
|
|
160
|
+
} catch {
|
|
161
|
+
}
|
|
162
|
+
}
|
|
139
163
|
}
|
|
140
164
|
return void 0;
|
|
141
165
|
}
|
|
142
166
|
};
|
|
143
167
|
};
|
|
144
168
|
|
|
145
|
-
export { create };
|
|
169
|
+
export { create, redaksjonFilenameStrategy };
|
|
146
170
|
//# sourceMappingURL=index5.js.map
|
package/dist/index5.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index5.js","sources":["../src/storage/adapter.ts"],"sourcesContent":["import { \n discoverOvercontext, \n OvercontextAPI,\n} from '@utilarium/overcontext';\nimport {\n redaksjonSchemas,\n redaksjonPluralNames,\n} from '../schemas';\nimport type {\n Person,\n Project,\n Company,\n Term,\n IgnoredTerm,\n RedaksjonEntity,\n RedaksjonEntityType,\n} from '../types';\n// eslint-disable-next-line no-restricted-imports\nimport { existsSync, statSync } from 'node:fs';\nimport * as path from 'node:path';\n\n// Re-export types for backwards compatibility\nexport type { Person, Project, Company, Term, IgnoredTerm, RedaksjonEntity };\nexport type EntityType = RedaksjonEntityType;\nexport type Entity = RedaksjonEntity;\n\n/**\n * StorageInstance interface - matches protokoll's current API.\n */\nexport interface StorageInstance {\n load(contextDirs: string[]): Promise<void>;\n save(entity: Entity, targetDir: string, allowUpdate?: boolean): Promise<void>;\n delete(type: EntityType, id: string, targetDir: string): Promise<boolean>;\n get<T extends Entity>(type: EntityType, id: string): T | undefined;\n getAll<T extends Entity>(type: EntityType): T[];\n search(query: string): Entity[];\n findBySoundsLike(phonetic: string): Entity | undefined;\n clear(): void;\n getEntityFilePath(type: EntityType, id: string, contextDirs: string[]): string | undefined;\n}\n\n/**\n * Create a storage instance backed by overcontext.\n * Maintains API compatibility with protokoll's existing storage.\n */\n// Map entity types to their directory names\nconst TYPE_TO_DIRECTORY: Record<EntityType, string> = {\n person: 'people',\n project: 'projects',\n company: 'companies',\n term: 'terms',\n ignored: 'ignored',\n};\n\nexport const create = (): StorageInstance => {\n // In-memory cache for sync access (matching original behavior)\n const cache = new Map<EntityType, Map<string, Entity>>();\n let api: OvercontextAPI<typeof redaksjonSchemas> | undefined;\n let loadedContextDirs: string[] = [];\n \n const initCache = () => {\n cache.set('person', new Map());\n cache.set('project', new Map());\n cache.set('company', new Map());\n cache.set('term', new Map());\n cache.set('ignored', new Map());\n };\n \n initCache();\n \n return {\n async load(contextDirs: string[]): Promise<void> {\n initCache();\n loadedContextDirs = contextDirs;\n \n // If no context directories, leave API undefined (empty context)\n if (contextDirs.length === 0) {\n api = undefined;\n return;\n }\n \n try {\n // contextDirs are already resolved paths (e.g., /path/to/context or /path/to/.protokoll/context)\n // We need to determine the parent directory to start overcontext discovery from\n // The context directory could be at different levels depending on configuration\n \n // Take the last (most specific) context dir\n const lastContextDir = contextDirs[contextDirs.length - 1];\n \n // Get the parent directory of the context directory\n // This will be the directory containing the context/ folder\n const startDir = path.dirname(lastContextDir);\n \n // Create overcontext API with hierarchical discovery\n // Note: We use 'context' as contextDirName since we're starting from the parent\n // Use maxLevels: 1 to limit discovery - we've already done hierarchical discovery\n // in loadHierarchicalConfig and are passing the specific contextDirs we want.\n // maxLevels: 1 prevents walking too far up the tree in CI environments where\n // parent directories might contain unrelated context data.\n api = await discoverOvercontext({\n schemas: redaksjonSchemas,\n pluralNames: redaksjonPluralNames, // Use standard names without context/ prefix\n startDir,\n contextDirName: path.basename(lastContextDir), // Use actual context dir name\n maxLevels: 1, // Limit discovery to prevent finding unrelated parent contexts\n });\n \n // Load all entities into cache\n for (const type of ['person', 'project', 'company', 'term', 'ignored'] as EntityType[]) {\n const entities = await api.getAll(type);\n for (const entity of entities) {\n cache.get(type)?.set(entity.id, entity as Entity);\n }\n }\n } catch (error) {\n // If no context directory found, leave API undefined (empty context)\n if (error instanceof Error && error.message.includes('No context directory found')) {\n api = undefined;\n } else {\n throw error;\n }\n }\n },\n \n async save(entity: Entity, _targetDir: string, allowUpdate = false): Promise<void> {\n // Check if entity already exists (for duplicate detection)\n const existing = cache.get(entity.type)?.get(entity.id);\n if (existing && !allowUpdate) {\n throw new Error(`Entity with id \"${entity.id}\" already exists`);\n }\n\n // If no API (empty context), just update cache (in-memory only)\n if (!api) {\n cache.get(entity.type)?.set(entity.id, entity);\n return;\n }\n \n // Save via overcontext (upsert will create or update)\n const saved = await api.upsert(entity.type, entity);\n \n // Update cache\n cache.get(entity.type)?.set(saved.id, saved as Entity);\n },\n \n async delete(type: EntityType, id: string, _targetDir: string): Promise<boolean> {\n if (!api) return false;\n \n const deleted = await api.delete(type, id);\n if (deleted) {\n cache.get(type)?.delete(id);\n }\n return deleted;\n },\n \n get<T extends Entity>(type: EntityType, id: string): T | undefined {\n return cache.get(type)?.get(id) as T | undefined;\n },\n \n getAll<T extends Entity>(type: EntityType): T[] {\n return Array.from(cache.get(type)?.values() ?? []) as T[];\n },\n \n search(query: string): Entity[] {\n const normalizedQuery = query.toLowerCase();\n const results: Entity[] = [];\n const seen = new Set<string>();\n \n for (const entityMap of cache.values()) {\n for (const entity of entityMap.values()) {\n if (seen.has(entity.id)) continue;\n \n // Check name\n if (entity.name.toLowerCase().includes(normalizedQuery)) {\n results.push(entity);\n seen.add(entity.id);\n continue;\n }\n \n // Check sounds_like\n const sounds = (entity as Entity & { sounds_like?: string[] }).sounds_like;\n if (sounds?.some((s: string) => s.toLowerCase().includes(normalizedQuery))) {\n results.push(entity);\n seen.add(entity.id);\n }\n }\n }\n \n return results;\n },\n \n findBySoundsLike(phonetic: string): Entity | undefined {\n const normalized = phonetic.toLowerCase().trim();\n \n for (const entityMap of cache.values()) {\n for (const entity of entityMap.values()) {\n const sounds = (entity as Entity & { sounds_like?: string[] }).sounds_like;\n if (sounds?.some((s: string) => s.toLowerCase() === normalized)) {\n return entity;\n }\n }\n }\n \n return undefined;\n },\n \n clear(): void {\n initCache();\n api = undefined;\n },\n \n getEntityFilePath(type: EntityType, id: string, contextDirs: string[]): string | undefined {\n const dirName = TYPE_TO_DIRECTORY[type];\n const dirsToSearch = contextDirs.length > 0 ? contextDirs : loadedContextDirs;\n \n // Search in reverse order (closest first) to find where the entity is defined\n for (const contextDir of [...dirsToSearch].reverse()) {\n const possiblePaths = [\n path.join(contextDir, dirName, `${id}.yaml`),\n path.join(contextDir, dirName, `${id}.yml`),\n ];\n \n for (const filePath of possiblePaths) {\n // Use sync access check - this is only for CLI, not hot path\n if (existsSync(filePath)) {\n const stat = statSync(filePath);\n if (stat.isFile()) {\n return filePath;\n }\n }\n }\n }\n \n return undefined;\n },\n };\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index5.js","sources":["../src/storage/adapter.ts"],"sourcesContent":["import { \n discoverOvercontext, \n OvercontextAPI,\n BaseEntity,\n} from '@utilarium/overcontext';\nimport {\n redaksjonSchemas,\n redaksjonPluralNames,\n} from '../schemas';\nimport type {\n Person,\n Project,\n Company,\n Term,\n IgnoredTerm,\n RedaksjonEntity,\n RedaksjonEntityType,\n} from '../types';\n// eslint-disable-next-line no-restricted-imports\nimport { existsSync, statSync, readdirSync } from 'node:fs';\nimport * as path from 'node:path';\n\n/**\n * Entity filename strategy: first 8 chars of UUID + slug.\n * Produces filenames like `d00acdc4-gerald-corson.yaml`.\n * Falls back to entity.id when no slug is present.\n */\nexport const redaksjonFilenameStrategy = (entity: BaseEntity): string => {\n const slug = (entity as RedaksjonEntity & { slug?: string }).slug;\n if (slug) {\n const prefix = entity.id.substring(0, 8);\n return `${prefix}-${slug}`;\n }\n return entity.id;\n};\n\n// Re-export types for backwards compatibility\nexport type { Person, Project, Company, Term, IgnoredTerm, RedaksjonEntity };\nexport type EntityType = RedaksjonEntityType;\nexport type Entity = RedaksjonEntity;\n\n/**\n * StorageInstance interface - matches protokoll's current API.\n */\nexport interface StorageInstance {\n load(contextDirs: string[]): Promise<void>;\n save(entity: Entity, targetDir: string, allowUpdate?: boolean): Promise<void>;\n delete(type: EntityType, id: string, targetDir: string): Promise<boolean>;\n get<T extends Entity>(type: EntityType, id: string): T | undefined;\n getAll<T extends Entity>(type: EntityType): T[];\n search(query: string): Entity[];\n findBySoundsLike(phonetic: string): Entity | undefined;\n clear(): void;\n getEntityFilePath(type: EntityType, id: string, contextDirs: string[]): string | undefined;\n}\n\n/**\n * Create a storage instance backed by overcontext.\n * Maintains API compatibility with protokoll's existing storage.\n */\n// Map entity types to their directory names\nconst TYPE_TO_DIRECTORY: Record<EntityType, string> = {\n person: 'people',\n project: 'projects',\n company: 'companies',\n term: 'terms',\n ignored: 'ignored',\n};\n\nexport const create = (): StorageInstance => {\n // In-memory cache for sync access (matching original behavior)\n const cache = new Map<EntityType, Map<string, Entity>>();\n let api: OvercontextAPI<typeof redaksjonSchemas> | undefined;\n let loadedContextDirs: string[] = [];\n \n const initCache = () => {\n cache.set('person', new Map());\n cache.set('project', new Map());\n cache.set('company', new Map());\n cache.set('term', new Map());\n cache.set('ignored', new Map());\n };\n \n initCache();\n \n return {\n async load(contextDirs: string[]): Promise<void> {\n initCache();\n loadedContextDirs = contextDirs;\n \n // If no context directories, leave API undefined (empty context)\n if (contextDirs.length === 0) {\n api = undefined;\n return;\n }\n \n try {\n // contextDirs are already resolved paths (e.g., /path/to/context or /path/to/.protokoll/context)\n // We need to determine the parent directory to start overcontext discovery from\n // The context directory could be at different levels depending on configuration\n \n // Take the last (most specific) context dir\n const lastContextDir = contextDirs[contextDirs.length - 1];\n \n // Get the parent directory of the context directory\n // This will be the directory containing the context/ folder\n const startDir = path.dirname(lastContextDir);\n \n // Create overcontext API with hierarchical discovery\n // Note: We use 'context' as contextDirName since we're starting from the parent\n // Use maxLevels: 1 to limit discovery - we've already done hierarchical discovery\n // in loadHierarchicalConfig and are passing the specific contextDirs we want.\n // maxLevels: 1 prevents walking too far up the tree in CI environments where\n // parent directories might contain unrelated context data.\n api = await discoverOvercontext({\n schemas: redaksjonSchemas,\n pluralNames: redaksjonPluralNames,\n startDir,\n contextDirName: path.basename(lastContextDir),\n maxLevels: 1,\n filenameStrategy: redaksjonFilenameStrategy,\n });\n \n // Load all entities into cache\n for (const type of ['person', 'project', 'company', 'term', 'ignored'] as EntityType[]) {\n const entities = await api.getAll(type);\n for (const entity of entities) {\n cache.get(type)?.set(entity.id, entity as Entity);\n }\n }\n } catch (error) {\n // If no context directory found, leave API undefined (empty context)\n if (error instanceof Error && error.message.includes('No context directory found')) {\n api = undefined;\n } else {\n throw error;\n }\n }\n },\n \n async save(entity: Entity, _targetDir: string, allowUpdate = false): Promise<void> {\n // Check if entity already exists (for duplicate detection)\n const existing = cache.get(entity.type)?.get(entity.id);\n if (existing && !allowUpdate) {\n throw new Error(`Entity with id \"${entity.id}\" already exists`);\n }\n\n // If no API (empty context), just update cache (in-memory only)\n if (!api) {\n cache.get(entity.type)?.set(entity.id, entity);\n return;\n }\n \n // Save via overcontext (upsert will create or update)\n const saved = await api.upsert(entity.type, entity);\n \n // Update cache\n cache.get(entity.type)?.set(saved.id, saved as Entity);\n },\n \n async delete(type: EntityType, id: string, _targetDir: string): Promise<boolean> {\n if (!api) return false;\n \n const deleted = await api.delete(type, id);\n if (deleted) {\n cache.get(type)?.delete(id);\n }\n return deleted;\n },\n \n get<T extends Entity>(type: EntityType, id: string): T | undefined {\n return cache.get(type)?.get(id) as T | undefined;\n },\n \n getAll<T extends Entity>(type: EntityType): T[] {\n return Array.from(cache.get(type)?.values() ?? []) as T[];\n },\n \n search(query: string): Entity[] {\n const normalizedQuery = query.toLowerCase();\n const results: Entity[] = [];\n const seen = new Set<string>();\n \n for (const entityMap of cache.values()) {\n for (const entity of entityMap.values()) {\n if (seen.has(entity.id)) continue;\n \n // Check name\n if (entity.name.toLowerCase().includes(normalizedQuery)) {\n results.push(entity);\n seen.add(entity.id);\n continue;\n }\n \n // Check sounds_like\n const sounds = (entity as Entity & { sounds_like?: string[] }).sounds_like;\n if (sounds?.some((s: string) => s.toLowerCase().includes(normalizedQuery))) {\n results.push(entity);\n seen.add(entity.id);\n }\n }\n }\n \n return results;\n },\n \n findBySoundsLike(phonetic: string): Entity | undefined {\n const normalized = phonetic.toLowerCase().trim();\n \n for (const entityMap of cache.values()) {\n for (const entity of entityMap.values()) {\n const sounds = (entity as Entity & { sounds_like?: string[] }).sounds_like;\n if (sounds?.some((s: string) => s.toLowerCase() === normalized)) {\n return entity;\n }\n }\n }\n \n return undefined;\n },\n \n clear(): void {\n initCache();\n api = undefined;\n },\n \n getEntityFilePath(type: EntityType, id: string, contextDirs: string[]): string | undefined {\n const dirName = TYPE_TO_DIRECTORY[type];\n const dirsToSearch = contextDirs.length > 0 ? contextDirs : loadedContextDirs;\n const entity = cache.get(type)?.get(id);\n \n for (const contextDir of [...dirsToSearch].reverse()) {\n const entityDir = path.join(contextDir, dirName);\n\n // Try compound filename first (e.g. d00acdc4-gerald-corson.yaml)\n if (entity) {\n const compoundName = redaksjonFilenameStrategy(entity as RedaksjonEntity & { slug?: string });\n for (const ext of ['.yaml', '.yml']) {\n const filePath = path.join(entityDir, `${compoundName}${ext}`);\n if (existsSync(filePath) && statSync(filePath).isFile()) {\n return filePath;\n }\n }\n }\n\n // Fall back to direct id-based filename (legacy)\n for (const ext of ['.yaml', '.yml']) {\n const filePath = path.join(entityDir, `${id}${ext}`);\n if (existsSync(filePath) && statSync(filePath).isFile()) {\n return filePath;\n }\n }\n\n // Prefix scan as last resort (handles files we haven't cached yet)\n if (existsSync(entityDir)) {\n const prefix = id.substring(0, 8);\n try {\n const files = readdirSync(entityDir);\n const match = files.find(f =>\n f.startsWith(prefix) && (f.endsWith('.yaml') || f.endsWith('.yml'))\n );\n if (match) {\n return path.join(entityDir, match);\n }\n } catch { /* directory read failed */ }\n }\n }\n \n return undefined;\n },\n };\n};\n"],"names":[],"mappings":";;;;;AA2BO,MAAM,yBAAA,GAA4B,CAAC,MAAA,KAA+B;AACrE,EAAA,MAAM,OAAQ,MAAA,CAA+C,IAAA;AAC7D,EAAA,IAAI,IAAA,EAAM;AACN,IAAA,MAAM,MAAA,GAAS,MAAA,CAAO,EAAA,CAAG,SAAA,CAAU,GAAG,CAAC,CAAA;AACvC,IAAA,OAAO,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA;AAAA,EAC5B;AACA,EAAA,OAAO,MAAA,CAAO,EAAA;AAClB;AA2BA,MAAM,iBAAA,GAAgD;AAAA,EAClD,MAAA,EAAQ,QAAA;AAAA,EACR,OAAA,EAAS,UAAA;AAAA,EACT,OAAA,EAAS,WAAA;AAAA,EACT,IAAA,EAAM,OAAA;AAAA,EACN,OAAA,EAAS;AACb,CAAA;AAEO,MAAM,SAAS,MAAuB;AAEzC,EAAA,MAAM,KAAA,uBAAY,GAAA,EAAqC;AACvD,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI,oBAA8B,EAAC;AAEnC,EAAA,MAAM,YAAY,MAAM;AACpB,IAAA,KAAA,CAAM,GAAA,CAAI,QAAA,kBAAU,IAAI,GAAA,EAAK,CAAA;AAC7B,IAAA,KAAA,CAAM,GAAA,CAAI,SAAA,kBAAW,IAAI,GAAA,EAAK,CAAA;AAC9B,IAAA,KAAA,CAAM,GAAA,CAAI,SAAA,kBAAW,IAAI,GAAA,EAAK,CAAA;AAC9B,IAAA,KAAA,CAAM,GAAA,CAAI,MAAA,kBAAQ,IAAI,GAAA,EAAK,CAAA;AAC3B,IAAA,KAAA,CAAM,GAAA,CAAI,SAAA,kBAAW,IAAI,GAAA,EAAK,CAAA;AAAA,EAClC,CAAA;AAEA,EAAA,SAAA,EAAU;AAEV,EAAA,OAAO;AAAA,IACH,MAAM,KAAK,WAAA,EAAsC;AAC7C,MAAA,SAAA,EAAU;AACV,MAAA,iBAAA,GAAoB,WAAA;AAGpB,MAAA,IAAI,WAAA,CAAY,WAAW,CAAA,EAAG;AAC1B,QAAA,GAAA,GAAM,MAAA;AACN,QAAA;AAAA,MACJ;AAEA,MAAA,IAAI;AAMA,QAAA,MAAM,cAAA,GAAiB,WAAA,CAAY,WAAA,CAAY,MAAA,GAAS,CAAC,CAAA;AAIzD,QAAA,MAAM,QAAA,GAAW,IAAA,CAAK,OAAA,CAAQ,cAAc,CAAA;AAQ5C,QAAA,GAAA,GAAM,MAAM,mBAAA,CAAoB;AAAA,UAC5B,OAAA,EAAS,gBAAA;AAAA,UACT,WAAA,EAAa,oBAAA;AAAA,UACb,QAAA;AAAA,UACA,cAAA,EAAgB,IAAA,CAAK,QAAA,CAAS,cAAc,CAAA;AAAA,UAC5C,SAAA,EAAW,CAAA;AAAA,UACX,gBAAA,EAAkB;AAAA,SACrB,CAAA;AAGD,QAAA,KAAA,MAAW,QAAQ,CAAC,QAAA,EAAU,WAAW,SAAA,EAAW,MAAA,EAAQ,SAAS,CAAA,EAAmB;AACpF,UAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CAAI,MAAA,CAAO,IAAI,CAAA;AACtC,UAAA,KAAA,MAAW,UAAU,QAAA,EAAU;AAC3B,YAAA,KAAA,CAAM,IAAI,IAAI,CAAA,EAAG,GAAA,CAAI,MAAA,CAAO,IAAI,MAAgB,CAAA;AAAA,UACpD;AAAA,QACJ;AAAA,MACJ,SAAS,KAAA,EAAO;AAEZ,QAAA,IAAI,iBAAiB,KAAA,IAAS,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,4BAA4B,CAAA,EAAG;AAChF,UAAA,GAAA,GAAM,MAAA;AAAA,QACV,CAAA,MAAO;AACH,UAAA,MAAM,KAAA;AAAA,QACV;AAAA,MACJ;AAAA,IACJ,CAAA;AAAA,IAEA,MAAM,IAAA,CAAK,MAAA,EAAgB,UAAA,EAAoB,cAAc,KAAA,EAAsB;AAE/E,MAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CAAI,MAAA,CAAO,IAAI,CAAA,EAAG,GAAA,CAAI,OAAO,EAAE,CAAA;AACtD,MAAA,IAAI,QAAA,IAAY,CAAC,WAAA,EAAa;AAC1B,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,gBAAA,EAAmB,MAAA,CAAO,EAAE,CAAA,gBAAA,CAAkB,CAAA;AAAA,MAClE;AAGA,MAAA,IAAI,CAAC,GAAA,EAAK;AACN,QAAA,KAAA,CAAM,IAAI,MAAA,CAAO,IAAI,GAAG,GAAA,CAAI,MAAA,CAAO,IAAI,MAAM,CAAA;AAC7C,QAAA;AAAA,MACJ;AAGA,MAAA,MAAM,QAAQ,MAAM,GAAA,CAAI,MAAA,CAAO,MAAA,CAAO,MAAM,MAAM,CAAA;AAGlD,MAAA,KAAA,CAAM,IAAI,MAAA,CAAO,IAAI,GAAG,GAAA,CAAI,KAAA,CAAM,IAAI,KAAe,CAAA;AAAA,IACzD,CAAA;AAAA,IAEA,MAAM,MAAA,CAAO,IAAA,EAAkB,EAAA,EAAY,UAAA,EAAsC;AAC7E,MAAA,IAAI,CAAC,KAAK,OAAO,KAAA;AAEjB,MAAA,MAAM,OAAA,GAAU,MAAM,GAAA,CAAI,MAAA,CAAO,MAAM,EAAE,CAAA;AACzC,MAAA,IAAI,OAAA,EAAS;AACT,QAAA,KAAA,CAAM,GAAA,CAAI,IAAI,CAAA,EAAG,MAAA,CAAO,EAAE,CAAA;AAAA,MAC9B;AACA,MAAA,OAAO,OAAA;AAAA,IACX,CAAA;AAAA,IAEA,GAAA,CAAsB,MAAkB,EAAA,EAA2B;AAC/D,MAAA,OAAO,KAAA,CAAM,GAAA,CAAI,IAAI,CAAA,EAAG,IAAI,EAAE,CAAA;AAAA,IAClC,CAAA;AAAA,IAEA,OAAyB,IAAA,EAAuB;AAC5C,MAAA,OAAO,KAAA,CAAM,KAAK,KAAA,CAAM,GAAA,CAAI,IAAI,CAAA,EAAG,MAAA,EAAO,IAAK,EAAE,CAAA;AAAA,IACrD,CAAA;AAAA,IAEA,OAAO,KAAA,EAAyB;AAC5B,MAAA,MAAM,eAAA,GAAkB,MAAM,WAAA,EAAY;AAC1C,MAAA,MAAM,UAAoB,EAAC;AAC3B,MAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAE7B,MAAA,KAAA,MAAW,SAAA,IAAa,KAAA,CAAM,MAAA,EAAO,EAAG;AACpC,QAAA,KAAA,MAAW,MAAA,IAAU,SAAA,CAAU,MAAA,EAAO,EAAG;AACrC,UAAA,IAAI,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,EAAE,CAAA,EAAG;AAGzB,UAAA,IAAI,OAAO,IAAA,CAAK,WAAA,EAAY,CAAE,QAAA,CAAS,eAAe,CAAA,EAAG;AACrD,YAAA,OAAA,CAAQ,KAAK,MAAM,CAAA;AACnB,YAAA,IAAA,CAAK,GAAA,CAAI,OAAO,EAAE,CAAA;AAClB,YAAA;AAAA,UACJ;AAGA,UAAA,MAAM,SAAU,MAAA,CAA+C,WAAA;AAC/D,UAAA,IAAI,MAAA,EAAQ,IAAA,CAAK,CAAC,CAAA,KAAc,CAAA,CAAE,aAAY,CAAE,QAAA,CAAS,eAAe,CAAC,CAAA,EAAG;AACxE,YAAA,OAAA,CAAQ,KAAK,MAAM,CAAA;AACnB,YAAA,IAAA,CAAK,GAAA,CAAI,OAAO,EAAE,CAAA;AAAA,UACtB;AAAA,QACJ;AAAA,MACJ;AAEA,MAAA,OAAO,OAAA;AAAA,IACX,CAAA;AAAA,IAEA,iBAAiB,QAAA,EAAsC;AACnD,MAAA,MAAM,UAAA,GAAa,QAAA,CAAS,WAAA,EAAY,CAAE,IAAA,EAAK;AAE/C,MAAA,KAAA,MAAW,SAAA,IAAa,KAAA,CAAM,MAAA,EAAO,EAAG;AACpC,QAAA,KAAA,MAAW,MAAA,IAAU,SAAA,CAAU,MAAA,EAAO,EAAG;AACrC,UAAA,MAAM,SAAU,MAAA,CAA+C,WAAA;AAC/D,UAAA,IAAI,MAAA,EAAQ,KAAK,CAAC,CAAA,KAAc,EAAE,WAAA,EAAY,KAAM,UAAU,CAAA,EAAG;AAC7D,YAAA,OAAO,MAAA;AAAA,UACX;AAAA,QACJ;AAAA,MACJ;AAEA,MAAA,OAAO,MAAA;AAAA,IACX,CAAA;AAAA,IAEA,KAAA,GAAc;AACV,MAAA,SAAA,EAAU;AACV,MAAA,GAAA,GAAM,MAAA;AAAA,IACV,CAAA;AAAA,IAEA,iBAAA,CAAkB,IAAA,EAAkB,EAAA,EAAY,WAAA,EAA2C;AACvF,MAAA,MAAM,OAAA,GAAU,kBAAkB,IAAI,CAAA;AACtC,MAAA,MAAM,YAAA,GAAe,WAAA,CAAY,MAAA,GAAS,CAAA,GAAI,WAAA,GAAc,iBAAA;AAC5D,MAAA,MAAM,SAAS,KAAA,CAAM,GAAA,CAAI,IAAI,CAAA,EAAG,IAAI,EAAE,CAAA;AAEtC,MAAA,KAAA,MAAW,cAAc,CAAC,GAAG,YAAY,CAAA,CAAE,SAAQ,EAAG;AAClD,QAAA,MAAM,SAAA,GAAY,IAAA,CAAK,IAAA,CAAK,UAAA,EAAY,OAAO,CAAA;AAG/C,QAAA,IAAI,MAAA,EAAQ;AACR,UAAA,MAAM,YAAA,GAAe,0BAA0B,MAA6C,CAAA;AAC5F,UAAA,KAAA,MAAW,GAAA,IAAO,CAAC,OAAA,EAAS,MAAM,CAAA,EAAG;AACjC,YAAA,MAAM,QAAA,GAAW,KAAK,IAAA,CAAK,SAAA,EAAW,GAAG,YAAY,CAAA,EAAG,GAAG,CAAA,CAAE,CAAA;AAC7D,YAAA,IAAI,WAAW,QAAQ,CAAA,IAAK,SAAS,QAAQ,CAAA,CAAE,QAAO,EAAG;AACrD,cAAA,OAAO,QAAA;AAAA,YACX;AAAA,UACJ;AAAA,QACJ;AAGA,QAAA,KAAA,MAAW,GAAA,IAAO,CAAC,OAAA,EAAS,MAAM,CAAA,EAAG;AACjC,UAAA,MAAM,QAAA,GAAW,KAAK,IAAA,CAAK,SAAA,EAAW,GAAG,EAAE,CAAA,EAAG,GAAG,CAAA,CAAE,CAAA;AACnD,UAAA,IAAI,WAAW,QAAQ,CAAA,IAAK,SAAS,QAAQ,CAAA,CAAE,QAAO,EAAG;AACrD,YAAA,OAAO,QAAA;AAAA,UACX;AAAA,QACJ;AAGA,QAAA,IAAI,UAAA,CAAW,SAAS,CAAA,EAAG;AACvB,UAAA,MAAM,MAAA,GAAS,EAAA,CAAG,SAAA,CAAU,CAAA,EAAG,CAAC,CAAA;AAChC,UAAA,IAAI;AACA,YAAA,MAAM,KAAA,GAAQ,YAAY,SAAS,CAAA;AACnC,YAAA,MAAM,QAAQ,KAAA,CAAM,IAAA;AAAA,cAAK,CAAA,CAAA,KACrB,CAAA,CAAE,UAAA,CAAW,MAAM,CAAA,KAAM,CAAA,CAAE,QAAA,CAAS,OAAO,CAAA,IAAK,CAAA,CAAE,QAAA,CAAS,MAAM,CAAA;AAAA,aACrE;AACA,YAAA,IAAI,KAAA,EAAO;AACP,cAAA,OAAO,IAAA,CAAK,IAAA,CAAK,SAAA,EAAW,KAAK,CAAA;AAAA,YACrC;AAAA,UACJ,CAAA,CAAA,MAAQ;AAAA,UAA8B;AAAA,QAC1C;AAAA,MACJ;AAEA,MAAA,OAAO,MAAA;AAAA,IACX;AAAA,GACJ;AACJ;;;;"}
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
+
import { BaseEntity } from '@utilarium/overcontext';
|
|
1
2
|
import { Person, Project, Company, Term, IgnoredTerm, RedaksjonEntity, RedaksjonEntityType } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Entity filename strategy: first 8 chars of UUID + slug.
|
|
5
|
+
* Produces filenames like `d00acdc4-gerald-corson.yaml`.
|
|
6
|
+
* Falls back to entity.id when no slug is present.
|
|
7
|
+
*/
|
|
8
|
+
export declare const redaksjonFilenameStrategy: (entity: BaseEntity) => string;
|
|
2
9
|
export type { Person, Project, Company, Term, IgnoredTerm, RedaksjonEntity };
|
|
3
10
|
export type EntityType = RedaksjonEntityType;
|
|
4
11
|
export type Entity = RedaksjonEntity;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/storage/adapter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/storage/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,UAAU,EACb,MAAM,wBAAwB,CAAC;AAKhC,OAAO,KAAK,EACR,MAAM,EACN,OAAO,EACP,OAAO,EACP,IAAI,EACJ,WAAW,EACX,eAAe,EACf,mBAAmB,EACtB,MAAM,UAAU,CAAC;AAKlB;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,GAAI,QAAQ,UAAU,KAAG,MAO9D,CAAC;AAGF,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,eAAe,EAAE,CAAC;AAC7E,MAAM,MAAM,UAAU,GAAG,mBAAmB,CAAC;AAC7C,MAAM,MAAM,MAAM,GAAG,eAAe,CAAC;AAErC;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1E,GAAG,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC;IACnE,MAAM,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,CAAC,EAAE,CAAC;IAChD,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAChC,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IACvD,KAAK,IAAI,IAAI,CAAC;IACd,iBAAiB,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAAC;CAC5F;AAeD,eAAO,MAAM,MAAM,QAAO,eA0MzB,CAAC"}
|
package/dist/storage/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { create, type StorageInstance, type Entity, type EntityType } from './adapter';
|
|
1
|
+
export { create, redaksjonFilenameStrategy, type StorageInstance, type Entity, type EntityType } from './adapter';
|
|
2
2
|
export { create as createStandaloneStorage } from './storage';
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AACA,OAAO,EACH,MAAM,EACN,KAAK,eAAe,EACpB,KAAK,MAAM,EACX,KAAK,UAAU,EAClB,MAAM,WAAW,CAAC;AAGnB,OAAO,EAAE,MAAM,IAAI,uBAAuB,EAAE,MAAM,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AACA,OAAO,EACH,MAAM,EACN,yBAAyB,EACzB,KAAK,eAAe,EACpB,KAAK,MAAM,EACX,KAAK,UAAU,EAClB,MAAM,WAAW,CAAC;AAGnB,OAAO,EAAE,MAAM,IAAI,uBAAuB,EAAE,MAAM,WAAW,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redaksjon/context",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"description": "Shared context schemas for redaksjon tools",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"prepublishOnly": "npm run clean && npm run build"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@utilarium/overcontext": "^0.0.
|
|
52
|
+
"@utilarium/overcontext": "^0.0.6",
|
|
53
53
|
"js-yaml": "^4.1.0",
|
|
54
54
|
"zod": "^4.0.0"
|
|
55
55
|
},
|
|
@@ -74,5 +74,8 @@
|
|
|
74
74
|
},
|
|
75
75
|
"peerDependencies": {
|
|
76
76
|
"zod": "^4.0.0"
|
|
77
|
+
},
|
|
78
|
+
"overrides": {
|
|
79
|
+
"@microsoft/api-extractor": "7.56.3"
|
|
77
80
|
}
|
|
78
81
|
}
|