Skip to content

Commit 19dc525

Browse files
authored
Add async processing of PDF imports and other general improvements (#22)
1 parent 1be4643 commit 19dc525

85 files changed

Lines changed: 4360 additions & 424 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CLAUDE.md

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,45 @@ common → (no dependencies)
114114
- **Testing**: Vitest (unit/integration), Playwright (E2E), @vitest/browser (Storybook)
115115
- **Language**: TypeScript throughout
116116

117+
### Development Workflow with Conditional Exports
118+
119+
This monorepo uses **conditional exports** for zero-build development workflow:
120+
121+
**In Development:**
122+
- Library packages (common, database, forms-core, auth, design) are consumed directly from TypeScript source files
123+
- No build step required when editing library code - changes are immediately reflected in consuming apps
124+
- Hot module replacement (HMR) works instantly across package boundaries
125+
- Consumer apps (server, spotlight, etc.) are configured with `customConditions: ["development"]` in tsconfig.json
126+
- Vite/Astro resolve the `development` export condition to use `./src/**/*.ts` files
127+
128+
**In Production:**
129+
- Library packages are built and published from `dist/` folders
130+
- Production builds use optimized, transpiled artifacts
131+
- The `development` export condition is not used
132+
133+
**How it Works:**
134+
Each library package.json has exports like:
135+
```json
136+
{
137+
"exports": {
138+
".": {
139+
"development": {
140+
"types": "./src/index.ts",
141+
"import": "./src/index.ts"
142+
},
143+
"types": "./dist/index.d.ts",
144+
"import": "./dist/index.js"
145+
}
146+
}
147+
}
148+
```
149+
150+
**Build Scripts:**
151+
- **Important:** The `design` package requires CSS/SASS compilation:
152+
- First time setup: Run `pnpm --filter @flexion/forms-design build:styles` (one-time)
153+
- Or use `pnpm dev` which includes `dev:styles` (gulp watch) for the design package
154+
- Production builds (`pnpm build`) are still required before publishing
155+
117156
### Pattern System
118157

119158
Patterns are the platform's primary building blocks. Each pattern has:
@@ -137,5 +176,9 @@ Use `describeDatabase` helper for testing database routines against both SQLite
137176
- Node version is specified in `.nvmrc` - use `nvm install` to ensure correct version
138177
- Requires Docker or Podman for running tests (PostgreSQL container)
139178
- Playwright version must match exactly (1.51.1) across local and CI environments
140-
- Build is required before running `pnpm dev`
179+
- **Development**:
180+
- No TypeScript build required - packages are consumed from source via conditional exports
181+
- CSS/styles must be built once: `pnpm --filter @flexion/forms-design build:styles`
182+
- Or run `pnpm dev` which includes style watching
183+
- **Production/Publishing**: Run `pnpm build` to create optimized artifacts before publishing
141184
- Pre-commit hook runs `pnpm format` automatically

apps/cli/src/cli-controller/forms.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { promises as fs } from 'fs';
22
import { Command } from 'commander';
33

4-
import { commands } from '@flexion/forms-infra-core';
54
import { type Context } from './types.js';
6-
import { createFormService, createFormsRepository, defaultFormConfig, parsePdf as parsePdfCore } from '@flexion/forms-core';
5+
import { createFormService, defaultFormConfig, parsePdf as parsePdfCore } from '@flexion/forms-core';
6+
import { createFormsRepository } from '@flexion/forms-core/repository';
77
import { createTestPdfParser } from '@flexion/forms-core/documents/pdf/context';
88
import { createFilesystemDatabaseContext } from '@flexion/forms-database/context';
99

apps/sandbox/tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
"module": "NodeNext",
55
"moduleResolution": "NodeNext",
66
"outDir": "./dist",
7-
"emitDeclarationOnly": true
7+
"emitDeclarationOnly": true,
8+
"customConditions": ["development"]
89
},
910
"include": ["./src"],
1011
"references": []

apps/server-doj/tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
"module": "NodeNext",
55
"moduleResolution": "NodeNext",
66
"outDir": "./dist",
7-
"emitDeclarationOnly": true
7+
"emitDeclarationOnly": true,
8+
"customConditions": ["development"]
89
},
910
"include": ["./src"],
1011
"references": []

apps/spotlight/astro.config.mjs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ export default defineConfig({
2121
define: {
2222
'import.meta.env.GITHUB': JSON.stringify(githubRepository),
2323
},
24+
resolve: {
25+
conditions: process.env.NODE_ENV === 'production'
26+
? ['production', 'import', 'module', 'browser', 'default']
27+
: ['development', 'import', 'module', 'browser', 'default'],
28+
},
2429
},
2530
});
2631

apps/spotlight/tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
"module": "NodeNext",
77
"moduleResolution": "NodeNext",
88
"jsx": "react",
9-
"resolveJsonModule": true
9+
"resolveJsonModule": true,
10+
"customConditions": ["development"]
1011
},
1112
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.astro"],
1213
"exclude": [".astro", "dist", "node_modules"]

packages/auth/package.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,17 @@
66
"license": "CC0",
77
"main": "dist/index.js",
88
"types": "dist/index.d.js",
9+
"exports": {
10+
".": {
11+
"development": {
12+
"types": "./src/index.ts",
13+
"import": "./src/index.ts"
14+
},
15+
"types": "./dist/index.d.ts",
16+
"import": "./dist/index.js",
17+
"default": "./dist/index.js"
18+
}
19+
},
920
"publishConfig": {
1021
"registry": "https://npm.pkg.github.com"
1122
},

packages/common/package.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,17 @@
66
"license": "CC0",
77
"main": "dist/index.js",
88
"types": "dist/index.d.ts",
9+
"exports": {
10+
".": {
11+
"development": {
12+
"types": "./src/index.ts",
13+
"import": "./src/index.ts"
14+
},
15+
"types": "./dist/index.d.ts",
16+
"import": "./dist/index.js",
17+
"default": "./dist/index.js"
18+
}
19+
},
920
"publishConfig": {
1021
"registry": "https://npm.pkg.github.com"
1122
},
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/**
2+
* @param { import("knex").Knex } knex
3+
* @returns { Promise<void> }
4+
*/
5+
export async function up(knex) {
6+
await knex.schema.createTable('form_jobs', table => {
7+
table.uuid('id').primary();
8+
9+
// Foreign key to forms (CASCADE delete: jobs belong to forms)
10+
table
11+
.uuid('form_id')
12+
.notNullable()
13+
.references('id')
14+
.inTable('forms')
15+
.onDelete('CASCADE');
16+
17+
// Job type - extensible for future operations
18+
table.text('job_type').notNullable();
19+
// Values: 'import-pdf', 'validate-schema', 'publish', 'export', etc.
20+
21+
// Job status - represents operation state
22+
table.text('status').notNullable();
23+
// Values: 'pending', 'processing', 'completed', 'failed'
24+
25+
// Timing information
26+
table.timestamp('created_at').notNullable().defaultTo(knex.fn.now());
27+
table.timestamp('started_at').nullable();
28+
table.timestamp('completed_at').nullable();
29+
30+
// Error tracking
31+
table.text('error_message').nullable();
32+
table.text('error_stack').nullable();
33+
34+
// Job metadata (input parameters, varies by job_type)
35+
// For 'import-pdf': { documentId, fileName, userId }
36+
// For 'publish': { targetEnvironment, publisherId }
37+
table.text('metadata').nullable();
38+
39+
// Job result (output data, varies by job_type)
40+
// For 'import-pdf': { patternsAdded: 5, fieldsExtracted: 12 }
41+
// For 'validate': { errorsFound: 2, warningsFound: 5 }
42+
table.text('result').nullable();
43+
44+
// Indexes for common queries
45+
table.index('form_id', 'idx_form_jobs_form_id');
46+
table.index('status', 'idx_form_jobs_status');
47+
table.index(['form_id', 'job_type'], 'idx_form_jobs_form_type');
48+
table.index('created_at', 'idx_form_jobs_created');
49+
});
50+
}
51+
52+
/**
53+
* @param { import("knex").Knex } knex
54+
* @returns { Promise<void> }
55+
*/
56+
export async function down(knex) {
57+
await knex.schema.dropTableIfExists('form_jobs');
58+
}

packages/database/package.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,28 @@
1212
},
1313
"exports": {
1414
".": {
15+
"development": {
16+
"types": "./src/index.ts",
17+
"import": "./src/index.ts"
18+
},
1519
"types": "./dist/types/index.d.ts",
1620
"import": "./dist/esm/index.js",
1721
"require": "./dist/cjs/index.js"
1822
},
1923
"./context": {
24+
"development": {
25+
"types": "./src/context/index.ts",
26+
"import": "./src/context/index.ts"
27+
},
2028
"types": "./dist/types/context/index.d.ts",
2129
"import": "./dist/esm/context.js",
2230
"require": "./dist/cjs/context.js"
2331
},
2432
"./testing": {
33+
"development": {
34+
"types": "./src/testing.ts",
35+
"import": "./src/testing.ts"
36+
},
2537
"types": "./dist/types/testing.d.ts",
2638
"import": "./dist/esm/testing.js",
2739
"require": "./dist/cjs/testing.js"

0 commit comments

Comments
 (0)