google appscript based webapp is not giving results. frontend is receiving null from the backend, even though the backend is returning valid results [duplicate]

I want to create a simple web app to search a database.
google app-script based webapp is not giving results.
The issue is that the frontend is receiving null from the backend, even though the backend is returning valid results (as shown in the Execution Log).
i have tried with hard coded result, that it is showing, but not result from the search.
My index.html file is as below.

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <style>
      body { font-family: Arial, sans-serif; margin: 20px; }
      input, select, button { margin: 5px; padding: 10px; }
      table { width: 100%; border-collapse: collapse; margin-top: 20px; }
      th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
      th { background-color: #f2f2f2; }
    </style>
  </head>
  <body>
    <h1>Book Search</h1>
    <input type="text" id="searchTerm" placeholder="Enter search term">
    <select id="category">
      <option value="">Select a category</option> <!-- Default option -->
    </select>
    <button onclick="search()">Search</button>

    <table id="results">
      <thead>
        <tr>
          <th>Timestamp</th>
          <th>Date of Addition</th>
          <th>Acc No</th>
          <th>Book Title</th>
          <th>Author</th>
          <th>Book Type</th>
          <th>Volume</th>
          <th>Publication House</th>
          <th>Publication Year</th>
          <th>Pages</th>
          <th>Bill No</th>
          <th>Bill Date</th>
          <th>Price</th>
          <th>Condition</th>
          <th>Subject</th>
          <th>Almirah</th>
          <th>Rack</th>
        </tr>
      </thead>
      <tbody>
      </tbody>
    </table>

    <script>
      // Load categories into dropdown
      google.script.run
        .withSuccessHandler((categories) => {
          console.log('Categories from backend:', categories); // Log categories for debugging
          const dropdown = document.getElementById('category');

          if (!categories || categories.length === 0) {
            console.error('No categories found or categories are empty');
            return;
          }

          // Add categories to the dropdown
          categories.forEach(([category]) => {
            const option = document.createElement('option');
            option.value = category;
            option.text = category;
            dropdown.appendChild(option);
          });
        })
        .withFailureHandler((error) => {
          console.error('Error fetching categories:', error);
          alert('An error occurred while loading categories. Please check the console for details.');
        })
        .getCategories();

      // Perform search
      function search() {
        const searchTerm = document.getElementById('searchTerm').value;
        const category = document.getElementById('category').value;

        if (!searchTerm || !category) {
          alert('Please enter a search term and select a category.');
          return;
        }

        console.log('Sending request to backend with:', { searchTerm, category }); // Log request data

        google.script.run
          .withSuccessHandler((results) => {
            console.log('Results from backend:', results); // Log results for debugging
            const tbody = document.querySelector('#results tbody');
            tbody.innerHTML = ''; // Clear previous results

            if (!results || results.length === 0) {
              tbody.innerHTML = '<tr><td colspan="17">No results found.</td></tr>';
              return;
            }

            // Ensure results is an array
            if (Array.isArray(results)) {
              results.forEach(row => {
                const tr = document.createElement('tr');
                row.forEach(cell => {
                  const td = document.createElement('td');
                  td.textContent = cell;
                  tr.appendChild(td);
                });
                tbody.appendChild(tr);
              });
            } else {
              console.error('Invalid results format:', results);
              tbody.innerHTML = '<tr><td colspan="17">Invalid results format.</td></tr>';
            }
          })
          .withFailureHandler((error) => {
            console.error('Error:', error);
            alert('An error occurred. Please check the console for details.');
          })
          .searchBooks(category, searchTerm);
      }
    </script>
  </body>
</html>

My code.gs file is as below

function doGet() {
  return HtmlService.createHtmlOutputFromFile('index');
}

function getCategories() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Category');
  if (!sheet) {
    console.error('Category sheet not found');
    return [];
  }
  const data = sheet.getRange(2, 1, sheet.getLastRow() - 1, 2).getValues(); // Skip header row
  console.log('Categories:', data); // Log categories for debugging
  return data;
}

function searchBooks(category, searchTerm) {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const categorySheet = ss.getSheetByName('Category');
  const booksSheet = ss.getSheetByName('Books');

  if (!categorySheet || !booksSheet) {
    console.error('Sheets not found');
    return []; // Return an empty array if sheets are not found
  }

  // Get column number for the selected category
  const categories = categorySheet.getRange(2, 1, categorySheet.getLastRow() - 1, 2).getValues();
  const columnNumber = categories.find(([cat]) => cat === category)?.[1];

  if (!columnNumber) {
    console.error('Invalid category:', category);
    return []; // Return an empty array if category is invalid
  }

  // Search the Books sheet
  const booksData = booksSheet.getRange(2, 1, booksSheet.getLastRow() - 1, booksSheet.getLastColumn()).getValues();
  const results = booksData
    .filter(row => row[columnNumber - 1].toString().toLowerCase().includes(searchTerm.toLowerCase()))
    .map(row => row.map(cell => cell || '')); // Replace null/undefined with empty strings

  console.log('Search results:', results); // Log results for debugging
  return results;
}

THIS IS MY GOOGLE SHEET FILE
https://docs.google.com/spreadsheets/d/1jBkZie2i3Xnt1DGYL0ChAZmSgbseq_nE6V7FzqLLJ3g/edit?usp=sharing

Healthkit framework in Windows? [closed]

Is it possible to develop a native iOS app using HealthKit on Windows?
I want to create a native app that fetches data from HealthKit, but I only have a Windows PC and an iPhone. I understand that Xcode is required for iOS development, but I am looking for any possible workarounds.

What I have tried:
-Looking into Expo Go, but it doesn’t support HealthKit.
-Checking cloud Mac services, but I prefer a free solution.
-Is there any way to build and test an iOS app with HealthKit without a Mac?

Charts.js tooltip position not working properly on Zoom In

I have created a React Application.I was working on dasboard page, in which i have used chart.js for displaying data in Barchart,Pie Chart.All things was working fine,but when i try to zoom in the browser, the tooltip of the Bachart not showing properly, means when i move the cursor to the bar tooltip didn’t get displayed.but when i move the cursor to a specific point it get displayed.I am getting recursion error when i try to use the postioning function inside tooltip.
Do u have any suggestions for me . It will be a great help for me .

tooltip: {
backgroundColor: “rgba(0, 0, 0, 0.7)”,
titleFont: {
size: 12,
weight: “bold”,
},
bodyFont: {
size: 10,
},
footerFont: {
size: 8,
},
callbacks: {
label: function (tooltipItem) {
return ${tooltipItem.label}: ${tooltipItem.raw};
},
},
position: function (context) {
try {
if (!context || !context.tooltip || !context.chart) {
return { x: 0, y: 0 };
}

          const { chart, tooltip } = context;

          // Ensure canvas exists before getting bounding box
          if (!chart.canvas) {
            return { x: 0, y: 0 };
          }

          // Get bounding rectangle of the chart canvas
          const canvasRect = chart.canvas.getBoundingClientRect();
          const zoomLevel = zoomLevelRef?.current || 1;

          // Prevent recursion by avoiding unnecessary updates
          const newX = (tooltip.caretX || 0) * zoomLevel + canvasRect.left;
          const newY = (tooltip.caretY || 0) * zoomLevel + canvasRect.top;

          if (Number.isNaN(newX) || Number.isNaN(newY)) {
            return { x: 0, y: 0 }; // Return safe fallback position
          }

          return { x: Math.round(newX), y: Math.round(newY) };
        } catch (error) {
          console.error("Tooltip positioning error:", error);
          return { x: 0, y: 0 }; // Fallback to prevent crash
        }
      },
    },

PHP Leaf framework – db()->lastInsertId() returns “0”

I have issue with PHP Leaf framework database operation which returns “0” instead of last inserted record id.

My PHP version is 8.2.12.

There is a code.

app/routes/__app.php

app()->get('/apiv1/test', function () {
    $res = db()
    ->insert('item_schemas')
    ->params([
        'table_name' => 'hat',
        'created_at' => Carbon::now(),
        'updated_at' => null
    ])->execute();

    $itemSchemaId = db()->lastInsertID();

    response()->json([
        'itemSchemaId' => $itemSchemaId,
        'errors' => $res ? 'No errors' : db()->errors(),
        'res' => $res
    ]);
});

public/index.php

<?php

/*
|--------------------------------------------------------------------------
| Switch to root path
|--------------------------------------------------------------------------
|
| Point to the application root directory so leaf can accurately
| resolve app paths.
|
*/
chdir(dirname(__DIR__));

/*
|--------------------------------------------------------------------------
| Register The Auto Loader
|--------------------------------------------------------------------------
|
| Composer provides a convenient, automatically generated class loader
| for our application. We just need to utilize it! We'll require it
| into the script here so that we do not have to worry about the
| loading of any our classes "manually". Feels great to relax.
|
*/
require dirname(__DIR__) . '/vendor/autoload.php';

/*
|--------------------------------------------------------------------------
| Bring in (env)
|--------------------------------------------------------------------------
|
| Quickly use our environment variables
|
*/
try {
    DotenvDotenv::createUnsafeImmutable(dirname(__DIR__))->load();
} catch (Throwable $th) {
    trigger_error($th);
}

/*
|--------------------------------------------------------------------------
| Load application paths
|--------------------------------------------------------------------------
|
| Decline static file requests back to the PHP built-in webserver
|
*/
if (php_sapi_name() === 'cli-server') {
    $path = realpath(__DIR__ . parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH));

    if (is_string($path) && __FILE__ !== $path && is_file($path)) {
        return false;
    }

    unset($path);
}

/*
|--------------------------------------------------------------------------
| Attach blade view
|--------------------------------------------------------------------------
|
| Templating has been disabled because you chose the MVC for APIs starter.
| If you want to use blade in your application,
| you can uncomment the line below.
|
*/
// LeafConfig::attachView(LeafBlade::class);

/*
|--------------------------------------------------------------------------
| Load Leaf configuration
|--------------------------------------------------------------------------
|
| Leaf MVC allows you to customize Leaf and it's modules using
| configuration files defined in the config folder. This line
| loads the configuration files and makes them available to
| your application.
|
*/
LeafCore::loadApplicationConfig();




/*
|--------------------------------------------------------------------------
| Sync Leaf Db with ORM and connect
|--------------------------------------------------------------------------
|
| Sync Leaf Db with ORM and connect to the database
| This allows you to use Leaf Db without having
| to initialize it in your controllers.
|
| If you want to use a different connection from those
| used in your models, you can remove the line below and
| add your own connection with:
| db()->connect(...)
|
| **Uncomment the line below to use Leaf Db**
| **You don't need this line to use Leaf Auth**
*/

db()->autoConnect();

/*
|--------------------------------------------------------------------------
| Load custom libraries
|--------------------------------------------------------------------------
|
| You can load your custom libraries here. If you have
| anything defined in your lib folder, you can load
| them here. Simply uncomment the line below.
|
*/
// LeafCore::loadLibs();

/*
|--------------------------------------------------------------------------
| Run your Leaf MVC application
|--------------------------------------------------------------------------
|
| This line brings in all your routes and starts your application
|
*/

LeafCore::runApplication();

composer.json

{
    "name": "leafs/mvc",
    "version": "3.9.1",
    "description": "A lightweight PHP MVC framework powered by Leaf",
    "type": "library",
    "keywords": [
        "framework",
        "leaf",
        "leafPHP",
        "mvc",
        "leaf mvc"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "Michael Darko",
            "email": "[email protected]",
            "homepage": "https://mychi.netlify.app",
            "role": "Maintainer"
        },
        {
            "name": "Abdulbasit Rubeya",
            "email": "[email protected]",
            "homepage": "https://github.com/ibnsultan",
            "role": "Maintainer"
        }
    ],
    "require": {
            "leafs/blade": "*",
            "leafs/mvc-core": "^1.11",
            "leafs/leaf": "^3.7",
            "leafs/csrf": "*",
            "leafs/logger": "v2.0",
            "leafs/cors": "*",
            "leafs/auth": "^3.0",
            "leafs/db": "*",
            "leafs/vite": "^0.3.0",
            "leafs/form": "^3.0",
            "leafs/http": "^3.0",
            "leafs/aloe": "^2.3",
            "leafs/fs": "v2.0"
    },
    "require-dev": {
        "fakerphp/faker": "^1.16",
        "leafs/alchemy": "^2.0"
    },
    "autoload": {
        "psr-4": {
            "App\": "app/",
            "Tests\": "tests/",
            "Config\": "config/",
            "App\Http\": "app/http/",
            "App\Jobs\": "app/jobs/",
            "App\Lang\": "app/lang/",
            "App\Mail\": "app/mail/",
            "App\Views\": "app/views/",
            "App\Utils\": "app/utils/",
            "App\Events\": "app/events/",
            "App\Models\": "app/models/",
            "App\Mailers\": "app/mailers/",
            "App\Workers\": "app/workers/",
            "App\Console\": "app/console/",
            "App\Scripts\": "app/scripts/",
            "App\Helpers\": "app/helpers/",
            "App\Channels\": "app/channels/",
            "App\Services\": "app/services/",
            "App\Middleware\": "app/middleware/",
            "App\Components\": "app/components/",
            "App\Controllers\": "app/controllers/",
            "App\Notifications\": "app/notifications/",
            "App\Database\Seeds\": "app/database/seeds/",
            "App\Database\Schema\": "app/database/schema/",
            "App\Database\Factories\": "app/database/factories/"
        },
        "exclude-from-classmap": [
            "app/database/migrations"
        ]
    },
    "config": {
        "optimize-autoloader": true,
        "sort-packages": false,
        "allow-plugins": {
            "pestphp/pest-plugin": true
        }
    },
    "scripts": {
        "post-root-package-install": [
            "@php -r "file_exists('.env') || copy('.env.example', '.env');"",
            "@php -r "if (file_exists('README2.MD')) {unlink('README.MD'); rename('README2.MD', 'README.MD');}""
        ],
        "post-create-project-cmd": [
            "@php leaf key:generate"
        ]
    },
    "minimum-stability": "dev",
    "prefer-stable": true
}

app/database/migrations/2025_03_18_075024_create_item_schema.php

<?php

use LeafDatabase;
use IlluminateDatabaseSchemaBlueprint;

class CreateItemSchema extends Database
{
    /**
     * Run the migrations.
     * @return void
     */
    public function up()
    {
        if (!static::$capsule::schema()->hasTable('item_schemas')) :
            static::$capsule::schema()->create('item_schemas', function (Blueprint $table) {
                $table->id();
                $table->string('table_name')->unique();
                $table->timestamp('created_at')->nullable();
                $table->timestamp('updated_at')->nullable();
            });
        endif;
    }

    /**
     * Reverse the migrations.
     * @return void
     */
    public function down()
    {
        static::$capsule::schema()->dropIfExists('item_schemas');
    }
}

all composer packages after command

composer show -i

carbonphp/carbon-doctrine-types  2.1.0    Types to use Carbon in Doctrine
doctrine/cache                   2.2.0    PHP Doctrine Cache library is a popular cache implementation that suppor...
doctrine/dbal                    3.9.4    Powerful PHP database abstraction layer (DBAL) with many features for da...
doctrine/deprecations            1.1.4    A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 loggin...
doctrine/event-manager           2.0.1    The Doctrine Event Manager is a simple PHP event system that was built t...
doctrine/inflector               2.0.10   PHP Doctrine Inflector is a small library that can perform string manipu...
fakerphp/faker                   v1.24.1  Faker is a PHP library that generates fake data for you.
firebase/php-jwt                 v6.11.0  A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Shou...
graham-campbell/result-type      v1.1.3   An Implementation Of The Result Type
illuminate/bus                   v8.83.27 The Illuminate Bus package.
illuminate/collections           v8.83.27 The Illuminate Collections package.
illuminate/container             v8.83.27 The Illuminate Container package.
illuminate/contracts             v8.83.27 The Illuminate Contracts package.
illuminate/database              v8.83.27 The Illuminate Database package.
illuminate/events                v8.83.27 The Illuminate Events package.
illuminate/filesystem            v8.83.27 The Illuminate Filesystem package.
illuminate/macroable             v8.83.27 The Illuminate Macroable package.
illuminate/pipeline              v8.83.27 The Illuminate Pipeline package.
illuminate/support               v8.83.27 The Illuminate Support package.
illuminate/view                  v8.83.27 The Illuminate View package.
jenssegers/blade                 v1.4.0   The standalone version of Laravel's Blade templating engine for use outs...
leafs/alchemy                    2.2      Integrated testing/style fixing tool for your PHP apps
leafs/aloe                       2.5.1    Overpowered command line tool for your leaf apps.
leafs/anchor                     v1.6.2   Leaf PHP util module
leafs/auth                       v3.4.1   Leaf PHP auth helper
leafs/blade                      v4.0     Leaf PHP Framework adaptation of jenssegers/blade package
leafs/cors                       v1.2     Leaf PHP cors config
leafs/csrf                       v0.5.4   Leaf CSRF security patch for leaf anchor
leafs/date                       v2.2     Leaf PHP date module
leafs/db                         v4.0.1   Leaf PHP db module.
leafs/exception                  v3.6.3   Error handler for leaf (fork of whoops)
leafs/form                       v3.2     Simple straightup data validation
leafs/fs                         v2.0     Leaf PHP session + flash modules
leafs/http                       v3.5     Http abstraction for Leaf PHP
leafs/leaf                       v3.12    Elegant PHP for modern developers
leafs/logger                     v2.0     Leaf PHP logger utility
leafs/mvc-core                   v1.11.1  Core files specific to MVC based leaf frameworks like Leaf MVC and Leaf ...
leafs/password                   v1.0     Leaf PHP password helper
leafs/session                    v4.0.1   Leaf PHP session + flash modules
leafs/vite                       v0.3.0   Server component for Vite
nesbot/carbon                    2.73.0   An API extension for DateTime that supports 281 different languages.
nikic/php-parser                 v4.19.4  A PHP parser written in PHP
phpoption/phpoption              1.9.3    Option Type for PHP
psr/cache                        3.0.0    Common interface for caching libraries
psr/clock                        1.0.0    Common interface for reading the clock.
psr/container                    1.1.2    Common Container Interface (PHP FIG PSR-11)
psr/log                          2.0.0    Common interface for logging libraries
psr/simple-cache                 1.0.1    Common interfaces for simple caching
psy/psysh                        v0.11.22 An interactive shell for modern PHP.
symfony/console                  v5.4.47  Eases the creation of beautiful and testable command line interfaces
symfony/deprecation-contracts    v3.5.1   A generic function and convention to trigger deprecation notices
symfony/finder                   v5.4.45  Finds files and directories via an intuitive fluent interface
symfony/polyfill-ctype           v1.31.0  Symfony polyfill for ctype functions
symfony/polyfill-intl-grapheme   v1.31.0  Symfony polyfill for intl's grapheme_* functions
symfony/polyfill-intl-normalizer v1.31.0  Symfony polyfill for intl's Normalizer class and related functions
symfony/polyfill-mbstring        v1.31.0  Symfony polyfill for the Mbstring extension
symfony/polyfill-php73           v1.31.0  Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions
symfony/polyfill-php80           v1.31.0  Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions
symfony/process                  v6.4.19  Executes commands in sub-processes
symfony/service-contracts        v3.5.1   Generic abstractions related to writing services
symfony/string                   v6.4.15  Provides an object-oriented API to strings and deals with bytes, UTF-8 c...
symfony/translation              v6.4.19  Provides tools to internationalize your application
symfony/translation-contracts    v3.5.1   Generic abstractions related to translation
symfony/var-dumper               v6.4.18  Provides mechanisms for walking through any arbitrary PHP variable
symfony/yaml                     v6.4.18  Loads and dumps YAML files
vlucas/phpdotenv                 v5.6.1   Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SE...
voku/portable-ascii              1.6.1    Portable ASCII library - performance optimized (ascii) string functions ...

And result is:

{
  "itemId": "0"
}

MySQL connection is established correct and record is inserted to the database, db()->lastInsertId() should returns valid record Id. Thanks very much for help.

EDIT:

Result after var_dump:

object(PDOStatement)#36 (1) {
  ["queryString"]=>
  string(78) "INSERT INTO item_schemas (table_name,created_at,updated_at) VALUES (?,?,?)"
}

API result:

{
"itemSchemaId": "0",
  "errors": "No errors",
  "res": {
    "queryString": "INSERT INTO item_schemas 
    (table_name,created_at,updated_at) VALUES (?,?,?)"
  }
}

After Explain query:

"query": [
{
  "id": 1,
  "select_type": "INSERT",
  "table": "item_schemas",
  "partitions": null,
  "type": "ALL",
  "possible_keys": null,
  "key": null,
  "key_len": null,
  "ref": null,
  "rows": null,
  "filtered": null,
  "Extra": null
}
],

Explain query:

$query = db()->query("EXPLAIN " . "INSERT INTO item_schemas (table_name,created_at,updated_at) VALUES ('glovesssssssssssssssdsssss','2025-03-23 10:29:29',NULL)")->all();

Table structure with EXPLAIN:

{
"query": [
{
"Field": "id",
"Type": "bigint(20) unsigned",
"Null": "NO",
"Key": "PRI",
"Default": null,
"Extra": "auto_increment"
},
{
"Field": "table_name",
"Type": "varchar(255)",
"Null": "NO",
"Key": "UNI",
"Default": null,
"Extra": ""
},
{
"Field": "created_at",
"Type": "timestamp",
"Null": "YES",
"Key": "",
"Default": null,
"Extra": ""
},
{
"Field": "updated_at",
"Type": "timestamp",
"Null": "YES",
"Key": "",
"Default": null,
"Extra": ""
}
}

How to get isset() to execute MORE than once in PHP? [duplicate]

I’m trying to do something that should be simple. I want a button that every time it’s clicked to update an mysql row value to increment by 1. so click in ten times and the value is 10. I am trying to use isset() to do this, with just normal variables to test:

php:

   $amount = 0;

   if(isset($_POST['button1'])) {
   echo "button 1 clicked";
   $amount++;
   }

html:

<form method="post">
    <input class="button" type="submit" value="select" name="button1"></input>
</form>

<h1><?= $amount ?></h1>

this works, but only once. My thought was that since $_POST[‘button1’] is now set, it doesn’t execute again because it is only supposed to execute when the value is no longer null and that only happens once. so, I thought I’d try:

   unset($_POST[‘button1’]);

in the isset() block, or even:

   $_POST[‘button1’] = null;

so that the button click would hopefully redefine it, but no luck. what do I do? most questions want a button to click only once, but I want the opposite, for it to theoretically click forever. why can’t a button just call a function like in js? I know php probably isn’t the best choice for this kind of project, but is there a way?

Datatables Server Side Filtering Wrong When Have Space Character

Hello i create datatables serverside with PHP, but filtering result is wrong.
i want to show only 1 data, when i filter “epic 5” but the result show 5 data.
You can check my screenshot here : https://i.ibb.co.com/4RnRcwLg/Screenshot-1.png

When i debug SQL code show like this. Why datatables split my filtering?

SELECT
    `rank_star`.*,
    `rk`.`rank_name`,
    `usr`.`employee_username` 
FROM
    `rank_star`
    LEFT JOIN `rank` AS `rk` ON `rk`.`id_rank` = `rank_star`.`id_rank`
    LEFT JOIN `employee` AS `usr` ON `usr`.`employee_id` = `rank_star`.`created_by`
    LEFT JOIN `employee` AS `usr_up` ON `usr_up`.`employee_id` = `rank_star`.`updated_by` 
WHERE
    (
        LOWER( `rk`.`rank_name` ) LIKE % epic % 
        OR LOWER( `rank_star`.`rank_name_star` ) LIKE % epic % 
        OR LOWER( `rank_star`.`rank_star_order` ) LIKE % epic % 
        OR LOWER( `rank_star`.`created_at` ) LIKE % epic % 
        OR LOWER( `rank_star`.`updated_at` ) LIKE % epic % 
        OR LOWER( `usr`.`employee_username` ) LIKE % epic % 
    OR LOWER( `usr_up`.`employee_username` ) LIKE % epic %) 
    AND (
        LOWER( `rk`.`rank_name` ) LIKE % 5 % 
        OR LOWER( `rank_star`.`rank_name_star` ) LIKE % 5 % 
        OR LOWER( `rank_star`.`rank_star_order` ) LIKE % 5 % 
        OR LOWER( `rank_star`.`created_at` ) LIKE % 5 % 
        OR LOWER( `rank_star`.`updated_at` ) LIKE % 5 % 
        OR LOWER( `usr`.`employee_username` ) LIKE % 5 % 
    OR LOWER( `usr_up`.`employee_username` ) LIKE % 5 %) 
ORDER BY
    `rank_star`.`rank_star_order` ASC 
    LIMIT 100 OFFSET 0

This is my javasript code

$(document).ready(function(){
    $("#example").DataTable({
        search: { "bSmart": false, "bRegex": true },
        serverSide : true,
        processing : true,
        ajax : {
            url : "rank_star/res",
            type : 'POST',
            dataType : 'JSON',
            data : {_token : '{{csrf_token()}}'}
        },
        columns : [
            {data : 'act', name : 'act'},
            {data : 'rank_name', name : 'rk.rank_name'},
            {data : 'rank_name_star', name : 'rank_star.rank_name_star'},
            {data : 'rank_min_star', name : 'rank_min_star',className: "text-center"},
            {data : 'rank_max_star', name : 'rank_max_star',className: "text-center"},
            {data : 'rank_star_order', name : 'rank_star.rank_star_order',className: "text-center"},
            {data : 'created_date', name : 'created_at'},
            {data : 'updated_date', name : 'updated_at'},
            {data : 'employee_add', name : 'usr.employee_username'},
            {data : 'employee_update', name : 'usr_up.employee_username'},
        ],
        pageLength: 100,
        order: [[5, 'asc']],
    });
});

And this is my PHP Code

$data = RankStar::query()->select(
                                [
                                 'rank_star.*',
                                 'rk.rank_name',
                                 'usr.employee_username',
                                ]
                            )
                            ->leftJoin('rank as rk', 'rk.id_rank', '=', 'rank_star.id_rank')
                            ->leftJoin('employee as usr', 'usr.employee_id', '=', 'rank_star.created_by')
                            ->leftJoin('employee as usr_up', 'usr_up.employee_id', '=', 'rank_star.updated_by');
        return datatables()->eloquent($data)
        ->addColumn("act", function($row){

            $func_action ="";
            $btn_edit    = "<button type='button' title='Update' class='btn btn-primary btn-sm' onclick='do_edit("".$row->id_rank_star."")' data-toggle='modal' data-target='#update_modal'><i class='fa fa-pencil'></i></button>&nbsp;";
            $btn_delete  = "<button type='button' title='Delete' class='btn btn-danger btn-sm' onclick='do_delete("".$row->id_rank_star."")'><i class='fa fa-trash'></i></button>";
            
            if(acc_update(Session::get('ses_level'),$this->data['id_menu']) == '1'){
                     $func_action .= $btn_edit;
            }

            if(acc_delete(Session::get('ses_level'),$this->data['id_menu']) == '1'){
                    $func_action .= $btn_delete;
            }

            return "<center>".$func_action."</center>"; 
        })
        ->addColumn("rank_name", function($row){
            return @$row->rank_name;
        })
        ->addColumn("rank_name_star", function($row){
            return @$row->rank_name_star;
        })
        ->addColumn("rank_min_star", function($row){
            return @$row->rank_min_star;
        })
        ->addColumn("rank_max_star", function($row){
            return @$row->rank_max_star;
        })
        ->addColumn("rank_star_order", function($row){
            return @$row->rank_star_order;
        })
        ->addColumn("employee_add", function($row){
            return @$row->creator->employee_username;
        })
        ->addColumn("employee_update", function($row){
            return @$row->updater->employee_username;
        })
        ->addColumn("created_date", function($row){
            return get_date_indonesia($row->created_at)." ".substr($row->created_at, 10, 9);
        })
        ->addColumn("updated_date", function($row){
            return get_date_indonesia($row->updated_at)." ".substr($row->updated_at, 10, 9);
        })
        ->rawColumns(['act'])
        ->make(true);

Help me sir, thanks.

FCM Auth2 subscribe to topic erro: Authentication using

I am trying to send a notification to a group of devices (topic) usin Auth2.
So first I tried to send a message to single device, and it worked OK.

Now I want to create the topic.
So I use this code that is attached at the bottom, but I get the result:

result= {“error”:”Authentication using server key is deprecated. Please use an OAuth2 token instead.”}

The access-token is the same as I use for sending one message.

The code:

$topic="{$card_id}_{$type}_{$locale}";
$url = "https://iid.googleapis.com/iid/v1:batchAdd";
$json=["to" => "/topics/{$topic}", "registration_tokens" => [$fcm_token]];
$result=send_2_FCM($json,$url);
function send_2_FCM($data,$url)
{
  require_once('firebase_access_token.php');
  $access_token=getAccessToken();

  $headers = array(
    "Authorization: Bearer $access_token",
    "Content-Type: application/json"
  );

  $ch = curl_init();
  curl_setopt( $ch,CURLOPT_URL,$url);
  curl_setopt( $ch,CURLOPT_POST,true);
  curl_setopt( $ch,CURLOPT_HTTPHEADER,$headers);
  curl_setopt( $ch,CURLOPT_RETURNTRANSFER,true);
  curl_setopt( $ch,CURLOPT_SSL_VERIFYPEER,false);
  curl_setopt( $ch,CURLOPT_CAINFO, "cacert.pem");
  if ($data)
  {
    curl_setopt( $ch,CURLOPT_POSTFIELDS,json_encode($data));
  }
  $result = curl_exec($ch);
  $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  curl_close($ch);
  debug_log("send_2_FCM: result= $result");
  if ($result && strpos($result,'"error"')) return 0;
  return 1;
}

Getting Cannot use import statement outside a module when running test in jest

I am trying to run the following test in jest:

import request from "supertest";
import app from '../../src/app';
import QuestionService from "../../src/api/services/questionService"; 
import { mockDBQuestions } from './get-question-utils';

// Mock the QuestionService function properly
jest.mock("../../src/api/services/questionService", () => ({
    __esModule: true, // Ensure ESM compatibility
    default: {
        getQuestionsAndAnswers: jest.fn(),
    },
}));

describe("fetchAllQuestionsController", () => {
    it("should return questions with status 200", async () => {
        // Mock DB response
        const mockQuestions = mockDBQuestions;

        jest.spyOn(QuestionService, "getQuestionsAndAnswers").mockResolvedValue(mockQuestions);

        const response = await request(app).get("/questions/fetchQuestions").query({ questionType: "Onboarding" });

        expect(response.status).toBe(200);
        expect(response.body).toEqual(mockQuestions);
        expect(QuestionService.getQuestionsAndAnswers).toHaveBeenCalledWith("Onboarding");
    });

    it("should return empty set with status 200", async () => {
        jest.spyOn(QuestionService, "getQuestionsAndAnswers").mockResolvedValue([]);

        const response = await request(app).get("/questions/fetchQuestions").query({ questionType: "abcdef" });

        expect(response.status).toBe(200);
        expect(response.body).toEqual([]);
        expect(QuestionService.getQuestionsAndAnswers).toHaveBeenCalledWith("Onboarding");
    });

    it("should return status 500 on error", async () => {
        jest.spyOn(QuestionService, "getQuestionsAndAnswers").mockRejectedValue(new Error("Internal Server Error"));

        const response = await request(app).get("/questions/fetchQuestions").query({ questionType: "Onboarding" });

        expect(response.status).toBe(500);
        expect(QuestionService.getQuestionsAndAnswers).toHaveBeenCalledWith("Onboarding");
    });
});

This is my babel.config.js:

export default {
  presets: [
      ['@babel/preset-env', { targets: { node: 'current' }, modules: false}],
      '@babel/preset-typescript',
  ],
  plugins: [
      ['@babel/plugin-proposal-decorators', { legacy: true }],
      ['@babel/plugin-transform-flow-strip-types'],
      ['@babel/plugin-proposal-class-properties', { loose: true }],
  ],
};

This is my test.config.js file :

export default {
    preset: 'ts-jest/presets/default-esm',
    testEnvironment: 'node',
    testMatch: ['**/tests/**/*.test.ts'],
    moduleFileExtensions: ['ts', 'js', 'json', 'node', 'mjs', 'cjs'],
    transform: {
        '^.+\.ts$': [
            'ts-jest',
            {
                useESM: true, // Ensuring Jest treats TS as ESM
            },
        ],
    },
    extensionsToTreatAsEsm: ['.ts'],
    transformIgnorePatterns: ['node_modules/(?!supertest/)'], // Transpile 'supertest' if needed
    globals: {
        'ts-jest': {
            tsconfig: 'tsconfig.json',
            useESM: true,
        },
    },
    setupFilesAfterEnv: ['./jest.setup.ts'], // Ensure Jest setup is working
};

This is my package.json file starting :

  "name": "backendtemplate",
  "version": "1.0.0",
  "main": "index.js",
  "type": "module",
  "jest": {
    "transform": {}
  },

and this is my tsconfig.json:

{
    "compilerOptions": {
        "target": "ESNext",
        "module": "ESNext",
        "outDir": "./dist",
        "rootDir": "./src",
        "esModuleInterop": true,
        "moduleResolution": "node",
        "resolveJsonModule": true,
        "experimentalDecorators": true,
        "emitDecoratorMetadata": true,
        "useDefineForClassFields": false,
        "allowSyntheticDefaultImports": true,
        "forceConsistentCasingInFileNames": true,
        "noEmit": true,
        "allowImportingTsExtensions": true,
        "strict": true,
        "noImplicitAny": true,
        "strictNullChecks": true,
        "skipLibCheck": true,
        "sourceMap": true,
        "removeComments": true,
        "noEmitOnError": true,
        "noUnusedLocals": true,
        "noUnusedParameters": true,
        "noImplicitReturns": true,
        "types": ["node"],
        "strictPropertyInitialization": false,
    },
    "include": ["src/**/*"],
    "exclude": ["node_modules", "dist"]
}

I am getting the following error when trying to run my test case:

(dev-serve/api) [dynodatingappbe:user_profile_edit_api] % npm run test                         

> [email protected] test
> jest

 PASS  tests/UserProfileEditModule/update-user-profile.test.ts
 PASS  tests/server.test.ts
 FAIL  tests/QuestionModule/get-questions.test.ts
  ● Test suite failed to run

    Jest encountered an unexpected token

    Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.

    Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.

    By default "node_modules" folder is ignored by transformers.

    Here's what you can do:
     • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
     • If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/configuration
    For information about custom transformations, see:
    https://jestjs.io/docs/code-transformation

    Details:

    /Users/rahul.negi/personal/Dyno/dynodatingappbe/tests/QuestionModule/get-questions.test.ts:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import request from "supertest";
                                                                                      ^^^^^^

    SyntaxError: Cannot use import statement outside a module

      at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1505:14)

Test Suites: 1 failed, 2 passed, 3 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        0.143 s, estimated 1 s
Ran all test suites.

What am I missing which is causing this issue?

So far I have tried the following methods :

  1. Tried to rename babel.config.js to babel.config.cjs
  2. Tried to Ensure that "module": "ESNext" and "moduleResolution": "node" are correctly set in tsconfig.json
  3. Tried adding transformIgnorePatterns: ['node_modules/(?!supertest/)'], in test.config.js file.

midtrans payment gateway stop default redirect

I am integrating Snap Midtrans into my application, using Laravel as the backend and React as the frontend. The application follows a single-page app (SPA) concept, meaning page transitions are handled by react-router/react-router-dom without reloading, refreshing, or redirecting the web page.

Currently, I am adding the Snap feature to the application, but I am facing difficulties because every time a user completes the payment method selection, Snap redirects the application to the URL specified in the Midtrans Dashboard. This redirection disrupts my application’s state. However, I have already used JS callbacks, specifically the onPending option. As stated in the documentation:

If Merchant use snap.js JS callbacks (onPending, onSuccess, onError), those JS callbacks will be triggered instead of redirection.

I have tried removing the Finish URL from the dashboard and overriding the Finish URL through the backend, but Snap still redirects (this time to the application’s main frontend page). I have also checked the documentation, but there seems to be no option to disable the redirection to the Finish URL.

I would appreciate any guidance. Thank you.