Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Init :: Sanitize name and paths #193

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

nmigueles
Copy link
Contributor

@nmigueles nmigueles commented Sep 30, 2024

@nmigueles
Copy link
Contributor Author

nmigueles commented Oct 2, 2024

#188 (comment)
Gracias por el catch @asanzo, ahi probe con un -n '' para forzar el caso del nombre vacío y obvio explotaba por los aires.

Ya esta fixeado el caso
image

Copy link
Contributor

@PalumboN PalumboN left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Groso @nmigueles !!! 💯 🐫

Ahí dejé los comentarios que te había contado y me habían quedado colgado hace un montón jajaj

Entiendo que parte de esto lo charlaste con @asanzo , me gustaría que saber qué piensa de mis comentarios 🤔

@@ -55,6 +55,7 @@
"cytoscape": "^3.15.2",
"express": "^4.18.1",
"globby": "^11.0.4",
"lodash": "^4.17.21",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uhhh polémico 😆

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Esto se usa para las funciones camelCase y kebabCase.

Quizá podemos encontrar alguna implementación por ahí y evitar la dependencia.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines 22 to 23
Assertion.addMethod('pathExists', function () {
const path = this._obj
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😨

const exampleName = name ?? 'example'
logger.info(`Creating definition file ${exampleName}.${WOLLOK_FILE_EXTENSION}`)
writeFileSync(join(project, `${exampleName}.${WOLLOK_FILE_EXTENSION}`), wlkDefinition)
const exampleName = name && name.length > 0 ? name : 'example'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👏

logger.info(`Creating definition file ${exampleName}.${WOLLOK_FILE_EXTENSION}`)
writeFileSync(join(project, `${exampleName}.${WOLLOK_FILE_EXTENSION}`), wlkDefinition)
const exampleName = name && name.length > 0 ? name : 'example'
const exampleFilename = sanitizeName(exampleName)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mmmm tengo dudas sobre esto...

A mí me gusta que los programas entiendan lo que quiero hacer y, o bien lo hagan, o bien me tiren un error.
No sé si este comportamiento entra en alguna de esas.

Si me la estoy mandando en el nombre que elegí, tal vez sea mejor tirar un error.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bueno, bien. Esta es la discusión interesante que quería tener.

Recordando lo frustrante que es elegir una contraseña en un banco y que te la vaya rechazando hasta que le pegás a cuántas mayúsculas y números quiere que tengas, y recordando la premisa que usamos en otros lugares de desburocratizar la UX (como cuando establecimos que el creador de desafíos de Pilas Bloques debía siempre armar desafíos válidos, en lugar de tirar popups de "te falta el personaje" o "no se puede poner un personaje encima de...." etc.), se me ocurrió la propuesta de "dejame pasar todo, corregí lo que quieras, sólo dame mi proyecto Wollok"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pero no me vuelvo loco si quieren mostrar un error del estilo "recordá que los nombres de proyecto deben empezar con minúscula, no incluir caracteres raros. Pueden tener letras, números y guiones bajos pero no espacios o eñes". y listo.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sí, yo prefiero no tomar decisiones por el usuario. Si elegís un nombre incorrecto, que falle es lo más sano (salvo en el package.json que no me interesa mucho que tenga un nombre porque esa validación no es nuestra ni tampoco la queremos)

src/commands/init.ts Show resolved Hide resolved
src/utils.ts Outdated
* Replaces every symbol not allowed with a '_'.
*/
export const sanitizeName = (name: string): string => camelCase(name[0].replace(/([^a-z_])/g, '_$1') + name.slice(1).replace(/[^a-zA-z1-9_-]/g, '_'))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creo que acá se debería re-usar la misma lógica que la validación (habría que hacer un refactor de la función):
https://github.com/uqbar-project/wollok-ts/blob/6ad63ac1f8ad7b069eb61204ab897f8cd49efa0c/src/validator/index.ts#L458-L461

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

De todas formas, yo creo que el problema del issue #188 es que los archivos se están creando con el mismo nombre que el proyecto.... yo no sé si quiero eso.

Yo voto por elegir el nombre del proyecto (carpeta base) y que los archivos siempre se llamen example.wlk, etc.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, ahí me di cuenta que el init crea los archivos pero no la carpeta base... En ese caso esperaría que:

  • si no le digo nada, tenga el cuenta el nombre del directorio en donde estoy
  • si le doy un nombre, me cree una carpeta

No sé, tiro comments para debatir 🍡

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sobre los defaults:

  • No me gusta la de tomar el nombre del directorio. Es raro el comportamiento, no siempre creo una carpeta especialmente. Es sucio, lo sé, pero haría que se llame de formas raras.
  • Si vamos a crear una carpeta, el nombre debería ser obligatorio para mí.
  • De todas formas, opino que no quiero crear una carpeta (el git init no lo hace, el npm init tampoco...)
  • Si no creamos la carpeta, podría tener "example" como nombre de proyecto por defecto y ya, o lo que quieran.
  • No tengo una opinión muy fuerte respecto de tener el nombre del proyecto en los nombres de los archivos. Siento que me gusta que los proyectos tengan nombres de archivos distintos, y por otro lado siento que me gusta la simplicidad de que se llamen todos igual.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No me gusta la de tomar el nombre del directorio. Es raro el comportamiento, no siempre creo una carpeta especialmente. Es sucio, lo sé, pero haría que se llame de formas raras.

+1 y comenté sobre el cambio de exampleFileName. Yo separaría por un lado el proyecto del nombre del example.

De todas formas, opino que no quiero crear una carpeta

stack test sí lo hace, CRA (create-react-app) sí lo hace, svelte-kit sí lo hace. Esta cuestión es debatible, lo que por ahí tiene a favor es que obliga a una persona a crear la carpeta previamente y eso no te va a dar el error de hacer code . en la carpeta raíz como pasa con el 20% de los pibes que reportan errores en Haskell.

Por otra parte, vas a tener el 20% de pibes que van a quejarse cuando creen su segundo proyecto porque van a olvidarse de crear la carpeta y van a tener todo en un gran directorio.

Comment on lines 109 to 123
it('should normalize package.json name when creating with custom name', async () => {
init(undefined, { ...baseOptions, name: 'Pepita Game' })

expect(join(project, 'pepitaGame.wlk')).to.pathExists()
expect(join(project, 'testPepitaGame.wtest')).to.pathExists()
expect(join(project, 'package.json')).to.pathExists()
expect(join(project, GITHUB_FOLDER, 'ci.yml')).to.pathExists()
expect(join(project, 'README.md')).to.pathExists()
expect(join(project, '.gitignore')).to.pathExists()

// Assert content of package.json
const packageJson = readFileSync(join(project, 'package.json'), 'utf8')
const { name } = JSON.parse(packageJson)
expect(name).to.be.equal('pepita-game')
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sé que dije de no tener este comportamiento, pero debo admitir que este test me cabe.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seh, es hermoso.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jajaja, banco!

@nmigueles
Copy link
Contributor Author

Buenas, retomando este PR, para mi la cuestion se divide en 3 partes atacables: (que podrian ser prs por separado para simplificar las discuciones)

  • Arreglar el assertion sobre los paths
  • Normalizar el nombre del proyecto a snake case para al package.json (aca no tenemos otra que mandarle algo valido y para mi lo mejor seria hacerle un kebabCase y olvidarse, obvio haciendo una implementación propia para evitar tener lodash como dependencia)
  • Normalizar / Limitar / X el nombre de los archivos, que mi take aca es que el name del proyecto no tenga injerencia en los nombres de los archivos, es decir, que siempre se llamen de la misma manera, esto puede ser util para generar cierto acostumbramiento en los alumnos y de sobre todo simplificar los tutoriales / docus.

@nmigueles nmigueles mentioned this pull request Dec 2, 2024
Copy link
Contributor

@fdodino fdodino left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bueno @nmigueles ahí dejé algunos comentarios sobre este PR


if (!noTest) {
const testFile = `test${capitalizeFirstLetter(exampleName)}.${TEST_FILE_EXTENSION}`
const testFile = `test${capitalizeFirstLetter(exampleFilename)}.${TEST_FILE_EXTENSION}`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ojo que deberíamos dejar exampleName y en todo caso validarlo/sanitizarlo

}

if (game) {
const gameFile = `main${capitalizeFirstLetter(exampleName)}.${PROGRAM_FILE_EXTENSION}`
const gameFile = `main${capitalizeFirstLetter(exampleFilename)}.${PROGRAM_FILE_EXTENSION}`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lo mismo acá: es exampleName

const exampleName = name && name.length > 0 ? name : 'example'
const exampleFilename = sanitizeName(exampleName)

const wollokDefinitionFile = `${exampleFilename}.${WOLLOK_FILE_EXTENSION}`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ver comentario más abajo exampleName

src/utils.ts Outdated
* Replaces every symbol not allowed with a '_'.
*/
export const sanitizeName = (name: string): string => camelCase(name[0].replace(/([^a-z_])/g, '_$1') + name.slice(1).replace(/[^a-zA-z1-9_-]/g, '_'))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No me gusta la de tomar el nombre del directorio. Es raro el comportamiento, no siempre creo una carpeta especialmente. Es sucio, lo sé, pero haría que se llame de formas raras.

+1 y comenté sobre el cambio de exampleFileName. Yo separaría por un lado el proyecto del nombre del example.

De todas formas, opino que no quiero crear una carpeta

stack test sí lo hace, CRA (create-react-app) sí lo hace, svelte-kit sí lo hace. Esta cuestión es debatible, lo que por ahí tiene a favor es que obliga a una persona a crear la carpeta previamente y eso no te va a dar el error de hacer code . en la carpeta raíz como pasa con el 20% de los pibes que reportan errores en Haskell.

Por otra parte, vas a tener el 20% de pibes que van a quejarse cuando creen su segundo proyecto porque van a olvidarse de crear la carpeta y van a tener todo en un gran directorio.

@@ -55,6 +55,7 @@
"cytoscape": "^3.15.2",
"express": "^4.18.1",
"globby": "^11.0.4",
"lodash": "^4.17.21",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const exists = existsSync(path)

const pathBasePath = path.split('/').slice(0, -1).join('/')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ésto funcionará para Windows?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mismo que aca, lo voy a volar #193 (comment)

const pathBasePath = path.split('/').slice(0, -1).join('/')

// Improve error message if path does not exist
const files = !exists ? lstatSync(pathBasePath).isDirectory() ? readdirSync(pathBasePath) : [] : []
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uh, áspero el : [] : []

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See, todo esto lo pase a #205 y cuando retome esto cuando tenga un cacho lo vuelo de aca, lo simplifique para que funcione y no haga cosas raras

@@ -81,28 +82,80 @@ describe('testing init', () => {
...baseOptions,
noCI: true,
noTest: true,
game: true,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

qué onda? por qué se agregó game: true?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Porque estaba en un limbo el test case, en el arrange seteaba un game: false, pero en el assert comprobaba archivos de game, asi que me parecio mas copado prenderlo

expect(join(project, '.gitignore')).to.pathExists
expect(join(project, 'README.md')).to.pathExists
expect(join(project, 'pepita.wlk')).to.pathExists()
expect(join(project, 'testPepita.wtest')).not.to.pathExists()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

qué loco que el flag no lo usaba y en el test no lo corregí, bien ahí detectando eso

Comment on lines 109 to 123
it('should normalize package.json name when creating with custom name', async () => {
init(undefined, { ...baseOptions, name: 'Pepita Game' })

expect(join(project, 'pepitaGame.wlk')).to.pathExists()
expect(join(project, 'testPepitaGame.wtest')).to.pathExists()
expect(join(project, 'package.json')).to.pathExists()
expect(join(project, GITHUB_FOLDER, 'ci.yml')).to.pathExists()
expect(join(project, 'README.md')).to.pathExists()
expect(join(project, '.gitignore')).to.pathExists()

// Assert content of package.json
const packageJson = readFileSync(join(project, 'package.json'), 'utf8')
const { name } = JSON.parse(packageJson)
expect(name).to.be.equal('pepita-game')
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jajaja, banco!

@nmigueles nmigueles marked this pull request as draft December 13, 2024 03:03
@PalumboN
Copy link
Contributor

PalumboN commented Jan 5, 2025

Qué onda esto @nmigueles @asanzo @fdodino ? Dejamos escrito alguna forma de cerrar este PR?

@fdodino
Copy link
Contributor

fdodino commented Jan 8, 2025

Qué onda esto @nmigueles @asanzo @fdodino ? Dejamos escrito alguna forma de cerrar este PR?

Dale, el jueves nos juntamos a cerrar una definición.

test/init.test.ts Outdated Show resolved Hide resolved
test/init.test.ts Outdated Show resolved Hide resolved
@fdodino
Copy link
Contributor

fdodino commented Jan 10, 2025

Bueno, acá nos juntamos el comité y unánimemente definimos

Crear o no crear la carpeta

  • init: debe crear una carpeta o asumir que hay que ubicarse primero en la carpeta?
    hoy si ponés -p te crea un carpeta y si no ponés -p no te la crea.

    Dejamos ese comportamiento.

Caracteres incorrectos en el proyecto o el nombre

  • qué pasa si elegís un nombre incorrecto (por un ejemplo un nombre con espacios, con caracteres inválidos tipo ?!@-?
    La propuesta del PR era sanitizarlo.

    No hay nada que pueda romper el proyecto, deberíamos dejarlo pasar. En el package.json había un warning, no pasa eso si tenés un profile con Wollok IDE y Wollok Highlighting. **Propuesta: ** usar la misma función que usa la validation (ver si está expuesta) para asegurarnos de que no tire errores linter.

Nombres de los archivos wlk, wtest

  • los nombres de los archivos por defecto: hoy podés elegir -p para el nombre del proyecto y -n para el nombre del ejemplo, si usás
wollok init -p proyectito -n pepita

te genera una carpeta proyectito que tiene adentro pepita.wlk y testPepita.wtest, por defecto si no te deja example.wlk y testExample.wtest.

Qué queremos: Mantener la propuesta

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants