@forgehive/forge-cli 0.1.8 → 0.2.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.
- package/dist/runner.js +36 -1
- package/dist/tasks/auth/add.d.ts +16 -0
- package/dist/tasks/auth/add.js +50 -0
- package/dist/tasks/auth/list.d.ts +14 -0
- package/dist/tasks/auth/list.js +31 -0
- package/dist/tasks/auth/load.d.ts +6 -0
- package/dist/tasks/auth/load.js +44 -0
- package/dist/tasks/auth/loadCurrent.d.ts +6 -0
- package/dist/tasks/auth/loadCurrent.js +24 -0
- package/dist/tasks/auth/remove.d.ts +13 -0
- package/dist/tasks/auth/remove.js +56 -0
- package/dist/tasks/auth/switch.d.ts +12 -0
- package/dist/tasks/auth/switch.js +43 -0
- package/dist/tasks/conf/info.d.ts +7 -0
- package/dist/tasks/conf/info.js +13 -8
- package/dist/tasks/task/createTask.js +4 -0
- package/dist/tasks/task/download.d.ts +58 -0
- package/dist/tasks/task/download.js +153 -0
- package/dist/tasks/task/publish.d.ts +41 -0
- package/dist/tasks/task/publish.js +106 -0
- package/dist/tasks/types.d.ts +10 -0
- package/dist/test/tasks/create.test.js +4 -0
- package/forge.json +32 -0
- package/logs/auth:list.log +4 -0
- package/logs/auth:load.log +2 -0
- package/logs/auth:loadCurrent.log +1 -0
- package/logs/conf:info.log +1 -0
- package/package.json +5 -4
- package/src/runner.ts +37 -1
- package/src/tasks/auth/add.ts +57 -0
- package/src/tasks/auth/list.ts +43 -0
- package/src/tasks/auth/load.ts +51 -0
- package/src/tasks/auth/loadCurrent.ts +35 -0
- package/src/tasks/auth/remove.ts +66 -0
- package/src/tasks/auth/switch.ts +53 -0
- package/src/tasks/conf/info.ts +16 -8
- package/src/tasks/task/createTask.ts +4 -0
- package/src/tasks/task/download.ts +192 -0
- package/src/tasks/task/publish.ts +135 -0
- package/src/tasks/types.ts +12 -0
- package/src/test/tasks/create.test.ts +4 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// TASK: loadCurrent
|
|
2
|
+
// Run this task with:
|
|
3
|
+
// forge task:run auth:loadCurrent
|
|
4
|
+
|
|
5
|
+
import { createTask } from '@forgehive/task'
|
|
6
|
+
import { Schema } from '@forgehive/schema'
|
|
7
|
+
|
|
8
|
+
import { load as loadProfiles } from './load'
|
|
9
|
+
import { type Profile } from '../types'
|
|
10
|
+
|
|
11
|
+
const schema = new Schema({})
|
|
12
|
+
|
|
13
|
+
const boundaries = {
|
|
14
|
+
loadProfiles: loadProfiles.asBoundary()
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const loadCurrent = createTask(
|
|
18
|
+
schema,
|
|
19
|
+
boundaries,
|
|
20
|
+
async function (_argv, { loadProfiles }): Promise<Profile> {
|
|
21
|
+
const profiles = await loadProfiles({})
|
|
22
|
+
|
|
23
|
+
if (!profiles.default || profiles.default === '') {
|
|
24
|
+
throw new Error('No default profile set. Please run forge task:run auth:add to create a profile.')
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const defaultProfile = profiles.profiles.find(profile => profile.name === profiles.default)
|
|
28
|
+
|
|
29
|
+
if (!defaultProfile) {
|
|
30
|
+
throw new Error(`Default profile "${profiles.default}" not found in profiles.`)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return { ...defaultProfile, name: profiles.default }
|
|
34
|
+
}
|
|
35
|
+
)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// TASK: remove
|
|
2
|
+
// Run this task with:
|
|
3
|
+
// forge task:run auth:remove --profileName [name]
|
|
4
|
+
|
|
5
|
+
import { createTask } from '@forgehive/task'
|
|
6
|
+
import { Schema } from '@forgehive/schema'
|
|
7
|
+
import path from 'path'
|
|
8
|
+
import fs from 'fs/promises'
|
|
9
|
+
import os from 'os'
|
|
10
|
+
|
|
11
|
+
import { load as loadProfiles } from './load'
|
|
12
|
+
import { type Profiles } from '../types'
|
|
13
|
+
|
|
14
|
+
const schema = new Schema({
|
|
15
|
+
profileName: Schema.string()
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
const boundaries = {
|
|
19
|
+
loadProfiles: loadProfiles.asBoundary(),
|
|
20
|
+
persistProfiles: async (profiles: Profiles): Promise<void> => {
|
|
21
|
+
const buildsPath = path.join(os.homedir(), '.forge')
|
|
22
|
+
const profilesPath = path.join(buildsPath, 'profiles.json')
|
|
23
|
+
await fs.writeFile(profilesPath, JSON.stringify(profiles, null, 2))
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const remove = createTask(
|
|
28
|
+
schema,
|
|
29
|
+
boundaries,
|
|
30
|
+
async function ({ profileName }, { loadProfiles, persistProfiles }) {
|
|
31
|
+
const profiles = await loadProfiles({})
|
|
32
|
+
|
|
33
|
+
// Check if profile exists
|
|
34
|
+
const profileExists = profiles.profiles.some(profile => profile.name === profileName)
|
|
35
|
+
|
|
36
|
+
if (!profileExists) {
|
|
37
|
+
throw new Error(`Profile "${profileName}" not found. Use auth:list to see available profiles.`)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Remove the profile using filter
|
|
41
|
+
profiles.profiles = profiles.profiles.filter(profile => profile.name !== profileName)
|
|
42
|
+
|
|
43
|
+
// If the removed profile was the default, update the default
|
|
44
|
+
if (profiles.default === profileName) {
|
|
45
|
+
if (profiles.profiles.length > 0) {
|
|
46
|
+
// Set the first available profile as default
|
|
47
|
+
profiles.default = profiles.profiles[0].name
|
|
48
|
+
console.log(`Default profile set to: ${profiles.default}`)
|
|
49
|
+
} else {
|
|
50
|
+
// No profiles left, set default to empty
|
|
51
|
+
profiles.default = ''
|
|
52
|
+
console.log('No profiles left. Default set to empty.')
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Persist updated profiles
|
|
57
|
+
await persistProfiles(profiles)
|
|
58
|
+
|
|
59
|
+
console.log(`Profile "${profileName}" has been removed.`)
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
status: 'Ok',
|
|
63
|
+
message: `Profile "${profileName}" has been removed.`
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
)
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// TASK: switch
|
|
2
|
+
// Run this task with:
|
|
3
|
+
// forge task:run auth:switch --profileName [name]
|
|
4
|
+
|
|
5
|
+
import { createTask } from '@forgehive/task'
|
|
6
|
+
import { Schema } from '@forgehive/schema'
|
|
7
|
+
import path from 'path'
|
|
8
|
+
import fs from 'fs/promises'
|
|
9
|
+
import os from 'os'
|
|
10
|
+
|
|
11
|
+
import { load as loadProfiles } from './load'
|
|
12
|
+
import { type Profiles } from '../types'
|
|
13
|
+
|
|
14
|
+
const schema = new Schema({
|
|
15
|
+
profileName: Schema.string()
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
const boundaries = {
|
|
19
|
+
loadProfiles: loadProfiles.asBoundary(),
|
|
20
|
+
persistProfiles: async (profiles: Profiles): Promise<void> => {
|
|
21
|
+
const buildsPath = path.join(os.homedir(), '.forge')
|
|
22
|
+
const profilesPath = path.join(buildsPath, 'profiles.json')
|
|
23
|
+
await fs.writeFile(profilesPath, JSON.stringify(profiles, null, 2))
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const switchProfile = createTask(
|
|
28
|
+
schema,
|
|
29
|
+
boundaries,
|
|
30
|
+
async function ({ profileName }, { loadProfiles, persistProfiles }) {
|
|
31
|
+
// Load profiles
|
|
32
|
+
const profiles = await loadProfiles({})
|
|
33
|
+
|
|
34
|
+
// Check if profile exists
|
|
35
|
+
const profileExists = profiles.profiles.some(profile => profile.name === profileName)
|
|
36
|
+
|
|
37
|
+
if (!profileExists) {
|
|
38
|
+
throw new Error(`Profile "${profileName}" not found. Use auth:list to see available profiles.`)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Update default profile
|
|
42
|
+
profiles.default = profileName
|
|
43
|
+
|
|
44
|
+
// Save updated profiles
|
|
45
|
+
await persistProfiles(profiles)
|
|
46
|
+
|
|
47
|
+
console.log(`Switched to profile: ${profileName}`)
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
default: profileName
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
)
|
package/src/tasks/conf/info.ts
CHANGED
|
@@ -7,26 +7,34 @@ import { Schema } from '@forgehive/schema'
|
|
|
7
7
|
import * as fs from 'fs'
|
|
8
8
|
import * as path from 'path'
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
})
|
|
10
|
+
import { loadCurrent as loadCurrentProfile } from '../auth/loadCurrent'
|
|
11
|
+
|
|
12
|
+
const schema = new Schema({})
|
|
13
13
|
|
|
14
14
|
const boundaries = {
|
|
15
|
-
readFile: async (filePath: string): Promise<string> => fs.promises.readFile(filePath, 'utf-8')
|
|
15
|
+
readFile: async (filePath: string): Promise<string> => fs.promises.readFile(filePath, 'utf-8'),
|
|
16
|
+
loadCurrentProfile: loadCurrentProfile.asBoundary()
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
export const info = createTask(
|
|
19
20
|
schema,
|
|
20
21
|
boundaries,
|
|
21
|
-
async function (_argv,
|
|
22
|
+
async function (_argv, { loadCurrentProfile, readFile }) {
|
|
22
23
|
const packageJsonPath = path.join(__dirname, '../../../package.json')
|
|
23
|
-
console.log('packageJsonPath', packageJsonPath)
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
|
|
26
|
+
const packageJsonContent = await readFile(packageJsonPath)
|
|
26
27
|
const packageJson = JSON.parse(packageJsonContent)
|
|
27
28
|
|
|
29
|
+
const profile = await loadCurrentProfile({})
|
|
30
|
+
|
|
28
31
|
return {
|
|
29
|
-
version: packageJson.version
|
|
32
|
+
version: packageJson.version,
|
|
33
|
+
profile: {
|
|
34
|
+
name: profile.name,
|
|
35
|
+
url: profile.url,
|
|
36
|
+
apiKey: profile.apiKey
|
|
37
|
+
}
|
|
30
38
|
}
|
|
31
39
|
}
|
|
32
40
|
)
|
|
@@ -18,6 +18,8 @@ const TASK_TEMPLATE = `// TASK: {{ taskName }}
|
|
|
18
18
|
import { createTask } from '@forgehive/task'
|
|
19
19
|
import { Schema } from '@forgehive/schema'
|
|
20
20
|
|
|
21
|
+
const description = 'Add task description here'
|
|
22
|
+
|
|
21
23
|
const schema = new Schema({
|
|
22
24
|
// Add your schema definitions here
|
|
23
25
|
// example: myParam: Schema.string()
|
|
@@ -40,6 +42,8 @@ export const {{ taskName }} = createTask(
|
|
|
40
42
|
return status
|
|
41
43
|
}
|
|
42
44
|
)
|
|
45
|
+
|
|
46
|
+
{{ taskName }}.setDescription(description)
|
|
43
47
|
`
|
|
44
48
|
|
|
45
49
|
const schema = new Schema({
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
// TASK: download
|
|
2
|
+
// Run this task with:
|
|
3
|
+
// forge task:run task:download --descriptorName [name] --uuid [task-uuid]
|
|
4
|
+
|
|
5
|
+
import { createTask } from '@forgehive/task'
|
|
6
|
+
import { Schema } from '@forgehive/schema'
|
|
7
|
+
import axios from 'axios'
|
|
8
|
+
import path from 'path'
|
|
9
|
+
import fs from 'fs/promises'
|
|
10
|
+
import { camelCase } from '../../utils/camelCase'
|
|
11
|
+
import { load as loadConf } from '../conf/load'
|
|
12
|
+
import { loadCurrent as loadCurrentProfile } from '../auth/loadCurrent'
|
|
13
|
+
import { Profile, type ForgeConf } from '../types'
|
|
14
|
+
|
|
15
|
+
const schema = new Schema({
|
|
16
|
+
descriptorName: Schema.string(),
|
|
17
|
+
uuid: Schema.string()
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
const boundaries = {
|
|
21
|
+
loadCurrentProfile: loadCurrentProfile.asBoundary(),
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
23
|
+
downloadTask: async (uuid: string, profile: Profile): Promise<any> => {
|
|
24
|
+
const downloadUrl = `${profile.url}/api/tasks/download`
|
|
25
|
+
|
|
26
|
+
console.log(`Downloading task from ${downloadUrl}...`)
|
|
27
|
+
|
|
28
|
+
const authToken = `${profile.apiKey}:${profile.apiSecret}`
|
|
29
|
+
const response = await axios.post(downloadUrl, { uuid }, {
|
|
30
|
+
headers: {
|
|
31
|
+
Authorization: `Bearer ${authToken}`,
|
|
32
|
+
'Content-Type': 'application/json'
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
return response.data
|
|
37
|
+
},
|
|
38
|
+
loadConf: loadConf.asBoundary(),
|
|
39
|
+
getCwd: async (): Promise<string> => {
|
|
40
|
+
return process.cwd()
|
|
41
|
+
},
|
|
42
|
+
parseTaskName: async (taskDescriptor: string): Promise<{
|
|
43
|
+
descriptor: string
|
|
44
|
+
taskName: string
|
|
45
|
+
fileName: string
|
|
46
|
+
dir?: string
|
|
47
|
+
}> => {
|
|
48
|
+
const res: string[] = taskDescriptor.split(':')
|
|
49
|
+
|
|
50
|
+
if (res.length === 1) {
|
|
51
|
+
return {
|
|
52
|
+
descriptor: `${camelCase(res[0])}`,
|
|
53
|
+
taskName: `${camelCase(res[0])}`,
|
|
54
|
+
fileName: `${camelCase(res[0])}.ts`
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
dir: res[0],
|
|
60
|
+
descriptor: `${res[0]}:${camelCase(res[1])}`,
|
|
61
|
+
taskName: `${camelCase(res[1])}`,
|
|
62
|
+
fileName: `${camelCase(res[1])}.ts`
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
persistTask: async (dir: string, fileName: string, content: string, cwd: string): Promise<{ path: string }> => {
|
|
66
|
+
const dirPath = path.resolve(cwd, dir)
|
|
67
|
+
const taskPath = path.resolve(dirPath, fileName)
|
|
68
|
+
|
|
69
|
+
await fs.mkdir(dirPath, { recursive: true })
|
|
70
|
+
await fs.writeFile(taskPath, content, 'utf-8')
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
path: taskPath.toString()
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
persistConf: async (forge: ForgeConf, cwd: string): Promise<void> => {
|
|
78
|
+
const forgePath = path.join(cwd, 'forge.json')
|
|
79
|
+
await fs.writeFile(forgePath, JSON.stringify(forge, null, 2))
|
|
80
|
+
},
|
|
81
|
+
checkTaskExists: async (dir: string, fileName: string): Promise<boolean> => {
|
|
82
|
+
const taskPath = path.resolve(dir, fileName)
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
await fs.access(taskPath)
|
|
86
|
+
return true
|
|
87
|
+
} catch {
|
|
88
|
+
return false
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export const download = createTask(
|
|
94
|
+
schema,
|
|
95
|
+
boundaries,
|
|
96
|
+
async function ({ descriptorName, uuid }, {
|
|
97
|
+
downloadTask,
|
|
98
|
+
getCwd,
|
|
99
|
+
parseTaskName,
|
|
100
|
+
persistTask,
|
|
101
|
+
loadConf,
|
|
102
|
+
persistConf,
|
|
103
|
+
checkTaskExists,
|
|
104
|
+
loadCurrentProfile
|
|
105
|
+
}) {
|
|
106
|
+
console.log(`Attempting to download task with descriptor: ${descriptorName} and uuid: ${uuid}`)
|
|
107
|
+
|
|
108
|
+
// Parse descriptor name to get task details
|
|
109
|
+
const { taskName, fileName, descriptor, dir } = await parseTaskName(descriptorName)
|
|
110
|
+
const profile = await loadCurrentProfile({})
|
|
111
|
+
const cwd = await getCwd()
|
|
112
|
+
const forge = await loadConf({})
|
|
113
|
+
|
|
114
|
+
let taskPath: string = forge.paths.tasks
|
|
115
|
+
|
|
116
|
+
if (dir !== undefined) {
|
|
117
|
+
taskPath = path.join(taskPath, dir)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Check if task already exists
|
|
121
|
+
const taskExists = await checkTaskExists(taskPath, fileName)
|
|
122
|
+
if (taskExists) {
|
|
123
|
+
console.log(`Task ${descriptor} already exists at ${taskPath}/${fileName}`)
|
|
124
|
+
return {
|
|
125
|
+
error: 'Task already exists',
|
|
126
|
+
taskPath: `${taskPath}/${fileName}`,
|
|
127
|
+
descriptor
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Download from hive api server
|
|
132
|
+
let response
|
|
133
|
+
try {
|
|
134
|
+
response = await downloadTask(uuid, profile)
|
|
135
|
+
} catch (e: unknown) {
|
|
136
|
+
const error = e as { status: number, message: string }
|
|
137
|
+
console.error('Error downloading task:', error.message, error.status)
|
|
138
|
+
|
|
139
|
+
if (error.status === 404) {
|
|
140
|
+
return {
|
|
141
|
+
error: 'Task not found',
|
|
142
|
+
taskPath: `${taskPath}/${fileName}`,
|
|
143
|
+
descriptor
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return {
|
|
148
|
+
error: 'Failed to download task',
|
|
149
|
+
message: error.message,
|
|
150
|
+
taskPath: `${taskPath}/${fileName}`,
|
|
151
|
+
descriptor
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
console.log(`
|
|
156
|
+
==================================================
|
|
157
|
+
Starting task download!
|
|
158
|
+
Creating: ${taskName}
|
|
159
|
+
Dir: ${dir ?? ''}
|
|
160
|
+
Into: ${taskPath}
|
|
161
|
+
==================================================
|
|
162
|
+
`)
|
|
163
|
+
|
|
164
|
+
console.log('Writing task file:', taskPath, fileName)
|
|
165
|
+
console.log('Handler:', response.handler)
|
|
166
|
+
console.log('Source code:', response.sourceCode)
|
|
167
|
+
|
|
168
|
+
// Persist task with cwd
|
|
169
|
+
await persistTask(taskPath, fileName, response.sourceCode, cwd)
|
|
170
|
+
|
|
171
|
+
// Update forge.json with the new task
|
|
172
|
+
if (forge.tasks === undefined) {
|
|
173
|
+
forge.tasks = {}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
forge.tasks[descriptor] = {
|
|
177
|
+
path: `${taskPath}/${fileName}`,
|
|
178
|
+
handler: response.handler
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
console.log('Forge:', forge)
|
|
182
|
+
|
|
183
|
+
await persistConf(forge, cwd)
|
|
184
|
+
|
|
185
|
+
return {
|
|
186
|
+
taskPath,
|
|
187
|
+
fileName,
|
|
188
|
+
descriptor,
|
|
189
|
+
handler: response.handler
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
)
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
// TASK: publish
|
|
2
|
+
// Run this task with:
|
|
3
|
+
// forge task:run task:publish --descriptorMame task-name
|
|
4
|
+
|
|
5
|
+
import { createTask } from '@forgehive/task'
|
|
6
|
+
import { Schema } from '@forgehive/schema'
|
|
7
|
+
import axios from 'axios'
|
|
8
|
+
|
|
9
|
+
import path from 'path'
|
|
10
|
+
import fs from 'fs/promises'
|
|
11
|
+
import os from 'os'
|
|
12
|
+
|
|
13
|
+
import { load as loadConf } from '../conf/load'
|
|
14
|
+
import { create as bundleCreate } from '../bundle/create'
|
|
15
|
+
import { load as bundleLoad } from '../bundle/load'
|
|
16
|
+
import { loadCurrent as loadCurrentProfile } from '../auth/loadCurrent'
|
|
17
|
+
import { Profile } from '../types'
|
|
18
|
+
|
|
19
|
+
const schema = new Schema({
|
|
20
|
+
descriptorName: Schema.string()
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
const boundaries = {
|
|
24
|
+
getCwd: async (): Promise<string> => {
|
|
25
|
+
return process.cwd()
|
|
26
|
+
},
|
|
27
|
+
loadConf: loadConf.asBoundary(),
|
|
28
|
+
loadCurrentProfile: loadCurrentProfile.asBoundary(),
|
|
29
|
+
bundleCreate: bundleCreate.asBoundary(),
|
|
30
|
+
bundleLoad: bundleLoad.asBoundary(),
|
|
31
|
+
readFileUtf8: async (filePath: string): Promise<string> => {
|
|
32
|
+
return fs.readFile(filePath, 'utf-8')
|
|
33
|
+
},
|
|
34
|
+
readFileBinary: async (filePath: string): Promise<Buffer> => {
|
|
35
|
+
return fs.readFile(filePath)
|
|
36
|
+
},
|
|
37
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
38
|
+
publishTask: async (data: any, profile: Profile): Promise<any> => {
|
|
39
|
+
const publishUrl = `${profile.url}/api/tasks/publish`
|
|
40
|
+
|
|
41
|
+
console.log(`Publishing task to ${publishUrl}...`)
|
|
42
|
+
const authToken = `${profile.apiKey}:${profile.apiSecret}`
|
|
43
|
+
const response = await axios.post(publishUrl, data, {
|
|
44
|
+
headers: {
|
|
45
|
+
Authorization: `Bearer ${authToken}`,
|
|
46
|
+
'Content-Type': 'application/json'
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
return response.data
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
ensureBuildsFolder: async (): Promise<string> => {
|
|
54
|
+
const buildsPath = path.join(os.homedir(), '.forge', 'builds')
|
|
55
|
+
try {
|
|
56
|
+
await fs.access(buildsPath)
|
|
57
|
+
} catch {
|
|
58
|
+
await fs.mkdir(buildsPath, { recursive: true })
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return buildsPath
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export const publish = createTask(
|
|
66
|
+
schema,
|
|
67
|
+
boundaries,
|
|
68
|
+
async function ({ descriptorName }, {
|
|
69
|
+
getCwd,
|
|
70
|
+
ensureBuildsFolder,
|
|
71
|
+
loadConf,
|
|
72
|
+
bundleCreate,
|
|
73
|
+
bundleLoad,
|
|
74
|
+
readFileUtf8,
|
|
75
|
+
readFileBinary,
|
|
76
|
+
publishTask,
|
|
77
|
+
loadCurrentProfile
|
|
78
|
+
}) {
|
|
79
|
+
const cwd = await getCwd()
|
|
80
|
+
const forgeJson = await loadConf({})
|
|
81
|
+
const profile = await loadCurrentProfile({})
|
|
82
|
+
|
|
83
|
+
const taskDescriptor = forgeJson.tasks[descriptorName as keyof typeof forgeJson.tasks]
|
|
84
|
+
const projectName = forgeJson.project.name
|
|
85
|
+
|
|
86
|
+
if (taskDescriptor === undefined) {
|
|
87
|
+
throw new Error('Task is not defined on forge.json')
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const entryPoint = path.join(cwd, taskDescriptor.path)
|
|
91
|
+
const buildsPath = await ensureBuildsFolder()
|
|
92
|
+
const outputFile = path.join(buildsPath, `${descriptorName}.js`)
|
|
93
|
+
|
|
94
|
+
console.log('entryPoint:', entryPoint)
|
|
95
|
+
console.log('buildsPath:', buildsPath)
|
|
96
|
+
console.log('outputFile:', outputFile)
|
|
97
|
+
|
|
98
|
+
// Bundle the task
|
|
99
|
+
await bundleCreate({
|
|
100
|
+
entryPoint,
|
|
101
|
+
outputFile
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
// Load the bundled task
|
|
105
|
+
const bundle = await bundleLoad({
|
|
106
|
+
bundlePath: outputFile
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
// Get the task handler
|
|
110
|
+
const task = bundle[taskDescriptor.handler]
|
|
111
|
+
const description = task.getDescription() ?? ''
|
|
112
|
+
const schema = task.getSchema() || new Schema({})
|
|
113
|
+
const schemaDescriptor = schema.describe()
|
|
114
|
+
|
|
115
|
+
// Read the task file content and bundle
|
|
116
|
+
const sourceCode = await readFileUtf8(entryPoint)
|
|
117
|
+
const bundleContent = await readFileBinary(outputFile)
|
|
118
|
+
|
|
119
|
+
const data = {
|
|
120
|
+
...taskDescriptor,
|
|
121
|
+
taskName: descriptorName,
|
|
122
|
+
projectName,
|
|
123
|
+
description,
|
|
124
|
+
schemaDescriptor: JSON.stringify(schemaDescriptor),
|
|
125
|
+
sourceCode,
|
|
126
|
+
bundle: bundleContent.toString('base64')
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Publish to hive api server
|
|
130
|
+
const response = await publishTask(data, profile)
|
|
131
|
+
|
|
132
|
+
console.log('Publish response:', response)
|
|
133
|
+
return { descriptor: taskDescriptor, publishResponse: response }
|
|
134
|
+
}
|
|
135
|
+
)
|
package/src/tasks/types.ts
CHANGED
|
@@ -39,3 +39,15 @@ export interface TaskName {
|
|
|
39
39
|
fileName: string
|
|
40
40
|
dir?: string
|
|
41
41
|
}
|
|
42
|
+
|
|
43
|
+
export interface Profile {
|
|
44
|
+
name: string
|
|
45
|
+
apiKey: string
|
|
46
|
+
apiSecret: string
|
|
47
|
+
url: string
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface Profiles {
|
|
51
|
+
default: string
|
|
52
|
+
profiles: Profile[]
|
|
53
|
+
}
|
|
@@ -12,6 +12,8 @@ const expectedContent = `// TASK: newTask
|
|
|
12
12
|
import { createTask } from '@forgehive/task'
|
|
13
13
|
import { Schema } from '@forgehive/schema'
|
|
14
14
|
|
|
15
|
+
const description = 'Add task description here'
|
|
16
|
+
|
|
15
17
|
const schema = new Schema({
|
|
16
18
|
// Add your schema definitions here
|
|
17
19
|
// example: myParam: Schema.string()
|
|
@@ -34,6 +36,8 @@ export const newTask = createTask(
|
|
|
34
36
|
return status
|
|
35
37
|
}
|
|
36
38
|
)
|
|
39
|
+
|
|
40
|
+
newTask.setDescription(description)
|
|
37
41
|
`
|
|
38
42
|
|
|
39
43
|
describe('Create task', () => {
|