@notifiles/sdk 1.1.17 → 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/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@notifiles/sdk",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.2.0",
|
|
5
5
|
"description": "",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "adoucoure",
|
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
},
|
|
51
51
|
"keywords": [],
|
|
52
52
|
"dependencies": {
|
|
53
|
+
"@lifeomic/attempt": "^3.1.0",
|
|
53
54
|
"@microflash/remark-figure-caption": "^2.0.2",
|
|
54
55
|
"@stdlib/string-replace": "^0.2.1",
|
|
55
56
|
"axios": "^1.6.1",
|
|
@@ -3,7 +3,7 @@ import fs from 'fs';
|
|
|
3
3
|
import translate from './translate.js';
|
|
4
4
|
import htmlToHast from '../../../../lib/remark/htmlToHast.js';
|
|
5
5
|
//#TODO: https://github.com/anfragment/react-email-dynamic
|
|
6
|
-
import
|
|
6
|
+
import { retry } from '@lifeomic/attempt';
|
|
7
7
|
|
|
8
8
|
export default async (props) => {
|
|
9
9
|
const { entry } = props
|
|
@@ -90,27 +90,32 @@ export default async (props) => {
|
|
|
90
90
|
subject,
|
|
91
91
|
'utf-8'
|
|
92
92
|
)
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
await retry(async (context) => {
|
|
95
96
|
await fs.promises.cp(
|
|
96
97
|
`${path}/manifest.json`,
|
|
97
98
|
buildPaths.manifestFileNameBuilt
|
|
98
99
|
)
|
|
99
100
|
return true
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
101
|
+
}, {
|
|
102
|
+
delay: 200,
|
|
103
|
+
maxAttempts: 3,
|
|
104
|
+
initialDelay: 0,
|
|
105
|
+
minDelay: 0,
|
|
106
|
+
maxDelay: 0,
|
|
107
|
+
factor: 0,
|
|
108
|
+
timeout: 0,
|
|
109
|
+
jitter: false,
|
|
110
|
+
initialJitter: false,
|
|
111
|
+
handleError: null,
|
|
112
|
+
handleTimeout: null,
|
|
113
|
+
beforeAttempt: null,
|
|
114
|
+
calculateDelay: null
|
|
115
|
+
});
|
|
116
|
+
} catch (err) {
|
|
117
|
+
console.log(`Attempt ${err} failed`);
|
|
104
118
|
}
|
|
105
|
-
pRetry(run, {
|
|
106
|
-
retries: 15,
|
|
107
|
-
onFailedAttempt: error => {
|
|
108
|
-
console.log(`Attempt ${error.attemptNumber} failed. There are ${error.retriesLeft} retries left.`);
|
|
109
|
-
// 1st request => Attempt 1 failed. There are 4 retries left.
|
|
110
|
-
// 2nd request => Attempt 2 failed. There are 3 retries left.
|
|
111
|
-
// …
|
|
112
|
-
},
|
|
113
|
-
})
|
|
114
119
|
|
|
115
120
|
const child = htmlToHast({ data: body })
|
|
116
121
|
const hast = await perform({
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import fsPath from 'path'
|
|
3
|
+
import { createHash } from 'crypto'
|
|
4
|
+
import checkFileExists from '../../../lib/fs/checkFileExists.js'
|
|
5
|
+
import importJSONAsync from '../../../lib/fs/importJSONAsync.js'
|
|
6
|
+
|
|
7
|
+
const CACHE_DIR_NAME = '.cache'
|
|
8
|
+
const CACHE_FILE_NAME = 'template-update.json'
|
|
9
|
+
const IGNORED_DIRECTORIES = new Set([CACHE_DIR_NAME, '.build'])
|
|
10
|
+
const IGNORED_FILES = new Set(['.DS_Store'])
|
|
11
|
+
|
|
12
|
+
const sortByName = (a, b) => a.name.localeCompare(b.name)
|
|
13
|
+
|
|
14
|
+
const digestDirectory = async ({
|
|
15
|
+
rootPath,
|
|
16
|
+
currentPath,
|
|
17
|
+
hash
|
|
18
|
+
}) => {
|
|
19
|
+
const entries = await fs.promises.readdir(currentPath, { withFileTypes: true })
|
|
20
|
+
entries.sort(sortByName)
|
|
21
|
+
|
|
22
|
+
for (const entry of entries) {
|
|
23
|
+
if (entry.isDirectory()) {
|
|
24
|
+
if (IGNORED_DIRECTORIES.has(entry.name)) {
|
|
25
|
+
continue
|
|
26
|
+
}
|
|
27
|
+
await digestDirectory({
|
|
28
|
+
rootPath,
|
|
29
|
+
currentPath: fsPath.join(currentPath, entry.name),
|
|
30
|
+
hash
|
|
31
|
+
})
|
|
32
|
+
continue
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (!entry.isFile() || IGNORED_FILES.has(entry.name)) {
|
|
36
|
+
continue
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const filePath = fsPath.join(currentPath, entry.name)
|
|
40
|
+
const relativePath = fsPath.relative(rootPath, filePath)
|
|
41
|
+
const content = await fs.promises.readFile(filePath)
|
|
42
|
+
hash.update(relativePath)
|
|
43
|
+
hash.update(content)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const computeTemplateHash = async ({
|
|
48
|
+
path
|
|
49
|
+
}) => {
|
|
50
|
+
try {
|
|
51
|
+
if (!(await checkFileExists(path))) {
|
|
52
|
+
return null
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const hash = createHash('sha256')
|
|
56
|
+
await digestDirectory({
|
|
57
|
+
rootPath: path,
|
|
58
|
+
currentPath: path,
|
|
59
|
+
hash,
|
|
60
|
+
})
|
|
61
|
+
return hash.digest('hex')
|
|
62
|
+
} catch (e) {
|
|
63
|
+
console.error(e)
|
|
64
|
+
}
|
|
65
|
+
return null
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export const getCachedTemplateHash = async ({
|
|
69
|
+
path
|
|
70
|
+
}) => {
|
|
71
|
+
try {
|
|
72
|
+
const cachePath = fsPath.join(path, CACHE_DIR_NAME, CACHE_FILE_NAME)
|
|
73
|
+
if (!(await checkFileExists(cachePath))) {
|
|
74
|
+
return null
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const cacheContent = await importJSONAsync(cachePath)
|
|
78
|
+
if (!cacheContent || !cacheContent.hash) {
|
|
79
|
+
return null
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return cacheContent.hash
|
|
83
|
+
} catch (e) {
|
|
84
|
+
console.error(e)
|
|
85
|
+
}
|
|
86
|
+
return null
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export const updateTemplateHashCache = async ({
|
|
90
|
+
path,
|
|
91
|
+
hash,
|
|
92
|
+
}) => {
|
|
93
|
+
try {
|
|
94
|
+
const cacheDir = fsPath.join(path, CACHE_DIR_NAME)
|
|
95
|
+
await fs.promises.mkdir(cacheDir, { recursive: true })
|
|
96
|
+
|
|
97
|
+
const cachePath = fsPath.join(cacheDir, CACHE_FILE_NAME)
|
|
98
|
+
const payload = {
|
|
99
|
+
hash,
|
|
100
|
+
updatedAt: (new Date()).toISOString(),
|
|
101
|
+
}
|
|
102
|
+
await fs.promises.writeFile(cachePath, JSON.stringify(payload, null, 2))
|
|
103
|
+
return true
|
|
104
|
+
} catch (e) {
|
|
105
|
+
console.error(e)
|
|
106
|
+
}
|
|
107
|
+
return false
|
|
108
|
+
}
|
|
@@ -7,19 +7,31 @@ import optimize from '../optimize/entry.js'
|
|
|
7
7
|
import cloudify from '../cloudify/entry.js'
|
|
8
8
|
import adaptSettings from '../../lib/adaptSettings.js'
|
|
9
9
|
import attach from '../attach/entry.js'
|
|
10
|
+
import {
|
|
11
|
+
computeTemplateHash,
|
|
12
|
+
getCachedTemplateHash,
|
|
13
|
+
updateTemplateHashCache
|
|
14
|
+
} from './lib/cache.js'
|
|
10
15
|
|
|
11
16
|
export default async ({
|
|
12
17
|
path,
|
|
13
|
-
settings
|
|
18
|
+
settings = {},
|
|
19
|
+
force = false
|
|
14
20
|
}) => {
|
|
15
21
|
adaptSettings({ settings })
|
|
16
22
|
let entries = await getEntries({
|
|
17
23
|
path,
|
|
18
24
|
settings
|
|
19
25
|
})
|
|
26
|
+
if (!entries || !entries.length) {
|
|
27
|
+
return true
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const forceUpdate = force || settings.forceUpdate
|
|
20
31
|
|
|
21
32
|
for (var i in entries) {
|
|
22
33
|
let entry = entries[i]
|
|
34
|
+
|
|
23
35
|
switch (entry.manifest.status) {
|
|
24
36
|
case 'pause': {
|
|
25
37
|
continue
|
|
@@ -27,6 +39,13 @@ export default async ({
|
|
|
27
39
|
default: break
|
|
28
40
|
}
|
|
29
41
|
|
|
42
|
+
const cachedHash = await getCachedTemplateHash({ path: entry.path })
|
|
43
|
+
const currentHash = await computeTemplateHash({ path: entry.path })
|
|
44
|
+
if (!forceUpdate && cachedHash && currentHash && cachedHash === currentHash) {
|
|
45
|
+
console.log(`[notifiles] Skip ${entry.slug || entry.name || entry.path}: no changes detected`)
|
|
46
|
+
continue
|
|
47
|
+
}
|
|
48
|
+
|
|
30
49
|
entry = (await format({ entry, settings })).entry
|
|
31
50
|
entry = (await build({ entry, settings })).entry
|
|
32
51
|
entry = (await consolidate({ entry, settings })).entry
|
|
@@ -37,6 +56,11 @@ export default async ({
|
|
|
37
56
|
continue
|
|
38
57
|
}
|
|
39
58
|
entry = (await sync({ entry, settings })).entry
|
|
59
|
+
|
|
60
|
+
const newHash = await computeTemplateHash({ path: entry.path })
|
|
61
|
+
if (newHash) {
|
|
62
|
+
await updateTemplateHashCache({ path: entry.path, hash: newHash })
|
|
63
|
+
}
|
|
40
64
|
}
|
|
41
65
|
|
|
42
66
|
return true
|