@jsenv/core 26.0.0 → 26.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/core",
3
- "version": "26.0.0",
3
+ "version": "26.0.1",
4
4
  "description": "Tool to develop, test and build js projects",
5
5
  "license": "MIT",
6
6
  "repository": {
package/readme.md CHANGED
@@ -291,11 +291,6 @@ _jsenv.config.mjs_ is meant to share configuration, other files will simply impo
291
291
  import { buildProject } from '@jsenv/core'
292
292
 
293
293
  + import { projectDirectoryUrl } from "./jsenv.config.mjs"
294
-
295
- await buildProject({
296
- - projectDirectoryUrl: new URL('./', import.meta.url)
297
- + projectDirectoryUrl
298
- })
299
294
  ```
300
295
 
301
296
  > We recommend to use ".mjs" extension when a file is written for Node.js but you can name the file as you want, "jsenv.config.js" is fine too.
@@ -324,10 +319,10 @@ Jsenv relies on **standard web features**. Each standard listed below is potenti
324
319
 
325
320
  - `<script type="module">`
326
321
  - `<script type="importmap">`
327
- - top level await
328
- - import.meta.url
329
322
  - dynamic imports
323
+ - import.meta.url
330
324
  - import assertions
325
+ - top level await
331
326
 
332
327
  ## When to use it?
333
328
 
@@ -14,6 +14,7 @@ export const compileFile = async ({
14
14
  logger,
15
15
 
16
16
  projectDirectoryUrl,
17
+ jsenvDirectory,
17
18
  jsenvRemoteDirectory,
18
19
  originalFileUrl,
19
20
  compiledFileUrl,
@@ -103,6 +104,7 @@ export const compileFile = async ({
103
104
  // when serving sourcemap files
104
105
  await updateCompileCache({
105
106
  logger,
107
+ jsenvDirectory,
106
108
  meta,
107
109
  compileResult,
108
110
  compileResultStatus,
@@ -138,6 +138,7 @@ export const createCompiledFileService = ({
138
138
  logger,
139
139
 
140
140
  projectDirectoryUrl,
141
+ jsenvDirectory,
141
142
  jsenvRemoteDirectory,
142
143
  originalFileUrl,
143
144
  compiledFileUrl,
@@ -38,6 +38,7 @@ export const setupJsenvDirectory = async ({
38
38
  )
39
39
  }
40
40
 
41
+ const compiledFileWriteSignal = { onwrite: () => {} }
41
42
  if (compileServerCanWriteOnFilesystem) {
42
43
  if (jsenvDirectoryClean) {
43
44
  await ensureEmptyDirectory(jsenvDirectoryUrl)
@@ -46,9 +47,15 @@ export const setupJsenvDirectory = async ({
46
47
  logger,
47
48
  jsenvDirectoryUrl,
48
49
  jsenvDirectoryMetaFileUrl,
49
- writeMetaFile,
50
50
  jsenvDirectoryMeta,
51
51
  })
52
+ // We want ".jsenv" directory to appear on the filesystem only
53
+ // if there is a compiled file inside (and not immediatly when compile server starts)
54
+ // To do this we wait for a file to be written to write "__jsenv_meta__.json" file
55
+ compiledFileWriteSignal.onwrite = async () => {
56
+ compiledFileWriteSignal.onwrite = () => {}
57
+ await writeMetaFile()
58
+ }
52
59
  }
53
60
 
54
61
  /*
@@ -88,7 +95,7 @@ export const setupJsenvDirectory = async ({
88
95
  }
89
96
  return existingCompileId
90
97
  }
91
- const compileIdBase = generateCompileId({ compileProfile })
98
+ const compileIdBase = generateCompileId({ compileProfile, runtime })
92
99
  let compileId = compileIdBase
93
100
  let integer = 1
94
101
  while (existingCompileIds.includes(compileId)) {
@@ -106,13 +113,20 @@ export const setupJsenvDirectory = async ({
106
113
  return {
107
114
  compileDirectories,
108
115
  getOrCreateCompileId,
116
+ compiledFileWriteSignal,
109
117
  }
110
118
  }
111
119
 
112
- const generateCompileId = ({ compileProfile }) => {
120
+ const generateCompileId = ({ compileProfile, runtime }) => {
121
+ if (runtime.name === "jsenv_build") {
122
+ return `out_build`
123
+ }
113
124
  if (compileProfile.missingFeatures["transform-instrument"]) {
114
125
  return `out_instrumented`
115
126
  }
127
+ if (compileProfile.moduleOutFormat === "systemjs") {
128
+ return `out_system`
129
+ }
116
130
  return `out`
117
131
  }
118
132
 
@@ -121,7 +135,6 @@ const applyFileSystemEffects = async ({
121
135
  jsenvDirectoryUrl,
122
136
  jsenvDirectoryMetaFileUrl,
123
137
  jsenvDirectoryMeta,
124
- writeMetaFile,
125
138
  }) => {
126
139
  try {
127
140
  const source = await readFile(jsenvDirectoryMetaFileUrl)
@@ -130,7 +143,6 @@ const applyFileSystemEffects = async ({
130
143
  `${jsenvDirectoryMetaFileUrl} is empty -> clean ${jsenvDirectoryUrl} directory`,
131
144
  )
132
145
  await ensureEmptyDirectory(jsenvDirectoryUrl)
133
- await writeMetaFile()
134
146
  return
135
147
  }
136
148
  const jsenvDirectoryMetaPrevious = JSON.parse(source)
@@ -144,7 +156,6 @@ const applyFileSystemEffects = async ({
144
156
  `compile context has changed -> clean ${jsenvDirectoryUrl} directory`,
145
157
  )
146
158
  await ensureEmptyDirectory(jsenvDirectoryUrl)
147
- await writeMetaFile()
148
159
  return
149
160
  }
150
161
  // reuse existing compile directories
@@ -158,7 +169,6 @@ const applyFileSystemEffects = async ({
158
169
  `${jsenvDirectoryMetaFileUrl} not found -> clean ${jsenvDirectoryUrl} directory`,
159
170
  )
160
171
  await ensureEmptyDirectory(jsenvDirectoryUrl)
161
- await writeMetaFile()
162
172
  return
163
173
  }
164
174
  if (e.name === "SyntaxError") {
@@ -166,7 +176,6 @@ const applyFileSystemEffects = async ({
166
176
  `${jsenvDirectoryMetaFileUrl} syntax error -> clean ${jsenvDirectoryUrl} directory`,
167
177
  )
168
178
  await ensureEmptyDirectory(jsenvDirectoryUrl)
169
- await writeMetaFile()
170
179
  return
171
180
  }
172
181
  throw e
@@ -10,6 +10,7 @@ import { getMetaJsonFileUrl } from "./compile_asset.js"
10
10
 
11
11
  export const updateCompileCache = async ({
12
12
  logger,
13
+ jsenvDirectory,
13
14
  meta,
14
15
  compiledFileUrl,
15
16
  compileResult,
@@ -17,6 +18,9 @@ export const updateCompileCache = async ({
17
18
  }) => {
18
19
  const isNew = compileResultStatus === "created"
19
20
  const isUpdated = compileResultStatus === "updated"
21
+ if (!isNew && !isUpdated) {
22
+ return
23
+ }
20
24
  const {
21
25
  compiledSource,
22
26
  contentType,
@@ -26,125 +30,102 @@ export const updateCompileCache = async ({
26
30
  assetsContent,
27
31
  dependencies,
28
32
  } = compileResult
29
-
30
33
  const promises = []
31
- if (isNew || isUpdated) {
32
- // ensure source that does not leads to concrete files are not capable to invalidate the cache
33
- const sourcesToRemove = sources.filter((sourceFileUrl) => {
34
- return (
35
- sourceFileUrl.startsWith("file://") && !testFilePresence(sourceFileUrl)
36
- )
37
- })
38
- const sourceNotFoundCount = sourcesToRemove.length
39
- if (sourceNotFoundCount > 0) {
40
- logger.warn(`SOURCE_META_NOT_FOUND: ${sourceNotFoundCount} source file(s) not found.
34
+ // ensure source that does not leads to concrete files are not capable to invalidate the cache
35
+ const sourcesToRemove = sources.filter((sourceFileUrl) => {
36
+ return (
37
+ sourceFileUrl.startsWith("file://") && !testFilePresence(sourceFileUrl)
38
+ )
39
+ })
40
+ const sourceNotFoundCount = sourcesToRemove.length
41
+ if (sourceNotFoundCount > 0) {
42
+ logger.warn(`SOURCE_META_NOT_FOUND: ${sourceNotFoundCount} source file(s) not found.
41
43
  --- consequence ---
42
44
  cache will be reused even if one of the source file is modified
43
45
  --- source files not found ---
44
46
  ${sourcesToRemove.join(`\n`)}`)
45
- sourcesToRemove.forEach((url) => {
46
- const sourceIndex = sources.indexOf(url)
47
- if (sourceIndex) {
48
- sources.splice(sourceIndex, 1)
49
- sourcesContent.splice(sourceIndex, 1)
50
- }
51
- })
52
- }
53
-
54
- const { writeCompiledSourceFile = true, writeAssetsFile = true } =
55
- compileResult
56
-
57
- if (writeCompiledSourceFile) {
58
- logger.debug(
59
- `write compiled file at ${urlToFileSystemPath(compiledFileUrl)}`,
60
- )
61
- promises.push(
62
- writeFileContent(compiledFileUrl, compiledSource, {
63
- fileLikelyNotFound: isNew,
64
- }).then(() => {
65
- const mtime = compileResult.compiledMtime
66
- // when compileResult.compiledMtime do not exists it means
67
- // the client is not interested in it so
68
- // -> moment we write the file is not important
69
- // -> There is no need to update mtime
70
- if (mtime) {
71
- utimesSync(
72
- urlToFileSystemPath(compiledFileUrl),
73
- new Date(mtime),
74
- new Date(mtime),
75
- )
76
- }
77
- }),
78
- )
79
- }
80
-
81
- if (writeAssetsFile) {
82
- promises.push(
83
- ...assets.map((assetFileUrl, index) => {
84
- logger.debug(
85
- `write compiled file asset at ${urlToFileSystemPath(assetFileUrl)}`,
86
- )
87
- return writeFileContent(assetFileUrl, assetsContent[index], {
88
- fileLikelyNotFound: isNew,
89
- })
90
- }),
91
- )
92
- }
93
- }
94
-
95
- const metaJsonFileUrl = getMetaJsonFileUrl(compiledFileUrl)
96
-
97
- if (isNew || isUpdated) {
98
- let latestMeta
99
-
100
- const sourceAndAssetProps = {
101
- sources: sources.map((source) =>
102
- urlToRelativeUrl(source, metaJsonFileUrl),
103
- ),
104
- sourcesEtag: sourcesContent.map((sourceContent) =>
105
- bufferToEtag(Buffer.from(sourceContent)),
106
- ),
107
- assets: assets.map((asset) => urlToRelativeUrl(asset, metaJsonFileUrl)),
108
- assetsEtag: assetsContent.map((assetContent) =>
109
- bufferToEtag(Buffer.from(assetContent)),
110
- ),
111
- dependencies: dependencies.filter((dep) => {
112
- return !dep.startsWith("data:")
113
- }),
114
- }
115
-
116
- if (isNew) {
117
- latestMeta = {
118
- contentType,
119
- ...sourceAndAssetProps,
120
- createdMs: Number(Date.now()),
121
- lastModifiedMs: Number(Date.now()),
122
- }
123
- } else if (isUpdated) {
124
- latestMeta = {
125
- ...meta,
126
- ...sourceAndAssetProps,
127
- lastModifiedMs: Number(Date.now()),
128
- }
129
- } else {
130
- latestMeta = {
131
- ...meta,
47
+ sourcesToRemove.forEach((url) => {
48
+ const sourceIndex = sources.indexOf(url)
49
+ if (sourceIndex) {
50
+ sources.splice(sourceIndex, 1)
51
+ sourcesContent.splice(sourceIndex, 1)
132
52
  }
133
- }
134
-
53
+ })
54
+ }
55
+ const { writeCompiledSourceFile = true, writeAssetsFile = true } =
56
+ compileResult
57
+ if (writeCompiledSourceFile) {
135
58
  logger.debug(
136
- `write compiled file meta at ${urlToFileSystemPath(metaJsonFileUrl)}`,
59
+ `write compiled file at ${urlToFileSystemPath(compiledFileUrl)}`,
60
+ )
61
+ promises.push(
62
+ writeFileContent(compiledFileUrl, compiledSource, {
63
+ fileLikelyNotFound: isNew,
64
+ }).then(() => {
65
+ const mtime = compileResult.compiledMtime
66
+ // when compileResult.compiledMtime do not exists it means
67
+ // the client is not interested in it so
68
+ // -> moment we write the file is not important
69
+ // -> There is no need to update mtime
70
+ if (mtime) {
71
+ utimesSync(
72
+ urlToFileSystemPath(compiledFileUrl),
73
+ new Date(mtime),
74
+ new Date(mtime),
75
+ )
76
+ }
77
+ }),
137
78
  )
79
+ }
80
+ if (writeAssetsFile) {
138
81
  promises.push(
139
- writeFileContent(
140
- metaJsonFileUrl,
141
- JSON.stringify(latestMeta, null, " "),
142
- {
82
+ ...assets.map((assetFileUrl, index) => {
83
+ logger.debug(
84
+ `write compiled file asset at ${urlToFileSystemPath(assetFileUrl)}`,
85
+ )
86
+ return writeFileContent(assetFileUrl, assetsContent[index], {
143
87
  fileLikelyNotFound: isNew,
144
- },
145
- ),
88
+ })
89
+ }),
146
90
  )
147
91
  }
148
-
149
- return Promise.all(promises)
92
+ const metaJsonFileUrl = getMetaJsonFileUrl(compiledFileUrl)
93
+ let latestMeta
94
+ const sourceAndAssetProps = {
95
+ sources: sources.map((source) => urlToRelativeUrl(source, metaJsonFileUrl)),
96
+ sourcesEtag: sourcesContent.map((sourceContent) =>
97
+ bufferToEtag(Buffer.from(sourceContent)),
98
+ ),
99
+ assets: assets.map((asset) => urlToRelativeUrl(asset, metaJsonFileUrl)),
100
+ assetsEtag: assetsContent.map((assetContent) =>
101
+ bufferToEtag(Buffer.from(assetContent)),
102
+ ),
103
+ dependencies: dependencies.filter((dep) => {
104
+ return !dep.startsWith("data:")
105
+ }),
106
+ }
107
+ if (isNew) {
108
+ latestMeta = {
109
+ contentType,
110
+ ...sourceAndAssetProps,
111
+ createdMs: Number(Date.now()),
112
+ lastModifiedMs: Number(Date.now()),
113
+ }
114
+ } else if (isUpdated) {
115
+ latestMeta = {
116
+ ...meta,
117
+ ...sourceAndAssetProps,
118
+ lastModifiedMs: Number(Date.now()),
119
+ }
120
+ }
121
+ logger.debug(
122
+ `write compiled file meta at ${urlToFileSystemPath(metaJsonFileUrl)}`,
123
+ )
124
+ promises.push(
125
+ writeFileContent(metaJsonFileUrl, JSON.stringify(latestMeta, null, " "), {
126
+ fileLikelyNotFound: isNew,
127
+ }),
128
+ )
129
+ promises.push(jsenvDirectory.compiledFileWriteSignal.onwrite())
130
+ await Promise.all(promises)
150
131
  }