@seed-design/cli 0.0.0-alpha-20241016030836 → 0.0.0-alpha-20241031064135
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/bin/index.mjs +2 -8
- package/package.json +2 -8
- package/src/commands/check-deprecated-icon-files.ts +256 -0
- package/src/index.ts +2 -2
- package/src/schema.ts +1 -1
- package/src/commands/icon-shift.ts +0 -147
- package/src/test/icon-shift/cases/migrateIdentifiers/expected.tsx +0 -11
- package/src/test/icon-shift/cases/migrateIdentifiers/input.tsx +0 -11
- package/src/test/icon-shift/cases/migrateImportDeclarations/expected.tsx +0 -3
- package/src/test/icon-shift/cases/migrateImportDeclarations/input.tsx +0 -3
- package/src/test/icon-shift/cases/migrateImportDeclarationsVariousTypes/expected.tsx +0 -6
- package/src/test/icon-shift/cases/migrateImportDeclarationsVariousTypes/input.tsx +0 -6
- package/src/test/icon-shift/cases/migrateImportDeclarationsVariousTypesWithMigrateIdentifiers/expected.tsx +0 -19
- package/src/test/icon-shift/cases/migrateImportDeclarationsVariousTypesWithMigrateIdentifiers/input.tsx +0 -19
- package/src/test/icon-shift/cases/migrateImportDeclarationsWithMigrateIdentifiers/expected.tsx +0 -13
- package/src/test/icon-shift/cases/migrateImportDeclarationsWithMigrateIdentifiers/input.tsx +0 -13
- package/src/test/icon-shift/index.test.ts +0 -90
- package/src/utils/files.ts +0 -63
- package/src/utils/migrate.ts +0 -156
package/bin/index.mjs
CHANGED
|
@@ -1,9 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{cosmiconfig as
|
|
3
|
-
`,"utf-8");let
|
|
4
|
-
(old) import { IconHeart } from "old-package"; <IconHeart />;
|
|
5
|
-
\u2192 (new) import { NewIconHeart } from "new-package"; <NewIconHeart />;
|
|
6
|
-
`},{label:"import\uB9CC \uBCC0\uACBD",value:"importOnly",hint:`
|
|
7
|
-
(old) import { IconHeart } from "old-package"; <IconHeart />;
|
|
8
|
-
\u2192 (new) import { NewIconHeart as IconHeart } from "new-package"; <IconHeart />;
|
|
9
|
-
`}],initialValue:"all"})}),c=(()=>{switch(s.target){case"tsconfig":return re({dirToFindTsconfig:process.cwd(),excludeDTs:!0});case"cwd":return k({dir:process.cwd(),extensionsToFind:ae,extensionsToExclude:ce});case"path":return k({dir:r.path,extensionsToFind:ae,extensionsToExclude:ce})}})(),{start:p,message:u,stop:m}=x.spinner();p("\uBA87 \uAC1C\uC758 \uD30C\uC77C\uC744 \uD655\uC778\uD560\uC9C0 \uACB0\uC815\uD558\uACE0 \uC788\uC5B4\uC694.");let a=r.includeIgnored?c:await oe({git:Ue(),filePaths:c});m(`${a.length}\uAC1C \uD30C\uC77C\uC5D0\uC11C \uC608\uC804 \uC544\uC774\uCF58\uC744 \uCC3E\uC544\uBCFC\uAC8C\uC694.`),p(`${a.length}\uAC1C \uD30C\uC77C\uC5D0\uC11C \uC608\uC804 \uC544\uC774\uCF58\uC744 \uCC3E\uC544\uBCFC\uAC8C\uC694.`);let w=Ke.withParser("tsx");for(let i=0;i<a.length;i++){let d=a[i],h=((i+1)/a.length*100).toFixed(1);u(`\uD30C\uC77C ${i+1}/${a.length} \uBCC0\uACBD \uC2DC\uC791 (${h}%): ${d}`),se({filePath:d,jscodeshift:w,importTransformers:Le})}m("\uCF54\uB4DC \uBCC0\uACBD\uC774 \uB05D\uB0AC\uC5B4\uC694.")})};var qe="seed-design",T=Xe(qe);async function Qe(){let e=Y();Q(T),te(T),pe(T),T.version(e.version||"1.0.0","-v, --version"),T.help(),T.parse()}Qe();
|
|
2
|
+
import{cosmiconfig as ee}from"cosmiconfig";import j from"path";import{z as g}from"zod";var $="seed-design",oe=ee($,{searchPlaces:[`${$}.json`]}),T=g.object({$schema:g.string().optional(),rsc:g.coerce.boolean().default(!1),tsx:g.coerce.boolean().default(!0),css:g.coerce.boolean().default(!0),path:g.string()}).strict(),ne=T.extend({resolvedUIPaths:g.string()});async function A(e){let n=await re(e);return n?await te(e,n):null}async function te(e,n){let t=j.resolve(e,n.path);return ne.parse({...n,resolvedUIPaths:j.join(t,"ui")})}async function re(e){try{let n=await oe.search(e);return n?T.parse(n.config):null}catch(n){throw console.log(n),new Error(`Invalid configuration found in ${e}/seed-design.json.`)}}import{z as c}from"zod";var M=c.object({name:c.string(),description:c.string().optional(),dependencies:c.array(c.string()).optional(),devDependencies:c.array(c.string()).optional(),innerDependencies:c.array(c.string()).optional(),files:c.array(c.string())}),O=c.array(M),ie=M.omit({files:!0}),ce=ie.extend({registries:c.array(c.object({name:c.string(),content:c.string()}))}),ze=c.array(ce);var k="https://component.seed-design.io";async function b(e){try{return await Promise.all(e.map(async t=>await(await fetch(`${k}/__registry__/component/${t}.json`)).json()))}catch(n){throw console.log(n),new Error(`Failed to fetch registry from ${k}.`)}}async function F(){try{let[e]=await b(["index"]);return O.parse(e)}catch(e){throw console.log(e),new Error(`Failed to fetch components from ${k}.`)}}import{detect as se}from"@antfu/ni";async function D(e){let n=await se({programmatic:!0,cwd:e});return n==="yarn@berry"?"yarn":n==="pnpm@6"?"pnpm":n==="bun"?"bun":n??"npm"}import{promises as de}from"fs";import{tmpdir as fe}from"os";import G from"path";import{transformFromAstSync as ae}from"@babel/core";import pe from"@babel/plugin-transform-typescript";import*as v from"recast";import{parse as le}from"@babel/parser";var me={sourceType:"module",allowImportExportEverywhere:!0,allowReturnOutsideFunction:!0,startLine:1,tokens:!0,plugins:["asyncGenerators","bigInt","classPrivateMethods","classPrivateProperties","classProperties","classStaticBlock","decimal","decorators-legacy","doExpressions","dynamicImport","exportDefaultFrom","exportNamespaceFrom","functionBind","functionSent","importAssertions","importMeta","nullishCoalescingOperator","numericSeparator","objectRestSpread","optionalCatchBinding","optionalChaining",["pipelineOperator",{proposal:"minimal"}],["recordAndTuple",{syntaxType:"hash"}],"throwExpressions","topLevelAwait","v8intrinsic","typescript","jsx"]},E=async({sourceFile:e,config:n})=>{let t=e.getFullText();if(n.tsx)return t;let i=v.parse(t,{parser:{parse:r=>le(r,me)}}),o=ae(i,t,{cloneInputAst:!1,code:!1,ast:!0,plugins:[pe],configFile:!1});if(!o||!o.ast)throw new Error("Failed to transform JSX");return v.print(o.ast).code};import{SyntaxKind as _e}from"ts-morph";var N=async({sourceFile:e,config:n})=>{if(n.rsc)return e;let t=e.getFirstChildByKind(_e.ExpressionStatement);return t?.getText()==='"use client";'&&t.remove(),e};var z=async({sourceFile:e,config:n})=>{if(n.css)return e;let i=e.getImportDeclarations().filter(o=>o.getModuleSpecifierValue().endsWith(".css"));for(let o of i)o.remove();return e};import{Project as ge,ScriptKind as ue}from"ts-morph";var he=[N,z],ye=new ge({compilerOptions:{}});async function we(e){let n=await de.mkdtemp(G.join(fe(),"seed-deisgn-"));return G.join(n,e)}async function J(e){let n=await we(e.filename),t=ye.createSourceFile(n,e.raw,{scriptKind:ue.TSX});for(let i of he)i({sourceFile:t,...e});return await E({sourceFile:t,...e})}import*as s from"@clack/prompts";import{execa as V}from"execa";import S from"fs-extra";import U from"path";import I from"picocolors";import{z as C}from"zod";function L(e,n){let t=new Set;function i(o){if(t.has(o))return;t.add(o);let r=n.find(l=>l.name===o);if(r&&r.innerDependencies)for(let l of r.innerDependencies)i(l)}for(let o of e)i(o);return Array.from(t)}var Ce=C.object({components:C.array(C.string()).optional(),cwd:C.string(),all:C.boolean()}),B=e=>{e.command("add [...components]","add component").option("-a, --all","Add all components",{default:!1}).option("-c, --cwd <cwd>","the working directory. defaults to the current directory.",{default:process.cwd()}).example("seed-design add box-button").example("seed-design add alert-dialog").action(async(n,t)=>{let i=Ce.parse({components:n,...t}),o=a=>I.cyan(a),r=i.cwd;S.existsSync(r)||(s.log.error(`The path ${r} does not exist. Please try again.`),process.exit(1));let l=await F(),d=i.all?l.map(a=>a.name):i.components;if(!i.components?.length&&!i.all){let a=await s.multiselect({message:"Select all components to add",options:l.map(_=>({label:_.name,value:_.name,hint:_.description}))});s.isCancel(a)&&(s.log.error("Aborted."),process.exit(0)),d=a}d?.length||(s.log.error("No components found."),process.exit(0));let y=L(d,l),x=y.filter(a=>!d.includes(a)),w=await A(r),Q=await b(y);s.log.message(`Selection: ${o(d.join(", "))}`),x.length&&s.log.message(`Inner Dependencies: ${o(x.join(", "))} will be also added.`);for(let a of Q){for(let m of a.registries){let f=w.resolvedUIPaths;S.existsSync(f)||await S.mkdir(f,{recursive:!0});let u=U.resolve(f,m.name),Y=await J({filename:m.name,config:w,raw:m.content});w.tsx||(u=u.replace(/\.tsx$/,".jsx"),u=u.replace(/\.ts$/,".js")),await S.writeFile(u,Y);let Z=U.relative(r,u);s.log.info(`Added ${o(m.name)} to ${o(Z)}`)}let _=await D(r),{start:P,stop:R}=s.spinner();if(a.dependencies?.length){P(I.gray("Installing dependencies"));let m=await V(_,[_==="npm"?"install":"add",...a.dependencies],{cwd:r});if(m.failed)console.error(m.all),process.exit(1);else{for(let f of a.dependencies)s.log.info(`- ${f}`);R("Dependencies installed.")}}if(a.devDependencies?.length){P(I.gray("Installing devDependencies"));let m=await V(_,[_==="npm"?"install":"add","-D",...a.devDependencies],{cwd:r});if(m.failed)console.error(m.all),process.exit(1);else{for(let f of a.devDependencies)s.log.info(`- ${f}`);R("Dependencies installed.")}}}s.outro("Components added.")})};import xe from"findup-sync";import ve from"fs-extra";var Se="package.json";function ke(){let e=xe(Se);if(!e)throw new Error("No package.json file found in the project.");return e}function K(){return ve.readJSONSync(ke())}import{cac as Te}from"cac";import*as p from"@clack/prompts";import be from"fs-extra";import W from"path";import Ie from"picocolors";import{z as q}from"zod";var Pe=q.object({cwd:q.string()}),X=e=>{e.command("init","initialize seed-design.json").option("-c, --cwd <cwd>","the working directory. defaults to the current directory.",{default:process.cwd()}).action(async n=>{let t=Pe.parse({...n}),i=w=>Ie.cyan(w),o=await p.group({tsx:()=>p.confirm({message:`Would you like to use ${i("TypeScript")} (recommended)?`,initialValue:!0}),rsc:()=>p.confirm({message:`Are you using ${i("React Server Components")}?`,initialValue:!1}),css:()=>p.confirm({message:`Would you like to use ${i("CSS Modules")}? (If true, CSS import will be added in components)`,initialValue:!0}),path:()=>p.text({message:`Enter the path to your ${i("seed-design directory")}`,initialValue:"./seed-design",defaultValue:"./seed-design",placeholder:"./seed-design"})},{onCancel:()=>{p.cancel("Operation cancelled."),process.exit(0)}}),r={rsc:o.rsc,tsx:o.tsx,css:o.css,path:o.path},{start:l,stop:d}=p.spinner();l("Writing seed-design.json...");let y=W.resolve(t.cwd,"seed-design.json");await be.writeFile(y,`${JSON.stringify(r,null,2)}
|
|
3
|
+
`,"utf-8");let x=W.relative(process.cwd(),y);d(`seed-design.json written to ${i(x)}`)})};import Re from"node:fs";var H=e=>{e.command("check-deprecated-icon-files [path]","Check deprecated icon files").action(async n=>{let t=Re.readdirSync(n,{recursive:!0}),i=$e.flatMap(o=>{let r=o.replace("icon_","");return[o,r,o.replace(/_/g,"-"),o.replace(/_/g,""),`${o.replace(/_/g,"")}thin`,`${o.replace(/_/g,"")}regular`,`${o.replace(/_/g,"")}fill`,r.replace(/_/g,"-"),r.replace(/_/g,""),`${r.replace(/_/g,"")}thin`,`${r.replace(/_/g,"")}regular`,`${r.replace(/_/g,"")}fill`]});for(let o of t){if(typeof o!="string"||o.includes("node_modules/"))continue;let r=o.split("/").pop().split(".")[0].toLowerCase();je.every(l=>o.endsWith(l)===!1)||i.includes(r)&&console.log(`Possible deprecated icon file found: ${o}`)}})},je=[".tsx",".jsx",".svg",".png"],$e=["icon_add","icon_add_circle","icon_aeb","icon_ai","icon_android_share","icon_arrow","icon_arrow_downward","icon_arrow_drop_down","icon_arrow_drop_up","icon_arrow_upward","icon_article","icon_backward","icon_bill","icon_bold","icon_bookmark","icon_bookmark_list","icon_calendar","icon_call","icon_call_declined","icon_camera","icon_car","icon_car_around_view","icon_car_blind_spot","icon_car_cruise_control","icon_car_epb","icon_car_heated_seat","icon_car_heated_steering_wheel","icon_car_ldws","icon_car_leather_seat","icon_car_navigation","icon_car_power_trunk","icon_car_rear_camera","icon_car_rear_sensor","icon_car_smart_key","icon_car_ventilation_seat","icon_cart","icon_certification","icon_challenge","icon_chart","icon_chat_bubble_check","icon_chatting","icon_chatting_send","icon_check","icon_check_flower","icon_chevron_left","icon_chevron_right","icon_click","icon_clock","icon_close","icon_cobuying","icon_community","icon_condo","icon_confirmation","icon_confirmation_pay","icon_confirmation_profile","icon_contents","icon_convert","icon_copy","icon_coupon","icon_coupon_download_done","icon_coupon_used","icon_delete_keyboard","icon_delivery","icon_direction","icon_download","icon_edit","icon_emoticon","icon_emoticon_bad","icon_expand","icon_expand_less","icon_expand_more","icon_file","icon_filter02","icon_forward","icon_gender","icon_global","icon_gps","icon_gps_enable","icon_gps_enable2","icon_groupchat_king","icon_handle","icon_hashtag","icon_headphone","icon_heart","icon_help","icon_helpcenter","icon_helper","icon_home","icon_house","icon_housekeeping_book","icon_import","icon_info","icon_interest","icon_interest_list","icon_invite","icon_invite_friend","icon_ios_share","icon_jobs","icon_keyboard_hiding","icon_keyword","icon_laptop","icon_leaf","icon_list","icon_list_card","icon_list_check","icon_list_select","icon_list_thumbnail","icon_location","icon_lock","icon_loudspeaker","icon_map","icon_market","icon_market_check","icon_market_write","icon_mention","icon_menu","icon_mic","icon_mic_off","icon_mission","icon_mobile","icon_money_send","icon_money_won","icon_moon","icon_more_horiz","icon_more_vert","icon_my","icon_my_profile","icon_near_me","icon_newtopic","icon_note","icon_notification","icon_notification_fall","icon_notification_off","icon_order","icon_pause","icon_payment","icon_percent","icon_photo","icon_photo_edit","icon_photo_edit_crop","icon_photo_edit_draw","icon_photo_edit_rotate","icon_photo_several","icon_play","icon_poll","icon_price_won","icon_product","icon_profile","icon_profile_badge","icon_prohibition","icon_pushpin","icon_question_check","icon_redo","icon_refund","icon_remove_circle","icon_reply","icon_reply_mission","icon_reply_re","icon_report","icon_reservation","icon_restaurant","icon_retry","icon_review_star","icon_scanner","icon_search","icon_search_doc","icon_sell","icon_setting","icon_signout","icon_sort","icon_story","icon_story_article","icon_subtract_circle","icon_subtraction","icon_suggest","icon_sun","icon_talkingdown","icon_talkingup","icon_text","icon_thumb_down","icon_thumb_up","icon_toolbox","icon_translate","icon_trash","icon_undo","icon_user_group","icon_video","icon_view_count","icon_view_count_off","icon_volume_off","icon_volume_on","icon_vote","icon_voucher","icon_walk","icon_warning","icon_write","icon_write_frequent_use","icon_write_story"];var Ae="seed-design",h=Te(Ae);async function Me(){let e=K();B(h),X(h),H(h),h.version(e.version||"1.0.0","-v, --version"),h.help(),h.parse()}Me();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seed-design/cli",
|
|
3
|
-
"version": "0.0.0-alpha-
|
|
3
|
+
"version": "0.0.0-alpha-20241031064135",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -29,30 +29,24 @@
|
|
|
29
29
|
"@babel/core": "^7.24.9",
|
|
30
30
|
"@babel/parser": "^7.24.8",
|
|
31
31
|
"@babel/plugin-transform-typescript": "^7.24.8",
|
|
32
|
-
"@biomejs/js-api": "^0.7.1",
|
|
33
|
-
"@biomejs/wasm-nodejs": "^1.9.3",
|
|
34
32
|
"@clack/prompts": "^0.7.0",
|
|
35
33
|
"cac": "^6.7.14",
|
|
36
34
|
"cosmiconfig": "^9.0.0",
|
|
37
35
|
"execa": "^9.3.0",
|
|
38
36
|
"findup-sync": "^5.0.0",
|
|
39
37
|
"fs-extra": "^11.2.0",
|
|
40
|
-
"jscodeshift": "^17.0.0",
|
|
41
38
|
"mktemp": "^1.0.1",
|
|
42
39
|
"picocolors": "^1.0.1",
|
|
43
40
|
"recast": "^0.23.9",
|
|
44
|
-
"simple-git": "^3.27.0",
|
|
45
41
|
"ts-morph": "^23.0.0",
|
|
46
|
-
"typescript": "^5.4.5",
|
|
47
42
|
"zod": "^3.23.8"
|
|
48
43
|
},
|
|
49
44
|
"devDependencies": {
|
|
50
45
|
"@types/babel__core": "^7.20.5",
|
|
51
46
|
"@types/fs-extra": "^11.0.4",
|
|
52
|
-
"@types/jscodeshift": "^0.12.0",
|
|
53
|
-
"@types/node": "^20",
|
|
54
47
|
"esbuild": "^0.19.3",
|
|
55
48
|
"type-fest": "^4.23.0",
|
|
49
|
+
"typescript": "^5.4.5",
|
|
56
50
|
"ultra-runner": "^3.10.5",
|
|
57
51
|
"vitest": "^2.0.5"
|
|
58
52
|
},
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import type { CAC } from "cac";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
|
|
4
|
+
export const checkDeprecatedIconFilesCommand = (cli: CAC) => {
|
|
5
|
+
cli
|
|
6
|
+
.command("check-deprecated-icon-files [path]", "Check deprecated icon files")
|
|
7
|
+
.action(async (path) => {
|
|
8
|
+
const files = fs.readdirSync(path, { recursive: true });
|
|
9
|
+
|
|
10
|
+
const deprecatedIconFileNames = deprecatedIconNames.flatMap((name) => {
|
|
11
|
+
const nameTrimmed = name.replace("icon_", "");
|
|
12
|
+
|
|
13
|
+
return [
|
|
14
|
+
// icon_arrow_downward
|
|
15
|
+
name,
|
|
16
|
+
// arrow_downward
|
|
17
|
+
nameTrimmed,
|
|
18
|
+
// icon-arrow-downward
|
|
19
|
+
name.replace(/_/g, "-"),
|
|
20
|
+
// iconarrowdownward
|
|
21
|
+
name.replace(/_/g, ""),
|
|
22
|
+
// iconarrowdownwardthin
|
|
23
|
+
`${name.replace(/_/g, "")}thin`,
|
|
24
|
+
// iconarrowdownwardregular
|
|
25
|
+
`${name.replace(/_/g, "")}regular`,
|
|
26
|
+
// iconarrowdownwardfill
|
|
27
|
+
`${name.replace(/_/g, "")}fill`,
|
|
28
|
+
// arrow-downward
|
|
29
|
+
nameTrimmed.replace(/_/g, "-"),
|
|
30
|
+
// arrowdownward
|
|
31
|
+
nameTrimmed.replace(/_/g, ""),
|
|
32
|
+
// arrowdownwardthin
|
|
33
|
+
`${nameTrimmed.replace(/_/g, "")}thin`,
|
|
34
|
+
// arrowdownwardregular
|
|
35
|
+
`${nameTrimmed.replace(/_/g, "")}regular`,
|
|
36
|
+
// arrowdownwardfill
|
|
37
|
+
`${nameTrimmed.replace(/_/g, "")}fill`,
|
|
38
|
+
];
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
for (const file of files) {
|
|
42
|
+
if (typeof file !== "string") continue;
|
|
43
|
+
if (file.includes("node_modules/")) continue;
|
|
44
|
+
|
|
45
|
+
const fileNameLowered = file.split("/").pop().split(".")[0].toLowerCase();
|
|
46
|
+
if (extensionsToCheck.every((ext) => file.endsWith(ext) === false)) continue;
|
|
47
|
+
|
|
48
|
+
if (deprecatedIconFileNames.includes(fileNameLowered)) {
|
|
49
|
+
console.log(`Possible deprecated icon file found: ${file}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const extensionsToCheck = [".tsx", ".jsx", ".svg", ".png"];
|
|
56
|
+
|
|
57
|
+
const deprecatedIconNames = [
|
|
58
|
+
"icon_add",
|
|
59
|
+
"icon_add_circle",
|
|
60
|
+
"icon_aeb",
|
|
61
|
+
"icon_ai",
|
|
62
|
+
"icon_android_share",
|
|
63
|
+
"icon_arrow",
|
|
64
|
+
"icon_arrow_downward",
|
|
65
|
+
"icon_arrow_drop_down",
|
|
66
|
+
"icon_arrow_drop_up",
|
|
67
|
+
"icon_arrow_upward",
|
|
68
|
+
"icon_article",
|
|
69
|
+
"icon_backward",
|
|
70
|
+
"icon_bill",
|
|
71
|
+
"icon_bold",
|
|
72
|
+
"icon_bookmark",
|
|
73
|
+
"icon_bookmark_list",
|
|
74
|
+
"icon_calendar",
|
|
75
|
+
"icon_call",
|
|
76
|
+
"icon_call_declined",
|
|
77
|
+
"icon_camera",
|
|
78
|
+
"icon_car",
|
|
79
|
+
"icon_car_around_view",
|
|
80
|
+
"icon_car_blind_spot",
|
|
81
|
+
"icon_car_cruise_control",
|
|
82
|
+
"icon_car_epb",
|
|
83
|
+
"icon_car_heated_seat",
|
|
84
|
+
"icon_car_heated_steering_wheel",
|
|
85
|
+
"icon_car_ldws",
|
|
86
|
+
"icon_car_leather_seat",
|
|
87
|
+
"icon_car_navigation",
|
|
88
|
+
"icon_car_power_trunk",
|
|
89
|
+
"icon_car_rear_camera",
|
|
90
|
+
"icon_car_rear_sensor",
|
|
91
|
+
"icon_car_smart_key",
|
|
92
|
+
"icon_car_ventilation_seat",
|
|
93
|
+
"icon_cart",
|
|
94
|
+
"icon_certification",
|
|
95
|
+
"icon_challenge",
|
|
96
|
+
"icon_chart",
|
|
97
|
+
"icon_chat_bubble_check",
|
|
98
|
+
"icon_chatting",
|
|
99
|
+
"icon_chatting_send",
|
|
100
|
+
"icon_check",
|
|
101
|
+
"icon_check_flower",
|
|
102
|
+
"icon_chevron_left",
|
|
103
|
+
"icon_chevron_right",
|
|
104
|
+
"icon_click",
|
|
105
|
+
"icon_clock",
|
|
106
|
+
"icon_close",
|
|
107
|
+
"icon_cobuying",
|
|
108
|
+
"icon_community",
|
|
109
|
+
"icon_condo",
|
|
110
|
+
"icon_confirmation",
|
|
111
|
+
"icon_confirmation_pay",
|
|
112
|
+
"icon_confirmation_profile",
|
|
113
|
+
"icon_contents",
|
|
114
|
+
"icon_convert",
|
|
115
|
+
"icon_copy",
|
|
116
|
+
"icon_coupon",
|
|
117
|
+
"icon_coupon_download_done",
|
|
118
|
+
"icon_coupon_used",
|
|
119
|
+
"icon_delete_keyboard",
|
|
120
|
+
"icon_delivery",
|
|
121
|
+
"icon_direction",
|
|
122
|
+
"icon_download",
|
|
123
|
+
"icon_edit",
|
|
124
|
+
"icon_emoticon",
|
|
125
|
+
"icon_emoticon_bad",
|
|
126
|
+
"icon_expand",
|
|
127
|
+
"icon_expand_less",
|
|
128
|
+
"icon_expand_more",
|
|
129
|
+
"icon_file",
|
|
130
|
+
"icon_filter02",
|
|
131
|
+
"icon_forward",
|
|
132
|
+
"icon_gender",
|
|
133
|
+
"icon_global",
|
|
134
|
+
"icon_gps",
|
|
135
|
+
"icon_gps_enable",
|
|
136
|
+
"icon_gps_enable2",
|
|
137
|
+
"icon_groupchat_king",
|
|
138
|
+
"icon_handle",
|
|
139
|
+
"icon_hashtag",
|
|
140
|
+
"icon_headphone",
|
|
141
|
+
"icon_heart",
|
|
142
|
+
"icon_help",
|
|
143
|
+
"icon_helpcenter",
|
|
144
|
+
"icon_helper",
|
|
145
|
+
"icon_home",
|
|
146
|
+
"icon_house",
|
|
147
|
+
"icon_housekeeping_book",
|
|
148
|
+
"icon_import",
|
|
149
|
+
"icon_info",
|
|
150
|
+
"icon_interest",
|
|
151
|
+
"icon_interest_list",
|
|
152
|
+
"icon_invite",
|
|
153
|
+
"icon_invite_friend",
|
|
154
|
+
"icon_ios_share",
|
|
155
|
+
"icon_jobs",
|
|
156
|
+
"icon_keyboard_hiding",
|
|
157
|
+
"icon_keyword",
|
|
158
|
+
"icon_laptop",
|
|
159
|
+
"icon_leaf",
|
|
160
|
+
"icon_list",
|
|
161
|
+
"icon_list_card",
|
|
162
|
+
"icon_list_check",
|
|
163
|
+
"icon_list_select",
|
|
164
|
+
"icon_list_thumbnail",
|
|
165
|
+
"icon_location",
|
|
166
|
+
"icon_lock",
|
|
167
|
+
"icon_loudspeaker",
|
|
168
|
+
"icon_map",
|
|
169
|
+
"icon_market",
|
|
170
|
+
"icon_market_check",
|
|
171
|
+
"icon_market_write",
|
|
172
|
+
"icon_mention",
|
|
173
|
+
"icon_menu",
|
|
174
|
+
"icon_mic",
|
|
175
|
+
"icon_mic_off",
|
|
176
|
+
"icon_mission",
|
|
177
|
+
"icon_mobile",
|
|
178
|
+
"icon_money_send",
|
|
179
|
+
"icon_money_won",
|
|
180
|
+
"icon_moon",
|
|
181
|
+
"icon_more_horiz",
|
|
182
|
+
"icon_more_vert",
|
|
183
|
+
"icon_my",
|
|
184
|
+
"icon_my_profile",
|
|
185
|
+
"icon_near_me",
|
|
186
|
+
"icon_newtopic",
|
|
187
|
+
"icon_note",
|
|
188
|
+
"icon_notification",
|
|
189
|
+
"icon_notification_fall",
|
|
190
|
+
"icon_notification_off",
|
|
191
|
+
"icon_order",
|
|
192
|
+
"icon_pause",
|
|
193
|
+
"icon_payment",
|
|
194
|
+
"icon_percent",
|
|
195
|
+
"icon_photo",
|
|
196
|
+
"icon_photo_edit",
|
|
197
|
+
"icon_photo_edit_crop",
|
|
198
|
+
"icon_photo_edit_draw",
|
|
199
|
+
"icon_photo_edit_rotate",
|
|
200
|
+
"icon_photo_several",
|
|
201
|
+
"icon_play",
|
|
202
|
+
"icon_poll",
|
|
203
|
+
"icon_price_won",
|
|
204
|
+
"icon_product",
|
|
205
|
+
"icon_profile",
|
|
206
|
+
"icon_profile_badge",
|
|
207
|
+
"icon_prohibition",
|
|
208
|
+
"icon_pushpin",
|
|
209
|
+
"icon_question_check",
|
|
210
|
+
"icon_redo",
|
|
211
|
+
"icon_refund",
|
|
212
|
+
"icon_remove_circle",
|
|
213
|
+
"icon_reply",
|
|
214
|
+
"icon_reply_mission",
|
|
215
|
+
"icon_reply_re",
|
|
216
|
+
"icon_report",
|
|
217
|
+
"icon_reservation",
|
|
218
|
+
"icon_restaurant",
|
|
219
|
+
"icon_retry",
|
|
220
|
+
"icon_review_star",
|
|
221
|
+
"icon_scanner",
|
|
222
|
+
"icon_search",
|
|
223
|
+
"icon_search_doc",
|
|
224
|
+
"icon_sell",
|
|
225
|
+
"icon_setting",
|
|
226
|
+
"icon_signout",
|
|
227
|
+
"icon_sort",
|
|
228
|
+
"icon_story",
|
|
229
|
+
"icon_story_article",
|
|
230
|
+
"icon_subtract_circle",
|
|
231
|
+
"icon_subtraction",
|
|
232
|
+
"icon_suggest",
|
|
233
|
+
"icon_sun",
|
|
234
|
+
"icon_talkingdown",
|
|
235
|
+
"icon_talkingup",
|
|
236
|
+
"icon_text",
|
|
237
|
+
"icon_thumb_down",
|
|
238
|
+
"icon_thumb_up",
|
|
239
|
+
"icon_toolbox",
|
|
240
|
+
"icon_translate",
|
|
241
|
+
"icon_trash",
|
|
242
|
+
"icon_undo",
|
|
243
|
+
"icon_user_group",
|
|
244
|
+
"icon_video",
|
|
245
|
+
"icon_view_count",
|
|
246
|
+
"icon_view_count_off",
|
|
247
|
+
"icon_volume_off",
|
|
248
|
+
"icon_volume_on",
|
|
249
|
+
"icon_vote",
|
|
250
|
+
"icon_voucher",
|
|
251
|
+
"icon_walk",
|
|
252
|
+
"icon_warning",
|
|
253
|
+
"icon_write",
|
|
254
|
+
"icon_write_frequent_use",
|
|
255
|
+
"icon_write_story",
|
|
256
|
+
];
|
package/src/index.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { addCommand } from "@/src/commands/add";
|
|
|
4
4
|
import { getPackageInfo } from "@/src/utils/get-package-info";
|
|
5
5
|
import { cac } from "cac";
|
|
6
6
|
import { initCommand } from "./commands/init";
|
|
7
|
-
import {
|
|
7
|
+
import { checkDeprecatedIconFilesCommand } from "@/src/commands/check-deprecated-icon-files";
|
|
8
8
|
|
|
9
9
|
const NAME = "seed-design";
|
|
10
10
|
const CLI = cac(NAME);
|
|
@@ -15,7 +15,7 @@ async function main() {
|
|
|
15
15
|
/* Commands */
|
|
16
16
|
addCommand(CLI);
|
|
17
17
|
initCommand(CLI);
|
|
18
|
-
|
|
18
|
+
checkDeprecatedIconFilesCommand(CLI);
|
|
19
19
|
|
|
20
20
|
CLI.version(packageInfo.version || "1.0.0", "-v, --version");
|
|
21
21
|
CLI.help();
|
package/src/schema.ts
CHANGED
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
import * as prompt from "@clack/prompts";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
import type { CAC } from "cac";
|
|
4
|
-
import {
|
|
5
|
-
filterGitIgnoredFiles,
|
|
6
|
-
getAllFileNamesWithMatchingExtension,
|
|
7
|
-
getAllTypeScriptCompiledFileNames,
|
|
8
|
-
} from "@/src/utils/files";
|
|
9
|
-
import { simpleGit } from "simple-git";
|
|
10
|
-
import jscodeshift from "jscodeshift";
|
|
11
|
-
import { migrateFile, type ImportTransformers } from "@/src/utils/migrate";
|
|
12
|
-
|
|
13
|
-
const importTransformersReact: ImportTransformers = {
|
|
14
|
-
source: [
|
|
15
|
-
{ startsWith: "@seed-design/icons", replaceWith: "@seed-design/react-icon" },
|
|
16
|
-
{ startsWith: "@seed-design/react-icon" },
|
|
17
|
-
],
|
|
18
|
-
identifier: {
|
|
19
|
-
Icon: "NewIcon",
|
|
20
|
-
},
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const iconShiftOptionsSchema = z.object({
|
|
24
|
-
path: z.string().optional(),
|
|
25
|
-
includeIgnored: z.boolean().optional(),
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
// 3. 로그 파일
|
|
29
|
-
// 3-1. 변경된 파일, (라인)
|
|
30
|
-
// 3-2. 에러났을 때 에러 메세지도 같이 들어있고, 어디서 문제 생겼는지도 나와야 한다.
|
|
31
|
-
// 3-2. 그 안에서의 아이콘 AS-IS, TO-BE
|
|
32
|
-
// 4. 마이그레이션 끝났습니다. 로그 파일은 어디 생성됐고, 총 몇개의 아이콘 변경됐습니다.
|
|
33
|
-
|
|
34
|
-
const EXTENSIONS_TO_FIND = [".js", ".jsx", ".ts", ".tsx"];
|
|
35
|
-
const EXTENSIONS_TO_EXCLUDE = [".d.ts"];
|
|
36
|
-
|
|
37
|
-
export const iconShiftCommand = (cli: CAC) => {
|
|
38
|
-
cli
|
|
39
|
-
.command("icon-shift", "V2 아이콘을 V3 아이콘으로 변환하는 명령어")
|
|
40
|
-
.option("--path <path>", "마이그레이션할 소스 코드가 있는 경로 (선택)")
|
|
41
|
-
.option("--include-ignored", ".gitignore를 통해 트래킹되지 않는 파일도 포함할지 여부 (선택)")
|
|
42
|
-
.example("seed-design icon-shift")
|
|
43
|
-
.action(async (opts) => {
|
|
44
|
-
const options = iconShiftOptionsSchema.parse({ ...opts });
|
|
45
|
-
|
|
46
|
-
const pathAvailableTargetPrompt = {
|
|
47
|
-
target: () =>
|
|
48
|
-
prompt.select({
|
|
49
|
-
message: `입력한 경로: ${options.path} 맞나요?`,
|
|
50
|
-
options: [{ label: "네", value: "path" }],
|
|
51
|
-
}),
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
const pathUnavailableTargetPrompt = {
|
|
55
|
-
target: () =>
|
|
56
|
-
prompt.select({
|
|
57
|
-
message: "어떤 파일을 대상으로 마이그레이션을 진행할까요?",
|
|
58
|
-
options: [
|
|
59
|
-
{
|
|
60
|
-
label: "현재 디렉토리에서 사용되는 tsconfig가 컴파일하는 파일",
|
|
61
|
-
value: "tsconfig",
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
// FIXME: 확장자
|
|
65
|
-
label: "현재 디렉토리 안의 .js, .jsx, .ts, .tsx (excluding d.ts)",
|
|
66
|
-
value: "cwd",
|
|
67
|
-
},
|
|
68
|
-
],
|
|
69
|
-
initialValue: "tsconfig.json",
|
|
70
|
-
}),
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
const group = await prompt.group({
|
|
74
|
-
...(options.path ? pathAvailableTargetPrompt : pathUnavailableTargetPrompt),
|
|
75
|
-
...(options.includeIgnored && {
|
|
76
|
-
includeIgnored: () =>
|
|
77
|
-
prompt.confirm({
|
|
78
|
-
message: "git에 트래킹되지 않는 파일도 포함할까요?",
|
|
79
|
-
initialValue: true,
|
|
80
|
-
}),
|
|
81
|
-
}),
|
|
82
|
-
migrateIdentifiers: () =>
|
|
83
|
-
prompt.select({
|
|
84
|
-
message: "어디까지 변경할까요?",
|
|
85
|
-
options: [
|
|
86
|
-
{
|
|
87
|
-
label: "모두 변경",
|
|
88
|
-
value: "all",
|
|
89
|
-
hint: `\n(old) import { IconHeart } from "old-package"; <IconHeart />;\n→ (new) import { NewIconHeart } from "new-package"; <NewIconHeart />;\n`,
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
label: "import만 변경",
|
|
93
|
-
value: "importOnly",
|
|
94
|
-
hint: `\n(old) import { IconHeart } from "old-package"; <IconHeart />;\n→ (new) import { NewIconHeart as IconHeart } from "new-package"; <IconHeart />;\n`,
|
|
95
|
-
},
|
|
96
|
-
],
|
|
97
|
-
initialValue: "all",
|
|
98
|
-
}),
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
const filesFound = (() => {
|
|
102
|
-
switch (group.target) {
|
|
103
|
-
case "tsconfig":
|
|
104
|
-
return getAllTypeScriptCompiledFileNames({
|
|
105
|
-
dirToFindTsconfig: process.cwd(),
|
|
106
|
-
excludeDTs: true,
|
|
107
|
-
});
|
|
108
|
-
case "cwd":
|
|
109
|
-
return getAllFileNamesWithMatchingExtension({
|
|
110
|
-
dir: process.cwd(),
|
|
111
|
-
extensionsToFind: EXTENSIONS_TO_FIND,
|
|
112
|
-
extensionsToExclude: EXTENSIONS_TO_EXCLUDE,
|
|
113
|
-
});
|
|
114
|
-
case "path":
|
|
115
|
-
return getAllFileNamesWithMatchingExtension({
|
|
116
|
-
dir: options.path,
|
|
117
|
-
extensionsToFind: EXTENSIONS_TO_FIND,
|
|
118
|
-
extensionsToExclude: EXTENSIONS_TO_EXCLUDE,
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
})();
|
|
122
|
-
|
|
123
|
-
const { start, message, stop } = prompt.spinner();
|
|
124
|
-
|
|
125
|
-
start("몇 개의 파일을 확인할지 결정하고 있어요.");
|
|
126
|
-
|
|
127
|
-
const filesTracked = options.includeIgnored
|
|
128
|
-
? filesFound
|
|
129
|
-
: await filterGitIgnoredFiles({ git: simpleGit(), filePaths: filesFound });
|
|
130
|
-
|
|
131
|
-
stop(`${filesTracked.length}개 파일에서 예전 아이콘을 찾아볼게요.`);
|
|
132
|
-
|
|
133
|
-
start(`${filesTracked.length}개 파일에서 예전 아이콘을 찾아볼게요.`);
|
|
134
|
-
const j = jscodeshift.withParser("tsx");
|
|
135
|
-
|
|
136
|
-
for (let i = 0; i < filesTracked.length; i++) {
|
|
137
|
-
const filePath = filesTracked[i];
|
|
138
|
-
const percent = (((i + 1) / filesTracked.length) * 100).toFixed(1);
|
|
139
|
-
|
|
140
|
-
message(`파일 ${i + 1}/${filesTracked.length} 변경 시작 (${percent}%): ${filePath}`);
|
|
141
|
-
|
|
142
|
-
migrateFile({ filePath, jscodeshift: j, importTransformers: importTransformersReact });
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
stop("코드 변경이 끝났어요.");
|
|
146
|
-
});
|
|
147
|
-
};
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
|
-
|
|
3
|
-
import { IconHeart } from "some-new-package";
|
|
4
|
-
import { IconStar } from "some-new-package";
|
|
5
|
-
import IconMoon from "some-new-package/IconMoon";
|
|
6
|
-
import * as IconFlame from "some-new-package/IconFlame";
|
|
7
|
-
|
|
8
|
-
export function IconDiv() {
|
|
9
|
-
console.log(IconHeart);
|
|
10
|
-
|
|
11
|
-
return (
|
|
12
|
-
<div>
|
|
13
|
-
<IconHeart />
|
|
14
|
-
<IconStar />
|
|
15
|
-
<IconMoon />
|
|
16
|
-
<IconFlame />
|
|
17
|
-
</div>
|
|
18
|
-
);
|
|
19
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
|
-
|
|
3
|
-
import { IconLike } from "some-package";
|
|
4
|
-
import { IconFavorite } from "some-package";
|
|
5
|
-
import IconNight from "some-package/IconNight";
|
|
6
|
-
import * as IconHot from "some-package/IconHot";
|
|
7
|
-
|
|
8
|
-
export function IconDiv() {
|
|
9
|
-
console.log(IconLike);
|
|
10
|
-
|
|
11
|
-
return (
|
|
12
|
-
<div>
|
|
13
|
-
<IconLike />
|
|
14
|
-
<IconFavorite />
|
|
15
|
-
<IconNight />
|
|
16
|
-
<IconHot />
|
|
17
|
-
</div>
|
|
18
|
-
);
|
|
19
|
-
}
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getFirstNode,
|
|
3
|
-
migrateIdentifiers,
|
|
4
|
-
migrateImportDeclarations,
|
|
5
|
-
type ImportTransformers,
|
|
6
|
-
} from "../../utils/migrate";
|
|
7
|
-
import jscodeshift from "jscodeshift";
|
|
8
|
-
import { describe, expect, test } from "vitest";
|
|
9
|
-
import { Biome, Distribution } from "@biomejs/js-api";
|
|
10
|
-
import fs from "fs";
|
|
11
|
-
import path from "path";
|
|
12
|
-
|
|
13
|
-
const biome = await Biome.create({ distribution: Distribution.NODE });
|
|
14
|
-
biome.applyConfiguration({ formatter: { indentStyle: "space", lineWidth: 100 } });
|
|
15
|
-
|
|
16
|
-
describe("shiftingIcons", () => {
|
|
17
|
-
const j = jscodeshift.withParser("tsx");
|
|
18
|
-
|
|
19
|
-
const importTransformers: ImportTransformers = {
|
|
20
|
-
source: [{ startsWith: "some-package", replaceWith: "some-new-package" }],
|
|
21
|
-
identifier: {
|
|
22
|
-
IconLike: "IconHeart",
|
|
23
|
-
IconFavorite: "IconStar",
|
|
24
|
-
IconHot: "IconFlame",
|
|
25
|
-
IconNight: "IconMoon",
|
|
26
|
-
},
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const cases: Record<string, ("migrateImportDeclarations" | "migrateIdentifiers")[]> = {
|
|
30
|
-
migrateImportDeclarations: ["migrateImportDeclarations"],
|
|
31
|
-
migrateImportDeclarationsVariousTypes: ["migrateImportDeclarations"],
|
|
32
|
-
migrateIdentifiers: ["migrateIdentifiers"],
|
|
33
|
-
migrateImportDeclarationsWithMigrateIdentifiers: [
|
|
34
|
-
"migrateImportDeclarations",
|
|
35
|
-
"migrateIdentifiers",
|
|
36
|
-
],
|
|
37
|
-
migrateImportDeclarationsVariousTypesWithMigrateIdentifiers: [
|
|
38
|
-
"migrateImportDeclarations",
|
|
39
|
-
"migrateIdentifiers",
|
|
40
|
-
],
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
// migrateImportDeclarations
|
|
44
|
-
for (const name in cases) {
|
|
45
|
-
test(name, () => {
|
|
46
|
-
const input = fs.readFileSync(path.resolve(__dirname, `./cases/${name}/input.tsx`), "utf-8");
|
|
47
|
-
const expected = fs.readFileSync(
|
|
48
|
-
path.resolve(__dirname, `./cases/${name}/expected.tsx`),
|
|
49
|
-
"utf-8",
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
-
const tree = j(input);
|
|
53
|
-
const firstNode = getFirstNode({ tree, jscodeshift: j });
|
|
54
|
-
|
|
55
|
-
if (cases[name].includes("migrateImportDeclarations")) {
|
|
56
|
-
const importDeclarations = tree.find(j.ImportDeclaration, {
|
|
57
|
-
source: {
|
|
58
|
-
value: (value: unknown) => {
|
|
59
|
-
if (typeof value !== "string") return false;
|
|
60
|
-
|
|
61
|
-
return importTransformers.source.some(({ startsWith }) =>
|
|
62
|
-
value.startsWith(startsWith),
|
|
63
|
-
);
|
|
64
|
-
},
|
|
65
|
-
},
|
|
66
|
-
});
|
|
67
|
-
migrateImportDeclarations({ importDeclarations, importTransformers });
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (cases[name].includes("migrateIdentifiers")) {
|
|
71
|
-
const identifiers = tree.find(j.Identifier, {
|
|
72
|
-
name: (value) => Object.keys(importTransformers.identifier).includes(value),
|
|
73
|
-
});
|
|
74
|
-
migrateIdentifiers({ identifiers, identifierTransformers: importTransformers.identifier });
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const firstNodeAfterModification = getFirstNode({ tree, jscodeshift: j });
|
|
78
|
-
|
|
79
|
-
if (firstNode !== firstNodeAfterModification) {
|
|
80
|
-
firstNodeAfterModification.comments = firstNode.comments;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const { content } = biome.formatContent(tree.toSource(), {
|
|
84
|
-
filePath: `${name}.tsx`,
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
expect(content).toBe(expected);
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
});
|
package/src/utils/files.ts
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import ts from "typescript";
|
|
2
|
-
import fs from "fs";
|
|
3
|
-
import path from "path";
|
|
4
|
-
import type { SimpleGit } from "simple-git";
|
|
5
|
-
|
|
6
|
-
export function getAllFileNamesWithMatchingExtension({
|
|
7
|
-
dir,
|
|
8
|
-
extensionsToFind,
|
|
9
|
-
extensionsToExclude,
|
|
10
|
-
}: {
|
|
11
|
-
dir: string;
|
|
12
|
-
extensionsToFind: string[];
|
|
13
|
-
extensionsToExclude?: string[];
|
|
14
|
-
}) {
|
|
15
|
-
// XXX: requires Node.js 20+
|
|
16
|
-
return fs
|
|
17
|
-
.readdirSync(dir, { withFileTypes: true, recursive: true })
|
|
18
|
-
.filter(
|
|
19
|
-
(item) =>
|
|
20
|
-
item.isFile() &&
|
|
21
|
-
extensionsToFind.some((ext) => item.name.endsWith(ext)) &&
|
|
22
|
-
(extensionsToExclude ? !extensionsToExclude.some((ext) => item.name.endsWith(ext)) : true),
|
|
23
|
-
)
|
|
24
|
-
.map((item) => `${item.parentPath}/${item.name}`);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function getAllTypeScriptCompiledFileNames({
|
|
28
|
-
dirToFindTsconfig,
|
|
29
|
-
excludeDTs,
|
|
30
|
-
}: {
|
|
31
|
-
dirToFindTsconfig: string;
|
|
32
|
-
excludeDTs?: boolean;
|
|
33
|
-
}) {
|
|
34
|
-
const tsconfigPath = ts.findConfigFile(dirToFindTsconfig, ts.sys.fileExists);
|
|
35
|
-
const tsconfigFile = ts.readConfigFile(tsconfigPath, ts.sys.readFile);
|
|
36
|
-
|
|
37
|
-
// FIXME: throw할 수 있을 것 같음
|
|
38
|
-
const { fileNames } = ts.parseJsonConfigFileContent(
|
|
39
|
-
tsconfigFile.config,
|
|
40
|
-
ts.sys,
|
|
41
|
-
path.dirname(tsconfigPath),
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
return fileNames.filter((fileName) => (excludeDTs ? !fileName.endsWith(".d.ts") : true));
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export async function filterGitIgnoredFiles({
|
|
48
|
-
git,
|
|
49
|
-
filePaths,
|
|
50
|
-
}: {
|
|
51
|
-
git: SimpleGit;
|
|
52
|
-
filePaths: string[];
|
|
53
|
-
}) {
|
|
54
|
-
const promises = await Promise.all(filePaths.map((file) => isFileGitTracked(git, file)));
|
|
55
|
-
|
|
56
|
-
return filePaths.filter((_, index) => promises[index]);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
async function isFileGitTracked(git: SimpleGit, filePath: string) {
|
|
60
|
-
const result = await git.checkIgnore(filePath);
|
|
61
|
-
|
|
62
|
-
return result.length <= 0;
|
|
63
|
-
}
|
package/src/utils/migrate.ts
DELETED
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
import jscodeshift from "jscodeshift";
|
|
2
|
-
import fs from "fs";
|
|
3
|
-
|
|
4
|
-
export interface ImportTransformers {
|
|
5
|
-
source: { startsWith: string; replaceWith?: string }[];
|
|
6
|
-
identifier: Record<string, string>;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
interface MigrateFileParams {
|
|
10
|
-
filePath: string;
|
|
11
|
-
jscodeshift: jscodeshift.JSCodeshift;
|
|
12
|
-
importTransformers: ImportTransformers;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function migrateFile({ filePath, jscodeshift, importTransformers }: MigrateFileParams) {
|
|
16
|
-
const file = fs.readFileSync(filePath, "utf-8");
|
|
17
|
-
|
|
18
|
-
const tree = jscodeshift(file);
|
|
19
|
-
const firstNode = getFirstNode({ tree, jscodeshift: jscodeshift });
|
|
20
|
-
|
|
21
|
-
migrateImportDeclarations({
|
|
22
|
-
importDeclarations: tree.find(jscodeshift.ImportDeclaration, {
|
|
23
|
-
source: {
|
|
24
|
-
value: (value: unknown) => {
|
|
25
|
-
if (typeof value !== "string") return false;
|
|
26
|
-
|
|
27
|
-
return importTransformers.source.some(({ startsWith }) => value.startsWith(startsWith));
|
|
28
|
-
},
|
|
29
|
-
},
|
|
30
|
-
}),
|
|
31
|
-
importTransformers,
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
migrateIdentifiers({
|
|
35
|
-
identifiers: tree.find(jscodeshift.Identifier, {
|
|
36
|
-
name: (value) => Object.keys(importTransformers.identifier).includes(value),
|
|
37
|
-
}),
|
|
38
|
-
identifierTransformers: importTransformers.identifier,
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
const firstNodeAfterModification = getFirstNode({ tree, jscodeshift: jscodeshift });
|
|
42
|
-
|
|
43
|
-
if (firstNode !== firstNodeAfterModification) {
|
|
44
|
-
firstNodeAfterModification.comments = firstNode.comments;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
fs.writeFileSync(filePath, tree.toSource());
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export function getFirstNode({
|
|
51
|
-
tree,
|
|
52
|
-
jscodeshift,
|
|
53
|
-
}: { tree: jscodeshift.Collection; jscodeshift: jscodeshift.JSCodeshift }) {
|
|
54
|
-
return tree.find(jscodeshift.Program).get("body", 0).node;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
interface MigrateImportDeclarationsParams {
|
|
58
|
-
importDeclarations: jscodeshift.Collection<jscodeshift.ImportDeclaration>;
|
|
59
|
-
importTransformers: ImportTransformers;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export function migrateImportDeclarations({
|
|
63
|
-
importDeclarations,
|
|
64
|
-
importTransformers,
|
|
65
|
-
}: MigrateImportDeclarationsParams) {
|
|
66
|
-
importDeclarations.replaceWith((imp) => {
|
|
67
|
-
const currentSourceValue = imp.node.source.value;
|
|
68
|
-
const currentSpecifiers = imp.node.specifiers;
|
|
69
|
-
const currentImportKind = imp.node.importKind;
|
|
70
|
-
|
|
71
|
-
const newSourceValue = (() => {
|
|
72
|
-
if (typeof currentSourceValue !== "string") return currentSourceValue;
|
|
73
|
-
|
|
74
|
-
const { startsWith, replaceWith } = importTransformers.source.find(({ startsWith }) =>
|
|
75
|
-
currentSourceValue.startsWith(startsWith),
|
|
76
|
-
);
|
|
77
|
-
|
|
78
|
-
const sourceReplaced = replaceWith
|
|
79
|
-
? currentSourceValue.replace(startsWith, replaceWith)
|
|
80
|
-
: currentSourceValue;
|
|
81
|
-
|
|
82
|
-
const slashSplits = sourceReplaced.split("/");
|
|
83
|
-
|
|
84
|
-
const itemReplaced = slashSplits
|
|
85
|
-
.map((split, index) => {
|
|
86
|
-
if (index !== slashSplits.length - 1 || split in importTransformers.identifier === false)
|
|
87
|
-
return split;
|
|
88
|
-
|
|
89
|
-
return importTransformers.identifier[split];
|
|
90
|
-
})
|
|
91
|
-
.join("/");
|
|
92
|
-
|
|
93
|
-
return itemReplaced;
|
|
94
|
-
})();
|
|
95
|
-
|
|
96
|
-
const newSpecifiers = currentSpecifiers.map((currentSpecifier) => {
|
|
97
|
-
switch (currentSpecifier.type) {
|
|
98
|
-
case "ImportSpecifier": {
|
|
99
|
-
// import { IconHeart } from "some-package";
|
|
100
|
-
const currentImportedName = currentSpecifier.imported.name;
|
|
101
|
-
|
|
102
|
-
if (currentImportedName in importTransformers.identifier === false)
|
|
103
|
-
return currentSpecifier;
|
|
104
|
-
|
|
105
|
-
const newImportedName = importTransformers.identifier[currentImportedName];
|
|
106
|
-
|
|
107
|
-
const hasNoChange = newImportedName === currentImportedName;
|
|
108
|
-
|
|
109
|
-
if (hasNoChange) return currentSpecifier;
|
|
110
|
-
|
|
111
|
-
// TODO
|
|
112
|
-
// impactedSpecifierCount++;
|
|
113
|
-
const newImportedIdentifier = jscodeshift.identifier(newImportedName);
|
|
114
|
-
|
|
115
|
-
// import { IconHeart as Heart } from "some-package"; 에서
|
|
116
|
-
// imported: "IconHeart", local: "Heart"
|
|
117
|
-
return jscodeshift.importSpecifier(newImportedIdentifier, currentSpecifier.local);
|
|
118
|
-
}
|
|
119
|
-
case "ImportDefaultSpecifier": {
|
|
120
|
-
// import Icon from "some-package";
|
|
121
|
-
return currentSpecifier;
|
|
122
|
-
}
|
|
123
|
-
case "ImportNamespaceSpecifier": {
|
|
124
|
-
// import * as Icon from "some-package";
|
|
125
|
-
return currentSpecifier;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
const newImportDeclaration = jscodeshift.importDeclaration(
|
|
131
|
-
newSpecifiers,
|
|
132
|
-
jscodeshift.literal(newSourceValue),
|
|
133
|
-
currentImportKind,
|
|
134
|
-
);
|
|
135
|
-
|
|
136
|
-
return newImportDeclaration;
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
interface MigrateIdentifiersParams {
|
|
141
|
-
identifiers: jscodeshift.Collection<jscodeshift.Identifier>;
|
|
142
|
-
identifierTransformers: ImportTransformers["identifier"];
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
export function migrateIdentifiers({
|
|
146
|
-
identifiers,
|
|
147
|
-
identifierTransformers,
|
|
148
|
-
}: MigrateIdentifiersParams) {
|
|
149
|
-
identifiers.replaceWith((identifier) => {
|
|
150
|
-
const currentName = identifier.node.name;
|
|
151
|
-
|
|
152
|
-
if (currentName in identifierTransformers === false) return identifier;
|
|
153
|
-
|
|
154
|
-
return jscodeshift.identifier(identifierTransformers[currentName]);
|
|
155
|
-
});
|
|
156
|
-
}
|