@platformatic/remix 2.71.1-alpha.0 → 3.0.0-alpha.1

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/config.d.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  * and run json-schema-to-typescript to regenerate this file.
6
6
  */
7
7
 
8
- export interface PlatformaticRemixStackable {
8
+ export interface PlatformaticRemixConfig {
9
9
  $schema?: string;
10
10
  logger?: {
11
11
  level: (
package/index.js CHANGED
@@ -1,272 +1,31 @@
1
- import {
2
- transformConfig as basicTransformConfig,
3
- cleanBasePath,
4
- ensureTrailingSlash,
5
- errors,
6
- getServerUrl,
7
- importFile,
8
- resolvePackage,
9
- schemaOptions
10
- } from '@platformatic/basic'
11
- import { ConfigManager } from '@platformatic/config'
12
- import { features } from '@platformatic/utils'
13
- import { ViteStackable } from '@platformatic/vite'
14
- import { createRequestHandler } from '@remix-run/express'
15
- import express from 'express'
16
- import inject from 'light-my-request'
17
- import { existsSync } from 'node:fs'
18
- import { readFile } from 'node:fs/promises'
19
- import { dirname, resolve } from 'node:path'
20
- import { pinoHttp } from 'pino-http'
21
- import { satisfies } from 'semver'
22
- import { packageJson, schema } from './lib/schema.js'
23
-
24
- const supportedVersions = '^2.0.0'
25
-
26
- export class RemixStackable extends ViteStackable {
27
- #app
28
- #server
29
- #dispatcher
30
- #remix
31
- #basePath
32
-
33
- constructor (options, root, configManager) {
34
- super(options, root, configManager)
35
-
36
- this.type = 'remix'
37
- this.version = packageJson.version
38
- }
39
-
40
- async init () {
41
- await super.init()
42
-
43
- if (!this.isProduction) {
44
- this.#remix = resolve(dirname(resolvePackage(this.root, '@remix-run/dev')), '..')
45
- const remixPackage = JSON.parse(await readFile(resolve(this.#remix, 'package.json'), 'utf-8'))
46
-
47
- if (!satisfies(remixPackage.version, supportedVersions)) {
48
- throw new errors.UnsupportedVersion('@remix-run/dev', remixPackage.version, supportedVersions)
49
- }
50
- }
51
-
52
- const config = this.configManager.current
53
- this.#basePath = config.application?.basePath
54
- ? ensureTrailingSlash(cleanBasePath(config.application?.basePath))
55
- : undefined
56
-
57
- this.registerGlobals({ basePath: this.#basePath })
58
-
59
- this.subprocessTerminationSignal = 'SIGKILL'
60
- }
61
-
62
- async start ({ listen }) {
63
- // Make this idempotent
64
- if (this.url) {
65
- return this.url
66
- }
67
-
68
- const config = this.configManager.current
69
- const command = config.application.commands[this.isProduction ? 'production' : 'development']
70
-
71
- if (command) {
72
- return this.startWithCommand(command)
73
- }
74
-
75
- return this.isProduction ? this.#startProduction(listen) : this.#startDevelopment(listen)
76
- }
77
-
78
- async stop () {
79
- if (this.childManager) {
80
- return this.stopCommand()
81
- }
82
-
83
- if (this.isProduction) {
84
- return this.#stopProduction()
85
- }
86
-
87
- return super.stop()
88
- }
89
-
90
- async build () {
91
- const config = this.configManager.current
92
- const command = config.application.commands.build
93
- const basePath = config.application?.basePath
94
- ? ensureTrailingSlash(cleanBasePath(config.application?.basePath))
95
- : undefined
96
-
97
- if (command) {
98
- return this.buildWithCommand(command, basePath)
99
- }
100
-
101
- await this.init()
102
- const { viteBuild } = await importFile(resolve(this.#remix, 'dist/cli/commands.js'))
103
-
104
- try {
105
- globalThis.platformatic.isBuilding = true
106
-
107
- await viteBuild(this.root, {
108
- emptyOutDir: true,
109
- logLevel: this.logger.level,
110
- mode: 'production',
111
- profile: false
112
- })
113
- } finally {
114
- globalThis.platformatic.isBuilding = false
115
- }
116
- }
117
-
118
- async inject (injectParams, onInject) {
119
- if (!this.isProduction) {
120
- return super.inject(injectParams, onInject)
121
- }
122
-
123
- const res = await inject(this.#app, injectParams, onInject)
124
-
125
- /* c8 ignore next 3 */
126
- if (onInject) {
127
- return
128
- } // Since inject might be called from the main thread directly via ITC, let's clean it up
129
-
130
- const { statusCode, headers, body, payload, rawPayload } = res
131
- return { statusCode, headers, body, payload, rawPayload }
132
- }
133
-
134
- getMeta () {
135
- if (!this.isProduction) {
136
- return super.getMeta()
137
- }
138
-
139
- return {
140
- composer: {
141
- tcp: typeof this.url !== 'undefined',
142
- url: this.url,
143
- prefix: this.basePath ?? this.#basePath,
144
- wantsAbsoluteUrls: true,
145
- needsRootTrailingSlash: true
146
- }
147
- }
148
- }
149
-
150
- async #startDevelopment (listen) {
151
- const preloadViteEsmPath = resolve(this.#remix, './dist/vite/import-vite-esm-sync.js')
152
-
153
- // Older versions
154
- if (existsSync(preloadViteEsmPath)) {
155
- const { preloadViteEsm } = await importFile(resolve(this.#remix, './dist/vite/import-vite-esm-sync.js'))
156
- await preloadViteEsm()
157
- } else {
158
- const { preloadVite } = await importFile(resolve(this.#remix, './dist/vite/vite.js'))
159
- await preloadVite()
160
- }
161
-
162
- await super.start({ listen })
163
-
164
- /* c8 ignore next 3 */
165
- if (!this._getVite().config.plugins.some(p => p.name === 'remix')) {
166
- this.logger.warn('Could not find Remix plugin in your Vite configuration. Continuing as plain Vite application.')
167
- }
168
-
169
- await this._collectMetrics()
170
- }
171
-
172
- async #startProduction (listen) {
173
- // Listen if entrypoint
174
- if (this.#app && listen) {
175
- const serverOptions = this.serverConfig
176
- const listenOptions = { host: serverOptions?.hostname || '127.0.0.1', port: serverOptions?.port || 0 }
177
-
178
- if (this.isProduction && features.node.reusePort) {
179
- listenOptions.reusePort = true
180
- }
181
-
182
- this.#server = await new Promise((resolve, reject) => {
183
- return this.#app
184
- .listen(listenOptions, function () {
185
- resolve(this)
186
- })
187
- .on('error', reject)
188
- })
189
-
190
- this.url = getServerUrl(this.#server)
191
-
192
- return this.url
193
- }
194
-
195
- const outputDirectory = this.configManager.current.remix.outputDirectory
196
- this.verifyOutputDirectory(resolve(this.root, outputDirectory))
197
-
198
- const build = await importFile(resolve(this.root, `${outputDirectory}/server/index.js`))
199
- this.#basePath = ensureTrailingSlash(cleanBasePath(build.basename))
200
-
201
- // Setup express app
202
- this.#app = express()
203
- this.#app.disable('x-powered-by')
204
- this.#app.use(pinoHttp({ logger: this.logger }))
205
- this.#app.use(this.#basePath, express.static(resolve(this.root, `${outputDirectory}/client`)))
206
- this.#app.all(`${ensureTrailingSlash(cleanBasePath(this.#basePath))}*`, createRequestHandler({ build }))
207
-
208
- await this._collectMetrics()
209
- return this.url
210
- }
211
-
212
- async #stopProduction () {
213
- /* c8 ignore next 3 */
214
- if (!this.#server?.listening) {
215
- return
216
- }
217
-
218
- return new Promise((resolve, reject) => {
219
- this.#server.close(error => {
220
- /* c8 ignore next 3 */
221
- if (error) {
222
- return reject(error)
223
- }
224
-
225
- resolve()
226
- })
227
- })
228
- }
1
+ import { transform as basicTransform, resolve, validationOptions } from '@platformatic/basic'
2
+ import { kMetadata, loadConfiguration as utilsLoadConfiguration } from '@platformatic/utils'
3
+ import { schema } from './lib/schema.js'
4
+ import { RemixStackable } from './lib/stackable.js'
5
+
6
+ /* c8 ignore next 5 */
7
+ export async function transform (config, schema, options) {
8
+ config = await basicTransform(config, schema, options)
9
+ config.watch = { enabled: false }
10
+ return config
229
11
  }
230
12
 
231
- /* c8 ignore next 9 */
232
- function transformConfig () {
233
- if (this.current.watch === undefined) {
234
- this.current.watch = { enabled: false }
235
- }
236
-
237
- if (typeof this.current.watch !== 'object') {
238
- this.current.watch = { enabled: this.current.watch || false }
239
- }
13
+ export async function loadConfiguration (configOrRoot, sourceOrConfig, context) {
14
+ const { root, source } = await resolve(configOrRoot, sourceOrConfig, 'application')
240
15
 
241
- return basicTransformConfig.call(this)
242
- }
243
-
244
- export async function buildStackable (opts) {
245
- const root = opts.context.directory
246
-
247
- const configManager = new ConfigManager({
248
- schema,
249
- source: opts.config ?? {},
250
- schemaOptions,
251
- transformConfig,
252
- dirname: root,
253
- context: opts.context
16
+ return utilsLoadConfiguration(source, context?.schema ?? schema, {
17
+ validationOptions,
18
+ transform,
19
+ replaceEnv: true,
20
+ root,
21
+ ...context
254
22
  })
255
- await configManager.parseAndValidate()
256
-
257
- return new RemixStackable(opts, root, configManager)
258
23
  }
259
24
 
260
- export { schema, schemaComponents } from './lib/schema.js'
261
-
262
- export default {
263
- configType: 'remix',
264
- configManagerConfig: {
265
- schemaOptions,
266
- transformConfig
267
- },
268
- buildStackable,
269
- schema,
270
- version: packageJson.version,
271
- modulesToLoad: []
25
+ export async function create (configOrRoot, sourceOrConfig, context) {
26
+ const config = await loadConfiguration(configOrRoot, sourceOrConfig, context)
27
+ return new RemixStackable(config[kMetadata].root, config, context)
272
28
  }
29
+
30
+ export { packageJson, schema, schemaComponents, version } from './lib/schema.js'
31
+ export * from './lib/stackable.js'
package/lib/schema.js CHANGED
@@ -2,8 +2,10 @@ import { schemaComponents as basicSchemaComponents } from '@platformatic/basic'
2
2
  import { schemaComponents as utilsSchemaComponents } from '@platformatic/utils'
3
3
  import { schemaComponents as viteSchemaComponents } from '@platformatic/vite'
4
4
  import { readFileSync } from 'node:fs'
5
+ import { resolve } from 'node:path'
5
6
 
6
- export const packageJson = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf-8'))
7
+ export const packageJson = JSON.parse(readFileSync(resolve(import.meta.dirname, '../package.json'), 'utf8'))
8
+ export const version = packageJson.version
7
9
 
8
10
  export const remix = {
9
11
  type: 'object',
@@ -22,7 +24,7 @@ export const schemaComponents = { remix }
22
24
  export const schema = {
23
25
  $id: `https://schemas.platformatic.dev/@platformatic/remix/${packageJson.version}.json`,
24
26
  $schema: 'http://json-schema.org/draft-07/schema#',
25
- title: 'Platformatic Remix Stackable',
27
+ title: 'Platformatic Remix Config',
26
28
  type: 'object',
27
29
  properties: {
28
30
  $schema: {
@@ -0,0 +1,224 @@
1
+ import {
2
+ cleanBasePath,
3
+ ensureTrailingSlash,
4
+ errors,
5
+ getServerUrl,
6
+ importFile,
7
+ resolvePackage
8
+ } from '@platformatic/basic'
9
+ import { features } from '@platformatic/utils'
10
+ import { ViteStackable } from '@platformatic/vite'
11
+ import { createRequestHandler } from '@remix-run/express'
12
+ import express from 'express'
13
+ import inject from 'light-my-request'
14
+ import { existsSync } from 'node:fs'
15
+ import { readFile } from 'node:fs/promises'
16
+ import { dirname, resolve } from 'node:path'
17
+ import { pinoHttp } from 'pino-http'
18
+ import { satisfies } from 'semver'
19
+ import { packageJson } from './schema.js'
20
+
21
+ const supportedVersions = '^2.0.0'
22
+
23
+ export class RemixStackable extends ViteStackable {
24
+ #app
25
+ #server
26
+ #remix
27
+ #basePath
28
+
29
+ constructor (root, config, context) {
30
+ super(root, config, context)
31
+ this.type = 'remix'
32
+ this.version = packageJson.version
33
+ }
34
+
35
+ async init () {
36
+ await super.init()
37
+
38
+ if (!this.isProduction) {
39
+ this.#remix = resolve(dirname(resolvePackage(this.root, '@remix-run/dev')), '..')
40
+ const remixPackage = JSON.parse(await readFile(resolve(this.#remix, 'package.json'), 'utf-8'))
41
+
42
+ if (!satisfies(remixPackage.version, supportedVersions)) {
43
+ throw new errors.UnsupportedVersion('@remix-run/dev', remixPackage.version, supportedVersions)
44
+ }
45
+ }
46
+
47
+ const config = this.config
48
+ this.#basePath = config.application?.basePath
49
+ ? ensureTrailingSlash(cleanBasePath(config.application?.basePath))
50
+ : undefined
51
+
52
+ this.registerGlobals({ basePath: this.#basePath })
53
+
54
+ this.subprocessTerminationSignal = 'SIGKILL'
55
+ }
56
+
57
+ async start ({ listen }) {
58
+ // Make this idempotent
59
+ if (this.url) {
60
+ return this.url
61
+ }
62
+
63
+ const config = this.config
64
+ const command = config.application.commands[this.isProduction ? 'production' : 'development']
65
+
66
+ if (command) {
67
+ return this.startWithCommand(command)
68
+ }
69
+
70
+ return this.isProduction ? this.#startProduction(listen) : this.#startDevelopment(listen)
71
+ }
72
+
73
+ async stop () {
74
+ if (this.childManager) {
75
+ return this.stopCommand()
76
+ }
77
+
78
+ if (this.isProduction) {
79
+ return this.#stopProduction()
80
+ }
81
+
82
+ return super.stop()
83
+ }
84
+
85
+ async build () {
86
+ const config = this.config
87
+ const command = config.application.commands.build
88
+ const basePath = config.application?.basePath
89
+ ? ensureTrailingSlash(cleanBasePath(config.application?.basePath))
90
+ : undefined
91
+
92
+ if (command) {
93
+ return this.buildWithCommand(command, basePath)
94
+ }
95
+
96
+ await this.init()
97
+ const { viteBuild } = await importFile(resolve(this.#remix, 'dist/cli/commands.js'))
98
+
99
+ try {
100
+ globalThis.platformatic.isBuilding = true
101
+
102
+ await viteBuild(this.root, {
103
+ emptyOutDir: true,
104
+ logLevel: this.logger.level,
105
+ mode: 'production',
106
+ profile: false
107
+ })
108
+ } finally {
109
+ globalThis.platformatic.isBuilding = false
110
+ }
111
+ }
112
+
113
+ async inject (injectParams, onInject) {
114
+ if (!this.isProduction) {
115
+ return super.inject(injectParams, onInject)
116
+ }
117
+
118
+ const res = await inject(this.#app, injectParams, onInject)
119
+
120
+ /* c8 ignore next 3 */
121
+ if (onInject) {
122
+ return
123
+ } // Since inject might be called from the main thread directly via ITC, let's clean it up
124
+
125
+ const { statusCode, headers, body, payload, rawPayload } = res
126
+ return { statusCode, headers, body, payload, rawPayload }
127
+ }
128
+
129
+ getMeta () {
130
+ if (!this.isProduction) {
131
+ return super.getMeta()
132
+ }
133
+
134
+ return {
135
+ composer: {
136
+ tcp: typeof this.url !== 'undefined',
137
+ url: this.url,
138
+ prefix: this.basePath ?? this.#basePath,
139
+ wantsAbsoluteUrls: true,
140
+ needsRootTrailingSlash: true
141
+ }
142
+ }
143
+ }
144
+
145
+ async #startDevelopment (listen) {
146
+ const preloadViteEsmPath = resolve(this.#remix, './dist/vite/import-vite-esm-sync.js')
147
+
148
+ // Older versions
149
+ if (existsSync(preloadViteEsmPath)) {
150
+ const { preloadViteEsm } = await importFile(resolve(this.#remix, './dist/vite/import-vite-esm-sync.js'))
151
+ await preloadViteEsm()
152
+ } else {
153
+ const { preloadVite } = await importFile(resolve(this.#remix, './dist/vite/vite.js'))
154
+ await preloadVite()
155
+ }
156
+
157
+ await super.start({ listen })
158
+
159
+ /* c8 ignore next 3 */
160
+ if (!this._getVite().config.plugins.some(p => p.name === 'remix')) {
161
+ this.logger.warn('Could not find Remix plugin in your Vite configuration. Continuing as plain Vite application.')
162
+ }
163
+
164
+ await this._collectMetrics()
165
+ }
166
+
167
+ async #startProduction (listen) {
168
+ // Listen if entrypoint
169
+ if (this.#app && listen) {
170
+ const serverOptions = this.serverConfig
171
+ const listenOptions = { host: serverOptions?.hostname || '127.0.0.1', port: serverOptions?.port || 0 }
172
+
173
+ if (this.isProduction && features.node.reusePort) {
174
+ listenOptions.reusePort = true
175
+ }
176
+
177
+ this.#server = await new Promise((resolve, reject) => {
178
+ return this.#app
179
+ .listen(listenOptions, function () {
180
+ resolve(this)
181
+ })
182
+ .on('error', reject)
183
+ })
184
+
185
+ this.url = getServerUrl(this.#server)
186
+
187
+ return this.url
188
+ }
189
+
190
+ const outputDirectory = this.config.remix.outputDirectory
191
+ this.verifyOutputDirectory(resolve(this.root, outputDirectory))
192
+
193
+ const build = await importFile(resolve(this.root, `${outputDirectory}/server/index.js`))
194
+ this.#basePath = ensureTrailingSlash(cleanBasePath(build.basename))
195
+
196
+ // Setup express app
197
+ this.#app = express()
198
+ this.#app.disable('x-powered-by')
199
+ this.#app.use(pinoHttp({ logger: this.logger }))
200
+ this.#app.use(this.#basePath, express.static(resolve(this.root, `${outputDirectory}/client`)))
201
+ this.#app.all(`${ensureTrailingSlash(cleanBasePath(this.#basePath))}*`, createRequestHandler({ build }))
202
+
203
+ await this._collectMetrics()
204
+ return this.url
205
+ }
206
+
207
+ async #stopProduction () {
208
+ /* c8 ignore next 3 */
209
+ if (!this.#server?.listening) {
210
+ return
211
+ }
212
+
213
+ return new Promise((resolve, reject) => {
214
+ this.#server.close(error => {
215
+ /* c8 ignore next 3 */
216
+ if (error) {
217
+ return reject(error)
218
+ }
219
+
220
+ resolve()
221
+ })
222
+ })
223
+ }
224
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformatic/remix",
3
- "version": "2.71.1-alpha.0",
3
+ "version": "3.0.0-alpha.1",
4
4
  "description": "Platformatic Remix Stackable",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -20,10 +20,9 @@
20
20
  "light-my-request": "^6.0.0",
21
21
  "pino-http": "^10.2.0",
22
22
  "semver": "^7.6.3",
23
- "@platformatic/config": "2.71.1-alpha.0",
24
- "@platformatic/basic": "2.71.1-alpha.0",
25
- "@platformatic/utils": "2.71.1-alpha.0",
26
- "@platformatic/vite": "2.71.1-alpha.0"
23
+ "@platformatic/utils": "3.0.0-alpha.1",
24
+ "@platformatic/vite": "3.0.0-alpha.1",
25
+ "@platformatic/basic": "3.0.0-alpha.1"
27
26
  },
28
27
  "devDependencies": {
29
28
  "@remix-run/dev": "^2.16.8",
@@ -40,12 +39,12 @@
40
39
  "typescript": "^5.5.4",
41
40
  "vite": "^5.4.2",
42
41
  "ws": "^8.18.0",
43
- "@platformatic/composer": "2.71.1-alpha.0",
44
- "@platformatic/service": "2.71.1-alpha.0"
42
+ "@platformatic/composer": "3.0.0-alpha.1",
43
+ "@platformatic/service": "3.0.0-alpha.1"
45
44
  },
46
45
  "scripts": {
47
- "test": "npm run lint && borp --concurrency=1 --no-timeout",
48
- "coverage": "npm run lint && borp -C -X test -X test/fixtures --concurrency=1 --no-timeout",
46
+ "test": "npm run lint && borp --concurrency=1 --timeout 1200000",
47
+ "coverage": "npm run lint && borp -C -X test -X test/fixtures --concurrency=1 --timeout 1200000",
49
48
  "gen-schema": "node lib/schema.js > schema.json",
50
49
  "gen-types": "json2ts > config.d.ts < schema.json",
51
50
  "build": "pnpm run gen-schema && pnpm run gen-types",
package/schema.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
- "$id": "https://schemas.platformatic.dev/@platformatic/remix/2.71.1-alpha.0.json",
2
+ "$id": "https://schemas.platformatic.dev/@platformatic/remix/3.0.0-alpha.1.json",
3
3
  "$schema": "http://json-schema.org/draft-07/schema#",
4
- "title": "Platformatic Remix Stackable",
4
+ "title": "Platformatic Remix Config",
5
5
  "type": "object",
6
6
  "properties": {
7
7
  "$schema": {