Strapi api doesn’t return image field

I’m in a pretty strange situation.

the url /api/home-page?populate=* doesn’t return my image field
but /api/home-page?populate=heroImage does

On the other side I have another single page very similar where populate=* and populate=heroImage are both working fine.

What can explain that problem?

Below the two schema.json

home-page :

{
  "kind": "singleType",
  "collectionName": "home_pages",
  "info": {
    "singularName": "home-page",
    "pluralName": "home-pages",
    "displayName": "Page d'accueil",
    "description": ""
  },
  "options": {
    "draftAndPublish": true
  },
  "pluginOptions": {},
  "attributes": {
    "title": {
      "type": "string"
    },
    "description": {
      "type": "text"
    },
    "seo": {
      "type": "component",
      "repeatable": false,
      "component": "shared.seo"
    },
    "heroImage": {
      "type": "media",
      "multiple": false,
      "required": false,
      "allowedTypes": ["images"]
    },
    "img": {
      "allowedTypes": ["images"],
      "type": "media",
      "multiple": false
    }
  }
}

the other page :

{
  "kind": "singleType",
  "collectionName": "ou_trouver_bonuxes",
  "info": {
    "singularName": "ou-trouver-bonux",
    "pluralName": "ou-trouver-bonuxes",
    "displayName": "Où trouver Bonux"
  },
  "options": {
    "draftAndPublish": true
  },
  "pluginOptions": {},
  "attributes": {
    "title": {
      "type": "string"
    },
    "description": {
      "type": "text"
    },
    "heroImage": {
      "allowedTypes": [
        "images"
      ],
      "type": "media",
      "multiple": false
    }
  }
}

Swiper carousel slider

I need to create a Swiper slider carousel, like the one here https://codepen.io/kristen17/pen/BaGEeKe :

However, I need the active element to be the leftmost one, as shown in this video: https://skrinshoter.ru/vSkii8DzT7T . Please help

I tried the cards and coverflow effects and searched on Google for a long time, but nothing works.

<div class="swiper-container">
    <div class="swiper">
      <div class="swiper-wrapper">
        <div class="swiper-slide swiper-slide--three">
          <div class="slide-content">
            <h3>All Quiet on the Western Front</h3>
            <p>The book describes the German soldiers' extreme physical and mental trauma during the war</p>

          </div>
          <div class="author">
            <img src="https://images.pexels.com/photos/262391/pexels-photo-262391.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1" alt="Erich Maria Remarque">
            <span>Erich Maria Remarque</span>
            <ul>
              <li>
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-6 h-6">
                  <path fill-rule="evenodd" d="M10.788 3.21c.448-1.077 1.976-1.077 2.424 0l2.082 5.007 5.404.433c1.164.093 1.636 1.545.749 2.305l-4.117 3.527 1.257 5.273c.271 1.136-.964 2.033-1.96 1.425L12 18.354 7.373 21.18c-.996.608-2.231-.29-1.96-1.425l1.257-5.273-4.117-3.527c-.887-.76-.415-2.212.749-2.305l5.404-.433 2.082-5.006z" clip-rule="evenodd" />
                </svg>

              </li>
              <li>
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-6 h-6">
                  <path fill-rule="evenodd" d="M10.788 3.21c.448-1.077 1.976-1.077 2.424 0l2.082 5.007 5.404.433c1.164.093 1.636 1.545.749 2.305l-4.117 3.527 1.257 5.273c.271 1.136-.964 2.033-1.96 1.425L12 18.354 7.373 21.18c-.996.608-2.231-.29-1.96-1.425l1.257-5.273-4.117-3.527c-.887-.76-.415-2.212.749-2.305l5.404-.433 2.082-5.006z" clip-rule="evenodd" />
                </svg>

              </li>
              <li>
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-6 h-6">
                  <path fill-rule="evenodd" d="M10.788 3.21c.448-1.077 1.976-1.077 2.424 0l2.082 5.007 5.404.433c1.164.093 1.636 1.545.749 2.305l-4.117 3.527 1.257 5.273c.271 1.136-.964 2.033-1.96 1.425L12 18.354 7.373 21.18c-.996.608-2.231-.29-1.96-1.425l1.257-5.273-4.117-3.527c-.887-.76-.415-2.212.749-2.305l5.404-.433 2.082-5.006z" clip-rule="evenodd" />
                </svg>

              </li>
              <li>
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-6 h-6">
                  <path fill-rule="evenodd" d="M10.788 3.21c.448-1.077 1.976-1.077 2.424 0l2.082 5.007 5.404.433c1.164.093 1.636 1.545.749 2.305l-4.117 3.527 1.257 5.273c.271 1.136-.964 2.033-1.96 1.425L12 18.354 7.373 21.18c-.996.608-2.231-.29-1.96-1.425l1.257-5.273-4.117-3.527c-.887-.76-.415-2.212.749-2.305l5.404-.433 2.082-5.006z" clip-rule="evenodd" />
                </svg>

              </li>
            </ul>
          </div>
        </div>
        <div class="swiper-slide swiper-slide--four">
          <div class="slide-content">
            <h3>Romeo and Juliet</h3>
            <p>a tragedy between two youths from feuding families</p>

          </div>
          <div class="author">
            <img src="https://images.pexels.com/photos/614810/pexels-photo-614810.jpeg?auto=compress&cs=tinysrgb&w=600" alt="William Shakespeare">
            <span>William Shakespeare</span>
            <ul>
              <li>
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-6 h-6">
                  <path fill-rule="evenodd" d="M10.788 3.21c.448-1.077 1.976-1.077 2.424 0l2.082 5.007 5.404.433c1.164.093 1.636 1.545.749 2.305l-4.117 3.527 1.257 5.273c.271 1.136-.964 2.033-1.96 1.425L12 18.354 7.373 21.18c-.996.608-2.231-.29-1.96-1.425l1.257-5.273-4.117-3.527c-.887-.76-.415-2.212.749-2.305l5.404-.433 2.082-5.006z" clip-rule="evenodd" />
                </svg>

              </li>
              <li>
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-6 h-6">
                  <path fill-rule="evenodd" d="M10.788 3.21c.448-1.077 1.976-1.077 2.424 0l2.082 5.007 5.404.433c1.164.093 1.636 1.545.749 2.305l-4.117 3.527 1.257 5.273c.271 1.136-.964 2.033-1.96 1.425L12 18.354 7.373 21.18c-.996.608-2.231-.29-1.96-1.425l1.257-5.273-4.117-3.527c-.887-.76-.415-2.212.749-2.305l5.404-.433 2.082-5.006z" clip-rule="evenodd" />
                </svg>

              </li>
              <li>
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-6 h-6">
                  <path fill-rule="evenodd" d="M10.788 3.21c.448-1.077 1.976-1.077 2.424 0l2.082 5.007 5.404.433c1.164.093 1.636 1.545.749 2.305l-4.117 3.527 1.257 5.273c.271 1.136-.964 2.033-1.96 1.425L12 18.354 7.373 21.18c-.996.608-2.231-.29-1.96-1.425l1.257-5.273-4.117-3.527c-.887-.76-.415-2.212.749-2.305l5.404-.433 2.082-5.006z" clip-rule="evenodd" />
                </svg>

              </li>
              <li>
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-6 h-6">
                  <path fill-rule="evenodd" d="M10.788 3.21c.448-1.077 1.976-1.077 2.424 0l2.082 5.007 5.404.433c1.164.093 1.636 1.545.749 2.305l-4.117 3.527 1.257 5.273c.271 1.136-.964 2.033-1.96 1.425L12 18.354 7.373 21.18c-.996.608-2.231-.29-1.96-1.425l1.257-5.273-4.117-3.527c-.887-.76-.415-2.212.749-2.305l5.404-.433 2.082-5.006z" clip-rule="evenodd" />
                </svg>

              </li>
            </ul>
          </div>
        </div>
      </div>
    </div>
  </div>
var swiper = new Swiper(".swiper", {
    effect: "coverflow",
    grabCursor: true,
    centeredSlides: false,
    coverflowEffect: {
        rotate: 0,
        stretch: 0,
        depth: 100,
        modifier: 4,
        slideShadows: true
    },
    loop: true,
    navigation: {
        nextEl: ".swiper-button-next",
        prevEl: ".swiper-button-prev"
    },
    keyboard: {
        enabled: true
    },
    mousewheel: {
        thresholdDelta: 70
    },
    breakpoints: {
        560: {
            slidesPerView: 2.5
        },
        768: {
            slidesPerView: 3
        },
        1024: {
            slidesPerView: 3
        }
    }
});

Vite errors out from node_modules

I am trying build using vite. How can I make it not error out on packages out of my control?

import {defineConfig, transformWithEsbuild} from 'vite';
import react from '@vitejs/plugin-react-swc';
import path from 'path';
import { createHtmlPlugin } from 'vite-plugin-html';
import baseViteConfig from "./base.config";

const serverUrl = "http://dev.pontiac.internal:1070/";

export default defineConfig({
    ...baseViteConfig,
    mode: 'development',
    root: path.resolve(__dirname, '../src'),
    build: {
        outDir: path.resolve(__dirname, '../dist'),
        rollupOptions: {
            input: {
                main: path.resolve(__dirname, '../src/index.html')
            },
            output: {
                entryFileNames: 'client.min.js'
            }
        }
    },
    plugins: [
        react(),
        createHtmlPlugin({
            inject: {
                data: {
                    serverUrl: serverUrl
                }
            },
            minify: false,
            template: '../src/maintenance.html',
            filename: '../dist/maintenance.html'
        })
    ],
    server: {
        open: true,
        hot: true,
        watch: {
            usePolling: true
        }
    },
    esbuild: {
        loader: "tsx", // OR "jsx"
        include: [
            // Add this for business-as-usual behaviour for .jsx and .tsx files
            "src/**/*.jsx",
            "src/**/*.tsx",

            // Add these lines to allow all .js files to contain JSX
            "src/**/*.js",

            // Add these lines to allow all .ts files to contain JSX
            "src/**/*.ts",
        ],
    },
});

errors

[TypeScript] Found 0 errors. Watching for file changes.
✘ [ERROR] Unterminated string literal

    node_modules/react-multiselect-checkboxes/lib/DropdownButton.jsx:33:2:
      33 │ ',
         ╵   ^

✘ [ERROR] Expected ";" but found "CheckboxOption"

    node_modules/react-multiselect-checkboxes/lib/CheckboxOption.jsx:41:1:
      41 │ }CheckboxOption.defaultProps = {
         │  ~~~~~~~~~~~~~~
         ╵  ;

✘ [ERROR] Unterminated regular expression

    node_modules/react-multiselect-checkboxes/lib/Dropdown.jsx:10:74:
      10 │       {isOpen ? <Menu rightAligned={rightAligned>{children}</Menu> : null}
         ╵                                                                           ^

✘ [ERROR] The symbol "getOptionValue" has already been declared

    node_modules/react-multiselect-checkboxes/lib/CheckboxGroup.jsx:20:8:
      20 │   const getOptionValue = props.selectProps.getOptionValue;
         ╵         ~~~~~~~~~~~~~~

  The symbol "getOptionValue" was originally declared here:

    node_modules/react-multiselect-checkboxes/lib/CheckboxGroup.jsx:7:8:
      7 │   const {
        ╵         ^

I understand these are actual errors, but I can’t remove them. Webpack built it with no issue

Jest failing because of import/export syntax

One of the files under test is importing the estree-util-to-js library, which cases Jest to exit with an error:

Details:

    /.../node_modules/estree-util-to-js/index.js:8
    export { toJs } from './lib/index.js';
    ^^^^^^

    SyntaxError: Unexpected token 'export'

Curiously, I already fixed this problem once. That’s why I have in my jest.config.json file the following:

{
  "preset": "ts-jest",
  "roots": ["src"],
  "testEnvironment": "jsdom",
  "transform": {
    "^.+\.tsx?$": [
      "ts-jest",
      {
        "diagnostics": false
      }
    ],
    "^.+/estree-util-to-js/.+\.js$": [
      "ts-jest",
      {
        "diagnostics": false
      }
    ]
  },
  "transformIgnorePatterns": ["<rootDir>/node_modules/(?!estree-util-to-js)"]
}

This worked just fine until today I upgraded lots of dependencies, after which this stopped working.

What I have managed to rule out so far:

  • estree-util-to-js was not upgraded.
  • The error also happens with plain import ...; export ... syntax, not just with export ... from;
  • Rolled back upgrade of ts-jest (29.1.2 -> 29.2.5). Didn’t help.
  • No upgrade of jest itself was done.

How to make active route link scroll to center in Angular?

In Angular, I have a Navbar, in which I have scrollable menu links. The links will start from the center.
What I’m trying to do is, that I want the active link to be scrolled to the center when I click on it. but I’m unable to do it. How can I achieve it? And FYI – whenever I click on links the page will reload.

Below is image –

enter image description here

enter image description here

Below is my code-

Html

<div class="menu-links-container">
    <ul class="navbar-nav ms-auto me-auto mb-lg-0">
        <li class="nav-item">
            <a class="nav-link" routerLink="/home" routerLinkActive="active" ariaCurrentWhenActive="page"
                id="home">Home</a>
        </li>
        <li class="nav-item">
            <a class="nav-link" routerLink="/about" routerLinkActive="active" ariaCurrentWhenActive="page"
                id="about">About Me</a>
        </li>
        <li class="nav-item">
            <a class="nav-link" routerLink="/contact" routerLinkActive="active" ariaCurrentWhenActive="page"
                id="contact">Contact Me</a>
        </li>
    </ul>
</div>


Css –

 .menu-links-container {
    order: 3;
    overflow: hidden;
    width: 100%;
    .navbar-nav {
      overflow-x: auto;
      scrollbar-width: none;
      padding: 0% 30%;
      gap: 20px;
      align-items: center;
      scroll-behavior: smooth;
      .nav-link {
        white-space: nowrap;
        transition: color 0.3s, background-color 0.3s;
      }
    }
  }

Select Newly Created Row on Create Dialog Close in Oracle APEX

I’m working with an Oracle APEX application that handles a large volume of data. To manage this, I’ve set the page size to 5 and configured the grid to display only 5 records at a time with a fixed report height of 270px.

Problem

When I try to select a newly created row on dialog close, the following code does not fetch records beyond the initial 20 (since only 20 records are loaded initially):

// Code on Dialog Close
var record = apex.region("employees_grid").widget().interactiveGrid("getViews", "grid").model.getRecord("78");
apex.region("employees_grid").widget().interactiveGrid("getViews", "grid").setSelectedRecords([record], true);
// Initialization JavaScript Function
function(config) {
    config.defaultGridViewOptions = {
        selectionStateItem: "P2_SELECTED_EMPNOS"
    };
    config.defaultModelOptions = {
        pageSize: 5
    };
    return config;
}

Issue

The above code is unable to fetch records beyond the initial 20 loaded records. How can I modify this to dynamically select the newly created row, even if it falls outside the initially loaded records?

How to Add Borders to Table Rows (Including Expanded Rows) in Ant Design When CSS Overrides Don’t Work?

I’m working with an Ant Design table that includes expandable rows. The table works as expected, but I noticed that none of the rows (main or expanded) have borders, and I’d like to add borders to make the table more visually structured. However, I’m unsure how to do this without breaking the table layout or conflicting with Ant Design’s default styles.

The main table rows and the rows in the expanded nested table don’t have borders. I want to add borders to all rows (both main and expanded tables).

Here’s the code I’m using:

 return (
    <>
      <Row  className="margin-bottom-m" gutter={[0, 10]} align="middle">
      <Col span={24}>
          <Row className="text-gray breadcrumb">
            <span onClick={() => history.push("/decarbonization/facilities")} className="c-pointer">
              Facilities
            </span>
              <>
                <span
                  onClick={() => history.push(`/user/${facility_id}`)}
                  className="c-pointer"
                >
                  &nbsp;
                </span>
                <span className="text-primary fw-600">
                  &nbsp;&nbsp;{">"} {form.getFieldValue('facility_name')}
                </span>
              </>
          </Row>
        </Col>
      </Row>
      
      <Row>
        <Col span={24}>
      <Form 
        form={form} 
        layout="vertical" 
        name="add_facility_form"
        validateTrigger={['onSubmit', 'onBlur', 'onChange']}
        onFinish={(e) => onFinish(e)}
      >
        <Col className='formstyle1'>
        <Row gutter={16}>
          <Col span={18}>
            <Form.Item
              name="facility_name"
              label={t('general.facilityName')}
              rules={[{ required: true, message: `${t('general.pleaseInputTheFacilityName')}}!` }]}
            >
              <Input placeholder= {t('general.facilityName')} />
            </Form.Item>
          </Col>
        </Row>
        <Row gutter={16}>
          <Col span={9}>
            <Form.Item  name="facility_address"
              label= {t('general.address')}>
              <GooglePlacesAutocomplete
                    form={form}
                    usage={"facilities"}
                  />
            </Form.Item>
          </Col>
          <Col span={9}>
            <Form.Item name="country" label= {t('general.country')} rules={[{ required: true, message: t('general.pleaseSelectACountry') }]}>            
              <Select placeholder={t('general.country')} onChange={handleChangeCountry} allowClear showSearch>
                {Countries.country().map((val:any, i:any) => (
                  <Option key={i} value={val}>
                    {val}
                  </Option>
                ))}
              </Select>
            </Form.Item>
          </Col>
        </Row>
        </Col>
        <Divider />
      
        <Table
          className="custom-table" 
          columns={electricityColumns}
          dataSource={electricityUsageData}
          components={components}
          rowClassName={() => 'table-row'}
          tableLayout="fixed"
          footer={() => (
            <Row>
              <Button onClick={() => addYearData(getPreviousYear())} disabled={isPreviousYearDisabled()} icon={<PlusOutlined  className='addButton' />} type="link">
                Add {getPreviousYear()} data
              </Button>
            </Row>
          )}
          expandable={{
            expandedRowRender: (record) => (
              <Table
                columns={purchaseColumns}
                dataSource={record.purchases}
                pagination={false}
                bordered={false}
                tableLayout="fixed"
              />
            ),
          }}
          pagination={false}
        />
    
        <Row justify="end">
          <Space style={{ margin: '20px 0px 0px 0px' }} wrap={true}>
            <Form.Item>
              <Button type="primary" htmlType="submit" icon={<SaveOutlined />}>
                SAVE
              </Button>
            </Form.Item>
          </Space>
        </Row>
      </Form>
      </Col>
      </Row>
      <DynamicDialog
        visibility={isModalVisible}
        onSetVisibility={setIsModalVisible}
        onCancel={handleCancel}
        content={{
          component: 
          <AddExternalEacModal 
          handleSave={handleSave} 
          handleCancel={handleCancel} 
          facilityName={facilityName} 
          selectedYear={year}
          technologies={technologies}
          />,
          footer: null,
          width: 550
      }}
        closable={true}
        className="external-eac-modal"
      />
      <DynamicInfoModal visible={openInfo} setVisible={setOpenInfo} {...infoConfig} />

      </>
  );

What’s the best way to add borders to rows while keeping the table layout intact? Is there a way to customize Ant Design styles directly for this, or should I rely on CSS overrides?

Getting request with auth token via Angular Interceptor and Intercepting further calls

I’m trying to authenticate to an API first and then “attach” the token to each one of my requests, but the one including ‘connect’.
I have the following:

Interceptor

@Injectable()
export class TokenInterceptor implements HttpInterceptor {
  constructor(private authService: AuthService) {}

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (!request.url.includes('/connect/token?grant_type=client_credentials')) {
      this.authService.isTokenExist()
      .pipe(
        catchError((error) => {
          return error;
        })
      )
      .subscribe((token: any) => {
        if (token) {
          request = request.clone({
            setHeaders: {
              Authorization: `Bearer ${token}`,
            },
          });
        }
        return next.handle(request);
      });
    }
    return next.handle(request); // here I'm hitting the point without token and I think this is the problem
  }
}

Service

import { Injectable } from '@angular/core';
import {
  HttpClient,
  HttpHeaderResponse,
  HttpHeaders,
} from '@angular/common/http';
import { environment } from '../../../environment';
import { urlString } from '../../utils/helpers';
import { Observable, catchError, of } from 'rxjs';
import { map } from 'rxjs/operators';

@Injectable({
  providedIn: 'root',
})
export class AuthService {
  constructor(private http: HttpClient) {}

  getToken(): Observable<string | null> {
    const requestBody: Request = {
      client_id: environment.client_id,
      client_secret: environment.client_secret,
      grant_type: environment.grant_type,
      scope: environment.scope,
    };
    const headers = new HttpHeaders().set(
      'Content-Type',
      'application/x-www-form-urlencoded'
    );
    const options = { headers };
    return this.http
      .post<Response>(
        `${environment.api_url}/connect/token?grant_type=client_credentials`,
        urlString(requestBody),
        options
      )
      .pipe(
        catchError((error) => {
          throw error;
        }),
        map((response: Response) => {
          this.setToken(response.access_token);
          return response.access_token;
        })
      );
  }

  getFileMetadata(fileId: number): Observable<any> {
    return this.http.get(
      `${environment.api_url}/api/v1.4/items/${fileId}/_metadata`
    );
  }

  isTokenExist(): Observable<string | null> {
    const tokenTime = localStorage.getItem('token_time');
    if (tokenTime) {
      const currentTime = new Date().getTime();
      const tokenTimeInt = parseInt(tokenTime, 10);
      if (currentTime - tokenTimeInt > 86400000) {
        return this.getToken();
      }
    } else {
      this.getToken().subscribe({
        next: (token) => {
          if (token) {
            this.setToken(token);
          }
          return of(token);
        },
        error: (error) => {
          throw error;
        }
      });
    }
    return of(localStorage.getItem('token'));
  }

  setToken(token: string): void {
    localStorage.setItem('token_', token);
    localStorage.setItem('token_time', new Date().getTime().toString());
  }
}

interface Request {
  grant_type: string;
  client_secret: string;
  client_id: string;
  scope: string;
}

interface Response {
  access_token: string;
  token_type: string;
  expires_in: number;
}

The result is that on the first-page load, I get 401, as the interceptor is just passing the request. The service returns the token on refresh, and the request passes as expected.
My question is, how can we hold the Interceptor until the token is available and then intercept all other calls?

Markdown in editor rendering? (Vue)

i have this vue component which has a textarea field for inputting markdown content and underneath i display the rendered content. But i want it to work similarly to something like Obsidian(All content is rendered in the editor field beside the line where the cursor is which should display the markdown content)

Who can i achieve this(in Vue)?

<template>
  <div class="p-2">  
    <textarea v-model="markdownText" class="w-full border rounded-md p-2 focus:outline-none resize-none"/>
    <div>
      <component 
        v-for="(node, index) in renderedNodes" 
        :key="index" 
        :is="node"
        />
    </div>
  </div>
</template>

import { ref, watch, onMounted, h } from 'vue';
import { marked } from '../lib/marked/marked';

const markdownText = ref("### Hello World!nThis is a [link](http://example.com)");
const renderedNodes = ref([]);


// Watch for changes in markdownText and re-render
watch(markdownText, async (newMarkdown) => {
  try {
    renderedNodes.value = await Promise.resolve(marked(newMarkdown));
  } catch (error) {
    console.error('Markdown parsing error:', error);
  }
});

// Initial rendering on mount
onMounted(async () => {
  try {
    renderedNodes.value = await Promise.resolve(marked(markdownText.value));
  } catch (error) {
    console.error('Initial markdown parsing error:', error);
  }
});
</script>

How to resolve execution policy issues when running npm create vite@latest command?

npm create vite@latest my-vue-app — –template vue
npm : File C:Program Filesnodejsnpm.ps1 cannot be loaded because running scripts is disabled on this system. For more information, see
about_Execution_Policies at https:/go.microsoft.com/fwlink/?LinkID=135170.
At line:1 char:1

  • npm create vite@latest my-vue-app — –template vue
  •   + CategoryInfo          : SecurityError: (:) [], PSSecurityException
      + FullyQualifiedErrorId : UnauthorizedAccess
    
    

I’m trying to create a new Vue application using Vite, but I’m encountering an issue related to execution policies. Here’s the command I’m running:

bash
npm create vite@latest my-vue-app — –template vue
However, it seems the execution policy is preventing this from working. To resolve this, I found that adding the following command beforehand bypasses the issue:

bash
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
Once I set the execution policy to bypass, the Vite project creation works as expected.
**
Question:**

  1. Is it safe to bypass the execution policy temporarily like this?

  2. Are there better or more permanent solutions to handle such issues without compromising system security?

Node.js version: 22.17
Operating System:windows 11

How can I wait for a JavaScript function to evaluation when scraping a website using Puppeteer/Node.js?

I have a website where I want to manipulate certain user inputs, generate a report by clicking a button, and download the resulting report by clicking on button.

I recorded the user behaviour (manipulation) with Chrome DevTools Recorder, exported the Puppeteer script and adapted it a bit.
Everything works fine, until the report is generated (some JavaScript function is evaluated in the back). Is there any chance to wait for this evaluation to be complete before the script tries to click something which is not yet available?

Here is the code up until I got an error (I redacted the URL for now):

        console.log('Navigating to the target page...');
        await page.goto('https://website.url', { waitUntil: 'networkidle2' });

        console.log('Clicking language selector...');
        await page.waitForSelector('div.active-lang', { visible: true });
        await page.click('div.active-lang');

        console.log('Switching to English...');
        await Promise.all([
            page.waitForNavigation({ waitUntil: 'networkidle2' }),
            page.click('li.en-gb > a')
        ]);

        console.log('Opening report...');
        await Promise.all([
            page.waitForNavigation({ waitUntil: 'networkidle2' }),
            page.click('#treeMenu\:0_4_1_3 a')
        ]);

        console.log('Selecting year...');
        await page.waitForSelector('#input > table:nth-of-type(1) span', { visible: true });
        await page.click('#input > table:nth-of-type(1) span');
        await page.waitForSelector('#yearBeg_0', { visible: true });
        await page.click('#yearBeg_0');

        console.log('Generating report...');
        await page.waitForSelector('td.action_c2 span', { visible: true });
        await page.click('td.action_c2 span', { timeout: 30000, waitUntil: 'networkidle2' });

        console.log('Exporting file...');
        await page.waitForSelector('td.action_c1 span.ui-button-text', { visible: true });
        await page.click('td.action_c1 span.ui-button-text', { timeout: 60000, waitUntil: 'networkidle2' });
        await page.screenshot({ path: 'debug.png_exporting' });

As you can see from the screenshot provided, the evaluation is still not complete:

evaluation not complete

and this is how it should look like after evaluation:

after evaluation

this is the output from Node after calling the script:

Clicking language selector...
Switching to English...
Opening report...
Selecting year...
Generating report...
Exporting file...
Hovering menu...
An error occurred: TimeoutError: Waiting for selector `li.ui-state-hover` failed: Waiting failed: 30000ms exceeded
    at new WaitTask (/home/zenz/node_modules/puppeteer/node_modules/puppeteer-core/lib/cjs/puppeteer/common/WaitTask.js:50:34)
    at IsolatedWorld.waitForFunction (/home/zenz/node_modules/puppeteer/node_modules/puppeteer-core/lib/cjs/puppeteer/api/Realm.js:25:26)
    at CSSQueryHandler.waitFor (/home/zenz/node_modules/puppeteer/node_modules/puppeteer-core/lib/cjs/puppeteer/common/QueryHandler.js:172:95)
    at async CdpFrame.waitForSelector (/home/zenz/node_modules/puppeteer/node_modules/puppeteer-core/lib/cjs/puppeteer/api/Frame.js:522:21)
    at async CdpPage.waitForSelector (/home/zenz/node_modules/puppeteer/node_modules/puppeteer-core/lib/cjs/puppeteer/api/Page.js:1304:20)
    at async /home/zenz/ShinyApps/AID/puppeteer/tasks/MD_FDI_IIP_orig.js:98:9
Browser closed.

I tried with varying timeouts, but this doesn’t seem to change anything.

Modifying response body from target proxy through http-proxy-middleware

I am trying to modify HTML body response of proxied target url, but my res.send method is not executing because onProxyRes function not waiting the proxyRes.on('end', () => { event.

const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');

const app = express();

const onProxyRes = async function  (proxyRes, req, res) {
  let body = '';
  proxyRes.on('data', (chunk) => {
    body += chunk;
  });

  proxyRes.on('end', () => {
    res.send(body + ' modified part'); // Send the modified response
  });
};

;(async() => {
  const exampleProxy = createProxyMiddleware({
    target: 'https://example.com',
    changeOrigin: true,
    on: { proxyRes: onProxyRes }
  });
  app.use('/', exampleProxy);
  
  app.listen(3000)
})()

output is the source code of https://example.com.

But if I update the function as,

const onProxyRes = async function  (proxyRes, req, res) {
  res.send('test'); // Send the modified response
};

I can set the response as test, but I need to set the response from actual target url’s response body + my modifications.. any suggestions? thanks.

What is the equivalent of `for await…of`?

I know there are plenty of resources explaining for await...of, but I don’t think I’ll ever fully grasp the concept until I see an example that works the exact same way but with more basic syntax.

Thing is, if my understanding is correct, these 2 for loops should behave the exact same way:

for(const p of iterableWithPromises) {
  const q = await p;
  // ...
}

for await (const q of iterableWithPromises) {
  // ...
}

Is that it? Is this syntax only saving us from creating a new variable inside the loop to store the promise’s result?

Adding a custom price calculator to webstore

I have 2 separate custom code liquid blocks on my product page that look like this:

For input fields for Width and Height:

<div class="product-custom-options">
  <label for="custom-width" style="display: block; margin-top: 10px;">Width (mm)</label>
  <input type="number" id="custom-width" name="properties[Width]" 
         min="1" max="3000" step="1" 
         placeholder="Enter width in mm" 
         class="product-form__input" 
         style="width: 100%; padding: 10px; margin-bottom: 10px;border-style:solid">

  <label for="custom-height" style="display: block; margin-top: 10px;">Height (mm)</label>
  <input type="number" id="custom-height" name="properties[Height]" 
         min="1" max="3000" step="1" 
         placeholder="Enter height in mm" 
         class="product-form__input" 
         style="width: 100%; padding: 10px; margin-bottom: 10px;border-style:solid">
</div>

<input type="hidden" id="hidden-width" name="properties[Width]" value="">
<input type="hidden" id="hidden-height" name="properties[Height]" value="">

For custom field for calculated price:

<div class="calculated-price" style="margin-top: 15px;display: none;">
  <strong>Calculated Price:</strong> 
  <span id="custom-price">R0.00</span>
</div>


<input type="hidden" id="hidden-calculated-price" name="properties[Calculated Price]" value="">

And I edited the code for main-product.liquid:

<script>
document.addEventListener('DOMContentLoaded', function() {
    // Set your base price per square meter
    const basePricePerSquareMeter = 50;

    // Elements
    const widthInput = document.getElementById('custom-width');
    const heightInput = document.getElementById('custom-height');
    const quantityInput = document.querySelector('.quantity__input');
    const priceBlock = document.querySelector('.price-item.price-item--regular');
    const customPriceDisplay = document.getElementById('custom-price');
    const variantSelect = document.querySelectorAll('[name="id"]');

    // Check if all elements are found
    if (!widthInput || !heightInput || !quantityInput || !customPriceDisplay) {
        console.error("One or more elements (width, height, quantity, or price display) are missing.");
        return;
    }

    const hiddenWidth = document.getElementById('hidden-width');
    const hiddenHeight = document.getElementById('hidden-height');
    const hiddenCalculatedPrice = document.getElementById('hidden-calculated-price');

    // Function to calculate and display the price
    function calculatePrice() {
        const width = parseFloat(widthInput.value) || 0;
        const height = parseFloat(heightInput.value) || 0;
        const quantity = parseInt(quantityInput.value) || 1;

        const areaInSquareMeters = (width * height) / 1000000; // Convert mm² to m²

        // Variant price adjustment if applicable
        let variantPriceAdjustment = 1;
        variantSelect.forEach((variant) => {
            if (variant.checked || variant.selected) {
                const variantData = JSON.parse(variant.getAttribute('data-variant-json'));
                variantPriceAdjustment = variantData ? variantData.price : 1;
            }
        });

        // Calculate final price
        const calculatedPrice = areaInSquareMeters * basePricePerSquareMeter * variantPriceAdjustment * quantity;

        // Update the displayed prices
        priceBlock.textContent = `R${calculatedPrice.toFixed(2)}`;
        customPriceDisplay.textContent = `R${calculatedPrice.toFixed(2)}`;

        // Update hidden fields for cart submission
        hiddenWidth.value = `${width} mm`;
        hiddenHeight.value = `${height} mm`;
        hiddenCalculatedPrice.value = `R${calculatedPrice.toFixed(2)}`;
    }

    // Event listeners for input changes
    widthInput.addEventListener('input', calculatePrice);
    heightInput.addEventListener('input', calculatePrice);
    quantityInput.addEventListener('input', calculatePrice);
    
    variantSelect.forEach((variant) => {
        variant.addEventListener('change', calculatePrice);
    });

    // Event listeners for plus and minus buttons
    const minusButton = document.querySelector('.quantity__button[name="minus"]');
    const plusButton = document.querySelector('.quantity__button[name="plus"]');

    minusButton.addEventListener('click', () => setTimeout(calculatePrice, 50));
    plusButton.addEventListener('click', () => setTimeout(calculatePrice, 50));

  const addToCartButton = document.querySelector('button[name="add"]');
    if (addToCartButton) {
        addToCartButton.addEventListener('click', function(e) {
            // Prevent default action initially to allow for price calculation
            e.preventDefault();
            // Calculate price first
            calculatePrice();

            // After calculation, submit the form now
            const form = addToCartButton.closest('form');
            if (form) {
                form.submit();
            }
        });
    }

    // Initial calculation on page load
    calculatePrice();
});
</script>

however when trying to add the item to cart. It appears as 0.00 and whatever I do I cannot get the price to show up in the cart.

Hooking Navigator object in Chrome extension detected by antibot detection

I want to spoof some attributes in the Navigator object for experimenting with anti fingerprinting by writing a Chrome extension.

I used techniques discussed here: Access variables and functions defined in page context from an extension

I tried both method 1 and 4. (code below is method 1 modified according to: Chrome Extension: Accessing `window` works on remote websites, but not possible in localhost)

While this changes the User-Agent and seems to actually work it gets detected as a bot on pages like https://www.browserscan.net/bot-detection why is that? Is there any way around it?

Note: The spoofed user agent is same as the authentic user agent to make sure that this is not the problem.

manifest.json

{
"manifest_version": 3,
"name": "Helper",
"description": "Base Level Extension",
"version": "1.0",

"background": {"service_worker": "bg.js"},

"host_permissions": ["<all_urls>"],

"permissions": [
    "scripting",
    "contentSettings",
    "tabs",
    "storage",
    "declarativeNetRequest",
    "declarativeNetRequestWithHostAccess"
],

"declarative_net_request": {
    "rule_resources": [{
        "id": "ruleset",
        "enabled": true,
        "path": "rules.json"
    }]
},

"action": {
    "default_popup": "helper.html",
    "default_icon": "helper.png"
}

bg.js

chrome.runtime.onInstalled.addListener(async () => {

const old = await chrome.scripting.getRegisteredContentScripts();

if (old[0]) await chrome.scripting.unregisterContentScripts({ids: old.map(s => s.id)});

await chrome.scripting.registerContentScripts([{
  id: 'write',
  js: ['write.js'],
  matches: ['<all_urls>'],
  runAt: 'document_start',
  world: 'MAIN',
}]);

write.js

var navigator = window.navigator;
var modifiedNavigator;

if ('userAgent' in Navigator.prototype) {
    modifiedNavigator = Navigator.prototype;

} else {
    modifiedNavigator = Object.create(navigator);
    Object.defineProperty(window, 'navigator', {
        value: modifiedNavigator,
        configurable: false,
        enumerable: false,
        writable: false
    });
}

console.info(navigator.userAgent)
console.info(navigator.appName)
console.info(navigator.appVersion)
console.info(navigator.platform)

var ua = navigator.userAgent

// I tried this
modifiedNavigator.__defineGetter__('userAgent', function () { return ua; });

// As well as this
Object.defineProperties(modifiedNavigator, {
    userAgent: {
        value: navigator.userAgent.replace(/([^)]+)/, 'Windows NT 5.1'),
        configurable: false,
        enumerable: true,
        writable: false
    }
});