Skip to content

Commit

Permalink
feat: Add ao process for testing
Browse files Browse the repository at this point in the history
  • Loading branch information
pawanpaudel93 committed Jul 7, 2024
1 parent cba2d4d commit cf38c40
Show file tree
Hide file tree
Showing 15 changed files with 1,044 additions and 77 deletions.
4 changes: 3 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended"
],
"rules": {}
"rules": {
"@typescript-eslint/no-explicit-any": "off"
}
}
Binary file modified bun.lockb
Binary file not shown.
42 changes: 23 additions & 19 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,28 +49,32 @@
"publish": "bun run build && changeset publish"
},
"dependencies": {
"@clack/core": "^0.3.2",
"@clack/prompts": "^0.6.3",
"chalk": "5.2.0",
"commander": "^10.0.0",
"execa": "^7.1.1",
"fs-extra": "^11.1.1",
"ora": "6.3.1",
"validate-npm-package-name": "^5.0.0"
"@clack/core": "^0.3.4",
"@clack/prompts": "^0.7.0",
"adm-zip": "^0.5.14",
"chalk": "^5.3.0",
"commander": "^12.1.0",
"env-paths": "^3.0.0",
"execa": "^9.3.0",
"fs-extra": "^11.2.0",
"node-fetch": "^3.3.2",
"ora": "^8.0.1",
"validate-npm-package-name": "^5.0.1"
},
"devDependencies": {
"@changesets/changelog-github": "^0.5.0",
"@changesets/cli": "^2.27.6",
"@types/fs-extra": "^11.0.1",
"@types/node": "^18.16.0",
"@types/validate-npm-package-name": "^4.0.1",
"@typescript-eslint/eslint-plugin": "^6.8.0",
"@typescript-eslint/parser": "^6.8.0",
"eslint": "^8.51.0",
"glob": "^10.3.10",
"prettier": "^3.0.0",
"@changesets/cli": "^2.27.7",
"@types/adm-zip": "^0.5.5",
"@types/fs-extra": "^11.0.4",
"@types/node": "^18.19.39",
"@types/validate-npm-package-name": "^4.0.2",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"eslint": "^8.57.0",
"glob": "^10.4.3",
"prettier": "^3.3.2",
"tsup": "^6.7.0",
"type-fest": "^3.7.0",
"typescript": "^5.0.4"
"type-fest": "^3.13.1",
"typescript": "^5.5.3"
}
}
87 changes: 87 additions & 0 deletions src/helpers/downloadAosProcess.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import fetch from "node-fetch";
import AdmZip from "adm-zip";
import fs from "fs/promises";
import fse from "fs-extra";
import path from "path";
import { getAosProcessPath } from "@/utils/getAosProcessPath.js";

const zipUrl = "https://github.com/permaweb/aos/archive/refs/heads/main.zip";
const folderToCopy = "aos-main/process";
const maxRetries = 3;
const retryDelay = 2000; // 2 seconds

async function fetchWithRetry(url: string, retries: number, delay: number) {
for (let attempt = 1; attempt <= retries; attempt++) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Failed to download zip file: ${response.statusText}`);
}
return response;
} catch (error: any) {
if (attempt < retries) {
console.warn(`Attempt ${attempt} failed. Retrying in ${delay}ms...`);
await new Promise((resolve) => setTimeout(resolve, delay));
} else {
throw new Error(`Failed to download zip file after ${retries} attempts: ${error.message}`);
}
}
}
return;
}

async function folderExists(folderPath: string) {
try {
await fs.access(folderPath);
return true;
} catch (error) {
return false;
}
}

export async function downloadAosProcess(projectDir: string) {
try {
const destinationDir = getAosProcessPath();

const isAosDownloaded = await folderExists(destinationDir);
if (isAosDownloaded) return true;

// Ensure the destination directory exists
await fs.mkdir(destinationDir, { recursive: true });

// Download the zip file with retries
const response = await fetchWithRetry(zipUrl, maxRetries, retryDelay);
if (!response) return false;

const arrayBuffer = await response.arrayBuffer();
const zip = new AdmZip(Buffer.from(arrayBuffer));
const zipEntries = zip.getEntries();

// Copy the specific folder to the destination directory
for (const entry of zipEntries) {
if (entry.entryName.startsWith(folderToCopy)) {
const relativePath = entry.entryName.replace(folderToCopy, "");
const filePath = path.join(destinationDir, relativePath);

if (entry.isDirectory) {
await fs.mkdir(filePath, { recursive: true });
} else {
await fs.writeFile(filePath, entry.getData());
}
}
}

// Copy json.lua
const jsonFileDst = path.join(destinationDir, "json.lua");
const jsonFileSrc = path.join(projectDir, "src", "libs", "json", "json.lua");
await fse.copy(jsonFileSrc, jsonFileDst);

// Copy everything inside testing Directory
const testingDir = path.join(projectDir, "src", "libs", "testing");
await fse.copy(testingDir, destinationDir);
await fse.remove(testingDir);
return true;
} catch (error: any) {
return false;
}
}
4 changes: 4 additions & 0 deletions src/helpers/scaffoldProject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import ora from "ora";
import { PKG_ROOT } from "@/constants.js";
import { logger } from "@/utils/logger.js";
import { type InstallerOptions } from "@/installers/index.js";
import { downloadAosProcess } from "./downloadAosProcess.js";

// This bootstraps the base Next.js application
export const scaffoldProject = async ({ projectName, projectDir, pkgManager, noInstall }: InstallerOptions) => {
Expand Down Expand Up @@ -73,6 +74,9 @@ export const scaffoldProject = async ({ projectName, projectDir, pkgManager, noI

fs.copySync(srcDir, projectDir);

// download AOS process
await downloadAosProcess(projectDir);

const scaffoldedName = projectName === "." ? "App" : chalk.cyan.bold(projectName);

spinner.succeed(`${scaffoldedName} ${chalk.green("scaffolded successfully!")}\n`);
Expand Down
6 changes: 4 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { initializeGit } from "@/helpers/git.js";
import { installDependencies } from "@/helpers/installDependencies.js";
import { logNextSteps } from "@/helpers/logNextSteps.js";
import { getNpmVersion, renderVersionWarning } from "@/utils/renderVersionWarning.js";
import { getAosProcessPath } from "./utils/getAosProcessPath.js";

type CPAPackageJSON = PackageJson & {
caaMetadata?: {
Expand Down Expand Up @@ -50,6 +51,7 @@ const main = async () => {
// Write name to package.json
const pkgJson = fs.readJSONSync(path.join(projectDir, "package.json")) as CPAPackageJSON;
pkgJson.name = scopedAppName;
pkgJson.scripts!.test = pkgJson.scripts?.test?.replace("AOS_PROCESS_PATH", getAosProcessPath());
pkgJson.cacMetadata = { initVersion: getVersion() };

// ? Bun doesn't support this field (yet)
Expand All @@ -73,9 +75,9 @@ const main = async () => {
let readmeContent = fs.readFileSync(path.join(projectDir, "README.md"), "utf-8");
readmeContent = readmeContent.replaceAll("my-ao-contract", scopedAppName);
if (pkgManager === "yarn" || pkgManager === "pnpm") {
readmeContent = readmeContent.replaceAll("npm run", pkgManager)
readmeContent = readmeContent.replaceAll("npm run", pkgManager);
} else if (pkgManager === "bun") {
readmeContent = readmeContent.replaceAll("npm", "bun")
readmeContent = readmeContent.replaceAll("npm", "bun");
}
fs.writeFileSync(path.join(projectDir, "README.md"), readmeContent);

Expand Down
8 changes: 8 additions & 0 deletions src/utils/getAosProcessPath.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import path from "path";
import envPaths from "env-paths";

export function getAosProcessPath() {
const paths = envPaths("create-ao-contract");
const aosProcessPath = path.join(paths.data, "aos-process");
return aosProcessPath;
}
8 changes: 4 additions & 4 deletions template/ao/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ AO contract created using [create-ao-contract](https://github.com/pawanpaudel93/

2. Install [arweave](https://luarocks.org/modules/crookse/arweave) using LuaRocks for testing purposes.

```bash
luarocks install arweave
```
```bash
luarocks install arweave
```

3. **[Recommended]** Install [Lua Language Server](https://luals.github.io/#install) to make development easier, safer, and faster!. On VSCode, install extension: [sumneko.lua](https://marketplace.visualstudio.com/items?itemName=sumneko.lua)
- Install AO & Busted addon using Lua Addon Manager. On VSCode, goto `View > Command Palette > Lua: Open Addon Manager`
- Install AO & Busted addon using Lua Addon Manager. On VSCode, goto `View > Command Palette > Lua: Open Addon Manager`

## Usage

Expand Down
2 changes: 1 addition & 1 deletion template/ao/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"license": "MIT",
"scripts": {
"deploy": "ao-deploy aod.config.js",
"test": "arweave test ."
"test": "arweave test . --lpath='./src/?.lua;./src/?/?.lua;./src/?/init.lua;AOS_PROCESS_PATH/?.lua'"
},
"type": "module",
"dependencies": {
Expand Down
127 changes: 127 additions & 0 deletions template/ao/src/libs/testing/ao-process.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
local ao = require(".ao")
require(".process")

---Generate a valid Arweave address
---@return string
local function generateAddress()
local id = ""

-- possible characters in a valid arweave address
local chars =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_-"

while string.len(id) < 43 do
-- get random char
local char = math.random(1, string.len(chars))

-- select and apply char
id = id .. string.sub(chars, char, char)
end

return id
end

local env = {
Module = {
Tags = {
{
name = "Memory-Limit",
value = "1-gb"
},
{
name = "Compute-Limit",
value = "9000000000000"
},
{
name = "Module-Format",
value = "wasm64-unknown-emscripten-draft_2024_02_15"
},
{
name = "Data-Protocol",
value = "ao"
},
{
name = "Type",
value = "Module"
},
{
name = "Input-Encoding",
value = "JSON-1"
},
{
name = "Output-Encoding",
value = "JSON-1"
},
{
name = "Variant",
value = "ao.TN.1"
},
{
name = "Content-Type",
value = "application/wasm"
}
},
Owner = "vh-NTHVvlKZqRxc8LyyTNok65yQ55a_PJ1zWLb9G2JI",
Id = "Pq2Zftrqut0hdisH_MC2pDOT6S4eQFoxGsFUzR6r350"
},
Process = {
Tags = {
["App-Name"] = "aos",
["aos-Version"] = "1.11.3",
[" Data-Protocol"] = "ao",
Scheduler = "_GQ33BkPtZrqxA84vM8Zk-N2aO0toNNu_C-l-rawrBA",
Variant = "ao.TN.1",
Name = "aos-process",
Type = "Process",
SDK = "aoconnect",
Module = "Pq2Zftrqut0hdisH_MC2pDOT6S4eQFoxGsFUzR6r350",
Authority = "fcoN_xJeisVsPXA-trzVAuIiqO3ydLQxM-L4XbrQKzY"
},
TagArray = {
{
name = "App-Name",
value = "aos"
},
{
name = "Name",
value = "aos-process"
},
{
name = "Authority",
value = "fcoN_xJeisVsPXA-trzVAuIiqO3ydLQxM-L4XbrQKzY"
},
{
name = "aos-Version",
value = "1.11.3"
},
{
name = "Data-Protocol",
value = "ao"
},
{
name = "Variant",
value = "ao.TN.1"
},
{
name = "Type",
value = "Process"
},
{
name = "Module",
value = "Pq2Zftrqut0hdisH_MC2pDOT6S4eQFoxGsFUzR6r350"
},
{
name = "Scheduler",
value = "_GQ33BkPtZrqxA84vM8Zk-N2aO0toNNu_C-l-rawrBA"
},
{
name = "SDK",
value = "aoconnect"
}
},
Owner = generateAddress(),
Id = generateAddress()
}
}

ao.init(env)
Loading

0 comments on commit cf38c40

Please sign in to comment.