@wallavi/vercel-build 0.1.0 → 0.1.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/dist/index.d.ts CHANGED
@@ -92,29 +92,6 @@ declare function ejecutarIgnorar(opciones: OpcionesIgnorar): number;
92
92
  declare function comandoIgnorar(args: string[], entorno: Entorno): number;
93
93
  declare const ignorar: typeof comandoIgnorar;
94
94
 
95
- declare const VARIABLES_VERCEL: readonly ["VERCEL_TOKEN", "VERCEL_ORG_ID", "VERCEL_PROJECT_ID"];
96
- declare const PASOS_VERCEL: readonly (readonly string[])[];
97
- interface ArgumentosDesplegar {
98
- carpeta: string;
99
- antes?: string;
100
- }
101
- declare function leerArgumentosDesplegar(args: readonly string[]): {
102
- ok: true;
103
- valor: ArgumentosDesplegar;
104
- } | {
105
- ok: false;
106
- motivo: string;
107
- };
108
- interface OpcionesDesplegar extends Entorno {
109
- carpeta: string;
110
- antes?: string;
111
- ejecutar?: Ejecutar;
112
- evaluar?: (opciones: OpcionesCambios) => Evaluacion;
113
- }
114
- declare function ejecutarDesplegar(opciones: OpcionesDesplegar): number;
115
- declare function comandoDesplegar(args: string[], entorno: Entorno): number;
116
- declare const desplegar: typeof comandoDesplegar;
117
-
118
95
  declare const API_VERCEL_URL = "https://api.vercel.com";
119
96
  declare const LIMITE_PAGINA_VERCEL = 100;
120
97
  declare const MAX_PAGINAS_VERCEL = 1000;
@@ -978,6 +955,36 @@ declare function ejecutarMedir(opciones: OpcionesMedir): number;
978
955
  declare function comandoMedir(args: string[], entorno: Entorno): number;
979
956
  declare const medir: typeof comandoMedir;
980
957
 
958
+ declare const VARIABLES_VERCEL: readonly ["VERCEL_TOKEN", "VERCEL_ORG_ID", "VERCEL_PROJECT_ID"];
959
+ declare const PASOS_VERCEL: readonly [readonly ["pull", "--yes", "--environment=production"], readonly ["build", "--prod"], readonly ["deploy", "--prebuilt", "--prod"]];
960
+ declare const PASO_DEPLOY_REMOTO: readonly ["deploy", "--prod", "--yes"];
961
+ declare const ARCHIVO_ENV_PRODUCCION: string;
962
+ interface ArgumentosDesplegar {
963
+ carpeta: string;
964
+ antes?: string;
965
+ urlSalud?: string;
966
+ }
967
+ declare function leerArgumentosDesplegar(args: readonly string[]): {
968
+ ok: true;
969
+ valor: ArgumentosDesplegar;
970
+ } | {
971
+ ok: false;
972
+ motivo: string;
973
+ };
974
+ declare function tieneVariablesSensibles(carpeta: string): boolean;
975
+ declare function extraerUrlSalud(salida: string, error?: string): string | null;
976
+ interface OpcionesDesplegar extends Entorno {
977
+ carpeta: string;
978
+ antes?: string;
979
+ urlSalud?: string;
980
+ ejecutar?: Ejecutar;
981
+ evaluar?: (opciones: OpcionesCambios) => Evaluacion;
982
+ solicitar?: SolicitarVercel;
983
+ }
984
+ declare function ejecutarDesplegar(opciones: OpcionesDesplegar): number;
985
+ declare function comandoDesplegar(args: string[], entorno: Entorno): number;
986
+ declare const desplegar: typeof comandoDesplegar;
987
+
981
988
  declare const ARCHIVO_DEPLOYMENTS_V6 = "deployments-v6.json";
982
989
  declare const ARCHIVO_CAPTURA_V6 = "captura-v6.json";
983
990
  declare const REFERENCIA_DEPLOYMENTS_V6 = "https://vercel.com/docs/rest-api/reference/endpoints/deployments/list-deployments";
@@ -1273,7 +1280,7 @@ declare function ejecutarCapturar(opciones: OpcionesCapturar): number;
1273
1280
  declare function comandoCapturar(args: string[], entorno: Entorno): number;
1274
1281
  declare const capturar: typeof comandoCapturar;
1275
1282
 
1276
- declare const USO = "Uso: wallavi-vercel <comando> [opciones]\n\nComandos:\n ignorar decide si Vercel debe omitir el build\n desplegar --carpeta <ruta> [--antes <sha>] compila y despliega a producci\u00F3n si hay cambios\n medir --equipo <slug|team_id> --desde <AAAA-MM-DD> --hasta <AAAA-MM-DD> [...] calcula los minutos de build por d\u00EDa en UTC\n capturar --equipo <slug|team_id> --desde <AAAA-MM-DD> --hasta <AAAA-MM-DD> ... descarga deployments de Vercel y escribe su captura\n\nOpciones:\n -h, --help muestra esta ayuda\n";
1283
+ declare const USO = "Uso: wallavi-vercel <comando> [opciones]\n\nComandos:\n ignorar decide si Vercel debe omitir el build\n desplegar --carpeta <ruta> [--antes <sha>] [--url-salud <url>] compila, despliega y verifica la salud HTTP\n medir --equipo <slug|team_id> --desde <AAAA-MM-DD> --hasta <AAAA-MM-DD> [...] calcula los minutos de build por d\u00EDa en UTC\n capturar --equipo <slug|team_id> --desde <AAAA-MM-DD> --hasta <AAAA-MM-DD> ... descarga deployments de Vercel y escribe su captura\n\nOpciones:\n -h, --help muestra esta ayuda\n";
1277
1284
  interface Entorno {
1278
1285
  cwd: string;
1279
1286
  env: NodeJS.ProcessEnv;
@@ -1284,4 +1291,4 @@ type Comando = (args: string[], entorno: Entorno) => number;
1284
1291
  declare const COMANDOS: Record<string, Comando>;
1285
1292
  declare function principal(argv: string[], entorno: Entorno): number;
1286
1293
 
1287
- export { API_VERCEL_URL, ARCHIVO_CAPTURA_V6, ARCHIVO_CONFIG, ARCHIVO_DEPLOYMENTS_V6, type ArgumentosCapturar, type ArgumentosDesplegar, type ArgumentosMedir, COMANDOS, type CapturaV6, type Comando, type ConfigVercelBuild, type DeploymentVercel, type DiaMinutos, ESTADOS_DEPLOYMENT, type Ejecutar, type Entorno, type EquipoVercel, ErrorContratoVercel, ErrorRedVercel, type Evaluacion, LIMITE_PAGINA_VERCEL, MAX_PAGINAS_VERCEL, type OpcionesCambios, type OpcionesCapturar, type OpcionesDesplegar, type OpcionesIgnorar, type OpcionesMedir, type OpcionesProceso, PASOS_VERCEL, PREFIJO_PREVIEW, type PaginaDeployments, type PaginaTeams, type PaginacionVercel, type PedidoCaptura, type ProyectoVercelBuild, RAMA_PRINCIPAL, REFERENCIA_DEPLOYMENTS_V6, type RespuestaHttp, type Resultado, type ResultadoDeployments, type ResultadoProceso, type SolicitarVercel, USO, VARIABLES_VERCEL, armarCapturaV6, calcularMinutosPorDia, capturar, comandoCapturar, comandoDesplegar, comandoIgnorar, comandoMedir, comandoTurbo, configVacia, consultarDeployments, desplegar, ejecutar, ejecutarCapturar, ejecutarDesplegar, ejecutarIgnorar, ejecutarMedir, esquemaArchivoDeployments, esquemaCapturaV6, esquemaConfig, esquemaDeployment, esquemaEquipo, esquemaEstadoDeployment, esquemaPaginaDeployments, esquemaPaginaTeams, esquemaPaginacion, esquemaPedidoCaptura, evaluarCambios, ignorar, leerArgumentosCapturar, leerArgumentosDesplegar, leerArgumentosMedir, leerConfig, leerFlagsCli, leerRespuestaDeployments, medir, normalizarCarpeta, paquetesDeTurbo, pedirJsonVercel, principal, proyectoDeCarpeta, ramaPermitida, rangoFechasUtc, redactarToken, resolverEquipo, solicitarVercel, ubicarEnRepo, validarConfig, validarFechaIso };
1294
+ export { API_VERCEL_URL, ARCHIVO_CAPTURA_V6, ARCHIVO_CONFIG, ARCHIVO_DEPLOYMENTS_V6, ARCHIVO_ENV_PRODUCCION, type ArgumentosCapturar, type ArgumentosDesplegar, type ArgumentosMedir, COMANDOS, type CapturaV6, type Comando, type ConfigVercelBuild, type DeploymentVercel, type DiaMinutos, ESTADOS_DEPLOYMENT, type Ejecutar, type Entorno, type EquipoVercel, ErrorContratoVercel, ErrorRedVercel, type Evaluacion, LIMITE_PAGINA_VERCEL, MAX_PAGINAS_VERCEL, type OpcionesCambios, type OpcionesCapturar, type OpcionesDesplegar, type OpcionesIgnorar, type OpcionesMedir, type OpcionesProceso, PASOS_VERCEL, PASO_DEPLOY_REMOTO, PREFIJO_PREVIEW, type PaginaDeployments, type PaginaTeams, type PaginacionVercel, type PedidoCaptura, type ProyectoVercelBuild, RAMA_PRINCIPAL, REFERENCIA_DEPLOYMENTS_V6, type RespuestaHttp, type Resultado, type ResultadoDeployments, type ResultadoProceso, type SolicitarVercel, USO, VARIABLES_VERCEL, armarCapturaV6, calcularMinutosPorDia, capturar, comandoCapturar, comandoDesplegar, comandoIgnorar, comandoMedir, comandoTurbo, configVacia, consultarDeployments, desplegar, ejecutar, ejecutarCapturar, ejecutarDesplegar, ejecutarIgnorar, ejecutarMedir, esquemaArchivoDeployments, esquemaCapturaV6, esquemaConfig, esquemaDeployment, esquemaEquipo, esquemaEstadoDeployment, esquemaPaginaDeployments, esquemaPaginaTeams, esquemaPaginacion, esquemaPedidoCaptura, evaluarCambios, extraerUrlSalud, ignorar, leerArgumentosCapturar, leerArgumentosDesplegar, leerArgumentosMedir, leerConfig, leerFlagsCli, leerRespuestaDeployments, medir, normalizarCarpeta, paquetesDeTurbo, pedirJsonVercel, principal, proyectoDeCarpeta, ramaPermitida, rangoFechasUtc, redactarToken, resolverEquipo, solicitarVercel, tieneVariablesSensibles, ubicarEnRepo, validarConfig, validarFechaIso };
package/dist/index.js CHANGED
@@ -722,9 +722,20 @@ var PASOS_VERCEL = [
722
722
  ["build", "--prod"],
723
723
  ["deploy", "--prebuilt", "--prod"]
724
724
  ];
725
+ var PASO_DEPLOY_REMOTO = ["deploy", "--prod", "--yes"];
726
+ var ARCHIVO_ENV_PRODUCCION = path3__namespace.join(
727
+ ".vercel",
728
+ ".env.production.local"
729
+ );
730
+ var MARCADOR_SENSITIVE = "[SENSITIVE]";
731
+ var REGEX_ANSI = new RegExp(
732
+ `${String.fromCharCode(27)}\\[[0-9;]*[a-zA-Z]`,
733
+ "g"
734
+ );
725
735
  function leerArgumentosDesplegar(args) {
726
736
  let carpeta;
727
737
  let antes;
738
+ let urlSalud;
728
739
  for (let i = 0; i < args.length; i++) {
729
740
  const arg = args[i] ?? "";
730
741
  if (arg === "--carpeta" || arg.startsWith("--carpeta=")) {
@@ -743,6 +754,14 @@ function leerArgumentosDesplegar(args) {
743
754
  antes = valor.trim();
744
755
  continue;
745
756
  }
757
+ if (arg === "--url-salud" || arg.startsWith("--url-salud=")) {
758
+ const valor = arg === "--url-salud" ? args[++i] : arg.slice("--url-salud=".length);
759
+ if (!valor || valor.trim() === "" || valor.startsWith("-")) {
760
+ return { ok: false, motivo: "falta el valor de --url-salud <url>" };
761
+ }
762
+ urlSalud = valor.trim();
763
+ continue;
764
+ }
746
765
  return { ok: false, motivo: `argumento no reconocido: ${arg}` };
747
766
  }
748
767
  if (!carpeta) {
@@ -753,9 +772,30 @@ function leerArgumentosDesplegar(args) {
753
772
  }
754
773
  return {
755
774
  ok: true,
756
- valor: { carpeta, ...antes !== void 0 ? { antes } : {} }
775
+ valor: {
776
+ carpeta,
777
+ ...antes !== void 0 ? { antes } : {},
778
+ ...urlSalud !== void 0 ? { urlSalud } : {}
779
+ }
757
780
  };
758
781
  }
782
+ function tieneVariablesSensibles(carpeta) {
783
+ const archivo = path3__namespace.join(carpeta, ARCHIVO_ENV_PRODUCCION);
784
+ return fs.existsSync(archivo) && fs.statSync(archivo).isFile() && fs.readFileSync(archivo, "utf8").includes(MARCADOR_SENSITIVE);
785
+ }
786
+ function extraerUrlSalud(salida, error = "") {
787
+ const stdout = salida.replace(REGEX_ANSI, "");
788
+ const texto = `${error}
789
+ ${salida}`.replace(REGEX_ANSI, "");
790
+ const alias = /\bAlias(?:ed)?\s*:\s*(https?:\/\/[^\s\]"')>]+)/i.exec(
791
+ texto
792
+ )?.[1];
793
+ const urlStdout = /^\s*(https?:\/\/[^\s\]"')>]+)/im.exec(stdout)?.[1];
794
+ const produccion = /\bProduction\s*:\s*(https?:\/\/[^\s\]"')>]+)/i.exec(
795
+ texto
796
+ )?.[1];
797
+ return (alias ?? urlStdout ?? produccion)?.replace(/[.,;]+$/, "") ?? null;
798
+ }
759
799
  function redactarCredenciales(texto, env) {
760
800
  let limpio = texto;
761
801
  for (const nombre of VARIABLES_VERCEL) {
@@ -766,9 +806,30 @@ function redactarCredenciales(texto, env) {
766
806
  }
767
807
  return limpio;
768
808
  }
809
+ function correrPasoVercel(ej, paso, cwd, opciones) {
810
+ const r = ej("vercel", paso, { cwd, env: opciones.env });
811
+ if (r.salida.trim() !== "") {
812
+ opciones.salida(redactarCredenciales(r.salida.trimEnd(), opciones.env));
813
+ }
814
+ if (r.error.trim() !== "") {
815
+ opciones.error(redactarCredenciales(r.error.trimEnd(), opciones.env));
816
+ }
817
+ if (r.codigo !== 0) {
818
+ const codigo = r.codigo ?? 127;
819
+ opciones.error(
820
+ redactarCredenciales(
821
+ `wallavi-vercel desplegar: vercel ${paso.join(" ")} fall\xF3 (${r.fallo ?? `c\xF3digo ${codigo}`})`,
822
+ opciones.env
823
+ )
824
+ );
825
+ return { ok: false, codigo };
826
+ }
827
+ return { ok: true, resultado: r };
828
+ }
769
829
  function ejecutarDesplegar(opciones) {
770
830
  const ej = opciones.ejecutar ?? ejecutar;
771
831
  const evaluar = opciones.evaluar ?? evaluarCambios;
832
+ const solicitar = opciones.solicitar ?? solicitarVercel;
772
833
  const rutaCarpeta = path3__namespace.resolve(opciones.cwd, opciones.carpeta);
773
834
  if (!fs.existsSync(rutaCarpeta) || !fs.statSync(rutaCarpeta).isDirectory()) {
774
835
  opciones.error(
@@ -795,27 +856,64 @@ function ejecutarDesplegar(opciones) {
795
856
  );
796
857
  return 0;
797
858
  }
798
- for (const paso of PASOS_VERCEL) {
799
- const r = ej("vercel", paso, {
800
- cwd: rutaCarpeta,
801
- env: opciones.env
802
- });
803
- if (r.salida.trim() !== "") {
804
- opciones.salida(redactarCredenciales(r.salida.trimEnd(), opciones.env));
805
- }
806
- if (r.error.trim() !== "") {
807
- opciones.error(redactarCredenciales(r.error.trimEnd(), opciones.env));
859
+ const rPull = correrPasoVercel(ej, PASOS_VERCEL[0], rutaCarpeta, opciones);
860
+ if (!rPull.ok) return rPull.codigo;
861
+ const cwdResuelto = path3__namespace.resolve(opciones.cwd);
862
+ const raizGit = ubicarEnRepo(rutaCarpeta, ej)?.raiz ?? ubicarEnRepo(cwdResuelto, ej)?.raiz;
863
+ const carpetasEnv = [
864
+ ...new Set(
865
+ [rutaCarpeta, cwdResuelto, raizGit].filter(
866
+ (c) => Boolean(c)
867
+ )
868
+ )
869
+ ];
870
+ const carpetasSensibles = carpetasEnv.filter(tieneVariablesSensibles);
871
+ const haySensibles = carpetasSensibles.length > 0;
872
+ if (haySensibles) {
873
+ for (const dir of carpetasSensibles) {
874
+ fs.rmSync(path3__namespace.join(dir, ARCHIVO_ENV_PRODUCCION), { force: true });
808
875
  }
809
- if (r.codigo !== 0) {
810
- const codigo = r.codigo ?? 127;
876
+ opciones.salida(
877
+ "wallavi-vercel desplegar: .vercel/.env.production.local contiene [SENSITIVE]; se omite --prebuilt y se delega a vercel deploy --prod --yes"
878
+ );
879
+ }
880
+ const pasosRestantes = haySensibles ? [PASO_DEPLOY_REMOTO] : PASOS_VERCEL.slice(1);
881
+ let ultimoDeploy = rPull.resultado;
882
+ for (const paso of pasosRestantes) {
883
+ const r = correrPasoVercel(ej, paso, rutaCarpeta, opciones);
884
+ if (!r.ok) return r.codigo;
885
+ ultimoDeploy = r.resultado;
886
+ }
887
+ const urlSalud = opciones.urlSalud?.trim() || opciones.env.VERCEL_HEALTHCHECK_URL?.trim() || extraerUrlSalud(ultimoDeploy.salida, ultimoDeploy.error);
888
+ if (!urlSalud) {
889
+ opciones.error(
890
+ redactarCredenciales(
891
+ "wallavi-vercel desplegar: healthcheck HTTP fall\xF3 (no se obtuvo URL del deploy)",
892
+ opciones.env
893
+ )
894
+ );
895
+ return 1;
896
+ }
897
+ try {
898
+ const respuesta = solicitar(urlSalud, {});
899
+ if (respuesta.estado >= 500 || respuesta.cuerpo.includes("MIDDLEWARE_INVOCATION_FAILED")) {
900
+ const detalle = respuesta.cuerpo.includes("MIDDLEWARE_INVOCATION_FAILED") ? `HTTP ${respuesta.estado} MIDDLEWARE_INVOCATION_FAILED` : `HTTP ${respuesta.estado}`;
811
901
  opciones.error(
812
902
  redactarCredenciales(
813
- `wallavi-vercel desplegar: vercel ${paso.join(" ")} fall\xF3 (${r.fallo ?? `c\xF3digo ${codigo}`})`,
903
+ `wallavi-vercel desplegar: healthcheck HTTP fall\xF3 en ${urlSalud} (${detalle})`,
814
904
  opciones.env
815
905
  )
816
906
  );
817
- return codigo;
907
+ return 1;
818
908
  }
909
+ } catch (e) {
910
+ opciones.error(
911
+ redactarCredenciales(
912
+ `wallavi-vercel desplegar: healthcheck HTTP fall\xF3 en ${urlSalud} (${e instanceof Error ? e.message : String(e)})`,
913
+ opciones.env
914
+ )
915
+ );
916
+ return 1;
819
917
  }
820
918
  opciones.salida(
821
919
  `wallavi-vercel desplegar: desplegado (${evaluacion.motivo})`
@@ -831,7 +929,8 @@ function comandoDesplegar(args, entorno) {
831
929
  return ejecutarDesplegar({
832
930
  ...entorno,
833
931
  carpeta: leido.valor.carpeta,
834
- ...leido.valor.antes !== void 0 ? { antes: leido.valor.antes } : {}
932
+ ...leido.valor.antes !== void 0 ? { antes: leido.valor.antes } : {},
933
+ ...leido.valor.urlSalud !== void 0 ? { urlSalud: leido.valor.urlSalud } : {}
835
934
  });
836
935
  }
837
936
  var desplegar = comandoDesplegar;
@@ -905,7 +1004,7 @@ var USO = `Uso: wallavi-vercel <comando> [opciones]
905
1004
 
906
1005
  Comandos:
907
1006
  ignorar decide si Vercel debe omitir el build
908
- desplegar --carpeta <ruta> [--antes <sha>] compila y despliega a producci\xF3n si hay cambios
1007
+ desplegar --carpeta <ruta> [--antes <sha>] [--url-salud <url>] compila, despliega y verifica la salud HTTP
909
1008
  medir --equipo <slug|team_id> --desde <AAAA-MM-DD> --hasta <AAAA-MM-DD> [...] calcula los minutos de build por d\xEDa en UTC
910
1009
  capturar --equipo <slug|team_id> --desde <AAAA-MM-DD> --hasta <AAAA-MM-DD> ... descarga deployments de Vercel y escribe su captura
911
1010
 
@@ -949,6 +1048,7 @@ exports.API_VERCEL_URL = API_VERCEL_URL;
949
1048
  exports.ARCHIVO_CAPTURA_V6 = ARCHIVO_CAPTURA_V6;
950
1049
  exports.ARCHIVO_CONFIG = ARCHIVO_CONFIG;
951
1050
  exports.ARCHIVO_DEPLOYMENTS_V6 = ARCHIVO_DEPLOYMENTS_V6;
1051
+ exports.ARCHIVO_ENV_PRODUCCION = ARCHIVO_ENV_PRODUCCION;
952
1052
  exports.COMANDOS = COMANDOS;
953
1053
  exports.ESTADOS_DEPLOYMENT = ESTADOS_DEPLOYMENT;
954
1054
  exports.ErrorContratoVercel = ErrorContratoVercel;
@@ -956,6 +1056,7 @@ exports.ErrorRedVercel = ErrorRedVercel;
956
1056
  exports.LIMITE_PAGINA_VERCEL = LIMITE_PAGINA_VERCEL;
957
1057
  exports.MAX_PAGINAS_VERCEL = MAX_PAGINAS_VERCEL;
958
1058
  exports.PASOS_VERCEL = PASOS_VERCEL;
1059
+ exports.PASO_DEPLOY_REMOTO = PASO_DEPLOY_REMOTO;
959
1060
  exports.PREFIJO_PREVIEW = PREFIJO_PREVIEW;
960
1061
  exports.RAMA_PRINCIPAL = RAMA_PRINCIPAL;
961
1062
  exports.REFERENCIA_DEPLOYMENTS_V6 = REFERENCIA_DEPLOYMENTS_V6;
@@ -988,6 +1089,7 @@ exports.esquemaPaginaTeams = esquemaPaginaTeams;
988
1089
  exports.esquemaPaginacion = esquemaPaginacion;
989
1090
  exports.esquemaPedidoCaptura = esquemaPedidoCaptura;
990
1091
  exports.evaluarCambios = evaluarCambios;
1092
+ exports.extraerUrlSalud = extraerUrlSalud;
991
1093
  exports.ignorar = ignorar;
992
1094
  exports.leerArgumentosCapturar = leerArgumentosCapturar;
993
1095
  exports.leerArgumentosDesplegar = leerArgumentosDesplegar;
@@ -1006,6 +1108,7 @@ exports.rangoFechasUtc = rangoFechasUtc;
1006
1108
  exports.redactarToken = redactarToken;
1007
1109
  exports.resolverEquipo = resolverEquipo;
1008
1110
  exports.solicitarVercel = solicitarVercel;
1111
+ exports.tieneVariablesSensibles = tieneVariablesSensibles;
1009
1112
  exports.ubicarEnRepo = ubicarEnRepo;
1010
1113
  exports.validarConfig = validarConfig;
1011
1114
  exports.validarFechaIso = validarFechaIso;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wallavi/vercel-build",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "private": false,
5
5
  "description": "Detección de cambios y despliegue compartidos para los proyectos de Vercel del monorepo",
6
6
  "license": "MIT",