gramstax 0.0.1 → 0.0.2

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.
Files changed (62) hide show
  1. package/dist/src/index.cjs +2 -0
  2. package/dist/src/index.cjs.map +1 -0
  3. package/dist/src/{core/bot.d.ts → index.d.cts} +500 -12
  4. package/dist/src/index.d.ts +1292 -5
  5. package/dist/src/index.js +2 -4
  6. package/dist/src/index.js.map +1 -0
  7. package/package.json +10 -9
  8. package/dist/package.json +0 -52
  9. package/dist/src/base/general.d.ts +0 -7
  10. package/dist/src/base/general.d.ts.map +0 -1
  11. package/dist/src/base/general.js +0 -15
  12. package/dist/src/base/guard.d.ts +0 -13
  13. package/dist/src/base/guard.d.ts.map +0 -1
  14. package/dist/src/base/guard.js +0 -8
  15. package/dist/src/base/index.d.ts +0 -4
  16. package/dist/src/base/index.d.ts.map +0 -1
  17. package/dist/src/base/index.js +0 -3
  18. package/dist/src/base/page.d.ts +0 -263
  19. package/dist/src/base/page.d.ts.map +0 -1
  20. package/dist/src/base/page.js +0 -805
  21. package/dist/src/cache/external.d.ts +0 -10
  22. package/dist/src/cache/external.d.ts.map +0 -1
  23. package/dist/src/cache/external.js +0 -16
  24. package/dist/src/cache/index.d.ts +0 -2
  25. package/dist/src/cache/index.d.ts.map +0 -1
  26. package/dist/src/cache/index.js +0 -1
  27. package/dist/src/core/bot.d.ts.map +0 -1
  28. package/dist/src/core/bot.js +0 -465
  29. package/dist/src/core/ctx.d.ts +0 -60
  30. package/dist/src/core/ctx.d.ts.map +0 -1
  31. package/dist/src/core/ctx.js +0 -175
  32. package/dist/src/core/index.d.ts +0 -3
  33. package/dist/src/core/index.d.ts.map +0 -1
  34. package/dist/src/core/index.js +0 -2
  35. package/dist/src/grammy/index.d.ts +0 -2
  36. package/dist/src/grammy/index.d.ts.map +0 -1
  37. package/dist/src/grammy/index.js +0 -1
  38. package/dist/src/index.d.ts.map +0 -1
  39. package/dist/src/template/engine.d.ts +0 -34
  40. package/dist/src/template/engine.d.ts.map +0 -1
  41. package/dist/src/template/engine.js +0 -122
  42. package/dist/src/template/index.d.ts +0 -3
  43. package/dist/src/template/index.d.ts.map +0 -1
  44. package/dist/src/template/index.js +0 -2
  45. package/dist/src/template/manager.d.ts +0 -111
  46. package/dist/src/template/manager.d.ts.map +0 -1
  47. package/dist/src/template/manager.js +0 -237
  48. package/src/base/general.ts +0 -17
  49. package/src/base/guard.ts +0 -10
  50. package/src/base/index.ts +0 -3
  51. package/src/base/page.ts +0 -1111
  52. package/src/cache/external.ts +0 -15
  53. package/src/cache/index.ts +0 -1
  54. package/src/core/bot.ts +0 -535
  55. package/src/core/ctx.ts +0 -177
  56. package/src/core/index.ts +0 -2
  57. package/src/grammy/index.ts +0 -1
  58. package/src/index.ts +0 -4
  59. package/src/template/engine.ts +0 -167
  60. package/src/template/index.ts +0 -2
  61. package/src/template/manager.ts +0 -280
  62. package/src/types/page.d.ts +0 -4
package/src/core/ctx.ts DELETED
@@ -1,177 +0,0 @@
1
- import { CacheExternal } from "../cache"
2
- import { setTimeout } from "node:timers/promises"
3
- import { BaseGeneral } from "../base"
4
- import { TemplateManager } from "../template"
5
- import { InlineKeyboard, Keyboard, type Context } from "grammy"
6
-
7
- export class Ctx extends BaseGeneral {
8
- public data = (this as any).constructor.data as { name: string; callbackData: (...args: any) => string | any } // for internal access (this.**). example this.data.callbackData
9
-
10
- public get isPremium() {
11
- return this.ct.from?.is_premium ?? false
12
- }
13
- public get isBot() {
14
- return this.ct.from?.is_bot ?? false
15
- }
16
- public get userid() {
17
- return this.ct.from?.id as number
18
- }
19
- public get username() {
20
- return this.ct.from?.username as string
21
- }
22
- public get fullname() {
23
- return `${this.ct.from?.first_name || ``}${this.ct.from?.last_name || ``}`
24
- }
25
- public get firstname() {
26
- return this.ct.from?.first_name as string
27
- }
28
- public get lastname() {
29
- return this.ct.from?.last_name as string
30
- }
31
- public get msgText() {
32
- return this.ct.message?.text as string
33
- }
34
- public get msgTextIntent() {
35
- return this.msgText && this.msgText.indexOf(` `) != -1 ? (this.msgText.split(` `)[0] as string) : ``
36
- }
37
- public get msgTextPayloads() {
38
- return this.msgText && this.msgText.indexOf(` `) != -1 ? (this.msgText.split(` `).slice(1) as any[]) : ([] as any[])
39
- }
40
- public get msgTextPayload() {
41
- return this.msgTextPayloads[0] as string
42
- }
43
- public get msgCaption() {
44
- return this.ct.message?.caption as string
45
- }
46
- public get msgCaptionIntent() {
47
- return this.msgCaption && this.msgCaption.indexOf(` `) != -1 ? (this.msgCaption.split(` `)[0] as string) : ``
48
- }
49
- public get msgPhoto() {
50
- return this.ct.message?.photo
51
- }
52
- public get msgVideo() {
53
- return this.ct.message?.video
54
- }
55
- public get msgAudio() {
56
- return this.ct.message?.audio
57
- }
58
- public get callbackData() {
59
- return this.ct.callbackQuery?.data as string
60
- }
61
- public get callbackDataIntent() {
62
- return this.callbackData && this.callbackData.indexOf(`:`) != -1 ? (this.callbackData.split(`:`)[0] as string) : ``
63
- }
64
- public get callbackDataPayloads() {
65
- return this.callbackData && this.callbackData.indexOf(`:`) != -1 ? (this.callbackData.split(`:`).slice(1) as any[]) : ([] as any[])
66
- }
67
- public get callbackDataPayload() {
68
- return this.callbackDataPayloads?.[0] as string
69
- }
70
- public get callbackDataParts() {
71
- return this.callbackDataPayload && this.callbackDataPayload.indexOf(`+`) != -1 ? (this.callbackDataPayload.split(`+`) as any[]) : ([] as any[])
72
- }
73
- public get languageCode() {
74
- return this.ct.from?.language_code as string
75
- }
76
- public set languageCode(v: any) {
77
- ;(this as any).ct.from.language_code = v
78
- }
79
-
80
- public session: { method?: string; params?: any } = {}
81
- public constructor(public ct: Context, public templateManager: TemplateManager, public cacheSession: CacheExternal, public cacheKeyboard: Map<any, any>) {
82
- super()
83
- }
84
-
85
- public async broadcast(ids: any[], languageCode: any[], keyboard?: Keyboard | InlineKeyboard, data?: Record<string, any>, baseId?: string, options?: any) {
86
- const limitFree = 30
87
- const msgs = languageCode.map((it) => this.templateManager.getMessage(this.data.name, baseId, it, data)) as any[]
88
- for (let index = 0; index < ids.length; index++) {
89
- const id = ids[index]
90
- const msg = msgs[index]
91
- await this.ct.api.sendMessage(id, msg, {
92
- parse_mode: `HTML`,
93
- reply_markup: keyboard,
94
- ...options
95
- })
96
-
97
- if (index + 1 == limitFree) {
98
- await setTimeout(1200)
99
- }
100
- }
101
- }
102
-
103
- public async reply(keyboard?: Keyboard | InlineKeyboard, data?: Record<string, any>, baseId?: string, options?: any) {
104
- const msg = this.templateManager.getMessage(this.data.name, baseId, this.languageCode, data)
105
- return await this.ct.reply(msg, {
106
- parse_mode: `HTML`,
107
- reply_markup: keyboard,
108
- ...options
109
- })
110
- }
111
-
112
- public async replyAction(type: Parameters<typeof this.ct.replyWithChatAction>[0]) {
113
- return await this.ct.replyWithChatAction(type)
114
- }
115
-
116
- public async edit(keyboard?: Keyboard | InlineKeyboard, data?: Record<string, any>, baseId?: string, options?: any) {
117
- try {
118
- const msg = this.templateManager.getMessage(this.data.name, baseId, this.languageCode, data)
119
- return await this.ct.editMessageText(msg, {
120
- parse_mode: `HTML`,
121
- reply_markup: keyboard,
122
- ...options
123
- })
124
- } catch (error) {
125
- await this.reply(keyboard, data, baseId, options)
126
- }
127
- }
128
-
129
- public async delete() {
130
- return await this.ct.deleteMessage()
131
- }
132
-
133
- public async callbackQueryAnswer(options?: any) {
134
- try {
135
- return await this.ct.answerCallbackQuery(options)
136
- } catch {
137
- return null
138
- }
139
- }
140
-
141
- public async sessionSet(method: string, params: any, ...moreRoot: any) {
142
- try {
143
- const value = { method, params, ...moreRoot }
144
- const result = await this.cacheSession.set(`${this.userid}`, { method, params, ...moreRoot })
145
- if (result) {
146
- this.session = value
147
- }
148
- return result
149
- } catch {
150
- return null
151
- }
152
- }
153
-
154
- public async sessionGet(): Promise<{ method: string; params: any; [moreRoot: string]: any } | null> {
155
- try {
156
- const result = await this.cacheSession.get(`${this.userid}`)
157
- if (result) {
158
- this.session = result
159
- }
160
- return result || null
161
- } catch {
162
- return null
163
- }
164
- }
165
-
166
- public async sessionClear() {
167
- try {
168
- const result = await this.cacheSession.delete(`${this.userid}`)
169
- if (result) {
170
- this.session = {}
171
- }
172
- return result
173
- } catch {
174
- return null
175
- }
176
- }
177
- }
package/src/core/index.ts DELETED
@@ -1,2 +0,0 @@
1
- export * from "./bot"
2
- export * from "./ctx"
@@ -1 +0,0 @@
1
- export * from "grammy"
package/src/index.ts DELETED
@@ -1,4 +0,0 @@
1
- export * from "./base"
2
- export * from "./cache"
3
- export * from "./core"
4
- export * from "./template"
@@ -1,167 +0,0 @@
1
- export class TemplateEngine {
2
- public static _escape(str: string): string {
3
- return str
4
- .replace(/\\/g, `\\\\`) // escape backslash: \ → \\
5
- .replace(/`/g, `\\\``) // escape backtick: ` → \`
6
- }
7
-
8
- public static _processVariables(template: string) {
9
- return template.replace(/\{\{(\w+)\}\}/g, (_, key) => `\${(data && data["${key}"]) ?? ""}`)
10
- }
11
-
12
- public static _processBaseBlocks(template: string) {
13
- const baseRegex = /<base\b[^>]*?(?:\sid=(["']?)([^"'\s>]+)\1)?[^>]*?>([\s\S]*?)<\/base>/g
14
- const result: {
15
- [baseId: string]: string
16
- } = {}
17
-
18
- for (const match of template.matchAll(baseRegex)) {
19
- const idValue = match[2] ?? `default`
20
- const inner = match[3] ?? ``
21
- const cleaned = inner
22
- .replace(/^[\t ]+/gm, ``)
23
- .replace(/^\n+/, ``)
24
- .replace(/\n+$/, ``)
25
- .trim()
26
-
27
- result[idValue] = cleaned
28
- }
29
- return result
30
- }
31
-
32
- public static _processScriptBlocks(template: string) {
33
- return template.replace(/<script\b[^>]*>([\s\S]*?)<\/script>/gi, (_, rawCode) => {
34
- const innerCode = rawCode.trim()
35
- if (!innerCode) return ``
36
-
37
- return `\${(() => { if (!data) return ''; try { with(data) { ${innerCode} } } catch(e) { return '' } })()}`
38
- })
39
- }
40
-
41
- public static _processSpaceBlocks(template: string) {
42
- return template.replace(/^[ \t]*<space\s*\/>[ \t]*$/gim, ``)
43
- }
44
-
45
- public static _processDivBlocks(template: string) {
46
- return template.replace(/<div>([\s\S]*?)<\/div>/gi, (_, inner) => {
47
- const cleaned = inner
48
- .replace(/^[\t ]+/gm, ``)
49
- .replace(/^\n+/, ``)
50
- .replace(/\n+$/, ``)
51
- return cleaned
52
- })
53
- }
54
-
55
- public static _processMessageBlocks(template: string) {
56
- const messageRegex = /<message\s+lang="([^"]+)"\s*>([\s\S]*?)<\/message>/gi
57
- const result: {
58
- [lang: string]: string
59
- } = {}
60
-
61
- for (const [, lang, rawContent] of template.matchAll(messageRegex) as any) {
62
- const cleaned = rawContent
63
- .replace(/^[\t ]+/gm, ``)
64
- .replace(/^\n+/, ``)
65
- .replace(/\n+$/, ``)
66
- .trim()
67
-
68
- result[lang] = cleaned
69
- }
70
- return result
71
- }
72
-
73
- public static _processKeyboardBlocks(template: string) {
74
- const keyboardRegex = /<keyboard\b[^>]*\blang="([^"]*)"[^>]*?(?:\sfor="([^"]*)")?[^>]*>([\s\S]*?)<\/keyboard>/gi
75
- const result: {
76
- [lang: string]: {
77
- inline?: string
78
- default?: string
79
- }
80
- } = {}
81
-
82
- for (const [, lang, forAttr, rawContent] of template.matchAll(keyboardRegex) as any) {
83
- const mode = forAttr === `default` ? `default` : `inline`
84
- const cleaned = rawContent.trim()
85
-
86
- if (!result[lang]) {
87
- result[lang] = {}
88
- }
89
- result[lang][mode] = cleaned
90
- }
91
- return result
92
- }
93
-
94
- public static _compileToFunction<T extends boolean>(template: T extends true ? string[] : string, isArray: T): T extends true ? (data?: Record<string, any>) => string[] : (data?: Record<string, any>) => string {
95
- let singleOrCombined: string
96
- if (isArray) {
97
- const multiTemplate = template as string[]
98
- singleOrCombined = multiTemplate.map((t) => `\`${t}\``).join(`,`)
99
- } else {
100
- singleOrCombined = `\`${template as string}\``
101
- }
102
-
103
- let processed = singleOrCombined
104
- processed = this._processScriptBlocks(this._processDivBlocks(this._processSpaceBlocks(processed)))
105
-
106
- if (isArray) {
107
- const functionBody = `return [${processed}]`
108
- return new Function(`data`, functionBody) as any
109
- } else {
110
- const functionBody = `return ${processed}`
111
- return new Function(`data`, functionBody) as any
112
- }
113
- }
114
-
115
- public static compileMessages(template: string) {
116
- const baseBlocks = this._processBaseBlocks(template)
117
- const result: {
118
- [baseId: string]: {
119
- [lang: string]: (data?: Record<string, any>) => string
120
- }
121
- } = {}
122
-
123
- for (const [baseId, baseContent] of Object.entries(baseBlocks)) {
124
- const messages = this._processMessageBlocks(baseContent)
125
- result[baseId] = {}
126
-
127
- for (const [lang, content] of Object.entries(messages)) {
128
- const processed = this._processVariables(this._processScriptBlocks(content))
129
- result[baseId][lang] = this._compileToFunction(processed, false)
130
- }
131
- }
132
-
133
- return result
134
- }
135
-
136
- public static compileKeyboards(template: string) {
137
- const baseBlocks = this._processBaseBlocks(template)
138
- const result: {
139
- [baseId: string]: {
140
- [lang: string]: {
141
- inline?: (data?: Record<string, any>) => string[]
142
- default?: (data?: Record<string, any>) => string[]
143
- }
144
- }
145
- } = {}
146
-
147
- for (const [baseId, baseContent] of Object.entries(baseBlocks)) {
148
- const keyboards = this._processKeyboardBlocks(baseContent)
149
- result[baseId] = {}
150
-
151
- for (const [lang, modes] of Object.entries(keyboards)) {
152
- result[baseId][lang] = {}
153
-
154
- for (const [mode, content] of Object.entries(modes)) {
155
- // Pisahkan label, handle escaped comma
156
- const labels = content.split(/(?<!\\),\s*/).map((label: string) => label.replace(/\\,/g, `,`).trim())
157
-
158
- const processedLabels = labels.map((label) => this._processVariables(this._processScriptBlocks(label)))
159
-
160
- result[baseId][lang][mode as `inline` | `default`] = this._compileToFunction(processedLabels, true)
161
- }
162
- }
163
- }
164
-
165
- return result
166
- }
167
- }
@@ -1,2 +0,0 @@
1
- export * from "./engine"
2
- export * from "./manager"
@@ -1,280 +0,0 @@
1
- import { TemplateEngine } from "."
2
- import { readFile, mkdir } from "node:fs/promises"
3
- import { watch, FSWatcher } from "chokidar"
4
- import { basename, join, extname } from "node:path"
5
- import { readdirSync, readFileSync, existsSync, statSync, writeFileSync } from "node:fs"
6
-
7
- /** Template file interface for better type safety */
8
- type ICompiledTemplate = {
9
- message: ReturnType<typeof TemplateEngine.compileMessages>
10
- keyboard: ReturnType<typeof TemplateEngine.compileKeyboards>
11
- }
12
-
13
- /** Template loading options */
14
- type ITemplateOptions = {
15
- /** Enable file watching for hot reloading (if have templatePath) */
16
- enableWatch?: boolean
17
- /** Base path for template files (set null if dont want read template from file) */
18
- path?: string | undefined | null
19
- /** Force language params to this value */
20
- forceLanguage?: string | undefined | null
21
- }
22
-
23
- /** Template management system */
24
- export class TemplateManager {
25
- public _map = new Map<string, ICompiledTemplate>()
26
- public _engine = TemplateEngine
27
- public _watcher: FSWatcher | null = null
28
- public _supportedExtensions = new Set([`.html`])
29
- public readonly _path: string | null
30
- public readonly _forceLanguage: string | null
31
- public readonly _isWatchEnabled: boolean
32
- public constructor(options: ITemplateOptions = {}) {
33
- const { enableWatch = false, path = null, forceLanguage = null } = options
34
-
35
- this._path = path
36
- this._forceLanguage = forceLanguage
37
- this._isWatchEnabled = enableWatch
38
-
39
- this._validatePath()
40
- this._initializeWatcher()
41
- this._loadAllFiles()
42
- }
43
-
44
- /** Validate and ensure template directory exists. @returns Void */
45
- public _validatePath(): void {
46
- try {
47
- if (this._path === null || !existsSync(this._path)) {
48
- return
49
- }
50
-
51
- const stats = statSync(this._path)
52
- if (!stats.isDirectory()) {
53
- throw new Error(`Template path is not a directory: ${this._path}`)
54
- }
55
- } catch (error) {
56
- throw new Error(`Failed to validate Template path: ${error}`)
57
- }
58
- }
59
-
60
- /** Initialize file system watcher for hot reloading. @returns Void */
61
- public _initializeWatcher(): void {
62
- if (this._path === null || !this._isWatchEnabled) {
63
- return
64
- }
65
-
66
- this._watcher = watch(this._path, {
67
- persistent: true,
68
- ignoreInitial: true,
69
- awaitWriteFinish: {
70
- stabilityThreshold: 100,
71
- pollInterval: 50
72
- }
73
- })
74
-
75
- this._watcher!.on(`change`, this._handleFileChange.bind(this))
76
- this._watcher!.on(`add`, this._handleFileAdd.bind(this))
77
- this._watcher!.on(`unlink`, this._handleFileDelete.bind(this))
78
- this._watcher!.on(`error`, this._handleWatchError.bind(this))
79
- }
80
-
81
- /** Handle file change events */
82
- public async _handleFileChange(filepath: string): Promise<void> {
83
- const filename = basename(filepath)
84
- if (this._isValidFile(filename)) {
85
- await this._loadFile(filename, false)
86
- }
87
- }
88
-
89
- /** Handle file add events */
90
- public async _handleFileAdd(filePath: string): Promise<void> {
91
- const fileName = basename(filePath)
92
- if (this._isValidFile(fileName)) {
93
- await this._loadFile(fileName, false)
94
- }
95
- }
96
-
97
- /** Handle file delete events */
98
- public _handleFileDelete(filePath: string): void {
99
- const fileName = basename(filePath)
100
- const fileKey = this._getKey(fileName)
101
- if (this._map.has(fileKey)) {
102
- this._map.delete(fileKey)
103
- }
104
- }
105
-
106
- /** Handle watcher errors */
107
- public _handleWatchError(error: any): void {
108
- // you can overrides
109
- }
110
-
111
- /** Load all Template files during initialization */
112
- public _loadAllFiles(): void {
113
- if (this._path === null || !existsSync(this._path)) {
114
- return
115
- }
116
- const files = readdirSync(this._path, { encoding: `utf8` })
117
- const validFiles = files.filter((file) => this._isValidFile(file))
118
- for (const fileName of validFiles) {
119
- this._loadFile(fileName, true)
120
- }
121
- }
122
-
123
- /** Load and compile a single template file */
124
- public async _loadFile(filename: string, useSync: boolean = true): Promise<void> {
125
- if (this._path === null) {
126
- return
127
- }
128
- const path = join(this._path, filename)
129
- const key = this._getKey(filename)
130
- const raw = useSync ? readFileSync(path, { encoding: `utf8` }) : await readFile(path, { encoding: `utf8` })
131
- this.compile(key, raw)
132
- }
133
-
134
- public _isValidFile(filename: string): boolean {
135
- const extension = extname(filename).toLowerCase()
136
- return this._supportedExtensions.has(extension)
137
- }
138
-
139
- public _getKey(filename: string): string {
140
- return filename.replace(/\.[^/.]+$/, ``)
141
- }
142
-
143
- public compile(key: string, rawTemplate: string, keepIfExist?: Partial<{ [K in keyof ICompiledTemplate]: boolean }>) {
144
- const existing = this._map.get(key)
145
- const compiled = existing || ({} as ICompiledTemplate)
146
- let updated = false
147
-
148
- if (keepIfExist === undefined || keepIfExist?.message === false || existing?.message === undefined) {
149
- compiled.message = TemplateEngine.compileMessages(rawTemplate)
150
- updated = true
151
- }
152
- if (keepIfExist === undefined || keepIfExist?.keyboard === false || existing?.keyboard === undefined) {
153
- compiled.keyboard = TemplateEngine.compileKeyboards(rawTemplate)
154
- updated = true
155
- }
156
-
157
- if (updated) {
158
- this._map.set(key, compiled)
159
- }
160
- }
161
-
162
- /**
163
- * Get compiled message template
164
- * @param key Template identifier (filename without extension)
165
- * @param baseId Base id attr from block
166
- * @param language Target language code
167
- * @param data Template variables
168
- * @returns Rendered message string
169
- */
170
- public getMessage(key: string, baseId: string = `default`, language: string = `en`, data?: Record<string, any>): string {
171
- const template = this._map.get(key)
172
- const func = template?.message?.[baseId]?.[this._forceLanguage || language]
173
- if (!func) {
174
- return ``
175
- }
176
-
177
- try {
178
- return func(data)
179
- } catch (error) {
180
- return ``
181
- }
182
- }
183
-
184
- /**
185
- * Get compiled keyboard template
186
- * @param key Template identifier (filename without extension)
187
- * @param baseId Base id attr from block
188
- * @param language Target language code
189
- * @param data Template variables
190
- * @returns Array of rendered button labels
191
- */
192
- public getKeyboard(key: string, baseId: string = `default`, language: string = `en`, display: `inline` | `default` = `inline`, data?: Record<string, any>): string[] {
193
- const template = this._map.get(key)
194
- const func = template?.keyboard?.[baseId]?.[this._forceLanguage || language]?.[display]
195
- if (!func) {
196
- return []
197
- }
198
-
199
- try {
200
- return func(data)
201
- } catch (error) {
202
- return []
203
- }
204
- }
205
-
206
- /**
207
- * Update message template in memory
208
- * @param key Template identifier (filename without extension)
209
- * @param rawTemplate Raw template string
210
- */
211
- public setMessage(key: string, rawTemplate: string): void {
212
- this.compile(key, rawTemplate, { keyboard: true })
213
- }
214
-
215
- /**
216
- * Update keyboard template in memory
217
- * @param key Template identifier (filename without extension)
218
- * @param rawTemplate Raw template string
219
- */
220
- public setKeyboard(key: string, rawTemplate: string): void {
221
- this.compile(key, rawTemplate, { message: true })
222
- }
223
-
224
- /**
225
- * Write template to file and update cache
226
- * @param filename Target filename (with extension)
227
- * @param rawTemplate Template to write
228
- * @returns Promise that resolves when file is written
229
- */
230
- public async write(filename: string, rawTemplate: string): Promise<void> {
231
- if (this._path === null) {
232
- return
233
- }
234
- const filePath = join(this._path, filename)
235
- await mkdir(this._path, { recursive: true })
236
- writeFileSync(filePath, rawTemplate, { encoding: `utf8` })
237
- await this._loadFile(filename, false)
238
- }
239
-
240
- /**
241
- * Get list of available template
242
- * @returns Array of template names
243
- */
244
- public getAvailable(): string[] {
245
- return Array.from(this._map.keys())
246
- }
247
-
248
- /**
249
- * Check if template exists
250
- * @param key Template identifier
251
- * @returns True if template exists
252
- */
253
- public has(key: string): boolean {
254
- return this._map.has(key)
255
- }
256
-
257
- /**
258
- * Get cache statistics
259
- * @returns Object with cache information
260
- */
261
- public getCacheStats(): { templateCount: number; totalSize: number } {
262
- return {
263
- templateCount: this._map.size,
264
- totalSize: JSON.stringify(this._map.entries().toArray(), (_, value) => {
265
- return typeof value === `function` ? value.toString() : value
266
- }).length
267
- }
268
- }
269
-
270
- /**
271
- * Cleanup resources and close watchers
272
- * @returns Promise void
273
- */
274
- public async destroy(): Promise<void> {
275
- if (this._watcher) {
276
- await this._watcher.close()
277
- }
278
- this._map.clear()
279
- }
280
- }
@@ -1,4 +0,0 @@
1
- import type { BasePage } from "../base/page"
2
-
3
- const Page = class extends BasePage {}
4
- export type IPageBase = typeof Page