@cogenta/cli 0.1.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/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +31 -0
- package/dist/bin.js.map +1 -0
- package/dist/commands/doctor.d.ts +45 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +147 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/generate.d.ts +19 -0
- package/dist/commands/generate.d.ts.map +1 -0
- package/dist/commands/generate.js +60 -0
- package/dist/commands/generate.js.map +1 -0
- package/dist/commands/import.d.ts +22 -0
- package/dist/commands/import.d.ts.map +1 -0
- package/dist/commands/import.js +77 -0
- package/dist/commands/import.js.map +1 -0
- package/dist/commands/migrate.d.ts +38 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +272 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/serve.d.ts +81 -0
- package/dist/commands/serve.d.ts.map +1 -0
- package/dist/commands/serve.js +515 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/commands/skin.d.ts +24 -0
- package/dist/commands/skin.d.ts.map +1 -0
- package/dist/commands/skin.js +199 -0
- package/dist/commands/skin.js.map +1 -0
- package/dist/commands/users.d.ts +22 -0
- package/dist/commands/users.d.ts.map +1 -0
- package/dist/commands/users.js +107 -0
- package/dist/commands/users.js.map +1 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +244 -0
- package/dist/index.js.map +1 -0
- package/dist/output.d.ts +17 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +39 -0
- package/dist/output.js.map +1 -0
- package/package.json +53 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { readdir, readFile } from 'node:fs/promises';
|
|
3
|
+
import { dirname, join, resolve as resolvePath } from 'node:path';
|
|
4
|
+
import process from 'node:process';
|
|
5
|
+
import { pathToFileURL } from 'node:url';
|
|
6
|
+
import { CogentaError, createDatabaseRegistry, createLogger, createMigrator, isCogentaError, loadConfig, } from '@cogenta/core';
|
|
7
|
+
/** The directory a project keeps its migrations in, relative to the config file. */
|
|
8
|
+
export const MIGRATIONS_DIRECTORY = 'migrations';
|
|
9
|
+
/**
|
|
10
|
+
* Only ESM sources. `.cjs` is deliberately absent: Cogenta is ESM-only, and a
|
|
11
|
+
* migration that needs a CommonJS loader would be the one place it leaked back
|
|
12
|
+
* in. `.ts` works from Node 22.18, which strips types on import.
|
|
13
|
+
*/
|
|
14
|
+
const MIGRATION_EXTENSIONS = ['.js', '.mjs', '.ts', '.mts'];
|
|
15
|
+
const USAGE = `Usage
|
|
16
|
+
cogenta migrate status List every migration and its state
|
|
17
|
+
cogenta migrate up [--to <id>] Apply the pending migrations
|
|
18
|
+
cogenta migrate down [--steps <n>|--to <id>] Revert applied migrations
|
|
19
|
+
|
|
20
|
+
Options
|
|
21
|
+
--confirm-destructive The impact of every destructive migration has been read
|
|
22
|
+
--backup-verified A backup was taken and verified to restore
|
|
23
|
+
`;
|
|
24
|
+
function isBody(value) {
|
|
25
|
+
return typeof value === 'function';
|
|
26
|
+
}
|
|
27
|
+
function invalidMigration(file, reason) {
|
|
28
|
+
return new CogentaError({
|
|
29
|
+
code: 'MIGRATION_FAILED',
|
|
30
|
+
message: `${file} is not a migration: ${reason}.`,
|
|
31
|
+
hint: 'A migration file default-exports an object with an `up(tx)` and a `down(tx)`, both returning a promise. `down` is required — every migration is reversible.',
|
|
32
|
+
details: { file },
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Turns one loaded module into a `Migration`, refusing anything that only looks
|
|
37
|
+
* like one.
|
|
38
|
+
*
|
|
39
|
+
* The id defaults to the file name without its extension, which is why files are
|
|
40
|
+
* sorted by name: the on-disk order and the applied order are then the same
|
|
41
|
+
* thing, and there is no second ordering to keep in sync.
|
|
42
|
+
*/
|
|
43
|
+
function toMigration(exported, file, checksum) {
|
|
44
|
+
if (typeof exported !== 'object' || exported === null) {
|
|
45
|
+
throw invalidMigration(file, 'its default export is not an object');
|
|
46
|
+
}
|
|
47
|
+
const record = exported;
|
|
48
|
+
const { up, down } = record;
|
|
49
|
+
if (!isBody(up))
|
|
50
|
+
throw invalidMigration(file, 'it has no `up` function');
|
|
51
|
+
if (!isBody(down))
|
|
52
|
+
throw invalidMigration(file, 'it has no `down` function');
|
|
53
|
+
const id = typeof record.id === 'string' ? record.id : file.replace(/\.[^.]+$/, '');
|
|
54
|
+
const name = record.name;
|
|
55
|
+
const impact = record.impact;
|
|
56
|
+
const duration = record.estimatedDurationMs;
|
|
57
|
+
return {
|
|
58
|
+
id,
|
|
59
|
+
...(typeof name === 'string' ? { name } : {}),
|
|
60
|
+
// The file's own checksum wins over a declared one: the point is to detect a
|
|
61
|
+
// file that changed after it was applied, and a hand-written checksum would
|
|
62
|
+
// be edited along with the file it is supposed to guard.
|
|
63
|
+
checksum,
|
|
64
|
+
...(record.destructive === true ? { destructive: true } : {}),
|
|
65
|
+
...(typeof impact === 'string' ? { impact } : {}),
|
|
66
|
+
...(typeof duration === 'number' ? { estimatedDurationMs: duration } : {}),
|
|
67
|
+
up,
|
|
68
|
+
down,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Loads every migration from a directory, in file-name order.
|
|
73
|
+
*
|
|
74
|
+
* A missing directory is not an error. L0 ships no business schema at all, so a
|
|
75
|
+
* fresh project legitimately has nothing to migrate, and failing there would
|
|
76
|
+
* make `migrate status` unusable exactly when an operator wants to check.
|
|
77
|
+
*/
|
|
78
|
+
export async function loadMigrations(directory) {
|
|
79
|
+
let names;
|
|
80
|
+
try {
|
|
81
|
+
names = await readdir(directory);
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return [];
|
|
85
|
+
}
|
|
86
|
+
const files = names
|
|
87
|
+
.filter((name) => !name.endsWith('.d.ts') && MIGRATION_EXTENSIONS.some((suffix) => name.endsWith(suffix)))
|
|
88
|
+
.sort((a, b) => a.localeCompare(b));
|
|
89
|
+
const migrations = [];
|
|
90
|
+
for (const file of files) {
|
|
91
|
+
const path = join(directory, file);
|
|
92
|
+
// Hashing the source, not the exported object: it is the source that an
|
|
93
|
+
// operator edits, and the engine refuses a migration whose hash moved after
|
|
94
|
+
// it was applied.
|
|
95
|
+
const checksum = createHash('sha256')
|
|
96
|
+
.update(await readFile(path))
|
|
97
|
+
.digest('hex');
|
|
98
|
+
let module;
|
|
99
|
+
try {
|
|
100
|
+
module = (await import(pathToFileURL(path).href));
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
throw new CogentaError({
|
|
104
|
+
code: 'MIGRATION_FAILED',
|
|
105
|
+
message: `Could not load ${path}: ${error instanceof Error ? error.message : String(error)}`,
|
|
106
|
+
hint: path.endsWith('.ts')
|
|
107
|
+
? 'A TypeScript migration needs a Node runtime that strips types, which means Node 22.18 or later. Rename it to .mjs on an older one.'
|
|
108
|
+
: 'Check the file for a syntax error, and that every import it uses is installed.',
|
|
109
|
+
cause: error,
|
|
110
|
+
details: { path },
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
migrations.push(toMigration(module.default, file, checksum));
|
|
114
|
+
}
|
|
115
|
+
return migrations;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Reads back the destructive migrations the engine named when it refused.
|
|
119
|
+
*
|
|
120
|
+
* The refusal is only useful if the operator can see *what* would be lost, so
|
|
121
|
+
* the details the engine attached are unpacked rather than summarised away.
|
|
122
|
+
*/
|
|
123
|
+
function destructiveDetails(error) {
|
|
124
|
+
const listed = error.details?.migrations;
|
|
125
|
+
if (!Array.isArray(listed))
|
|
126
|
+
return [];
|
|
127
|
+
const entries = listed;
|
|
128
|
+
return entries.flatMap((entry) => {
|
|
129
|
+
if (typeof entry !== 'object' || entry === null)
|
|
130
|
+
return [];
|
|
131
|
+
const record = entry;
|
|
132
|
+
const id = record.id;
|
|
133
|
+
const impact = record.impact;
|
|
134
|
+
if (typeof id !== 'string')
|
|
135
|
+
return [];
|
|
136
|
+
return [{ id, impact: typeof impact === 'string' ? impact : 'not documented' }];
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
function formatStatus(rows, out) {
|
|
140
|
+
out.heading('Migrations');
|
|
141
|
+
if (rows.length === 0) {
|
|
142
|
+
out.warn('No migration found. Add files to the migrations/ directory of the project.');
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
for (const row of rows) {
|
|
146
|
+
const label = row.name === row.id ? row.id : `${row.id} — ${row.name}`;
|
|
147
|
+
if (!row.applied) {
|
|
148
|
+
out.warn(`${label} — pending`);
|
|
149
|
+
}
|
|
150
|
+
else if (row.checksumMismatch) {
|
|
151
|
+
out.bad(`${label} — applied ${row.appliedAt ?? 'at an unknown time'}, but changed since`);
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
out.ok(`${label} — applied ${row.appliedAt ?? 'at an unknown time'} (${row.durationMs ?? 0}ms)`);
|
|
155
|
+
}
|
|
156
|
+
if (row.destructive)
|
|
157
|
+
out.detail(`destructive: ${row.impact ?? 'impact not documented'}`);
|
|
158
|
+
if (row.checksumMismatch) {
|
|
159
|
+
out.detail('The file no longer matches what ran here. Write a new migration instead.');
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function formatOutcomes(outcomes, out) {
|
|
164
|
+
for (const outcome of outcomes) {
|
|
165
|
+
const verb = outcome.direction === 'up' ? 'applied' : 'reverted';
|
|
166
|
+
out.ok(`${verb} ${outcome.id} (${outcome.durationMs}ms)`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/** Opens the database named by the configuration, exactly the way doctor does. */
|
|
170
|
+
async function withDatabase(options, logger, use) {
|
|
171
|
+
const env = options.env ?? process.env;
|
|
172
|
+
const loaded = await loadConfig({
|
|
173
|
+
...(options.cwd === undefined ? {} : { cwd: options.cwd }),
|
|
174
|
+
env,
|
|
175
|
+
});
|
|
176
|
+
// Migrations belong to the project, so they sit next to its configuration
|
|
177
|
+
// file — not next to whatever directory the command happened to be run from.
|
|
178
|
+
const projectRoot = loaded.path === null ? resolvePath(options.cwd ?? process.cwd()) : dirname(loaded.path);
|
|
179
|
+
const selection = await createDatabaseRegistry({ logger }).select(loaded.config.database);
|
|
180
|
+
try {
|
|
181
|
+
return await use(selection.instance, projectRoot);
|
|
182
|
+
}
|
|
183
|
+
finally {
|
|
184
|
+
await selection.dispose();
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Runs one `migrate` subcommand and returns its exit code.
|
|
189
|
+
*
|
|
190
|
+
* 0 succeeded, 1 the database or a migration said no, 2 the command line was
|
|
191
|
+
* wrong. Nothing calls `process.exit` and nothing writes to a stream directly,
|
|
192
|
+
* so a test drives this exactly as a shell does.
|
|
193
|
+
*/
|
|
194
|
+
export async function runMigrate(options) {
|
|
195
|
+
const { out, stderr } = options;
|
|
196
|
+
if (options.subcommand === undefined) {
|
|
197
|
+
stderr(`cogenta migrate needs a subcommand.\n\n${USAGE}`);
|
|
198
|
+
return 2;
|
|
199
|
+
}
|
|
200
|
+
if (options.subcommand !== 'status' &&
|
|
201
|
+
options.subcommand !== 'up' &&
|
|
202
|
+
options.subcommand !== 'down') {
|
|
203
|
+
stderr(`Unknown subcommand "${options.subcommand}".\n\n${USAGE}`);
|
|
204
|
+
return 2;
|
|
205
|
+
}
|
|
206
|
+
const subcommand = options.subcommand;
|
|
207
|
+
// Silent unless asked: a human report on stdout must not be interleaved with
|
|
208
|
+
// NDJSON. `--verbose` sends the structured lines to stderr instead.
|
|
209
|
+
const logger = options.logger ?? createLogger({ level: 'silent' });
|
|
210
|
+
try {
|
|
211
|
+
return await withDatabase(options, logger, async (db, projectRoot) => {
|
|
212
|
+
const directory = options.directory ?? join(projectRoot, MIGRATIONS_DIRECTORY);
|
|
213
|
+
const migrations = await loadMigrations(directory);
|
|
214
|
+
const migrator = createMigrator({ db, migrations, logger });
|
|
215
|
+
const run = {
|
|
216
|
+
...(options.to === undefined ? {} : { to: options.to }),
|
|
217
|
+
...(options.confirmDestructive === true ? { confirmDestructive: true } : {}),
|
|
218
|
+
...(options.backupVerified === true ? { backupVerified: true } : {}),
|
|
219
|
+
};
|
|
220
|
+
if (subcommand === 'status') {
|
|
221
|
+
const rows = await migrator.status();
|
|
222
|
+
formatStatus(rows, out);
|
|
223
|
+
const pending = rows.filter((row) => !row.applied).length;
|
|
224
|
+
const drifted = rows.filter((row) => row.checksumMismatch).length;
|
|
225
|
+
out.line();
|
|
226
|
+
out.line(`${rows.length - pending} applied, ${pending} pending.`);
|
|
227
|
+
// A drifted checksum is a real fault, not a note: two environments ran
|
|
228
|
+
// different SQL under the same id, and a deployment script must notice.
|
|
229
|
+
return drifted === 0 ? 0 : 1;
|
|
230
|
+
}
|
|
231
|
+
const outcomes = subcommand === 'up'
|
|
232
|
+
? await migrator.up(run)
|
|
233
|
+
: await migrator.down({
|
|
234
|
+
...run,
|
|
235
|
+
...(options.steps === undefined ? {} : { steps: options.steps }),
|
|
236
|
+
});
|
|
237
|
+
out.heading(subcommand === 'up' ? 'Applied' : 'Reverted');
|
|
238
|
+
formatOutcomes(outcomes, out);
|
|
239
|
+
out.line();
|
|
240
|
+
out.line(outcomes.length === 0
|
|
241
|
+
? subcommand === 'up'
|
|
242
|
+
? 'Nothing to apply.'
|
|
243
|
+
: 'Nothing to revert.'
|
|
244
|
+
: `${outcomes.length} migration(s) ${subcommand === 'up' ? 'applied' : 'reverted'}.`);
|
|
245
|
+
return 0;
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
catch (error) {
|
|
249
|
+
if (isCogentaError(error) && error.code === 'MIGRATION_DESTRUCTIVE') {
|
|
250
|
+
// The engine already refused. The CLI's job is to make the refusal
|
|
251
|
+
// actionable: name what would be lost, then say the two flags out loud.
|
|
252
|
+
stderr(`${error.message}\n`);
|
|
253
|
+
for (const entry of destructiveDetails(error)) {
|
|
254
|
+
stderr(` ${entry.id}: ${entry.impact}\n`);
|
|
255
|
+
}
|
|
256
|
+
if (error.hint !== undefined)
|
|
257
|
+
stderr(`\n${error.hint}\n`);
|
|
258
|
+
stderr('\nRe-run with --confirm-destructive --backup-verified once both are true.\n');
|
|
259
|
+
return 1;
|
|
260
|
+
}
|
|
261
|
+
if (isCogentaError(error)) {
|
|
262
|
+
stderr(`${error.code}: ${error.message}\n`);
|
|
263
|
+
if (error.hint !== undefined)
|
|
264
|
+
stderr(`${error.hint}\n`);
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
stderr(`${error instanceof Error ? error.stack : String(error)}\n`);
|
|
268
|
+
}
|
|
269
|
+
return 1;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
//# sourceMappingURL=migrate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { type IncomingMessage, type ServerResponse } from 'node:http';
|
|
2
|
+
import { type AgentsRouter, type AuditRouter, type AuthRouter, createContentGateway, type MediaRouter, type RestRouter } from '@cogenta/api';
|
|
3
|
+
import { type AuthStore } from '@cogenta/auth';
|
|
4
|
+
import { type DatabaseHandle, type HealthReport, type Logger, type MediaStore, type StorageDriver } from '@cogenta/core';
|
|
5
|
+
import { type CollectionDefinition, type SchemaDocument } from '@cogenta/schema';
|
|
6
|
+
import type { GraphQLSchema } from 'graphql';
|
|
7
|
+
import type { Output, Writer } from '../output.js';
|
|
8
|
+
/**
|
|
9
|
+
* Loads a project's content model.
|
|
10
|
+
*
|
|
11
|
+
* `cogenta.schema.ts` next to the config file, default-exporting the
|
|
12
|
+
* collections — the same "one file, dynamic-imported, next to the config"
|
|
13
|
+
* convention `migrate.ts` already established for migrations. A project with
|
|
14
|
+
* none is invalid here, unlike a project with no migrations: a site with zero
|
|
15
|
+
* collections has nothing to serve.
|
|
16
|
+
*/
|
|
17
|
+
export declare function loadCollections(projectRoot: string): Promise<readonly CollectionDefinition[]>;
|
|
18
|
+
interface Site {
|
|
19
|
+
readonly db: DatabaseHandle;
|
|
20
|
+
readonly auth: AuthStore;
|
|
21
|
+
readonly restRouter: RestRouter;
|
|
22
|
+
readonly authRouter: AuthRouter;
|
|
23
|
+
readonly mediaRouter: MediaRouter;
|
|
24
|
+
readonly auditRouter: AuditRouter;
|
|
25
|
+
/** Only set when a caller passes `agents` into `assembleSite` — no site constructs one today (R2: agents are optional, not a hard dependency of the CMS). */
|
|
26
|
+
readonly agentsRouter?: AgentsRouter;
|
|
27
|
+
/** Not routed through `mediaRouter`: serving a binary body is outside the JSON-only `RestResponse` shape, so the file route is handled directly (same treatment `/api/schema` already gets). */
|
|
28
|
+
readonly mediaStore: MediaStore;
|
|
29
|
+
readonly storage: StorageDriver;
|
|
30
|
+
readonly graphqlSchema: GraphQLSchema;
|
|
31
|
+
readonly gateway: ReturnType<typeof createContentGateway>;
|
|
32
|
+
/** `.cogenta/schema.json`'s in-memory twin — the admin's only view of the collections (never the schema modules themselves, which are Node code). */
|
|
33
|
+
readonly schemaDocument: SchemaDocument;
|
|
34
|
+
/** Live, not cached: a driver that just went down must show as down the next time this is called, not until the process restarts. */
|
|
35
|
+
readonly health: () => Promise<{
|
|
36
|
+
readonly database: HealthReport;
|
|
37
|
+
readonly storage: HealthReport;
|
|
38
|
+
}>;
|
|
39
|
+
dispose(): Promise<void>;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Builds the Node request handler from an already-assembled site.
|
|
43
|
+
*
|
|
44
|
+
* All the actual logic — routing, permissions, actor resolution — was already
|
|
45
|
+
* tested as plain values in `@cogenta/api` and `@cogenta/auth`; this function
|
|
46
|
+
* is deliberately just the translation from `IncomingMessage`/`ServerResponse`
|
|
47
|
+
* to that shape and back, so a serverless adapter later is the same kind of
|
|
48
|
+
* thin layer rather than a second implementation of any of it.
|
|
49
|
+
*/
|
|
50
|
+
export declare function createRequestListener(site: Site, logger: Logger): (req: IncomingMessage, res: ServerResponse) => Promise<void>;
|
|
51
|
+
export interface ServeOptions {
|
|
52
|
+
readonly cwd?: string;
|
|
53
|
+
readonly env?: Record<string, string | undefined>;
|
|
54
|
+
readonly logger?: Logger;
|
|
55
|
+
readonly out: Output;
|
|
56
|
+
readonly stderr: Writer;
|
|
57
|
+
readonly port?: number;
|
|
58
|
+
readonly host?: string;
|
|
59
|
+
/** Resolves once the server is actually listening — tests need the OS-assigned port. */
|
|
60
|
+
onListening?: (address: {
|
|
61
|
+
port: number;
|
|
62
|
+
host: string;
|
|
63
|
+
}) => void;
|
|
64
|
+
/** Stops the server and disposes the database when aborted. */
|
|
65
|
+
readonly signal?: AbortSignal;
|
|
66
|
+
/**
|
|
67
|
+
* "Commencer par une démo en lecture seule" (L9 tâche 12, playground). Every
|
|
68
|
+
* write attempt refuses with `CONTENT_READ_ONLY`; reads are unaffected.
|
|
69
|
+
* Scheduling a periodic reset back to demo content is an operational
|
|
70
|
+
* decision for whoever deploys a read-only instance, not made here.
|
|
71
|
+
*/
|
|
72
|
+
readonly readOnly?: boolean;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Runs until `options.signal` aborts. Returns 0 on a clean shutdown, 1 if
|
|
76
|
+
* startup failed — nothing here calls `process.exit` (same convention as
|
|
77
|
+
* every other command), so an embedder controls the process lifecycle.
|
|
78
|
+
*/
|
|
79
|
+
export declare function runServe(options: ServeOptions): Promise<number>;
|
|
80
|
+
export {};
|
|
81
|
+
//# sourceMappingURL=serve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/commands/serve.ts"],"names":[],"mappings":"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"}
|