enuchi / React-Google-Apps-Script

This is your boilerplate project for developing React apps inside Google Sheets, Docs, Forms and Slides projects. It's perfect for personal projects and for publishing complex add-ons in the Google Workspace Marketplace.
MIT License
1.32k stars 171 forks source link

Typescript support for custom functions #212

Closed sheldoncoates closed 4 months ago

sheldoncoates commented 5 months ago

Is there any way to support typescript in custom functions?

This is my current webpack config:

// webpack settings for copying files to the destination folder
const copyFilesConfig = {
    name: 'COPY FILES - appsscript.json',
    mode: 'production', // unnecessary for this config, but removes console warning
    entry: copyAppscriptEntry,
    output: {
        path: destination,
        publicPath,
    },
    optimization: {
        minimize: false,
    },
    plugins: [
        new CopyWebpackPlugin({
            patterns: [
                {
                    from: copyAppscriptEntry,
                    to: destination,
                },
                {
                    from: './src/server/function.js', // custom function js file
                    to: destination,
                },
            ],
        }),
    ],
}

All it does it take the js file and copies it into dist. I've attempted to convert js to ts with ts-loader but webpack adds a bunch of bootstrap and EEFI to the function file it outputs which google server doesn't like.

Just wondering if anyone has overcome this and is able to share how? Thanks!

enuchi commented 5 months ago

You should review the webpack config here in this repo. Check out the server section specifically.

enuchi commented 5 months ago

https://github.com/enuchi/React-Google-Apps-Script/blob/main/webpack.config.js#L342-L414

sheldoncoates commented 5 months ago

Do you need to include the custom function inside src/server/index.ts? When I do the custom function isn't recognized by google sheets. This is why I have the custom function file as a straight copy over - the existing webpack hasn't ever worked for me for some reason.

enuchi commented 5 months ago

Yes and it needs to be exported from src/server/index.ts in the format shown.

sheldoncoates commented 5 months ago

Doesnt seem like google sheets recognizes it as a custom function

./src/server/custom-function.js:

 * Multiplies an input value by 2.
 * @param {number} input The number to double.
 * @return The input multiplied by 2.
 * @customfunction
 */
export function DOUBLE(input) {
    return input * 2
}

./src/server/index.ts:

import * as CustomFunction from './custom-function'
const { DOUBLE } = CustomFunction

export {DOUBLE}

dist/code.js snippet

    }, (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
        /**
 * Multiplies an input value by 2.
 * @param {number} input The number to double.
 * @return The input multiplied by 2.
 * @customfunction
 */
        function DOUBLE(input) {
            return 2 * input;
        }
        __webpack_require__.r(__webpack_exports__), __webpack_require__.d(__webpack_exports__, {
            DOUBLE: () => DOUBLE
        });
    } ], __webpack_module_cache__ = {};

Any idea?

sheldoncoates commented 5 months ago

At the top of code.gs where all the global definitions are I see that the custom function doesn't have the JSDOC

var global = this;

function DOUBLE() {}

could this be why?

enuchi commented 5 months ago

This seemed to work for me -- give below a try:

// src/server/index.ts

declare global {
  var global;
}

import { DOUBLE } from './custom-function';

export { DOUBLE };

/**
 * Multiplies an input value by 2.
 * @param {number} input The number to double.
 * @return The input multiplied by 2.
 * @customfunction
 */
global.DOUBLE = DOUBLE;
enuchi commented 5 months ago

Were you able to get this to work @sheldoncoates ?

sheldoncoates commented 5 months ago

No, no matter what i did the functions werent globally exported. Had to move on to something else so i think ill have to circle back to this when i can take another look at converting to ts

sheldoncoates commented 4 months ago

@enuchi i ended getting this working now, its unfortunate that you have to specify the custom function jsdoc like that in the src/server/index.ts but what can you do 🤷 thanks for the help!

sheldoncoates commented 4 months ago

@enuchi just realized that when the file uses Google Sheet specific class/function and the file is a typescript file, it doesn't seem to recognize the uses; Cannot find name 'PropertiesService'. for example. Does this work you if you use a sheets specific class inside a ts file?

enuchi commented 4 months ago

Are you using the boilerplate from this repo?

sheldoncoates commented 4 months ago

yes, the project is based off this boilerplate. am i missing something obvious for how ts can tell what SpreadsheetApp is when building the project?

enuchi commented 4 months ago

All the types are defined in the gas-types-detailed package, which should be referenced in your tsconfig.json file: https://github.com/enuchi/React-Google-Apps-Script/blob/main/tsconfig.json#L3