feat(planning): grille hebdomadaire complète avec API et filtres
- Connexion API via proxy Angular (résolution CORS, base path /api) - Import CSS ng-zorro global pour les modales et composants - Filtres Camion/Show câblés sur l'affichage de la grille - Camions affichés via TrucksService (linkés au show du même créneau) - Panneau de détails : spectacles + camions du jour sélectionné - Modale de création de spectacle stylisée avec fond et centrage - Positionnement précis des events à la minute dans leur créneau - Auto-scroll vers l'heure courante au chargement - Ligne "maintenant" sur la colonne du jour actuel - Régénération des services OpenAPI (nouveaux noms de types) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+211
-224
@@ -67,7 +67,7 @@ function normalizePackageBin (pkg, changes) {
|
||||
changes?.push(`"bin[${binKey}]" was renamed to "bin[${base}]"`)
|
||||
}
|
||||
if (binTarget !== pkg.bin[binKey]) {
|
||||
changes?.push(`"bin[${base}]" script name ${binTarget} was invalid and removed`)
|
||||
changes?.push(`"bin[${base}]" script name was cleaned`)
|
||||
}
|
||||
pkg.bin[base] = binTarget
|
||||
}
|
||||
@@ -133,9 +133,15 @@ function secureAndUnixifyPath (ref) {
|
||||
return secured.startsWith('./') ? '' : secured
|
||||
}
|
||||
|
||||
// Only steps that can be ran synchronously. There are some object constructors (i.e. Aborist Node) that need synchronous normalization so here we are.
|
||||
function syncSteps (pkg, { strict, steps, changes, allowLegacyCase }) {
|
||||
// We don't want the `changes` array in here by default because this is a hot
|
||||
// path for parsing packuments during install. So the calling method passes it
|
||||
// in if it wants to track changes.
|
||||
const normalize = async (pkg, { strict, steps, root, changes, allowLegacyCase }) => {
|
||||
if (!pkg.content) {
|
||||
throw new Error('Can not normalize without content')
|
||||
}
|
||||
const data = pkg.content
|
||||
const scripts = data.scripts || {}
|
||||
const pkgId = `${data.name ?? ''}@${data.version ?? ''}`
|
||||
|
||||
// name and version are load bearing so we have to clean them up first
|
||||
@@ -189,7 +195,6 @@ function syncSteps (pkg, { strict, steps, changes, allowLegacyCase }) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// remove attributes that start with "_"
|
||||
if (steps.includes('_attributes')) {
|
||||
for (const key in data) {
|
||||
@@ -209,14 +214,14 @@ function syncSteps (pkg, { strict, steps, changes, allowLegacyCase }) {
|
||||
}
|
||||
|
||||
// fix bundledDependencies typo
|
||||
// normalize bundleDependencies
|
||||
if (steps.includes('bundledDependencies')) {
|
||||
if (data.bundleDependencies === undefined && data.bundledDependencies !== undefined) {
|
||||
data.bundleDependencies = data.bundledDependencies
|
||||
changes?.push(`Deleted incorrect "bundledDependencies"`)
|
||||
}
|
||||
changes?.push(`Deleted incorrect "bundledDependencies"`)
|
||||
delete data.bundledDependencies
|
||||
}
|
||||
|
||||
// expand "bundleDependencies: true or translate from object"
|
||||
if (steps.includes('bundleDependencies')) {
|
||||
const bd = data.bundleDependencies
|
||||
@@ -255,6 +260,32 @@ function syncSteps (pkg, { strict, steps, changes, allowLegacyCase }) {
|
||||
}
|
||||
}
|
||||
|
||||
// add "install" attribute if any "*.gyp" files exist
|
||||
if (steps.includes('gypfile')) {
|
||||
if (!scripts.install && !scripts.preinstall && data.gypfile !== false) {
|
||||
const files = await lazyLoadGlob()('*.gyp', { cwd: pkg.path })
|
||||
if (files.length) {
|
||||
scripts.install = 'node-gyp rebuild'
|
||||
data.scripts = scripts
|
||||
data.gypfile = true
|
||||
changes?.push(`"scripts.install" was set to "node-gyp rebuild"`)
|
||||
changes?.push(`"gypfile" was set to "true"`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add "start" attribute if "server.js" exists
|
||||
if (steps.includes('serverjs') && !scripts.start) {
|
||||
try {
|
||||
await fs.access(path.join(pkg.path, 'server.js'))
|
||||
scripts.start = 'node server.js'
|
||||
data.scripts = scripts
|
||||
changes?.push('"scripts.start" was set to "node server.js"')
|
||||
} catch {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
// strip "node_modules/.bin" from scripts entries
|
||||
// remove invalid scripts entries (non-strings)
|
||||
if ((steps.includes('scripts') || steps.includes('scriptpath')) && data.scripts !== undefined) {
|
||||
@@ -282,6 +313,179 @@ function syncSteps (pkg, { strict, steps, changes, allowLegacyCase }) {
|
||||
}
|
||||
}
|
||||
|
||||
// populate "authors" attribute
|
||||
if (steps.includes('authors') && !data.contributors) {
|
||||
try {
|
||||
const authorData = await fs.readFile(path.join(pkg.path, 'AUTHORS'), 'utf8')
|
||||
const authors = authorData.split(/\r?\n/g)
|
||||
.map(line => line.replace(/^\s*#.*$/, '').trim())
|
||||
.filter(line => line)
|
||||
data.contributors = authors
|
||||
changes?.push('"contributors" was auto-populated with the contents of the "AUTHORS" file')
|
||||
} catch {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
// populate "readme" attribute
|
||||
if (steps.includes('readme') && !data.readme) {
|
||||
const mdre = /\.m?a?r?k?d?o?w?n?$/i
|
||||
const files = await lazyLoadGlob()('{README,README.*}', {
|
||||
cwd: pkg.path,
|
||||
nocase: true,
|
||||
mark: true,
|
||||
})
|
||||
let readmeFile
|
||||
for (const file of files) {
|
||||
// don't accept directories.
|
||||
if (!file.endsWith(path.sep)) {
|
||||
if (file.match(mdre)) {
|
||||
readmeFile = file
|
||||
break
|
||||
}
|
||||
if (file.endsWith('README')) {
|
||||
readmeFile = file
|
||||
}
|
||||
}
|
||||
}
|
||||
if (readmeFile) {
|
||||
const readmeData = await fs.readFile(path.join(pkg.path, readmeFile), 'utf8')
|
||||
data.readme = readmeData
|
||||
data.readmeFilename = readmeFile
|
||||
changes?.push(`"readme" was set to the contents of ${readmeFile}`)
|
||||
changes?.push(`"readmeFilename" was set to ${readmeFile}`)
|
||||
}
|
||||
if (!data.readme) {
|
||||
data.readme = 'ERROR: No README data found!'
|
||||
}
|
||||
}
|
||||
|
||||
// expand directories.man
|
||||
if (steps.includes('mans')) {
|
||||
if (data.directories?.man && !data.man) {
|
||||
const manDir = secureAndUnixifyPath(data.directories.man)
|
||||
const cwd = path.resolve(pkg.path, manDir)
|
||||
const files = await lazyLoadGlob()('**/*.[0-9]', { cwd })
|
||||
data.man = files.map(man =>
|
||||
path.relative(pkg.path, path.join(cwd, man)).split(path.sep).join('/')
|
||||
)
|
||||
}
|
||||
normalizePackageMan(data, changes)
|
||||
}
|
||||
|
||||
if (steps.includes('bin') || steps.includes('binDir') || steps.includes('binRefs')) {
|
||||
normalizePackageBin(data, changes)
|
||||
}
|
||||
|
||||
// expand "directories.bin"
|
||||
if (steps.includes('binDir') && data.directories?.bin && !data.bin) {
|
||||
const binsDir = path.resolve(pkg.path, secureAndUnixifyPath(data.directories.bin))
|
||||
const bins = await lazyLoadGlob()('**', { cwd: binsDir })
|
||||
data.bin = bins.reduce((acc, binFile) => {
|
||||
if (binFile && !binFile.startsWith('.')) {
|
||||
const binName = path.basename(binFile)
|
||||
acc[binName] = path.join(data.directories.bin, binFile)
|
||||
}
|
||||
return acc
|
||||
}, {})
|
||||
// *sigh*
|
||||
normalizePackageBin(data, changes)
|
||||
}
|
||||
|
||||
// populate "gitHead" attribute
|
||||
if (steps.includes('gitHead') && !data.gitHead) {
|
||||
const git = require('@npmcli/git')
|
||||
const gitRoot = await git.find({ cwd: pkg.path, root })
|
||||
let head
|
||||
if (gitRoot) {
|
||||
try {
|
||||
head = await fs.readFile(path.resolve(gitRoot, '.git/HEAD'), 'utf8')
|
||||
} catch (err) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
let headData
|
||||
if (head) {
|
||||
if (head.startsWith('ref: ')) {
|
||||
const headRef = head.replace(/^ref: /, '').trim()
|
||||
const headFile = path.resolve(gitRoot, '.git', headRef)
|
||||
try {
|
||||
headData = await fs.readFile(headFile, 'utf8')
|
||||
headData = headData.replace(/^ref: /, '').trim()
|
||||
} catch (err) {
|
||||
// do nothing
|
||||
}
|
||||
if (!headData) {
|
||||
const packFile = path.resolve(gitRoot, '.git/packed-refs')
|
||||
try {
|
||||
let refs = await fs.readFile(packFile, 'utf8')
|
||||
if (refs) {
|
||||
refs = refs.split('\n')
|
||||
for (let i = 0; i < refs.length; i++) {
|
||||
const match = refs[i].match(/^([0-9a-f]{40}) (.+)$/)
|
||||
if (match && match[2].trim() === headRef) {
|
||||
headData = match[1]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
} else {
|
||||
headData = head.trim()
|
||||
}
|
||||
}
|
||||
if (headData) {
|
||||
data.gitHead = headData
|
||||
}
|
||||
}
|
||||
|
||||
// populate "types" attribute
|
||||
if (steps.includes('fillTypes')) {
|
||||
const index = data.main || 'index.js'
|
||||
|
||||
if (typeof index !== 'string') {
|
||||
throw new TypeError('The "main" attribute must be of type string.')
|
||||
}
|
||||
|
||||
// TODO exports is much more complicated than this in verbose format
|
||||
// We need to support for instance
|
||||
|
||||
// "exports": {
|
||||
// ".": [
|
||||
// {
|
||||
// "default": "./lib/npm.js"
|
||||
// },
|
||||
// "./lib/npm.js"
|
||||
// ],
|
||||
// "./package.json": "./package.json"
|
||||
// },
|
||||
// as well as conditional exports
|
||||
|
||||
// if (data.exports && typeof data.exports === 'string') {
|
||||
// index = data.exports
|
||||
// }
|
||||
|
||||
// if (data.exports && data.exports['.']) {
|
||||
// index = data.exports['.']
|
||||
// if (typeof index !== 'string') {
|
||||
// }
|
||||
// }
|
||||
const extless = path.join(path.dirname(index), path.basename(index, path.extname(index)))
|
||||
const dts = `./${extless}.d.ts`
|
||||
const hasDTSFields = 'types' in data || 'typings' in data
|
||||
if (!hasDTSFields) {
|
||||
try {
|
||||
await fs.access(path.join(pkg.path, dts))
|
||||
data.types = dts.split(path.sep).join('/')
|
||||
} catch {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// "normalizeData" from "read-package-json", which was just a call through to
|
||||
// "normalize-package-data". We only call the "fixer" functions because
|
||||
// outside of that it was also clobbering _id (which we already conditionally
|
||||
@@ -379,209 +583,6 @@ function syncSteps (pkg, { strict, steps, changes, allowLegacyCase }) {
|
||||
const { normalizeData } = require('./normalize-data.js')
|
||||
normalizeData(data, changes)
|
||||
}
|
||||
}
|
||||
|
||||
// Steps that require await, distinct from sync-steps.js
|
||||
async function asyncSteps (pkg, { steps, root, changes }) {
|
||||
const data = pkg.content
|
||||
const scripts = data.scripts || {}
|
||||
const pkgId = `${data.name ?? ''}@${data.version ?? ''}`
|
||||
|
||||
// add "install" attribute if any "*.gyp" files exist
|
||||
if (steps.includes('gypfile')) {
|
||||
if (!scripts.install && !scripts.preinstall && data.gypfile !== false) {
|
||||
const files = await lazyLoadGlob()('*.gyp', { cwd: pkg.path })
|
||||
if (files.length) {
|
||||
scripts.install = 'node-gyp rebuild'
|
||||
data.scripts = scripts
|
||||
data.gypfile = true
|
||||
changes?.push(`"scripts.install" was set to "node-gyp rebuild"`)
|
||||
changes?.push(`"gypfile" was set to "true"`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add "start" attribute if "server.js" exists
|
||||
if (steps.includes('serverjs') && !scripts.start) {
|
||||
try {
|
||||
await fs.access(path.join(pkg.path, 'server.js'))
|
||||
scripts.start = 'node server.js'
|
||||
data.scripts = scripts
|
||||
changes?.push('"scripts.start" was set to "node server.js"')
|
||||
} catch {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
// populate "authors" attribute
|
||||
if (steps.includes('authors') && !data.contributors) {
|
||||
try {
|
||||
const authorData = await fs.readFile(path.join(pkg.path, 'AUTHORS'), 'utf8')
|
||||
const authors = authorData.split(/\r?\n/g)
|
||||
.map(line => line.replace(/^\s*#.*$/, '').trim())
|
||||
.filter(line => line)
|
||||
data.contributors = authors
|
||||
changes?.push('"contributors" was auto-populated with the contents of the "AUTHORS" file')
|
||||
} catch {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
// populate "readme" attribute
|
||||
if (steps.includes('readme') && !data.readme) {
|
||||
const mdre = /\.m?a?r?k?d?o?w?n?$/i
|
||||
const files = await lazyLoadGlob()('{README,README.*}', {
|
||||
cwd: pkg.path,
|
||||
nocase: true,
|
||||
mark: true,
|
||||
})
|
||||
let readmeFile
|
||||
for (const file of files) {
|
||||
// don't accept directories.
|
||||
if (!file.endsWith(path.sep)) {
|
||||
if (file.match(mdre)) {
|
||||
readmeFile = file
|
||||
break
|
||||
}
|
||||
if (file.endsWith('README')) {
|
||||
readmeFile = file
|
||||
}
|
||||
}
|
||||
}
|
||||
if (readmeFile) {
|
||||
const readmeData = await fs.readFile(path.join(pkg.path, readmeFile), 'utf8')
|
||||
data.readme = readmeData
|
||||
data.readmeFilename = readmeFile
|
||||
changes?.push(`"readme" was set to the contents of ${readmeFile}`)
|
||||
changes?.push(`"readmeFilename" was set to ${readmeFile}`)
|
||||
}
|
||||
if (!data.readme) {
|
||||
data.readme = 'ERROR: No README data found!'
|
||||
}
|
||||
}
|
||||
|
||||
// expand directories.man
|
||||
if (steps.includes('mans')) {
|
||||
if (data.directories?.man && !data.man) {
|
||||
const manDir = secureAndUnixifyPath(data.directories.man)
|
||||
const cwd = path.resolve(pkg.path, manDir)
|
||||
const files = await lazyLoadGlob()('**/*.[0-9]', { cwd })
|
||||
data.man = files.map(man =>
|
||||
path.relative(pkg.path, path.join(cwd, man)).split(path.sep).join('/')
|
||||
)
|
||||
}
|
||||
normalizePackageMan(data, changes)
|
||||
}
|
||||
|
||||
// expand "directories.bin"
|
||||
if (steps.includes('binDir') && data.directories?.bin && !data.bin && pkg.path) {
|
||||
const binPath = secureAndUnixifyPath(data.directories.bin)
|
||||
const bins = await lazyLoadGlob()('**', { cwd: path.resolve(pkg.path, binPath) })
|
||||
data.bin = bins.reduce((acc, binFile) => {
|
||||
if (binFile && !binFile.startsWith('.')) {
|
||||
const binName = path.basename(binFile)
|
||||
// binPath is already cleaned and unixified, no need to path.join here.
|
||||
acc[binName] = `${binPath}/${secureAndUnixifyPath(binFile)}`
|
||||
}
|
||||
return acc
|
||||
}, {})
|
||||
} else if (steps.includes('bin') || steps.includes('binDir') || steps.includes('binRefs')) {
|
||||
normalizePackageBin(data, changes)
|
||||
}
|
||||
|
||||
// populate "gitHead" attribute
|
||||
if (steps.includes('gitHead') && !data.gitHead) {
|
||||
const git = require('@npmcli/git')
|
||||
const gitRoot = await git.find({ cwd: pkg.path, root })
|
||||
let head
|
||||
if (gitRoot) {
|
||||
try {
|
||||
head = await fs.readFile(path.resolve(gitRoot, '.git/HEAD'), 'utf8')
|
||||
} catch (err) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
let headData
|
||||
if (head) {
|
||||
if (head.startsWith('ref: ')) {
|
||||
const headRef = head.replace(/^ref: /, '').trim()
|
||||
const headFile = path.resolve(gitRoot, '.git', headRef)
|
||||
try {
|
||||
headData = await fs.readFile(headFile, 'utf8')
|
||||
headData = headData.replace(/^ref: /, '').trim()
|
||||
} catch (err) {
|
||||
// do nothing
|
||||
}
|
||||
if (!headData) {
|
||||
const packFile = path.resolve(gitRoot, '.git/packed-refs')
|
||||
try {
|
||||
let refs = await fs.readFile(packFile, 'utf8')
|
||||
if (refs) {
|
||||
refs = refs.split('\n')
|
||||
for (let i = 0; i < refs.length; i++) {
|
||||
const match = refs[i].match(/^([0-9a-f]{40}) (.+)$/)
|
||||
if (match && match[2].trim() === headRef) {
|
||||
headData = match[1]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
} else {
|
||||
headData = head.trim()
|
||||
}
|
||||
}
|
||||
if (headData) {
|
||||
data.gitHead = headData
|
||||
}
|
||||
}
|
||||
|
||||
// populate "types" attribute
|
||||
if (steps.includes('fillTypes')) {
|
||||
const index = data.main || 'index.js'
|
||||
|
||||
if (typeof index !== 'string') {
|
||||
throw new TypeError('The "main" attribute must be of type string.')
|
||||
}
|
||||
|
||||
// TODO exports is much more complicated than this in verbose format
|
||||
// We need to support for instance
|
||||
|
||||
// "exports": {
|
||||
// ".": [
|
||||
// {
|
||||
// "default": "./lib/npm.js"
|
||||
// },
|
||||
// "./lib/npm.js"
|
||||
// ],
|
||||
// "./package.json": "./package.json"
|
||||
// },
|
||||
// as well as conditional exports
|
||||
|
||||
// if (data.exports && typeof data.exports === 'string') {
|
||||
// index = data.exports
|
||||
// }
|
||||
|
||||
// if (data.exports && data.exports['.']) {
|
||||
// index = data.exports['.']
|
||||
// if (typeof index !== 'string') {
|
||||
// }
|
||||
// }
|
||||
const extless = path.join(path.dirname(index), path.basename(index, path.extname(index)))
|
||||
const dts = `./${extless}.d.ts`
|
||||
const hasDTSFields = 'types' in data || 'typings' in data
|
||||
if (!hasDTSFields) {
|
||||
try {
|
||||
await fs.access(path.join(pkg.path, dts))
|
||||
data.types = dts.split(path.sep).join('/')
|
||||
} catch {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Warn if the bin references don't point to anything. This might be better
|
||||
// in normalize-package-data if it had access to the file path.
|
||||
@@ -597,18 +598,4 @@ async function asyncSteps (pkg, { steps, root, changes }) {
|
||||
}
|
||||
}
|
||||
|
||||
// We don't want the `changes` array in here by default because this is a hot path for parsing packuments during install. The calling method passes it in if it wants to track changes.
|
||||
async function normalize (pkg, opts) {
|
||||
if (!pkg.content) {
|
||||
throw new Error('Can not normalize without content')
|
||||
}
|
||||
await asyncSteps(pkg, opts)
|
||||
// the normalizeData part of this needs to be the last thing ran, so sync comes second
|
||||
syncSteps(pkg, opts)
|
||||
}
|
||||
|
||||
function syncNormalize (pkg, opts) {
|
||||
syncSteps(pkg, opts)
|
||||
}
|
||||
|
||||
module.exports = { normalize, syncNormalize }
|
||||
module.exports = normalize
|
||||
|
||||
Reference in New Issue
Block a user