From 2be4fe2bd446b5eca0c8172278fedccef757132d Mon Sep 17 00:00:00 2001 From: AJ Beckner Date: Tue, 11 Jun 2024 14:48:57 -0500 Subject: [PATCH 01/15] added watch command; fixed 1st react build by adding npm installl --- commands/build.js | 6 ++--- index.js | 35 ++++++++++++++++++++++++++- lib/checks.js | 10 +++++--- lib/react.js | 13 ++++++++-- package-lock.json | 60 ++++++++++++++++++++++++++++++++++++++++++++--- package.json | 7 +++--- 6 files changed, 116 insertions(+), 15 deletions(-) diff --git a/commands/build.js b/commands/build.js index 3e5c714..4c50e3a 100644 --- a/commands/build.js +++ b/commands/build.js @@ -4,7 +4,7 @@ import { copyDeskToUrbit } from '../lib/files.js' import { isInGolemProject, isUrbitInstalled, isShipCreated, isDeskMountedOnShip } from '../lib/checks.js' import { buildUI } from '../lib/react.js' -async function build ({ uiOnly }) { +async function build ({ uiOnly, connect }) { try { await isInGolemProject() @@ -15,7 +15,7 @@ async function build ({ uiOnly }) { if (!uiOnly) { await isUrbitInstalled() - await isShipCreated(pier) + await isShipCreated(pier, { connect }) await isDeskMountedOnShip(deskName, pier) console.log('BUILD: building desk to urbit ship') @@ -25,7 +25,7 @@ async function build ({ uiOnly }) { await clack.commitDesk(urbitSafeDeskName) await clack.reviveDesk(urbitSafeDeskName) } else { - console.log('BUILD: skipping desk build to urbit ship, because --ui-only flag set to true') + console.log('BUILD: skipping desk build to urbit ship, because --ui-only flag was set') } console.log('BUILD: building UI') diff --git a/index.js b/index.js index c84751e..471f2ec 100755 --- a/index.js +++ b/index.js @@ -3,6 +3,7 @@ import fs from 'fs' import { fileURLToPath } from 'url'; import { join, dirname } from 'path' +import chokidar from 'chokidar'; import { program } from 'commander' import { closeClack } from '@archetype-org/clack' @@ -46,6 +47,31 @@ program.command('build') .description('build the current urbit project to it\'s test environment') .action(build) .option('--ui-only', 'only build the UI, do not build the desk') + .option('--connect', 'attempt to connect to a running ship, instead of starting a new one') + +program.command('watch') + .description('watch the current project files and run the build command on changes') + .action(() => { + const watcher = chokidar.watch('./apps', { + ignored: /node_modules|\.git|dist/, + persistent: true + }); + + watcher.on('change', async (path) => { + console.log(`File ${path} has been changed. Rebuilding...`); + await build({ connect: true }); + console.log('Build complete.'); + console.log('Watching for changes...') + }); + + watcher.on('close', () => { + console.log('Watcher has been closed.'); + // need to close manually because the postaction hook doesn't run for persistent commands + closeClack(); + }); + + console.log('Watching for file changes...'); + }); // Package Management @@ -86,6 +112,13 @@ program.command('version') console.log(packageJson.version); }); -program.hook('postAction', () => closeClack()) +const persistentCommands = ['watch']; + +program.hook('postAction', () => { + const currentCommand = process.argv[2]; + if (!persistentCommands.includes(currentCommand)) { + closeClack(); + } +}); program.parse() diff --git a/lib/checks.js b/lib/checks.js index 5d1396b..3e7bbad 100644 --- a/lib/checks.js +++ b/lib/checks.js @@ -21,15 +21,19 @@ async function isUrbitInstalled () { } } -async function isShipCreated (shipName, { shell } = { shell: false}) { +async function isShipCreated (shipName, { shell, connect } = { shell: false, connect: false }) { try { const condition = await folderExists(`ships/${shipName}`) if (!condition) { console.log(`booting ${shipName} for the first time — may take a while`) await bootFakeShip(shipName, { shell }) } else { - console.log(`pier named ${shipName} already found, restarting`) - await restartFakeShip(shipName, { shell }) + if (connect) { + console.log(`pier named ${shipName} already found, attempting to connect to running ${shipName}`) + } else { + console.log(`pier named ${shipName} already found, restarting`) + await restartFakeShip(shipName, { shell }) + } } } catch (err) { throw new Error(`failed to find or create ship named ${shipName}`) diff --git a/lib/react.js b/lib/react.js index 9767030..781e60e 100644 --- a/lib/react.js +++ b/lib/react.js @@ -1,11 +1,20 @@ import execSh from "exec-sh" +import fs from "fs" const execShPromise = execSh.promise async function buildUI (name) { - return execShPromise(`npm run --prefix ./apps/${name}/ui build`) + const uiPath = `./apps/${name}/ui` + const nodeModulesPath = `${uiPath}/node_modules` + + if (!fs.existsSync(nodeModulesPath)) { + console.log("BUILD: node_modules not found, installing...") + await execShPromise(`npm install --prefix ${uiPath}`) + } + + const buildCommand = `npm run --prefix ${uiPath} build` + return execShPromise(buildCommand) } export { buildUI, } - diff --git a/package-lock.json b/package-lock.json index 62ccb41..9970b7e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@archetype-org/clack": "^0.2.0", "@archetype-org/ribbit": "^0.2.0", "@near-js/accounts": "1.0.4", + "chokidar": "^3.6.0", "commander": "^11.0.0", "exec-sh": "^0.4.0" }, @@ -5052,7 +5053,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "peer": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -5240,6 +5240,17 @@ } ] }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/bl": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", @@ -5487,6 +5498,29 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, "node_modules/chownr": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", @@ -6411,7 +6445,6 @@ "os": [ "darwin" ], - "peer": true, "engines": { "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } @@ -6855,6 +6888,17 @@ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "peer": true }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-core-module": { "version": "2.13.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", @@ -8711,7 +8755,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -9593,6 +9636,17 @@ "node": ">= 6" } }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/readline": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz", diff --git a/package.json b/package.json index 33090aa..39f87e8 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "bin": { "golem": "./index.js" }, - "version": "1.5.2", + "version": "1.6.0", "description": "Project creation and package management CLI for Urbit", "main": "index.js", "scripts": { @@ -15,8 +15,9 @@ "dependencies": { "@archetype-org/clack": "^0.2.0", "@archetype-org/ribbit": "^0.2.0", + "@near-js/accounts": "1.0.4", + "chokidar": "^3.6.0", "commander": "^11.0.0", - "exec-sh": "^0.4.0", - "@near-js/accounts": "1.0.4" + "exec-sh": "^0.4.0" } } From b4e77e3a6b38e7ef250ae7712696d7d675f17b93 Mon Sep 17 00:00:00 2001 From: AJ Beckner Date: Tue, 11 Jun 2024 17:35:54 -0500 Subject: [PATCH 02/15] multiple ships in config/shell/build --- commands/build.js | 38 +++++++++++++++++++++++--------------- commands/init.js | 22 +++++++++++++++++----- commands/shell.js | 15 ++++++++++++--- index.js | 3 ++- lib/files.js | 6 +++++- lib/urbit.js | 15 +++++++++++++-- 6 files changed, 72 insertions(+), 27 deletions(-) diff --git a/commands/build.js b/commands/build.js index 4c50e3a..5829f31 100644 --- a/commands/build.js +++ b/commands/build.js @@ -9,27 +9,35 @@ async function build ({ uiOnly, connect }) { await isInGolemProject() const { ships } = JSON.parse(fs.readFileSync('./ships/ships.json')) - const { pier, desks } = ships[0] // only supports zod for now - - const deskName = desks[0] if (!uiOnly) { await isUrbitInstalled() - await isShipCreated(pier, { connect }) - await isDeskMountedOnShip(deskName, pier) - - console.log('BUILD: building desk to urbit ship') - await copyDeskToUrbit(deskName, pier) - const urbitSafeDeskName = `%${deskName}` - const clack = await Clack({ ship: `ships/${pier}` }) - await clack.commitDesk(urbitSafeDeskName) - await clack.reviveDesk(urbitSafeDeskName) + + for (const ship of ships) { + const { pier, desks } = ship + + await isShipCreated(pier, { connect }) + + for (const desk of desks) { + await isDeskMountedOnShip(desk, pier) + + console.log(`BUILD: building desk ${desk} to urbit ship ${pier}`) + await copyDeskToUrbit(desk, pier) + const urbitSafeDeskName = `%${desk}` + const clack = await Clack({ ship: `ships/${pier}` }) + await clack.commitDesk(urbitSafeDeskName) + await clack.reviveDesk(urbitSafeDeskName) + } + } } else { console.log('BUILD: skipping desk build to urbit ship, because --ui-only flag was set') } - - console.log('BUILD: building UI') - await buildUI(deskName) + + const uniqueDesks = new Set(ships.flatMap(ship => ship.desks)) + for (const desk of uniqueDesks) { + console.log(`BUILD: building UI for ${desk}`) + await buildUI(desk) + } } catch (err) { console.log(err) diff --git a/commands/init.js b/commands/init.js index dbc98d8..10ec0a5 100644 --- a/commands/init.js +++ b/commands/init.js @@ -6,15 +6,27 @@ async function init () { await isInGolemProject() const { ships } = JSON.parse(fs.readFileSync('./ships/ships.json')) - const { pier, desks } = ships[0] // only supports zod for now await isUrbitInstalled() - await isShipCreated(pier) - await isDeskMountedOnShip(desks[0], pier) - console.log(`Initialized fakeship for ${desks[0]}`) + + for (const ship of ships) { + const { pier, desks } = ship + + console.log(`INIT: Creating ship for ${pier}...`) + await isShipCreated(pier) + console.log(`INIT: ${pier} created.`) + + for (const desk of desks) { + console.log(`INIT: Mounting ${desk} on ${pier}...`) + await isDeskMountedOnShip(desk, pier) + console.log(`INIT: Successfully mounted desk: ${desk} on pier: ${pier}.`) + } + } + + console.log(`INIT: The fakeships: ${ships.map(ship => ship.pier).join(', ')} have been initialized with ${ships.flatMap(ship => ship.desks).join(', ')}`) } catch (err) { - console.log(err) + console.error('INIT: An error occurred while attempting to create the fakeships:', err) return err } } diff --git a/commands/shell.js b/commands/shell.js index 5db02ec..d4c93ef 100644 --- a/commands/shell.js +++ b/commands/shell.js @@ -1,17 +1,26 @@ import fs from 'fs' import { isInGolemProject, isUrbitInstalled, isShipCreated } from "../lib/checks.js" -async function shell () { +async function shell (shipName) { try { await isInGolemProject() await isUrbitInstalled() const { ships } = JSON.parse(fs.readFileSync('./ships/ships.json')) - const { pier } = ships[0] // only supports zod for now + + const ship = shipName + ? ships.find(s => s.pier === shipName) + : ships[0] + + if (!ship) { + throw new Error(`Ship with name ${shipName} does not exist.`) + } + + const { pier } = ship await isShipCreated(pier, { shell: true }) } catch (err) { - console.log(err) + console.error(`SHELL: An error occurred while attempting to connect to ${shipName}:`, err) return err } } diff --git a/index.js b/index.js index 471f2ec..cfc0516 100755 --- a/index.js +++ b/index.js @@ -37,10 +37,11 @@ program.command('new') program.command('shell') .description('open dojo for your current project') + .argument('[shipName]', 'name of the ship whose dojo to connect to', 'zod') .action(shell) program.command('init') - .description('initialize a test ship for the project') + .description('initialize test ships for the project') .action(init) program.command('build') diff --git a/lib/files.js b/lib/files.js index f05bab5..2b20fe9 100644 --- a/lib/files.js +++ b/lib/files.js @@ -1,4 +1,4 @@ -import { readFileSync, readdirSync } from 'fs' +import { readFileSync, readdirSync, writeFileSync } from 'fs' import { basename, extname, dirname} from 'path' import { fileURLToPath } from 'url'; import execSh from "exec-sh" @@ -81,6 +81,10 @@ async function copyDeskToUrbit (desk, ship) { } } } + const docketPath = `./apps/${desk}/desk/desk.docket-0` + let docketContent = readFileSync(docketPath, 'utf8') + docketContent = docketContent.replace(/%%SHIPNAME%%/g, `~${ship}`) + writeFileSync(`./ships/${ship}/${desk}/desk.docket-0`, docketContent) } catch (err) { console.error(err) return err diff --git a/lib/urbit.js b/lib/urbit.js index f7ed004..f42671c 100644 --- a/lib/urbit.js +++ b/lib/urbit.js @@ -1,5 +1,14 @@ import execSh from 'exec-sh' const execShPromise = execSh.promise + +function getPortFromShipName(shipName) { + let hash = 0 + for (let i = 0; i < shipName.length; i++) { + hash = shipName.charCodeAt(i) + ((hash << 5) - hash) + } + return 10000 + (hash % 10000) // Ensure port is within a valid range +} + async function fetchUrbitBinary () { try { await execShPromise(`curl -L https://urbit.org/install/macos-x86_64/latest | tar xzk -s '/.*/urbit/' && mv ./urbit ./ships/urbit`); @@ -28,7 +37,8 @@ rm -rf ./landscape-git`) async function bootFakeShip (shipName, { shell } = { shell: false}) { try { const args = !shell ? ' -dF ' : ' -F ' - await execShPromise(`./ships/urbit -c ./ships/${shipName}${args}${shipName}`); + const port = getPortFromShipName(shipName) + await execShPromise(`./ships/urbit -c ./ships/${shipName}${args}${shipName} --http-port=${port}`) } catch (err) { console.log(err) return err @@ -38,7 +48,8 @@ async function bootFakeShip (shipName, { shell } = { shell: false}) { async function restartFakeShip (shipName, { shell } = { shell: false}) { try { const args = !shell ? ' -d ' : ' ' - await execShPromise(`./ships/urbit${args}./ships/${shipName}`); + const port = getPortFromShipName(shipName) + await execShPromise(`./ships/urbit${args}./ships/${shipName} --http-port=${port}`) } catch (err) { console.log(err) return err From 188ce94b487cb627263aa741a9b6d7cf63e462e6 Mon Sep 17 00:00:00 2001 From: AJ Beckner Date: Sun, 16 Jun 2024 21:28:31 -0400 Subject: [PATCH 03/15] move ships.json --- commands/build.js | 2 +- commands/init.js | 2 +- commands/shell.js | 2 +- lib/checks.js | 2 +- partials/cruft.js | 17 ++++++++++++++++- 5 files changed, 20 insertions(+), 5 deletions(-) diff --git a/commands/build.js b/commands/build.js index 5829f31..78c3e0c 100644 --- a/commands/build.js +++ b/commands/build.js @@ -8,7 +8,7 @@ async function build ({ uiOnly, connect }) { try { await isInGolemProject() - const { ships } = JSON.parse(fs.readFileSync('./ships/ships.json')) + const { ships } = JSON.parse(fs.readFileSync('./ships.json')) if (!uiOnly) { await isUrbitInstalled() diff --git a/commands/init.js b/commands/init.js index 10ec0a5..63307eb 100644 --- a/commands/init.js +++ b/commands/init.js @@ -5,7 +5,7 @@ async function init () { try { await isInGolemProject() - const { ships } = JSON.parse(fs.readFileSync('./ships/ships.json')) + const { ships } = JSON.parse(fs.readFileSync('./ships.json')) await isUrbitInstalled() diff --git a/commands/shell.js b/commands/shell.js index d4c93ef..07705d0 100644 --- a/commands/shell.js +++ b/commands/shell.js @@ -6,7 +6,7 @@ async function shell (shipName) { await isInGolemProject() await isUrbitInstalled() - const { ships } = JSON.parse(fs.readFileSync('./ships/ships.json')) + const { ships } = JSON.parse(fs.readFileSync('./ships.json')) const ship = shipName ? ships.find(s => s.pier === shipName) diff --git a/lib/checks.js b/lib/checks.js index 3e7bbad..243c5da 100644 --- a/lib/checks.js +++ b/lib/checks.js @@ -3,7 +3,7 @@ import { fileExists, folderExists } from './files.js' import { fetchUrbitBinary, bootFakeShip, restartFakeShip } from './urbit.js' async function isInGolemProject () { - const condition = await fileExists('ships/ships.json') + const condition = await fileExists('ships.json') if (!condition) { throw new Error(`Could not identify the current directory as a project. Make sure you are running the command from inside a project`) } diff --git a/partials/cruft.js b/partials/cruft.js index f8bf8fa..a549afa 100644 --- a/partials/cruft.js +++ b/partials/cruft.js @@ -23,7 +23,7 @@ function cruft (shipName, deskName) { content: `:~ %${deskName} ==` }, { - path: 'ships', + path: '.', name: 'ships.json', content: JSON.stringify({ ships: [ @@ -33,6 +33,21 @@ function cruft (shipName, deskName) { } ] }, null, 2) + }, { + path: '.', + name: '.gitignore', + content: `.node_modules +.DS_Store +dist +dist-ssr +*.local +stats.html +.eslintcache +.vercel +ships +./ships/urbit +desk-deps + ` }, ] return files From 5563c1904727706445463800e1377d9276957773 Mon Sep 17 00:00:00 2001 From: AJ Beckner Date: Mon, 17 Jun 2024 18:13:44 -0400 Subject: [PATCH 04/15] more templates --- commands/create.js | 10 +- partials/hub-agent.js | 168 ++++++++++++++++++++++++ partials/item-source-files.js | 124 +++++++++++++++++ templates/aframe-desk.js | 34 +++++ templates/{sail-desk.js => cms-desk.js} | 0 templates/hub-desk.js | 83 ++++++++++++ templates/phaser-desk.js | 77 +++++++++++ 7 files changed, 493 insertions(+), 3 deletions(-) create mode 100644 partials/hub-agent.js create mode 100644 partials/item-source-files.js create mode 100644 templates/aframe-desk.js rename templates/{sail-desk.js => cms-desk.js} (100%) create mode 100644 templates/hub-desk.js create mode 100644 templates/phaser-desk.js diff --git a/commands/create.js b/commands/create.js index e4c370f..7e273ab 100644 --- a/commands/create.js +++ b/commands/create.js @@ -11,10 +11,14 @@ async function create (deskName, template, { skipDeps }) { file.path = file.path.replace('./', '') if (!(await fileExists(file))) await createFile(`./${deskName}/${file.path}/${file.name}`, file.content.trimStart()) } - // download code dependancues (incl. base, garden etc) - const depsPath = `./${deskName}/apps/${deskName}/desk-deps` - await createPath(depsPath) + + const shipsPath = `./ships` + await createPath(shipsPath) + if (!skipDeps) { + // download code dependancues (incl. base, garden etc) + const depsPath = `./${deskName}/apps/${deskName}/desk-deps` + await createPath(depsPath) await installCoreDependencies(depsPath) } } diff --git a/partials/hub-agent.js b/partials/hub-agent.js new file mode 100644 index 0000000..8a85c80 --- /dev/null +++ b/partials/hub-agent.js @@ -0,0 +1,168 @@ +function hubAgent (shipName, deskName) { + const files = [ + { + path: `apps/${deskName}/desk/app`, + name: `${deskName}.hoon`, + content: ` + /- item + /+ default-agent, dbug + |% + +$ versioned-state + $% state-0 + == + +$ state-0 [%0 =items:item] + +$ card card:agent:gall + ++ tell + |= update=update:item + ^- (list card) + :~ :* %give %fact ~[/updates] %item-update + !>(update) + == + == + -- + %- agent:dbug + =| state-0 + =* state - + ^- agent:gall + |_ =bowl:gall + +* this . + def ~(. (default-agent this %.n) bowl) + :: + ++ on-init + ^- (quip card _this) + :_ + this(items ~) + ?: =(our.bowl ~zod) ~ + :~ + [%pass /items %agent [~zod %hub] %watch /updates] + == + :: + ++ on-save + ^- vase + !>(state) + :: + ++ on-load + |= old-state=vase + ^- (quip card _this) + =/ old !<(versioned-state old-state) + ?- -.old + %0 \\\`this(state old) + == + :: + ++ on-poke + |= [=mark =vase] + ^- (quip card _this) + |^ + ?> =(src.bowl our.bowl) + ?+ mark (on-poke:def mark vase) + %item-action + =^ cards state + (handle-poke !<(action:item vase)) + [cards this] + == + ++ handle-poke + |= =action:item + ^- (quip card _state) + ?- -.action + %create + =/ id (mod now.bowl (pow 10 10)) + ?: (~(has by items) id) + $(now.bowl (add id 1)) + :_ state(items (~(put by items) id [name.action our.bowl])) + (tell \\\`update:item\\\`[%create id name.action our.bowl]) + :: + %delete + :_ state(items (~(del by items) id.action)) + (tell \\\`update:item\\\`action) + :: + %update + :- (tell \\\`update:item\\\`[%update id.action name.action our.bowl]) + %= state + items %+ ~(jab by items) + id.action + |=(i=item:item i(name name.action, src our.bowl)) + == + == + -- + :: + ++ on-watch + |= =path + ^- (quip card _this) + ?+ path (on-watch:def path) + [%updates ~] + %- (slog leaf+"Subscribed to updates." ~) + :_ this + :~ [%give %fact ~[/updates] %item-update !>([%initial items])] + == + == + ++ on-leave on-leave:def + ++ on-peek + |= =path + ^- (unit (unit cage)) + ?+ path (on-peek:def path) + [%x %items ~] + \\\`\\\`items+!>(items) + :: todo: add example for 'retrive one' + :: + == + ++ on-agent + |= [=wire =sign:agent:gall] + ^- (quip card _this) + |^ + ?+ wire (on-agent:def wire sign) + [%items ~] + ?+ -.sign (on-agent:def wire sign) + %watch-ack + ?~ p.sign + ((slog '%hub: Subscribed to ~zod!' ~) \\\`this) + ((slog '%hub: Could NOT Subscribe to ~zod!' ~) \\\`this) + :: + %kick + %- (slog '%hub: Got kick, resubscribing...' ~) + :_ this + :~ [%pass /items %agent [src.bowl %hub] %watch /updates] + == + :: + %fact + ?+ p.cage.sign (on-agent:def wire sign) + %item-update + (handle-update !<(update:item q.cage.sign)) + == + == + == + ++ handle-update + |= =update:item + ~& "Got update" + ~& update + ?- -.update + %initial + (hear (~(uni by items) items.update)) + %create + (hear (~(put by items) id.update [name=name.update src=src.update])) + %update + (hear (~(put by items) id.update [name=name.update src=src.update])) + %delete + (hear (~(del by items) id.update)) + == + ++ hear + |= items=$_(+.state) + :- ~ + %= this state + %= state items + items + == + == + -- + ++ on-arvo on-arvo:def + ++ on-fail on-fail:def + -- + ` + }, + ] + return files + } + + export { + hubAgent, + } + \ No newline at end of file diff --git a/partials/item-source-files.js b/partials/item-source-files.js new file mode 100644 index 0000000..0ae03a0 --- /dev/null +++ b/partials/item-source-files.js @@ -0,0 +1,124 @@ +function itemFiles (shipName, deskName) { + const files = [ + { + path: `apps/${deskName}/desk/mar/item`, + name: `action.hoon`, + content: ` + /- item + /+ *item + |_ =action:item + ++ grab + |% + ++ noun action:item + ++ json decode-item-action + -- + ++ grow + |% + ++ noun action + -- + ++ grad %noun + --` + }, { + path: `apps/${deskName}/desk/mar/item`, + name: `update.hoon`, + content: ` + /- item + |_ =update:item + ++ grab + |% + ++ noun update:item + -- + ++ grow + |% + ++ noun update + -- + ++ grad %noun + --` + }, { + path: `apps/${deskName}/desk/sur`, + name: `item.hoon`, + content: ` +|% ++$ id @ ++$ name @t ++$ src @p ++$ item [=name =src] ++$ items (map id item) ++$ action + $% [%create =name] + [%delete =id] + [%update =id =name] + == ++$ update + $% [%create =id =name =src] + [%delete =id] + [%update =id =name =src] + [%initial =items] + == +-- +` + }, { + path: `apps/${deskName}/desk/lib`, + name: `item.hoon`, + content: ` +/- *item +|% +++ decode-item-action + =, dejs:format + |= jon=json + ^- action + %. jon + %- of + :~ [%create (ot ~[name+so])] + [%delete (ot ~[id+ni])] + [%update (ot ~[id+ni name+so])] + == +++ enc-items + |= =items + ^- json + a+(turn ~(tap by items) enc-item-tuple) +++ enc-item-tuple + =, enjs:format + |= t=[=id =item] + ^= json + %- pairs + :~ ['id' (numb id.t)] + ['item' (enc-item item.t)] + == +++ enc-item + =, enjs:format + |= i=item + %- pairs + :~ + ['name' (tape (trip name.i))] + == +-- +` + }, { + path: `apps/${deskName}/desk/mar`, + name: `items.hoon`, + content: ` + /- *item + /+ *item + |_ =items + ++ grab + |% + ++ noun items + -- + ++ grow + |% + ++ noun items + ++ json (enc-items items) + -- + ++ grad %noun + -- + ` + }, + ] + return files + } + + export { + itemFiles, + } + \ No newline at end of file diff --git a/templates/aframe-desk.js b/templates/aframe-desk.js new file mode 100644 index 0000000..15b48cd --- /dev/null +++ b/templates/aframe-desk.js @@ -0,0 +1,34 @@ +import { cruft } from '../partials/cruft.js' +import { crudAgent } from '../partials/crud-agent.js' +import { itemFiles } from '../partials/item-files.js' + +function crudDesk (shipName, deskName) { + const files = [ + ...cruft(shipName, deskName), + ...crudAgent(shipName, deskName), + ...itemFiles(shipName, deskName), + { + path: `apps/${deskName}/ui`, + name: `index.html`, + content: ` + + + + + + + + + + + + + + + ` + }, + ] + return { files } +} + +export default crudDesk diff --git a/templates/sail-desk.js b/templates/cms-desk.js similarity index 100% rename from templates/sail-desk.js rename to templates/cms-desk.js diff --git a/templates/hub-desk.js b/templates/hub-desk.js new file mode 100644 index 0000000..ce77166 --- /dev/null +++ b/templates/hub-desk.js @@ -0,0 +1,83 @@ +import { cruft } from '../partials/cruft.js' +import { hubAgent } from '../partials/hub-agent.js' +import { itemFiles } from '../partials/item-source-files.js' +import { reactFiles } from '../partials/react-files.js' + +function crudDesk (shipName, deskName) { + const files = [ + ...cruft(shipName, deskName), + ...hubAgent(shipName, deskName), + ...itemFiles(shipName, deskName), + ...reactFiles(shipName, deskName), + { + path: `apps/${deskName}/ui/src`, + name: `app.jsx`, + content: ` +import React, { useEffect, useState } from 'react' +import Urbit from '@urbit/http-api' + +const api = new Urbit('', '', window.desk) +api.ship = window.ship + +const sendPoke = async (path, payload) => { + return api.poke({ + app: "hub", + mark: "item-action", + json: { [path]: { ...payload } }, + onError: err => { + alert(\\\`Error: \\\${path} failed. You may need to refresh the page and try again\\\`) + } + }) +} + +const scryFor = async (path) => { + return api.scry({ app: 'hub', path }) +} + + +export function App() { + const [items, setItems] = useState([]) + const [name, setName] = useState("") + + useEffect(() => { + async function init() { + let items = await scryFor('/items') + setItems(items) + } + init() + }, []) + + return ( +
+
+
+
+

Welcome to hub

+

Here are ~zod's items:

+
+ {items && ( +
    + {items.map(({id, item}) => ( +
  • +
    +

    + {item.name || 'untitled'} +   +

    +
    +
  • + ))} +
+ )} +
+
+
+ ) +} +` + } + ] + return { files } +} + +export default crudDesk diff --git a/templates/phaser-desk.js b/templates/phaser-desk.js new file mode 100644 index 0000000..af96199 --- /dev/null +++ b/templates/phaser-desk.js @@ -0,0 +1,77 @@ +import { cruft } from '../partials/cruft.js' +import { crudAgent } from '../partials/crud-agent.js' +import { itemFiles } from '../partials/item-files.js' + +function crudDesk (shipName, deskName) { + const files = [ + ...cruft(shipName, deskName), + ...crudAgent(shipName, deskName), + ...itemFiles(shipName, deskName), + { + path: `apps/${deskName}/ui`, + name: `index.html`, + content: ` + + + + + + + + + + + + ` + }, + ] + return { files } +} + +export default crudDesk From 9e65c9c2e6fe3db9e8416df2b37151ccbbf62d6f Mon Sep 17 00:00:00 2001 From: AJ Beckner Date: Mon, 17 Jun 2024 18:13:54 -0400 Subject: [PATCH 05/15] 1.6.1-next.0 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9970b7e..a0be46e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@archetype-org/golem", - "version": "1.5.2", + "version": "1.6.1-next.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@archetype-org/golem", - "version": "1.5.2", + "version": "1.6.1-next.0", "license": "ISC", "dependencies": { "@archetype-org/clack": "^0.2.0", diff --git a/package.json b/package.json index 39f87e8..31788f1 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "bin": { "golem": "./index.js" }, - "version": "1.6.0", + "version": "1.6.1-next.0", "description": "Project creation and package management CLI for Urbit", "main": "index.js", "scripts": { From f3d8ca507175f93f79d91474ea7689a00d1a738e Mon Sep 17 00:00:00 2001 From: AJ Beckner Date: Tue, 18 Jun 2024 11:51:50 -0400 Subject: [PATCH 06/15] keep for /ships --- partials/cruft.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/partials/cruft.js b/partials/cruft.js index a549afa..1115645 100644 --- a/partials/cruft.js +++ b/partials/cruft.js @@ -33,6 +33,10 @@ function cruft (shipName, deskName) { } ] }, null, 2) + }, { + path: 'ships', + name: '.keep', + content: '' }, { path: '.', name: '.gitignore', From 945a668e29a709a2defbf813b554c33cb97b1877 Mon Sep 17 00:00:00 2001 From: AJ Beckner Date: Tue, 18 Jun 2024 11:52:21 -0400 Subject: [PATCH 07/15] version bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 31788f1..4ea6659 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "bin": { "golem": "./index.js" }, - "version": "1.6.1-next.0", + "version": "1.6.1-next.1", "description": "Project creation and package management CLI for Urbit", "main": "index.js", "scripts": { From a80a5688089d16b4ad2bf7e8b0228934b00ecfbb Mon Sep 17 00:00:00 2001 From: AJ Beckner Date: Mon, 1 Jul 2024 11:20:11 -0500 Subject: [PATCH 08/15] changes to enable multiple desks and prevent trying ti build nonexistant react code --- lib/files.js | 16 +++++++++------- lib/react.js | 4 ++++ package.json | 2 +- partials/cruft.js | 2 +- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/lib/files.js b/lib/files.js index 2b20fe9..8868ae4 100644 --- a/lib/files.js +++ b/lib/files.js @@ -67,24 +67,26 @@ EOF async function copyDeskToUrbit (desk, ship) { try { - await execShPromise(`cp -r ./apps/${desk}/desk/* ./ships/${ship}/*`, true) + await execShPromise(`cp -r ./apps/${desk}/desk/* ./ships/${ship}/${desk}`) const packageDeps = readdirSync(`./apps/${desk}/desk-deps`) for (const packageName of packageDeps) { if (packageName[0] !== '@') { - await execShPromise(`cp -r ./apps/${desk}/desk-deps/${packageName}/* ./ships/${ship}/*`, true) + await execShPromise(`cp -r ./apps/${desk}/desk-deps/${packageName}/* ./ships/${ship}/${desk}`, true) } else { // '@' means its an org folder! const orgName = packageName const orgPackageDeps = readdirSync(`./apps/${desk}/desk-deps/${orgName}`) for (const orgPackageName of orgPackageDeps) { - await execShPromise(`cp -r ./apps/${desk}/desk-deps/${orgName}/${orgPackageName}/* ./ships/${ship}/*`, true) + await execShPromise(`cp -r ./apps/${desk}/desk-deps/${orgName}/${orgPackageName}/* ./ships/${ship}/${desk}`, true) } } } - const docketPath = `./apps/${desk}/desk/desk.docket-0` - let docketContent = readFileSync(docketPath, 'utf8') - docketContent = docketContent.replace(/%%SHIPNAME%%/g, `~${ship}`) - writeFileSync(`./ships/${ship}/${desk}/desk.docket-0`, docketContent) + if (!(desk === 'base')) { // base has no docket + const docketPath = `./apps/${desk}/desk/desk.docket-0` + let docketContent = readFileSync(docketPath, 'utf8') + docketContent = docketContent.replace(/%%SHIPNAME%%/g, `~${ship}`) + writeFileSync(`./ships/${ship}/${desk}/desk.docket-0`, docketContent) + } } catch (err) { console.error(err) return err diff --git a/lib/react.js b/lib/react.js index 781e60e..e914930 100644 --- a/lib/react.js +++ b/lib/react.js @@ -4,6 +4,10 @@ const execShPromise = execSh.promise async function buildUI (name) { const uiPath = `./apps/${name}/ui` + if (!fs.existsSync(uiPath)) { + return execShPromise(`echo "No /ui folder in ${name}, skipped building"`) + } + const nodeModulesPath = `${uiPath}/node_modules` if (!fs.existsSync(nodeModulesPath)) { diff --git a/package.json b/package.json index 4ea6659..b8f9735 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "bin": { "golem": "./index.js" }, - "version": "1.6.1-next.1", + "version": "1.6.1-next.2", "description": "Project creation and package management CLI for Urbit", "main": "index.js", "scripts": { diff --git a/partials/cruft.js b/partials/cruft.js index 1115645..cabf546 100644 --- a/partials/cruft.js +++ b/partials/cruft.js @@ -3,7 +3,7 @@ function cruft (shipName, deskName) { { path: `apps/${deskName}/desk`, name: "sys.kelvin", - content: `[%zuse 412]` + content: `[%zuse 411]` }, { path: `apps/${deskName}/desk`, name: "desk.docket-0", From fdfa44ede07e4dcfe4e14409a9b061cffe0c4785 Mon Sep 17 00:00:00 2001 From: AJ Beckner Date: Mon, 1 Jul 2024 15:39:55 -0500 Subject: [PATCH 09/15] delete old /ships creation --- commands/create.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/commands/create.js b/commands/create.js index 7e273ab..a38e06b 100644 --- a/commands/create.js +++ b/commands/create.js @@ -11,9 +11,6 @@ async function create (deskName, template, { skipDeps }) { file.path = file.path.replace('./', '') if (!(await fileExists(file))) await createFile(`./${deskName}/${file.path}/${file.name}`, file.content.trimStart()) } - - const shipsPath = `./ships` - await createPath(shipsPath) if (!skipDeps) { // download code dependancues (incl. base, garden etc) From 62f6f06ff4ad0ff140ae49c343c860b165411d72 Mon Sep 17 00:00:00 2001 From: AJ Beckner Date: Tue, 2 Jul 2024 10:54:01 -0500 Subject: [PATCH 10/15] remove extra brace in title --- partials/react-files.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/partials/react-files.js b/partials/react-files.js index 15d685e..d64282d 100644 --- a/partials/react-files.js +++ b/partials/react-files.js @@ -84,7 +84,7 @@ module.exports = { - ${deskName}} + ${deskName} From e6d42a175b1e08150bc055b7386ca0cc633d82e2 Mon Sep 17 00:00:00 2001 From: AJ Beckner Date: Tue, 2 Jul 2024 16:24:40 -0500 Subject: [PATCH 11/15] fix: don't build UI when its not there; use pathExists instead of fs module --- lib/react.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/react.js b/lib/react.js index e914930..f020f30 100644 --- a/lib/react.js +++ b/lib/react.js @@ -1,16 +1,17 @@ import execSh from "exec-sh" -import fs from "fs" +import { pathExists } from './files.js' const execShPromise = execSh.promise async function buildUI (name) { const uiPath = `./apps/${name}/ui` - if (!fs.existsSync(uiPath)) { - return execShPromise(`echo "No /ui folder in ${name}, skipped building"`) + if (!(await pathExists(uiPath))) { + console.log(`BUILD: No /ui folder in ${name}, skipped building`) + return } const nodeModulesPath = `${uiPath}/node_modules` - if (!fs.existsSync(nodeModulesPath)) { + if (!(await pathExists(nodeModulesPath))) { console.log("BUILD: node_modules not found, installing...") await execShPromise(`npm install --prefix ${uiPath}`) } From a4990456cee1d6431de767f6dccce348b0699747 Mon Sep 17 00:00:00 2001 From: AJ Beckner Date: Wed, 3 Jul 2024 15:05:41 -0500 Subject: [PATCH 12/15] shrub docket and flag --- commands/create.js | 11 +++++-- index.js | 1 + lib/urbit.js | 15 +++++++++- partials/shrub.js | 63 +++++++++++++++++++++++++++++++++++++++++ templates/shrub-desk.js | 11 +++++++ 5 files changed, 97 insertions(+), 4 deletions(-) create mode 100644 partials/shrub.js create mode 100644 templates/shrub-desk.js diff --git a/commands/create.js b/commands/create.js index a38e06b..0dc2695 100644 --- a/commands/create.js +++ b/commands/create.js @@ -1,7 +1,7 @@ import { fileExists, createFile, createPath, getTemplates } from '../lib/files.js' -import { installCoreDependencies } from '../lib/urbit.js' +import { installCoreDependencies, installShrubDependencies } from '../lib/urbit.js' -async function create (deskName, template, { skipDeps }) { +async function create (deskName, template, { skipDeps, useShrub }) { console.log(`create: creating urbit project`) console.log(`create: using template — ${template}`) const templates = await getTemplates() @@ -16,7 +16,12 @@ async function create (deskName, template, { skipDeps }) { // download code dependancues (incl. base, garden etc) const depsPath = `./${deskName}/apps/${deskName}/desk-deps` await createPath(depsPath) - await installCoreDependencies(depsPath) + if (!useShrub) { + await installCoreDependencies(depsPath) + } else { + console.log('create: installing shrub dependencies') + await installShrubDependencies(depsPath) + } } } diff --git a/index.js b/index.js index cfc0516..3eef2a6 100755 --- a/index.js +++ b/index.js @@ -33,6 +33,7 @@ program.command('new') .argument('', 'the application name — used for the desk as well as the first agent') .argument('[template]', 'the template to use: (empty | crud | tomedb', 'empty') .option('--skip-deps', 'skip downloading base and garden') + .option('--use-shrub', 'include the shrub runner in the project') .action(create) program.command('shell') diff --git a/lib/urbit.js b/lib/urbit.js index f42671c..0e41e10 100644 --- a/lib/urbit.js +++ b/lib/urbit.js @@ -34,6 +34,18 @@ rm -rf ./landscape-git`) } } +async function installShrubDependencies(depsPath) { + try { + await execShPromise(`git clone https://github.com/urbit/shrub.git ./shrub-git +mkdir ${depsPath}/shrub +rsync -avL ./shrub-git/pkg/shrub/* ${depsPath}/shrub +rm -rf ./shrub-git`) + } catch (err) { + console.log(err) + return err + } +} + async function bootFakeShip (shipName, { shell } = { shell: false}) { try { const args = !shell ? ' -dF ' : ' -F ' @@ -49,7 +61,7 @@ async function restartFakeShip (shipName, { shell } = { shell: false}) { try { const args = !shell ? ' -d ' : ' ' const port = getPortFromShipName(shipName) - await execShPromise(`./ships/urbit${args}./ships/${shipName} --http-port=${port}`) + await execShPromise(`./ships/urbit${args}--loom 33 ./ships/${shipName} --http-port=${port}`) } catch (err) { console.log(err) return err @@ -61,4 +73,5 @@ export { restartFakeShip, fetchUrbitBinary, installCoreDependencies, + installShrubDependencies, } diff --git a/partials/shrub.js b/partials/shrub.js new file mode 100644 index 0000000..51ff0e0 --- /dev/null +++ b/partials/shrub.js @@ -0,0 +1,63 @@ +function shrubCruft (shipName, deskName) { + const files = [ + { + path: `apps/${deskName}/desk`, + name: "sys.kelvin", + content: `[%zuse 411]` + }, { + path: `apps/${deskName}/desk`, + name: "desk.docket-0", + content: `:~ + title+'${deskName}' + info+'Shrubbery namespace browser.' + color+0xdd.dddd + image+'https://storage.googleapis.com/tlon-prod-memex-assets/simsur-ronbet/2024.6.19..16.56.27..5ced.9168.72b0.20c4-sky-icon.png' + site+/neo/sky + version+[0 0 1] + website+'https://github.com/urbit/shrub' + license+'MIT' + ==` + }, { + path: `apps/${deskName}/desk`, + name: "desk.bill", + content: `:~ %neo + ==` + }, { + path: '.', + name: 'ships.json', + content: JSON.stringify({ + ships: [ + { + pier: shipName, + desks: [ `${deskName}`] + } + ] + }, null, 2) + }, { + path: 'ships', + name: '.keep', + content: '' + }, { + path: '.', + name: '.gitignore', + content: `.node_modules + .DS_Store + dist + dist-ssr + *.local + stats.html + .eslintcache + .vercel + ships + ./ships/urbit + desk-deps + ` + }, + ] + return files + } + + export { + shrubCruft, + } + \ No newline at end of file diff --git a/templates/shrub-desk.js b/templates/shrub-desk.js new file mode 100644 index 0000000..8b772e1 --- /dev/null +++ b/templates/shrub-desk.js @@ -0,0 +1,11 @@ +import { shrubCruft } from '../partials/shrub.js' + +function shrubDesk (shipName, deskName) { + const files = [ + ...shrubCruft(shipName, deskName), + ] + return { files } +} + +export default shrubDesk + From 626271d9e95abb15d6e33910d514c06a399dfadf Mon Sep 17 00:00:00 2001 From: AJ Beckner Date: Thu, 4 Jul 2024 09:15:27 -0500 Subject: [PATCH 13/15] shrub template and contract cleanup --- commands/create.js | 5 +- index.js | 1 - partials/shrub-files.js | 110 ++++++++++++++++++++++++++++++++++++++++ partials/shrub.js | 63 ----------------------- templates/shrub-desk.js | 6 ++- 5 files changed, 118 insertions(+), 67 deletions(-) create mode 100644 partials/shrub-files.js delete mode 100644 partials/shrub.js diff --git a/commands/create.js b/commands/create.js index 0dc2695..952b9b9 100644 --- a/commands/create.js +++ b/commands/create.js @@ -1,7 +1,10 @@ import { fileExists, createFile, createPath, getTemplates } from '../lib/files.js' import { installCoreDependencies, installShrubDependencies } from '../lib/urbit.js' -async function create (deskName, template, { skipDeps, useShrub }) { +async function create (deskName, template, { skipDeps }) { + + const useShrub = template === 'shrub' + console.log(`create: creating urbit project`) console.log(`create: using template — ${template}`) const templates = await getTemplates() diff --git a/index.js b/index.js index 3eef2a6..cfc0516 100755 --- a/index.js +++ b/index.js @@ -33,7 +33,6 @@ program.command('new') .argument('', 'the application name — used for the desk as well as the first agent') .argument('[template]', 'the template to use: (empty | crud | tomedb', 'empty') .option('--skip-deps', 'skip downloading base and garden') - .option('--use-shrub', 'include the shrub runner in the project') .action(create) program.command('shell') diff --git a/partials/shrub-files.js b/partials/shrub-files.js new file mode 100644 index 0000000..3734f4f --- /dev/null +++ b/partials/shrub-files.js @@ -0,0 +1,110 @@ + +function shrubFiles (shipName, deskName) { + const neoPath = `apps/${deskName}/desk/neo/cod/std/src` + const files = [ + { + path: `apps/${deskName}/desk`, + name: "desk.docket-0", + content: `:~ + title+'${deskName}' + info+'Shrubbery namespace browser.' + color+0xdd.dddd + image+'https://storage.googleapis.com/tlon-prod-memex-assets/simsur-ronbet/2024.6.19..16.56.27..5ced.9168.72b0.20c4-sky-icon.png' + site+/neo/sky + version+[0 0 1] + website+'https://github.com/urbit/shrub' + license+'MIT' + ==` + }, { + path: `${neoPath}/imp`, + name: "counter.hoon", + content: `/@ number +/@ counter-diff +^- kook:neo +|% +++ state + ^- curb:neo + [%pro %number] +++ poke + ^- (set stud:neo) + (sy %counter-diff ~) +++ kids + ^- kids:neo + *kids:neo +++ deps + ^- deps:neo + *deps:neo +++ form + ^- form:neo + |_ [=bowl:neo =aeon:neo =stud:neo state-vase=vase] + +* state !<(number state-vase) + ++ init + |= old=(unit pail:neo) + ^- (quip card:neo pail:neo) + [~ (need old)] + ++ poke + |= [=stud:neo vaz=vase] + ^- (quip card:neo pail:neo) + ?> =(%counter-diff stud) + =/ act + !<(counter-diff vaz) + ?> =(-.act %inc) + [~ [%number !>(+(state))]] + -- +--` + }, { + path: `${neoPath}/pro`, + name: "counter-diff.hoon", + content: `,[%inc ~]` + }, { + path: `${neoPath}/pro`, + name: "number.hoon", + content: `,@ud` + }, { + path: `${neoPath}/con`, + name: "number-htmx.hoon", + content: `/@ number :: @ud +/- feather-icons +:- [%number %$ %htmx] +|= =number +|= =bowl:neo +^- manx +;div.p3.fc.g2.ac.br2 + ;h1: Counter + ;p: {} + ;form + =hx-post "/neo/hawk{(en-tape:pith:neo here.bowl)}?stud=counter-diff" + =hx-target "find .loading" + =hx-swap "outerHTML" + =head "inc" + ;button.bd1.br1.p2.b1.hover.loader + ;span.loaded: Increment + ;span.loading + ;+ loading.feather-icons + == + == + == +== +` + }, { + path: `${neoPath}/con`, + name: "node-counter-diff.hoon", + content: `/@ node :: manx +/@ counter-diff :: [%inc ~] +/- manx-utils +:- [%node %$ %counter-diff] +|= =node +^- counter-diff +=/ mu ~(. manx-utils node) +=/ head (?(%inc) (got:mu %head)) +[head ~] +` + } + ] + return files + } + + export { + shrubFiles, + } + \ No newline at end of file diff --git a/partials/shrub.js b/partials/shrub.js deleted file mode 100644 index 51ff0e0..0000000 --- a/partials/shrub.js +++ /dev/null @@ -1,63 +0,0 @@ -function shrubCruft (shipName, deskName) { - const files = [ - { - path: `apps/${deskName}/desk`, - name: "sys.kelvin", - content: `[%zuse 411]` - }, { - path: `apps/${deskName}/desk`, - name: "desk.docket-0", - content: `:~ - title+'${deskName}' - info+'Shrubbery namespace browser.' - color+0xdd.dddd - image+'https://storage.googleapis.com/tlon-prod-memex-assets/simsur-ronbet/2024.6.19..16.56.27..5ced.9168.72b0.20c4-sky-icon.png' - site+/neo/sky - version+[0 0 1] - website+'https://github.com/urbit/shrub' - license+'MIT' - ==` - }, { - path: `apps/${deskName}/desk`, - name: "desk.bill", - content: `:~ %neo - ==` - }, { - path: '.', - name: 'ships.json', - content: JSON.stringify({ - ships: [ - { - pier: shipName, - desks: [ `${deskName}`] - } - ] - }, null, 2) - }, { - path: 'ships', - name: '.keep', - content: '' - }, { - path: '.', - name: '.gitignore', - content: `.node_modules - .DS_Store - dist - dist-ssr - *.local - stats.html - .eslintcache - .vercel - ships - ./ships/urbit - desk-deps - ` - }, - ] - return files - } - - export { - shrubCruft, - } - \ No newline at end of file diff --git a/templates/shrub-desk.js b/templates/shrub-desk.js index 8b772e1..5edb8c8 100644 --- a/templates/shrub-desk.js +++ b/templates/shrub-desk.js @@ -1,8 +1,10 @@ -import { shrubCruft } from '../partials/shrub.js' +import { cruft } from '../partials/cruft.js' +import { shrubFiles } from '../partials/shrub-files.js' function shrubDesk (shipName, deskName) { const files = [ - ...shrubCruft(shipName, deskName), + ...cruft(shipName, deskName), + ...shrubFiles(shipName, deskName), ] return { files } } From 87dc5f809f45d3d8218635dc7c402c8997936a1d Mon Sep 17 00:00:00 2001 From: AJ Beckner Date: Thu, 4 Jul 2024 09:18:34 -0500 Subject: [PATCH 14/15] version bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b8f9735..089e194 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "bin": { "golem": "./index.js" }, - "version": "1.6.1-next.2", + "version": "1.6.1-next.3", "description": "Project creation and package management CLI for Urbit", "main": "index.js", "scripts": { From dd6608939d07b6d46ee97bf3061cda3acb04d6aa Mon Sep 17 00:00:00 2001 From: AJ Beckner Date: Thu, 11 Jul 2024 13:18:14 -0500 Subject: [PATCH 15/15] clear desk before building --- lib/files.js | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/files.js b/lib/files.js index 8868ae4..54d0dc5 100644 --- a/lib/files.js +++ b/lib/files.js @@ -67,6 +67,7 @@ EOF async function copyDeskToUrbit (desk, ship) { try { + await execShPromise(`rm -rf ./ships/${ship}/${desk}/*`) await execShPromise(`cp -r ./apps/${desk}/desk/* ./ships/${ship}/${desk}`) const packageDeps = readdirSync(`./apps/${desk}/desk-deps`) for (const packageName of packageDeps) { diff --git a/package.json b/package.json index 089e194..cd01a5b 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "bin": { "golem": "./index.js" }, - "version": "1.6.1-next.3", + "version": "1.6.1-next.4", "description": "Project creation and package management CLI for Urbit", "main": "index.js", "scripts": {