diff --git a/.ci/doc/Dockerfile b/.ci/doc/Dockerfile new file mode 100644 index 000000000..7f7049488 --- /dev/null +++ b/.ci/doc/Dockerfile @@ -0,0 +1,76 @@ +FROM node:20-bookworm-slim + +USER root + +RUN mkdir -p /home/node/.cache/puppeteer + +# Puppeteer Chrome headless dependencies +RUN apt-get update && apt-get install -y \ + ca-certificates \ + curl \ + fonts-liberation \ + libasound2 \ + libatk-bridge2.0-0 \ + libatk1.0-0 \ + libc6 \ + libcairo2 \ + libcups2 \ + libdbus-1-3 \ + libexpat1 \ + libfontconfig1 \ + libgbm1 \ + libgcc1 \ + libglib2.0-0 \ + libgtk-3-0 \ + libnspr4 \ + libnss3 \ + libpango-1.0-0 \ + libpangocairo-1.0-0 \ + libstdc++6 \ + libx11-6 \ + libx11-xcb1 \ + libxcb1 \ + libxcomposite1 \ + libxcursor1 \ + libxdamage1 \ + libxext6 \ + libxfixes3 \ + libxi6 \ + libxrandr2 \ + libxrender1 \ + libxss1 \ + libxtst6 \ + lsb-release \ + wget \ + xdg-utils \ + && rm -rf /var/lib/apt/lists/* + +# Install all dependencies needed for both services +RUN npm install -g \ + puppeteer \ + eslint@8.38.0 \ + eslint-plugin-html \ + eslint-plugin-import \ + eslint-plugin-node \ + eslint-plugin-promise \ + eslint-plugin-standard \ + babel-loader \ + @babel/core \ + html-webpack-plugin \ + webpack \ + webpack-cli + +RUN usermod -a -G video,audio node + +# Create working directories for snippets +RUN mkdir -p /var/snippets/web && \ + mkdir -p /var/snippets/webpack + +# Set proper permissions +RUN chown -R node:node /var/snippets/ +RUN chown -R node:node /home/node/.cache/puppeteer + +USER node + +# Keep container running +CMD ["tail", "-f", "/dev/null"] diff --git a/.ci/doc/config.yml b/.ci/doc/config.yml index 59d9f91d1..5af33babc 100644 --- a/.ci/doc/config.yml +++ b/.ci/doc/config.yml @@ -5,40 +5,40 @@ snippets: templates: /mnt/.ci/doc/templates runners: - default: node + default: web - node: - service: doc-runner-node - path: /var/snippets/node - lint: - global: true - cmd: eslint -c /mnt/.ci/doc/eslint.json {{ snippet.dir }} - before: timeout 600 ash -c 'until stat /tmp/runner_ready_to_lint; do sleep 1; done' - run: - cmd: node {{ snippet.source }} - before: timeout 600 ash -c 'until stat /tmp/runner_is_ready && curl -f -s -o /dev/null http://kuzzle:7512/_now; do sleep 1; done' + # node: + # service: doc-runner-node + # path: /var/snippets/node + # lint: + # global: true + # cmd: npx eslint@8.38.0 -c /mnt/.ci/doc/eslint.json {{ snippet.dir }} + # before: timeout 600 ash -c 'until stat /home/node/runner_ready_to_lint; do sleep 1; done' + # run: + # cmd: node {{ snippet.source }} + # before: timeout 600 ash -c 'until stat /home/node/runner_is_ready && curl -f -s -o /dev/null http://kuzzle:7512/_now; do sleep 1; done' web: service: doc-runner-web path: /var/snippets/web lint: global: true - cmd: eslint -c /mnt/.ci/doc/eslint.json --parser-options ecmaVersion:12 {{ snippet.dir }}/*.html - before: timeout 600 bash -c 'until stat /tmp/runner_ready_to_lint; do sleep 1; done' + cmd: npx eslint@8.38.0 -c /mnt/.ci/doc/eslint.json --parser-options ecmaVersion:12 {{ snippet.dir }}/*.html + before: timeout 600 bash -c 'until stat /home/node/runner_ready_to_lint; do sleep 1; done' run: cmd: node puppeteer.js {{ snippet.dir }}/{{ snippet.source }} - before: timeout 600 bash -c 'until stat /tmp/runner_is_ready && curl -f -s -o /dev/null http://kuzzle:7512/_now; do sleep 1; done' + before: timeout 600 bash -c 'until stat /home/node/runner_is_ready && curl -f -s -o /dev/null http://kuzzle:7512/_now; do sleep 1; done' webpack: service: doc-runner-webpack path: /var/snippets/webpack lint: global: true - cmd: eslint -c /mnt/.ci/doc/eslint.json {{ snippet.dir }} - before: timeout 600 bash -c 'until stat /tmp/runner_ready_to_lint; do sleep 1; done' + cmd: npx eslint8.38.0 -c /mnt/.ci/doc/eslint.json {{ snippet.dir }} + before: timeout 600 bash -c 'until stat /home/node/runner_ready_to_lint; do sleep 1; done' build: cmd: node webpackBuild.js {{ snippet.dir }}/{{ snippet.source }} - before: timeout 600 bash -c 'until stat /tmp/runner_is_ready; do sleep 1; done' + before: timeout 600 bash -c 'until stat /home/node/runner_is_ready; do sleep 1; done' run: cmd: node puppeteer.js /tmp/{{ snippet.name }}/index.html before: timeout 600 bash -c 'until curl -f -s -o /dev/null http://kuzzle:7512/_now; do sleep 1; done' diff --git a/.ci/doc/docker-compose.yml b/.ci/doc/docker-compose.yml index d990e5815..4c03c7c72 100644 --- a/.ci/doc/docker-compose.yml +++ b/.ci/doc/docker-compose.yml @@ -47,12 +47,11 @@ services: ash -c ' mkdir -p /var/snippets/node; apk add --no-cache curl; - npm install -g eslint@8.38.0; cd /var/snippets/node; npm install \ bluebird \ /mnt/ \ - eslint \ + eslint@8.38.0 \ eslint-plugin-html \ eslint-plugin-import \ eslint-plugin-node \ @@ -67,68 +66,40 @@ services: - snippets:/var/snippets doc-runner-web: - image: ghcr.io/puppeteer/puppeteer:23.5.1 - user: root + build: . + volumes: + - ../..:/mnt + - snippets:/var/snippets + working_dir: /var/snippets/web command: > bash -c ' - mkdir -p /var/snippets/web; - apt-get update; - apt-get install -y curl; - npm install -g \ - eslint@8.38.0; - cd /var/snippets/web; cp /mnt/.ci/doc/puppeteer.js /var/snippets/web/; - npm install \ - /mnt/ \ - puppeteer \ - eslint \ - eslint-plugin-html \ - eslint-plugin-import \ - eslint-plugin-node \ - eslint-plugin-promise \ - eslint-plugin-standard; - touch /tmp/runner_ready_to_lint; - touch /tmp/runner_is_ready; + npm install /mnt/; + cp -fr /usr/local/lib/node_modules/* /var/snippets/web/node_modules; + cp -fr /usr/local/lib/node_modules/* /var/snippets/webpack/node_modules; + touch /home/node/runner_ready_to_lint; + touch /home/node/runner_is_ready; tail -f /dev/null ' + + doc-runner-webpack: + build: . volumes: - ../..:/mnt - snippets:/var/snippets - - doc-runner-webpack: - image: ghcr.io/puppeteer/puppeteer:23.5.1 - user: root + working_dir: /var/snippets/webpack command: > bash -c ' - mkdir -p /var/snippets/webpack; - apt-get update; - apt-get install -y curl; - npm install -g \ - eslint@8.38.0; - cd /var/snippets/webpack; cp /mnt/.ci/doc/puppeteer.js /var/snippets/webpack/; cp /mnt/.ci/doc/webpackBuild.js /var/snippets/webpack/; - npm install \ - /mnt/ \ - puppeteer \ - babel-loader \ - @babel/core \ - html-webpack-plugin \ - webpack \ - webpack-cli \ - eslint \ - eslint-plugin-html \ - eslint-plugin-import \ - eslint-plugin-node \ - eslint-plugin-promise \ - eslint-plugin-standard; - touch /tmp/runner_ready_to_lint; - touch /tmp/runner_is_ready; + npm install /mnt/; + cp -fr /usr/local/lib/node_modules/* /var/snippets/web/node_modules; + cp -fr /usr/local/lib/node_modules/* /var/snippets/webpack/node_modules; + touch /home/node/runner_ready_to_lint; + touch /home/node/runner_is_ready; tail -f /dev/null ' - volumes: - - ../..:/mnt - - snippets:/var/snippets + volumes: snippets: diff --git a/.ci/doc/package.json b/.ci/doc/package.json index 9a193f572..a98376095 100644 --- a/.ci/doc/package.json +++ b/.ci/doc/package.json @@ -3,6 +3,7 @@ "version": "1.0.0", "description": "docs for kuzzle-sdk", "author": "The Kuzzle Team ", + "main": "index.js", "scripts": {}, "dependencies": {}, "devDependencies": {} diff --git a/.ci/doc/puppeteer.js b/.ci/doc/puppeteer.js index 6e7ef84b1..eb4558052 100644 --- a/.ci/doc/puppeteer.js +++ b/.ci/doc/puppeteer.js @@ -1,38 +1,60 @@ -const puppeteer = require('puppeteer'); +const puppeteer = require("puppeteer"); const renderedSnippetPath = process.argv[2]; -const runInBrowser = async snippetPath => { +const runInBrowser = async (snippetPath) => { let browser; - try { + // Install Chrome browser first + const { execSync } = require('child_process'); + execSync('npx puppeteer browsers install chrome', { stdio: 'inherit' }); + browser = await puppeteer.launch({ dumpio: true, - args: ['--no-sandbox'] + headless: "new", + // Remove executablePath to use the bundled Chromium + args: [ + "--no-sandbox", + "--disable-setuid-sandbox", + "--disable-gpu", + "--disable-dev-shm-usage", + ], }); } catch (error) { - console.error(error); - return; + console.error('Browser launch error:', error); + process.exit(1); } try { const page = await browser.newPage(); - page.on('error', err => { - console.error(err); + page.on("error", (err) => { + console.error('Page error:', err); }); - page.on('pageerror', err => { - console.error(err); + page.on("pageerror", (err) => { + console.error('Page error:', err); + }); + + page.on('console', msg => { + console.log('Page console:', msg.text()); }); await page.goto(`file:${snippetPath}`, { - waitUntil: 'networkidle0' + waitUntil: "networkidle0", + timeout: 30000, }); } catch (error) { - console.error(error); + console.error('Page processing error:', error); } finally { - await browser.close(); + if (browser) { + await browser.close(); + } } }; -runInBrowser(renderedSnippetPath); +if (!renderedSnippetPath) { + console.error('Please provide a path to the snippet file'); + process.exit(1); +} + +runInBrowser(renderedSnippetPath); \ No newline at end of file diff --git a/.ci/test-docs.sh b/.ci/test-docs.sh index 8ff1d1ad8..23c39b09f 100644 --- a/.ci/test-docs.sh +++ b/.ci/test-docs.sh @@ -5,7 +5,8 @@ set -ex here="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" cd "$here" +docker compose -f ./doc/docker-compose.yml build docker compose -f ./doc/docker-compose.yml pull docker compose -f ./doc/docker-compose.yml run doc-tests node index EXIT=$? -docker compose -f ./doc/docker-compose.yml down +# docker compose -f ./doc/docker-compose.yml down diff --git a/src/utils/browser.js b/src/utils/browser.js new file mode 100644 index 000000000..3d81f11b6 --- /dev/null +++ b/src/utils/browser.js @@ -0,0 +1,40 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.isBrowser = exports.getBrowserWindow = void 0; +function getBrowserWindow() { + let windowObject; + try { + windowObject || (windowObject = globalThis.window); + if (windowObject) { + return windowObject; + } + } + catch { + // Check next variable + } + try { + windowObject || (windowObject = global.window); + if (windowObject) { + return windowObject; + } + } + catch { + // Check next variable + } + try { + windowObject || (windowObject = window); + if (windowObject) { + return windowObject; + } + } + catch { + // return undefined + } +} +exports.getBrowserWindow = getBrowserWindow; +function isBrowser() { + const window = getBrowserWindow(); + return window !== undefined && window !== null && typeof window === "object"; +} +exports.isBrowser = isBrowser; +//# sourceMappingURL=browser.js.map \ No newline at end of file