@enonic/nextjs-adapter 2.0.0-B3 → 2.0.1

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 (82) hide show
  1. package/.eslint-childrc.js +17 -0
  2. package/.eslintrc.js +15 -0
  3. package/.github/dependabot.yml +20 -0
  4. package/.github/pull-merger.yml +1 -0
  5. package/.github/workflows/release.yml +39 -0
  6. package/LICENSE +201 -0
  7. package/RELEASE.md +75 -0
  8. package/package.json +8 -7
  9. package/server/.eslintrc.js +11 -0
  10. package/server/ClearableFileCache.ts +410 -0
  11. package/server/cache.ts +50 -0
  12. package/server/index.ts +74 -0
  13. package/server/tsconfig.json +23 -0
  14. package/setversion.js +8 -0
  15. package/src/.eslintrc.js +11 -0
  16. package/src/ComponentRegistry.ts +189 -0
  17. package/{UrlProcessor.js → src/UrlProcessor.ts} +54 -36
  18. package/{baseMappings.js → src/baseMappings.ts} +13 -3
  19. package/{guillotine/fetchContent.js → src/guillotine/fetchContent.ts} +496 -243
  20. package/src/guillotine/getMetaData.ts +246 -0
  21. package/{index.d.ts → src/index.ts} +1 -1
  22. package/src/tsconfig.json +20 -0
  23. package/{utils.js → src/utils.ts} +160 -70
  24. package/{views/BaseComponent.jsx → src/views/BaseComponent.tsx} +73 -39
  25. package/{views/BaseContent.jsx → src/views/BaseContent.tsx} +24 -17
  26. package/src/views/BaseLayout.tsx +45 -0
  27. package/{views/BaseMacro.jsx → src/views/BaseMacro.tsx} +45 -29
  28. package/src/views/BasePage.tsx +56 -0
  29. package/src/views/BasePart.tsx +50 -0
  30. package/{views/Empty.jsx → src/views/Empty.tsx} +2 -0
  31. package/src/views/Fragment.tsx +45 -0
  32. package/src/views/MainView.tsx +21 -0
  33. package/src/views/Region.tsx +89 -0
  34. package/{views/RichTextView.jsx → src/views/RichTextView.tsx} +31 -10
  35. package/{views/SingleComponent.jsx → src/views/SingleComponent.tsx} +8 -2
  36. package/src/views/StaticContent.tsx +40 -0
  37. package/src/views/Text.tsx +15 -0
  38. package/src/views/macros/DefaultMacro.tsx +9 -0
  39. package/src/views/macros/DisableMacro.tsx +8 -0
  40. package/ComponentRegistry.d.ts +0 -64
  41. package/ComponentRegistry.js +0 -121
  42. package/UrlProcessor.d.ts +0 -25
  43. package/baseMappings.d.ts +0 -1
  44. package/guillotine/fetchContent.d.ts +0 -48
  45. package/guillotine/getMetaData.d.ts +0 -94
  46. package/guillotine/getMetaData.js +0 -128
  47. package/index.js +0 -5
  48. package/query/Shortcut.d.ts +0 -1
  49. package/server/ClearableFileCache.d.ts +0 -31
  50. package/server/ClearableFileCache.js +0 -472
  51. package/server/cache.d.ts +0 -2
  52. package/server/cache.js +0 -129
  53. package/server/index.d.ts +0 -5
  54. package/server/index.js +0 -132
  55. package/utils.d.ts +0 -114
  56. package/views/BaseComponent.d.ts +0 -25
  57. package/views/BaseContent.d.ts +0 -4
  58. package/views/BaseLayout.d.ts +0 -17
  59. package/views/BaseLayout.jsx +0 -24
  60. package/views/BaseMacro.d.ts +0 -16
  61. package/views/BasePage.d.ts +0 -19
  62. package/views/BasePage.jsx +0 -34
  63. package/views/BasePart.d.ts +0 -19
  64. package/views/BasePart.jsx +0 -24
  65. package/views/Empty.d.ts +0 -3
  66. package/views/Fragment.d.ts +0 -10
  67. package/views/Fragment.jsx +0 -30
  68. package/views/MainView.d.ts +0 -4
  69. package/views/MainView.jsx +0 -14
  70. package/views/Region.d.ts +0 -20
  71. package/views/Region.jsx +0 -52
  72. package/views/RichTextView.d.ts +0 -16
  73. package/views/SingleComponent.d.ts +0 -5
  74. package/views/StaticContent.d.ts +0 -15
  75. package/views/StaticContent.jsx +0 -36
  76. package/views/Text.d.ts +0 -9
  77. package/views/Text.jsx +0 -4
  78. package/views/macros/DefaultMacro.d.ts +0 -4
  79. package/views/macros/DefaultMacro.jsx +0 -3
  80. package/views/macros/DisableMacro.d.ts +0 -3
  81. package/views/macros/DisableMacro.jsx +0 -2
  82. /package/{query/Shortcut.js → src/query/Shortcut.ts} +0 -0
@@ -0,0 +1,410 @@
1
+ import path from 'path';
2
+ import {LRUCache} from 'lru-cache';
3
+ import {CacheHandler, CacheHandlerContext, CacheHandlerValue} from 'next/dist/server/lib/incremental-cache';
4
+ import {CacheFs} from 'next/dist/shared/lib/utils';
5
+ import {CachedFetchValue, IncrementalCacheValue} from 'next/dist/server/response-cache';
6
+ import type {OutgoingHttpHeaders} from 'http';
7
+ import {getDerivedTags} from 'next/dist/server/lib/incremental-cache/utils';
8
+
9
+ type FileSystemCacheContext = Omit<
10
+ CacheHandlerContext,
11
+ 'fs' | 'serverDistDir'
12
+ > & {
13
+ fs: CacheFs
14
+ serverDistDir: string
15
+ };
16
+
17
+ type TagsManifest = {
18
+ version: 1
19
+ items: { [tag: string]: { keys: string[]; revalidatedAt: number } }
20
+ };
21
+ let memoryCache: LRUCache<string, CacheHandlerValue> | undefined;
22
+ let tagsManifest: TagsManifest | undefined;
23
+
24
+ export default class FileSystemCache implements CacheHandler {
25
+ private fs: FileSystemCacheContext['fs'];
26
+ private flushToDisk?: FileSystemCacheContext['flushToDisk'];
27
+ private serverDistDir: FileSystemCacheContext['serverDistDir'];
28
+ private appDir: boolean;
29
+ private tagsManifestPath?: string;
30
+ private revalidatedTags: string[];
31
+
32
+ constructor(ctx: FileSystemCacheContext) {
33
+ this.fs = ctx.fs;
34
+ this.flushToDisk = ctx.flushToDisk;
35
+ this.serverDistDir = ctx.serverDistDir;
36
+ this.appDir = !!ctx._appDir;
37
+ this.revalidatedTags = ctx.revalidatedTags;
38
+
39
+ if (ctx.maxMemoryCacheSize && !memoryCache) {
40
+ memoryCache = new LRUCache({
41
+ max: ctx.maxMemoryCacheSize,
42
+ maxSize: 10 * ctx.maxMemoryCacheSize, // had to be used sizeCalculation function
43
+ sizeCalculation({value}: { value: IncrementalCacheValue | null }) {
44
+ if (!value) {
45
+ return 25;
46
+ } else if (value.kind === 'REDIRECT') {
47
+ return JSON.stringify(value.props).length;
48
+ } else if (value.kind === 'IMAGE') {
49
+ throw new Error('invariant image should not be incremental-cache');
50
+ } else if (value.kind === 'FETCH') {
51
+ return JSON.stringify(value.data || '').length;
52
+ } else if (value.kind === 'ROUTE') {
53
+ return value.body.length;
54
+ }
55
+ // rough estimate of size of cache value
56
+ return (
57
+ value.html.length + (JSON.stringify(value.pageData)?.length || 0)
58
+ );
59
+ },
60
+ });
61
+ }
62
+ if (this.serverDistDir && this.fs) {
63
+ this.tagsManifestPath = path.join(
64
+ this.serverDistDir,
65
+ '..',
66
+ 'cache',
67
+ 'fetch-cache',
68
+ 'tags-manifest.json',
69
+ );
70
+ this.loadTagsManifest();
71
+ }
72
+ }
73
+
74
+ public clear() {
75
+ memoryCache?.clear();
76
+ }
77
+
78
+ public delete(path: string) {
79
+ return memoryCache?.delete(path);
80
+ }
81
+
82
+ private loadTagsManifest() {
83
+ if (!this.tagsManifestPath || !this.fs || tagsManifest) return;
84
+ try {
85
+ tagsManifest = JSON.parse(
86
+ this.fs.readFileSync(this.tagsManifestPath).toString('utf8'),
87
+ );
88
+ } catch (err: any) {
89
+ tagsManifest = {version: 1, items: {}};
90
+ }
91
+ }
92
+
93
+ async setTags(key: string, tags: string[]) {
94
+ this.loadTagsManifest();
95
+ if (!tagsManifest || !this.tagsManifestPath) {
96
+ return;
97
+ }
98
+
99
+ for (const tag of tags) {
100
+ const data = tagsManifest.items[tag] || {keys: []};
101
+ if (!data.keys.includes(key)) {
102
+ data.keys.push(key);
103
+ }
104
+ tagsManifest.items[tag] = data;
105
+ }
106
+
107
+ try {
108
+ await this.fs.mkdir(path.dirname(this.tagsManifestPath));
109
+ await this.fs.writeFile(
110
+ this.tagsManifestPath,
111
+ JSON.stringify(tagsManifest || {}),
112
+ );
113
+ } catch (err: any) {
114
+ console.warn('Failed to update tags manifest.', err);
115
+ }
116
+ }
117
+
118
+ public async revalidateTag(tag: string) {
119
+ // we need to ensure the tagsManifest is refreshed
120
+ // since separate workers can be updating it at the same
121
+ // time and we can't flush out of sync data
122
+ this.loadTagsManifest();
123
+ if (!tagsManifest || !this.tagsManifestPath) {
124
+ return;
125
+ }
126
+
127
+ const data = tagsManifest.items[tag] || {keys: []};
128
+ data.revalidatedAt = Date.now();
129
+ tagsManifest.items[tag] = data;
130
+
131
+ try {
132
+ await this.fs.mkdir(path.dirname(this.tagsManifestPath));
133
+ await this.fs.writeFile(
134
+ this.tagsManifestPath,
135
+ JSON.stringify(tagsManifest || {}),
136
+ );
137
+ } catch (err: any) {
138
+ console.warn('Failed to update tags manifest.', err);
139
+ }
140
+ }
141
+
142
+ public async get(key: string, fetchCache?: boolean) {
143
+ let data = memoryCache?.get(key);
144
+
145
+ // let's check the disk for seed data
146
+ if (!data && process.env.NEXT_RUNTIME !== 'edge') {
147
+ try {
148
+ const {filePath} = await this.getFsPath({
149
+ pathname: `${key}.body`,
150
+ appDir: true,
151
+ });
152
+ const fileData = await this.fs.readFile(filePath);
153
+ const {mtime} = await this.fs.stat(filePath);
154
+
155
+ const meta = JSON.parse(
156
+ (
157
+ await this.fs.readFile(filePath.replace(/\.body$/, '.meta'))
158
+ ).toString('utf8'),
159
+ );
160
+
161
+ const cacheEntry: CacheHandlerValue = {
162
+ lastModified: mtime.getTime(),
163
+ value: {
164
+ kind: 'ROUTE',
165
+ body: fileData,
166
+ headers: meta.headers,
167
+ status: meta.status,
168
+ },
169
+ };
170
+ return cacheEntry;
171
+ } catch (_) {
172
+ // no .meta data for the related key
173
+ }
174
+
175
+ try {
176
+ const {filePath, isAppPath} = await this.getFsPath({
177
+ pathname: fetchCache ? key : `${key}.html`,
178
+ fetchCache,
179
+ });
180
+ const fileData = (await this.fs.readFile(filePath)).toString('utf-8');
181
+ const {mtime} = await this.fs.stat(filePath);
182
+
183
+ if (fetchCache) {
184
+ const lastModified = mtime.getTime();
185
+ const parsedData: CachedFetchValue = JSON.parse(fileData);
186
+ data = {
187
+ lastModified,
188
+ value: parsedData,
189
+ };
190
+ } else {
191
+ const pageData = isAppPath
192
+ ? (
193
+ await this.fs.readFile(
194
+ (
195
+ await this.getFsPath({
196
+ pathname: `${key}.rsc`,
197
+ appDir: true,
198
+ })
199
+ ).filePath,
200
+ )
201
+ ).toString('utf8')
202
+ : JSON.parse(
203
+ (
204
+ await this.fs.readFile(
205
+ (
206
+ await this.getFsPath({
207
+ pathname: `${key}.json`,
208
+ appDir: false,
209
+ })
210
+ ).filePath,
211
+ )
212
+ ).toString('utf8'),
213
+ );
214
+
215
+ let meta: { status?: number; headers?: OutgoingHttpHeaders } = {};
216
+
217
+ if (isAppPath) {
218
+ try {
219
+ meta = JSON.parse(
220
+ (
221
+ await this.fs.readFile(filePath.replace(/\.html$/, '.meta'))
222
+ ).toString('utf-8'),
223
+ );
224
+ } catch (_) { /* empty */
225
+ }
226
+ }
227
+
228
+ data = {
229
+ lastModified: mtime.getTime(),
230
+ value: {
231
+ kind: 'PAGE',
232
+ html: fileData,
233
+ pageData,
234
+ headers: meta.headers,
235
+ status: meta.status,
236
+ },
237
+ };
238
+ }
239
+
240
+ if (data) {
241
+ memoryCache?.set(key, data);
242
+ }
243
+ } catch (_) {
244
+ // unable to get data from disk
245
+ }
246
+ }
247
+ let cacheTags: undefined | string[];
248
+
249
+ if (data?.value?.kind === 'PAGE') {
250
+ const tagsHeader = data.value.headers?.['x-next-cache-tags'];
251
+
252
+ if (typeof tagsHeader === 'string') {
253
+ cacheTags = tagsHeader.split(',');
254
+ }
255
+ }
256
+
257
+ if (data?.value?.kind === 'PAGE' && cacheTags?.length) {
258
+ this.loadTagsManifest();
259
+ const derivedTags = getDerivedTags(cacheTags || []);
260
+
261
+ const isStale = derivedTags.some((tag) => {
262
+ return (
263
+ tagsManifest?.items[tag]?.revalidatedAt &&
264
+ tagsManifest?.items[tag].revalidatedAt >=
265
+ (data?.lastModified || Date.now())
266
+ );
267
+ });
268
+
269
+ // we trigger a blocking validation if an ISR page
270
+ // had a tag revalidated, if we want to be a background
271
+ // revalidation instead we return data.lastModified = -1
272
+ if (isStale) {
273
+ data = undefined;
274
+ }
275
+ }
276
+
277
+ if (data && data?.value?.kind === 'FETCH') {
278
+ this.loadTagsManifest();
279
+ const innerData = data.value.data;
280
+ const derivedTags = getDerivedTags(innerData.tags || []);
281
+
282
+ const wasRevalidated = derivedTags.some((tag) => {
283
+ if (this.revalidatedTags.includes(tag)) {
284
+ return true;
285
+ }
286
+
287
+ return (
288
+ tagsManifest?.items[tag]?.revalidatedAt &&
289
+ tagsManifest?.items[tag].revalidatedAt >=
290
+ (data?.lastModified || Date.now())
291
+ );
292
+ });
293
+ // When revalidate tag is called we don't return
294
+ // stale data so it's updated right away
295
+ if (wasRevalidated) {
296
+ data = undefined;
297
+ }
298
+ }
299
+
300
+ return data || null;
301
+ }
302
+
303
+ public async set(key: string, data: CacheHandlerValue['value']) {
304
+ memoryCache?.set(key, {
305
+ value: data,
306
+ lastModified: Date.now(),
307
+ });
308
+ if (!this.flushToDisk) return;
309
+
310
+ if (data?.kind === 'ROUTE') {
311
+ const {filePath} = await this.getFsPath({
312
+ pathname: `${key}.body`,
313
+ appDir: true,
314
+ });
315
+ await this.fs.mkdir(path.dirname(filePath));
316
+ await this.fs.writeFile(filePath, data.body);
317
+ await this.fs.writeFile(
318
+ filePath.replace(/\.body$/, '.meta'),
319
+ JSON.stringify({headers: data.headers, status: data.status}),
320
+ );
321
+ return;
322
+ }
323
+
324
+ if (data?.kind === 'PAGE') {
325
+ const isAppPath = typeof data.pageData === 'string';
326
+ const {filePath: htmlPath} = await this.getFsPath({
327
+ pathname: `${key}.html`,
328
+ appDir: isAppPath,
329
+ });
330
+ await this.fs.mkdir(path.dirname(htmlPath));
331
+ await this.fs.writeFile(htmlPath, data.html);
332
+
333
+ await this.fs.writeFile(
334
+ (
335
+ await this.getFsPath({
336
+ pathname: `${key}.${isAppPath ? 'rsc' : 'json'}`,
337
+ appDir: isAppPath,
338
+ })
339
+ ).filePath,
340
+ isAppPath ? data.pageData : JSON.stringify(data.pageData),
341
+ );
342
+
343
+ if (data.headers || data.status) {
344
+ await this.fs.writeFile(
345
+ htmlPath.replace(/\.html$/, '.meta'),
346
+ JSON.stringify({
347
+ headers: data.headers,
348
+ status: data.status,
349
+ }),
350
+ );
351
+ }
352
+ } else if (data?.kind === 'FETCH') {
353
+ const {filePath} = await this.getFsPath({
354
+ pathname: key,
355
+ fetchCache: true,
356
+ });
357
+ await this.fs.mkdir(path.dirname(filePath));
358
+ await this.fs.writeFile(filePath, JSON.stringify(data));
359
+ await this.setTags(key, data.data.tags || []);
360
+ }
361
+ }
362
+
363
+ public async getFsPath({
364
+ pathname,
365
+ appDir,
366
+ fetchCache,
367
+ }: {
368
+ pathname: string
369
+ appDir?: boolean
370
+ fetchCache?: boolean
371
+ }): Promise<{
372
+ filePath: string
373
+ isAppPath: boolean
374
+ }> {
375
+ if (fetchCache) {
376
+ // we store in .next/cache/fetch-cache so it can be persisted
377
+ // across deploys
378
+ return {
379
+ filePath: path.join(
380
+ this.serverDistDir,
381
+ '..',
382
+ 'cache',
383
+ 'fetch-cache',
384
+ pathname,
385
+ ),
386
+ isAppPath: false,
387
+ };
388
+ }
389
+ const isAppPath = false;
390
+ const filePath = path.join(this.serverDistDir, 'pages', pathname);
391
+
392
+ if (!this.appDir || appDir === false)
393
+ return {
394
+ filePath,
395
+ isAppPath,
396
+ };
397
+ try {
398
+ await this.fs.readFile(filePath);
399
+ return {
400
+ filePath,
401
+ isAppPath,
402
+ };
403
+ } catch (err) {
404
+ return {
405
+ filePath: path.join(this.serverDistDir, 'app', pathname),
406
+ isAppPath: true,
407
+ };
408
+ }
409
+ }
410
+ }
@@ -0,0 +1,50 @@
1
+ import * as fs from 'fs';
2
+ import {IncrementalCache} from 'next/dist/server/lib/incremental-cache';
3
+ import ClearableFileCache from './ClearableFileCache';
4
+
5
+ const getCacheHandler = (cache: IncrementalCache): ClearableFileCache => {
6
+ return cache.cacheHandler as ClearableFileCache;
7
+ };
8
+
9
+ export const purgeCache = async (cache: IncrementalCache, pathname?: string) => {
10
+ if (pathname) {
11
+ return purgePath(cache, pathname);
12
+ } else {
13
+ return purgeAll(cache);
14
+ }
15
+ };
16
+
17
+ const purgePath = async (cache: IncrementalCache, pathname: string) => {
18
+ const handler = getCacheHandler(cache);
19
+ const fsPathObj = await handler.getFsPath({pathname});
20
+ try {
21
+ /* Delete entry in cache */
22
+ handler.delete(pathname);
23
+
24
+ /* Delete files from disc */
25
+ fs.unlinkSync(`${fsPathObj.filePath}.html`);
26
+ fs.unlinkSync(`${fsPathObj.filePath}.json`);
27
+
28
+ console.info(`\nCache deleted for '${fsPathObj.filePath}'\n`);
29
+ } catch (err) {
30
+ console.error(`Could not delete cache of '${fsPathObj.filePath}':`, err);
31
+ }
32
+ };
33
+
34
+ const purgeAll = async (cache: IncrementalCache) => {
35
+ const handler = getCacheHandler(cache);
36
+ try {
37
+ /* Purge cache */
38
+ handler.clear();
39
+
40
+ const {filePath: pagesRoot} = await handler.getFsPath({pathname: ''});
41
+
42
+ if (fs.existsSync(pagesRoot)) {
43
+ fs.rmSync(pagesRoot, {recursive: true});
44
+ }
45
+
46
+ console.info('\nCache was successfully purged\n');
47
+ } catch (err) {
48
+ console.error('Could not purge cache:', err);
49
+ }
50
+ };
@@ -0,0 +1,74 @@
1
+ import {createServer} from 'http';
2
+ import {purgeCache} from './cache';
3
+ import {NextServer} from 'next/dist/server/next';
4
+ import path from 'path';
5
+ import {NextConfig} from 'next/dist/server/config-shared';
6
+
7
+ const hostname = process.env.HOST || '127.0.0.1';
8
+ const dev = process.env.NODE_ENV !== 'production';
9
+ const port = process.env.PORT && parseInt(process.env.PORT, 10) || (dev ? 3000 : 4242);
10
+
11
+ export const PURGE_CACHE_URL = '/_/enonic/cache/purge';
12
+
13
+ export const withEnonicCache = function (config: any) {
14
+ const exp = config.experimental || {};
15
+ exp.isrMemoryCacheSize = exp.isrMemoryCacheSize || 1000000;
16
+ exp.incrementalCacheHandlerPath = path.resolve(__dirname, 'ClearableFileCache.js');
17
+ config.experimental = exp;
18
+ return config;
19
+ };
20
+
21
+ // Not typed to prevent collision of local types with end-user ones
22
+ export default async (next: (options: any) => any) => {
23
+ const nextServer = next({dev, hostname, port}) as NextServer;
24
+ const nextHandler = nextServer.getRequestHandler();
25
+ return await nextServer.prepare().then(async () => {
26
+ const nextNodeServer = await nextServer['getServer']?.();
27
+ if (!nextNodeServer) {
28
+ console.error('Unable to access incremental cache, cache purge endpoint will be disabled');
29
+ return nextServer;
30
+ }
31
+ const opts: NextConfig = nextNodeServer['serverOptions'].conf;
32
+ const purgeUrl = (opts?.basePath || '') + PURGE_CACHE_URL;
33
+
34
+ console.info(`Staring cache purge endpoint at ${purgeUrl}...`);
35
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
36
+ const server = createServer(async (req, res) => {
37
+ const parsedUrl = new URL(`http://${hostname}:${port}${req.url || ''}`);
38
+ if (parsedUrl.pathname !== purgeUrl) {
39
+ await nextHandler(req, res);
40
+ } else if (dev) {
41
+ console.warn('\nCache clearing is not available in DEV mode.\n');
42
+
43
+ res.setHeader('Content-Type', 'application/json');
44
+ res.end(JSON.stringify({purged: false}));
45
+ } else {
46
+ const tokenParam = parsedUrl.searchParams.get('token');
47
+ if (tokenParam !== process.env.ENONIC_API_TOKEN) {
48
+ // XP hijacks 401 to show login page, so send 407 instead
49
+ res.statusCode = 407;
50
+ res.end(JSON.stringify({message: 'Invalid token'}));
51
+ return;
52
+ }
53
+
54
+ const cache = nextNodeServer.getIncrementalCache({
55
+ requestHeaders: Object.assign({}, req.headers),
56
+ });
57
+
58
+ const pathParam = parsedUrl.searchParams.get('path') || undefined;
59
+ await purgeCache(cache, pathParam);
60
+
61
+ res.setHeader('Content-Type', 'application/json');
62
+ res.end(JSON.stringify({purged: true}));
63
+ }
64
+
65
+ }).listen(port, hostname, () => {
66
+ console.info(`Server ready on ${hostname}:${port}`);
67
+ }).on('error', (e) => {
68
+ console.error('Server error:', e);
69
+ server.close();
70
+ });
71
+
72
+ return nextServer;
73
+ });
74
+ };
@@ -0,0 +1,23 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es5",
4
+ "module": "commonjs",
5
+ "skipLibCheck": true,
6
+ "moduleResolution": "Node",
7
+ "lib": [
8
+ "es6"
9
+ ],
10
+ "strict": true,
11
+ "esModuleInterop": true,
12
+ "allowJs": true,
13
+ "noImplicitAny": true,
14
+ "outDir": "../dist/server",
15
+ "resolveJsonModule": true,
16
+ "declaration": true
17
+ },
18
+ "include": [
19
+ "../next-env.d.ts",
20
+ "**/*.ts"
21
+ ],
22
+ "exclude": []
23
+ }
package/setversion.js ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+
3
+ "use strict";
4
+
5
+ const { execSync } = require("child_process");
6
+ const version = execSync("git describe --tags --abbrev=0").toString().slice(1).trim();
7
+
8
+ execSync(`awk -v ver="${version}" '{gsub(/"version": ".*"/,"\\"version\\": \\""ver"\\"")}1' package.json > tmp && mv tmp package.json`);
@@ -0,0 +1,11 @@
1
+ module.exports = {
2
+ extends: ['../.eslintrc.js'],
3
+ overrides: [{
4
+ extends: '../.eslint-childrc.js',
5
+ files: ['*.ts', '*.tsx'],
6
+ parserOptions: {
7
+ tsconfigRootDir: __dirname,
8
+ project: './tsconfig.json',
9
+ },
10
+ }],
11
+ };