): any
11 |
--------------------------------------------------------------------------------
/packages/contentful/astro-contentful.js:
--------------------------------------------------------------------------------
1 | export { contentfulIntegration as default } from './integrations/contentful-astro-integration.js'
2 |
3 | export * from './bundled/contentful.js'
4 |
--------------------------------------------------------------------------------
/packages/contentful/bundled/dotenv.js:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2015, Scott Motte
2 | // All rights reserved.
3 |
4 | // Redistribution and use in source and binary forms, with or without
5 | // modification, are permitted provided that the following conditions are met:
6 |
7 | // * Redistributions of source code must retain the above copyright notice, this
8 | // list of conditions and the following disclaimer.
9 |
10 | // * Redistributions in binary form must reproduce the above copyright notice,
11 | // this list of conditions and the following disclaimer in the documentation
12 | // and/or other materials provided with the distribution.
13 |
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 |
25 | const LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg
26 |
27 | // Parser src into an Object
28 | export function parseEnv (src) {
29 | const obj = {}
30 |
31 | // Convert buffer to string
32 | let lines = src.toString()
33 |
34 | // Convert line breaks to same format
35 | lines = lines.replace(/\r\n?/mg, '\n')
36 |
37 | let match
38 | while ((match = LINE.exec(lines)) != null) {
39 | const key = match[1]
40 |
41 | // Default undefined or null to empty string
42 | let value = (match[2] || '')
43 |
44 | // Remove whitespace
45 | value = value.trim()
46 |
47 | // Check if double quoted
48 | const maybeQuote = value[0]
49 |
50 | // Remove surrounding quotes
51 | value = value.replace(/^(['"`])([\s\S]*)\1$/mg, '$2')
52 |
53 | // Expand newlines if double quoted
54 | if (maybeQuote === '"') {
55 | value = value.replace(/\\n/g, '\n')
56 | value = value.replace(/\\r/g, '\r')
57 | }
58 |
59 | // Add to object
60 | obj[key] = value
61 | }
62 |
63 | return obj
64 | }
65 |
--------------------------------------------------------------------------------
/packages/contentful/global.d.ts:
--------------------------------------------------------------------------------
1 | declare namespace Contentful {
2 | interface Locales {
3 | sys: object,
4 | total: number,
5 | skip: number,
6 | limit: number,
7 | items: {
8 | name: string,
9 | internal_code: string,
10 | code: string,
11 | fallbackCode: unknown,
12 | default: boolean,
13 | contentManagementApi: boolean,
14 | contentDeliveryApi: boolean,
15 | optional: boolean,
16 | sys: object[]
17 | }[]
18 | }
19 |
20 | interface Sys {
21 | type: string
22 | linkType: string
23 | id: string
24 | }
25 |
26 | interface PlainTextField {
27 | [key: string]: string
28 | }
29 |
30 | interface RichTextField {
31 | nodeType: string
32 | data: {}
33 | content: {
34 | nodeType: string
35 | data: {}
36 | value: string
37 | marks: {
38 | type: string
39 | }[]
40 | }[]
41 | }
42 |
43 | interface Entry {
44 | metadata: {
45 | tags: []
46 | }
47 | sys: {
48 | space: {
49 | sys: Sys
50 | }
51 | id: string
52 | type: string
53 | createdAt: string
54 | updatedAt: string
55 | environment: {
56 | sys: Sys
57 | }
58 | publishedVersion: number
59 | publishedAt: string
60 | firstPublishedAt: string
61 | createdBy: {
62 | sys:Sys
63 | }
64 | updatedBy: {
65 | sys: Sys
66 | }
67 | publishedCounter: number
68 | version: number
69 | publishedBy: {
70 | sys: Sys
71 | }
72 | contentType: {
73 | sys: Sys
74 | }
75 | }
76 | fields: {
77 | [key: string]: PlainTextField | RichTextField
78 | }
79 | }
80 |
81 | interface EntryList {
82 | sys: {
83 | type: 'Array'
84 | }
85 | total: number
86 | skip: number
87 | limit: number
88 | items: Entry[]
89 | }
90 |
91 | interface EntryProps {
92 | of: string
93 | }
94 |
95 | interface EntryComponent {
96 | (props: EntryProps): any
97 |
98 | of(name: string): string | null
99 | }
100 |
101 | interface EntryListComponent {
102 | (props: EntryListProp
): any
103 |
104 | None(props: Record): any
105 | }
106 |
107 | type EntryListProp> = {
108 | [K in keyof T]: K extends 'children'
109 | ? {
110 | (entry: any): any
111 | }
112 | : T[K]
113 | } & {
114 | children?: {
115 | (item: typeof EntryComponent): any
116 | }
117 | }
118 |
119 | interface Fields {
120 | [name: string]: string | null
121 | }
122 |
123 | var EntryList: EntryList
124 | var Entry: Entry
125 | var EntryComponent: EntryComponent
126 | var EntryListComponent: EntryListComponent
127 | var Fields: Fields
128 | var Locales: Locales
129 | }
130 |
131 | // Entry
132 | // -----------------------------------------------------------------------------
133 |
134 | declare module '@astropub/contentful:entries/*!astro' {
135 | export type Props = Contentful.EntryProps
136 |
137 | export var Entry: Contentful.EntryComponent
138 | export var entry: Contentful.Entry
139 |
140 | export default Contentful.EntryComponent
141 | }
142 |
143 | declare module '@astropub/contentful:entries/*' {
144 | export type Props = Contentful.EntryProps
145 |
146 | export var Entry: Contentful.EntryComponent
147 | export var entry: Contentful.Entry
148 |
149 | export default Contentful.Entry
150 | }
151 |
152 | // EntryList
153 | // -----------------------------------------------------------------------------
154 |
155 | declare module '@astropub/contentful:entries*!astro' {
156 | export type Props = Contentful.EntryProps
157 |
158 | export var EntryList: Contentful.EntryListComponent
159 | export var entryList: Contentful.Entry
160 |
161 | export default Contentful.EntryListComponent
162 | }
163 |
164 | declare module '@astropub/contentful:entries*' {
165 | export type Props = Contentful.EntryProps
166 |
167 | export var EntryList: Contentful.EntryListComponent
168 | export var entryList: Contentful.EntryList
169 |
170 | export default Contentful.EntryList
171 | }
172 |
173 | // -----------------------------------------------------------------------------
174 |
175 | declare module '@astropub/contentful:locales*' {
176 | export var locales: Contentful.Locales
177 |
178 | export default Contentful.Locales
179 | }
180 |
181 | declare module '@astropub/contentful:content_types/*' {
182 | const exports: any
183 |
184 | export default exports
185 | }
186 |
--------------------------------------------------------------------------------
/packages/contentful/integrations/contentful-astro-integration.d.ts:
--------------------------------------------------------------------------------
1 | import { AstroIntegration } from 'astro'
2 |
3 | export const contentfulIntegration: () => AstroIntegration
4 |
5 | /** Current working directory of the Node.js Process. ([reference](https://nodejs.org/api/process.html#processcwd)) */
6 | export type CurrentWorkingDirectory = string
7 |
8 | /** Environment variables. ([reference](https://en.wikipedia.org/wiki/Environment_variable)) */
9 | export interface EnvironmentVariables {
10 | [variable: string]: string
11 | }
12 |
13 | /** Mode the app is running in. ([reference](https://vitejs.dev/guide/env-and-mode.html#modes)) */
14 | export type Mode = string
15 |
16 | export interface Internals {
17 | /** Current working directory of the Node.js Process. ([reference](https://nodejs.org/api/process.html#processcwd)) */
18 | cwd: CurrentWorkingDirectory
19 |
20 | /** Environment variables. ([reference](https://en.wikipedia.org/wiki/Environment_variable)) */
21 | env: EnvironmentVariables
22 |
23 | /** Mode the app is running in. ([reference](https://vitejs.dev/guide/env-and-mode.html#modes)) */
24 | mode: Mode
25 | }
26 |
--------------------------------------------------------------------------------
/packages/contentful/integrations/contentful-astro-integration.js:
--------------------------------------------------------------------------------
1 | // @ts-check
2 |
3 | import { createMeta } from './createMeta.js'
4 | import { contentfulMiddleware } from './contentful-middleware.js'
5 | import { contentfulVite } from './contentful-vite-plugin.js'
6 |
7 | export const contentfulIntegration = (/** @type {AstroIntegrationOpts} */ opts = any) => {
8 | const meta = createMeta()
9 |
10 | /** @type {AstroIntegration} */
11 | const integration = {
12 | name: 'astro:contentful',
13 | hooks: {
14 | 'astro:config:setup'({ config, updateConfig }) {
15 | meta.update(config.root)
16 |
17 | updateConfig({
18 | vite: {
19 | plugins: [
20 | contentfulVite({ meta })
21 | ],
22 | }
23 | })
24 | },
25 | 'astro:config:done'({ config }) {
26 | meta.protocol = config.vite?.server?.https ? 'https:' : 'http:'
27 |
28 | meta.hostname = (
29 | typeof config.server.host === 'string'
30 | ? config.server.host
31 | : 'localhost'
32 | )
33 |
34 | meta.port = String(config.server.port || meta.port)
35 | },
36 | 'astro:server:setup'({ server }) {
37 | if (!meta.env.CONTENTFUL_ACCESS_TOKEN) {
38 | server.middlewares.use(contentfulMiddleware({ meta }))
39 | }
40 | },
41 | async 'astro:server:start'(options) {
42 | meta.port = String(options.address.port || meta.port)
43 | },
44 | },
45 | }
46 |
47 | return integration
48 | }
49 |
50 | const any = /** @type {any} */ (null)
51 |
52 | /** @typedef {ReturnType} Meta */
53 | /** @typedef {import('astro').AstroIntegration} AstroIntegration */
54 | /** @typedef {Partial} AstroIntegrationOpts */
55 | /** @typedef {import('vite').Plugin} VitePlugin */
56 | /** @typedef {import('./contentful-vite-plugin').ContentfulConfig} ContentfulConfig */
57 |
--------------------------------------------------------------------------------
/packages/contentful/integrations/contentful-middleware.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Astro Contentful
5 |
6 |
187 |
188 |
218 |
307 |
308 |
--------------------------------------------------------------------------------
/packages/contentful/integrations/contentful-middleware.js:
--------------------------------------------------------------------------------
1 | import * as fs from 'node:fs'
2 | import { parseEnv } from '../bundled/dotenv.js'
3 |
4 | export const contentfulMiddleware = (/** @type {{ meta: Meta }} */ { meta }) => {
5 | const middleware = /** @type {ContentfulMiddleware} */ ((req, res, next) => {
6 | const url = new URL(req.url, meta.origin)
7 |
8 | if (url.pathname === middlewareConfig.pathToHTML) {
9 | res.setHeader('Content-Type', 'text/html;charset=utf-8')
10 |
11 | return res.end(
12 | fs.readFileSync(pathToHtml, 'utf-8').replace(/\{\{([\w_]+)\}\}/g, ($0, $1) => {
13 | return (
14 | $1 in meta.env
15 | ? meta.env[$1]
16 | : $1 in middlewareConfig
17 | ? middlewareConfig[$1]
18 | : ''
19 | )
20 | })
21 | )
22 | }
23 |
24 | if (url.pathname === middlewareConfig.pathToJSON) {
25 | if (req.method == 'POST') {
26 | let body = '';
27 |
28 | req.on('data', function (data) {
29 | body += data
30 | })
31 |
32 | req.on('end', async () => {
33 | res.setHeader('Content-Type', 'application/json;charset=utf-8')
34 |
35 | try {
36 | const update = JSON.parse(body)
37 |
38 | if (update.token && update.space) {
39 | const checkURL = new URL(`https://api.contentful.com/spaces/${update.space}`)
40 | const checkReq = new Request(checkURL, {
41 | cache: 'no-cache',
42 | headers: {
43 | 'Accept': 'application/json',
44 | 'Authorization': 'Bearer ' + update.token,
45 | 'Accept-Encoding': 'gzip',
46 | 'User-Agent': 'node.js/',
47 | 'x-contentful-user-agent': 'sdk contentful-management.js/10.12.0;',
48 | },
49 | })
50 |
51 | res.setHeader('Content-Type', 'application/json;charset=utf-8')
52 |
53 | const checkRes = await fetch(checkReq)
54 | const checkJSO = await checkRes.json()
55 |
56 | if (checkJSO?.sys?.type === 'Space') {
57 | const envValu = {
58 | CONTENTFUL_SPACE: update.space,
59 | CONTENTFUL_ACCESS_TOKEN: update.token,
60 | CONTENTFUL_ENVIRONMENT: 'master',
61 | CONTENTFUL_LOCALE: 'en-US',
62 | }
63 | const envPath = new URL('.env.local', meta.cwd)
64 |
65 | touchFileSync(envPath)
66 |
67 | const envOpts = parseEnv(fs.readFileSync(envPath))
68 |
69 | envOpts.CONTENTFUL_SPACE = update.space
70 | envOpts.CONTENTFUL_ACCESS_TOKEN = update.token
71 | envOpts.CONTENTFUL_ENVIRONMENT = 'master'
72 | envOpts.CONTENTFUL_LOCALE = 'en-US'
73 |
74 | const envText = Object.entries(envOpts).reduce(
75 | (all, [ name, data ]) => all.concat(
76 | `${name}=${
77 | /\s/.test(data)
78 | ? JSON.stringify(data)
79 | : data
80 | }`
81 | ),
82 | []
83 | ).join('\n')
84 |
85 | fs.writeFileSync(envPath, envText)
86 |
87 | Object.assign(meta.env, envValu)
88 |
89 | res.end(JSON.stringify(checkJSO))
90 | } else {
91 | res.end(JSON.stringify({ sys: { type: 'Error' }}))
92 | }
93 |
94 | return
95 | }
96 |
97 | if (update.token && !update.space) {
98 | const checkURL = new URL('https://api.contentful.com/spaces')
99 | const checkReq = new Request(checkURL, {
100 | cache: 'no-cache',
101 | headers: {
102 | 'Accept': 'application/json',
103 | 'Authorization': 'Bearer ' + update.token,
104 | 'Accept-Encoding': 'gzip',
105 | 'User-Agent': 'node.js/',
106 | 'x-contentful-user-agent': 'sdk contentful-management.js/10.12.0;',
107 | },
108 | })
109 |
110 | res.setHeader('Content-Type', 'application/json;charset=utf-8')
111 |
112 | const checkRes = await fetch(checkReq)
113 | const checkJSO = await checkRes.json()
114 |
115 | if (checkJSO?.sys?.type === 'Array') {
116 | res.end(JSON.stringify(checkJSO))
117 | } else {
118 | res.end(JSON.stringify({ sys: { type: 'Error' }}))
119 | }
120 |
121 | return
122 | }
123 | } catch (error) {
124 | res.end(JSON.stringify({ sys: { type: 'Error' } }))
125 |
126 | return
127 | }
128 | });
129 | }
130 |
131 | return
132 | }
133 |
134 | if (!meta.env.CONTENTFUL_ACCESS_TOKEN) {
135 | res.writeHead(302, {
136 | Location: middlewareConfig.pathToHTML
137 | }).end()
138 |
139 | return
140 | }
141 |
142 | return next()
143 | })
144 |
145 | return middleware
146 | }
147 |
148 | const middlewareConfig = {
149 | pathToHTML: '/@contentful/',
150 | pathToJSON: '/@contentful/api'
151 | }
152 | const pathToHtml = new URL('./contentful-middleware.html', import.meta.url)
153 | const touchFileSync = (/** @type {fs.PathLike} */ path) => {
154 | const time = new Date()
155 |
156 | try {
157 | fs.utimesSync(path, time, time)
158 | } catch (err) {
159 | fs.closeSync(fs.openSync(path, 'w'))
160 | }
161 | }
162 |
163 | /** @typedef {(req: Connect.IncomingMessage, res: ServerResponse, next: Connect.NextFunction) => void} ContentfulMiddleware */
164 | /** @typedef {import('./createMeta.d').Meta} Meta */
165 |
--------------------------------------------------------------------------------
/packages/contentful/integrations/contentful-response.js:
--------------------------------------------------------------------------------
1 | export const contentfulResponse = async (
2 | /** @type {string} */ input,
3 | /** @type {Meta} */ meta,
4 | /** @type {string} */ format
5 | ) => {
6 | const requestURL = new URL(input, 'https://api.contentful.com')
7 |
8 | const request = new Request(requestURL, {
9 | cache: 'no-cache',
10 | headers: {
11 | 'Accept': 'application/json',
12 | 'Authorization': 'Bearer ' + meta.env.CONTENTFUL_ACCESS_TOKEN,
13 | 'Accept-Encoding': 'gzip',
14 | 'User-Agent': 'node.js/',
15 | 'x-contentful-user-agent': 'sdk contentful-management.js/10.12.0;',
16 | },
17 | })
18 |
19 | /** Cached JSON response. */
20 | let json = throttled[input] || null
21 |
22 | // cache the json response
23 | if (json === null) {
24 | const response = await fetch(request)
25 |
26 | json = throttled[input] = await response.json()
27 |
28 | setTimeout(() => {
29 | delete throttled[input]
30 | }, 200)
31 | }
32 |
33 | const isComponent = format === '!astro'
34 |
35 | const isEntry = requestURL.pathname.includes('/entries/')
36 | const isEntryList = requestURL.pathname.endsWith('/entries')
37 |
38 | const data = JSON.stringify(json, null, '\t')
39 |
40 | const code = (
41 | isComponent && isEntry
42 | ? [
43 | `import { renderTemplate, renderSlot } from 'astro/server/render/index.js';`,
44 | `import { richtexttohtml } from '@astropub/contentful';`,
45 | `export const locale = ${JSON.stringify(meta.env.CONTENTFUL_LOCALE)};`,
46 | `export const entry = ${data};`,
47 | toHTML,
48 | exportEntry,
49 | `export default Entry;`,
50 | ].join('\n')
51 | : isComponent && isEntryList
52 | ? [
53 | `import { renderTemplate, renderSlot } from 'astro/server/render/index.js';`,
54 | `import { richtexttohtml } from '@astropub/contentful';`,
55 | `export const locale = ${JSON.stringify(meta.env.CONTENTFUL_LOCALE)};`,
56 | `export const entryList = ${data};`,
57 | toHTML,
58 | exportEntryList,
59 | `export default EntryList;`,
60 | ].join('\n')
61 | : `export default ${data};`
62 | )
63 |
64 | return { code }
65 | }
66 |
67 | const throttled = Object.create(null)
68 |
69 | const toHTML = `const toHTML = (entry, name) => {
70 | let html = '';
71 |
72 | html = entry?.[name]?.[locale] || null;
73 | html = html ? html.nodeType ? richtexttohtml(html) : html : null;
74 |
75 | return new String(html);
76 | };`
77 |
78 | const exportEntry = `export const Entry = async (result, attrs, slots) => {
79 | return renderTemplate\`\${
80 | attrs.of in Object(entry.fields)
81 | ? toHTML(entry.fields, attrs.of)
82 | : renderSlot(result, slots.default)
83 | }\`;
84 | };
85 |
86 | Entry.of = (of) => (
87 | of in Object(entry.fields)
88 | ? toHTML(entry.fields, of)
89 | : null
90 | );
91 |
92 | Entry.isAstroComponentFactory = true`
93 |
94 | const exportEntryList = `export const EntryList = (_result, attrs, slots) => {
95 | const render = slots.default?.().then(
96 | (result) => result.expressions.at(0),
97 | () => null
98 | )
99 |
100 | return {
101 | get [Symbol.toStringTag]() {
102 | return 'AstroComponent'
103 | },
104 | async *[Symbol.asyncIterator]() {
105 | const normalizedGenerator = getNormalizedGenerator(await render)
106 |
107 | if (entryList.items?.length) for (const itemdata of entryList.items) {
108 | const Entry = async (result, attrs, slots) => {
109 | return renderTemplate\`\${
110 | attrs.of in Object(itemdata.fields)
111 | ? toHTML(itemdata.fields, attrs.of)
112 | : renderSlot(result, slots.default)
113 | }\`;
114 | };
115 |
116 | Entry.of = (name) => (
117 | name in Object(itemdata.fields)
118 | ? toHTML(itemdata.fields, name)
119 | : null
120 | );
121 |
122 | Entry.isAstroComponentFactory = true
123 |
124 | yield * normalizedGenerator(Entry)
125 | }
126 | },
127 | }
128 | };
129 |
130 | EntryList.isAstroComponentFactory = true
131 |
132 | EntryList.None = async (result, attrs, slots) => {
133 | return renderTemplate\`\${
134 | entryList.items === Object(entryList.items)
135 | ? ''
136 | : renderSlot(result, slots.default)
137 | }\`;
138 | };
139 |
140 | EntryList.None.isAstroComponentFactory = true
141 |
142 | const isIterable = (value) => (
143 | value != null &&
144 | (
145 | typeof value[Symbol.iterator] === 'function' ||
146 | typeof value[Symbol.asyncIterator] === 'function'
147 | )
148 | )
149 |
150 | export const getNormalizedGenerator = (fn) => (
151 | typeof fn !== 'function'
152 | ? async function * (value) {
153 | yield await value
154 | }
155 | : (
156 | fn instanceof GeneratorFunction ||
157 | fn instanceof AsyncGeneratorFunction
158 | )
159 | ? fn
160 | : async function * (value) {
161 | yield await fn(await value)
162 | }
163 | )
164 |
165 | const GeneratorFunction = (function * () {}).constructor
166 |
167 | const AsyncGeneratorFunction = (async function * () {}).constructor`
168 |
169 | /** @typedef {{ space: string, environment: string, origin: string, locale: string, token: string }} ContentfulConfig */
170 | /** @typedef {import('./createMeta.d').Meta} Meta */
171 |
--------------------------------------------------------------------------------
/packages/contentful/integrations/contentful-vite-plugin.js:
--------------------------------------------------------------------------------
1 | import { contentfulResponse } from './contentful-response.js'
2 |
3 | export const contentfulVite = (/** @type {{ meta: Meta }} */ { meta }) => {
4 | /** Prefix used by this plugin to differentiate Contentful imports. */
5 | const virtualModuleId = '@astropub/contentful:'
6 |
7 | /** Prefix used by Vite to differentiate virtual modules. */
8 | const virtualPrefixId = '\0'
9 |
10 | return /** @type {VitePlugin} */ ({
11 | name: 'vite:contentful',
12 | enforce: 'pre',
13 | resolveId(importeeId) {
14 | if (importeeId.startsWith(virtualModuleId)) {
15 | return virtualPrefixId + importeeId
16 | }
17 | },
18 | async load(importeeId) {
19 | if (importeeId.startsWith(virtualPrefixId + virtualModuleId)) {
20 | const [ request, format ] = importeeId.slice(virtualModuleId.length + 1).split(/(?=\!astro$)/)
21 |
22 | return await contentfulResponse(
23 | `/spaces/${
24 | meta.env.CONTENTFUL_SPACE
25 | }/environments/${
26 | meta.env.CONTENTFUL_ENVIRONMENT
27 | }/${request}`,
28 | meta,
29 | format
30 | )
31 | }
32 | },
33 | })
34 | }
35 |
36 | /** @typedef {import('./createMeta').Meta} Meta */
37 | /** @typedef {import('./contentful-response.js').ContentfulConfig} ContentfulConfig */
38 | /** @typedef {Partial & { space: string, token: string }} VitePluginConfig */
39 | /** @typedef {import('vite').Plugin} VitePlugin */
40 |
--------------------------------------------------------------------------------
/packages/contentful/integrations/createMeta.d.ts:
--------------------------------------------------------------------------------
1 | export interface UpdateInit {
2 | /** Current working directory of the Node.js Process. */
3 | cwd: URL
4 |
5 | /** Environment variables. */
6 | env: EnvironmentVariables
7 |
8 | /** Mode the app is running in. */
9 | mode: string
10 | }
11 |
12 | export interface Meta {
13 | /** Current working directory of the Node.js Process. */
14 | cwd: URL
15 |
16 | /** Environment variables. */
17 | env: EnvironmentVariables
18 |
19 | /** Mode the app is running in. */
20 | mode: string
21 |
22 | /** Mode the server is running in. */
23 | port: string
24 |
25 | /** Protocol the server is running as. */
26 | protocol: string
27 |
28 | /** Hostname the server is running as. */
29 | hostname: string
30 |
31 | /** Origin the server is running as. */
32 | readonly origin: string
33 |
34 | update(init: URL): void
35 | }
36 |
37 | /** Environment variables. */
38 | export interface EnvironmentVariables {
39 | [variable: string]: string
40 | }
41 |
42 | export declare function createMeta(): Meta
43 |
--------------------------------------------------------------------------------
/packages/contentful/integrations/createMeta.js:
--------------------------------------------------------------------------------
1 | // @ts-check
2 |
3 | import { fileURLToPath, pathToFileURL } from 'node:url'
4 | import { loadEnv } from 'vite'
5 |
6 | /** Returns context-specific metadata about the current process. */
7 | export const createMeta = /** @type {() => Meta} */ () => {
8 | /** Current working directory of the Node.js Process. */
9 | const cwd = pathToFileURL(process.cwd())
10 |
11 | /** Environment variables. */
12 | const env = /** @type {EnvironmentVariables} */ (Object.assign(
13 | Object.create(null),
14 | process.env
15 | ))
16 |
17 | /** Mode the app is running in. */
18 | const mode = env.MODE || 'development'
19 |
20 | /** @type {Meta} */
21 | const meta = {
22 | cwd,
23 | mode,
24 | port: env.PORT || '3000',
25 | protocol: env.PROTOCOL || 'http:',
26 | hostname: env.HOSTNAME || 'localhost',
27 | get env() {
28 | return env
29 | },
30 | set env(value) {
31 | Object.assign(env, value)
32 | },
33 | get origin() {
34 | return `${this.protocol}//${this.hostname}:${this.port}`
35 | },
36 | /** Updates the internals. */
37 | update(cwd) {
38 | // update the current working directory (`root`).
39 | this.cwd = cwd
40 |
41 | // clear the existing environment variables
42 | for (const name in env) {
43 | delete env[name]
44 | }
45 |
46 | // update the environment variables
47 | Object.assign(env, loadEnv(this.mode, fileURLToPath(this.cwd), ''))
48 | },
49 | }
50 |
51 | return meta
52 | }
53 |
54 | /** @typedef {import('./createMeta.d').EnvironmentVariables} EnvironmentVariables */
55 | /** @typedef {import('./createMeta.d').Meta} Meta */
56 | /** @typedef {import('./createMeta.d').UpdateInit} UpdateInit */
57 |
--------------------------------------------------------------------------------
/packages/contentful/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/package.json",
3 | "name": "@astropub/contentful",
4 | "description": "Use Contentful in Astro",
5 | "version": "0.1.0",
6 | "type": "module",
7 | "license": "CC0-1.0",
8 | "exports": {
9 | ".": {
10 | "default": "./astro-contentful.js",
11 | "types": "./astro-contentful.d.ts"
12 | },
13 | "./astro-contentful": {
14 | "default": "./astro-contentful.js",
15 | "types": "./astro-contentful.d.ts"
16 | },
17 | "./global": {
18 | "types": "./global.d.ts"
19 | },
20 | "./package": "./package.json",
21 | "./package.json": "./package.json"
22 | },
23 | "main": "astro-contentful.js",
24 | "types": "astro-contentful.d.ts",
25 | "unpkg": "astro-contentful.js",
26 | "jsdelivr": "astro-contentful.js",
27 | "sideEffects": false,
28 | "files": [
29 | "bundled",
30 | "integrations",
31 | "astro-contentful.js",
32 | "astro-contentful.d.ts"
33 | ],
34 | "keywords": [
35 | "astro",
36 | "astro-component",
37 | "ui",
38 | "perf",
39 | "performance",
40 | "content",
41 | "contentful"
42 | ],
43 | "author": "Jonathan Neal ",
44 | "bugs": "https://github.com/astro-community/contentful/issues",
45 | "homepage": "https://github.com/astro-community/contentful",
46 | "repository": "https://github.com/astro-community/contentful.git"
47 | }
48 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "module": "ESNext",
5 | "moduleResolution": "node",
6 | "exactOptionalPropertyTypes": true,
7 | "isolatedModules": true,
8 | "resolveJsonModule": true,
9 | "strictNullChecks": true,
10 | "types": ["astro/client", "types-object"]
11 | }
12 | }
13 |
--------------------------------------------------------------------------------