polen 0.10.0-next.19 → 0.10.0-next.20
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/README.md +2 -2
- package/build/api/api.d.ts +1 -0
- package/build/api/api.d.ts.map +1 -1
- package/build/api/api.js +1 -0
- package/build/api/api.js.map +1 -1
- package/build/api/builder/builder.d.ts +8 -2
- package/build/api/builder/builder.d.ts.map +1 -1
- package/build/api/builder/builder.js +5 -18
- package/build/api/builder/builder.js.map +1 -1
- package/build/api/config/configurator.d.ts +31 -8
- package/build/api/config/configurator.d.ts.map +1 -1
- package/build/api/config/configurator.js +9 -10
- package/build/api/config/configurator.js.map +1 -1
- package/build/api/config/merge.d.ts.map +1 -1
- package/build/api/config/merge.js +9 -16
- package/build/api/config/merge.js.map +1 -1
- package/build/api/project/index.d.ts +2 -0
- package/build/api/project/index.d.ts.map +1 -0
- package/build/api/project/index.js +2 -0
- package/build/api/project/index.js.map +1 -0
- package/build/api/project/validate.d.ts +11 -0
- package/build/api/project/validate.d.ts.map +1 -0
- package/build/api/project/validate.js +30 -0
- package/build/api/project/validate.js.map +1 -0
- package/build/api/vite/plugins/core.d.ts.map +1 -1
- package/build/api/vite/plugins/core.js +1 -0
- package/build/api/vite/plugins/core.js.map +1 -1
- package/build/api/vite/plugins/serve.js +1 -1
- package/build/api/vite/plugins/serve.js.map +1 -1
- package/build/cli/_/parameters.d.ts +6 -0
- package/build/cli/_/parameters.d.ts.map +1 -0
- package/build/cli/_/parameters.js +9 -0
- package/build/cli/_/parameters.js.map +1 -0
- package/build/cli/commands/build.js +17 -10
- package/build/cli/commands/build.js.map +1 -1
- package/build/cli/commands/config/create.js +12 -1
- package/build/cli/commands/config/create.js.map +1 -1
- package/build/cli/commands/create.js +3 -5
- package/build/cli/commands/create.js.map +1 -1
- package/build/cli/commands/dev.js +14 -4
- package/build/cli/commands/dev.js.map +1 -1
- package/build/lib/graphql-document/components/GraphQLDocument.d.ts.map +1 -1
- package/build/lib/graphql-document/components/GraphQLDocument.js +3 -1
- package/build/lib/graphql-document/components/GraphQLDocument.js.map +1 -1
- package/build/lib/kit-temp.d.ts +33 -0
- package/build/lib/kit-temp.d.ts.map +1 -1
- package/build/lib/kit-temp.js +48 -0
- package/build/lib/kit-temp.js.map +1 -1
- package/build/project-data.d.ts +1 -0
- package/build/project-data.d.ts.map +1 -1
- package/build/template/server/main.js +2 -1
- package/build/template/server/main.js.map +1 -1
- package/package.json +1 -1
- package/src/api/api.ts +1 -0
- package/src/api/builder/builder.ts +12 -21
- package/src/api/config/configurator.ts +41 -19
- package/src/api/config/merge.ts +13 -16
- package/src/api/project/index.ts +1 -0
- package/src/api/project/validate.ts +41 -0
- package/src/api/vite/plugins/core.ts +1 -0
- package/src/api/vite/plugins/serve.ts +1 -1
- package/src/cli/_/parameters.ts +10 -0
- package/src/cli/commands/build.ts +25 -10
- package/src/cli/commands/config/create.ts +18 -1
- package/src/cli/commands/create.ts +4 -4
- package/src/cli/commands/dev.ts +19 -5
- package/src/lib/graphql-document/components/GraphQLDocument.tsx +8 -6
- package/src/lib/kit-temp.test.ts +85 -1
- package/src/lib/kit-temp.ts +51 -0
- package/src/project-data.ts +1 -0
- package/src/template/server/main.ts +2 -1
@@ -1,11 +1,16 @@
|
|
1
1
|
// @ts-nocheck
|
2
2
|
import { Api } from '#api/index'
|
3
|
-
import {
|
3
|
+
import { projectParameter } from '#cli/_/parameters'
|
4
|
+
import { ensureOptionalAbsoluteWithCwd } from '#lib/kit-temp'
|
4
5
|
import { Command } from '@molt/command'
|
5
6
|
import { z } from 'zod'
|
6
7
|
|
7
8
|
const args = Command.create()
|
8
9
|
.parameter(`--debug -d`, z.boolean().default(false))
|
10
|
+
.parameter(
|
11
|
+
`--project -p`,
|
12
|
+
projectParameter,
|
13
|
+
)
|
9
14
|
.parameter(
|
10
15
|
`--architecture -a`,
|
11
16
|
Api.Config.BuildArchitecture.default('ssg').describe('Which kind of application architecture to output.'),
|
@@ -14,6 +19,10 @@ const args = Command.create()
|
|
14
19
|
`--base -b`,
|
15
20
|
z.string().optional().describe('Base public path for deployment (e.g., /my-project/)'),
|
16
21
|
)
|
22
|
+
.parameter(
|
23
|
+
`--port`,
|
24
|
+
z.number().optional().describe('Default port for the SSR application'),
|
25
|
+
)
|
17
26
|
.settings({
|
18
27
|
parameters: {
|
19
28
|
environment: {
|
@@ -27,14 +36,20 @@ const args = Command.create()
|
|
27
36
|
})
|
28
37
|
.parse()
|
29
38
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
39
|
+
const dir = ensureOptionalAbsoluteWithCwd(args.project)
|
40
|
+
|
41
|
+
if (!await Api.Project.validateProjectDirectory(dir)) {
|
42
|
+
process.exit(1)
|
43
|
+
}
|
44
|
+
|
36
45
|
await Api.Builder.build({
|
37
|
-
|
38
|
-
|
39
|
-
|
46
|
+
dir,
|
47
|
+
architecture: args.architecture,
|
48
|
+
base: args.base,
|
49
|
+
server: {
|
50
|
+
port: args.port,
|
51
|
+
},
|
52
|
+
advanced: {
|
53
|
+
debug: args.debug,
|
54
|
+
},
|
40
55
|
})
|
@@ -1,6 +1,23 @@
|
|
1
|
+
import { Api } from '#api/index'
|
2
|
+
import { projectParameter } from '#cli/_/parameters'
|
3
|
+
import { ensureOptionalAbsoluteWithCwd } from '#lib/kit-temp'
|
4
|
+
import { Command } from '@molt/command'
|
1
5
|
import { Fs, Path } from '@wollybeard/kit'
|
2
6
|
import consola from 'consola'
|
3
7
|
|
8
|
+
const args = Command.create()
|
9
|
+
.parameter(
|
10
|
+
`--project -p`,
|
11
|
+
projectParameter,
|
12
|
+
)
|
13
|
+
.parse()
|
14
|
+
|
15
|
+
const dir = ensureOptionalAbsoluteWithCwd(args.project)
|
16
|
+
|
17
|
+
if (!await Api.Project.validateProjectDirectory(dir)) {
|
18
|
+
process.exit(1)
|
19
|
+
}
|
20
|
+
|
4
21
|
const fileName = 'polen.config.ts'
|
5
22
|
const fileContent = `import { Polen } from 'polen'
|
6
23
|
|
@@ -9,7 +26,7 @@ export default Polen.defineConfig({
|
|
9
26
|
})
|
10
27
|
`
|
11
28
|
|
12
|
-
const filePath = Path.join(
|
29
|
+
const filePath = Path.join(dir, fileName)
|
13
30
|
|
14
31
|
const exists = await Fs.exists(filePath)
|
15
32
|
if (exists) {
|
@@ -1,4 +1,5 @@
|
|
1
1
|
// @ts-nocheck
|
2
|
+
import { Api } from '#api/index'
|
2
3
|
import { Command } from '@molt/command'
|
3
4
|
import { Err, Fs, Manifest, Name, Path, Str } from '@wollybeard/kit'
|
4
5
|
import * as Ansis from 'ansis'
|
@@ -48,10 +49,9 @@ const args = Command
|
|
48
49
|
|
49
50
|
const getProjectRoot = async (): Promise<string> => {
|
50
51
|
if (args.path) {
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
consola.error(`The given path ${args.path} already exists and is not an empty directory`)
|
52
|
+
if (await Api.Project.validateProjectDirectory(args.path, { mustExist: false, mustBeEmpty: true })) {
|
53
|
+
return args.path
|
54
|
+
}
|
55
55
|
process.exit(1)
|
56
56
|
}
|
57
57
|
|
package/src/cli/commands/dev.ts
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
// @ts-nocheck
|
2
2
|
import { Api } from '#api/index'
|
3
|
+
import { projectParameter } from '#cli/_/parameters'
|
3
4
|
import { Vite } from '#dep/vite/index'
|
4
|
-
import {
|
5
|
+
import { ensureOptionalAbsoluteWithCwd } from '#lib/kit-temp'
|
5
6
|
import { Command } from '@molt/command'
|
6
|
-
import { Err
|
7
|
+
import { Err } from '@wollybeard/kit'
|
7
8
|
import { z } from 'zod'
|
8
9
|
|
9
10
|
const args = Command.create()
|
@@ -11,12 +12,16 @@ const args = Command.create()
|
|
11
12
|
.parameter(
|
12
13
|
`--project -p`,
|
13
14
|
// @ts-expect-error
|
14
|
-
|
15
|
+
projectParameter,
|
15
16
|
)
|
16
17
|
.parameter(
|
17
18
|
`--base -b`,
|
18
19
|
z.string().optional().describe('Base public path for deployment (e.g., /my-project/)'),
|
19
20
|
)
|
21
|
+
.parameter(
|
22
|
+
`--port`,
|
23
|
+
z.number().optional().describe('Port to run the development server on'),
|
24
|
+
)
|
20
25
|
.settings({
|
21
26
|
parameters: {
|
22
27
|
environment: {
|
@@ -30,12 +35,21 @@ const args = Command.create()
|
|
30
35
|
})
|
31
36
|
.parse()
|
32
37
|
|
33
|
-
const dir = ensureOptionalAbsoluteWithCwd(args.project)
|
38
|
+
const dir = ensureOptionalAbsoluteWithCwd(args.project)
|
39
|
+
|
40
|
+
if (!await Api.Project.validateProjectDirectory(dir)) {
|
41
|
+
process.exit(1)
|
42
|
+
}
|
34
43
|
|
35
44
|
const viteUserConfig = await Api.ConfigResolver.fromFile({
|
36
45
|
dir,
|
37
46
|
overrides: {
|
38
|
-
|
47
|
+
build: {
|
48
|
+
base: args.base,
|
49
|
+
},
|
50
|
+
server: {
|
51
|
+
port: args.port,
|
52
|
+
},
|
39
53
|
advanced: {
|
40
54
|
debug: args.debug,
|
41
55
|
},
|
@@ -202,13 +202,15 @@ export const GraphQLDocument: React.FC<GraphQLDocumentProps> = ({
|
|
202
202
|
data-testid='graphql-document'
|
203
203
|
>
|
204
204
|
{/* Base code block */}
|
205
|
-
{renderCode
|
206
|
-
|
207
|
-
|
208
|
-
|
205
|
+
{renderCode
|
206
|
+
? (
|
207
|
+
renderCode()
|
208
|
+
)
|
209
|
+
: (
|
210
|
+
<pre className='code-block'>
|
209
211
|
<code>{children}</code>
|
210
|
-
|
211
|
-
|
212
|
+
</pre>
|
213
|
+
)}
|
212
214
|
|
213
215
|
{/* Interactive overlay layer */}
|
214
216
|
{!plain && isReady && (
|
package/src/lib/kit-temp.test.ts
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import * as fc from 'fast-check'
|
2
2
|
import { describe, expect, test } from 'vitest'
|
3
|
-
import { objFilter, ObjOmit, ObjPick, objPolicyFilter } from './kit-temp.js'
|
3
|
+
import { objFilter, ObjOmit, ObjPick, objPolicyFilter, spreadShallow } from './kit-temp.js'
|
4
4
|
|
5
5
|
describe('objPolicyFilter', () => {
|
6
6
|
const testObj = { a: 1, b: 2, c: 3, d: 4 }
|
@@ -137,3 +137,87 @@ describe('property-based tests', () => {
|
|
137
137
|
)
|
138
138
|
})
|
139
139
|
})
|
140
|
+
|
141
|
+
describe('mergeShallow', () => {
|
142
|
+
test('merges objects while omitting undefined values', () => {
|
143
|
+
const base = { a: 1, b: 2, c: 3 }
|
144
|
+
const override = { b: undefined, c: 4, d: 5 }
|
145
|
+
|
146
|
+
expect(spreadShallow(base, override)).toEqual({ a: 1, b: 2, c: 4, d: 5 })
|
147
|
+
})
|
148
|
+
|
149
|
+
test('handles multiple objects', () => {
|
150
|
+
const obj1 = { a: 1, b: 2 }
|
151
|
+
const obj2 = { b: undefined, c: 3 }
|
152
|
+
const obj3 = { c: undefined, d: 4 }
|
153
|
+
|
154
|
+
expect(spreadShallow(obj1, obj2, obj3)).toEqual({ a: 1, b: 2, c: 3, d: 4 })
|
155
|
+
})
|
156
|
+
|
157
|
+
test('handles empty objects', () => {
|
158
|
+
expect(spreadShallow({}, {})).toEqual({})
|
159
|
+
expect(spreadShallow({ a: 1 }, {})).toEqual({ a: 1 })
|
160
|
+
expect(spreadShallow({}, { a: 1 })).toEqual({ a: 1 })
|
161
|
+
})
|
162
|
+
|
163
|
+
test('handles single object', () => {
|
164
|
+
const obj = { a: 1, b: undefined, c: 3 }
|
165
|
+
expect(spreadShallow(obj)).toEqual({ a: 1, c: 3 })
|
166
|
+
})
|
167
|
+
|
168
|
+
test('handles no objects', () => {
|
169
|
+
expect(spreadShallow()).toEqual({})
|
170
|
+
})
|
171
|
+
|
172
|
+
test('handles undefined objects', () => {
|
173
|
+
const obj = { a: 1, b: 2 }
|
174
|
+
expect(spreadShallow(undefined, obj, undefined)).toEqual({ a: 1, b: 2 })
|
175
|
+
expect(spreadShallow(obj, undefined)).toEqual({ a: 1, b: 2 })
|
176
|
+
expect(spreadShallow(undefined, undefined)).toEqual({})
|
177
|
+
})
|
178
|
+
|
179
|
+
test('preserves null values', () => {
|
180
|
+
const obj1 = { a: 1, b: null }
|
181
|
+
const obj2 = { b: 2, c: null }
|
182
|
+
expect(spreadShallow(obj1, obj2)).toEqual({ a: 1, b: 2, c: null })
|
183
|
+
})
|
184
|
+
|
185
|
+
test('preserves false and 0 values', () => {
|
186
|
+
const obj1 = { a: true, b: 1 }
|
187
|
+
const obj2 = { a: false, b: 0 }
|
188
|
+
expect(spreadShallow(obj1, obj2)).toEqual({ a: false, b: 0 })
|
189
|
+
})
|
190
|
+
|
191
|
+
test('property-based: never includes undefined values', () => {
|
192
|
+
fc.assert(
|
193
|
+
fc.property(
|
194
|
+
fc.array(fc.object({ withUndefined: true })),
|
195
|
+
(objects) => {
|
196
|
+
const result = spreadShallow(...objects)
|
197
|
+
Object.values(result).forEach(value => {
|
198
|
+
expect(value).not.toBe(undefined)
|
199
|
+
})
|
200
|
+
},
|
201
|
+
),
|
202
|
+
)
|
203
|
+
})
|
204
|
+
|
205
|
+
test('property-based: later objects override earlier ones', () => {
|
206
|
+
fc.assert(
|
207
|
+
fc.property(
|
208
|
+
fc.object(),
|
209
|
+
fc.object(),
|
210
|
+
fc.string(),
|
211
|
+
fc.anything({ withUndefined: false }),
|
212
|
+
(obj1, obj2, key, value) => {
|
213
|
+
// Set the same key in both objects
|
214
|
+
obj1[key] = 'first'
|
215
|
+
obj2[key] = value
|
216
|
+
|
217
|
+
const result = spreadShallow(obj1, obj2)
|
218
|
+
expect(result[key]).toBe(value)
|
219
|
+
},
|
220
|
+
),
|
221
|
+
)
|
222
|
+
})
|
223
|
+
})
|
package/src/lib/kit-temp.ts
CHANGED
@@ -592,3 +592,54 @@ export const brand = <$BaseType, $BrandName extends string>(
|
|
592
592
|
): Brand<$BaseType, $BrandName> => {
|
593
593
|
return value as Brand<$BaseType, $BrandName>
|
594
594
|
}
|
595
|
+
|
596
|
+
/**
|
597
|
+
* Shallow merge objects while omitting undefined values.
|
598
|
+
*
|
599
|
+
* This utility simplifies the common pattern of conditionally spreading objects
|
600
|
+
* to avoid including undefined values that would override existing values.
|
601
|
+
*
|
602
|
+
* @param objects - Objects to merge (later objects override earlier ones). Undefined objects are ignored.
|
603
|
+
* @returns Merged object with undefined values omitted
|
604
|
+
*
|
605
|
+
* @example
|
606
|
+
* ```ts
|
607
|
+
* // Instead of:
|
608
|
+
* const overrides = {
|
609
|
+
* ...(value1 ? { key1: value1 } : {}),
|
610
|
+
* ...(value2 ? { key2: value2 } : {}),
|
611
|
+
* }
|
612
|
+
*
|
613
|
+
* // Use:
|
614
|
+
* const overrides = mergeShallow({
|
615
|
+
* key1: value1,
|
616
|
+
* key2: value2,
|
617
|
+
* })
|
618
|
+
*
|
619
|
+
* // Example with config merging:
|
620
|
+
* const config = mergeShallow(
|
621
|
+
* defaultConfig,
|
622
|
+
* userConfig,
|
623
|
+
* { debug: args.debug, base: args.base }
|
624
|
+
* )
|
625
|
+
* // undefined values in the last object won't override earlier values
|
626
|
+
* ```
|
627
|
+
*/
|
628
|
+
export const spreadShallow = <T extends object>(...objects: (T | undefined)[]): T => {
|
629
|
+
const result = {} as T
|
630
|
+
|
631
|
+
for (const obj of objects) {
|
632
|
+
if (obj === undefined) continue
|
633
|
+
|
634
|
+
for (const key in obj) {
|
635
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
636
|
+
const value = obj[key]
|
637
|
+
if (value !== undefined) {
|
638
|
+
result[key] = value
|
639
|
+
}
|
640
|
+
}
|
641
|
+
}
|
642
|
+
}
|
643
|
+
|
644
|
+
return result
|
645
|
+
}
|
package/src/project-data.ts
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
import { serve } from '@hono/node-server' // TODO: support non-node platforms.
|
2
2
|
import { neverCase } from '@wollybeard/kit/language'
|
3
|
+
import PROJECT_DATA from 'virtual:polen/project/data.jsonsuper'
|
3
4
|
import { createApp } from './app.js'
|
4
5
|
import { generate } from './ssg/generate.js'
|
5
6
|
import { view } from './view.js'
|
@@ -10,7 +11,7 @@ if (__BUILDING__) {
|
|
10
11
|
await generate(view)
|
11
12
|
break
|
12
13
|
case `ssr`:
|
13
|
-
const port = process.env[`PORT`] ? parseInt(process.env[`PORT`]) :
|
14
|
+
const port = process.env[`PORT`] ? parseInt(process.env[`PORT`]) : PROJECT_DATA.server.port
|
14
15
|
const app = createApp()
|
15
16
|
serve({ fetch: app.fetch, port })
|
16
17
|
break
|