@@ -25,20 +25,29 @@ const throwMissingFsModule = () => {
2525 throw "Clerk: fsModule.fs is missing. This is an internal error. Please contact Clerk's support." ;
2626} ;
2727
28- /**
29- * The `.clerk/` is NOT safe to be commited as it may include sensitive information about a Clerk instance.
30- * It may include an instance's secret key and the secret token for claiming that instance.
31- */
32- function updateGitignore ( ) {
28+ const safeNodeRuntimeFs = ( ) => {
3329 if ( ! nodeRuntime . fs ) {
3430 throwMissingFsModule ( ) ;
3531 }
36- const { existsSync, writeFileSync, readFileSync, appendFileSync } = nodeRuntime . fs ;
32+ return nodeRuntime . fs ;
33+ } ;
3734
35+ const safeNodeRuntimePath = ( ) => {
3836 if ( ! nodeRuntime . path ) {
3937 throwMissingFsModule ( ) ;
4038 }
41- const gitignorePath = nodeRuntime . path . join ( process . cwd ( ) , '.gitignore' ) ;
39+ return nodeRuntime . path ;
40+ } ;
41+
42+ /**
43+ * The `.clerk/` directory is NOT safe to be committed as it may include sensitive information about a Clerk instance.
44+ * It may include an instance's secret key and the secret token for claiming that instance.
45+ */
46+ function updateGitignore ( ) {
47+ const { existsSync, writeFileSync, readFileSync, appendFileSync } = safeNodeRuntimeFs ( ) ;
48+
49+ const path = safeNodeRuntimePath ( ) ;
50+ const gitignorePath = path . join ( process . cwd ( ) , '.gitignore' ) ;
4251 if ( ! existsSync ( gitignorePath ) ) {
4352 writeFileSync ( gitignorePath , '' ) ;
4453 }
@@ -52,10 +61,8 @@ function updateGitignore() {
5261}
5362
5463const generatePath = ( ...slugs : string [ ] ) => {
55- if ( ! nodeRuntime . path ) {
56- throwMissingFsModule ( ) ;
57- }
58- return nodeRuntime . path . join ( process . cwd ( ) , CLERK_HIDDEN , ...slugs ) ;
64+ const path = safeNodeRuntimePath ( ) ;
65+ return path . join ( process . cwd ( ) , CLERK_HIDDEN , ...slugs ) ;
5966} ;
6067
6168const _TEMP_DIR_NAME = '.tmp' ;
@@ -64,11 +71,8 @@ const getKeylessReadMePath = () => generatePath(_TEMP_DIR_NAME, 'README.md');
6471
6572let isCreatingFile = false ;
6673
67- function safeParseClerkFile ( ) : AccountlessApplication | undefined {
68- if ( ! nodeRuntime . fs ) {
69- throwMissingFsModule ( ) ;
70- }
71- const { readFileSync } = nodeRuntime . fs ;
74+ export function safeParseClerkFile ( ) : AccountlessApplication | undefined {
75+ const { readFileSync } = safeNodeRuntimeFs ( ) ;
7276 try {
7377 const CONFIG_PATH = getKeylessConfigurationPath ( ) ;
7478 let fileAsString ;
@@ -87,20 +91,11 @@ const createMessage = (keys: AccountlessApplication) => {
8791 return `\n\x1b[35m\n[Clerk]:\x1b[0m You are running in keyless mode.\nYou can \x1b[35mclaim your keys\x1b[0m by visiting ${ keys . claimUrl } \n` ;
8892} ;
8993
90- async function createOrReadKeyless ( ) : Promise < AccountlessApplication | undefined > {
91- if ( ! nodeRuntime . fs ) {
92- // This should never happen.
93- throwMissingFsModule ( ) ;
94- }
95- const { existsSync, writeFileSync, mkdirSync, rmSync } = nodeRuntime . fs ;
96-
97- /**
98- * If another request is already in the process of acquiring keys return early.
99- * Using both an in-memory and file system lock seems to be the most effective solution.
100- */
101- if ( isCreatingFile || existsSync ( CLERK_LOCK ) ) {
102- return undefined ;
103- }
94+ /**
95+ * Using both an in-memory and file system lock seems to be the most effective solution.
96+ */
97+ const lockFileWriting = ( ) => {
98+ const { writeFileSync } = safeNodeRuntimeFs ( ) ;
10499
105100 isCreatingFile = true ;
106101
@@ -114,6 +109,37 @@ async function createOrReadKeyless(): Promise<AccountlessApplication | undefined
114109 flag : 'w' ,
115110 } ,
116111 ) ;
112+ } ;
113+
114+ const unlockFileWriting = ( ) => {
115+ const { rmSync } = safeNodeRuntimeFs ( ) ;
116+
117+ try {
118+ rmSync ( CLERK_LOCK , { force : true , recursive : true } ) ;
119+ } catch ( e ) {
120+ // Simply ignore if the removal of the directory/file fails
121+ }
122+
123+ isCreatingFile = false ;
124+ } ;
125+
126+ const isFileWritingLocked = ( ) => {
127+ const { existsSync } = safeNodeRuntimeFs ( ) ;
128+ return isCreatingFile || existsSync ( CLERK_LOCK ) ;
129+ } ;
130+
131+ async function createOrReadKeyless ( ) : Promise < AccountlessApplication | undefined > {
132+ const { writeFileSync, mkdirSync } = safeNodeRuntimeFs ( ) ;
133+
134+ /**
135+ * If another request is already in the process of acquiring keys return early.
136+ * Using both an in-memory and file system lock seems to be the most effective solution.
137+ */
138+ if ( isFileWritingLocked ( ) ) {
139+ return undefined ;
140+ }
141+
142+ lockFileWriting ( ) ;
117143
118144 const CONFIG_PATH = getKeylessConfigurationPath ( ) ;
119145 const README_PATH = getKeylessReadMePath ( ) ;
@@ -126,8 +152,7 @@ async function createOrReadKeyless(): Promise<AccountlessApplication | undefined
126152 */
127153 const envVarsMap = safeParseClerkFile ( ) ;
128154 if ( envVarsMap ?. publishableKey && envVarsMap ?. secretKey ) {
129- isCreatingFile = false ;
130- rmSync ( CLERK_LOCK , { force : true , recursive : true } ) ;
155+ unlockFileWriting ( ) ;
131156
132157 /**
133158 * Notify developers.
@@ -169,10 +194,34 @@ This directory is auto-generated from \`@clerk/nextjs\` because you are running
169194 /**
170195 * Clean up locks.
171196 */
172- rmSync ( CLERK_LOCK , { force : true , recursive : true } ) ;
173- isCreatingFile = false ;
197+ unlockFileWriting ( ) ;
174198
175199 return accountlessApplication ;
176200}
177201
178- export { createOrReadKeyless } ;
202+ function removeKeyless ( ) {
203+ const { rmSync } = safeNodeRuntimeFs ( ) ;
204+
205+ /**
206+ * If another request is already in the process of acquiring keys return early.
207+ * Using both an in-memory and file system lock seems to be the most effective solution.
208+ */
209+ if ( isFileWritingLocked ( ) ) {
210+ return undefined ;
211+ }
212+
213+ lockFileWriting ( ) ;
214+
215+ try {
216+ rmSync ( generatePath ( ) , { force : true , recursive : true } ) ;
217+ } catch ( e ) {
218+ // Simply ignore if the removal of the directory/file fails
219+ }
220+
221+ /**
222+ * Clean up locks.
223+ */
224+ unlockFileWriting ( ) ;
225+ }
226+
227+ export { createOrReadKeyless , removeKeyless } ;
0 commit comments