@gasboost/vite 1.0.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +198 -0
- package/dist/dev.d.ts +3 -2
- package/dist/gasboost.d.ts +3 -0
- package/dist/globals.d.ts +2 -2
- package/dist/index.js +137 -122
- package/dist/loadAppsScript.d.ts +4 -0
- package/dist/runtime.d.ts +3 -0
- package/package.json +5 -2
- package/dist/analyzer.d.ts +0 -6
package/README.md
CHANGED
|
@@ -603,6 +603,152 @@ URL encoded な RPC 名も decode されます。
|
|
|
603
603
|
|
|
604
604
|
---
|
|
605
605
|
|
|
606
|
+
## Client Transport
|
|
607
|
+
|
|
608
|
+
`@gasboost/client` を利用している場合、dev plugin はローカル開発時の transport を自動で Local RPC に切り替えます。
|
|
609
|
+
|
|
610
|
+
アプリケーション側では development / production を判定する必要はありません。
|
|
611
|
+
|
|
612
|
+
```ts
|
|
613
|
+
import { appsScriptClient } from "@gasboost/client";
|
|
614
|
+
import type { App } from "./server";
|
|
615
|
+
|
|
616
|
+
const { client } = appsScriptClient<App>();
|
|
617
|
+
|
|
618
|
+
const result = await client.sum(1, 2);
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
Vite Dev Server 上では、`appsScriptClient()` に transport が指定されていない場合、dev plugin が自動的に `FetchTransport` を適用します。
|
|
622
|
+
|
|
623
|
+
```text
|
|
624
|
+
appsScriptClient()
|
|
625
|
+
↓
|
|
626
|
+
FetchTransport
|
|
627
|
+
↓
|
|
628
|
+
POST /__gasboost/{rpcName}
|
|
629
|
+
↓
|
|
630
|
+
AppsScript.dispatch()
|
|
631
|
+
```
|
|
632
|
+
|
|
633
|
+
そのため、ローカル開発用に transport を切り替えるコードを書く必要はありません。
|
|
634
|
+
|
|
635
|
+
```ts
|
|
636
|
+
// 不要
|
|
637
|
+
appsScriptClient({
|
|
638
|
+
transport: import.meta.env.DEV
|
|
639
|
+
? new FetchTransport({
|
|
640
|
+
endpoint: "/__gasboost",
|
|
641
|
+
})
|
|
642
|
+
: new AppsScriptTransport(),
|
|
643
|
+
});
|
|
644
|
+
```
|
|
645
|
+
|
|
646
|
+
production build では dev plugin による差し替えは行われません。
|
|
647
|
+
|
|
648
|
+
GAS 上では `appsScriptClient()` のデフォルトである `AppsScriptTransport` がそのまま利用されます。
|
|
649
|
+
|
|
650
|
+
```text
|
|
651
|
+
appsScriptClient()
|
|
652
|
+
↓
|
|
653
|
+
AppsScriptTransport
|
|
654
|
+
↓
|
|
655
|
+
google.script.run
|
|
656
|
+
```
|
|
657
|
+
|
|
658
|
+
つまり、同じ application code のまま local development と GAS production の両方で利用できます。
|
|
659
|
+
|
|
660
|
+
```ts
|
|
661
|
+
const { client } = appsScriptClient<App>();
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
また、明示的に `transport` を指定した場合はその transport が優先されます。
|
|
665
|
+
|
|
666
|
+
```ts
|
|
667
|
+
const { client } = appsScriptClient<App>({
|
|
668
|
+
transport: customTransport,
|
|
669
|
+
});
|
|
670
|
+
```
|
|
671
|
+
|
|
672
|
+
dev plugin が明示指定された transport を上書きすることはありません。
|
|
673
|
+
|
|
674
|
+
---
|
|
675
|
+
|
|
676
|
+
## HtmlTemplate variables
|
|
677
|
+
|
|
678
|
+
GAS の `HtmlTemplate` では、`<?= variable ?>` を使用してサーバー側の値を HTML に埋め込めます。
|
|
679
|
+
|
|
680
|
+
```html
|
|
681
|
+
<script>
|
|
682
|
+
const variables = "<?= variables ?>";
|
|
683
|
+
</script>
|
|
684
|
+
```
|
|
685
|
+
|
|
686
|
+
GAS 上では `HtmlTemplate` によって評価されますが、Vite Dev Server では GAS のテンプレート処理が実行されません。
|
|
687
|
+
|
|
688
|
+
`@gasboost/vite` では、`template` オプションを指定することで、開発時にこれらの template variables を置換できます。
|
|
689
|
+
|
|
690
|
+
```ts
|
|
691
|
+
import { gasboost } from "@gasboost/vite";
|
|
692
|
+
import { defineConfig } from "vite";
|
|
693
|
+
|
|
694
|
+
export default defineConfig({
|
|
695
|
+
plugins: [
|
|
696
|
+
gasboost({
|
|
697
|
+
entry: "./src/backend/main.ts",
|
|
698
|
+
template: {
|
|
699
|
+
variables: JSON.stringify({
|
|
700
|
+
scriptId: "local-script-id",
|
|
701
|
+
isSetupCompleted: true,
|
|
702
|
+
isTermsAccepted: true,
|
|
703
|
+
}),
|
|
704
|
+
},
|
|
705
|
+
}).dev,
|
|
706
|
+
],
|
|
707
|
+
});
|
|
708
|
+
```
|
|
709
|
+
|
|
710
|
+
例えば、次の HTML は、
|
|
711
|
+
|
|
712
|
+
```html
|
|
713
|
+
<script>
|
|
714
|
+
const variables = "<?= variables ?>";
|
|
715
|
+
</script>
|
|
716
|
+
```
|
|
717
|
+
|
|
718
|
+
Vite の開発環境では次のように変換されます。
|
|
719
|
+
|
|
720
|
+
```html
|
|
721
|
+
<script>
|
|
722
|
+
const variables =
|
|
723
|
+
'{"scriptId":"local-script-id","isSetupCompleted":true,"isTermsAccepted":true}';
|
|
724
|
+
</script>
|
|
725
|
+
```
|
|
726
|
+
|
|
727
|
+
複数の template variable も指定できます。
|
|
728
|
+
|
|
729
|
+
```ts
|
|
730
|
+
gasboost({
|
|
731
|
+
entry: "./src/backend/main.ts",
|
|
732
|
+
template: {
|
|
733
|
+
environment: "development",
|
|
734
|
+
userName: "Tiger",
|
|
735
|
+
},
|
|
736
|
+
});
|
|
737
|
+
```
|
|
738
|
+
|
|
739
|
+
```html
|
|
740
|
+
<p>Environment: <?= environment ?></p>
|
|
741
|
+
<p>User: <?= userName ?></p>
|
|
742
|
+
```
|
|
743
|
+
|
|
744
|
+
`template` の型は `Record<string, string>` です。
|
|
745
|
+
|
|
746
|
+
値の serialize は `@gasboost/vite` では行いません。オブジェクトなどを埋め込む場合は、利用側で `JSON.stringify()` などを使用して文字列へ変換してください。
|
|
747
|
+
|
|
748
|
+
`template` による置換は Vite Dev Server でのみ行われます。production build では値を埋め込まず、GAS 上で実際の `HtmlTemplate` が template expression を評価します。
|
|
749
|
+
|
|
750
|
+
---
|
|
751
|
+
|
|
606
752
|
# build と dev の責務
|
|
607
753
|
|
|
608
754
|
```text
|
|
@@ -643,6 +789,58 @@ export default defineConfig(({ mode }) => {
|
|
|
643
789
|
|
|
644
790
|
`build` を通常の frontend build に含めると、server entry が Vite の build input になるため、frontend と backend の build は分離してください。
|
|
645
791
|
|
|
792
|
+
---
|
|
793
|
+
|
|
794
|
+
## GAS ランタイム
|
|
795
|
+
|
|
796
|
+
`@gasboost/vite` は、build 時と local RPC 実行時に server entry を実際に評価します。
|
|
797
|
+
|
|
798
|
+
一般的な GAS API は、デフォルトのローカルランタイムから提供されます。
|
|
799
|
+
|
|
800
|
+
```ts
|
|
801
|
+
import { gasboost } from "@gasboost/vite";
|
|
802
|
+
|
|
803
|
+
export default gasboost({
|
|
804
|
+
entry: "./src/server.ts",
|
|
805
|
+
});
|
|
806
|
+
```
|
|
807
|
+
|
|
808
|
+
entry の初期化時に追加の GAS API が必要な場合は、`runtime` から差し込めます。
|
|
809
|
+
|
|
810
|
+
```ts
|
|
811
|
+
import { SpreadsheetAppStub } from "@gasboost/sheetorm";
|
|
812
|
+
import { gasboost } from "@gasboost/vite";
|
|
813
|
+
|
|
814
|
+
export default gasboost({
|
|
815
|
+
entry: "./src/server.ts",
|
|
816
|
+
runtime: {
|
|
817
|
+
SpreadsheetApp: SpreadsheetAppStub,
|
|
818
|
+
},
|
|
819
|
+
});
|
|
820
|
+
```
|
|
821
|
+
|
|
822
|
+
`runtime` に渡した値は、デフォルトのローカルランタイムを上書きします。
|
|
823
|
+
|
|
824
|
+
このランタイムは build 時の entry 評価と、local RPC 実行時の両方で利用されます。
|
|
825
|
+
|
|
826
|
+
基本的には、module 初期化時に必要な API だけを差し込み、実際の GAS API 呼び出しは handler 実行時まで遅延させることを推奨します。
|
|
827
|
+
|
|
828
|
+
## ランタイム解析
|
|
829
|
+
|
|
830
|
+
GET / POST / RPC の登録状態は、entry ファイルを静的解析するのではなく、実際に評価された `AppsScript` インスタンスから取得します。
|
|
831
|
+
|
|
832
|
+
そのため、import 先、ヘルパー関数、loop、`AppsScript.calls()` 経由の登録にも対応できます。
|
|
833
|
+
|
|
834
|
+
```ts
|
|
835
|
+
const app = new AppsScript();
|
|
836
|
+
|
|
837
|
+
for (const [name, handler] of Object.entries(handlers)) {
|
|
838
|
+
app.call(name, handler);
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
export default app;
|
|
842
|
+
```
|
|
843
|
+
|
|
646
844
|
## 関連パッケージ
|
|
647
845
|
|
|
648
846
|
- `@gasboost/app` — GAS バックエンドランタイムと RPC 定義
|
package/dist/dev.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import type
|
|
2
|
-
|
|
1
|
+
import { type Plugin } from "vite";
|
|
2
|
+
import type { GasboostOptions } from "./gasboost";
|
|
3
|
+
export declare function createDevPlugin(options: GasboostOptions): Plugin;
|
package/dist/gasboost.d.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import type { Plugin } from "vite";
|
|
2
|
+
export type GasRuntime = Readonly<Record<string, unknown>>;
|
|
2
3
|
export interface GasboostOptions {
|
|
3
4
|
entry: string;
|
|
4
5
|
envDir?: string;
|
|
6
|
+
runtime?: GasRuntime;
|
|
7
|
+
template?: Record<string, string>;
|
|
5
8
|
}
|
|
6
9
|
export declare function gasboost(options: GasboostOptions): {
|
|
7
10
|
build: Plugin;
|
package/dist/globals.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare function createGlobalCode(analysis:
|
|
1
|
+
import type { AppsScriptDescription } from "@gasboost/app";
|
|
2
|
+
export declare function createGlobalCode(analysis: AppsScriptDescription): string;
|
package/dist/index.js
CHANGED
|
@@ -1,91 +1,12 @@
|
|
|
1
|
-
import e from "node:
|
|
2
|
-
import t from "
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { API as l } from "typescript/unstable/sync";
|
|
6
|
-
//#region src/analyzer.ts
|
|
7
|
-
function u(r) {
|
|
8
|
-
let i = t.resolve(r);
|
|
9
|
-
if (!e.existsSync(i)) throw Error(`Entry file not found: ${i}`);
|
|
10
|
-
let s = d(i, e.readFileSync(i, "utf8")), c = f(s);
|
|
11
|
-
if (c.length === 0) throw Error("AppsScript instance not found.");
|
|
12
|
-
if (c.length > 1) throw Error("Multiple AppsScript instances found in entry.");
|
|
13
|
-
let l = c[0];
|
|
14
|
-
g(s, l);
|
|
15
|
-
let u = {
|
|
16
|
-
hasGet: !1,
|
|
17
|
-
hasPost: !1,
|
|
18
|
-
calls: []
|
|
19
|
-
}, p = /* @__PURE__ */ new Set();
|
|
20
|
-
function m(e) {
|
|
21
|
-
if (!a(e.expression)) return;
|
|
22
|
-
let t = e.expression, n = t.name.text;
|
|
23
|
-
if (!h(t.expression, l)) return;
|
|
24
|
-
if (n === "get") {
|
|
25
|
-
if (u.hasGet) throw Error("Duplicate GET handler registration.");
|
|
26
|
-
u.hasGet = !0;
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
if (n === "post") {
|
|
30
|
-
if (u.hasPost) throw Error("Duplicate POST handler registration.");
|
|
31
|
-
u.hasPost = !0;
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
if (n !== "call") return;
|
|
35
|
-
let r = e.arguments[0];
|
|
36
|
-
if (!r) throw Error(".call() requires a function name.");
|
|
37
|
-
if (!o(r)) throw Error(".call() function name must be a string literal.");
|
|
38
|
-
if (p.has(r.text)) throw Error(`Duplicate RPC registration: "${r.text}".`);
|
|
39
|
-
p.add(r.text), u.calls.unshift(r.text);
|
|
40
|
-
}
|
|
41
|
-
function _(e) {
|
|
42
|
-
n(e) && m(e), e.forEachChild(_);
|
|
43
|
-
}
|
|
44
|
-
return _(s), u;
|
|
45
|
-
}
|
|
46
|
-
function d(e, t) {
|
|
47
|
-
let n = "/entry.ts", r = "/tsconfig.json", i = c({
|
|
48
|
-
[r]: JSON.stringify({ files: [n] }),
|
|
49
|
-
[n]: t
|
|
50
|
-
}), a = new l({
|
|
51
|
-
cwd: "/",
|
|
52
|
-
fs: i
|
|
53
|
-
}).updateSnapshot({ openProject: r }).getProject(r);
|
|
54
|
-
if (!a) throw Error("Failed to create TypeScript project.");
|
|
55
|
-
let o = a.program.getSourceFile(n);
|
|
56
|
-
if (!o) throw Error(`Failed to parse entry: ${e}`);
|
|
57
|
-
return o;
|
|
58
|
-
}
|
|
59
|
-
function f(e) {
|
|
60
|
-
let t = [];
|
|
61
|
-
function n(e) {
|
|
62
|
-
s(e) && p(e) && t.push(e.name.text), e.forEachChild(n);
|
|
63
|
-
}
|
|
64
|
-
return n(e), t;
|
|
65
|
-
}
|
|
66
|
-
function p(e) {
|
|
67
|
-
return !r(e.name) || !e.initializer ? !1 : m(e.initializer);
|
|
68
|
-
}
|
|
69
|
-
function m(e) {
|
|
70
|
-
return i(e) && r(e.expression) && e.expression.text === "AppsScript" ? !0 : n(e) && a(e.expression) ? m(e.expression.expression) : !1;
|
|
71
|
-
}
|
|
72
|
-
function h(e, t) {
|
|
73
|
-
return r(e) && e.text === t || i(e) && r(e.expression) && e.expression.text === "AppsScript" ? !0 : n(e) && a(e.expression) ? h(e.expression.expression, t) : !1;
|
|
74
|
-
}
|
|
75
|
-
function g(e, t) {
|
|
76
|
-
let n = !1;
|
|
77
|
-
for (let r of e.statements) if (r.getText() === `export default ${t};`) {
|
|
78
|
-
n = !0;
|
|
79
|
-
break;
|
|
80
|
-
}
|
|
81
|
-
if (!n) throw Error("AppsScript instance must be default exported.");
|
|
82
|
-
}
|
|
83
|
-
//#endregion
|
|
1
|
+
import e from "node:path";
|
|
2
|
+
import { createServer as t, isRunnableDevEnvironment as n } from "vite";
|
|
3
|
+
import { InMemoryCacheService as r, InMemoryContext as i, InMemoryPropertiesService as a, InMemorySession as o, SecurityPolicy as s } from "@gasboost/fake-core";
|
|
4
|
+
import { NodeUtilities as c } from "@gasboost/fake-node";
|
|
84
5
|
//#region src/config.ts
|
|
85
|
-
function
|
|
86
|
-
let n =
|
|
6
|
+
function l(t) {
|
|
7
|
+
let n = e.resolve(t.entry);
|
|
87
8
|
return {
|
|
88
|
-
envDir:
|
|
9
|
+
envDir: t.envDir,
|
|
89
10
|
build: {
|
|
90
11
|
target: "es2019",
|
|
91
12
|
outDir: "dist",
|
|
@@ -94,7 +15,7 @@ function _(e) {
|
|
|
94
15
|
input: n,
|
|
95
16
|
output: {
|
|
96
17
|
format: "cjs",
|
|
97
|
-
entryFileNames:
|
|
18
|
+
entryFileNames: e.basename(n, e.extname(n)) + ".js"
|
|
98
19
|
}
|
|
99
20
|
}
|
|
100
21
|
}
|
|
@@ -102,75 +23,157 @@ function _(e) {
|
|
|
102
23
|
}
|
|
103
24
|
//#endregion
|
|
104
25
|
//#region src/globals.ts
|
|
105
|
-
var
|
|
106
|
-
function
|
|
107
|
-
if (
|
|
26
|
+
var u = /* @__PURE__ */ new Set(["doGet", "doPost"]);
|
|
27
|
+
function d(e) {
|
|
28
|
+
if (u.has(e)) throw Error(`RPC name "${e}" is reserved by Google Apps Script.`);
|
|
108
29
|
if (!/^[$A-Z_a-z][$\w]*$/u.test(e)) throw Error(`RPC name "${e}" is not a valid JavaScript identifier.`);
|
|
109
30
|
}
|
|
110
|
-
function
|
|
31
|
+
function f(e) {
|
|
111
32
|
let t = [];
|
|
112
33
|
e.hasGet && t.push("function doGet() {}"), e.hasPost && t.push("function doPost() {}");
|
|
113
|
-
for (let n of e.calls)
|
|
34
|
+
for (let n of e.calls) d(n), t.push(`function ${n}() {}`);
|
|
114
35
|
return t.join("\n");
|
|
115
36
|
}
|
|
116
37
|
//#endregion
|
|
38
|
+
//#region src/runtime.ts
|
|
39
|
+
var p = new i("", "", {
|
|
40
|
+
type: "WEB_APP",
|
|
41
|
+
executeAs: "USER"
|
|
42
|
+
}, new s([]), "en", "UTC"), m = {
|
|
43
|
+
CacheService: new r(),
|
|
44
|
+
PropertiesService: new a(),
|
|
45
|
+
Session: new o(p),
|
|
46
|
+
Utilities: new c()
|
|
47
|
+
};
|
|
48
|
+
function h(e = {}) {
|
|
49
|
+
Object.assign(globalThis, {
|
|
50
|
+
...m,
|
|
51
|
+
...e
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
//#endregion
|
|
55
|
+
//#region src/loadAppsScript.ts
|
|
56
|
+
async function g(e, r) {
|
|
57
|
+
h(e.runtime);
|
|
58
|
+
let i = await t({
|
|
59
|
+
configFile: !1,
|
|
60
|
+
root: r.root,
|
|
61
|
+
mode: r.mode,
|
|
62
|
+
envDir: e.envDir,
|
|
63
|
+
appType: "custom",
|
|
64
|
+
ssr: { external: ["@gasboost/app"] },
|
|
65
|
+
server: {
|
|
66
|
+
middlewareMode: !0,
|
|
67
|
+
hmr: !1
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
try {
|
|
71
|
+
let t = i.environments.ssr;
|
|
72
|
+
if (!n(t)) throw Error("Vite SSR environment is not runnable.");
|
|
73
|
+
let r = await t.runner.import(e.entry);
|
|
74
|
+
if (!r.default) throw Error("AppsScript entry must have a default export.");
|
|
75
|
+
return r.default.describe();
|
|
76
|
+
} finally {
|
|
77
|
+
await i.close();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
//#endregion
|
|
117
81
|
//#region src/build.ts
|
|
118
|
-
function
|
|
119
|
-
let t;
|
|
82
|
+
function _(e) {
|
|
83
|
+
let t, n;
|
|
120
84
|
return {
|
|
121
85
|
name: "gasboost:build",
|
|
122
86
|
apply: "build",
|
|
123
87
|
config() {
|
|
124
|
-
return
|
|
88
|
+
return l(e);
|
|
89
|
+
},
|
|
90
|
+
configResolved(e) {
|
|
91
|
+
t = e;
|
|
125
92
|
},
|
|
126
|
-
buildStart() {
|
|
127
|
-
|
|
93
|
+
async buildStart() {
|
|
94
|
+
n = await g(e, t);
|
|
128
95
|
},
|
|
129
|
-
generateBundle(e,
|
|
130
|
-
let r =
|
|
131
|
-
for (let e of Object.values(
|
|
96
|
+
generateBundle(e, t) {
|
|
97
|
+
let r = f(n);
|
|
98
|
+
for (let e of Object.values(t)) e.type === "chunk" && e.isEntry && (e.code = `${r}\n\n${e.code}`);
|
|
132
99
|
}
|
|
133
100
|
};
|
|
134
101
|
}
|
|
135
102
|
//#endregion
|
|
136
103
|
//#region src/dev.ts
|
|
137
|
-
var
|
|
104
|
+
var v = class extends Error {
|
|
138
105
|
constructor(e) {
|
|
139
106
|
super(e), this.name = "InvalidRpcRequestError";
|
|
140
107
|
}
|
|
141
|
-
};
|
|
142
|
-
function
|
|
108
|
+
}, y = "@gasboost/client", b = "\0gasboost:client", x = "/__gasboost";
|
|
109
|
+
function S(e) {
|
|
110
|
+
let { runtime: t, template: r } = e, i;
|
|
143
111
|
return {
|
|
144
112
|
name: "gasboost:dev",
|
|
145
113
|
apply: "serve",
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
114
|
+
enforce: "pre",
|
|
115
|
+
async resolveId(e, t, n) {
|
|
116
|
+
if (e !== y || this.environment.config.consumer !== "client") return null;
|
|
117
|
+
let r = await this.resolve(e, t, {
|
|
118
|
+
...n,
|
|
119
|
+
skipSelf: !0
|
|
120
|
+
});
|
|
121
|
+
return r ? (i = r.id, b) : null;
|
|
122
|
+
},
|
|
123
|
+
load(e) {
|
|
124
|
+
if (e !== b) return null;
|
|
125
|
+
if (!i) throw Error("@gasboost/client could not be resolved.");
|
|
126
|
+
let t = JSON.stringify(i);
|
|
127
|
+
return `
|
|
128
|
+
import {
|
|
129
|
+
appsScriptClient as originalAppsScriptClient,
|
|
130
|
+
FetchTransport,
|
|
131
|
+
} from ${t};
|
|
132
|
+
|
|
133
|
+
export * from ${t};
|
|
134
|
+
|
|
135
|
+
export function appsScriptClient(options = {}) {
|
|
136
|
+
return originalAppsScriptClient({
|
|
137
|
+
...options,
|
|
138
|
+
transport:
|
|
139
|
+
options.transport ??
|
|
140
|
+
new FetchTransport({
|
|
141
|
+
endpoint: ${JSON.stringify(x)},
|
|
142
|
+
}),
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
`;
|
|
146
|
+
},
|
|
147
|
+
configureServer(r) {
|
|
148
|
+
h(t), r.middlewares.use(async (t, i, a) => {
|
|
149
|
+
if (!t.url) {
|
|
150
|
+
a();
|
|
150
151
|
return;
|
|
151
152
|
}
|
|
152
|
-
let
|
|
153
|
-
if (!
|
|
154
|
-
|
|
153
|
+
let o = t.url.split("?")[0], s = `${x}/`;
|
|
154
|
+
if (!o.startsWith(s)) {
|
|
155
|
+
a();
|
|
155
156
|
return;
|
|
156
157
|
}
|
|
157
|
-
let
|
|
158
|
-
if (!
|
|
159
|
-
|
|
158
|
+
let c = o.slice(s.length);
|
|
159
|
+
if (!c || c.includes("/")) {
|
|
160
|
+
a();
|
|
160
161
|
return;
|
|
161
162
|
}
|
|
162
|
-
if (
|
|
163
|
-
|
|
163
|
+
if (t.method !== "POST") {
|
|
164
|
+
i.statusCode = 405, i.setHeader("Content-Type", "application/json; charset=utf-8"), i.end(JSON.stringify({ error: {
|
|
164
165
|
name: "MethodNotAllowedError",
|
|
165
166
|
message: "Only POST is allowed."
|
|
166
167
|
} }));
|
|
167
168
|
return;
|
|
168
169
|
}
|
|
169
170
|
try {
|
|
170
|
-
let { args:
|
|
171
|
-
|
|
171
|
+
let { args: a } = await w(t), o = r.environments.ssr;
|
|
172
|
+
if (!n(o)) throw Error("Vite SSR environment is not runnable.");
|
|
173
|
+
let s = await (await o.runner.import(e.entry)).default.dispatch(decodeURIComponent(c), ...a);
|
|
174
|
+
i.statusCode = 200, i.setHeader("Content-Type", "application/json; charset=utf-8"), i.end(s.contents);
|
|
172
175
|
} catch (e) {
|
|
173
|
-
|
|
176
|
+
i.statusCode = e instanceof v ? 400 : 500, i.setHeader("Content-Type", "application/json; charset=utf-8"), i.end(JSON.stringify({ error: e instanceof Error ? {
|
|
174
177
|
name: e.name,
|
|
175
178
|
message: e.message,
|
|
176
179
|
stack: e.stack
|
|
@@ -180,9 +183,21 @@ function C(e) {
|
|
|
180
183
|
} }));
|
|
181
184
|
}
|
|
182
185
|
});
|
|
186
|
+
},
|
|
187
|
+
transformIndexHtml(e) {
|
|
188
|
+
if (!r) return e;
|
|
189
|
+
let t = e;
|
|
190
|
+
for (let [e, n] of Object.entries(r)) {
|
|
191
|
+
let r = RegExp(`<\\?=\\s*${C(e)}\\s*\\?>`, "g");
|
|
192
|
+
t = t.replace(r, () => n);
|
|
193
|
+
}
|
|
194
|
+
return t;
|
|
183
195
|
}
|
|
184
196
|
};
|
|
185
197
|
}
|
|
198
|
+
function C(e) {
|
|
199
|
+
return e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
200
|
+
}
|
|
186
201
|
function w(e) {
|
|
187
202
|
return new Promise((t, n) => {
|
|
188
203
|
let r = [];
|
|
@@ -198,11 +213,11 @@ function w(e) {
|
|
|
198
213
|
try {
|
|
199
214
|
i = JSON.parse(e);
|
|
200
215
|
} catch {
|
|
201
|
-
n(new
|
|
216
|
+
n(new v("Invalid RPC request body. Expected valid JSON."));
|
|
202
217
|
return;
|
|
203
218
|
}
|
|
204
219
|
if (typeof i != "object" || !i || !("args" in i) || !Array.isArray(i.args)) {
|
|
205
|
-
n(new
|
|
220
|
+
n(new v("Invalid RPC request body. Expected { args: unknown[] }."));
|
|
206
221
|
return;
|
|
207
222
|
}
|
|
208
223
|
t({ args: i.args });
|
|
@@ -213,8 +228,8 @@ function w(e) {
|
|
|
213
228
|
//#region src/gasboost.ts
|
|
214
229
|
function T(e) {
|
|
215
230
|
return {
|
|
216
|
-
build:
|
|
217
|
-
dev:
|
|
231
|
+
build: _(e),
|
|
232
|
+
dev: S(e)
|
|
218
233
|
};
|
|
219
234
|
}
|
|
220
235
|
//#endregion
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { AppsScriptDescription } from "@gasboost/app";
|
|
2
|
+
import { type ResolvedConfig } from "vite";
|
|
3
|
+
import type { GasboostOptions } from "./gasboost";
|
|
4
|
+
export declare function loadAppsScript(options: GasboostOptions, config: ResolvedConfig): Promise<AppsScriptDescription>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gasboost/vite",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "A Vite plugin for building @gasboost/app applications for Google Apps Script.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"google-apps-script",
|
|
@@ -33,11 +33,14 @@
|
|
|
33
33
|
},
|
|
34
34
|
"type": "module",
|
|
35
35
|
"devDependencies": {
|
|
36
|
+
"@types/google-apps-script": "^2.0.12",
|
|
36
37
|
"vite": "^8.2.2"
|
|
37
38
|
},
|
|
38
39
|
"dependencies": {
|
|
40
|
+
"@gasboost/fake-core": "^0.1.2",
|
|
41
|
+
"@gasboost/fake-node": "^0.1.2",
|
|
39
42
|
"typescript": "^7.0.2",
|
|
40
|
-
"@gasboost/app": "1.0
|
|
43
|
+
"@gasboost/app": "1.3.0"
|
|
41
44
|
},
|
|
42
45
|
"publishConfig": {
|
|
43
46
|
"access": "public"
|