Compare commits
2 Commits
1da7e77f00
...
ed46638b50
| Author | SHA1 | Date | |
|---|---|---|---|
| ed46638b50 | |||
| 5ea9d5f843 |
1
apps/code/20260130-000000/.npmrc
Normal file
1
apps/code/20260130-000000/.npmrc
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
registry=https://npm.nose.space
|
||||||
1
apps/profile/20260130-000000/.npmrc
Normal file
1
apps/profile/20260130-000000/.npmrc
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
registry=https://npm.nose.space
|
||||||
1
apps/risk/20260130-000000/.npmrc
Normal file
1
apps/risk/20260130-000000/.npmrc
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
registry=https://npm.nose.space
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
{
|
|
||||||
"lockfileVersion": 1,
|
|
||||||
"configVersion": 1,
|
|
||||||
"workspaces": {
|
|
||||||
"": {
|
|
||||||
"name": "todo",
|
|
||||||
"dependencies": {
|
|
||||||
"@because/forge": "*",
|
|
||||||
"@because/howl": "*",
|
|
||||||
"@because/hype": "*",
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/bun": "latest",
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"typescript": "^5.9.2",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"packages": {
|
|
||||||
"@because/forge": ["@because/forge@0.0.1", "https://npm.nose.space/@because/forge/-/forge-0.0.1.tgz", { "peerDependencies": { "typescript": "^5" } }, "sha512-QS5CK51gcWma91i4uECWe4HPJeNHcE+Af4SQHOcfEovyzOEa7VOTAjei+jIWr2i+abGWqQCEC9wIuFgPgyr2Bg=="],
|
|
||||||
|
|
||||||
"@because/howl": ["@because/howl@0.0.2", "https://npm.nose.space/@because/howl/-/howl-0.0.2.tgz", { "dependencies": { "lucide-static": "^0.555.0" }, "peerDependencies": { "@because/forge": "*", "typescript": "^5" } }, "sha512-Z4okzEa282LKkBk9DQwEUU6FT+PeThfQ6iQAY41LIEjs8B2kfXRZnbWLs7tgpwCfYORxb0RO4Hr7KiyEqnfTvQ=="],
|
|
||||||
|
|
||||||
"@because/hype": ["@because/hype@0.0.1", "https://npm.nose.space/@because/hype/-/hype-0.0.1.tgz", { "dependencies": { "hono": "^4.10.4", "kleur": "^4.1.5" }, "peerDependencies": { "typescript": "^5" } }, "sha512-i92DNUXJOwt3J8dN1x8sh7i86blelcTCk8XDpwD839Ic8oe710lkDSVXJ7xYZb/i8YtzGhRg+L6eXDhaRiU2Pw=="],
|
|
||||||
|
|
||||||
"@types/bun": ["@types/bun@1.3.8", "https://npm.nose.space/@types/bun/-/bun-1.3.8.tgz", { "dependencies": { "bun-types": "1.3.8" } }, "sha512-3LvWJ2q5GerAXYxO2mffLTqOzEu5qnhEAlh48Vnu8WQfnmSwbgagjGZV6BoHKJztENYEDn6QmVd949W4uESRJA=="],
|
|
||||||
|
|
||||||
"@types/node": ["@types/node@25.1.0", "https://npm.nose.space/@types/node/-/node-25.1.0.tgz", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-t7frlewr6+cbx+9Ohpl0NOTKXZNV9xHRmNOvql47BFJKcEG1CxtxlPEEe+gR9uhVWM4DwhnvTF110mIL4yP9RA=="],
|
|
||||||
|
|
||||||
"bun-types": ["bun-types@1.3.8", "https://npm.nose.space/bun-types/-/bun-types-1.3.8.tgz", { "dependencies": { "@types/node": "*" } }, "sha512-fL99nxdOWvV4LqjmC+8Q9kW3M4QTtTR1eePs94v5ctGqU8OeceWrSUaRw3JYb7tU3FkMIAjkueehrHPPPGKi5Q=="],
|
|
||||||
|
|
||||||
"hono": ["hono@4.11.7", "https://npm.nose.space/hono/-/hono-4.11.7.tgz", {}, "sha512-l7qMiNee7t82bH3SeyUCt9UF15EVmaBvsppY2zQtrbIhl/yzBTny+YUxsVjSjQ6gaqaeVtZmGocom8TzBlA4Yw=="],
|
|
||||||
|
|
||||||
"kleur": ["kleur@4.1.5", "https://npm.nose.space/kleur/-/kleur-4.1.5.tgz", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="],
|
|
||||||
|
|
||||||
"lucide-static": ["lucide-static@0.555.0", "https://npm.nose.space/lucide-static/-/lucide-static-0.555.0.tgz", {}, "sha512-FMMaYYsEYsUA6xlEzIMoKEV3oGnxIIvAN+AtLmYXvlTJptJTveJjVBQwvtA/zZLrD6KLEu89G95dQYlhivw5jQ=="],
|
|
||||||
|
|
||||||
"typescript": ["typescript@5.9.3", "https://npm.nose.space/typescript/-/typescript-5.9.3.tgz", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
|
||||||
|
|
||||||
"undici-types": ["undici-types@7.16.0", "https://npm.nose.space/undici-types/-/undici-types-7.16.0.tgz", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
export { default } from './src/server'
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
{
|
|
||||||
"name": "todo",
|
|
||||||
"module": "index.tsx",
|
|
||||||
"type": "module",
|
|
||||||
"private": true,
|
|
||||||
"scripts": {
|
|
||||||
"toes": "bun run --watch index.tsx",
|
|
||||||
"start": "bun toes",
|
|
||||||
"dev": "bun run --hot index.tsx"
|
|
||||||
},
|
|
||||||
"toes": {
|
|
||||||
"tool": true,
|
|
||||||
"icon": "🖥️"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/bun": "latest"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"typescript": "^5.9.2"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@because/hype": "*",
|
|
||||||
"@because/forge": "*",
|
|
||||||
"@because/howl": "*"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,36 +0,0 @@
|
||||||
import { render, useState } from 'hono/jsx/dom'
|
|
||||||
import { define } from '@because/forge'
|
|
||||||
|
|
||||||
const Wrapper = define({
|
|
||||||
margin: '0 auto',
|
|
||||||
marginTop: 50,
|
|
||||||
width: '50vw',
|
|
||||||
border: '1px solid black',
|
|
||||||
padding: 24,
|
|
||||||
textAlign: 'center'
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
export default function App() {
|
|
||||||
const [count, setCount] = useState(0)
|
|
||||||
|
|
||||||
try {
|
|
||||||
return (
|
|
||||||
<Wrapper>
|
|
||||||
<h1>It works!</h1>
|
|
||||||
<h2>Count: {count}</h2>
|
|
||||||
<div>
|
|
||||||
<button onClick={() => setCount(c => c + 1)}>+</button>
|
|
||||||
|
|
||||||
<button onClick={() => setCount(c => c && c - 1)}>-</button>
|
|
||||||
</div>
|
|
||||||
</Wrapper>
|
|
||||||
)
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Render error:', error)
|
|
||||||
return <><h1>Error</h1><pre>{error instanceof Error ? error : new Error(String(error))}</pre></>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const root = document.getElementById('root')!
|
|
||||||
render(<App />, root)
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
section {
|
|
||||||
max-width: 500px;
|
|
||||||
margin: 0 auto;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 200%;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hype {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 0.3rem 0.8rem;
|
|
||||||
background: linear-gradient(45deg,
|
|
||||||
#ff00ff 0%,
|
|
||||||
#00ffff 33%,
|
|
||||||
#ffff00 66%,
|
|
||||||
#ff00ff 100%);
|
|
||||||
background-size: 400% 400%;
|
|
||||||
animation: gradientShift 15s ease infinite;
|
|
||||||
color: black;
|
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
||||||
font-weight: 700;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes gradientShift {
|
|
||||||
0% {
|
|
||||||
background-position: 0% 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
background-position: 100% 50%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ul {
|
|
||||||
list-style-type: none;
|
|
||||||
}
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
import { $ } from 'bun'
|
|
||||||
|
|
||||||
const GIT_HASH = process.env.RENDER_GIT_COMMIT?.slice(0, 7)
|
|
||||||
|| await $`git rev-parse --short HEAD`.text().then(s => s.trim()).catch(() => 'unknown')
|
|
||||||
|
|
||||||
export default () => <>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<title>hype</title>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<meta name="color-scheme" content="light dark" />
|
|
||||||
|
|
||||||
<link href={`/css/main.css?${GIT_HASH}`} rel="stylesheet" />
|
|
||||||
<script dangerouslySetInnerHTML={{
|
|
||||||
__html: `
|
|
||||||
window.GIT_HASH = '${GIT_HASH}';
|
|
||||||
${(process.env.NODE_ENV !== 'production' || process.env.IS_PULL_REQUEST === 'true') ? 'window.DEBUG = true;' : ''}
|
|
||||||
`
|
|
||||||
}} />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="viewport">
|
|
||||||
<main>
|
|
||||||
<div id="root" />
|
|
||||||
<script src={`/client/app.js?${GIT_HASH}`} type="module" />
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
</>
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
import { Hype } from '@because/hype'
|
|
||||||
|
|
||||||
const app = new Hype({ layout: false })
|
|
||||||
|
|
||||||
// custom routes go here
|
|
||||||
// app.get("/my-custom-routes", (c) => c.text("wild, wild stuff"))
|
|
||||||
|
|
||||||
export default app.defaults
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"lib": ["ESNext"],
|
|
||||||
"target": "ESNext",
|
|
||||||
"module": "Preserve",
|
|
||||||
"moduleDetection": "force",
|
|
||||||
"jsx": "react-jsx",
|
|
||||||
"jsxImportSource": "hono/jsx",
|
|
||||||
"allowJs": true,
|
|
||||||
"moduleResolution": "bundler",
|
|
||||||
"allowImportingTsExtensions": true,
|
|
||||||
"verbatimModuleSyntax": true,
|
|
||||||
"noEmit": true,
|
|
||||||
"strict": true,
|
|
||||||
"skipLibCheck": true,
|
|
||||||
"noFallthroughCasesInSwitch": true,
|
|
||||||
"noUncheckedIndexedAccess": true,
|
|
||||||
"noImplicitOverride": true,
|
|
||||||
"noUnusedLocals": false,
|
|
||||||
"noUnusedParameters": false,
|
|
||||||
"noPropertyAccessFromIndexSignature": false,
|
|
||||||
"baseUrl": ".",
|
|
||||||
"paths": {
|
|
||||||
"$*": ["src/server/*"],
|
|
||||||
"#*": ["src/client/*"],
|
|
||||||
"@*": ["src/shared/*"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
1
apps/truisms/20260130-000000/.npmrc
Normal file
1
apps/truisms/20260130-000000/.npmrc
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
registry=https://npm.nose.space
|
||||||
|
|
@ -53,7 +53,7 @@ export async function infoApp(arg?: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const icon = STATE_ICONS[app.state] ?? '◯'
|
const icon = STATE_ICONS[app.state] ?? '◯'
|
||||||
console.log(`${icon} ${color.bold(app.name)}`)
|
console.log(`${icon} ${color.bold(app.name)} ${app.tool && '[tool]'}`)
|
||||||
console.log(` State: ${app.state}`)
|
console.log(` State: ${app.state}`)
|
||||||
if (app.port) {
|
if (app.port) {
|
||||||
console.log(` Port: ${app.port}`)
|
console.log(` Port: ${app.port}`)
|
||||||
|
|
@ -73,11 +73,22 @@ export async function infoApp(arg?: string) {
|
||||||
if (app.error) console.log(` Error: ${color.red(app.error)}`)
|
if (app.error) console.log(` Error: ${color.red(app.error)}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function listApps() {
|
interface ListAppsOptions {
|
||||||
|
tools?: boolean
|
||||||
|
all?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function listApps(options: ListAppsOptions) {
|
||||||
const apps: App[] | undefined = await get('/api/apps')
|
const apps: App[] | undefined = await get('/api/apps')
|
||||||
if (!apps) return
|
if (!apps) return
|
||||||
|
|
||||||
for (const app of apps) {
|
const filtered = apps.filter((app) => {
|
||||||
|
if (options.all) return true
|
||||||
|
if (options.tools) return app.tool
|
||||||
|
return !app.tool
|
||||||
|
})
|
||||||
|
|
||||||
|
for (const app of filtered) {
|
||||||
console.log(`${STATE_ICONS[app.state] ?? '◯'} ${app.name}`)
|
console.log(`${STATE_ICONS[app.state] ?? '◯'} ${app.name}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import { program } from 'commander'
|
import { program } from 'commander'
|
||||||
import { readFileSync } from 'fs'
|
|
||||||
|
|
||||||
import color from 'kleur'
|
import color from 'kleur'
|
||||||
import {
|
import {
|
||||||
|
|
@ -60,6 +59,8 @@ program
|
||||||
program
|
program
|
||||||
.command('list')
|
.command('list')
|
||||||
.description('List all apps')
|
.description('List all apps')
|
||||||
|
.option('-t, --tools', 'show only tools')
|
||||||
|
.option('-a, --all', 'show all apps including tools')
|
||||||
.action(listApps)
|
.action(listApps)
|
||||||
|
|
||||||
program
|
program
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ const render = () => {
|
||||||
// Update tool iframes after DOM settles
|
// Update tool iframes after DOM settles
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
const tools = apps.filter(a => a.tool)
|
const tools = apps.filter(a => a.tool)
|
||||||
updateToolIframes(selectedTab, tools)
|
updateToolIframes(selectedTab, tools, selectedApp)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,11 @@ export function initToolIframes() {
|
||||||
const match = iframe.src.match(/localhost:(\d+)/)
|
const match = iframe.src.match(/localhost:(\d+)/)
|
||||||
if (match && match[1]) {
|
if (match && match[1]) {
|
||||||
const port = parseInt(match[1], 10)
|
const port = parseInt(match[1], 10)
|
||||||
const name = iframe.dataset.toolName
|
const toolName = iframe.dataset.toolName
|
||||||
if (name) {
|
const appName = iframe.dataset.appName
|
||||||
iframes.set(name, { iframe, port })
|
if (toolName) {
|
||||||
|
const cacheKey = appName ? `${toolName}:${appName}` : toolName
|
||||||
|
iframes.set(cacheKey, { iframe, port })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -42,7 +44,8 @@ export function initToolIframes() {
|
||||||
// Update which iframe is visible based on selected tab and tool state
|
// Update which iframe is visible based on selected tab and tool state
|
||||||
export function updateToolIframes(
|
export function updateToolIframes(
|
||||||
selectedTab: string,
|
selectedTab: string,
|
||||||
tools: Array<{ name: string; port?: number; state: string }>
|
tools: Array<{ name: string; port?: number; state: string }>,
|
||||||
|
selectedApp: string | null
|
||||||
) {
|
) {
|
||||||
const container = getContainer()
|
const container = getContainer()
|
||||||
if (!container) return
|
if (!container) return
|
||||||
|
|
@ -63,8 +66,11 @@ export function updateToolIframes(
|
||||||
|
|
||||||
const tool = selectedTool!
|
const tool = selectedTool!
|
||||||
|
|
||||||
|
// Build cache key for tool + app combination
|
||||||
|
const cacheKey = selectedApp ? `${tool.name}:${selectedApp}` : tool.name
|
||||||
|
|
||||||
// Skip if nothing changed
|
// Skip if nothing changed
|
||||||
if (currentTool === tool.name) {
|
if (currentTool === cacheKey) {
|
||||||
// Just update position in case of scroll/resize
|
// Just update position in case of scroll/resize
|
||||||
const tabContent = document.querySelector('[data-tool-target]')
|
const tabContent = document.querySelector('[data-tool-target]')
|
||||||
if (tabContent) {
|
if (tabContent) {
|
||||||
|
|
@ -97,34 +103,38 @@ export function updateToolIframes(
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
`
|
`
|
||||||
|
|
||||||
// Get or create the iframe for this tool
|
// Get or create the iframe for this tool + app combination
|
||||||
let cached = iframes.get(tool.name)
|
let cached = iframes.get(cacheKey)
|
||||||
|
|
||||||
if (!cached || cached.port !== tool.port) {
|
if (!cached || cached.port !== tool.port) {
|
||||||
// Create new iframe (first time or port changed)
|
// Create new iframe (first time or port changed)
|
||||||
const iframe = document.createElement('iframe')
|
const iframe = document.createElement('iframe')
|
||||||
iframe.src = `http://localhost:${tool.port}`
|
const url = selectedApp
|
||||||
|
? `http://localhost:${tool.port}?app=${encodeURIComponent(selectedApp)}`
|
||||||
|
: `http://localhost:${tool.port}`
|
||||||
|
iframe.src = url
|
||||||
iframe.dataset.toolName = tool.name // For hot reload recovery
|
iframe.dataset.toolName = tool.name // For hot reload recovery
|
||||||
|
iframe.dataset.appName = selectedApp ?? '' // For hot reload recovery
|
||||||
iframe.style.cssText = `
|
iframe.style.cssText = `
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
border: none;
|
border: none;
|
||||||
`
|
`
|
||||||
cached = { iframe, port: tool.port! }
|
cached = { iframe, port: tool.port! }
|
||||||
iframes.set(tool.name, cached)
|
iframes.set(cacheKey, cached)
|
||||||
// Add to container
|
// Add to container
|
||||||
container.appendChild(iframe)
|
container.appendChild(iframe)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show only the selected iframe, hide others
|
// Show only the selected iframe, hide others
|
||||||
for (const [name, { iframe }] of iframes) {
|
for (const [key, { iframe }] of iframes) {
|
||||||
const shouldShow = name === tool.name
|
const shouldShow = key === cacheKey
|
||||||
if (shouldShow && iframe.parentElement !== container) {
|
if (shouldShow && iframe.parentElement !== container) {
|
||||||
container.appendChild(iframe)
|
container.appendChild(iframe)
|
||||||
}
|
}
|
||||||
iframe.style.display = shouldShow ? 'block' : 'none'
|
iframe.style.display = shouldShow ? 'block' : 'none'
|
||||||
}
|
}
|
||||||
|
|
||||||
currentTool = tool.name
|
currentTool = cacheKey
|
||||||
;(window as any).__currentTool = tool.name
|
;(window as any).__currentTool = cacheKey
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user