@tothalex/nulljs 0.0.48 → 0.0.54
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/package.json +25 -32
- package/scripts/install-server.js +0 -199
- package/src/commands/api.ts +0 -16
- package/src/commands/auth.ts +0 -54
- package/src/commands/create.ts +0 -43
- package/src/commands/deploy.ts +0 -160
- package/src/commands/dev/function/index.ts +0 -221
- package/src/commands/dev/function/utils.ts +0 -99
- package/src/commands/dev/index.tsx +0 -126
- package/src/commands/dev/logging-manager.ts +0 -87
- package/src/commands/dev/server/index.ts +0 -48
- package/src/commands/dev/server/utils.ts +0 -37
- package/src/commands/dev/ui/components/scroll-area.tsx +0 -141
- package/src/commands/dev/ui/components/tab-bar.tsx +0 -67
- package/src/commands/dev/ui/index.tsx +0 -71
- package/src/commands/dev/ui/logging-context.tsx +0 -76
- package/src/commands/dev/ui/tabs/functions-tab.tsx +0 -35
- package/src/commands/dev/ui/tabs/server-tab.tsx +0 -36
- package/src/commands/dev/ui/tabs/vite-tab.tsx +0 -35
- package/src/commands/dev/ui/use-logging.tsx +0 -34
- package/src/commands/dev/vite/index.ts +0 -54
- package/src/commands/dev/vite/utils.ts +0 -71
- package/src/commands/host.ts +0 -339
- package/src/commands/index.ts +0 -8
- package/src/commands/profile.ts +0 -189
- package/src/commands/secret.ts +0 -79
- package/src/index.ts +0 -346
- package/src/lib/api.ts +0 -189
- package/src/lib/bundle/external.ts +0 -23
- package/src/lib/bundle/function/index.ts +0 -46
- package/src/lib/bundle/index.ts +0 -2
- package/src/lib/bundle/react/index.ts +0 -2
- package/src/lib/bundle/react/spa.ts +0 -77
- package/src/lib/bundle/react/ssr/client.ts +0 -93
- package/src/lib/bundle/react/ssr/config.ts +0 -77
- package/src/lib/bundle/react/ssr/index.ts +0 -4
- package/src/lib/bundle/react/ssr/props.ts +0 -71
- package/src/lib/bundle/react/ssr/server.ts +0 -83
- package/src/lib/bundle/types.ts +0 -4
- package/src/lib/config.ts +0 -347
- package/src/lib/deployment.ts +0 -244
- package/src/lib/update-server.ts +0 -262
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import { basename, extname } from 'path'
|
|
2
|
-
import type { InlineConfig, Plugin, UserConfig } from 'vite'
|
|
3
|
-
import react from '@vitejs/plugin-react'
|
|
4
|
-
import tailwindcss from '@tailwindcss/vite'
|
|
5
|
-
|
|
6
|
-
import type { PluginOptions } from '../../types'
|
|
7
|
-
|
|
8
|
-
const jsClientSsr = ({ filePath }: PluginOptions): Plugin => {
|
|
9
|
-
const entry = basename(filePath, extname(filePath))
|
|
10
|
-
const virtualPrefix = `virtual:ssr/${entry}.tsx`
|
|
11
|
-
|
|
12
|
-
return {
|
|
13
|
-
name: 'nulljs-ssr-client-plugin',
|
|
14
|
-
apply: 'build',
|
|
15
|
-
config: async (config: UserConfig, { command }) => {
|
|
16
|
-
if (command !== 'build') {
|
|
17
|
-
return config
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return {
|
|
21
|
-
build: {
|
|
22
|
-
rollupOptions: {
|
|
23
|
-
input: {
|
|
24
|
-
[entry]: virtualPrefix
|
|
25
|
-
},
|
|
26
|
-
external: ['cloud'],
|
|
27
|
-
output: {
|
|
28
|
-
entryFileNames: '[name].js'
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
plugins: [react()]
|
|
33
|
-
}
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
resolveId: (id: string) => {
|
|
37
|
-
if (id === virtualPrefix) {
|
|
38
|
-
return id
|
|
39
|
-
}
|
|
40
|
-
return null
|
|
41
|
-
},
|
|
42
|
-
|
|
43
|
-
load: (id: string) => {
|
|
44
|
-
if (id === virtualPrefix) {
|
|
45
|
-
const script = `
|
|
46
|
-
import { StrictMode } from 'react'
|
|
47
|
-
import { hydrateRoot } from "react-dom/client";
|
|
48
|
-
import { Page } from "${filePath.replace(/\\/g, '\\\\')}";
|
|
49
|
-
|
|
50
|
-
const domNode = document.getElementById("root");
|
|
51
|
-
if (domNode) {
|
|
52
|
-
const initialProps = window.__INITIAL_PROPS__ || {};
|
|
53
|
-
|
|
54
|
-
hydrateRoot(
|
|
55
|
-
domNode,
|
|
56
|
-
<StrictMode>
|
|
57
|
-
<Page {...initialProps} />
|
|
58
|
-
</StrictMode>,
|
|
59
|
-
)
|
|
60
|
-
}`
|
|
61
|
-
|
|
62
|
-
return script
|
|
63
|
-
}
|
|
64
|
-
return null
|
|
65
|
-
},
|
|
66
|
-
|
|
67
|
-
generateBundle(_, bundle) {
|
|
68
|
-
Object.keys(bundle).forEach((fileName) => {
|
|
69
|
-
const chunk = bundle[fileName]
|
|
70
|
-
if (chunk.type === 'chunk') {
|
|
71
|
-
chunk.code = chunk.code.replace(/import\s+.*?\s+from\s+['"]cloud['"];?\s*/g, '')
|
|
72
|
-
chunk.code = chunk.code.replace('import"cloud";', '')
|
|
73
|
-
chunk.code = chunk.code.replace(/require\(['"]cloud['"]\);?\s*/g, '')
|
|
74
|
-
}
|
|
75
|
-
})
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export const ssrClientConfig = (filePath: string): InlineConfig => {
|
|
81
|
-
return {
|
|
82
|
-
logLevel: 'error',
|
|
83
|
-
plugins: [
|
|
84
|
-
jsClientSsr({
|
|
85
|
-
filePath
|
|
86
|
-
}),
|
|
87
|
-
tailwindcss()
|
|
88
|
-
],
|
|
89
|
-
build: {
|
|
90
|
-
outDir: '/tmp'
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import path from 'path'
|
|
2
|
-
import type { InlineConfig, Plugin, UserConfig } from 'vite'
|
|
3
|
-
import { external } from '../../external'
|
|
4
|
-
|
|
5
|
-
import type { PluginOptions } from '../../types'
|
|
6
|
-
|
|
7
|
-
const jsConfigSsr = ({ filePath }: PluginOptions): Plugin => {
|
|
8
|
-
const entry = path.basename(filePath, path.extname(filePath))
|
|
9
|
-
const virtualPrefix = `virtual:ssr/${entry}.ts`
|
|
10
|
-
|
|
11
|
-
return {
|
|
12
|
-
name: 'nulljs-ssr-props-plugin',
|
|
13
|
-
apply: 'build',
|
|
14
|
-
config: async (config: UserConfig, { command }) => {
|
|
15
|
-
if (command !== 'build') {
|
|
16
|
-
return config
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
return {
|
|
20
|
-
build: {
|
|
21
|
-
ssr: true,
|
|
22
|
-
rollupOptions: {
|
|
23
|
-
input: {
|
|
24
|
-
[entry]: virtualPrefix
|
|
25
|
-
},
|
|
26
|
-
external: [...external, 'react', 'react/jsx-runtime'],
|
|
27
|
-
output: {
|
|
28
|
-
entryFileNames: '[name].js'
|
|
29
|
-
},
|
|
30
|
-
preserveEntrySignatures: 'strict'
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
resolveId: (id: string) => {
|
|
37
|
-
if (id === virtualPrefix) {
|
|
38
|
-
return id
|
|
39
|
-
}
|
|
40
|
-
return null
|
|
41
|
-
},
|
|
42
|
-
|
|
43
|
-
load: (id: string) => {
|
|
44
|
-
if (id === virtualPrefix) {
|
|
45
|
-
const script = `
|
|
46
|
-
import { config } from "${filePath.replace(/\\/g, '\\\\')}";
|
|
47
|
-
|
|
48
|
-
export default config;
|
|
49
|
-
`
|
|
50
|
-
|
|
51
|
-
return script
|
|
52
|
-
}
|
|
53
|
-
return null
|
|
54
|
-
},
|
|
55
|
-
|
|
56
|
-
transform: (code, id) => {
|
|
57
|
-
if (id === filePath) {
|
|
58
|
-
const configMatch = code.match(/export const config = \{[^}]*\};/)
|
|
59
|
-
return configMatch ? { code: configMatch[0], map: null } : null
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export const ssrConfigConfig = (filePath: string): InlineConfig => {
|
|
66
|
-
return {
|
|
67
|
-
logLevel: 'error',
|
|
68
|
-
plugins: [
|
|
69
|
-
jsConfigSsr({
|
|
70
|
-
filePath
|
|
71
|
-
})
|
|
72
|
-
],
|
|
73
|
-
build: {
|
|
74
|
-
outDir: '/tmp'
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import path from 'path'
|
|
2
|
-
import type { InlineConfig, Plugin, UserConfig } from 'vite'
|
|
3
|
-
import react from '@vitejs/plugin-react-swc'
|
|
4
|
-
|
|
5
|
-
import type { PluginOptions } from '../../types'
|
|
6
|
-
import { external } from '../../external'
|
|
7
|
-
|
|
8
|
-
const jsPagesSsr = ({ filePath }: PluginOptions): Plugin => {
|
|
9
|
-
const entry = path.basename(filePath, path.extname(filePath))
|
|
10
|
-
const virtualPrefix = `virtual:ssr/${entry}.ts`
|
|
11
|
-
|
|
12
|
-
return {
|
|
13
|
-
name: 'nulljs-ssr-server-plugin',
|
|
14
|
-
apply: 'build',
|
|
15
|
-
config: async (config: UserConfig, { command }) => {
|
|
16
|
-
if (command !== 'build') {
|
|
17
|
-
return config
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return {
|
|
21
|
-
build: {
|
|
22
|
-
ssr: true,
|
|
23
|
-
rollupOptions: {
|
|
24
|
-
input: {
|
|
25
|
-
[entry]: virtualPrefix
|
|
26
|
-
},
|
|
27
|
-
external,
|
|
28
|
-
output: {
|
|
29
|
-
entryFileNames: '[name].js'
|
|
30
|
-
},
|
|
31
|
-
preserveEntrySignatures: 'strict'
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
},
|
|
36
|
-
|
|
37
|
-
resolveId: (id: string) => {
|
|
38
|
-
if (id === virtualPrefix) {
|
|
39
|
-
return id
|
|
40
|
-
}
|
|
41
|
-
return null
|
|
42
|
-
},
|
|
43
|
-
|
|
44
|
-
load: (id: string) => {
|
|
45
|
-
if (id === virtualPrefix) {
|
|
46
|
-
const script = `
|
|
47
|
-
import { props } from "${filePath.replace(/\\/g, '\\\\')}";
|
|
48
|
-
|
|
49
|
-
export { props }
|
|
50
|
-
`
|
|
51
|
-
|
|
52
|
-
return script
|
|
53
|
-
}
|
|
54
|
-
return null
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export const ssrPropsConfig = (filePath: string): InlineConfig => {
|
|
60
|
-
return {
|
|
61
|
-
logLevel: 'error',
|
|
62
|
-
plugins: [
|
|
63
|
-
jsPagesSsr({
|
|
64
|
-
filePath
|
|
65
|
-
})
|
|
66
|
-
],
|
|
67
|
-
build: {
|
|
68
|
-
outDir: '/tmp'
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import path from 'path'
|
|
2
|
-
import type { InlineConfig, Plugin, UserConfig } from 'vite'
|
|
3
|
-
import react from '@vitejs/plugin-react-swc'
|
|
4
|
-
|
|
5
|
-
import type { PluginOptions } from '../../types'
|
|
6
|
-
import { external } from '../../external'
|
|
7
|
-
|
|
8
|
-
const jsPagesSsr = ({ filePath }: PluginOptions): Plugin => {
|
|
9
|
-
const entry = path.basename(filePath, path.extname(filePath))
|
|
10
|
-
const virtualPrefix = `virtual:ssr/${entry}.tsx`
|
|
11
|
-
|
|
12
|
-
return {
|
|
13
|
-
name: 'nulljs-ssr-server-plugin',
|
|
14
|
-
apply: 'build',
|
|
15
|
-
config: async (config: UserConfig, { command }) => {
|
|
16
|
-
if (command !== 'build') {
|
|
17
|
-
return config
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return {
|
|
21
|
-
build: {
|
|
22
|
-
ssr: true,
|
|
23
|
-
rollupOptions: {
|
|
24
|
-
input: {
|
|
25
|
-
[entry]: virtualPrefix
|
|
26
|
-
},
|
|
27
|
-
external,
|
|
28
|
-
output: {
|
|
29
|
-
format: 'iife',
|
|
30
|
-
entryFileNames: '[name].js'
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
},
|
|
34
|
-
ssr: {
|
|
35
|
-
target: 'webworker',
|
|
36
|
-
noExternal: true
|
|
37
|
-
},
|
|
38
|
-
plugins: [react()]
|
|
39
|
-
}
|
|
40
|
-
},
|
|
41
|
-
|
|
42
|
-
resolveId: (id: string) => {
|
|
43
|
-
if (id === virtualPrefix) {
|
|
44
|
-
return id
|
|
45
|
-
}
|
|
46
|
-
return null
|
|
47
|
-
},
|
|
48
|
-
|
|
49
|
-
load: (id: string) => {
|
|
50
|
-
if (id === virtualPrefix) {
|
|
51
|
-
const script = `
|
|
52
|
-
import "fast-text-encoding";
|
|
53
|
-
import React from "react";
|
|
54
|
-
import { renderToString } from "react-dom/server";
|
|
55
|
-
import { Page } from "${filePath.replace(/\\/g, '\\\\')}";
|
|
56
|
-
|
|
57
|
-
export const Index = (props) => {
|
|
58
|
-
const p = props ? JSON.parse(props) : {};
|
|
59
|
-
|
|
60
|
-
return renderToString(<Page {...p} />);
|
|
61
|
-
}
|
|
62
|
-
`
|
|
63
|
-
|
|
64
|
-
return script
|
|
65
|
-
}
|
|
66
|
-
return null
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export const ssrServerConfig = (filePath: string): InlineConfig => {
|
|
72
|
-
return {
|
|
73
|
-
logLevel: 'error',
|
|
74
|
-
plugins: [
|
|
75
|
-
jsPagesSsr({
|
|
76
|
-
filePath
|
|
77
|
-
})
|
|
78
|
-
],
|
|
79
|
-
build: {
|
|
80
|
-
outDir: '/tmp'
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
package/src/lib/bundle/types.ts
DELETED
package/src/lib/config.ts
DELETED
|
@@ -1,347 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
readFileSync,
|
|
3
|
-
writeFileSync,
|
|
4
|
-
existsSync,
|
|
5
|
-
mkdirSync,
|
|
6
|
-
readdirSync,
|
|
7
|
-
unlinkSync
|
|
8
|
-
} from 'node:fs'
|
|
9
|
-
import { join, dirname } from 'node:path'
|
|
10
|
-
import chalk from 'chalk'
|
|
11
|
-
|
|
12
|
-
type NulljsConfig = {
|
|
13
|
-
key?: {
|
|
14
|
-
private: string
|
|
15
|
-
public: string
|
|
16
|
-
}
|
|
17
|
-
api?: string
|
|
18
|
-
dev?: {
|
|
19
|
-
apiPort?: number
|
|
20
|
-
gatewayPort?: number
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const findProjectRoot = (startPath: string = process.cwd()): string => {
|
|
25
|
-
let currentPath = startPath
|
|
26
|
-
while (currentPath !== dirname(currentPath)) {
|
|
27
|
-
if (existsSync(join(currentPath, 'package.json'))) {
|
|
28
|
-
return currentPath
|
|
29
|
-
}
|
|
30
|
-
currentPath = dirname(currentPath)
|
|
31
|
-
}
|
|
32
|
-
return startPath
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export const configPath = join(findProjectRoot(), '.nulljs', 'config.json')
|
|
36
|
-
export const profilesDir = join(findProjectRoot(), '.nulljs', 'profiles')
|
|
37
|
-
export const activeProfilePath = join(findProjectRoot(), '.nulljs', 'active-profile')
|
|
38
|
-
|
|
39
|
-
export const loadConfig = (): NulljsConfig => {
|
|
40
|
-
if (!existsSync(configPath)) {
|
|
41
|
-
return {}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
try {
|
|
45
|
-
const configContent = readFileSync(configPath, 'utf8')
|
|
46
|
-
return JSON.parse(configContent) as NulljsConfig
|
|
47
|
-
} catch (error) {
|
|
48
|
-
console.error('Failed to parse config file:', error)
|
|
49
|
-
return {}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export const saveConfig = (config: NulljsConfig): void => {
|
|
54
|
-
try {
|
|
55
|
-
// Ensure the directory exists
|
|
56
|
-
const configDir = dirname(configPath)
|
|
57
|
-
if (!existsSync(configDir)) {
|
|
58
|
-
mkdirSync(configDir, { recursive: true })
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const configContent = JSON.stringify(config, null, 2)
|
|
62
|
-
writeFileSync(configPath, configContent, 'utf8')
|
|
63
|
-
} catch (error) {
|
|
64
|
-
console.error('Failed to save config file:', error)
|
|
65
|
-
throw error
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export const updateConfig = (partialConfig: Partial<NulljsConfig>): void => {
|
|
70
|
-
const currentConfig = loadConfig()
|
|
71
|
-
const updatedConfig = { ...currentConfig, ...partialConfig }
|
|
72
|
-
|
|
73
|
-
saveConfig(updatedConfig)
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Profile-related functions (must be defined before other functions use them)
|
|
77
|
-
export const getActiveProfile = (): string | null => {
|
|
78
|
-
if (!existsSync(activeProfilePath)) {
|
|
79
|
-
return null
|
|
80
|
-
}
|
|
81
|
-
try {
|
|
82
|
-
return readFileSync(activeProfilePath, 'utf8').trim()
|
|
83
|
-
} catch {
|
|
84
|
-
return null
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export const setActiveProfile = (profileName: string): void => {
|
|
89
|
-
const configDir = dirname(activeProfilePath)
|
|
90
|
-
if (!existsSync(configDir)) {
|
|
91
|
-
mkdirSync(configDir, { recursive: true })
|
|
92
|
-
}
|
|
93
|
-
writeFileSync(activeProfilePath, profileName, 'utf8')
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export const getProfilePath = (profileName: string): string => {
|
|
97
|
-
return join(profilesDir, `${profileName}.json`)
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export const loadProfile = (profileName: string): NulljsConfig => {
|
|
101
|
-
const profilePath = getProfilePath(profileName)
|
|
102
|
-
if (!existsSync(profilePath)) {
|
|
103
|
-
return {}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
try {
|
|
107
|
-
const profileContent = readFileSync(profilePath, 'utf8')
|
|
108
|
-
return JSON.parse(profileContent) as NulljsConfig
|
|
109
|
-
} catch (error) {
|
|
110
|
-
console.error(`Failed to parse profile '${profileName}':`, error)
|
|
111
|
-
return {}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export const saveProfile = (profileName: string, config: NulljsConfig): void => {
|
|
116
|
-
try {
|
|
117
|
-
if (!existsSync(profilesDir)) {
|
|
118
|
-
mkdirSync(profilesDir, { recursive: true })
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
const profilePath = getProfilePath(profileName)
|
|
122
|
-
const configContent = JSON.stringify(config, null, 2)
|
|
123
|
-
writeFileSync(profilePath, configContent, 'utf8')
|
|
124
|
-
} catch (error) {
|
|
125
|
-
console.error(`Failed to save profile '${profileName}':`, error)
|
|
126
|
-
throw error
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
export const profileExists = (profileName: string): boolean => {
|
|
131
|
-
return existsSync(getProfilePath(profileName))
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
export const loadConfigWithProfile = (): NulljsConfig => {
|
|
135
|
-
const activeProfile = getActiveProfile()
|
|
136
|
-
|
|
137
|
-
if (activeProfile && profileExists(activeProfile)) {
|
|
138
|
-
return loadProfile(activeProfile)
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
return loadConfig()
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
export const saveConfigWithProfile = (config: NulljsConfig, profileName?: string): void => {
|
|
145
|
-
if (profileName) {
|
|
146
|
-
saveProfile(profileName, config)
|
|
147
|
-
setActiveProfile(profileName)
|
|
148
|
-
} else {
|
|
149
|
-
const activeProfile = getActiveProfile()
|
|
150
|
-
if (activeProfile && profileExists(activeProfile)) {
|
|
151
|
-
saveProfile(activeProfile, config)
|
|
152
|
-
} else {
|
|
153
|
-
saveConfig(config)
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
export const updateConfigWithProfile = (
|
|
159
|
-
partialConfig: Partial<NulljsConfig>,
|
|
160
|
-
profileName?: string
|
|
161
|
-
): void => {
|
|
162
|
-
if (profileName) {
|
|
163
|
-
const currentConfig = loadProfile(profileName)
|
|
164
|
-
const updatedConfig = { ...currentConfig, ...partialConfig }
|
|
165
|
-
saveProfile(profileName, updatedConfig)
|
|
166
|
-
setActiveProfile(profileName)
|
|
167
|
-
} else {
|
|
168
|
-
const activeProfile = getActiveProfile()
|
|
169
|
-
if (activeProfile && profileExists(activeProfile)) {
|
|
170
|
-
const currentConfig = loadProfile(activeProfile)
|
|
171
|
-
const updatedConfig = { ...currentConfig, ...partialConfig }
|
|
172
|
-
saveProfile(activeProfile, updatedConfig)
|
|
173
|
-
} else {
|
|
174
|
-
updateConfig(partialConfig)
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// Functions that use profile-related functions
|
|
180
|
-
export const saveKeys = (privateKey: string, publicKey: string, profileName?: string): void => {
|
|
181
|
-
updateConfigWithProfile(
|
|
182
|
-
{
|
|
183
|
-
key: {
|
|
184
|
-
private: privateKey,
|
|
185
|
-
public: publicKey
|
|
186
|
-
}
|
|
187
|
-
},
|
|
188
|
-
profileName
|
|
189
|
-
)
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
export const saveApiUrl = (apiUrl: string, profileName?: string): void => {
|
|
193
|
-
updateConfigWithProfile({ api: apiUrl }, profileName)
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
export const loadPrivateKey = async () => {
|
|
197
|
-
let base64Key = process.env.NULLJS_PRIVATE_KEY
|
|
198
|
-
|
|
199
|
-
if (!base64Key) {
|
|
200
|
-
const config = loadConfigWithProfile()
|
|
201
|
-
if (!config.key?.private) {
|
|
202
|
-
throw new Error('Private key not found in config file or environment variable')
|
|
203
|
-
}
|
|
204
|
-
base64Key = config.key.private
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
const keyBuffer = Uint8Array.from(atob(base64Key), (c) => c.charCodeAt(0))
|
|
208
|
-
|
|
209
|
-
return await crypto.subtle.importKey(
|
|
210
|
-
'pkcs8',
|
|
211
|
-
keyBuffer,
|
|
212
|
-
{
|
|
213
|
-
name: 'Ed25519',
|
|
214
|
-
namedCurve: 'Ed25519'
|
|
215
|
-
},
|
|
216
|
-
false,
|
|
217
|
-
['sign']
|
|
218
|
-
)
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
export const getApiUrl = (): string => {
|
|
222
|
-
const config = loadConfigWithProfile()
|
|
223
|
-
return config.api || 'http://localhost:3000/api'
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
export const API = getApiUrl()
|
|
227
|
-
|
|
228
|
-
export type DevConfig = {
|
|
229
|
-
apiPort: number
|
|
230
|
-
gatewayPort: number
|
|
231
|
-
publicKey: string | undefined
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
export const getDevConfig = () => {
|
|
235
|
-
const config = loadConfigWithProfile()
|
|
236
|
-
return {
|
|
237
|
-
apiPort: config.dev?.apiPort || 3000,
|
|
238
|
-
gatewayPort: config.dev?.gatewayPort || 3001,
|
|
239
|
-
publicKey: config.key?.public
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
export const getProjectRoot = () => findProjectRoot()
|
|
244
|
-
|
|
245
|
-
export const getCloudPath = () => join(findProjectRoot(), '.nulljs')
|
|
246
|
-
|
|
247
|
-
export const listProfiles = (): string[] => {
|
|
248
|
-
if (!existsSync(profilesDir)) {
|
|
249
|
-
return []
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
try {
|
|
253
|
-
return readdirSync(profilesDir)
|
|
254
|
-
.filter((file) => file.endsWith('.json'))
|
|
255
|
-
.map((file) => file.replace('.json', ''))
|
|
256
|
-
} catch {
|
|
257
|
-
return []
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
export const deleteProfile = (profileName: string): boolean => {
|
|
262
|
-
const profilePath = getProfilePath(profileName)
|
|
263
|
-
if (!existsSync(profilePath)) {
|
|
264
|
-
return false
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
try {
|
|
268
|
-
unlinkSync(profilePath)
|
|
269
|
-
|
|
270
|
-
const activeProfile = getActiveProfile()
|
|
271
|
-
if (activeProfile === profileName) {
|
|
272
|
-
if (existsSync(activeProfilePath)) {
|
|
273
|
-
unlinkSync(activeProfilePath)
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
return true
|
|
278
|
-
} catch {
|
|
279
|
-
return false
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
export const requireActiveProfile = (): { profileName: string; config: NulljsConfig } => {
|
|
284
|
-
const activeProfile = getActiveProfile()
|
|
285
|
-
|
|
286
|
-
if (!activeProfile) {
|
|
287
|
-
console.error(chalk.red('❌ No active profile selected.'))
|
|
288
|
-
console.error(chalk.gray(' Create a profile: nulljs profile create <name>'))
|
|
289
|
-
console.error(chalk.gray(' Or switch to existing: nulljs profile use <name>'))
|
|
290
|
-
process.exit(1)
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
if (!profileExists(activeProfile)) {
|
|
294
|
-
console.error(chalk.red(`❌ Active profile '${activeProfile}' does not exist.`))
|
|
295
|
-
console.error(chalk.gray(' Available profiles:'))
|
|
296
|
-
const profiles = listProfiles()
|
|
297
|
-
if (profiles.length > 0) {
|
|
298
|
-
profiles.forEach((profile) => console.error(chalk.gray(` - ${profile}`)))
|
|
299
|
-
console.error(chalk.gray(' Switch to an existing profile: nulljs profile use <name>'))
|
|
300
|
-
} else {
|
|
301
|
-
console.error(chalk.gray(' Create your first profile: nulljs profile create <name>'))
|
|
302
|
-
}
|
|
303
|
-
process.exit(1)
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
const config = loadProfile(activeProfile)
|
|
307
|
-
return { profileName: activeProfile, config }
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
export const requireProfileConfiguration = (
|
|
311
|
-
requiredFields: Array<'api' | 'key' | 'dev'> = ['api', 'key']
|
|
312
|
-
): { profileName: string; config: NulljsConfig } => {
|
|
313
|
-
const { profileName, config } = requireActiveProfile()
|
|
314
|
-
|
|
315
|
-
const missing: string[] = []
|
|
316
|
-
|
|
317
|
-
if (requiredFields.includes('api') && !config.api) {
|
|
318
|
-
missing.push('API URL')
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
if (requiredFields.includes('key') && (!config.key?.private || !config.key?.public)) {
|
|
322
|
-
missing.push('authentication keys')
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
if (requiredFields.includes('dev') && !config.dev) {
|
|
326
|
-
missing.push('dev configuration')
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
if (missing.length > 0) {
|
|
330
|
-
console.error(chalk.red(`❌ Profile '${profileName}' is missing required configuration:`))
|
|
331
|
-
missing.forEach((field) => console.error(chalk.yellow(` - ${field}`)))
|
|
332
|
-
console.error('')
|
|
333
|
-
console.error(chalk.gray(' Configure your profile:'))
|
|
334
|
-
if (missing.includes('API URL')) {
|
|
335
|
-
console.error(chalk.gray(' nulljs api <url>'))
|
|
336
|
-
}
|
|
337
|
-
if (missing.includes('authentication keys')) {
|
|
338
|
-
console.error(chalk.gray(' nulljs auth'))
|
|
339
|
-
}
|
|
340
|
-
if (missing.includes('dev configuration')) {
|
|
341
|
-
console.error(chalk.gray(' Check your .nulljs/profiles/<profile>.json file'))
|
|
342
|
-
}
|
|
343
|
-
process.exit(1)
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
return { profileName, config }
|
|
347
|
-
}
|