Skip to content

Commit

Permalink
fix: include type definitions
Browse files Browse the repository at this point in the history
  • Loading branch information
wkillerud committed Sep 23, 2024
1 parent aa4e076 commit 9389774
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 122 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ coverage/
node_modules/
*.log
.vscode
.tap
.tap
*.d.ts
!podium.d.ts
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const app = fastify();
const podlet = new Podlet({
pathname: '/',
version: '2.0.0',
name: 'podletContent',
name: 'podlet-content',
});

// Register the plugin, with the podlet as the option
Expand All @@ -44,21 +44,24 @@ app.get(podlet.content(), async (request, reply) => {
return;
}
reply.podiumSend('<h2>Hello world</h2>');
await reply;
});

app.get(podlet.manifest(), async (request, reply) => {
reply.send(podlet);
await reply;
});

const start = async () => {
try {
await app.listen(7100);
await app.listen({ port: 7100 });
app.log.info(`server listening on ${app.server.address().port}`);
} catch (err) {
app.log.error(err);
process.exit(1);
}
};

start();
```

Expand Down Expand Up @@ -86,6 +89,7 @@ app.get(podlet.content(), async (request, reply) => {
return;
}
reply.podiumSend('<h2>Hello world</h2>');
await reply;
});
```

Expand Down
59 changes: 0 additions & 59 deletions example/server.js

This file was deleted.

12 changes: 12 additions & 0 deletions fixup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import fs from 'node:fs';
import path from 'node:path';

let podium = path.join(process.cwd(), 'types', 'podium.d.ts');
let module = path.join(process.cwd(), 'types', 'podlet-plugin.d.ts');

fs.writeFileSync(
module,
`${fs.readFileSync(podium, 'utf-8')}
${fs.readFileSync(module, 'utf-8')}`,
'utf-8',
);
129 changes: 73 additions & 56 deletions lib/podlet-plugin.js
Original file line number Diff line number Diff line change
@@ -1,68 +1,85 @@
import { HttpIncoming, pathnameBuilder } from '@podium/utils';
import fp from 'fastify-plugin';

const podiumPodletFastifyPlugin = (fastify, podlet, done) => {
// Decorate reply with .app.podium we can write to throught the request
fastify.decorateReply('app', null);
fastify.addHook('onRequest', async (request, reply) => {
reply.app = {
podium: {},
};
});

// Run parsers on pre handler and store state object on reply.app.podium
fastify.addHook('preHandler', async (request, reply) => {
const incoming = new HttpIncoming(
request.raw,
reply.raw,
reply.app.params,
);
reply.app.podium = await podlet.process(incoming, { proxy: false });
});

// Set http headers on response
fastify.addHook('preHandler', async (request, reply) => {
reply.header('podlet-version', podlet.version);
});

// Decorate response with .podiumSend() method
fastify.decorateReply('podiumSend', function podiumSend(payload) {
this.type('text/html; charset=utf-8'); // "this" here is the fastify 'Reply' object
this.send(podlet.render(this.app.podium, payload));
});

// Mount proxy route as an instance so its executed only on
// the registered path. Iow: the proxy check is not run on
// any other routes
fastify.register((instance, opts, next) => {
const pathname = pathnameBuilder(
podlet.httpProxy.pathname,
podlet.httpProxy.prefix,
'/*',
);
export default fp(
/**
* @type {import('fastify').FastifyPluginCallback<import('@podium/podlet').default>}
*/
(fastify, podlet, done) => {
// Decorate reply with .app.podium we can write to throught the request
fastify.decorateReply('app', null);
fastify.addHook('onRequest', async (request, reply) => {
// @ts-ignore We decorate this above
reply.app = {
podium: {},
};
});

// Allow all content types for proxy requests
// https://github.com/fastify/fastify/blob/main/docs/ContentTypeParser.md#catch-all
instance.addContentTypeParser('*', (req, payload, cb) => {
cb();
// Run parsers on pre handler and store state object on reply.app.podium
fastify.addHook('preHandler', async (request, reply) => {
const incoming = new HttpIncoming(
request.raw,
reply.raw,
// @ts-ignore
reply.app.params,
);
// @ts-ignore We decorate this above
reply.app.podium = await podlet.process(incoming, { proxy: false });
});

instance.addHook('preHandler', async (req, reply) => {
const incoming = await podlet.httpProxy.process(reply.app.podium);
if (incoming.proxy) return;
return incoming;
// Set http headers on response
fastify.addHook('preHandler', async (request, reply) => {
reply.header('podlet-version', podlet.version);
});

instance.all(pathname, (req, reply) => {
reply.code(404).send('Not found');
// Decorate response with .podiumSend() method
fastify.decorateReply('podiumSend', function podiumSend(payload) {
this.type('text/html; charset=utf-8'); // "this" here is the fastify 'Reply' object
this.send(
podlet.render(
// @ts-ignore We decorate this above
this.app.podium,
payload,
),
);
});

next();
});
// Mount proxy route as an instance so its executed only on
// the registered path. Iow: the proxy check is not run on
// any other routes
fastify.register((instance, opts, next) => {
const pathname = pathnameBuilder(
podlet.httpProxy.pathname,
podlet.httpProxy.prefix,
'/*',
);

done();
};
// Allow all content types for proxy requests
// https://github.com/fastify/fastify/blob/main/docs/ContentTypeParser.md#catch-all
instance.addContentTypeParser('*', (req, payload, cb) => {
// @ts-ignore
cb();
});

instance.addHook('preHandler', async (req, reply) => {
const incoming = await podlet.httpProxy.process(
// @ts-ignore We decorate this above
reply.app.podium,
);
if (incoming.proxy) return;
return incoming;
});

instance.all(pathname, (req, reply) => {
reply.code(404).send('Not found');
});

next();
});

export default fp(podiumPodletFastifyPlugin, {
name: 'podium-podlet',
});
done();
},
{
name: 'podium-podlet',
},
);
16 changes: 12 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"type": "module",
"description": "Fastify plugin for Podium Podlet",
"main": "lib/podlet-plugin.js",
"types": "types/podlet-plugin.d.ts",
"repository": {
"type": "git",
"url": "[email protected]:podium-lib/fastify-podlet.git"
Expand All @@ -17,13 +18,18 @@
"CHANGELOG.md",
"README.md",
"LICENSE",
"lib"
"lib",
"types"
],
"scripts": {
"test": "tap --disable-coverage --allow-empty-coverage",
"test:coverage": "tap",
"lint": "eslint .",
"lint:fix": "eslint . --fix"
"lint:fix": "eslint . --fix",
"types": "run-s types:tsc types:fixup",
"types:tsc": "tsc",
"types:test": "tsc --project tsconfig.test.json",
"types:fixup": "node ./fixup.js"
},
"author": "Trygve Lie",
"license": "MIT",
Expand All @@ -40,7 +46,7 @@
},
"devDependencies": {
"@fastify/formbody": "7.4.0",
"@podium/podlet": "5.1.12",
"@podium/podlet": "5.1.16",
"@podium/test-utils": "2.5.2",
"@semantic-release/changelog": "6.0.3",
"@semantic-release/commit-analyzer": "11.1.0",
Expand All @@ -53,8 +59,10 @@
"eslint-plugin-prettier": "5.2.1",
"fastify": "4.28.1",
"globals": "15.9.0",
"npm-run-all2": "6.2.3",
"prettier": "3.3.3",
"semantic-release": "23.1.1",
"tap": "18.8.0"
"tap": "18.8.0",
"typescript": "5.6.2"
}
}
16 changes: 16 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"compilerOptions": {
"lib": ["es2020"],
"module": "nodenext",
"target": "es2020",
"resolveJsonModule": true,
"checkJs": true,
"allowJs": true,
"moduleResolution": "nodenext",
"noEmit": true,
"declaration": true,
"allowSyntheticDefaultImports": true,
"outDir": "types"
},
"include": ["./lib/**/*.js"]
}
9 changes: 9 additions & 0 deletions tsconfig.test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "./tsconfig.json",
"include": ["./tests/**/*.js"],
"compilerOptions": {
"module": "nodenext",
"moduleResolution": "nodenext",
"noEmit": true
}
}
22 changes: 22 additions & 0 deletions types/podium.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
declare module 'fastify' {
interface PodiumLocals {} // this is declared in @podium/podlet, we just hook onto it here

interface FastifyReply {
app: PodiumLocals;

/**
* Calls the send / write method on the `http.ServerResponse` object.
*
* When in development mode this method will wrap the provided fragment in a
* default HTML document before dispatching. When not in development mode, this
* method will just dispatch the fragment.
*
* @example
* app.get(podlet.content(), async (req, reply) => {
* reply.podiumSend('<h1>Hello World</h1>');
* await reply;
* });
*/
podiumSend(fragment: string, ...args: unknown[]): Response;
}
}

0 comments on commit 9389774

Please sign in to comment.