Skip to content

feat: ofetch addition for unified fetching on both sides #24

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion adex/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
"types": "./src/ssr.d.ts",
"import": "./src/ssr.js"
},
"./types": {
"types": "./types.d.ts"
},
"./head": {
"types": "./src/head.d.ts",
"import": "./src/head.js"
Expand Down Expand Up @@ -61,11 +64,13 @@
"hoofd": "^1.7.1",
"mri": "^1.2.0",
"node-stream-zip": "^1.15.0",
"ofetch": "^1.4.1",
"preact-render-to-string": "^6.5.5",
"regexparam": "^3.0.0",
"sirv": "^2.0.4",
"trouter": "^4.0.0",
"unifont": "^0.0.2"
"unifont": "^0.0.2",
"unimport": "^4.0.0"
},
"devDependencies": {
"@preact/preset-vite": "^2.8.2",
Expand Down
16 changes: 16 additions & 0 deletions adex/runtime/fetch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { ofetch as _ofetch } from 'ofetch'
import { env } from 'adex/env'

const constructBaseURL = () => {
if (import.meta.server) {
const origin = env.get('HOST', 'localhost')
const port = env.get('PORT', '3000')
return new URL(`http:${origin}${port ? `:${port}` : ''}`).toString()
}
return window.location.toString()
}

const baseURL = constructBaseURL()
export const $fetch = _ofetch.create({
baseURL: baseURL,
})
25 changes: 13 additions & 12 deletions adex/src/env.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
const isClient = typeof window !== 'undefined'
export const env = {}

if (isClient) {
throw new Error('[adex] Cannot use/import `adex/env` on the client side')
}

export const env = {
get(key, defaultValue = '') {
if (isClient) return ''
if (import.meta.server) {
env.get = (key, defaultValue = '') => {
return process.env[key] ?? defaultValue
},
set(key, value) {
if (isClient) return ''
}
env.set = (key, value) => {
return (process.env[key] = value)
},
}
} else {
env.get = (key, defaultValue = '') => {
return import.meta.env[key] ?? defaultValue
}
env.set = (key, value) => {
return (import.meta.env[key] = value)
}
}
2 changes: 1 addition & 1 deletion adex/src/ssr.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ export { renderToString } from 'preact-render-to-string'
export { parse as pathToRegex } from 'regexparam'
export { use as useMiddleware } from '@barelyhuman/tiny-use'
export { default as sirv } from 'sirv'
export { default as mri } from 'mri'
export { default as mri } from 'mri'
82 changes: 41 additions & 41 deletions adex/src/vite.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
isFunctionIsland,
readSourceFile,
} from '@dumbjs/preland'
import Unimport from 'unimport/unplugin'
import { addImportToAST, codeFromAST } from '@dumbjs/preland/ast'
import preact from '@preact/preset-vite'
import { mkdirSync, readFileSync, writeFileSync } from 'fs'
Expand Down Expand Up @@ -37,6 +38,7 @@ export function adex({
adapter: adapter = 'node',
} = {}) {
return [
adexConfig(),
preactPages({
root: '/src/pages',
id: '~routes',
Expand All @@ -61,15 +63,15 @@ export function adex({
import { dirname, join } from 'node:path'
import { fileURLToPath } from 'node:url'
import { existsSync, readFileSync } from 'node:fs'
import { env } from 'adex/env'
import {env} from "adex/env"

import 'virtual:adex:font.css'
import 'virtual:adex:global.css'

const __dirname = dirname(fileURLToPath(import.meta.url))

const PORT = parseInt(env.get('PORT', '3000'), 10)
const HOST = env.get('HOST', 'localhost')
const PORT = parseInt(env.get("PORT","3000"))
const HOST = env.get("HOST","localhost")

const paths = {
assets: join(__dirname, './assets'),
Expand Down Expand Up @@ -128,7 +130,6 @@ export function adex({
adexServerBuilder({ islands }),
!islands && adexClientBuilder(),
islands && adexIslandsBuilder(),
...adexGuards(),
]
}

Expand Down Expand Up @@ -212,6 +213,10 @@ function adexIslandsBuilder() {
await build({
configFile: false,
plugins: [preact()],
define: {
'import.meta.server': false,
'import.meta.client': true,
},
build: {
ssr: false,
outDir: join(outDir, 'islands'),
Expand Down Expand Up @@ -346,6 +351,10 @@ function adexClientBuilder() {
),
preact({ prefreshEnabled: false }),
],
define: {
'import.meta.client': true,
'import.meta.server': false,
},
build: {
outDir: 'dist/client',
emptyOutDir: true,
Expand Down Expand Up @@ -388,8 +397,12 @@ function adexServerBuilder({ islands = false } = {}) {
return {
appType: 'custom',
ssr: {
external: ['preact', 'adex', 'preact-render-to-string'],
noExternal: Object.values(adapterMap),
external: ['preact', 'preact-render-to-string'],
noExternal: Object.values(adapterMap).concat('adex/env'),
},
define: {
'import.meta.server': true,
'import.meta.client': false,
},
build: {
outDir: 'dist/server',
Expand Down Expand Up @@ -479,45 +492,32 @@ function adexServerBuilder({ islands = false } = {}) {
/**
* @returns {import("vite").Plugin[]}
*/
function adexGuards() {
function adexConfig() {
return [
// @ts-expect-error something wrong wrong
Unimport.vite({
imports: [
{
name: '$fetch',
from: fileURLToPath(new URL('../runtime/fetch.js', import.meta.url)),
},
],
}),
{
name: 'adex-guard-env',
name: 'adex-config',
enforce: 'pre',
async transform(code, id) {
// ignore usage of `process.env` in node_modules
// Still risky but hard to do anything about
const nodeMods = resolve(cwd, 'node_modules')
if (id.startsWith(nodeMods)) return

// ignore usage of `process.env` in `adex/env`
const envLoadId = await this.resolve('adex/env')
if (id === envLoadId.id) return

if (code.includes('process.env')) {
this.error(
'Avoid using `process.env` to access environment variables and secrets. Use `adex/env` instead'
)
}
},
writeBundle() {
const pagesPath = resolve(cwd, 'src/pages')
const info = this.getModuleInfo('adex/env')
const viteRef = this

function checkTree(importPath, importStack = []) {
if (importPath.startsWith(pagesPath)) {
throw new Error(
`Cannot use/import \`adex/env\` on the client side, importerStack: ${importStack.join(' -> ')}`
)
}
viteRef
.getModuleInfo(importPath)
.importers.forEach(d =>
checkTree(d, [...importStack, importPath, d])
)
config() {
return {
server: {
port: 3000,
},
define: {
'import.meta.env.PORT': JSON.stringify(process.env.PORT ?? '3000'),
'import.meta.env.HOST': JSON.stringify(
process.env.HOST ?? 'localhost'
),
},
}
info.importers.forEach(i => checkTree(i))
},
},
]
Expand Down
4 changes: 4 additions & 0 deletions adex/types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
interface ImportMeta {
readonly server: boolean
readonly client: boolean
}
1 change: 0 additions & 1 deletion packages/adapters/node/lib/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { existsSync } from 'node:fs'
import http from 'node:http'

import { sirv, useMiddleware } from 'adex/ssr'

import { handler } from 'virtual:adex:handler'
Expand Down
77 changes: 40 additions & 37 deletions playground/.islands/island-counter.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { render, h } from 'preact'

import { render, h } from 'preact';

// h() imports will be added at build time since this file is inlined with the client template
// h() imports will be added at build time since this file is inlined with the client template

const restoreTree = (type, props = {}) => {
if (typeof props.children === 'object') {
Expand Down Expand Up @@ -61,49 +60,53 @@ function mergePropsWithDOM(rootNode, props) {
rootNode.append(...scriptNodes)
}

init()

init()

function init(){
if(customElements.get("island-counter")){
return
}
customElements.define("island-counter", class IslandCounter extends HTMLElement {
constructor(){
super();
function init() {
if (customElements.get('island-counter')) {
return
}
customElements.define(
'island-counter',
class IslandCounter extends HTMLElement {
constructor() {
super()
}

async connectedCallback() {
const c = await import("/Users/sid/code/adex/playground/src/components/counter.tsx");
const usableComponent = c["Counter"]
const props = JSON.parse(this.dataset.props || '{}');
this.baseProps = props
this.component = usableComponent
this.renderOnView({threshold:0.2})
const c = await import(
'/Users/sid/code/adex/playground/src/components/counter.tsx'
)
const usableComponent = c['Counter']
const props = JSON.parse(this.dataset.props || '{}')
this.baseProps = props
this.component = usableComponent
this.renderOnView({ threshold: 0.2 })
}
renderOnView({threshold} = {}){

renderOnView({ threshold } = {}) {
const options = {
root: null,
threshold,
};
const self = this;
const callback = function(entries, observer) {
entries.forEach((entry) => {
if(!entry.isIntersecting) return
}

const self = this

const callback = function (entries, observer) {
entries.forEach(entry => {
if (!entry.isIntersecting) return
self.renderIsland()
});
})
}
let observer = new IntersectionObserver(callback, options);
observer.observe(this);

let observer = new IntersectionObserver(callback, options)
observer.observe(this)
}
renderIsland(){
mergePropsWithDOM(this, this.baseProps);

renderIsland() {
mergePropsWithDOM(this, this.baseProps)
render(restoreTree(this.component, this.baseProps), this, undefined)
}
})
}
}
)
}
7 changes: 6 additions & 1 deletion playground/src/components/SharedSignal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@ export function Triggerer() {
return (
<div class="p-10 border border-red-400 border-dashed">
<h2>Triggerer Island</h2>
<button class="px-4 py-2 text-white bg-black rounded-md" onClick={fetchData}>Fetch Again</button>
<button
class="px-4 py-2 text-white bg-black rounded-md"
onClick={fetchData}
>
Fetch Again
</button>
</div>
)
}
Expand Down
2 changes: 1 addition & 1 deletion playground/src/global.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@tailwind utilities;
16 changes: 8 additions & 8 deletions playground/src/index.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
</head>
<body>
<div id="app"></div>
</body>
</html>
</body>
</html>
Loading
Loading