jax-hono 1.0.28 → 1.0.29

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.
@@ -4,9 +4,10 @@ import { join, parse, relative } from 'node:path'
4
4
  import { ensureGeneratedDir, generatedDir, projectDir } from './generated-path'
5
5
 
6
6
  const srcDir = join(cwd(), 'src')
7
- const configDir = join(srcDir, 'config')
8
- const typesFile = join(srcDir, 'types/index.ts')
9
- const outputFile = join(generatedDir, 'config.ts')
7
+ const configDir = join(srcDir, 'config')
8
+ const typesFile = join(srcDir, 'types/index.ts')
9
+ const outputFile = join(generatedDir, 'config.ts')
10
+ const typeAugmentationFile = join(srcDir, 'jax-hono.generated.d.ts')
10
11
  const envStages = new Set([
11
12
  'default',
12
13
  'local',
@@ -64,15 +65,24 @@ function getConfigFiles() {
64
65
  })
65
66
  }
66
67
 
67
- function hasProjectConfigType() {
68
+ function hasProjectConfigType() {
68
69
  if (!existsSync(typesFile)) {
69
70
  return false
70
71
  }
71
72
 
72
73
  const source = readFileSync(typesFile, 'utf8')
73
74
 
74
- return /\bexport\s+(?:type|interface)\s+ProjectConfig\b/.test(source)
75
- }
75
+ return /\bexport\s+(?:type|interface)\s+ProjectConfig\b/.test(source)
76
+ }
77
+
78
+ function writeIfChanged(filePath: string, content: string, message: string) {
79
+ if (existsSync(filePath) && readFileSync(filePath, 'utf8') === content) {
80
+ return
81
+ }
82
+
83
+ writeFileSync(filePath, content)
84
+ console.log(message)
85
+ }
76
86
 
77
87
  export function generateConfig() {
78
88
  const files = getConfigFiles()
@@ -82,40 +92,45 @@ export function generateConfig() {
82
92
  })
83
93
  const modules = files.map((fileName, index) => {
84
94
  return ` { name: '${fileName}', stage: '${getStage(fileName)}', config: ${toImportName(fileName, index)} },`
85
- })
86
- const hasProjectTypes = hasProjectConfigType()
87
- const typeImports = hasProjectTypes ? [`import type { ProjectConfig } from '${join(srcDir, 'types').replaceAll('\\', '/')}'`] : []
88
- const projectConfigType = hasProjectTypes
89
- ? 'export type { ProjectConfig }'
90
- : defaultConfigIndex === -1
95
+ })
96
+ const hasProjectTypes = hasProjectConfigType()
97
+ const typeImports = [
98
+ `import { config as jaxConfig, type JaxConfig } from 'jax-hono'`,
99
+ ...(hasProjectTypes ? [`import type { ProjectConfig } from '${join(srcDir, 'types').replaceAll('\\', '/')}'`] : []),
100
+ ]
101
+ const projectConfigType = hasProjectTypes
102
+ ? 'export type { ProjectConfig }'
103
+ : defaultConfigIndex === -1
91
104
  ? 'export type ProjectConfig = Record<string, unknown>'
92
105
  : `export type ProjectConfig = typeof ${toImportName(files[defaultConfigIndex], defaultConfigIndex)}`
93
106
  const content = `${[...typeImports, ...imports].join('\n')}
94
107
 
95
108
  export const configModules = [
96
109
  ${modules.join('\n')}
97
- ] as const
98
-
99
- ${projectConfigType}
100
-
101
- declare module 'jax-hono/core/generated' {
102
- interface JaxGenerated {
110
+ ] as const
111
+
112
+ ${projectConfigType}
113
+ export type Config = JaxConfig & ProjectConfig
114
+
115
+ export const config = jaxConfig as Config
116
+
117
+ declare module 'jax-hono/core/generated' {
118
+ interface JaxGenerated {
103
119
  config: ProjectConfig
104
120
  }
105
121
  }
106
-
107
- export default configModules
108
- `
109
-
110
- ensureGeneratedDir()
111
-
112
- if (existsSync(outputFile) && readFileSync(outputFile, 'utf8') === content) {
113
- return
114
- }
115
-
116
- writeFileSync(outputFile, content)
117
- console.log(`Generated ${relative(projectDir, outputFile)} with ${files.length} config file(s).`)
118
- }
122
+
123
+ export default configModules
124
+ `
125
+ const typeAugmentationContent = `import '../.jax-hono/config'
126
+
127
+ export {}
128
+ `
129
+
130
+ ensureGeneratedDir()
131
+ writeIfChanged(outputFile, content, `Generated ${relative(projectDir, outputFile)} with ${files.length} config file(s).`)
132
+ writeIfChanged(typeAugmentationFile, typeAugmentationContent, `Generated ${relative(projectDir, typeAugmentationFile)}.`)
133
+ }
119
134
 
120
135
  if (import.meta.main) {
121
136
  generateConfig()
@@ -5,11 +5,12 @@ import { basename, dirname, isAbsolute, join, parse, relative, resolve } from 'n
5
5
  import { ensureGeneratedDir, generatedDir, packageDir, projectDir } from './generated-path'
6
6
 
7
7
  const srcDir = join(cwd(), 'src')
8
- const projectRequire = createRequire(join(projectDir, 'package.json'))
9
- const moduleExtensions = new Set(['.ts', '.js', '.mjs', '.cjs'])
10
- const generatedHeader = `// This file is generated by jax-hono/build/generate-registry.ts.
11
- // Do not edit it directly.
12
- `
8
+ const projectRequire = createRequire(join(projectDir, 'package.json'))
9
+ const moduleExtensions = new Set(['.ts', '.js', '.mjs', '.cjs'])
10
+ const warnedPluginPackages = new Set<string>()
11
+ const generatedHeader = `// This file is generated by jax-hono/build/generate-registry.ts.
12
+ // Do not edit it directly.
13
+ `
13
14
 
14
15
  type ControllerGroup = {
15
16
  name: string
@@ -27,11 +28,12 @@ type PluginConfigItem =
27
28
 
28
29
  type PluginConfig = Record<string, PluginConfigItem>
29
30
 
30
- type EnabledPlugin = {
31
- name: string
32
- packageName: string
33
- rootDir: string
34
- }
31
+ type EnabledPlugin = {
32
+ name: string
33
+ packageName: string
34
+ rootDir: string
35
+ options?: unknown
36
+ }
35
37
 
36
38
  type PluginFile = EnabledPlugin & {
37
39
  filePath: string
@@ -782,13 +784,35 @@ function getEnabledPluginConfigItems() {
782
784
  ])
783
785
  }
784
786
 
785
- function resolvePluginPackageDir(packageName: string) {
786
- const resolved = resolvePluginPackage(packageName)
787
-
788
- return statSync(resolved).isDirectory()
789
- ? resolved
790
- : dirname(resolved)
791
- }
787
+ function resolvePluginPackageDir(packageName: string) {
788
+ const resolved = resolvePluginPackage(packageName)
789
+
790
+ return statSync(resolved).isDirectory()
791
+ ? resolved
792
+ : dirname(resolved)
793
+ }
794
+
795
+ function tryResolvePlugin(name: string, item: Exclude<PluginConfigItem, false> & { package: string }): EnabledPlugin | undefined {
796
+ try {
797
+ return {
798
+ name,
799
+ packageName: item.package,
800
+ rootDir: resolvePluginPackageDir(item.package),
801
+ options: item.options,
802
+ }
803
+ } catch (error) {
804
+ const warningKey = `${name}:${item.package}`
805
+
806
+ if (!warnedPluginPackages.has(warningKey)) {
807
+ warnedPluginPackages.add(warningKey)
808
+ console.warn(
809
+ `[plugins] package not found [${name}]: ${item.package} (${(error as Error).message})`,
810
+ )
811
+ }
812
+
813
+ return undefined
814
+ }
815
+ }
792
816
 
793
817
  function resolvePluginPackage(packageName: string) {
794
818
  if (isAbsolute(packageName)) {
@@ -817,19 +841,12 @@ function resolvePluginPackage(packageName: string) {
817
841
  return projectRequire.resolve(packageName)
818
842
  }
819
843
 
820
- function getEnabledPlugins(): EnabledPlugin[] {
821
- return getEnabledPluginConfigItems()
822
- .map(([name, item]) => {
823
- const rootDir = resolvePluginPackageDir(item.package)
824
-
825
- return {
826
- name,
827
- packageName: item.package,
828
- rootDir,
829
- }
830
- })
831
- .filter((plugin) => existsSync(plugin.rootDir))
832
- }
844
+ function getEnabledPlugins(): EnabledPlugin[] {
845
+ return getEnabledPluginConfigItems()
846
+ .map(([name, item]) => tryResolvePlugin(name, item))
847
+ .filter((plugin): plugin is EnabledPlugin => Boolean(plugin))
848
+ .filter((plugin) => existsSync(plugin.rootDir))
849
+ }
833
850
 
834
851
  function serializePluginOptions(options: unknown) {
835
852
  return options === undefined ? '' : `, options: ${JSON.stringify(options)}`
@@ -855,26 +872,29 @@ function pluginExportsJaxPluginContext(rootDir: string) {
855
872
  return false
856
873
  }
857
874
 
858
- function generatePluginContextRegistry() {
859
- const enabledPlugins = getEnabledPluginConfigItems()
860
- const imports = enabledPlugins.map(([name, item]) => {
861
- return `import ${toLowerCamelIdentifier([name], 'Plugin')} from ${JSON.stringify(item.package)}`
862
- })
863
- const pluginContexts = enabledPlugins
864
- .filter(([, item]) => pluginExportsJaxPluginContext(resolvePluginPackageDir(item.package)))
865
- .map(([name, item]) => ({
866
- importName: toLowerCamelIdentifier([name], 'PluginContext'),
867
- packageName: item.package,
868
- }))
875
+ function generatePluginContextRegistry() {
876
+ const enabledPlugins = getEnabledPluginConfigItems()
877
+ .map(([name, item]) => tryResolvePlugin(name, item))
878
+ .filter((plugin): plugin is EnabledPlugin => Boolean(plugin))
879
+ .filter((plugin) => existsSync(plugin.rootDir))
880
+ const imports = enabledPlugins.map((plugin) => {
881
+ return `import ${toLowerCamelIdentifier([plugin.name], 'Plugin')} from ${JSON.stringify(plugin.packageName)}`
882
+ })
883
+ const pluginContexts = enabledPlugins
884
+ .filter((plugin) => pluginExportsJaxPluginContext(plugin.rootDir))
885
+ .map((plugin) => ({
886
+ importName: toLowerCamelIdentifier([plugin.name], 'PluginContext'),
887
+ packageName: plugin.packageName,
888
+ }))
869
889
  const contextImports = pluginContexts.map(({ importName, packageName }) => {
870
890
  return `import type { JaxPluginContext as ${importName} } from ${JSON.stringify(packageName)}`
871
891
  })
872
892
  const pluginContextTypes = pluginContexts.map(({ importName }) => importName)
873
- const exportNames = enabledPlugins.map(([name]) => toLowerCamelIdentifier([name], 'Plugin'))
874
- const moduleEntries = enabledPlugins.map(
875
- ([name, item]) =>
876
- ` { name: ${JSON.stringify(name)}, module: ${toLowerCamelIdentifier([name], 'Plugin')}${serializePluginOptions(item.options)} },`,
877
- )
893
+ const exportNames = enabledPlugins.map((plugin) => toLowerCamelIdentifier([plugin.name], 'Plugin'))
894
+ const moduleEntries = enabledPlugins.map(
895
+ (plugin) =>
896
+ ` { name: ${JSON.stringify(plugin.name)}, module: ${toLowerCamelIdentifier([plugin.name], 'Plugin')}${serializePluginOptions(plugin.options)} },`,
897
+ )
878
898
  const exportBlock = formatExportBlock(exportNames)
879
899
  const pluginsType = ['Record<string, unknown>', ...pluginContextTypes].join(' & ')
880
900
 
@@ -906,23 +926,24 @@ import * as configModule from './config'
906
926
  import * as controllersModule from './controllers.generated'
907
927
  import * as middlewaresModule from './middlewares.generated'
908
928
  import * as modelsModule from './models.generated'
909
- import * as servicesModule from './services.generated'
910
- import * as cronsModule from './crons.generated'
911
- import * as pluginsModule from './plugins.generated'
912
- import { registerGeneratedModules } from 'jax-hono/core/generated'
913
-
914
- registerGeneratedModules({
915
- 'config.ts': configModule,
916
- 'controllers.generated.ts': controllersModule,
929
+ import * as servicesModule from './services.generated'
930
+ import * as cronsModule from './crons.generated'
931
+ import * as pluginsModule from './plugins.generated'
932
+ import { registerGeneratedModules } from 'jax-hono/core/generated'
933
+
934
+ registerGeneratedModules({
935
+ 'config.ts': configModule,
936
+ 'controllers.generated.ts': controllersModule,
917
937
  'middlewares.generated.ts': middlewaresModule,
918
938
  'models.generated.ts': modelsModule,
919
939
  'services.generated.ts': servicesModule,
920
940
  'crons.generated.ts': cronsModule,
921
- 'plugins.generated.ts': pluginsModule,
922
- })
923
-
924
- export * from 'jax-hono'
925
- `
941
+ 'plugins.generated.ts': pluginsModule,
942
+ })
943
+
944
+ export * from 'jax-hono'
945
+ export { config } from './config'
946
+ `
926
947
 
927
948
  writeGeneratedFile('index.ts', content)
928
949
  }
package/index.ts CHANGED
@@ -103,7 +103,7 @@ export const createServices: CreateServices = ((deps: unknown) => {
103
103
  return getCreateServices()(deps);
104
104
  }) as CreateServices;
105
105
 
106
- export const config = new Proxy({} as Config, {
106
+ export const config: Config = new Proxy<Config>({} as Config, {
107
107
  get(_target, property, receiver) {
108
108
  return Reflect.get(getConfig(), property, receiver);
109
109
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jax-hono",
3
- "version": "1.0.28",
3
+ "version": "1.0.29",
4
4
  "description": "Lightweight framework layer on top of Hono, built for Bun",
5
5
  "type": "module",
6
6
  "main": "./index.ts",