Skip to content
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

feat(runtime-logger): Expose integration logger on runtime #125

Merged
merged 8 commits into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from 5 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
5 changes: 5 additions & 0 deletions .changeset/wild-boxes-judge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@inox-tools/runtime-logger': minor
---

Expose `AstroIntegrationLogger` in runtime
3 changes: 3 additions & 0 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ pkg/aik-route-config:
pkg/custom-routing:
- 'packages/custom-routing/**'

pkg/runtime-logger:
- 'packages/runtime-logger/**'

pkg/inline-mod:
- 'packages/inline-mod/**'

Expand Down
4 changes: 4 additions & 0 deletions docs/astro.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ export default defineConfig({
label: 'Astro When',
link: '/astro-when',
},
{
label: 'Runtime Logger',
link: '/runtime-logger',
},
],
},
{
Expand Down
3 changes: 2 additions & 1 deletion docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
"@vercel/analytics": "^1.3.1",
"astro": "^4.11.5",
"sharp": "^0.33.4",
"starlight-links-validator": "^0.9.1"
"starlight-links-validator": "^0.9.1",
"starlight-package-managers": "^0.6.0"
},
"devDependencies": {
"@astrojs/check": "^0.7.0",
Expand Down
48 changes: 48 additions & 0 deletions docs/src/content/docs/runtime-logger.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
title: Runtime Logger
packageName: '@inox-tools/runtime-logger'
description: Access your Astro Integration Logger from the runtime of your integration.
---

Astro provides [a logger (typed `AstroIntegrationLogger`)](https://docs.astro.build/en/reference/integrations-reference/#astrointegrationlogger) configured for each integration on all the official [integration hooks](https://docs.astro.build/en/reference/integrations-reference/#hooks). But this logger is only accessible on the code configuring the integration, not for any runtime modules defined by it.

This integration allows you to access the logger from the runtime of your integration.

## Installing the integration

import { PackageManagers } from 'starlight-package-managers';

<PackageManagers pkg="@inox-tools/runtime-logger" />

## Using the integration

To enable this, you need to register your integration to have a runtime logger under some name:

```ts title="your-integration/index.ts" ins={1,7-9}
import { runtimeLogger } from '@inox-tools/runtime-logger';

export default () => ({
name: 'your-integration',
hooks: {
'astro:config:setup': (params) => {
runtimeLogger(params, {
name: 'your-integration',
});
},
},
});
```

With that in place, your runtime code can now access the logger by importing the generated module `@it-astro:logger:<name>`:

```astro title="injected-route.astro"
---
import { logger } from '@it-astro:logger:your-integration';

logger.info('Hello World!');
---
```

## License

Astro Runtime Logger is available under the MIT license.
4 changes: 4 additions & 0 deletions examples/content-injection/integration.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { injectCollections } from '@inox-tools/content-utils';
import { runtimeLogger } from '@inox-tools/runtime-logger';
import { defineIntegration } from 'astro-integration-kit';

export default defineIntegration({
Expand All @@ -7,6 +8,9 @@ export default defineIntegration({
return {
hooks: {
'astro:config:setup': (params) => {
runtimeLogger(params, {
name: 'test-integration',
});
injectCollections(params, {
entrypoint: './src/integration/config.ts',
seedTemplateDirectory: './src/integration',
Expand Down
1 change: 1 addition & 0 deletions examples/content-injection/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"dependencies": {
"@astrojs/check": "^0.7.0",
"@inox-tools/content-utils": "workspace:^",
"@inox-tools/runtime-logger": "workspace:^",
"astro": "^4.11.5",
"astro-integration-kit": "^0.14.0",
"typescript": "^5.5.3"
Expand Down
3 changes: 3 additions & 0 deletions examples/content-injection/src/pages/index.astro
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
---
import { getLatestCommitDate, getOldestCommitDate } from '@it-astro:content/git';
import { getCollection } from 'astro:content';
import { logger } from '@it-astro:logger:test-integration';

const entries = await getCollection('blog');

logger.info(`Retrieved ${entries.length} entries`);

const dates = await Promise.all(
entries.map(async (entry) => {
const latest = await getLatestCommitDate(entry);
Expand Down
46 changes: 46 additions & 0 deletions packages/runtime-logger/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<p align="center">
<img alt="InoxTools" width="350px" src="https://github.com/Fryuni/inox-tools/blob/main/assets/shield.png?raw=true"/>
</p>

# Runtime Logger

Expose Astro Integration Logger at runtime for consistent output

## Install

```js
npm i @inox-tools/runtime-logger
```

## Using the integration

To enable this, you need to register your integration to have a runtime logger under some name:

```ts
import { runtimeLogger } from '@inox-tools/runtime-logger';

export default () => ({
name: 'your-integration',
hooks: {
'astro:config:setup': (params) => {
runtimeLogger(params, {
name: 'your-integration',
});
},
},
});
```

With that in place, your runtime code can now access the logger by importing the generated module `@it-astro:logger:<name>`:

```astro
---
import { logger } from '@it-astro:logger:your-integration';

logger.info('Hello World!');
---
```

## License

Astro Runtime Logger is available under the MIT license.
3 changes: 3 additions & 0 deletions packages/runtime-logger/npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
*.log
src
49 changes: 49 additions & 0 deletions packages/runtime-logger/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"name": "@inox-tools/runtime-logger",
"version": "0.0.0",
"description": "Expose Astro Integration Logger at runtime for consistent output",
"keywords": [
"astro-integration",
"withastro",
"astro"
],
"license": "MIT",
"author": "Luiz Ferraz <[email protected]>",
"type": "module",
"exports": {
".": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
},
"files": [
"dist",
"src",
"virtual.d.ts"
],
"scripts": {
"build": "tsup",
"dev": "tsup --watch",
"prepublish": "pnpm run build",
"test": "echo 'No tests'"
},
"dependencies": {
"astro-integration-kit": "^0.14",
"@inox-tools/utils": "workspace:^",
"@inox-tools/modular-station": "workspace:^"
},
"devDependencies": {
"@types/node": "^20",
"@vitest/coverage-v8": "^1",
"@vitest/ui": "^1",
"jest-extended": "^4",
"astro": "^4",
"tsup": "^8",
"typescript": "^5",
"vite": "^5",
"vitest": "^1"
},
"peerDependencies": {
"astro": "^4"
}
}
45 changes: 45 additions & 0 deletions packages/runtime-logger/src/buildLoggerPlugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import type { Plugin } from 'vite';
import type { AstroIntegrationLogger } from 'astro';
import { INTERNAL_MODULE } from './internalPlugin.js';

const MODULE_PREFIX = '@it-astro:logger:';
const RESOLVED_MODULE_PREFIX = '\x00@it-astro:logger:';

const pluginName = '@inox-tools/runtime-logger/dev';

export const buildLoggerPlugin = (loggers: Map<string, AstroIntegrationLogger>): Plugin => {
(globalThis as any)[Symbol.for(pluginName)] = loggers;

return {
name: pluginName,
resolveId(id) {
if (id.startsWith(MODULE_PREFIX)) {
const loggerName = id.slice(MODULE_PREFIX.length);
if (loggers.has(loggerName)) {
return `${RESOLVED_MODULE_PREFIX}${loggerName}`;
}
}
return null;
},
load(id) {
if (!id.startsWith(RESOLVED_MODULE_PREFIX)) return;
const loggerName = id.slice(RESOLVED_MODULE_PREFIX.length);
const logger = loggers.get(loggerName)!;
if (logger === undefined) return;

return `
import { baseLogger } from '${INTERNAL_MODULE}';
florian-lefebvre marked this conversation as resolved.
Show resolved Hide resolved

const buildLogger = globalThis[Symbol.for('${pluginName}')]?.get('${loggerName}');

const logger = buildLogger ?? baseLogger.fork('${logger.label}');

if (buildLogger === undefined) {
logger.options.level = '${logger.options.level}';
}

export { logger };
`;
},
};
};
37 changes: 37 additions & 0 deletions packages/runtime-logger/src/devLoggerPlugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import type { Plugin } from 'vite';
import type { AstroIntegrationLogger } from 'astro';

const MODULE_PREFIX = '@it-astro:logger:';
const RESOLVED_MODULE_PREFIX = '\x00@it-astro:logger:';

const pluginName = '@inox-tools/runtime-logger/dev';

export const devLoggerPlugin = (loggers: Map<string, AstroIntegrationLogger>): Plugin => {
(globalThis as any)[Symbol.for(pluginName)] = loggers;

return {
name: pluginName,
resolveId(id) {
if (id.startsWith(MODULE_PREFIX)) {
const loggerName = id.slice(MODULE_PREFIX.length);
if (loggers.has(loggerName)) {
return `${RESOLVED_MODULE_PREFIX}${loggerName}`;
}
}
return null;
},
load(id) {
if (!id.startsWith(RESOLVED_MODULE_PREFIX)) return;
const loggerName = id.slice(RESOLVED_MODULE_PREFIX.length);
if (!loggers.has(loggerName)) return;

return `
console.log(Symbol.for('${pluginName}'));
Fryuni marked this conversation as resolved.
Show resolved Hide resolved

const logger = globalThis[Symbol.for('${pluginName}')].get('${loggerName}');

export { logger };
`;
},
};
};
55 changes: 55 additions & 0 deletions packages/runtime-logger/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { withApi } from '@inox-tools/modular-station';
import { addVitePlugin, defineUtility, type HookParameters } from 'astro-integration-kit';
import { z } from 'astro/zod';
import { buildLoggerPlugin } from './buildLoggerPlugin.js';
import { loggerInternalsPlugin } from './internalPlugin.js';
import { devLoggerPlugin } from './devLoggerPlugin.js';
import type { AstroIntegrationLogger } from 'astro';

const schema = z
.object({
name: z.string(),
})
.strict();

const integration = withApi(() => {
const loggers = new Map<string, AstroIntegrationLogger>();

return {
name: '@inox-tools/runtime-logger',
hooks: {
'astro:config:setup': (params) => {
switch (params.command) {
case 'build': {
addVitePlugin(params, {
plugin: loggerInternalsPlugin,
warnDuplicated: true,
});
addVitePlugin(params, {
plugin: buildLoggerPlugin(loggers),
warnDuplicated: true,
});
}
case 'dev': {
addVitePlugin(params, {
plugin: devLoggerPlugin(loggers),
warnDuplicated: true,
});
}
}
},
},
addLogger(name: string, logger: AstroIntegrationLogger) {
loggers.set(name, logger);
},
};
});

export const runtimeLogger = defineUtility('astro:config:setup')((
params: HookParameters<'astro:config:setup'>,
options: z.infer<typeof schema>
) => {
const api = integration.fromSetup(params);

api.addLogger(options.name, params.logger);
});
Loading
Loading