estruyf / vscode-front-matter

Front Matter is a CMS running straight in Visual Studio Code. Can be used with static site generators like Hugo, Jekyll, Hexo, NextJs, Gatsby, and many more...
https://frontmatter.codes
MIT License
2.02k stars 83 forks source link

Issue: No Astro Content Collections found on new astro project with blog template #703

Closed T3sT3ro closed 1 year ago

T3sT3ro commented 1 year ago

Describe the bug I expected frontmatter to generate appropriate content types from astro's content collections, but during frontmatter initialization no content collections are found.

To Reproduce Steps to reproduce the behavior:

  1. create new astro project with blog template
  2. open in vscode
  3. try to initialize with frontmatter
  4. See "No astro collections found" on the "CREATE CONTENT-TYPES FOR YOUR ASTRO CONTENT COLLECTIONS" step

Expected behavior Content collections should be found, content types generated and new posts should be created with proper fields in the frontmatter.

Desktop (please complete the following information):

Additional context I made sure that content types were generated by running astro sync

estruyf commented 1 year ago

Thanks, @T3sT3ro, for opening this issue. FM retrieves the content collections by executing a script on the Astro project. Normally it should output the error in the VSCode output under the Front Matter CMS category.

Would you be able to check that in order to know what is happening?

T3sT3ro commented 1 year ago

Here is the log from that window after removing .frontmatter dir, it's config, restarting vscode and trying to initialize frontmatter anew and selecting astro as framework.

["INFO" - 12:11:23]  No ".frontmatter/config" config files found.
["INFO" - 12:11:23]  Trigger page update: main
["INFO" - 12:11:25]  Receiving message from webview to panel: get-data
["INFO" - 12:11:25]  Sending message to panel: folderInfo
["INFO" - 12:11:25]  Receiving message from webview to panel: get-mode
["INFO" - 12:11:25]  Receiving message from webview to panel: getLocalization
["INFO" - 12:11:25]  Sending message to panel: settings
["INFO" - 12:11:26]  Sending message to panel: setLocalization
["INFO" - 12:11:26]  Receiving message from webview to panel: is-server-started
["INFO" - 12:11:26]  Sending request result to panel: is-server-started
["INFO" - 12:11:28]  Receiving message from webview to panel: open-dashboard
["INFO" - 12:11:28]  Trigger page update: onDidChangeActiveTextEditor
["INFO" - 12:11:28]  Receiving message from webview: getViewType
["INFO" - 12:11:28]  Sending message to dashboard: viewData
["INFO" - 12:11:28]  Receiving message from webview: getTheme
["INFO" - 12:11:28]  Receiving message from webview: getData
["INFO" - 12:11:28]  Sending message to dashboard: settings
["INFO" - 12:11:28]  Receiving message from webview: getMode
["INFO" - 12:11:28]  Receiving message from webview: getLocalization
["INFO" - 12:11:28]  Sending message to dashboard: setLocalization
["INFO" - 12:11:28]  Sending message to dashboard: pages
["INFO" - 12:11:28]  Sending message to dashboard: pages
["INFO" - 12:11:28]  Sending message to dashboard: searchReady
["INFO" - 12:11:28]  Sending message to dashboard: loading
["INFO" - 12:11:28]  Receiving message from webview: sendTelemetry
["INFO" - 12:11:29]  Sending message to panel: metadata
["INFO" - 12:11:29]  Receiving message from webview to panel: is-server-started
["INFO" - 12:11:29]  Sending request result to panel: is-server-started
["INFO" - 12:11:39]  Trigger page update: onDidChangeActiveTextEditor
["INFO" - 12:11:39]  Sending message to panel: mediaSelectionData
["INFO" - 12:11:41]  Trigger page update: onDidChangeActiveTextEditor
["INFO" - 12:11:44]  Sending message to panel: mediaSelectionData
["INFO" - 12:11:44]  Trigger page update: onDidChangeActiveTextEditor
["INFO" - 12:11:44]  Receiving message from webview to panel: is-server-started
["INFO" - 12:11:44]  Sending request result to panel: is-server-started
["INFO" - 12:11:45]  Sending message to panel: metadata
["INFO" - 12:11:46]  Receiving message from webview to panel: open-dashboard
["INFO" - 12:11:46]  Trigger page update: onDidChangeActiveTextEditor
["INFO" - 12:11:46]  Receiving message from webview: getViewType
["INFO" - 12:11:46]  Sending message to dashboard: viewData
["INFO" - 12:11:46]  Receiving message from webview: getTheme
["INFO" - 12:11:46]  Receiving message from webview: getData
["INFO" - 12:11:46]  Sending message to dashboard: settings
["INFO" - 12:11:46]  Receiving message from webview: getMode
["INFO" - 12:11:46]  Receiving message from webview: getLocalization
["INFO" - 12:11:46]  Sending message to dashboard: setLocalization
["INFO" - 12:11:46]  Sending message to dashboard: pages
["INFO" - 12:11:46]  Sending message to dashboard: pages
["INFO" - 12:11:46]  Sending message to dashboard: searchReady
["INFO" - 12:11:46]  Sending message to dashboard: loading
["INFO" - 12:11:46]  Receiving message from webview: sendTelemetry
["INFO" - 12:11:47]  Sending message to panel: metadata
["INFO" - 12:11:47]  Receiving message from webview to panel: is-server-started
["INFO" - 12:11:47]  Sending request result to panel: is-server-started
["INFO" - 12:11:51]  Receiving message from webview: setFramework
["INFO" - 12:11:51]  Config change detected - /home/tooster/workspace/ttr/T3sT3ro.github.io/frontmatter.json changed
["INFO" - 12:11:51]  No ".frontmatter/config" config files found.
["INFO" - 12:11:51]  Triggering listener: settings-init
["INFO" - 12:11:51]  Triggering listener: settings-global
["INFO" - 12:11:51]  Triggering listener: panel-listener
["INFO" - 12:11:51]  Triggering listener: dashboard-listener
["INFO" - 12:11:51]  Sending message to panel: folderInfo
["INFO" - 12:11:51]  Config change detected - /home/tooster/workspace/ttr/T3sT3ro.github.io/frontmatter.json changed
["INFO" - 12:11:51]  No ".frontmatter/config" config files found.
["INFO" - 12:11:51]  Sending message to panel: settings
["INFO" - 12:11:51]  Triggering listener: settings-init
["INFO" - 12:11:51]  Triggering listener: settings-global
["INFO" - 12:11:51]  Triggering listener: panel-listener
["INFO" - 12:11:51]  Triggering listener: dashboard-listener
["INFO" - 12:11:51]  Sending message to panel: folderInfo
["INFO" - 12:11:51]  Sending message to panel: settings
["INFO" - 12:11:54]  Sending message to dashboard: settings
["INFO" - 12:11:54]  Receiving message from webview: ssgGetAstroContentTypes
["INFO" - 12:11:54]  Sending message to dashboard: settings
["INFO" - 12:11:54]  Sending message to dashboard: settings
["INFO" - 12:11:54]  Executing script: node "/home/tooster/workspace/ttr/T3sT3ro.github.io/.frontmatter/temp/astro.collections.mjs" "/home/tooster/workspace/ttr/T3sT3ro.github.io/src/content/config.ts"
["ERROR" - 12:11:54]  Command failed: node "/home/tooster/workspace/ttr/T3sT3ro.github.io/.frontmatter/temp/astro.collections.mjs" "/home/tooster/workspace/ttr/T3sT3ro.github.io/src/content/config.ts"
node:internal/errors:497
    ErrorCaptureStackTrace(err);
    ^

Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'vite' imported from /home/tooster/workspace/ttr/T3sT3ro.github.io/.frontmatter/temp/astro.collections.mjs
    at new NodeError (node:internal/errors:406:5)
    at packageResolve (node:internal/modules/esm/resolve:789:9)
    at moduleResolve (node:internal/modules/esm/resolve:838:20)
    at defaultResolve (node:internal/modules/esm/resolve:1043:11)
    at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:383:12)
    at ModuleLoader.resolve (node:internal/modules/esm/loader:352:25)
    at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:228:38)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:85:39)
    at link (node:internal/modules/esm/module_job:84:36) {
  code: 'ERR_MODULE_NOT_FOUND'
}

Node.js v20.8.0

["INFO" - 12:11:01]  Triggering listener: settings-init
["INFO" - 12:11:01]  Triggering listener: settings-global
["INFO" - 12:11:01]  Triggering listener: panel-listener
["INFO" - 12:11:01]  Triggering listener: dashboard-listener
["INFO" - 12:11:01]  Sending message to panel: folderInfo
["INFO" - 12:11:01]  Sending message to panel: settings
["INFO" - 12:11:03]  Trigger page update: onDidChangeTextEditorSelection
["INFO" - 12:11:03]  Sending message to dashboard: settings
["INFO" - 12:11:04]  Trigger page update: onDidChangeActiveTextEditor
["ERROR" - 12:11:05]  DataListener::pushMetadata: cannot open file:///extension-output-eliostruyf.vscode-front-matter-%231-Front%20Matter%20CMS. Detail: Unable to read file '/extension-output-eliostruyf.vscode-front-matter-#1-Front Matter CMS' (Error: Unable to resolve nonexistent file '/extension-output-eliostruyf.vscode-front-matter-#1-Front Matter CMS')
["INFO" - 12:11:05]  Sending message to panel: metadata
["INFO" - 12:11:05]  Receiving message from webview to panel: is-server-started
["INFO" - 12:11:05]  Sending request result to panel: is-server-started
["INFO" - 12:11:08]  Trigger page update: onDidChangeTextEditorSelection
["ERROR" - 12:11:09]  DataListener::pushMetadata: cannot open file:///extension-output-eliostruyf.vscode-front-matter-%231-Front%20Matter%20CMS. Detail: Unable to read file '/extension-output-eliostruyf.vscode-front-matter-#1-Front Matter CMS' (Error: Unable to resolve nonexistent file '/extension-output-eliostruyf.vscode-front-matter-#1-Front Matter CMS')
["INFO" - 12:11:09]  Sending message to panel: metadata
T3sT3ro commented 1 year ago

this is the dashboard view after initialization: image

I guess step 4 should be populated with detected content types.

estruyf commented 1 year ago

Did you install the dependencies in your project?

In the output, I can see Vite cannot be found. I'm guessing this is because of the project is missing the dependencies. The script which retrieves these Astro Collections is using Astro it's project dependencies.

T3sT3ro commented 1 year ago

I didn't install vite separately, because I assume it's not needed. Astro works on top of vite and it works out of the box, it prints vite:something logs, so I assume it's working and is there, somewhere. Inside my node_modules (btw I use pnpm if it's important) I can see:

Based on that I think I have a hunch that it might be something that has to do with pnpm and that the current support in frontmatter makes assumptions about either the node_modules, package manager used or some structure. If I am correct, it may turn out that it also doesn't behave like it should under other package managers.

Maybe a good way to integrate with astro would be using their Integrations API instead?

estruyf commented 1 year ago

Indeed, it might be a pnpm thingy, which I will have to figure out how to fix. The reason why it uses a script to run in the current project, is because it doesn't require front matter to package extra dependencies into the extension.

Thank you so much for looking into it and providing all details! This helps a lot.

estruyf commented 1 year ago

It has indeed to do with pnpm.

The script imports dependencies as follows:

import { writeFileSync } from "fs";
import { join } from "path";
import { createServer } from "vite";
import zod from "zod";

but for pnpm, it needs to be updated to:

import { writeFileSync } from "fs";
import { join } from "path";
import { createServer } from "./node_modules/.pnpm/vite@4.5.0/node_modules/vite/dist/node/index.js";
import zod from "./node_modules/.pnpm/zod@3.22.4/node_modules/zod/lib/index.js";

Think we need to include a check to see if pnpm is used, and when it is, the dependency references need to be updated accordingly.

estruyf commented 1 year ago

For zod we can use import zod from "astro/zod"; instead of the direct zod reference. Which would allows us to focus on vite alone.

T3sT3ro commented 1 year ago

just to remind, that if there are pnpm problems there might also be some problems with yarn (although their packaging model is similar npm so maybe not) and turbo, if someone is using it.

Have you looked into https://docs.astro.build/en/reference/integrations-reference/ and considered maybe creating a lightweight integration in another repo that handles everything to do with astro?

estruyf commented 1 year ago

I have seen that integration with Astro indeed, but that would probably require more work 🧐

estruyf commented 1 year ago

Got it working on my machine with pnpm, will push out a new beta version for you to test it out.

Screenshot 2023-11-09 at 14 12 56

estruyf commented 1 year ago

Fix is included in beta version: 9.4.6818057. Feel free to give it a try.

estruyf commented 1 year ago

Verified a project with yarn and it works fine as it behaves like npm.

T3sT3ro commented 1 year ago

Nice, it's detecting content correctly. It doesn't generate appropriate types in some cases though. Below is zod configuration and resulting content types generated:

zod and resulting config type ```ts const blogCollection = defineCollection({ // Type-check frontmatter using a schema schema: z.object({ title: z.string(), description: z.string(), heroImage: z.string().optional(), tags: z.array(z.string()).optional(), categories: z.array(z.string()).optional(), draft: z.boolean().optional().default(true), published: z .string().datetime({offset: true}) .or(z.date()) // Transform string to Date object .transform((val) => new Date(val)), modified: z .string().datetime({offset: true}) .or(z.date()) .optional() .transform((val) => (val ? new Date(val) : undefined)), }) }); ``` Result content types: ```json "frontMatter.taxonomy.contentTypes": [ { "name": "default", "pageBundle": false, "previewPath": null, "fields": [ { "title": "Title", "name": "title", "type": "string" }, { "title": "Description", "name": "description", "type": "string" }, { "title": "Publishing date", "name": "date", "type": "datetime", "default": "{{now}}", "isPublishDate": true }, { "title": "Content preview", "name": "preview", "type": "image" }, { "title": "Is in draft", "name": "draft", "type": "draft" }, { "title": "Tags", "name": "tags", "type": "tags" }, { "title": "Categories", "name": "categories", "type": "categories" } ] }, { "name": "blog", "previewPath": "'blog'", "pageBundle": false, "clearEmpty": true, "fields": [ { "name": "title", "type": "string", "single": true, "required": true }, { "name": "description", "type": "string", "single": true, "required": true }, { "name": "heroImage", "type": "string", "single": true, "required": true, "default": true }, { "name": "tags", "type": "list", "required": true, "default": true }, { "name": "categories", "type": "list", "required": true, "default": true }, { "name": "draft", "type": "boolean", "required": true, "default": true } ] } ] ```

In words:

Aside from that I would also think about the UX of the "use template" and "detect content" steps because using "blog template" — which looks like a required step — finalizes the whole configuration and opens the dashboard. I clicked it the first time thinking it would just append some defaults to configs and let me proceed with initialization, but it basically finished everything on it's own. Maybe make it the "step 0" where those buttons are on the very top.

Not sure if above comments belong to this thread or should be moved to separate issues though.

estruyf commented 1 year ago

@T3sT3ro, thanks for those insights. Created a new issue with your comments to have a separate thread.

T3sT3ro commented 1 year ago

Nice, in that case the original issue seems to be resolved.