pipework 0.1.5 → 0.3.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.
Files changed (155) hide show
  1. package/README.md +21 -14
  2. package/dist/auth/chain.d.ts +2 -2
  3. package/dist/auth/chain.d.ts.map +1 -1
  4. package/dist/auth/chain.js +3 -3
  5. package/dist/auth/chain.js.map +1 -1
  6. package/dist/auth/index.d.ts +1 -1
  7. package/dist/auth/index.d.ts.map +1 -1
  8. package/dist/auth/types.d.ts +6 -2
  9. package/dist/auth/types.d.ts.map +1 -1
  10. package/dist/cli/commands/generate.d.ts +7 -0
  11. package/dist/cli/commands/generate.d.ts.map +1 -0
  12. package/dist/cli/commands/generate.js +50 -0
  13. package/dist/cli/commands/generate.js.map +1 -0
  14. package/dist/cli/commands/init.d.ts.map +1 -1
  15. package/dist/cli/commands/init.js +1 -0
  16. package/dist/cli/commands/init.js.map +1 -1
  17. package/dist/cli/commands/run.d.ts +8 -0
  18. package/dist/cli/commands/run.d.ts.map +1 -0
  19. package/dist/cli/commands/run.js +33 -0
  20. package/dist/cli/commands/run.js.map +1 -0
  21. package/dist/cli/commands/test.d.ts +7 -0
  22. package/dist/cli/commands/test.d.ts.map +1 -0
  23. package/dist/cli/commands/test.js +37 -0
  24. package/dist/cli/commands/test.js.map +1 -0
  25. package/dist/cli/index.d.ts.map +1 -1
  26. package/dist/cli/index.js +50 -0
  27. package/dist/cli/index.js.map +1 -1
  28. package/dist/config/env-resolve.d.ts +4 -0
  29. package/dist/config/env-resolve.d.ts.map +1 -0
  30. package/dist/config/env-resolve.js +71 -0
  31. package/dist/config/env-resolve.js.map +1 -0
  32. package/dist/config/env-types.d.ts +42 -0
  33. package/dist/config/env-types.d.ts.map +1 -0
  34. package/dist/config/env-types.js +2 -0
  35. package/dist/config/env-types.js.map +1 -0
  36. package/dist/config/index.d.ts +4 -2
  37. package/dist/config/index.d.ts.map +1 -1
  38. package/dist/config/index.js +1 -0
  39. package/dist/config/index.js.map +1 -1
  40. package/dist/config/load.d.ts +8 -0
  41. package/dist/config/load.d.ts.map +1 -1
  42. package/dist/config/load.js +9 -0
  43. package/dist/config/load.js.map +1 -1
  44. package/dist/config/namespace.d.ts +47 -15
  45. package/dist/config/namespace.d.ts.map +1 -1
  46. package/dist/config/schema.d.ts +39 -0
  47. package/dist/config/schema.d.ts.map +1 -1
  48. package/dist/config/schema.js +14 -0
  49. package/dist/config/schema.js.map +1 -1
  50. package/dist/context/create.d.ts +5 -1
  51. package/dist/context/create.d.ts.map +1 -1
  52. package/dist/context/create.js +3 -3
  53. package/dist/context/create.js.map +1 -1
  54. package/dist/context/guard.d.ts.map +1 -1
  55. package/dist/context/guard.js +6 -1
  56. package/dist/context/guard.js.map +1 -1
  57. package/dist/db/db.d.ts +1 -0
  58. package/dist/db/db.d.ts.map +1 -1
  59. package/dist/db/db.js +13 -1
  60. package/dist/db/db.js.map +1 -1
  61. package/dist/db/index.d.ts +1 -0
  62. package/dist/db/index.d.ts.map +1 -1
  63. package/dist/db/index.js +1 -0
  64. package/dist/db/index.js.map +1 -1
  65. package/dist/db/instrumentation.d.ts +5 -0
  66. package/dist/db/instrumentation.d.ts.map +1 -0
  67. package/dist/db/instrumentation.js +44 -0
  68. package/dist/db/instrumentation.js.map +1 -0
  69. package/dist/db/namespace.d.ts +1 -0
  70. package/dist/db/namespace.d.ts.map +1 -1
  71. package/dist/db/namespace.js +2 -0
  72. package/dist/db/namespace.js.map +1 -1
  73. package/dist/db/pool.d.ts +2 -1
  74. package/dist/db/pool.d.ts.map +1 -1
  75. package/dist/db/pool.js +4 -1
  76. package/dist/db/pool.js.map +1 -1
  77. package/dist/di/builder.d.ts +3 -0
  78. package/dist/di/builder.d.ts.map +1 -1
  79. package/dist/di/builder.js +4 -1
  80. package/dist/di/builder.js.map +1 -1
  81. package/dist/di/index.d.ts +1 -0
  82. package/dist/di/index.d.ts.map +1 -1
  83. package/dist/di/index.js +1 -0
  84. package/dist/di/index.js.map +1 -1
  85. package/dist/di/resolve.d.ts.map +1 -1
  86. package/dist/di/resolve.js +12 -5
  87. package/dist/di/resolve.js.map +1 -1
  88. package/dist/di/types.d.ts +1 -0
  89. package/dist/di/types.d.ts.map +1 -1
  90. package/dist/di/types.js +1 -1
  91. package/dist/di/types.js.map +1 -1
  92. package/dist/http/middleware.d.ts.map +1 -1
  93. package/dist/http/middleware.js +10 -1
  94. package/dist/http/middleware.js.map +1 -1
  95. package/dist/index.d.ts +2 -2
  96. package/dist/index.d.ts.map +1 -1
  97. package/dist/index.js.map +1 -1
  98. package/dist/migrate/generate.d.ts +9 -0
  99. package/dist/migrate/generate.d.ts.map +1 -0
  100. package/dist/migrate/generate.js +145 -0
  101. package/dist/migrate/generate.js.map +1 -0
  102. package/dist/migrate/index.d.ts +1 -0
  103. package/dist/migrate/index.d.ts.map +1 -1
  104. package/dist/migrate/index.js +1 -0
  105. package/dist/migrate/index.js.map +1 -1
  106. package/dist/pipework.d.ts +6 -2
  107. package/dist/pipework.d.ts.map +1 -1
  108. package/dist/pipework.js +4 -4
  109. package/dist/pipework.js.map +1 -1
  110. package/dist/tenant/index.d.ts +2 -0
  111. package/dist/tenant/index.d.ts.map +1 -1
  112. package/dist/tenant/index.js +2 -0
  113. package/dist/tenant/index.js.map +1 -1
  114. package/dist/tenant/namespace.d.ts +3 -0
  115. package/dist/tenant/namespace.d.ts.map +1 -1
  116. package/dist/tenant/namespace.js +3 -0
  117. package/dist/tenant/namespace.js.map +1 -1
  118. package/dist/tenant/scope.d.ts +8 -0
  119. package/dist/tenant/scope.d.ts.map +1 -0
  120. package/dist/tenant/scope.js +21 -0
  121. package/dist/tenant/scope.js.map +1 -0
  122. package/dist/tenant/scoped-db.d.ts +3 -0
  123. package/dist/tenant/scoped-db.d.ts.map +1 -0
  124. package/dist/tenant/scoped-db.js +173 -0
  125. package/dist/tenant/scoped-db.js.map +1 -0
  126. package/dist/test/auto-setup.js +6 -1
  127. package/dist/test/auto-setup.js.map +1 -1
  128. package/dist/test/context.d.ts.map +1 -1
  129. package/dist/test/context.js +10 -0
  130. package/dist/test/context.js.map +1 -1
  131. package/dist/test/index.d.ts +3 -1
  132. package/dist/test/index.d.ts.map +1 -1
  133. package/dist/test/index.js +2 -0
  134. package/dist/test/index.js.map +1 -1
  135. package/dist/test/plugin.d.ts +1 -1
  136. package/dist/test/plugin.d.ts.map +1 -1
  137. package/dist/test/plugin.js +2 -2
  138. package/dist/test/plugin.js.map +1 -1
  139. package/dist/test/setup.d.ts +2 -0
  140. package/dist/test/setup.d.ts.map +1 -1
  141. package/dist/test/setup.js +39 -1
  142. package/dist/test/setup.js.map +1 -1
  143. package/dist/test/vitest-config.d.ts +17 -0
  144. package/dist/test/vitest-config.d.ts.map +1 -0
  145. package/dist/test/vitest-config.js +28 -0
  146. package/dist/test/vitest-config.js.map +1 -0
  147. package/dist/test/vitest-plugin.d.ts +7 -0
  148. package/dist/test/vitest-plugin.d.ts.map +1 -0
  149. package/dist/test/vitest-plugin.js +13 -0
  150. package/dist/test/vitest-plugin.js.map +1 -0
  151. package/dist/test/vitest.d.ts +6 -0
  152. package/dist/test/vitest.d.ts.map +1 -1
  153. package/dist/test/vitest.js +31 -13
  154. package/dist/test/vitest.js.map +1 -1
  155. package/package.json +35 -21
package/README.md CHANGED
@@ -31,7 +31,14 @@ Pipework eliminates the infrastructure decisions that every SaaS backend makes i
31
31
  import { createManifold } from 'pipework'
32
32
 
33
33
  export default createManifold({
34
- databases: { app: { url: 'DATABASE_URL', testUrl: 'DATABASE_URL_TEST' } },
34
+ databases: {
35
+ app: {
36
+ url: 'DATABASE_URL',
37
+ testUrl: 'DATABASE_URL_TEST',
38
+ schema: './src/db/schema.ts',
39
+ migrations: './migrations/app',
40
+ },
41
+ },
35
42
  })
36
43
  ```
37
44
 
@@ -41,12 +48,12 @@ import pipework from '../pipework.config.js'
41
48
  import { http, fitting, schema } from 'pipework'
42
49
 
43
50
  const createNote = fitting
44
- .use('app')
51
+ .use()
45
52
  .auth<{ userId: string; tenantId: string }>()
46
53
  .input(schema.check.object({ title: schema.check.string(), body: schema.check.string() }))
47
54
  .route('POST', '/notes')
48
- .fit(async ({ app, auth, input }) => {
49
- const [note] = await app
55
+ .fit(async ({ db, auth, input }) => {
56
+ const [note] = await db
50
57
  .insert(notes)
51
58
  .values({ ...input, tenantId: auth.tenantId })
52
59
  .returning()
@@ -97,11 +104,12 @@ const rows = await db.execute(pipe.sql`SELECT * FROM users`)
97
104
 
98
105
  ## Testing
99
106
 
100
- Add one line to your vitest config and put your connection strings in `.env.test`:
107
+ One-liner vitest config. Put your connection string in `.env.test`:
101
108
 
102
109
  ```typescript
103
110
  // vitest.config.ts
104
- test: { setupFiles: ['pipework/test/setup'] }
111
+ import { defineTestConfig } from 'pipework/vitest'
112
+ export default defineTestConfig()
105
113
  ```
106
114
 
107
115
  ```bash
@@ -109,27 +117,26 @@ test: { setupFiles: ['pipework/test/setup'] }
109
117
  DATABASE_URL_TEST=postgresql://user:pass@localhost:5432/myapp_test
110
118
  ```
111
119
 
112
- The setup file loads your env files, discovers `pipework.config.ts`, creates test databases, and isolates each test in a rollback transaction. No other setup needed.
120
+ Add `"pipework/globals"` to your tsconfig types for the `db` global, then write tests directly:
113
121
 
114
122
  ```typescript
115
123
  // tests/notes.test.ts
116
- import { useTestDb, withFlow } from 'pipework/test'
117
124
  import { pipe } from 'pipework'
118
125
 
119
126
  it('creates a note', async () => {
120
- const db = useTestDb()
121
- await withFlow(async () => {
122
- await db.execute(pipe.sql`INSERT INTO notes (title) VALUES ('Test')`)
123
- const rows = await db.execute(pipe.sql`SELECT * FROM notes`)
124
- expect(rows).toHaveLength(1)
125
- })
127
+ await db.execute(pipe.sql`INSERT INTO notes (title) VALUES ('Test')`)
128
+ const rows = await db.execute(pipe.sql`SELECT * FROM notes`)
129
+ expect(rows).toHaveLength(1)
126
130
  })
127
131
  ```
128
132
 
133
+ Every test runs in a rollback transaction. No cleanup, no state leaks. Run with `pipework test` for automatic database setup/teardown, or use `pnpm vitest` directly.
134
+
129
135
  ## Documentation
130
136
 
131
137
  - **[Getting Started](https://github.com/theconstructory/pipework/blob/main/docs/getting-started.md)** — zero to running server
132
138
  - **Guides**
139
+ - [Monorepo](https://github.com/theconstructory/pipework/blob/main/docs/guides/monorepo.md)
133
140
  - [Configuration](https://github.com/theconstructory/pipework/blob/main/docs/guides/configuration.md)
134
141
  - [Handlers](https://github.com/theconstructory/pipework/blob/main/docs/guides/handlers.md)
135
142
  - [Auth & Tenants](https://github.com/theconstructory/pipework/blob/main/docs/guides/auth-and-tenants.md)
@@ -1,4 +1,4 @@
1
- import type { AuthStrategy, AuthRequest } from './types.js';
1
+ import type { AuthStrategy, AuthRequest, AuthContext } from './types.js';
2
2
  export interface AuthEnricher<TAuth> {
3
3
  readonly name: string;
4
4
  enrich(auth: TAuth): Promise<TAuth>;
@@ -17,5 +17,5 @@ export interface AuthChainResult<TAuth> {
17
17
  }
18
18
  export declare function runAuthChain<TAuth>(config: AuthChainConfig<TAuth>, request: AuthRequest, options: {
19
19
  optional: boolean;
20
- }): Promise<AuthChainResult<TAuth>>;
20
+ }, context: AuthContext): Promise<AuthChainResult<TAuth>>;
21
21
  //# sourceMappingURL=chain.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"chain.d.ts","sourceRoot":"","sources":["../../src/auth/chain.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAG3D,MAAM,WAAW,YAAY,CAAC,KAAK;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,MAAM,CAAC,IAAI,EAAE,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAA;CACpC;AAED,MAAM,WAAW,cAAc,CAAC,KAAK;IACnC,OAAO,CAAC,IAAI,EAAE,KAAK,GAAG,MAAM,CAAA;CAC7B;AAED,MAAM,WAAW,eAAe,CAAC,KAAK;IACpC,QAAQ,CAAC,UAAU,EAAE,SAAS,YAAY,CAAC,KAAK,CAAC,EAAE,CAAA;IACnD,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,YAAY,CAAC,KAAK,CAAC,EAAE,CAAA;IACnD,QAAQ,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC,KAAK,CAAC,CAAA;CAChD;AAED,MAAM,WAAW,eAAe,CAAC,KAAK;IACpC,QAAQ,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI,CAAA;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CAC/B;AAED,wBAAsB,YAAY,CAAC,KAAK,EACtC,MAAM,EAAE,eAAe,CAAC,KAAK,CAAC,EAC9B,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE;IAAE,QAAQ,EAAE,OAAO,CAAA;CAAE,GAC7B,OAAO,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAqCjC"}
1
+ {"version":3,"file":"chain.d.ts","sourceRoot":"","sources":["../../src/auth/chain.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAGxE,MAAM,WAAW,YAAY,CAAC,KAAK;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,MAAM,CAAC,IAAI,EAAE,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAA;CACpC;AAED,MAAM,WAAW,cAAc,CAAC,KAAK;IACnC,OAAO,CAAC,IAAI,EAAE,KAAK,GAAG,MAAM,CAAA;CAC7B;AAED,MAAM,WAAW,eAAe,CAAC,KAAK;IACpC,QAAQ,CAAC,UAAU,EAAE,SAAS,YAAY,CAAC,KAAK,CAAC,EAAE,CAAA;IACnD,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,YAAY,CAAC,KAAK,CAAC,EAAE,CAAA;IACnD,QAAQ,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC,KAAK,CAAC,CAAA;CAChD;AAED,MAAM,WAAW,eAAe,CAAC,KAAK;IACpC,QAAQ,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI,CAAA;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CAC/B;AAED,wBAAsB,YAAY,CAAC,KAAK,EACtC,MAAM,EAAE,eAAe,CAAC,KAAK,CAAC,EAC9B,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE;IAAE,QAAQ,EAAE,OAAO,CAAA;CAAE,EAC9B,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAqCjC"}
@@ -1,9 +1,9 @@
1
1
  import { UnauthorizedError } from '../errors/index.js';
2
- export async function runAuthChain(config, request, options) {
2
+ export async function runAuthChain(config, request, options, context) {
3
3
  let extracted = null;
4
4
  let matchedStrategy = null;
5
5
  for (const strategy of config.strategies) {
6
- extracted = await strategy.extract(request);
6
+ extracted = await strategy.extract(request, context);
7
7
  if (extracted !== null) {
8
8
  matchedStrategy = strategy;
9
9
  break;
@@ -16,7 +16,7 @@ export async function runAuthChain(config, request, options) {
16
16
  }
17
17
  let auth;
18
18
  try {
19
- auth = await matchedStrategy.verify(extracted);
19
+ auth = await matchedStrategy.verify(extracted, context);
20
20
  }
21
21
  catch (error) {
22
22
  if (error instanceof UnauthorizedError)
@@ -1 +1 @@
1
- {"version":3,"file":"chain.js","sourceRoot":"","sources":["../../src/auth/chain.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAsBtD,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,MAA8B,EAC9B,OAAoB,EACpB,OAA8B;IAE9B,IAAI,SAAS,GAAiB,IAAI,CAAA;IAClC,IAAI,eAAe,GAA+B,IAAI,CAAA;IAEtD,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACzC,SAAS,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;QAC3C,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;YACvB,eAAe,GAAG,QAAQ,CAAA;YAC1B,MAAK;QACP,CAAC;IACH,CAAC;IAED,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;QACvB,IAAI,OAAO,CAAC,QAAQ;YAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAA;QACzD,MAAM,IAAI,iBAAiB,EAAE,CAAA;IAC/B,CAAC;IAED,IAAI,IAAW,CAAA;IACf,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,eAAgB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;IACjD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,iBAAiB;YAAE,MAAM,KAAK,CAAA;QACnD,MAAM,IAAI,iBAAiB,CAAC,uBAAuB,EAAE;YACnD,QAAQ,EAAE,eAAgB,CAAC,IAAI;YAC/B,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAC9D,CAAC,CAAA;IACJ,CAAC;IAED,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACrB,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YACxC,IAAI,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QACpC,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAA;IAEhG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA;AACzB,CAAC;AAED,SAAS,aAAa,CAAC,IAAa;IAClC,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,UAAU,IAAI,IAAI,EAAE,CAAC;QACpE,MAAM,QAAQ,GAAI,IAA8B,CAAC,QAAQ,CAAA;QACzD,IAAI,OAAO,QAAQ,KAAK,QAAQ;YAAE,OAAO,QAAQ,CAAA;IACnD,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC"}
1
+ {"version":3,"file":"chain.js","sourceRoot":"","sources":["../../src/auth/chain.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAsBtD,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,MAA8B,EAC9B,OAAoB,EACpB,OAA8B,EAC9B,OAAoB;IAEpB,IAAI,SAAS,GAAiB,IAAI,CAAA;IAClC,IAAI,eAAe,GAA+B,IAAI,CAAA;IAEtD,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACzC,SAAS,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;QACpD,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;YACvB,eAAe,GAAG,QAAQ,CAAA;YAC1B,MAAK;QACP,CAAC;IACH,CAAC;IAED,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;QACvB,IAAI,OAAO,CAAC,QAAQ;YAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAA;QACzD,MAAM,IAAI,iBAAiB,EAAE,CAAA;IAC/B,CAAC;IAED,IAAI,IAAW,CAAA;IACf,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,eAAgB,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;IAC1D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,iBAAiB;YAAE,MAAM,KAAK,CAAA;QACnD,MAAM,IAAI,iBAAiB,CAAC,uBAAuB,EAAE;YACnD,QAAQ,EAAE,eAAgB,CAAC,IAAI;YAC/B,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAC9D,CAAC,CAAA;IACJ,CAAC;IAED,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACrB,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YACxC,IAAI,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QACpC,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAA;IAEhG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA;AACzB,CAAC;AAED,SAAS,aAAa,CAAC,IAAa;IAClC,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,UAAU,IAAI,IAAI,EAAE,CAAC;QACpE,MAAM,QAAQ,GAAI,IAA8B,CAAC,QAAQ,CAAA;QACzD,IAAI,OAAO,QAAQ,KAAK,QAAQ;YAAE,OAAO,QAAQ,CAAA;IACnD,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC"}
@@ -1,4 +1,4 @@
1
- export type { AuthStrategy, AuthRequest, BaseAuth } from './types.js';
1
+ export type { AuthStrategy, AuthRequest, AuthContext, BaseAuth } from './types.js';
2
2
  export { runAuthChain } from './chain.js';
3
3
  export type { AuthEnricher, TenantResolver, AuthChainConfig, AuthChainResult } from './chain.js';
4
4
  export { createSessions } from './sessions.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AACzC,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAChG,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC9C,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACjI,YAAY,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AACrE,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAClH,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AACvD,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,eAAe,EAAE,aAAa,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAClF,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AACzC,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAChG,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC9C,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACjI,YAAY,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AACrE,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAClH,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AACvD,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,eAAe,EAAE,aAAa,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA"}
@@ -1,7 +1,11 @@
1
+ import type { DB } from '../db/types.js';
2
+ export interface AuthContext {
3
+ readonly db: (name?: string) => DB;
4
+ }
1
5
  export interface AuthStrategy<TAuth> {
2
6
  readonly name: string;
3
- extract(request: AuthRequest): Promise<TAuth | null>;
4
- verify(extracted: TAuth): Promise<TAuth>;
7
+ extract(request: AuthRequest, context: AuthContext): Promise<TAuth | null>;
8
+ verify(extracted: TAuth, context: AuthContext): Promise<TAuth>;
5
9
  }
6
10
  export interface AuthRequest {
7
11
  readonly headers: Readonly<Record<string, string | undefined>>;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY,CAAC,KAAK;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAA;IACpD,MAAM,CAAC,SAAS,EAAE,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAA;CACzC;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAA;IAC9D,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAA;CAC/D;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAA;AAExC,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,EAAE,CAAA;CACnC;AAED,MAAM,WAAW,YAAY,CAAC,KAAK;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,OAAO,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAA;IAC1E,MAAM,CAAC,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,CAAA;CAC/D;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAA;IAC9D,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAA;CAC/D;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B"}
@@ -0,0 +1,7 @@
1
+ export interface GenerateCommandOptions {
2
+ db: string | undefined;
3
+ name: string | undefined;
4
+ cwd: string;
5
+ }
6
+ export declare function generate(options: GenerateCommandOptions): Promise<void>;
7
+ //# sourceMappingURL=generate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/generate.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,GAAG,SAAS,CAAA;IACtB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;IACxB,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,wBAAsB,QAAQ,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CA6C7E"}
@@ -0,0 +1,50 @@
1
+ import { info, success, warn, error as logError } from '../output.js';
2
+ export async function generate(options) {
3
+ const { discoverInstance } = await import('../../config/discover.js');
4
+ const { generateForDatabase } = await import('../../migrate/generate.js');
5
+ let instance;
6
+ try {
7
+ instance = await discoverInstance(options.cwd);
8
+ }
9
+ catch {
10
+ logError('No pipework.config.ts found.\n\n' +
11
+ ' Run `pipework init` to create one.\n');
12
+ process.exit(1);
13
+ }
14
+ try {
15
+ if (options.db !== undefined) {
16
+ const dbConfig = instance.config.database(options.db);
17
+ info(`Generating migration for database: ${options.db}`);
18
+ const result = await generateForDatabase(dbConfig, options.cwd, options.name);
19
+ if (result.migrationFile === null) {
20
+ warn(`${options.db}: no schema changes detected`);
21
+ }
22
+ else {
23
+ success(`${options.db}: generated ${result.migrationFile}`);
24
+ }
25
+ }
26
+ else {
27
+ info('Generating migrations for all databases...');
28
+ let generated = 0;
29
+ for (const [, dbConfig] of instance.config.databases()) {
30
+ if (dbConfig.schema === undefined)
31
+ continue;
32
+ const result = await generateForDatabase(dbConfig, options.cwd, options.name);
33
+ if (result.migrationFile === null) {
34
+ warn(`${dbConfig.name}: no schema changes detected`);
35
+ }
36
+ else {
37
+ success(`${dbConfig.name}: generated ${result.migrationFile}`);
38
+ generated++;
39
+ }
40
+ }
41
+ if (generated === 0) {
42
+ warn('No schema changes detected in any database.');
43
+ }
44
+ }
45
+ }
46
+ finally {
47
+ await instance.pool.closeAll();
48
+ }
49
+ }
50
+ //# sourceMappingURL=generate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.js","sourceRoot":"","sources":["../../../src/cli/commands/generate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,IAAI,QAAQ,EAAE,MAAM,cAAc,CAAA;AAQrE,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,OAA+B;IAC5D,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,0BAA0B,CAAC,CAAA;IACrE,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC,2BAA2B,CAAC,CAAA;IAEzE,IAAI,QAAQ,CAAA;IACZ,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,gBAAgB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,QAAQ,CACN,kCAAkC;YAClC,wCAAwC,CACzC,CAAA;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,IAAI,CAAC;QACH,IAAI,OAAO,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;YAC7B,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;YACrD,IAAI,CAAC,sCAAsC,OAAO,CAAC,EAAE,EAAE,CAAC,CAAA;YACxD,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,QAAQ,EAAE,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;YAC7E,IAAI,MAAM,CAAC,aAAa,KAAK,IAAI,EAAE,CAAC;gBAClC,IAAI,CAAC,GAAG,OAAO,CAAC,EAAE,8BAA8B,CAAC,CAAA;YACnD,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,OAAO,CAAC,EAAE,eAAe,MAAM,CAAC,aAAa,EAAE,CAAC,CAAA;YAC7D,CAAC;QACH,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,4CAA4C,CAAC,CAAA;YAClD,IAAI,SAAS,GAAG,CAAC,CAAA;YACjB,KAAK,MAAM,CAAC,EAAE,QAAQ,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,CAAC;gBACvD,IAAI,QAAQ,CAAC,MAAM,KAAK,SAAS;oBAAE,SAAQ;gBAC3C,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,QAAQ,EAAE,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;gBAC7E,IAAI,MAAM,CAAC,aAAa,KAAK,IAAI,EAAE,CAAC;oBAClC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,8BAA8B,CAAC,CAAA;gBACtD,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,GAAG,QAAQ,CAAC,IAAI,eAAe,MAAM,CAAC,aAAa,EAAE,CAAC,CAAA;oBAC9D,SAAS,EAAE,CAAA;gBACb,CAAC;YACH,CAAC;YACD,IAAI,SAAS,KAAK,CAAC,EAAE,CAAC;gBACpB,IAAI,CAAC,6CAA6C,CAAC,CAAA;YACrD,CAAC;QACH,CAAC;IACH,CAAC;YAAS,CAAC;QACT,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAA;IAChC,CAAC;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAiBA,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAiBtC"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAkBA,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAiBtC"}
@@ -8,6 +8,7 @@ export default createManifold({
8
8
  app: {
9
9
  url: 'DATABASE_URL',
10
10
  testUrl: 'DATABASE_URL_TEST',
11
+ schema: './src/db/schema.ts',
11
12
  migrations: './migrations/app',
12
13
  },
13
14
  },
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AAE5C,MAAM,eAAe,GAAG;;;;;;;;;;;CAWvB,CAAA;AAED,MAAM,UAAU,IAAI,CAAC,GAAW;IAC9B,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,oBAAoB,CAAC,CAAA;IAClD,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,YAAY,EAAE,KAAK,CAAC,CAAA;IAErD,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3B,IAAI,CAAC,8CAA8C,CAAC,CAAA;IACtD,CAAC;SAAM,CAAC;QACN,aAAa,CAAC,UAAU,EAAE,eAAe,EAAE,OAAO,CAAC,CAAA;QACnD,OAAO,CAAC,4BAA4B,CAAC,CAAA;IACvC,CAAC;IAED,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QAChC,SAAS,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QAC9C,OAAO,CAAC,WAAW,cAAc,EAAE,CAAC,CAAA;IACtC,CAAC;SAAM,CAAC;QACN,IAAI,CAAC,GAAG,cAAc,4BAA4B,CAAC,CAAA;IACrD,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AAE5C,MAAM,eAAe,GAAG;;;;;;;;;;;;CAYvB,CAAA;AAED,MAAM,UAAU,IAAI,CAAC,GAAW;IAC9B,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,oBAAoB,CAAC,CAAA;IAClD,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,YAAY,EAAE,KAAK,CAAC,CAAA;IAErD,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3B,IAAI,CAAC,8CAA8C,CAAC,CAAA;IACtD,CAAC;SAAM,CAAC;QACN,aAAa,CAAC,UAAU,EAAE,eAAe,EAAE,OAAO,CAAC,CAAA;QACnD,OAAO,CAAC,4BAA4B,CAAC,CAAA;IACvC,CAAC;IAED,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QAChC,SAAS,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QAC9C,OAAO,CAAC,WAAW,cAAc,EAAE,CAAC,CAAA;IACtC,CAAC;SAAM,CAAC;QACN,IAAI,CAAC,GAAG,cAAc,4BAA4B,CAAC,CAAA;IACrD,CAAC;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ export interface RunCommandOptions {
2
+ script: string;
3
+ cwd: string;
4
+ tenant?: string | undefined;
5
+ jobType?: string | undefined;
6
+ }
7
+ export declare function run(options: RunCommandOptions): Promise<void>;
8
+ //# sourceMappingURL=run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/run.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC7B;AAED,wBAAsB,GAAG,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiCnE"}
@@ -0,0 +1,33 @@
1
+ import { resolve } from 'node:path';
2
+ import { existsSync } from 'node:fs';
3
+ import { pathToFileURL } from 'node:url';
4
+ import { bold, success } from '../output.js';
5
+ export async function run(options) {
6
+ const scriptPath = resolve(options.cwd, options.script);
7
+ if (!existsSync(scriptPath)) {
8
+ throw new Error(`Script not found: ${options.script}\n\n` +
9
+ ` Provide a path relative to the project root.\n` +
10
+ ` Example: ${bold('pipework run ./scripts/seed.ts')}\n`);
11
+ }
12
+ const { loadEnvFiles } = await import('../../config/env.js');
13
+ const { discoverInstance } = await import('../../config/discover.js');
14
+ const { createJobContext } = await import('../../context/create.js');
15
+ const { runInContext } = await import('../../context/store.js');
16
+ loadEnvFiles(options.cwd);
17
+ const instance = await discoverInstance(options.cwd);
18
+ const ctx = createJobContext({
19
+ instance,
20
+ jobType: options.jobType ?? 'script',
21
+ tenant: options.tenant ?? null,
22
+ });
23
+ try {
24
+ await runInContext(ctx, async () => {
25
+ await import(pathToFileURL(scriptPath).href);
26
+ });
27
+ success(`Script completed: ${options.script}`);
28
+ }
29
+ finally {
30
+ await instance.pool.closeAll();
31
+ }
32
+ }
33
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/cli/commands/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAS5C,MAAM,CAAC,KAAK,UAAU,GAAG,CAAC,OAA0B;IAClD,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;IAEvD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CACb,qBAAqB,OAAO,CAAC,MAAM,MAAM;YACzC,kDAAkD;YAClD,cAAc,IAAI,CAAC,gCAAgC,CAAC,IAAI,CACzD,CAAA;IACH,CAAC;IAED,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAA;IAC5D,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,0BAA0B,CAAC,CAAA;IACrE,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,yBAAyB,CAAC,CAAA;IACpE,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,wBAAwB,CAAC,CAAA;IAE/D,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACzB,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IAEpD,MAAM,GAAG,GAAG,gBAAgB,CAAC;QAC3B,QAAQ;QACR,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,QAAQ;QACpC,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,IAAI;KAC/B,CAAC,CAAA;IAEF,IAAI,CAAC;QACH,MAAM,YAAY,CAAC,GAAG,EAAE,KAAK,IAAI,EAAE;YACjC,MAAM,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAA;QAC9C,CAAC,CAAC,CAAA;QACF,OAAO,CAAC,qBAAqB,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IAChD,CAAC;YAAS,CAAC;QACT,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAA;IAChC,CAAC;AACH,CAAC"}
@@ -0,0 +1,7 @@
1
+ export interface TestOptions {
2
+ cwd: string;
3
+ db?: string | undefined;
4
+ vitestArgs: string[];
5
+ }
6
+ export declare function test(options: TestOptions): Promise<void>;
7
+ //# sourceMappingURL=test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/test.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACvB,UAAU,EAAE,MAAM,EAAE,CAAA;CACrB;AAED,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAuC9D"}
@@ -0,0 +1,37 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import { bold, info, success } from '../output.js';
3
+ export async function test(options) {
4
+ const { loadEnvFiles } = await import('../../config/env.js');
5
+ const { discoverInstance } = await import('../../config/discover.js');
6
+ const { setupTestDatabases, teardownTestDatabases } = await import('../../test/setup.js');
7
+ loadEnvFiles(options.cwd);
8
+ const instance = await discoverInstance(options.cwd);
9
+ info('Setting up test databases...');
10
+ await setupTestDatabases(instance);
11
+ try {
12
+ const args = ['vitest', 'run', ...options.vitestArgs];
13
+ info(`Running: ${bold(args.join(' '))}`);
14
+ const result = spawnSync('npx', args, {
15
+ cwd: options.cwd,
16
+ stdio: 'inherit',
17
+ env: { ...process.env },
18
+ });
19
+ if (result.error !== undefined) {
20
+ throw new Error(`Failed to spawn vitest: ${result.error.message}\n\n` +
21
+ ` Ensure vitest is installed as a devDependency.\n` +
22
+ ` Example: ${bold('pnpm add -D vitest')}\n`);
23
+ }
24
+ if (result.status !== 0) {
25
+ process.exitCode = result.status ?? 1;
26
+ }
27
+ else {
28
+ success('Tests completed.');
29
+ }
30
+ }
31
+ finally {
32
+ info('Tearing down test databases...');
33
+ await teardownTestDatabases();
34
+ await instance.pool.closeAll();
35
+ }
36
+ }
37
+ //# sourceMappingURL=test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test.js","sourceRoot":"","sources":["../../../src/cli/commands/test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAC9C,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAQlD,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,OAAoB;IAC7C,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAA;IAC5D,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,0BAA0B,CAAC,CAAA;IACrE,MAAM,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAA;IAEzF,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACzB,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IAEpD,IAAI,CAAC,8BAA8B,CAAC,CAAA;IACpC,MAAM,kBAAkB,CAAC,QAAQ,CAAC,CAAA;IAElC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,CAAC,QAAQ,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;QACrD,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAA;QAExC,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE;YACpC,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,KAAK,EAAE,SAAS;YAChB,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE;SACxB,CAAC,CAAA;QAEF,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CACb,2BAA2B,MAAM,CAAC,KAAK,CAAC,OAAO,MAAM;gBACrD,oDAAoD;gBACpD,cAAc,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAC7C,CAAA;QACH,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,IAAI,CAAC,CAAA;QACvC,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,kBAAkB,CAAC,CAAA;QAC7B,CAAC;IACH,CAAC;YAAS,CAAC;QACT,IAAI,CAAC,gCAAgC,CAAC,CAAA;QACtC,MAAM,qBAAqB,EAAE,CAAA;QAC7B,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAA;IAChC,CAAC;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AA2BA,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsEvD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAuCA,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA4GvD"}
package/dist/cli/index.js CHANGED
@@ -6,22 +6,34 @@ ${bold('pipework')} — TypeScript framework for multi-tenant SaaS
6
6
 
7
7
  ${bold('Commands:')}
8
8
  init Scaffold pipework.config.ts and migrations directory
9
+ generate Generate SQL migrations from Drizzle schema changes
9
10
  migrate Run pending migrations for all databases
11
+ run <script> Execute a script with database context
12
+ test Run tests with automatic database setup
10
13
  check Type-check, lint, and boundary enforcement
11
14
  dev Start dev server with file watching
12
15
 
13
16
  ${bold('Options:')}
14
17
  --help, -h Show this help message
15
18
  --version, -v Show version
19
+ --name Migration name (used with generate)
16
20
  --confirm Required for production migrations
17
21
  --allow-destructive Permit destructive DDL (DROP TABLE, DROP COLUMN, etc.)
18
22
  --acknowledge-lock Permit operations that acquire heavy locks
23
+ --tenant Tenant ID for tenant-scoped scripts
24
+ --job-type Override job type (default: "script")
19
25
 
20
26
  ${bold('Examples:')}
21
27
  pipework init
28
+ pipework generate --name add-users
29
+ pipework generate --db app
22
30
  pipework migrate --db app
23
31
  pipework migrate --confirm # required in production
24
32
  pipework dev --port 4000
33
+ pipework run ./scripts/seed.ts
34
+ pipework run ./scripts/backfill.ts --tenant t-123
35
+ pipework test
36
+ pipework test -- --reporter verbose
25
37
  `;
26
38
  export async function run(argv) {
27
39
  const { values, positionals } = parseArgs({
@@ -31,11 +43,14 @@ export async function run(argv) {
31
43
  help: { type: 'boolean', short: 'h' },
32
44
  version: { type: 'boolean', short: 'v' },
33
45
  db: { type: 'string' },
46
+ name: { type: 'string' },
34
47
  port: { type: 'string' },
35
48
  entry: { type: 'string' },
36
49
  confirm: { type: 'boolean' },
37
50
  'allow-destructive': { type: 'boolean' },
38
51
  'acknowledge-lock': { type: 'boolean' },
52
+ tenant: { type: 'string' },
53
+ 'job-type': { type: 'string' },
39
54
  },
40
55
  });
41
56
  if (values.help === true || positionals.length === 0) {
@@ -60,6 +75,15 @@ export async function run(argv) {
60
75
  await init(cwd);
61
76
  break;
62
77
  }
78
+ case 'generate': {
79
+ const { generate } = await import('./commands/generate.js');
80
+ await generate({
81
+ db: values.db,
82
+ name: values.name,
83
+ cwd,
84
+ });
85
+ break;
86
+ }
63
87
  case 'migrate': {
64
88
  const { migrate } = await import('./commands/migrate.js');
65
89
  await migrate({
@@ -71,6 +95,32 @@ export async function run(argv) {
71
95
  });
72
96
  break;
73
97
  }
98
+ case 'run': {
99
+ const scriptPath = positionals[1];
100
+ if (scriptPath === undefined || scriptPath === '') {
101
+ error('Missing script path.');
102
+ process.stderr.write(`\n Usage: ${bold('pipework run <script> [-- args...]')}\n\n`);
103
+ process.exit(1);
104
+ }
105
+ const { run: runScript } = await import('./commands/run.js');
106
+ await runScript({
107
+ script: scriptPath,
108
+ cwd,
109
+ tenant: values.tenant,
110
+ jobType: values['job-type'],
111
+ });
112
+ break;
113
+ }
114
+ case 'test': {
115
+ const vitestArgs = positionals.slice(1);
116
+ const { test: runTests } = await import('./commands/test.js');
117
+ await runTests({
118
+ cwd,
119
+ db: values.db,
120
+ vitestArgs,
121
+ });
122
+ break;
123
+ }
74
124
  case 'check': {
75
125
  const { check } = await import('./commands/check.js');
76
126
  await check(cwd);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { EnvDefs, EnvVarDef } from './env-types.js';
2
+ import type { Environment } from './schema.js';
3
+ export declare function resolveEnvVars(defs: EnvDefs | Record<string, EnvVarDef>, environment: Environment): Record<string, unknown>;
4
+ //# sourceMappingURL=env-resolve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-resolve.d.ts","sourceRoot":"","sources":["../../src/config/env-resolve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAM9C,wBAAgB,cAAc,CAC5B,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EACzC,WAAW,EAAE,WAAW,GACvB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAqCzB"}
@@ -0,0 +1,71 @@
1
+ import { ConfigError } from './resolve.js';
2
+ const TRUTHY = new Set(['true', '1', 'yes']);
3
+ const FALSY = new Set(['false', '0', 'no']);
4
+ export function resolveEnvVars(defs, environment) {
5
+ const result = {};
6
+ const errors = [];
7
+ for (const [name, def] of Object.entries(defs)) {
8
+ const raw = readRaw(name, def, environment);
9
+ if (raw === null) {
10
+ if (def.default !== undefined) {
11
+ result[name] = def.type === 'string[]' ? [...def.default] : def.default;
12
+ continue;
13
+ }
14
+ if (def.required === true) {
15
+ errors.push(def.sensitive === true
16
+ ? ` ${name}: Required but not set. (value redacted — marked sensitive)`
17
+ : ` ${name}: Required but not set.`);
18
+ continue;
19
+ }
20
+ errors.push(` ${name}: No value set and no default provided.`);
21
+ continue;
22
+ }
23
+ try {
24
+ result[name] = coerce(raw, def);
25
+ }
26
+ catch (err) {
27
+ errors.push(` ${name}: ${err.message}`);
28
+ }
29
+ }
30
+ if (errors.length > 0) {
31
+ throw new ConfigError(`Environment validation failed (${errors.length} error${errors.length > 1 ? 's' : ''}):\n\n${errors.join('\n')}`, 'Set these in your .env file or environment.');
32
+ }
33
+ return result;
34
+ }
35
+ function readRaw(name, def, environment) {
36
+ const envValue = process.env[name];
37
+ if (envValue !== undefined && envValue !== '')
38
+ return envValue;
39
+ const envSpecific = def.defaults?.[environment];
40
+ if (envSpecific !== undefined && envSpecific !== '')
41
+ return envSpecific;
42
+ return null;
43
+ }
44
+ function coerce(raw, def) {
45
+ switch (def.type) {
46
+ case 'string':
47
+ return raw;
48
+ case 'number': {
49
+ const n = Number(raw);
50
+ if (Number.isNaN(n)) {
51
+ const display = def.sensitive === true ? '(redacted)' : `"${raw}"`;
52
+ throw new Error(`Expected a number, got ${display}.`);
53
+ }
54
+ return n;
55
+ }
56
+ case 'boolean': {
57
+ const lower = raw.toLowerCase();
58
+ if (TRUTHY.has(lower))
59
+ return true;
60
+ if (FALSY.has(lower))
61
+ return false;
62
+ const display = def.sensitive === true ? '(redacted)' : `"${raw}"`;
63
+ throw new Error(`Expected a boolean (true/false/1/0/yes/no), got ${display}.`);
64
+ }
65
+ case 'string[]': {
66
+ const sep = def.separator ?? ',';
67
+ return raw.split(sep).map(s => s.trim()).filter(s => s !== '');
68
+ }
69
+ }
70
+ }
71
+ //# sourceMappingURL=env-resolve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-resolve.js","sourceRoot":"","sources":["../../src/config/env-resolve.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE1C,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,CAAA;AAC5C,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAA;AAE3C,MAAM,UAAU,cAAc,CAC5B,IAAyC,EACzC,WAAwB;IAExB,MAAM,MAAM,GAA4B,EAAE,CAAA;IAC1C,MAAM,MAAM,GAAa,EAAE,CAAA;IAE3B,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/C,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,EAAE,GAAG,EAAE,WAAW,CAAC,CAAA;QAE3C,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACjB,IAAI,GAAG,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;gBAC9B,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAA;gBACvE,SAAQ;YACV,CAAC;YACD,IAAI,GAAG,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;gBAC1B,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,KAAK,IAAI;oBAChC,CAAC,CAAC,KAAK,IAAI,6DAA6D;oBACxE,CAAC,CAAC,KAAK,IAAI,yBAAyB,CAAC,CAAA;gBACvC,SAAQ;YACV,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,yCAAyC,CAAC,CAAA;YAC/D,SAAQ;QACV,CAAC;QAED,IAAI,CAAC;YACH,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;QACjC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,KAAM,GAAa,CAAC,OAAO,EAAE,CAAC,CAAA;QACrD,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,WAAW,CACnB,kCAAkC,MAAM,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,SAAS,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAChH,6CAA6C,CAC9C,CAAA;IACH,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC;AAED,SAAS,OAAO,CAAC,IAAY,EAAE,GAAc,EAAE,WAAwB;IACrE,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IAClC,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,EAAE;QAAE,OAAO,QAAQ,CAAA;IAE9D,MAAM,WAAW,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC,WAAW,CAAC,CAAA;IAC/C,IAAI,WAAW,KAAK,SAAS,IAAI,WAAW,KAAK,EAAE;QAAE,OAAO,WAAW,CAAA;IAEvE,OAAO,IAAI,CAAA;AACb,CAAC;AAED,SAAS,MAAM,CAAC,GAAW,EAAE,GAAc;IACzC,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;QACjB,KAAK,QAAQ;YACX,OAAO,GAAG,CAAA;QAEZ,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAA;YACrB,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpB,MAAM,OAAO,GAAG,GAAG,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,GAAG,GAAG,CAAA;gBAClE,MAAM,IAAI,KAAK,CAAC,0BAA0B,OAAO,GAAG,CAAC,CAAA;YACvD,CAAC;YACD,OAAO,CAAC,CAAA;QACV,CAAC;QAED,KAAK,SAAS,CAAC,CAAC,CAAC;YACf,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,EAAE,CAAA;YAC/B,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAA;YAClC,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC;gBAAE,OAAO,KAAK,CAAA;YAClC,MAAM,OAAO,GAAG,GAAG,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,GAAG,GAAG,CAAA;YAClE,MAAM,IAAI,KAAK,CAAC,mDAAmD,OAAO,GAAG,CAAC,CAAA;QAChF,CAAC;QAED,KAAK,UAAU,CAAC,CAAC,CAAC;YAChB,MAAM,GAAG,GAAG,GAAG,CAAC,SAAS,IAAI,GAAG,CAAA;YAChC,OAAO,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAA;QAChE,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,42 @@
1
+ import type { Environment } from './schema.js';
2
+ interface EnvVarBase {
3
+ readonly sensitive?: boolean | undefined;
4
+ readonly defaults?: Partial<Record<Environment, string>> | undefined;
5
+ }
6
+ export interface StringEnvVar extends EnvVarBase {
7
+ readonly type: 'string';
8
+ readonly required?: boolean | undefined;
9
+ readonly default?: string | undefined;
10
+ }
11
+ export interface NumberEnvVar extends EnvVarBase {
12
+ readonly type: 'number';
13
+ readonly required?: boolean | undefined;
14
+ readonly default?: number | undefined;
15
+ }
16
+ export interface BooleanEnvVar extends EnvVarBase {
17
+ readonly type: 'boolean';
18
+ readonly required?: boolean | undefined;
19
+ readonly default?: boolean | undefined;
20
+ }
21
+ export interface StringArrayEnvVar extends EnvVarBase {
22
+ readonly type: 'string[]';
23
+ readonly separator?: string | undefined;
24
+ readonly required?: boolean | undefined;
25
+ readonly default?: readonly string[] | undefined;
26
+ }
27
+ export type EnvVarDef = StringEnvVar | NumberEnvVar | BooleanEnvVar | StringArrayEnvVar;
28
+ export type EnvDefs = Record<string, EnvVarDef>;
29
+ export type ResolvedEnvType<T extends EnvVarDef> = T extends {
30
+ readonly type: 'string';
31
+ } ? string : T extends {
32
+ readonly type: 'number';
33
+ } ? number : T extends {
34
+ readonly type: 'boolean';
35
+ } ? boolean : T extends {
36
+ readonly type: 'string[]';
37
+ } ? string[] : never;
38
+ export type ResolveEnvDefs<T extends EnvDefs> = {
39
+ readonly [K in keyof T]: ResolvedEnvType<T[K]>;
40
+ };
41
+ export {};
42
+ //# sourceMappingURL=env-types.d.ts.map