@notifiles/sdk 1.1.18 → 1.3.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.1.18",
4
+ "version": "1.3.0",
5
5
  "description": "",
6
6
  "author": {
7
7
  "name": "adoucoure",
@@ -49,7 +49,7 @@ export default async ({
49
49
  destination,
50
50
  filePath,
51
51
  err => {
52
- console.log(filePath, 'uploaded')
52
+ console.log('🮱 ', filePath, 'uploaded')
53
53
  if (err) {
54
54
  console.error(err)
55
55
  reject(err)
@@ -1,6 +1,28 @@
1
1
  import fs from "fs"
2
2
  import checkFileExists from "./checkFileExists.js"
3
3
 
4
+ const expandEnvPlaceholders = (value) => {
5
+ if (typeof value === 'string') {
6
+ return value.replace(/\$\{process\.env\.([A-Z0-9_]+)\}/g, (match, envKey) => {
7
+ const envValue = process.env[envKey]
8
+ return envValue !== undefined ? envValue : match
9
+ })
10
+ }
11
+
12
+ if (Array.isArray(value)) {
13
+ return value.map(expandEnvPlaceholders)
14
+ }
15
+
16
+ if (value && typeof value === 'object') {
17
+ return Object.entries(value).reduce((acc, [key, val]) => {
18
+ acc[key] = expandEnvPlaceholders(val)
19
+ return acc
20
+ }, {})
21
+ }
22
+
23
+ return value
24
+ }
25
+
4
26
  export default async _url => {
5
27
  // try {
6
28
  if (!(await checkFileExists(_url))) {
@@ -8,7 +30,7 @@ export default async _url => {
8
30
  }
9
31
  const fileUrl = new URL(_url, import.meta.url)
10
32
  const parsedPackageJSON = JSON.parse(await fs.promises.readFile(fileUrl, 'utf8'))
11
- return parsedPackageJSON
33
+ return expandEnvPlaceholders(parsedPackageJSON)
12
34
  // } catch (e) {
13
35
  // console.log("[notifiles]", `importJSONAsync → `, e)
14
36
  // return null
@@ -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