This commit is contained in:
Cat /dev/Nulo 2023-05-31 09:48:26 -03:00
commit 7bbf52a757
6 changed files with 113 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
node_modules/

1
.npmrc Normal file
View file

@ -0,0 +1 @@
@nulo:registry=https://gitea.nulo.in/api/packages/nulo/npm/

67
index.js Normal file
View file

@ -0,0 +1,67 @@
import { execFile as _execFile } from "node:child_process";
import { readFile, stat, symlink, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { promisify } from "node:util";
const execFile = promisify(_execFile);
/**
* @typedef {object} Alpine
* @prop {(packages: string[]) => Promise<void>} install
* @prop {(runlevel: string, service: string) => Promise<void>} rcUpdate
*/
/**
* Initialize an Alpine 3.18 rootfs at `root`
* @param {string} root
* @returns {Promise<Alpine>}
*/
export async function init(root) {
await runInContainer(
root,
`
mkdir -p /rootfs/etc/apk
cp -r /etc/apk/keys /rootfs/etc/apk/
echo https://dl-cdn.alpinelinux.org/alpine/v3.18/main >> /rootfs/etc/apk/repositories
echo https://dl-cdn.alpinelinux.org/alpine/v3.18/community >> /rootfs/etc/apk/repositories
apk add --initdb --root /rootfs alpine-base
`
);
return {
async install(packages) {
const worldPath = join(root, "/etc/apk/world");
const oldWorld = (await readFile(worldPath, "utf-8")).split("\n");
const newWorld = oldWorld.concat(packages);
await writeFile(worldPath, newWorld.join("\n"));
await runInContainer(root, `apk fix --root /rootfs`);
},
async rcUpdate(runlevel, service) {
const servicePath = `/etc/init.d/${service}`;
try {
await stat(servicePath);
} catch (error) {
throw new Error(`Can't stat service ${service}: ${error}`);
}
await symlink(servicePath, join(root, `/etc/runlevels/`, runlevel));
},
};
}
/**
* Run script inside an Alpine 3.18 container with `root` mounted in /rootfs
* @param {string} root
* @param {string} script
*/
async function runInContainer(root, script) {
await execFile("podman", [
"run",
"-it",
"--rm",
"-v",
`${root}:/rootfs:Z`,
"docker.io/alpine:3.18",
"sh",
"-ec",
script,
]);
}

17
package.json Normal file
View file

@ -0,0 +1,17 @@
{
"name": "@nulo/apkit",
"type": "module",
"version": "0.0.1",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@tsconfig/node16": "^1.0.4",
"@types/node": "^20.2.5"
}
}

19
pnpm-lock.yaml Normal file
View file

@ -0,0 +1,19 @@
lockfileVersion: '6.0'
devDependencies:
'@tsconfig/node16':
specifier: ^1.0.4
version: 1.0.4
'@types/node':
specifier: ^20.2.5
version: 20.2.5
packages:
/@tsconfig/node16@1.0.4:
resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==}
dev: true
/@types/node@20.2.5:
resolution: {integrity: sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==}
dev: true

8
tsconfig.json Normal file
View file

@ -0,0 +1,8 @@
{
"extends": "@tsconfig/node16/tsconfig.json",
"exclude": ["build.js/", "build/"],
"compilerOptions": {
"allowJs": true,
"checkJs": true
}
}