diff --git a/packages/storage/package.json b/packages/storage/package.json new file mode 100644 index 0000000..f85d90b --- /dev/null +++ b/packages/storage/package.json @@ -0,0 +1,19 @@ +{ + "name": "@glowtrack/storage", + "private": true, + "version": "0.0.0", + "type": "module", + "description": "Storage layer for GlowTrack (models, IndexedDB, export/import)", + "scripts": { + "test": "vitest run", + "test:unit": "vitest run", + "test:ui": "vitest" + }, + "dependencies": { + "ajv": "^8.17.1" + }, + "devDependencies": { + "typescript": "^5.5.4", + "vitest": "^2.1.1" + } +} diff --git a/packages/storage/tests/contract/export.spec.ts b/packages/storage/tests/contract/export.spec.ts new file mode 100644 index 0000000..1d2d2df --- /dev/null +++ b/packages/storage/tests/contract/export.spec.ts @@ -0,0 +1,42 @@ +import { describe, it, expect } from 'vitest'; +import Ajv, { type ErrorObject } from 'ajv'; +import fs from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +// Implementation placeholder import; will fail until implemented per tasks T016, T018 +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-expect-error - module not implemented yet +import { exportToJson } from '../../src/export'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const repoRoot = path.resolve(__dirname, '../../../../'); +const schemaPath = path.join( + repoRoot, + 'specs/001-glowtrack-a-mood/contracts/export.schema.json' +); + +describe('Contract: export JSON schema (T009)', () => { + it('exportToJson() output should validate against export.schema.json', async () => { + const schemaJson = JSON.parse(fs.readFileSync(schemaPath, 'utf-8')); + const ajv = new Ajv({ allErrors: true, strict: true }); + const validate = ajv.compile(schemaJson); + + // Minimal call; actual implementation will read from DB/models + // For now, call without args or with undefined to get full export + const data = await exportToJson(); + const valid = validate(data); + + if (!valid) { + // Show helpful aggregated errors + const errors = (validate.errors || []) + .map((e: ErrorObject) => `${e.instancePath || '/'} ${e.message}`) + .join('\n'); + // Intentionally using expect(...).toBe(true) so test fails until impl is ready + expect({ valid, errors }).toEqual({ valid: true, errors: '' }); + } + + expect(valid).toBe(true); + }); +}); diff --git a/packages/storage/tsconfig.json b/packages/storage/tsconfig.json new file mode 100644 index 0000000..48cb13a --- /dev/null +++ b/packages/storage/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "module": "ESNext", + "target": "ES2022", + "moduleResolution": "Bundler", + "types": ["node", "vitest/globals"], + "strict": true, + "skipLibCheck": true, + "esModuleInterop": true, + "resolveJsonModule": true, + "noEmit": true + }, + "include": ["tests", "src"] +} diff --git a/result b/result deleted file mode 120000 index 7edb235..0000000 --- a/result +++ /dev/null @@ -1 +0,0 @@ -/nix/store/a7d43vv7g79mi2da7b977vqy0cqnaa45-glowtrack-app-0.0.0 \ No newline at end of file diff --git a/specs/001-glowtrack-a-mood/tasks.md b/specs/001-glowtrack-a-mood/tasks.md index 2c3aa41..7ef3ce9 100644 --- a/specs/001-glowtrack-a-mood/tasks.md +++ b/specs/001-glowtrack-a-mood/tasks.md @@ -68,7 +68,7 @@ Paths below are absolute to this repo. ## Phase 3.2: Tests First (TDD) — MUST FAIL before 3.3 Contract files from /home/jawz/Development/Projects/GlowTrack/specs/001-glowtrack-a-mood/contracts/ → contract tests [P] -- [ ] T009 [P] Contract test: export JSON schema +- [X] T009 [P] Contract test: export JSON schema - Create /home/jawz/Development/Projects/GlowTrack/packages/storage/tests/contract/export.spec.ts - Use Ajv to validate object from exportToJson() against export.schema.json at /home/jawz/Development/Projects/GlowTrack/specs/001-glowtrack-a-mood/contracts/export.schema.json - Expect failure until export service implemented