@jaredwray/fumanchu 4.5.1 → 4.6.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 CHANGED
@@ -7,7 +7,8 @@ Handlebars + Helpers Together
7
7
  [![tests](https://github.com/jaredwray/fumanchu/actions/workflows/tests.yaml/badge.svg)](https://github.com/jaredwray/fumanchu/actions/workflows/tests.yaml)
8
8
  [![codecov](https://codecov.io/gh/jaredwray/fumanchu/graph/badge.svg?token=gtYw78huva)](https://codecov.io/gh/jaredwray/fumanchu)
9
9
  [![npm version](https://img.shields.io/npm/v/@jaredwray/fumanchu.svg)](https://npmjs.com/package/@jaredwray/fumanchu)
10
- [![GitHub license](https://img.shields.io/github/license/jaredwray/fumanchu)](https://github.com/jaredwray/fumanchu/blob/master/LICENSE)
10
+ [![NPM License](https://img.shields.io/npm/l/%40jaredwray%2Ffumanchu)
11
+ ](https://github.com/jaredwray/fumanchu/blob/main/LICENSE)
11
12
  [![npm](https://img.shields.io/npm/dm/@jaredwray/fumanchu)](https://npmjs.com/package/@jaredwray/fumanchu)
12
13
 
13
14
  [Handlebars](https://github.com/handlebars-lang/handlebars.js) + [Handlebars-helpers](https://github.com/helpers/handlebars-helpers) (helpers are now maintained in this project) combined into a single package. Easily use it as a drop in replacement when using handlebars directly. More than 160 Handlebars helpers in ~20 categories. Helpers can be used with Assemble, Generate, Verb, Ghost, gulp-handlebars, grunt-handlebars, consolidate, or any node.js/Handlebars project. Currently **189 helpers** in **20 categories**! 🎉
@@ -39,6 +40,7 @@ Handlebars + Helpers Together
39
40
  * [string](https://fumanchu.org/docs/string/)
40
41
  * [url](https://fumanchu.org/docs/url/)
41
42
  * [utils](https://fumanchu.org/docs/utils/)
43
+ * [Caching](#caching)
42
44
  * [How to Contribute](#how-to-contribute)
43
45
  * [License and Copyright](#license-and-copyright)
44
46
 
@@ -112,6 +114,53 @@ registry.load(hbs, { names: ['if']}); // Load the helpers into Handlebars
112
114
 
113
115
  In addition, we have made the helper functions have a compatibility such as `HelperRegistryCompatibility.NODEJS` or `HelperRegistryCompatibility.BROWSER`. This will allow you to filter out based on your environment!
114
116
 
117
+ # Caching
118
+
119
+ When caching is enabled, Fumanchu wraps the Handlebars `compile()` method to cache compiled template functions using [@cacheable/memory](https://github.com/jaredwray/cacheable/tree/main/packages/memory). If you compile the same template string multiple times, the cached version is returned instead of recompiling. The returned Handlebars instance is fully compatible -- caching is transparent to your existing code.
120
+
121
+ The `caching` option accepts three types:
122
+ - `boolean` -- `true` enables caching with defaults, `false` disables it
123
+ - `CacheableMemory` -- a pre-configured instance from `@cacheable/memory`
124
+ - `CacheableMemoryOptions` -- an options object passed to `CacheableMemory` (supports `ttl`, `lruSize`, `checkInterval`, etc.)
125
+
126
+ ## Enable caching with default settings
127
+
128
+ ```javascript
129
+ import { fumanchu } from '@jaredwray/fumanchu';
130
+ const handlebars = fumanchu({ caching: true });
131
+
132
+ const template = handlebars.compile('Hello {{name}}!');
133
+ template({ name: 'World' }); // compiles and caches
134
+
135
+ const template2 = handlebars.compile('Hello {{name}}!');
136
+ // returns the cached compiled function -- no recompilation
137
+ ```
138
+
139
+ ## Pass caching options
140
+
141
+ ```javascript
142
+ import { fumanchu } from '@jaredwray/fumanchu';
143
+ const handlebars = fumanchu({
144
+ caching: {
145
+ ttl: '1h', // Time-to-live in ms or human-readable string like '1h'
146
+ lruSize: 500, // LRU cache size limit (0 = unlimited)
147
+ checkInterval: 0, // Interval to check for expired items in ms (0 = disabled)
148
+ },
149
+ });
150
+ ```
151
+
152
+ ## Pass a pre-configured `CacheableMemory` instance
153
+
154
+ This is useful if you want to share a cache across multiple Fumanchu instances or manage the cache lifecycle yourself:
155
+
156
+ ```javascript
157
+ import { fumanchu, CacheableMemory } from '@jaredwray/fumanchu';
158
+ const cache = new CacheableMemory({ ttl: '1h', lruSize: 1000, useClone: false });
159
+
160
+ const hbs1 = fumanchu({ caching: cache });
161
+ const hbs2 = fumanchu({ caching: cache }); // shares the same cache as hbs1
162
+ ```
163
+
115
164
  ## How to Contribute
116
165
  Clone the repository locally refer to the [CONTRIBUTING](CONTRIBUTING.md) guide. If you have any questions please feel free to ask by creating an issue and label it `question`.
117
166
 
package/dist/index.cjs CHANGED
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ CacheableMemory: () => import_memory.CacheableMemory,
33
34
  Handlebars: () => Handlebars3,
34
35
  HelperRegistry: () => HelperRegistry,
35
36
  createHandlebars: () => createHandlebars,
@@ -38,6 +39,7 @@ __export(index_exports, {
38
39
  helpers: () => helpers21
39
40
  });
40
41
  module.exports = __toCommonJS(index_exports);
42
+ var import_memory = require("@cacheable/memory");
41
43
  var import_handlebars3 = __toESM(require("handlebars"), 1);
42
44
 
43
45
  // src/helpers/array.ts
@@ -3167,10 +3169,35 @@ function fumanchu(options2) {
3167
3169
  handlebars2.registerPartial(import_handlebars3.default.partials);
3168
3170
  }
3169
3171
  registry.load(handlebars2);
3172
+ if (options2?.caching) {
3173
+ let cache;
3174
+ if (options2.caching instanceof import_memory.CacheableMemory) {
3175
+ cache = options2.caching;
3176
+ } else if (typeof options2.caching === "object") {
3177
+ cache = new import_memory.CacheableMemory({
3178
+ useClone: false,
3179
+ ...options2.caching
3180
+ });
3181
+ } else {
3182
+ cache = new import_memory.CacheableMemory({ useClone: false });
3183
+ }
3184
+ const originalCompile = handlebars2.compile.bind(handlebars2);
3185
+ handlebars2.compile = (input, compileOptions) => {
3186
+ const key = compileOptions ? input + JSON.stringify(compileOptions) : String(input);
3187
+ const cached = cache.get(key);
3188
+ if (cached) {
3189
+ return cached;
3190
+ }
3191
+ const compiled = originalCompile(input, compileOptions);
3192
+ cache.set(key, compiled);
3193
+ return compiled;
3194
+ };
3195
+ }
3170
3196
  return handlebars2;
3171
3197
  }
3172
3198
  // Annotate the CommonJS export names for ESM import in node:
3173
3199
  0 && (module.exports = {
3200
+ CacheableMemory,
3174
3201
  Handlebars,
3175
3202
  HelperRegistry,
3176
3203
  createHandlebars,
package/dist/index.d.cts CHANGED
@@ -1,3 +1,5 @@
1
+ import { CacheableMemory, CacheableMemoryOptions } from '@cacheable/memory';
2
+ export { CacheableMemory, CacheableMemoryOptions } from '@cacheable/memory';
1
3
  import HandlebarsLib from 'handlebars';
2
4
 
3
5
  type Helper = {
@@ -88,25 +90,10 @@ declare function helpers(options: HelpersOptions): void;
88
90
  * @deprecated Will be deprecated in future versions, use `fumanchu()` instead.
89
91
  */
90
92
  declare function createHandlebars(): Promise<typeof HandlebarsLib>;
91
- /**
92
- * @typedef {Object} FumanchuCachingOptions
93
- * @property {number|string} [ttl] - Time to Live - If you set a number it is miliseconds, if you set a string it is a human-readable
94
- * format such as `1s` for 1 second or `1h` for 1 hour. Setting undefined means that it will use the default time-to-live. If both are
95
- * undefined then it will not have a time-to-live.
96
- * @property {boolean} [useClone] - If true, it will clone the value before returning it. If false, it will return the value directly. Default is true.
97
- * @property {number} [lruSize] - The size of the LRU cache. If set to 0, it will not use LRU cache. Default is 0.
98
- * @property {number} [checkInterval] - The interval to check for expired items. If set to 0, it will not check for expired items. Default is 0.
99
- */
100
- type FumanchuCachingOptions = {
101
- ttl?: number | string;
102
- useClone?: boolean;
103
- lruSize?: number;
104
- checkInterval?: number;
105
- };
106
93
  type FumanchuOptions = {
107
94
  handlebars?: typeof HandlebarsLib;
108
95
  filter?: HelperFilter;
109
- caching?: boolean | FumanchuCachingOptions;
96
+ caching?: boolean | CacheableMemory | CacheableMemoryOptions;
110
97
  };
111
98
  /**
112
99
  * Will return a Handlebars instance with Fumanchu helpers (experimental)
@@ -115,4 +102,4 @@ type FumanchuOptions = {
115
102
  */
116
103
  declare function fumanchu(options?: FumanchuOptions): typeof HandlebarsLib;
117
104
 
118
- export { type FumanchuCachingOptions, type FumanchuOptions, Handlebars, type HelperFilter, HelperRegistry, type HelpersOptions, createHandlebars, fumanchu, handlebars, helpers };
105
+ export { type FumanchuOptions, Handlebars, type HelperFilter, HelperRegistry, type HelpersOptions, createHandlebars, fumanchu, handlebars, helpers };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { CacheableMemory, CacheableMemoryOptions } from '@cacheable/memory';
2
+ export { CacheableMemory, CacheableMemoryOptions } from '@cacheable/memory';
1
3
  import HandlebarsLib from 'handlebars';
2
4
 
3
5
  type Helper = {
@@ -88,25 +90,10 @@ declare function helpers(options: HelpersOptions): void;
88
90
  * @deprecated Will be deprecated in future versions, use `fumanchu()` instead.
89
91
  */
90
92
  declare function createHandlebars(): Promise<typeof HandlebarsLib>;
91
- /**
92
- * @typedef {Object} FumanchuCachingOptions
93
- * @property {number|string} [ttl] - Time to Live - If you set a number it is miliseconds, if you set a string it is a human-readable
94
- * format such as `1s` for 1 second or `1h` for 1 hour. Setting undefined means that it will use the default time-to-live. If both are
95
- * undefined then it will not have a time-to-live.
96
- * @property {boolean} [useClone] - If true, it will clone the value before returning it. If false, it will return the value directly. Default is true.
97
- * @property {number} [lruSize] - The size of the LRU cache. If set to 0, it will not use LRU cache. Default is 0.
98
- * @property {number} [checkInterval] - The interval to check for expired items. If set to 0, it will not check for expired items. Default is 0.
99
- */
100
- type FumanchuCachingOptions = {
101
- ttl?: number | string;
102
- useClone?: boolean;
103
- lruSize?: number;
104
- checkInterval?: number;
105
- };
106
93
  type FumanchuOptions = {
107
94
  handlebars?: typeof HandlebarsLib;
108
95
  filter?: HelperFilter;
109
- caching?: boolean | FumanchuCachingOptions;
96
+ caching?: boolean | CacheableMemory | CacheableMemoryOptions;
110
97
  };
111
98
  /**
112
99
  * Will return a Handlebars instance with Fumanchu helpers (experimental)
@@ -115,4 +102,4 @@ type FumanchuOptions = {
115
102
  */
116
103
  declare function fumanchu(options?: FumanchuOptions): typeof HandlebarsLib;
117
104
 
118
- export { type FumanchuCachingOptions, type FumanchuOptions, Handlebars, type HelperFilter, HelperRegistry, type HelpersOptions, createHandlebars, fumanchu, handlebars, helpers };
105
+ export { type FumanchuOptions, Handlebars, type HelperFilter, HelperRegistry, type HelpersOptions, createHandlebars, fumanchu, handlebars, helpers };
package/dist/index.js CHANGED
@@ -1,4 +1,7 @@
1
1
  // src/index.ts
2
+ import {
3
+ CacheableMemory
4
+ } from "@cacheable/memory";
2
5
  import HandlebarsLib from "handlebars";
3
6
 
4
7
  // src/helpers/array.ts
@@ -3128,9 +3131,34 @@ function fumanchu(options2) {
3128
3131
  handlebars2.registerPartial(HandlebarsLib.partials);
3129
3132
  }
3130
3133
  registry.load(handlebars2);
3134
+ if (options2?.caching) {
3135
+ let cache;
3136
+ if (options2.caching instanceof CacheableMemory) {
3137
+ cache = options2.caching;
3138
+ } else if (typeof options2.caching === "object") {
3139
+ cache = new CacheableMemory({
3140
+ useClone: false,
3141
+ ...options2.caching
3142
+ });
3143
+ } else {
3144
+ cache = new CacheableMemory({ useClone: false });
3145
+ }
3146
+ const originalCompile = handlebars2.compile.bind(handlebars2);
3147
+ handlebars2.compile = (input, compileOptions) => {
3148
+ const key = compileOptions ? input + JSON.stringify(compileOptions) : String(input);
3149
+ const cached = cache.get(key);
3150
+ if (cached) {
3151
+ return cached;
3152
+ }
3153
+ const compiled = originalCompile(input, compileOptions);
3154
+ cache.set(key, compiled);
3155
+ return compiled;
3156
+ };
3157
+ }
3131
3158
  return handlebars2;
3132
3159
  }
3133
3160
  export {
3161
+ CacheableMemory,
3134
3162
  Handlebars3 as Handlebars,
3135
3163
  HelperRegistry,
3136
3164
  createHandlebars,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@jaredwray/fumanchu",
3
3
  "description": "Handlebars + Helpers = Fumanchu",
4
- "version": "4.5.1",
4
+ "version": "4.6.0",
5
5
  "homepage": "https://github.com/jaredwray/fumanchu",
6
6
  "author": "Jared Wray (me@jaredwray.com)",
7
7
  "type": "module",
@@ -63,6 +63,7 @@
63
63
  "license"
64
64
  ],
65
65
  "dependencies": {
66
+ "@cacheable/memory": "^2.0.7",
66
67
  "chrono-node": "2.9.0",
67
68
  "dayjs": "^1.11.19",
68
69
  "ent": "^2.2.2",