Skip to content

Commit 61d958d

Browse files
authored
Merge pull request #80 from boostcampwm-2024/dev-fe
[MERGE] 백엔드, 프론트 통합 준비
2 parents 94e3e79 + 9688e5d commit 61d958d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+5432
-149
lines changed

.vscode/extensions.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"recommendations": [
3+
"arcanis.vscode-zipfs"
4+
]
5+
}

.vscode/settings.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"typescript.tsdk": ".yarn/sdks/typescript/lib",
3+
"eslint.nodePath": ".yarn/sdks",
4+
"editor.formatOnSave": true,
5+
"editor.defaultFormatter": "esbenp.prettier-vscode",
6+
"typescript.enablePromptUseWorkspaceTsdk": true,
7+
"search.exclude": {
8+
"**/.yarn": true,
9+
"**/.pnp.*": true
10+
}
11+
}

.yarn/sdks/integrations.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# This file is automatically generated by @yarnpkg/sdks.
2+
# Manual changes might be lost!
3+
4+
integrations:
5+
- vscode

.yarn/sdks/typescript/bin/tsc

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#!/usr/bin/env node
2+
3+
const {existsSync} = require(`fs`);
4+
const {createRequire, register} = require(`module`);
5+
const {resolve} = require(`path`);
6+
const {pathToFileURL} = require(`url`);
7+
8+
const relPnpApiPath = "../../../../.pnp.cjs";
9+
10+
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
11+
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
12+
const absRequire = createRequire(absPnpApiPath);
13+
14+
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
15+
const isPnpLoaderEnabled = existsSync(absPnpLoaderPath);
16+
17+
if (existsSync(absPnpApiPath)) {
18+
if (!process.versions.pnp) {
19+
// Setup the environment to be able to require typescript/bin/tsc
20+
require(absPnpApiPath).setup();
21+
if (isPnpLoaderEnabled && register) {
22+
register(pathToFileURL(absPnpLoaderPath));
23+
}
24+
}
25+
}
26+
27+
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
28+
? exports => absRequire(absUserWrapperPath)(exports)
29+
: exports => exports;
30+
31+
// Defer to the real typescript/bin/tsc your application uses
32+
module.exports = wrapWithUserWrapper(absRequire(`typescript/bin/tsc`));

.yarn/sdks/typescript/bin/tsserver

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#!/usr/bin/env node
2+
3+
const {existsSync} = require(`fs`);
4+
const {createRequire, register} = require(`module`);
5+
const {resolve} = require(`path`);
6+
const {pathToFileURL} = require(`url`);
7+
8+
const relPnpApiPath = "../../../../.pnp.cjs";
9+
10+
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
11+
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
12+
const absRequire = createRequire(absPnpApiPath);
13+
14+
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
15+
const isPnpLoaderEnabled = existsSync(absPnpLoaderPath);
16+
17+
if (existsSync(absPnpApiPath)) {
18+
if (!process.versions.pnp) {
19+
// Setup the environment to be able to require typescript/bin/tsserver
20+
require(absPnpApiPath).setup();
21+
if (isPnpLoaderEnabled && register) {
22+
register(pathToFileURL(absPnpLoaderPath));
23+
}
24+
}
25+
}
26+
27+
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
28+
? exports => absRequire(absUserWrapperPath)(exports)
29+
: exports => exports;
30+
31+
// Defer to the real typescript/bin/tsserver your application uses
32+
module.exports = wrapWithUserWrapper(absRequire(`typescript/bin/tsserver`));

.yarn/sdks/typescript/lib/tsc.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#!/usr/bin/env node
2+
3+
const {existsSync} = require(`fs`);
4+
const {createRequire, register} = require(`module`);
5+
const {resolve} = require(`path`);
6+
const {pathToFileURL} = require(`url`);
7+
8+
const relPnpApiPath = "../../../../.pnp.cjs";
9+
10+
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
11+
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
12+
const absRequire = createRequire(absPnpApiPath);
13+
14+
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
15+
const isPnpLoaderEnabled = existsSync(absPnpLoaderPath);
16+
17+
if (existsSync(absPnpApiPath)) {
18+
if (!process.versions.pnp) {
19+
// Setup the environment to be able to require typescript/lib/tsc.js
20+
require(absPnpApiPath).setup();
21+
if (isPnpLoaderEnabled && register) {
22+
register(pathToFileURL(absPnpLoaderPath));
23+
}
24+
}
25+
}
26+
27+
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
28+
? exports => absRequire(absUserWrapperPath)(exports)
29+
: exports => exports;
30+
31+
// Defer to the real typescript/lib/tsc.js your application uses
32+
module.exports = wrapWithUserWrapper(absRequire(`typescript/lib/tsc.js`));

.yarn/sdks/typescript/lib/tsserver.js

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
#!/usr/bin/env node
2+
3+
const {existsSync} = require(`fs`);
4+
const {createRequire, register} = require(`module`);
5+
const {resolve} = require(`path`);
6+
const {pathToFileURL} = require(`url`);
7+
8+
const relPnpApiPath = "../../../../.pnp.cjs";
9+
10+
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
11+
const absUserWrapperPath = resolve(__dirname, `./sdk.user.cjs`);
12+
const absRequire = createRequire(absPnpApiPath);
13+
14+
const absPnpLoaderPath = resolve(absPnpApiPath, `../.pnp.loader.mjs`);
15+
const isPnpLoaderEnabled = existsSync(absPnpLoaderPath);
16+
17+
if (existsSync(absPnpApiPath)) {
18+
if (!process.versions.pnp) {
19+
// Setup the environment to be able to require typescript/lib/tsserver.js
20+
require(absPnpApiPath).setup();
21+
if (isPnpLoaderEnabled && register) {
22+
register(pathToFileURL(absPnpLoaderPath));
23+
}
24+
}
25+
}
26+
27+
const wrapWithUserWrapper = existsSync(absUserWrapperPath)
28+
? exports => absRequire(absUserWrapperPath)(exports)
29+
: exports => exports;
30+
31+
const moduleWrapper = exports => {
32+
return wrapWithUserWrapper(moduleWrapperFn(exports));
33+
};
34+
35+
const moduleWrapperFn = tsserver => {
36+
if (!process.versions.pnp) {
37+
return tsserver;
38+
}
39+
40+
const {isAbsolute} = require(`path`);
41+
const pnpApi = require(`pnpapi`);
42+
43+
const isVirtual = str => str.match(/\/(\$\$virtual|__virtual__)\//);
44+
const isPortal = str => str.startsWith("portal:/");
45+
const normalize = str => str.replace(/\\/g, `/`).replace(/^\/?/, `/`);
46+
47+
const dependencyTreeRoots = new Set(pnpApi.getDependencyTreeRoots().map(locator => {
48+
return `${locator.name}@${locator.reference}`;
49+
}));
50+
51+
// VSCode sends the zip paths to TS using the "zip://" prefix, that TS
52+
// doesn't understand. This layer makes sure to remove the protocol
53+
// before forwarding it to TS, and to add it back on all returned paths.
54+
55+
function toEditorPath(str) {
56+
// We add the `zip:` prefix to both `.zip/` paths and virtual paths
57+
if (isAbsolute(str) && !str.match(/^\^?(zip:|\/zip\/)/) && (str.match(/\.zip\//) || isVirtual(str))) {
58+
// We also take the opportunity to turn virtual paths into physical ones;
59+
// this makes it much easier to work with workspaces that list peer
60+
// dependencies, since otherwise Ctrl+Click would bring us to the virtual
61+
// file instances instead of the real ones.
62+
//
63+
// We only do this to modules owned by the the dependency tree roots.
64+
// This avoids breaking the resolution when jumping inside a vendor
65+
// with peer dep (otherwise jumping into react-dom would show resolution
66+
// errors on react).
67+
//
68+
const resolved = isVirtual(str) ? pnpApi.resolveVirtual(str) : str;
69+
if (resolved) {
70+
const locator = pnpApi.findPackageLocator(resolved);
71+
if (locator && (dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) || isPortal(locator.reference))) {
72+
str = resolved;
73+
}
74+
}
75+
76+
str = normalize(str);
77+
78+
if (str.match(/\.zip\//)) {
79+
switch (hostInfo) {
80+
// Absolute VSCode `Uri.fsPath`s need to start with a slash.
81+
// VSCode only adds it automatically for supported schemes,
82+
// so we have to do it manually for the `zip` scheme.
83+
// The path needs to start with a caret otherwise VSCode doesn't handle the protocol
84+
//
85+
// Ref: https://github.com/microsoft/vscode/issues/105014#issuecomment-686760910
86+
//
87+
// 2021-10-08: VSCode changed the format in 1.61.
88+
// Before | ^zip:/c:/foo/bar.zip/package.json
89+
// After | ^/zip//c:/foo/bar.zip/package.json
90+
//
91+
// 2022-04-06: VSCode changed the format in 1.66.
92+
// Before | ^/zip//c:/foo/bar.zip/package.json
93+
// After | ^/zip/c:/foo/bar.zip/package.json
94+
//
95+
// 2022-05-06: VSCode changed the format in 1.68
96+
// Before | ^/zip/c:/foo/bar.zip/package.json
97+
// After | ^/zip//c:/foo/bar.zip/package.json
98+
//
99+
case `vscode <1.61`: {
100+
str = `^zip:${str}`;
101+
} break;
102+
103+
case `vscode <1.66`: {
104+
str = `^/zip/${str}`;
105+
} break;
106+
107+
case `vscode <1.68`: {
108+
str = `^/zip${str}`;
109+
} break;
110+
111+
case `vscode`: {
112+
str = `^/zip/${str}`;
113+
} break;
114+
115+
// To make "go to definition" work,
116+
// We have to resolve the actual file system path from virtual path
117+
// and convert scheme to supported by [vim-rzip](https://github.com/lbrayner/vim-rzip)
118+
case `coc-nvim`: {
119+
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
120+
str = resolve(`zipfile:${str}`);
121+
} break;
122+
123+
// Support neovim native LSP and [typescript-language-server](https://github.com/theia-ide/typescript-language-server)
124+
// We have to resolve the actual file system path from virtual path,
125+
// everything else is up to neovim
126+
case `neovim`: {
127+
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
128+
str = `zipfile://${str}`;
129+
} break;
130+
131+
default: {
132+
str = `zip:${str}`;
133+
} break;
134+
}
135+
} else {
136+
str = str.replace(/^\/?/, process.platform === `win32` ? `` : `/`);
137+
}
138+
}
139+
140+
return str;
141+
}
142+
143+
function fromEditorPath(str) {
144+
switch (hostInfo) {
145+
case `coc-nvim`: {
146+
str = str.replace(/\.zip::/, `.zip/`);
147+
// The path for coc-nvim is in format of /<pwd>/zipfile:/<pwd>/.yarn/...
148+
// So in order to convert it back, we use .* to match all the thing
149+
// before `zipfile:`
150+
return process.platform === `win32`
151+
? str.replace(/^.*zipfile:\//, ``)
152+
: str.replace(/^.*zipfile:/, ``);
153+
} break;
154+
155+
case `neovim`: {
156+
str = str.replace(/\.zip::/, `.zip/`);
157+
// The path for neovim is in format of zipfile:///<pwd>/.yarn/...
158+
return str.replace(/^zipfile:\/\//, ``);
159+
} break;
160+
161+
case `vscode`:
162+
default: {
163+
return str.replace(/^\^?(zip:|\/zip(\/ts-nul-authority)?)\/+/, process.platform === `win32` ? `` : `/`)
164+
} break;
165+
}
166+
}
167+
168+
// Force enable 'allowLocalPluginLoads'
169+
// TypeScript tries to resolve plugins using a path relative to itself
170+
// which doesn't work when using the global cache
171+
// https://github.com/microsoft/TypeScript/blob/1b57a0395e0bff191581c9606aab92832001de62/src/server/project.ts#L2238
172+
// VSCode doesn't want to enable 'allowLocalPluginLoads' due to security concerns but
173+
// TypeScript already does local loads and if this code is running the user trusts the workspace
174+
// https://github.com/microsoft/vscode/issues/45856
175+
const ConfiguredProject = tsserver.server.ConfiguredProject;
176+
const {enablePluginsWithOptions: originalEnablePluginsWithOptions} = ConfiguredProject.prototype;
177+
ConfiguredProject.prototype.enablePluginsWithOptions = function() {
178+
this.projectService.allowLocalPluginLoads = true;
179+
return originalEnablePluginsWithOptions.apply(this, arguments);
180+
};
181+
182+
// And here is the point where we hijack the VSCode <-> TS communications
183+
// by adding ourselves in the middle. We locate everything that looks
184+
// like an absolute path of ours and normalize it.
185+
186+
const Session = tsserver.server.Session;
187+
const {onMessage: originalOnMessage, send: originalSend} = Session.prototype;
188+
let hostInfo = `unknown`;
189+
190+
Object.assign(Session.prototype, {
191+
onMessage(/** @type {string | object} */ message) {
192+
const isStringMessage = typeof message === 'string';
193+
const parsedMessage = isStringMessage ? JSON.parse(message) : message;
194+
195+
if (
196+
parsedMessage != null &&
197+
typeof parsedMessage === `object` &&
198+
parsedMessage.arguments &&
199+
typeof parsedMessage.arguments.hostInfo === `string`
200+
) {
201+
hostInfo = parsedMessage.arguments.hostInfo;
202+
if (hostInfo === `vscode` && process.env.VSCODE_IPC_HOOK) {
203+
const [, major, minor] = (process.env.VSCODE_IPC_HOOK.match(
204+
// The RegExp from https://semver.org/ but without the caret at the start
205+
/(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
206+
) ?? []).map(Number)
207+
208+
if (major === 1) {
209+
if (minor < 61) {
210+
hostInfo += ` <1.61`;
211+
} else if (minor < 66) {
212+
hostInfo += ` <1.66`;
213+
} else if (minor < 68) {
214+
hostInfo += ` <1.68`;
215+
}
216+
}
217+
}
218+
}
219+
220+
const processedMessageJSON = JSON.stringify(parsedMessage, (key, value) => {
221+
return typeof value === 'string' ? fromEditorPath(value) : value;
222+
});
223+
224+
return originalOnMessage.call(
225+
this,
226+
isStringMessage ? processedMessageJSON : JSON.parse(processedMessageJSON)
227+
);
228+
},
229+
230+
send(/** @type {any} */ msg) {
231+
return originalSend.call(this, JSON.parse(JSON.stringify(msg, (key, value) => {
232+
return typeof value === `string` ? toEditorPath(value) : value;
233+
})));
234+
}
235+
});
236+
237+
return tsserver;
238+
};
239+
240+
const [major, minor] = absRequire(`typescript/package.json`).version.split(`.`, 2).map(value => parseInt(value, 10));
241+
// In TypeScript@>=5.5 the tsserver uses the public TypeScript API so that needs to be patched as well.
242+
// Ref https://github.com/microsoft/TypeScript/pull/55326
243+
if (major > 5 || (major === 5 && minor >= 5)) {
244+
moduleWrapper(absRequire(`typescript`));
245+
}
246+
247+
// Defer to the real typescript/lib/tsserver.js your application uses
248+
module.exports = moduleWrapper(absRequire(`typescript/lib/tsserver.js`));

0 commit comments

Comments
 (0)