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(next): codegenDir and update .astro paths #11963

Merged
merged 22 commits into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
a60023e
feat: update paths
florian-lefebvre Sep 10, 2024
a28f00e
chore: changeset
florian-lefebvre Sep 10, 2024
74174b4
fix: tests
florian-lefebvre Sep 10, 2024
eb0c144
Update test-utils.js
florian-lefebvre Sep 10, 2024
a2616d8
Merge branch 'next' into feat/dotastro-move
florian-lefebvre Sep 11, 2024
540d2a9
Discard changes to packages/astro/test/units/dev/restart.test.js
florian-lefebvre Sep 18, 2024
e963c87
Discard changes to packages/astro/test/test-utils.js
florian-lefebvre Sep 18, 2024
7438ef7
Discard changes to packages/astro/test/data-collections-schema.test.js
florian-lefebvre Sep 18, 2024
575a774
Discard changes to packages/astro/test/content-layer.test.js
florian-lefebvre Sep 18, 2024
7de2901
Discard changes to packages/astro/test/content-intellisense.test.js
florian-lefebvre Sep 18, 2024
37b064b
Merge branch 'next' into feat/dotastro-move
florian-lefebvre Sep 18, 2024
186aa60
chore: remove changeset
florian-lefebvre Sep 18, 2024
9109991
feat: adjust
florian-lefebvre Sep 18, 2024
92bdac7
feat: move dts to root
florian-lefebvre Sep 18, 2024
a850394
chore: remove duplicate folder creation
florian-lefebvre Sep 18, 2024
091dbe5
feat: fix test and add codegenDir
florian-lefebvre Sep 18, 2024
3edbe68
chore: changeset
florian-lefebvre Sep 18, 2024
0c30ceb
Update three-olives-reflect.md
florian-lefebvre Sep 18, 2024
46fd026
feat: createCodegenDir
florian-lefebvre Sep 23, 2024
d077e47
Merge branch 'next' into feat/dotastro-move
florian-lefebvre Sep 23, 2024
635abe3
Update .changeset/three-olives-reflect.md
florian-lefebvre Sep 23, 2024
1400894
Apply suggestions from code review
florian-lefebvre Sep 24, 2024
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
25 changes: 25 additions & 0 deletions .changeset/three-olives-reflect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
'astro': minor
---

Adds a new `createCodegenDir()` function to the `astro:config:setup` hook in the Integrations API

In 4.14, we introduced the `injectTypes` utility on the `astro:config:done` hook. It can create `.d.ts` files and make their types available to user's projects automatically. Under the hood, it creates a file in `<root>/.astro/integrations/<normalized_integration_name>`.

While the `.astro` directory has always been the preferred place to write code generated files, it has also been prone to mistakes. For example, you can write a `.astro/types.d.ts` file, breaking Astro types. Or you can create a file that overrides a file created by another integration.

In this release, `<root>/.astro/integrations/<normalized_integration_name>` can now be retrieved in the `astro:config:setup` hook by calling `createCodegenDir()`. It allows you to have a dedicated folder, avoiding conflicts with another integration or Astro itself. This directory is created by calling this function so it's safe to write files to it directly:

```js
import { writeFileSync } from 'node:fs'

const integration = {
name: 'my-integration',
hooks: {
'astro:config:setup': ({ createCodegenDir }) => {
const codegenDir = createCodegenDir()
writeFileSync(new URL('cache.json', codegenDir), '{}', 'utf-8')
}
}
}
```
2 changes: 1 addition & 1 deletion packages/astro/src/actions/consts.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export const VIRTUAL_MODULE_ID = 'astro:actions';
export const RESOLVED_VIRTUAL_MODULE_ID = '\0' + VIRTUAL_MODULE_ID;
export const ACTIONS_TYPES_FILE = 'astro/actions.d.ts';
export const ACTIONS_TYPES_FILE = 'actions.d.ts';
export const VIRTUAL_INTERNAL_MODULE_ID = 'astro:internal-actions';
export const RESOLVED_VIRTUAL_INTERNAL_MODULE_ID = '\0astro:internal-actions';
export const NOOP_ACTIONS = '\0noop-actions';
Expand Down
9 changes: 5 additions & 4 deletions packages/astro/src/content/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@ export const CONTENT_FLAGS = [
CONTENT_MODULE_FLAG,
] as const;

export const CONTENT_TYPES_FILE = 'astro/content.d.ts';

export const CONTENT_TYPES_FILE = 'content.d.ts';
export const DATA_STORE_FILE = 'data-store.json';
export const ASSET_IMPORTS_FILE = 'assets.mjs';
export const MODULES_IMPORTS_FILE = 'modules.mjs';
export const ASSET_IMPORTS_FILE = 'content-assets.mjs';
export const MODULES_IMPORTS_FILE = 'content-modules.mjs';
export const COLLECTIONS_MANIFEST_FILE = 'collections/collections.json';
export const COLLECTIONS_DIR = 'collections/'

export const CONTENT_LAYER_TYPE = 'content_layer';
11 changes: 4 additions & 7 deletions packages/astro/src/content/content-layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type { AstroSettings } from '../types/astro.js';
import type { ContentEntryType, RefreshContentOptions } from '../types/public/content.js';
import {
ASSET_IMPORTS_FILE,
COLLECTIONS_MANIFEST_FILE,
CONTENT_LAYER_TYPE,
DATA_STORE_FILE,
MODULES_IMPORTS_FILE,
Expand Down Expand Up @@ -214,14 +215,10 @@ export class ContentLayer {
return collection.loader.load(context);
}),
);
if (!existsSync(this.#settings.config.cacheDir)) {
await fs.mkdir(this.#settings.config.cacheDir, { recursive: true });
}
await fs.mkdir(this.#settings.config.cacheDir, { recursive: true });
await fs.mkdir(this.#settings.dotAstroDir, { recursive: true });
const cacheFile = getDataStoreFile(this.#settings);
await this.#store.writeToDisk(cacheFile);
if (!existsSync(this.#settings.dotAstroDir)) {
await fs.mkdir(this.#settings.dotAstroDir, { recursive: true });
}
const assetImportsFile = new URL(ASSET_IMPORTS_FILE, this.#settings.dotAstroDir);
await this.#store.writeAssetImports(assetImportsFile);
const modulesImportsFile = new URL(MODULES_IMPORTS_FILE, this.#settings.dotAstroDir);
Expand All @@ -233,7 +230,7 @@ export class ContentLayer {
}

async regenerateCollectionFileManifest() {
const collectionsManifest = new URL('collections/collections.json', this.#settings.dotAstroDir);
const collectionsManifest = new URL(COLLECTIONS_MANIFEST_FILE, this.#settings.dotAstroDir);
this.#logger.debug('content', 'Regenerating collection file manifest');
if (existsSync(collectionsManifest)) {
try {
Expand Down
27 changes: 14 additions & 13 deletions packages/astro/src/content/types-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@ import type { Logger } from '../core/logger/core.js';
import { isRelativePath } from '../core/path.js';
import type { AstroSettings } from '../types/astro.js';
import type { ContentEntryType } from '../types/public/content.js';
import { CONTENT_LAYER_TYPE, CONTENT_TYPES_FILE, VIRTUAL_MODULE_ID } from './consts.js';
import {
COLLECTIONS_DIR,
CONTENT_LAYER_TYPE,
CONTENT_TYPES_FILE,
VIRTUAL_MODULE_ID,
} from './consts.js';
import {
type CollectionConfig,
type ContentConfig,
Expand Down Expand Up @@ -428,10 +433,8 @@ async function writeContentFiles({
let contentTypesStr = '';
let dataTypesStr = '';

const collectionSchemasDir = new URL('./collections/', settings.dotAstroDir);
if (!fs.existsSync(collectionSchemasDir)) {
fs.mkdirSync(collectionSchemasDir, { recursive: true });
}
const collectionSchemasDir = new URL(COLLECTIONS_DIR, settings.dotAstroDir);
fs.mkdirSync(collectionSchemasDir, { recursive: true });

for (const [collection, config] of Object.entries(contentConfig?.collections ?? {})) {
collectionEntryMap[JSON.stringify(collection)] ??= {
Expand Down Expand Up @@ -568,12 +571,8 @@ async function writeContentFiles({
);
}

if (!fs.existsSync(settings.dotAstroDir)) {
fs.mkdirSync(settings.dotAstroDir, { recursive: true });
}

const configPathRelativeToCacheDir = normalizeConfigPath(
new URL('astro', settings.dotAstroDir).pathname,
settings.dotAstroDir.pathname,
contentPaths.config.url.pathname,
);

Expand All @@ -591,9 +590,11 @@ async function writeContentFiles({

// If it's the first time, we inject types the usual way. sync() will handle creating files and references. If it's not the first time, we just override the dts content
if (settings.injectedTypes.some((t) => t.filename === CONTENT_TYPES_FILE)) {
const filePath = fileURLToPath(new URL(CONTENT_TYPES_FILE, settings.dotAstroDir));
await fs.promises.mkdir(path.dirname(filePath), { recursive: true });
await fs.promises.writeFile(filePath, typeTemplateContent, 'utf-8');
await fs.promises.writeFile(
new URL(CONTENT_TYPES_FILE, settings.dotAstroDir),
typeTemplateContent,
'utf-8',
);
} else {
settings.injectedTypes.push({
filename: CONTENT_TYPES_FILE,
Expand Down
3 changes: 2 additions & 1 deletion packages/astro/src/core/dev/restart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { createSafeError } from '../errors/index.js';
import { formatErrorMessage } from '../messages.js';
import type { Container } from './container.js';
import { createContainer, startContainer } from './container.js';
import { SETTINGS_FILE } from '../../preferences/constants.js';

async function createRestartedContainer(
container: Container,
Expand Down Expand Up @@ -50,7 +51,7 @@ function shouldRestartContainer(
else {
shouldRestart = configRE.test(normalizedChangedFile);
const settingsPath = vite.normalizePath(
fileURLToPath(new URL('settings.json', settings.dotAstroDir)),
fileURLToPath(new URL(SETTINGS_FILE, settings.dotAstroDir)),
);
if (settingsPath.endsWith(normalizedChangedFile)) {
shouldRestart = settings.preferences.ignoreNextPreferenceReload ? false : true;
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/env/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export const VIRTUAL_MODULES_IDS = {
};
export const VIRTUAL_MODULES_IDS_VALUES = new Set(Object.values(VIRTUAL_MODULES_IDS));

export const ENV_TYPES_FILE = 'astro/env.d.ts';
export const ENV_TYPES_FILE = 'env.d.ts';

const PKG_BASE = new URL('../../', import.meta.url);
export const MODULE_TEMPLATE_URL = new URL('templates/env.mjs', PKG_BASE);
11 changes: 10 additions & 1 deletion packages/astro/src/integrations/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,13 +112,17 @@ export function getToolbarServerCommunicationHelpers(server: ViteDevServer) {
// Will match any invalid characters (will be converted to _). We only allow a-zA-Z0-9.-_
const SAFE_CHARS_RE = /[^\w.-]/g;

export function normalizeCodegenDir(integrationName: string): string {
return `./integrations/${integrationName.replace(SAFE_CHARS_RE, '_')}/`;
}

export function normalizeInjectedTypeFilename(filename: string, integrationName: string): string {
if (!filename.endsWith('.d.ts')) {
throw new Error(
`Integration ${bold(integrationName)} is injecting a type that does not end with "${bold('.d.ts')}"`,
);
}
return `./integrations/${integrationName.replace(SAFE_CHARS_RE, '_')}/${filename.replace(SAFE_CHARS_RE, '_')}`;
return `${normalizeCodegenDir(integrationName)}${filename.replace(SAFE_CHARS_RE, '_')}`;
}

export async function runHookConfigSetup({
Expand Down Expand Up @@ -234,6 +238,11 @@ export async function runHookConfigSetup({
);
updatedSettings.middlewares[order].push(entrypoint);
},
createCodegenDir: () => {
const codegenDir = new URL(normalizeCodegenDir(integration.name), settings.dotAstroDir);
fs.mkdirSync(codegenDir, { recursive: true });
return codegenDir;
},
logger: integrationLogger,
};

Expand Down
1 change: 1 addition & 0 deletions packages/astro/src/preferences/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const SETTINGS_FILE = 'settings.json';
3 changes: 2 additions & 1 deletion packages/astro/src/preferences/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ import fs from 'node:fs';
import path from 'node:path';
import dget from 'dlv';
import { dset } from 'dset';
import { SETTINGS_FILE } from './constants.js';

export class PreferenceStore {
private file: string;

constructor(
private dir: string,
filename = 'settings.json',
filename = SETTINGS_FILE,
) {
this.file = path.join(this.dir, filename);
}
Expand Down
1 change: 1 addition & 0 deletions packages/astro/src/types/public/integrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ export interface BaseIntegrationHooks {
addClientDirective: (directive: ClientDirectiveConfig) => void;
addDevToolbarApp: (entrypoint: DevToolbarAppEntry) => void;
addMiddleware: (mid: AstroIntegrationMiddleware) => void;
createCodegenDir: () => URL;
logger: AstroIntegrationLogger;
}) => void | Promise<void>;
'astro:config:done': (options: {
Expand Down
26 changes: 13 additions & 13 deletions packages/astro/test/astro-sync.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,23 +123,23 @@ describe('astro sync', () => {
fixture.thenFileShouldExist('.astro/types.d.ts');
fixture.thenFileContentShouldInclude(
'.astro/types.d.ts',
`/// <reference path="astro/content.d.ts" />`,
`/// <reference path="content.d.ts" />`,
);
fixture.thenFileShouldExist('.astro/astro/content.d.ts');
fixture.thenFileShouldExist('.astro/content.d.ts');
fixture.thenFileContentShouldInclude(
'.astro/astro/content.d.ts',
'.astro/content.d.ts',
`declare module 'astro:content' {`,
'Types file does not include `astro:content` module declaration',
);
fixture.thenFileShouldBeValidTypescript('.astro/astro/content.d.ts');
fixture.thenFileShouldBeValidTypescript('.astro/content.d.ts');
});

it('Writes types for empty collections', async () => {
await fixture.load('./fixtures/content-collections-empty-dir/');
fixture.clean();
await fixture.whenSyncing();
fixture.thenFileContentShouldInclude(
'.astro/astro/content.d.ts',
'.astro/content.d.ts',
`"blog": Record<string, {
id: string;
slug: string;
Expand All @@ -151,7 +151,7 @@ describe('astro sync', () => {
'Types file does not include empty collection type',
);
fixture.thenFileContentShouldInclude(
'.astro/astro/content.d.ts',
'.astro/content.d.ts',
`"blogMeta": Record<string, {
id: string;
collection: "blogMeta";
Expand All @@ -170,11 +170,11 @@ describe('astro sync', () => {
fixture.thenFileShouldExist('.astro/types.d.ts');
fixture.thenFileContentShouldInclude(
'.astro/types.d.ts',
`/// <reference path="astro/env.d.ts" />`,
`/// <reference path="env.d.ts" />`,
);
fixture.thenFileShouldExist('.astro/astro/env.d.ts');
fixture.thenFileShouldExist('.astro/env.d.ts');
fixture.thenFileContentShouldInclude(
'.astro/astro/env.d.ts',
'.astro/env.d.ts',
`declare module 'astro:env/client' {`,
'Types file does not include `astro:env` module declaration',
);
Expand Down Expand Up @@ -210,15 +210,15 @@ describe('astro sync', () => {
fixture.thenFileShouldExist('.astro/types.d.ts');
fixture.thenFileContentShouldInclude(
'.astro/types.d.ts',
`/// <reference path="astro/actions.d.ts" />`,
`/// <reference path="actions.d.ts" />`,
);
fixture.thenFileShouldExist('.astro/astro/actions.d.ts');
fixture.thenFileShouldExist('.astro/actions.d.ts');
fixture.thenFileContentShouldInclude(
'.astro/astro/actions.d.ts',
'.astro/actions.d.ts',
`declare module "astro:actions" {`,
'Types file does not include `astro:actions` module declaration',
);
fixture.thenFileShouldBeValidTypescript('.astro/astro/actions.d.ts');
fixture.thenFileShouldBeValidTypescript('.astro/actions.d.ts');
});
});
});
8 changes: 8 additions & 0 deletions packages/astro/test/units/integrations/api.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as assert from 'node:assert/strict';
import { describe, it } from 'node:test';
import { validateSupportedFeatures } from '../../../dist/integrations/features-validation.js';
import {
normalizeCodegenDir,
normalizeInjectedTypeFilename,
runHookBuildSetup,
runHookConfigSetup,
Expand All @@ -12,6 +13,7 @@ const defaultConfig = {
root: new URL('./', import.meta.url),
srcDir: new URL('src/', import.meta.url),
};
const dotAstroDir = new URL('./.astro/', defaultConfig.root);

describe('Integration API', () => {
it('runHookBuildSetup should work', async () => {
Expand Down Expand Up @@ -87,6 +89,7 @@ describe('Integration API', () => {
},
],
},
dotAstroDir,
},
});
assert.equal(updatedSettings.config.site, site);
Expand Down Expand Up @@ -122,6 +125,7 @@ describe('Integration API', () => {
},
],
},
dotAstroDir,
},
});
assert.equal(updatedSettings.config.site, site);
Expand Down Expand Up @@ -270,3 +274,7 @@ describe('normalizeInjectedTypeFilename', () => {
'./integrations/aA1-_____./types.d.ts',
);
});

describe('normalizeCodegenDir', () => {
assert.equal(normalizeCodegenDir('aA1-*/_"~.'), './integrations/aA1-_____./');
});
Loading