From c3695384ee122a1a7487a3bbcbe4a0ee8632ca98 Mon Sep 17 00:00:00 2001 From: stefano Date: Sun, 4 Aug 2024 23:57:43 +0100 Subject: [PATCH 1/5] Add upload folders script --- examples/single/test/test.json | 3 + examples/single/test1/test1.json | 3 + lib/cli.ts | 20 ++++++- lib/config.ts | 6 ++ lib/deploy.ts | 94 ++++++++++++++++++++++++++++++++ 5 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 examples/single/test/test.json create mode 100644 examples/single/test1/test1.json diff --git a/examples/single/test/test.json b/examples/single/test/test.json new file mode 100644 index 0000000..e225b92 --- /dev/null +++ b/examples/single/test/test.json @@ -0,0 +1,3 @@ +{ + "data": "this is test" +} \ No newline at end of file diff --git a/examples/single/test1/test1.json b/examples/single/test1/test1.json new file mode 100644 index 0000000..816865d --- /dev/null +++ b/examples/single/test1/test1.json @@ -0,0 +1,3 @@ +{ + "data": "this is test1" +} \ No newline at end of file diff --git a/lib/cli.ts b/lib/cli.ts index 0c576f9..2b18411 100644 --- a/lib/cli.ts +++ b/lib/cli.ts @@ -2,7 +2,7 @@ import { buildApp } from "@/lib/build"; import { initProject } from "@/lib/init"; import { Logger, LogLevel } from "@/lib/logger"; import { Command } from "commander"; -import { deploy, deployAppData, DeployOptions } from "./deploy"; +import { deploy, deployAppData, deployAppDataFolders, DeployOptions } from "./deploy"; import { dev } from "./dev"; import { cloneRepository } from "./repository"; import { buildWorkspace, devWorkspace } from "./workspace"; @@ -143,6 +143,24 @@ async function run() { }) }); + program + .command("uploadData") + .description("Upload data to SocialDB from bos.config.json configuration") + .argument("[appName]", "Workspace app name to deploy") + .option("-n, --network ", "network to deploy to", "mainnet") + .action(async (appName, options) => { + const deployOptions: DeployOptions = { + signerPublicKey: options.signerPublicKey, + signerPrivateKey: options.signerPrivateKey, + network: options.network, + deployAccountId: options.deployAccountId, + }; + + await deployAppDataFolders(appName, deployOptions).catch((e: Error) => { + log.error(e.stack || e.message); + }) + }); + program.parse(); } diff --git a/lib/config.ts b/lib/config.ts index b91f387..4645ad5 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -20,6 +20,9 @@ export interface BaseConfig { index?: string; // widget to use as index aliasPrefix?: string; // prefix to use for aliases, default is "alias" aliasesContainsPrefix?: boolean; // aliases keys contains prefix (default is false) + data?: { + include: string[]; // specify folder's array to upload along with widget + } } interface NetworkConfig { @@ -62,6 +65,9 @@ const baseConfigSchema = Joi.object({ aliasPrefix: Joi.string().allow(null), aliasesContainsPrefix: Joi.boolean().allow(null), index: Joi.string().allow(null), + data: Joi.object({ + include: Joi.array().items(Joi.string()).min(1).required() + }).optional() }); const networkConfigSchema = Joi.object({ diff --git a/lib/deploy.ts b/lib/deploy.ts index 6f1dcd7..23d992c 100644 --- a/lib/deploy.ts +++ b/lib/deploy.ts @@ -176,6 +176,100 @@ export async function deployAppData(appName: string, opts: DeployOptions) { }); } +export async function deployAppDataFolders(appName: string, opts: DeployOptions) { + const config = await readConfig(path.join(appName, "bos.config.json"), opts.network); + const BOS_SIGNER_ACCOUNT_ID = config.accounts.signer || opts.signerAccountId || config.account; + + if (!BOS_SIGNER_ACCOUNT_ID) { + console.log(`App account is not defined for ${appName}. Skipping data upload`); + return; + } + + if (!config.data || !Array.isArray(config.data.include) || config.data.include.length === 0) throw new Error('Config must contain a data.include array with at least one folder'); + + const result = {}; + + for (const folder of config.data.include) { + try { + const files = await fs.readdirSync(folder); + + for (const file of files) { + const filePath = path.join(folder, file); + const fileContent = await fs.readFileSync(filePath, 'utf8'); + const jsonContent = JSON.parse(fileContent); + + const key = path.basename(file, '.json'); + result[key] = jsonContent; + } + } catch (error) { + console.error(`Error processing folder ${folder}:`, error); + } + } + + const outputPath = path.join(process.cwd(), 'combined_output.json'); + await fs.writeFileSync(outputPath, JSON.stringify(result, null, 2)); + + console.log(`Combined JSON written to ${outputPath}`); + + // const dataJSON = fs.readFileSync( + // path.join(appName, DEPLOY_DIST_FOLDER, "data.json"), + // "utf8" + // ); + + // const args = { data: JSON.parse(dataJSON) }; + // const argsBase64 = Buffer.from(JSON.stringify(args)).toString("base64"); + + // const BOS_SIGNER_PUBLIC_KEY = opts?.signerPublicKey; + // const BOS_SIGNER_PRIVATE_KEY = opts?.signerPrivateKey; + + // const automaticSignIn = [ + // "sign-with-plaintext-private-key", + // "--signer-public-key", + // BOS_SIGNER_PUBLIC_KEY, + // "--signer-private-key", + // BOS_SIGNER_PRIVATE_KEY, + // "send" + // ] + + // let command = [ + // "near-cli-rs", + // "contract", + // "call-function", + // "as-transaction", + // opts.network === "mainnet" ? SOCIAL_CONTRACT.mainnet : SOCIAL_CONTRACT.testnet, + // "set", + // "base64-args", + // `${argsBase64}`, + // "prepaid-gas", + // "300 TeraGas", + // "attached-deposit", + // "0.15 NEAR", // deposit + // "sign-as", + // BOS_SIGNER_ACCOUNT_ID, + // "network-config", + // opts.network, + // ]; + + // if (BOS_SIGNER_PUBLIC_KEY && BOS_SIGNER_PRIVATE_KEY) command = command.concat(automaticSignIn) + + // const deployProcess = spawn("npx", command, { + // cwd: path.join(appName, DEPLOY_DIST_FOLDER), + // stdio: "inherit", + // }); + + // deployProcess.on("close", (code) => { + // if (code === 0) { + // console.log(`Uploaded data for ${appName}`); + // } else { + // console.error(`Data upload failed with code ${code}`); + // } + // }); + + // deployProcess.on("error", (err) => { + // console.error(`Error uploading data for ${appName}:\n${err.message}`); + // }); +} + export async function deploy(appName: string, opts: DeployOptions) { const src = "."; From 2b02aea4a51ebab641c1e5db904d0c17a4b93b13 Mon Sep 17 00:00:00 2001 From: stefano Date: Mon, 5 Aug 2024 00:20:30 +0100 Subject: [PATCH 2/5] Add support for nested folders --- examples/single/bos.config.json | 3 +++ .../single/test/nestedTest/nestedTest.json | 3 +++ lib/deploy.ts | 13 ++--------- lib/utils/fs.ts | 23 ++++++++++++++++++- 4 files changed, 30 insertions(+), 12 deletions(-) create mode 100644 examples/single/test/nestedTest/nestedTest.json diff --git a/examples/single/bos.config.json b/examples/single/bos.config.json index 273c159..6704118 100644 --- a/examples/single/bos.config.json +++ b/examples/single/bos.config.json @@ -8,5 +8,8 @@ "aliases": ["./aliases.testnet.json"], "index": "quickstart.testnet/widget/home" } + }, + "data": { + "include": ["test", "test1"] } } diff --git a/examples/single/test/nestedTest/nestedTest.json b/examples/single/test/nestedTest/nestedTest.json new file mode 100644 index 0000000..519728a --- /dev/null +++ b/examples/single/test/nestedTest/nestedTest.json @@ -0,0 +1,3 @@ +{ + "data": "this is a nested folder" +} \ No newline at end of file diff --git a/lib/deploy.ts b/lib/deploy.ts index 23d992c..fb4908c 100644 --- a/lib/deploy.ts +++ b/lib/deploy.ts @@ -5,7 +5,7 @@ import fs from "fs"; import { buildApp } from "@/lib/build"; import { readConfig } from "@/lib/config"; import { Network } from "@/lib/types"; -import { move, pathExists, readdir, remove } from "@/lib/utils/fs"; +import { move, pathExists, processDirectory, readdir, remove } from "@/lib/utils/fs"; import { readWorkspace } from "@/lib/workspace"; import { SOCIAL_CONTRACT } from './server'; @@ -191,16 +191,7 @@ export async function deployAppDataFolders(appName: string, opts: DeployOptions) for (const folder of config.data.include) { try { - const files = await fs.readdirSync(folder); - - for (const file of files) { - const filePath = path.join(folder, file); - const fileContent = await fs.readFileSync(filePath, 'utf8'); - const jsonContent = JSON.parse(fileContent); - - const key = path.basename(file, '.json'); - result[key] = jsonContent; - } + await processDirectory(folder, result); } catch (error) { console.error(`Error processing folder ${folder}:`, error); } diff --git a/lib/utils/fs.ts b/lib/utils/fs.ts index 52ef78b..399a511 100644 --- a/lib/utils/fs.ts +++ b/lib/utils/fs.ts @@ -1,4 +1,5 @@ import { copy, ensureDir, move, outputFile, pathExists, readdir, readFile, readJson, remove, writeJson, existsSync, promises } from 'fs-extra'; +import { readdirSync, readFileSync } from 'fs'; import path from 'path'; async function loopThroughFiles(pwd: string, callback: (file: string) => Promise) { @@ -16,4 +17,24 @@ async function loopThroughFiles(pwd: string, callback: (file: string) => Promise } } -export { copy, ensureDir, loopThroughFiles, move, outputFile, pathExists, readdir, readFile, readJson, remove, writeJson, existsSync, promises }; +async function processDirectory(dir, result) { + const files = await readdirSync(dir, { withFileTypes: true }); + for (const file of files) { + const filePath = path.join(dir, file.name); + if (file.isDirectory()) { + await processDirectory(filePath, result); + } else if (path.extname(file.name).toLowerCase() === '.json') { + try { + const fileContent = await readFileSync(filePath, 'utf8'); + const jsonContent = JSON.parse(fileContent); + const relativePath = path.relative(process.cwd(), filePath); + const key = path.dirname(relativePath) + '/' + path.basename(file.name, '.json'); + result[key] = jsonContent; + } catch (error) { + console.error(`Error processing file ${filePath}:`, error); + } + } + } +} + +export { copy, ensureDir, loopThroughFiles, move, outputFile, pathExists, readdir, readFile, readJson, remove, writeJson, existsSync, promises, processDirectory }; From a12fb499e446454f16e2139af52445427e315b49 Mon Sep 17 00:00:00 2001 From: stefano Date: Mon, 5 Aug 2024 11:38:12 +0100 Subject: [PATCH 3/5] Smart contract panic --- lib/cli.ts | 2 + lib/deploy.ts | 142 +++++++++++++++++++++++++++----------------------- 2 files changed, 80 insertions(+), 64 deletions(-) diff --git a/lib/cli.ts b/lib/cli.ts index 2b18411..01246b8 100644 --- a/lib/cli.ts +++ b/lib/cli.ts @@ -148,6 +148,8 @@ async function run() { .description("Upload data to SocialDB from bos.config.json configuration") .argument("[appName]", "Workspace app name to deploy") .option("-n, --network ", "network to deploy to", "mainnet") + .option("--signerPublicKey ", "Signer public key") + .option("--signerPrivateKey ", "Signer private key") .action(async (appName, options) => { const deployOptions: DeployOptions = { signerPublicKey: options.signerPublicKey, diff --git a/lib/deploy.ts b/lib/deploy.ts index fb4908c..dbdd34a 100644 --- a/lib/deploy.ts +++ b/lib/deploy.ts @@ -176,16 +176,32 @@ export async function deployAppData(appName: string, opts: DeployOptions) { }); } -export async function deployAppDataFolders(appName: string, opts: DeployOptions) { - const config = await readConfig(path.join(appName, "bos.config.json"), opts.network); - const BOS_SIGNER_ACCOUNT_ID = config.accounts.signer || opts.signerAccountId || config.account; +export async function deployAppDataFolders( + appName: string, + opts: DeployOptions +) { + const config = await readConfig( + path.join(appName, "bos.config.json"), + opts.network + ); + const BOS_SIGNER_ACCOUNT_ID = + config.accounts.signer || opts.signerAccountId || config.account; if (!BOS_SIGNER_ACCOUNT_ID) { - console.log(`App account is not defined for ${appName}. Skipping data upload`); + console.log( + `App account is not defined for ${appName}. Skipping data upload` + ); return; } - if (!config.data || !Array.isArray(config.data.include) || config.data.include.length === 0) throw new Error('Config must contain a data.include array with at least one folder'); + if ( + !config.data || + !Array.isArray(config.data.include) || + config.data.include.length === 0 + ) + throw new Error( + "Config must contain a data.include array with at least one folder" + ); const result = {}; @@ -197,68 +213,66 @@ export async function deployAppDataFolders(appName: string, opts: DeployOptions) } } - const outputPath = path.join(process.cwd(), 'combined_output.json'); - await fs.writeFileSync(outputPath, JSON.stringify(result, null, 2)); + const args = { + data: { + [config.account]: result, + }, + }; + + const argsBase64 = Buffer.from(JSON.stringify(args)).toString("base64"); + + let command = [ + "near-cli-rs", + "contract", + "call-function", + "as-transaction", + opts.network === "mainnet" + ? SOCIAL_CONTRACT.mainnet + : SOCIAL_CONTRACT.testnet, + "set", + "base64-args", + `${argsBase64}`, + "prepaid-gas", + "300 TeraGas", + "attached-deposit", + "0.15 NEAR", // deposit + "sign-as", + BOS_SIGNER_ACCOUNT_ID, + "network-config", + opts.network, + ]; + + const BOS_SIGNER_PUBLIC_KEY = opts?.signerPublicKey; + const BOS_SIGNER_PRIVATE_KEY = opts?.signerPrivateKey; + + const automaticSignIn = [ + "sign-with-plaintext-private-key", + "--signer-public-key", + BOS_SIGNER_PUBLIC_KEY, + "--signer-private-key", + BOS_SIGNER_PRIVATE_KEY, + "send", + ]; - console.log(`Combined JSON written to ${outputPath}`); + if (BOS_SIGNER_PUBLIC_KEY && BOS_SIGNER_PRIVATE_KEY) + command = command.concat(automaticSignIn); - // const dataJSON = fs.readFileSync( - // path.join(appName, DEPLOY_DIST_FOLDER, "data.json"), - // "utf8" - // ); + const deployProcess = spawn("npx", command, { + cwd: path.join(appName, DEPLOY_DIST_FOLDER), + stdio: "inherit", + }); - // const args = { data: JSON.parse(dataJSON) }; - // const argsBase64 = Buffer.from(JSON.stringify(args)).toString("base64"); - - // const BOS_SIGNER_PUBLIC_KEY = opts?.signerPublicKey; - // const BOS_SIGNER_PRIVATE_KEY = opts?.signerPrivateKey; - - // const automaticSignIn = [ - // "sign-with-plaintext-private-key", - // "--signer-public-key", - // BOS_SIGNER_PUBLIC_KEY, - // "--signer-private-key", - // BOS_SIGNER_PRIVATE_KEY, - // "send" - // ] - - // let command = [ - // "near-cli-rs", - // "contract", - // "call-function", - // "as-transaction", - // opts.network === "mainnet" ? SOCIAL_CONTRACT.mainnet : SOCIAL_CONTRACT.testnet, - // "set", - // "base64-args", - // `${argsBase64}`, - // "prepaid-gas", - // "300 TeraGas", - // "attached-deposit", - // "0.15 NEAR", // deposit - // "sign-as", - // BOS_SIGNER_ACCOUNT_ID, - // "network-config", - // opts.network, - // ]; - - // if (BOS_SIGNER_PUBLIC_KEY && BOS_SIGNER_PRIVATE_KEY) command = command.concat(automaticSignIn) - - // const deployProcess = spawn("npx", command, { - // cwd: path.join(appName, DEPLOY_DIST_FOLDER), - // stdio: "inherit", - // }); - - // deployProcess.on("close", (code) => { - // if (code === 0) { - // console.log(`Uploaded data for ${appName}`); - // } else { - // console.error(`Data upload failed with code ${code}`); - // } - // }); - - // deployProcess.on("error", (err) => { - // console.error(`Error uploading data for ${appName}:\n${err.message}`); - // }); + deployProcess.on("close", (code) => { + if (code === 0) { + console.log(`Uploaded data for ${appName}`); + } else { + console.error(`Data upload failed with code ${code}`); + } + }); + + deployProcess.on("error", (err) => { + console.error(`Error uploading data for ${appName}:\n${err.message}`); + }); } export async function deploy(appName: string, opts: DeployOptions) { From b9efc3b3163aa92ba8207eccb7b7c84b421a50a3 Mon Sep 17 00:00:00 2001 From: stefano Date: Tue, 6 Aug 2024 22:32:03 +0100 Subject: [PATCH 4/5] Fix data creation + add test --- examples/single/bos.config.json | 3 - .../single/test/nestedTest/nestedTest.json | 3 - examples/single/test/test.json | 3 - examples/single/test1/test1.json | 3 - lib/deploy.ts | 8 +-- lib/utils/fs.ts | 24 ++++--- tests/unit/devNoMock.ts | 65 ++++++++++++++++++- 7 files changed, 82 insertions(+), 27 deletions(-) delete mode 100644 examples/single/test/nestedTest/nestedTest.json delete mode 100644 examples/single/test/test.json delete mode 100644 examples/single/test1/test1.json diff --git a/examples/single/bos.config.json b/examples/single/bos.config.json index 6704118..273c159 100644 --- a/examples/single/bos.config.json +++ b/examples/single/bos.config.json @@ -8,8 +8,5 @@ "aliases": ["./aliases.testnet.json"], "index": "quickstart.testnet/widget/home" } - }, - "data": { - "include": ["test", "test1"] } } diff --git a/examples/single/test/nestedTest/nestedTest.json b/examples/single/test/nestedTest/nestedTest.json deleted file mode 100644 index 519728a..0000000 --- a/examples/single/test/nestedTest/nestedTest.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "data": "this is a nested folder" -} \ No newline at end of file diff --git a/examples/single/test/test.json b/examples/single/test/test.json deleted file mode 100644 index e225b92..0000000 --- a/examples/single/test/test.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "data": "this is test" -} \ No newline at end of file diff --git a/examples/single/test1/test1.json b/examples/single/test1/test1.json deleted file mode 100644 index 816865d..0000000 --- a/examples/single/test1/test1.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "data": "this is test1" -} \ No newline at end of file diff --git a/lib/deploy.ts b/lib/deploy.ts index dbdd34a..21d30d1 100644 --- a/lib/deploy.ts +++ b/lib/deploy.ts @@ -206,11 +206,9 @@ export async function deployAppDataFolders( const result = {}; for (const folder of config.data.include) { - try { - await processDirectory(folder, result); - } catch (error) { - console.error(`Error processing folder ${folder}:`, error); - } + const folderName = path.basename(folder); + result[folderName] = {}; + await processDirectory(folder, '', result[folderName]); } const args = { diff --git a/lib/utils/fs.ts b/lib/utils/fs.ts index 399a511..461af08 100644 --- a/lib/utils/fs.ts +++ b/lib/utils/fs.ts @@ -17,21 +17,27 @@ async function loopThroughFiles(pwd: string, callback: (file: string) => Promise } } -async function processDirectory(dir, result) { - const files = await readdirSync(dir, { withFileTypes: true }); +async function processDirectory(baseDir, currentDir, result) { + const files = await readdirSync(path.join(baseDir, currentDir), { withFileTypes: true }); for (const file of files) { - const filePath = path.join(dir, file.name); + const relativePath = path.join(currentDir, file.name); + const fullPath = path.join(baseDir, relativePath); + if (file.isDirectory()) { - await processDirectory(filePath, result); + await processDirectory(baseDir, relativePath, result); } else if (path.extname(file.name).toLowerCase() === '.json') { try { - const fileContent = await readFileSync(filePath, 'utf8'); + const fileContent = await readFileSync(fullPath, 'utf8'); const jsonContent = JSON.parse(fileContent); - const relativePath = path.relative(process.cwd(), filePath); - const key = path.dirname(relativePath) + '/' + path.basename(file.name, '.json'); - result[key] = jsonContent; + let key; + if (currentDir === '') { + key = path.basename(file.name, '.json'); + } else { + key = path.join(currentDir, path.basename(file.name, '.json')).replace(/[\\/]/g, '.'); + } + result[key] = { "": JSON.stringify(jsonContent) }; } catch (error) { - console.error(`Error processing file ${filePath}:`, error); + console.error(`Error processing file ${fullPath}:`, error); } } } diff --git a/tests/unit/devNoMock.ts b/tests/unit/devNoMock.ts index 5613260..ddb0322 100644 --- a/tests/unit/devNoMock.ts +++ b/tests/unit/devNoMock.ts @@ -1,6 +1,7 @@ import { startFileWatcher } from "@/lib/watcher"; import path from "path"; import fs from "fs"; +import { processDirectory } from "@/lib/utils/fs"; describe("File Watcher Tests", () => { let watcher; @@ -37,4 +38,66 @@ describe("File Watcher Tests", () => { fs.rmSync(tempDirPath, { recursive: true, force: true }); } }); -}); \ No newline at end of file +}); + +describe('Folder structure processing', () => { + const tempDirPath = path.join(__dirname, 'temp_test_dir'); + const testFolderPath = path.join(tempDirPath, 'test'); + const nestedTestFolderPath = path.join(testFolderPath, 'nestedTest'); + const test1FolderPath = path.join(tempDirPath, 'test1'); + + beforeAll(() => { + fs.mkdirSync(tempDirPath, { recursive: true }); + fs.mkdirSync(testFolderPath, { recursive: true }); + fs.mkdirSync(nestedTestFolderPath, { recursive: true }); + fs.mkdirSync(test1FolderPath, { recursive: true }); + + fs.writeFileSync( + path.join(testFolderPath, 'file.json'), + JSON.stringify({ data: "this is test" }) + ); + fs.writeFileSync( + path.join(nestedTestFolderPath, 'nestedFile.json'), + JSON.stringify({ data: "this is a nested folder", data2: "other data" }) + ); + fs.writeFileSync( + path.join(test1FolderPath, 'file1.json'), + JSON.stringify({ data: "this is test1" }) + ); + }); + + it("should build the correct object based on folder structure", async () => { + const config = { + data: { + include: [tempDirPath] + }, + account: 'myaccount' + }; + + const result = {}; + + for (const folder of config.data.include) { + const folderName = path.basename(folder); + result[folderName] = {}; + await processDirectory(folder, '', result[folderName]); + } + + expect(result).toEqual({ + 'temp_test_dir': { + 'test.nestedTest.nestedFile': { + '': JSON.stringify({ data: "this is a nested folder", data2: "other data" }) + }, + 'test.file': { + '': JSON.stringify({ data: "this is test" }) + }, + 'test1.file1': { + '': JSON.stringify({ data: "this is test1" }) + } + } + }); + }); + + afterAll(() => { + fs.rmSync(tempDirPath, { recursive: true, force: true }); + }); +}); From 65f190f4f50d10af831949366fe4753bf371cbd4 Mon Sep 17 00:00:00 2001 From: stefano Date: Thu, 8 Aug 2024 16:14:26 +0100 Subject: [PATCH 5/5] Merge uplaod functions + README --- README.md | 10 ++++- lib/cli.ts | 22 +---------- lib/deploy.ts | 104 +++++++++----------------------------------------- 3 files changed, 29 insertions(+), 107 deletions(-) diff --git a/README.md b/README.md index e64db19..b4b5730 100644 --- a/README.md +++ b/README.md @@ -291,7 +291,15 @@ Commands: **Command:** `deploy` -Deploys an app in the workspace via a convenient wrapper to [bos-cli-rs](https://github.com/bos-cli-rs/bos-cli-rs). +Deploys an app in the workspace via a convenient wrapper to [bos-cli-rs](https://github.com/bos-cli-rs/bos-cli-rs). It's also possible to add an optional string array in the `bos.config.json` to specify the data to upload: + +``` + "data": { + "include": ["folder"] + } +``` + +The upload script will bundle all the json files inside the specified folder and upload the data with the app. ```cmd bw deploy [app name] --deploy-account-id [deployAccountId] --signer-account-id [signerAccountId] --signer-public-key [signerPublicKey] --signer-private-key [signerPrivateKey] diff --git a/lib/cli.ts b/lib/cli.ts index 01246b8..0c576f9 100644 --- a/lib/cli.ts +++ b/lib/cli.ts @@ -2,7 +2,7 @@ import { buildApp } from "@/lib/build"; import { initProject } from "@/lib/init"; import { Logger, LogLevel } from "@/lib/logger"; import { Command } from "commander"; -import { deploy, deployAppData, deployAppDataFolders, DeployOptions } from "./deploy"; +import { deploy, deployAppData, DeployOptions } from "./deploy"; import { dev } from "./dev"; import { cloneRepository } from "./repository"; import { buildWorkspace, devWorkspace } from "./workspace"; @@ -143,26 +143,6 @@ async function run() { }) }); - program - .command("uploadData") - .description("Upload data to SocialDB from bos.config.json configuration") - .argument("[appName]", "Workspace app name to deploy") - .option("-n, --network ", "network to deploy to", "mainnet") - .option("--signerPublicKey ", "Signer public key") - .option("--signerPrivateKey ", "Signer private key") - .action(async (appName, options) => { - const deployOptions: DeployOptions = { - signerPublicKey: options.signerPublicKey, - signerPrivateKey: options.signerPrivateKey, - network: options.network, - deployAccountId: options.deployAccountId, - }; - - await deployAppDataFolders(appName, deployOptions).catch((e: Error) => { - log.error(e.stack || e.message); - }) - }); - program.parse(); } diff --git a/lib/deploy.ts b/lib/deploy.ts index 21d30d1..9447be9 100644 --- a/lib/deploy.ts +++ b/lib/deploy.ts @@ -108,75 +108,7 @@ export async function deployAppCode(src: string, dist: string, opts: DeployOptio }); } -export async function deployAppData(appName: string, opts: DeployOptions) { - const config = await readConfig(path.join(appName, "bos.config.json"), opts.network); - const BOS_SIGNER_ACCOUNT_ID = config.accounts.signer || opts.signerAccountId || config.account; - - if (!BOS_SIGNER_ACCOUNT_ID) { - console.log(`App account is not defined for ${appName}. Skipping data upload`); - return; - } - - const dataJSON = fs.readFileSync( - path.join(appName, DEPLOY_DIST_FOLDER, "data.json"), - "utf8" - ); - - const args = { data: JSON.parse(dataJSON) }; - const argsBase64 = Buffer.from(JSON.stringify(args)).toString("base64"); - - const BOS_SIGNER_PUBLIC_KEY = opts?.signerPublicKey; - const BOS_SIGNER_PRIVATE_KEY = opts?.signerPrivateKey; - - const automaticSignIn = [ - "sign-with-plaintext-private-key", - "--signer-public-key", - BOS_SIGNER_PUBLIC_KEY, - "--signer-private-key", - BOS_SIGNER_PRIVATE_KEY, - "send" - ] - - let command = [ - "near-cli-rs", - "contract", - "call-function", - "as-transaction", - opts.network === "mainnet" ? SOCIAL_CONTRACT.mainnet : SOCIAL_CONTRACT.testnet, - "set", - "base64-args", - `${argsBase64}`, - "prepaid-gas", - "300 TeraGas", - "attached-deposit", - "0.15 NEAR", // deposit - "sign-as", - BOS_SIGNER_ACCOUNT_ID, - "network-config", - opts.network, - ]; - - if (BOS_SIGNER_PUBLIC_KEY && BOS_SIGNER_PRIVATE_KEY) command = command.concat(automaticSignIn) - - const deployProcess = spawn("npx", command, { - cwd: path.join(appName, DEPLOY_DIST_FOLDER), - stdio: "inherit", - }); - - deployProcess.on("close", (code) => { - if (code === 0) { - console.log(`Uploaded data for ${appName}`); - } else { - console.error(`Data upload failed with code ${code}`); - } - }); - - deployProcess.on("error", (err) => { - console.error(`Error uploading data for ${appName}:\n${err.message}`); - }); -} - -export async function deployAppDataFolders( +export async function deployAppData( appName: string, opts: DeployOptions ) { @@ -184,6 +116,7 @@ export async function deployAppDataFolders( path.join(appName, "bos.config.json"), opts.network ); + const BOS_SIGNER_ACCOUNT_ID = config.accounts.signer || opts.signerAccountId || config.account; @@ -194,28 +127,29 @@ export async function deployAppDataFolders( return; } - if ( - !config.data || - !Array.isArray(config.data.include) || - config.data.include.length === 0 - ) + const dataJSON = fs.readFileSync( + path.join(appName, DEPLOY_DIST_FOLDER, "data.json"), + "utf8" + ); + + const args = { data: JSON.parse(dataJSON) }; + + if (config.data?.include) { + if (!Array.isArray(config.data.include) || config.data.include.length === 0) throw new Error( "Config must contain a data.include array with at least one folder" ); - const result = {}; + const result = {}; - for (const folder of config.data.include) { - const folderName = path.basename(folder); - result[folderName] = {}; - await processDirectory(folder, '', result[folderName]); - } + for (const folder of config.data.include) { + const folderName = path.basename(folder); + result[folderName] = {}; + await processDirectory(folder, "", result[folderName]); + } - const args = { - data: { - [config.account]: result, - }, - }; + Object.assign(args.data[config.account], result); + } const argsBase64 = Buffer.from(JSON.stringify(args)).toString("base64");