New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@allmaps/cli

Package Overview
Dependencies
Maintainers
0
Versions
39
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@allmaps/cli - npm Package Compare versions

Comparing version 1.0.0-beta.39 to 1.0.0-beta.40

dist/commands/annotation/image-ids.d.ts

4

dist/commands/annotation.js

@@ -5,2 +5,3 @@ import { Command } from 'commander';

import svg from './annotation/svg.js';
import imageIds from './annotation/image-ids.js';
export default function annotation() {

@@ -12,3 +13,4 @@ return new Command('annotation')

.addCommand(generate())
.addCommand(svg());
.addCommand(svg())
.addCommand(imageIds());
}

@@ -9,3 +9,3 @@ import { Command } from 'commander';

.summary('generate Georeference Annotation')
.description(`Generate a single Georeference Annotation from input files`)
.description('Generate a single Georeference Annotation from input files')
.action(async (files) => {

@@ -12,0 +12,0 @@ const jsonValues = await parseJsonInput(files);

@@ -8,3 +8,3 @@ import { Command } from 'commander';

.summary('parse Georeference Annotation')
.description(`Parses and validates Georeference Annotations and outputs Allmaps' internal format`)
.description("Parses and validates Georeference Annotations and outputs Allmaps' internal format")
.action(async (files) => {

@@ -11,0 +11,0 @@ const jsonValues = await parseJsonInput(files);

import { Command } from 'commander';
import { generateId } from '@allmaps/id';
import { readFromStdin, printString } from '../lib/io.js';
// Instead of supplying input files, you can also use the standard input
export default function id() {

@@ -6,0 +5,0 @@ return new Command('id')

import { Command } from 'commander';
import parse from './iiif/parse.js';
import manifest from './iiif/manifest.js';
import imageIds from './iiif/image-ids.js';
export default function iiif() {

@@ -9,3 +10,4 @@ return new Command('iiif')

.addCommand(parse())
.addCommand(manifest());
.addCommand(manifest())
.addCommand(imageIds());
}

@@ -10,3 +10,3 @@ import { Command } from 'commander';

.summary('generate IIIF Manifest')
.description(`Generates IIIF Manifest from other IIIF Manifests, IIIF Image Information and Georeference Annotations`)
.description('Generates IIIF Manifest from other IIIF Manifests, IIIF Image Information and Georeference Annotations')
// TODO: add version option to allow choosing between IIIF Presentation API 2.1 and 3.0

@@ -13,0 +13,0 @@ .option('-i, --id <id>', 'Manifest ID', 'https://example.org/manifest')

import { Command } from 'commander';
import { fromZodError } from 'zod-validation-error';
import { IIIF } from '@allmaps/iiif-parser';
import { parseJsonInput, printJson } from '../../lib/io.js';
import { parseIiif } from '../../lib/iiif.js';
import { addParseIiifOptions } from '../../lib/options.js';
export default function parse() {
return new Command('parse')
let command = new Command('parse')
.argument('[files...]')
.summary('parse IIIF resources')
.description('Parses IIIF resources and outputs them in the internal format used by Allmaps')
.action(async (files) => {
.description('Parses IIIF resources and outputs them in the internal format used by Allmaps');
command = addParseIiifOptions(command);
return command.action(async (files, options) => {
const jsonValues = await parseJsonInput(files);
const parsedIiif = [];
const parsedIiifs = [];
for (const jsonValue of jsonValues) {
try {
parsedIiif.push(IIIF.parse(jsonValue));
const parseIiifOptions = {
fetchCollections: options.fetchCollections,
fetchManifests: options.fetchManifests,
fetchImages: options.fetchImages,
fetchAll: options.fetchAll
};
const parsedIiif = await parseIiif(jsonValue, parseIiifOptions);
parsedIiifs.push(parsedIiif);
}

@@ -28,8 +37,8 @@ catch (err) {

}
if (parsedIiif.length) {
if (parsedIiifs.length) {
if (jsonValues.length === 1) {
printJson({ ...parsedIiif[0] });
printJson({ ...parsedIiifs[0] });
}
else {
printJson({ ...parsedIiif });
printJson({ ...parsedIiifs });
}

@@ -36,0 +45,0 @@ }

@@ -5,2 +5,4 @@ #!/usr/bin/env node

import annotation from './commands/annotation.js';
import script from './commands/script.js';
import fetch from './commands/fetch.js';
import id from './commands/id.js';

@@ -14,5 +16,7 @@ import iiif from './commands/iiif.js';

.addCommand(annotation())
.addCommand(id())
.addCommand(transform())
.addCommand(iiif())
.addCommand(id())
.addCommand(fetch())
.addCommand(script())
.configureHelp({

@@ -19,0 +23,0 @@ helpWidth: fixedWidth ? 80 : undefined

@@ -1,29 +0,100 @@

"use strict";
// export function gdalwarp (imageFilename, basename, outputDir, gcps, geoMask, tr = 0.5) {
// return `
// #!/usr/bin/env bash
// mkdir -p ${outputDir}
// gdal_translate -of vrt \\
// -a_srs EPSG:4326 \\
// ${gcps.map((gcp) => `-gcp ${gcp.image.join(' ')} ${gcp.world.join(' ')}`).join(' \\\n')} \\
// ${imageFilename} \\
// ${outputDir}/${basename}.vrt
// echo '${JSON.stringify(geoMask)}' > ${outputDir}/${basename}.geojson
// gdalwarp -co TILED=YES \\
// -co COMPRESS=JPEG -co JPEG_QUALITY=80 \\
// -dstalpha -overwrite \\
// -cutline ${outputDir}/${basename}.geojson -crop_to_cutline \\
// -tr ${tr} ${tr} -t_srs "EPSG:3857" \\
// ${outputDir}/${basename}.vrt \\
// ${outputDir}/${basename}-warped.tif`.trim()
// }
// export function gdalmerge (outputDir, inputTiffs, outputTiff) {
// // TODO: merge to VRT?!?!?!
// return `
// gdal_merge.py -o ${outputDir}/${outputTiff} \\
// ${inputTiffs.map((tiff) => `${outputDir}/${tiff}`).join(' ')}`.trim()
// }
// export function gdal2tiles (outputDir, outputTiff, layerId) {
// return `
// gdal2tiles.py --xyz ${outputDir}/${outputTiff} ${outputDir}/${layerId}`.trim()
// }
import path from 'path';
import { checkCommand } from './bash.js';
const defaultOptions = {
srs: 'EPSG:3857',
quality: 75
};
const jqNotFoundMessage = 'Please install jq: https://jqlang.github.io/jq/.';
const gdalNotFoundMessage = 'Please install GDAL.';
export function preamble(outputDir) {
return `#!/usr/bin/env bash
mkdir -p ${outputDir}
${checkCommand('gdalinfo', gdalNotFoundMessage)}
${checkCommand('gdalbuildvrt', gdalNotFoundMessage)}
${checkCommand('gdal_translate', gdalNotFoundMessage)}
${checkCommand('gdalwarp', gdalNotFoundMessage)}
${checkCommand('jq', jqNotFoundMessage)}`.trim();
}
export function checkImageExistsAndCorrectSize(imageFilename, basename, map) {
return `
if ! [ -f ${imageFilename} ]; then
echo "Image file does not exist: ${imageFilename}"
echo "This script expects a full-size source images for each georeferenced map it processes. See the README for more information."
exit 1
fi
required_width_${basename}=${map.resource.width}
required_height_${basename}=${map.resource.height}
width_${basename}=( $(gdalinfo -json ${imageFilename} | jq '.size[0]') )
height_${basename}=( $(gdalinfo -json ${imageFilename} | jq '.size[1]') )
if [ "$width_${basename}" -eq "$required_width_${basename}" ] &&
[ "$height_${basename}" -eq "$required_height_${basename}" ]; then
echo "Found image with correct size: ${imageFilename}"
else
echo "Error: found image with incorrect size"
echo " Image: ${imageFilename}"
echo " Expected: $required_width_${basename} x $required_height_${basename}"
echo " Found: $width_${basename} x $height_${basename}"
exit 1
fi`.trim();
}
export function gdalwarp(imageFilename, basename, outputDir, map, geoMask, options) {
// See also: https://blog.cleverelephant.ca/2015/02/geotiff-compression-for-dummies.html
options = { ...defaultOptions, ...options };
// TODO: parseTransformationType(options, map)
// Read transformation from georeferenced map
// See https://gdal.org/programs/gdalwarp.html#cmdoption-gdalwarp-tps
let transformationArguments = '-order 1';
let transformationMessage = '';
if (map.transformation) {
if (map.transformation.type === 'polynomial') {
if (map.transformation.order) {
transformationArguments = `-order ${map.transformation.order}`;
}
}
else if (map.transformation.type === 'thinPlateSpline') {
transformationArguments = '-tps';
}
else if (map.transformation.type) {
transformationMessage = `Transformation type "${map.transformation.type}" is not supported. Using default transformation.`;
}
}
const vrtFilename = path.join(outputDir, `${basename}.vrt`);
const geojsonFilename = path.join(outputDir, `${basename}.geojson`);
const geotiffFilename = path.join(outputDir, `${basename}-warped.tif`);
return `${transformationMessage ? `echo "${transformationMessage}"` : ''}
gdal_translate -of vrt \\
-a_srs EPSG:4326 \\
${map.gcps
.map((gcp) => `-gcp ${gcp.resource.join(' ')} ${gcp.geo.join(' ')}`)
.join(' \\\n')} \\
${imageFilename} \\
${vrtFilename}
echo '${JSON.stringify(geoMask)}' > ${geojsonFilename}
gdalwarp \\
-of COG -co COMPRESS=JPEG -co QUALITY=${options.quality} \\
-dstalpha -overwrite \\
-cutline ${geojsonFilename} -crop_to_cutline \\
-t_srs "${options.srs}" \\
${transformationArguments} \\
${vrtFilename} \\
${geotiffFilename}`.trim();
}
export function gdalbuildvrt(outputDir, inputTiffs, outputVrt) {
const vrtFilename = path.join(outputDir, outputVrt);
return `
gdalbuildvrt ${vrtFilename} \\
${inputTiffs.map((tiff) => path.join(outputDir, tiff)).join(' ')}`.trim();
}
// TODO: consider adding gdal2tiles export:
// gdal2tiles.py --xyz merged.vrt merged
// TODO: consider adding pmtiles export:
// gdal_translate -of MBTILES merged.vrt merged.mbtiles
// pmtiles convert merged.mbtiles merged.pmtiles
import type { EmbeddedImage } from '@allmaps/iiif-parser';
type ParseOptions = {
fetchCollections: boolean;
fetchManifests: boolean;
fetchImages: boolean;
fetchAll: boolean;
};
export declare function parseIiif(sourceIiif: unknown, options?: Partial<ParseOptions>): Promise<import("@allmaps/iiif-parser").Manifest | import("@allmaps/iiif-parser").Collection | import("@allmaps/iiif-parser").Image>;
export declare function generateManifest(id: string, images: EmbeddedImage[]): {

@@ -34,1 +41,2 @@ '@context': string;

};
export {};

@@ -0,1 +1,35 @@

import { IIIF } from '@allmaps/iiif-parser';
const defaultParseOptions = {
fetchCollections: false,
fetchManifests: false,
fetchImages: false,
fetchAll: false
};
function fetchFn(input, init) {
console.warn('Fetching', input);
return fetch(input, init);
}
export async function parseIiif(sourceIiif, options) {
if (options && options.fetchAll) {
options = {
fetchCollections: true,
fetchManifests: true,
fetchImages: true
};
}
else {
options = {
...defaultParseOptions,
...options
};
}
const parsedIiif = IIIF.parse(sourceIiif);
if (parsedIiif.type === 'collection') {
await parsedIiif.fetchAll({ ...options, fetchFn });
}
else if (parsedIiif.type === 'manifest' && options && options.fetchImages) {
await parsedIiif.fetchAll(fetchFn);
}
return parsedIiif;
}
function generateImageService(image) {

@@ -2,0 +36,0 @@ const profile = image.supportsAnyRegionAndSize ? 'level1' : 'level0';

@@ -1,3 +0,3 @@

/// <reference types="node" />
import { Readable } from 'stream';
export declare function readLines(lines: string[]): Promise<string[]>;
export declare function readInput(files: string[]): Promise<string[]>;

@@ -4,0 +4,0 @@ export declare function readFromFiles(files: string[]): string[];

@@ -5,2 +5,11 @@ import { createReadStream, readFileSync } from 'fs';

// Read Input: files (or file) and stdin. For reading general files (svg, strings, ...).
export async function readLines(lines) {
if (process.stdin.isTTY) {
return lines;
}
else {
const stdin = await readFromStdin();
return stdin.trim().split('\n');
}
}
export async function readInput(files) {

@@ -7,0 +16,0 @@ if (process.stdin.isTTY) {

import type { Command } from 'commander';
export declare function addAnnotationOptions(command: Command): Command;
export declare function addTransformOptions(command: Command): Command;
export declare function addParseIiifOptions(command: Command): Command;

@@ -24,1 +24,8 @@ const DEFAULT_MAX_OFFSET_RATIO = 0;

}
export function addParseIiifOptions(command) {
return command
.option('-c, --fetch-collections', 'Recursively fetches and parses embedded IIIF Collections', false)
.option('-m, --fetch-manifests', 'Recursively fetches and parses embedded IIIF Manifests', false)
.option('-i, --fetch-images', 'Recursively fetches and parses embedded IIIF Images', false)
.option('-a, --fetch-all', 'Recursively fetches and parses embedded IIIF Collections, Manifests and Images', false);
}
{
"name": "@allmaps/cli",
"version": "1.0.0-beta.39",
"version": "1.0.0-beta.40",
"author": {

@@ -54,7 +54,7 @@ "name": "Bert Spaan",

"dependencies": {
"@allmaps/annotation": "^1.0.0-beta.27",
"@allmaps/id": "^1.0.0-beta.27",
"@allmaps/iiif-parser": "^1.0.0-beta.37",
"@allmaps/stdlib": "^1.0.0-beta.28",
"@allmaps/transform": "^1.0.0-beta.38",
"@allmaps/annotation": "^1.0.0-beta.28",
"@allmaps/id": "^1.0.0-beta.28",
"@allmaps/iiif-parser": "^1.0.0-beta.38",
"@allmaps/stdlib": "^1.0.0-beta.29",
"@allmaps/transform": "^1.0.0-beta.39",
"commander": "^10.0.0",

@@ -79,3 +79,3 @@ "stream-json": "^1.7.4",

},
"gitHead": "2cd1595a894c77557a492e61371508d615d9f6b8"
"gitHead": "ee99d1696cd81fb650cccada4352418ba3e9f2aa"
}

@@ -9,3 +9,3 @@ # @allmaps/cli

```sh
```bash
npm install -g @allmaps/cli

@@ -16,5 +16,5 @@ ```

Run Allmaps CLI in your terminal using:
Run Allmaps CLI in your terminal:
```sh
```bash
allmaps

@@ -25,7 +25,7 @@ ```

```sh
```bash
allmaps --help
```
```sh
```bash
allmaps <command> --help

@@ -51,3 +51,3 @@ ```

```sh
```bash
allmaps annotation --help

@@ -58,3 +58,3 @@ ```

```sh
```bash
allmaps annotation generate [files...]

@@ -65,3 +65,3 @@ ```

```sh
```bash
allmaps annotation parse [files...]

@@ -72,6 +72,12 @@ ```

```sh
```bash
allmaps annotation svg [files...]
```
Output the IDs of the IIIF Images in the input files:
```bash
allmaps annotation image-ids [files...]
```
For all the commands above, the input files can be either Georeference Annotations or parsed Georeference Annotations

@@ -83,3 +89,3 @@

```sh
```bash
allmaps transform --help

@@ -104,3 +110,3 @@ ```

```sh
```bash
allmaps transform svg -a <filename> [files...]

@@ -118,3 +124,3 @@ ```

```sh
```bash
allmaps transform coordinates -a /path/to/annotation.json /path/to/coordinates.txt

@@ -132,3 +138,3 @@ ```

```sh
```bash
cat /path/to/coordinates.txt | allmaps transform coordinates -a /path/to/annotation.json \

@@ -152,3 +158,3 @@ > /path/to/transformed-coordinates.txt

```sh
```bash
allmaps transform coordinates -g /path/to/gcps.txt -t thinPlateSpline /path/to/coordinates.txt

@@ -163,11 +169,11 @@ ```

```sh
```bash
allmaps transform svg -a <filename> [files...]
```
```sh
```bash
allmaps transform svg -a /path/to/annotation.json /path/to/svg.svg
```
```sh
```bash
allmaps transform svg -g /path/to/gcps.txt -t thinPlateSpline /path/to/svg.svg

@@ -182,11 +188,11 @@ ```

```sh
```bash
allmaps transform geojson -a <filename> [files...]
```
```sh
```bash
allmaps transform geojson -a /path/to/annotation.json path/to/myGeoJSON.geosjon
```
```sh
```bash
allmaps transform geojson -g path/to/gcps.txt -t thinPlateSpline /path/to/myGeoJSON.geosjon

@@ -203,7 +209,7 @@ ```

```sh
```bash
allmaps transform resource-mask [files...]
```
```sh
```bash
allmaps transform resource-mask path/to/myAnnotation.json path/to/myAnnotation2.json

@@ -234,3 +240,3 @@ ```

```sh
```bash
allmaps iiif --help

@@ -241,3 +247,3 @@ ```

```sh
```bash
allmaps iiif parse [files...]

@@ -248,3 +254,3 @@ ```

```sh
```bash
allmaps manifest -d <id> [files...]

@@ -255,2 +261,8 @@ ```

Output the IDs of the IIIF Images in the input files:
```bash
allmaps iiif image-ids [files...]
```
### Generate Allmaps IDs

@@ -262,3 +274,3 @@

```sh
```bash
allmaps id --help

@@ -269,3 +281,3 @@ ```

```sh
```bash
allmaps id https://digital.zlb.de/viewer/api/v1/records/34231682/manifest/

@@ -276,6 +288,112 @@ ```

```sh
```bash
echo https://digital.zlb.de/viewer/api/v1/records/34231682/manifest/ | allmaps id
```
### Fetch IIIF images
Fetches the full-size image using a given IIIF Image ID:
```bash
allmaps fetch full-image "https://iiif.digitalcommonwealth.org/iiif/2/commonwealth:7h14cx32p"
```
> [!NOTE]
> Not all IIIF image servers allow downloading full-sized images. This command does not yet take the image's `maxWidth`, `maxHeight` and `maxArea` properties into account.
### Generate Bash scripts
#### Dezoomify
Generate a Bash script that uses [dezoomify-rs](https://dezoomify-rs.ophir.dev/) to download full-size IIIF images from their IIIF Image IDs:
```bash
allmaps script dezoomify "https://www.davidrumsey.com/luna/servlet/iiif/RUMSEY~8~1~344467~90112435"
```
You can use dezoomify-rs when the IIIF server does not allow downloading full-size images directly.
#### Create GeoTIFFs using GDAL
Generate a Bash script that uses [GDAL](https://gdal.org/index.html) to convert one or more downloaded full-size IIIF images to [Cloud Optimized GeoTIFFs](https://www.cogeo.org/) using a given Georeference Annotation:
```bash
curl "https://annotations.allmaps.org/images/0b9aef31f14cb5bf" | \
allmaps script geotiff
```
> [!NOTE]
> The generated Bash script expects the full-size images to be available on the local file system. You can download these images manually or use the [`allmaps fetch full-image`](#fetch-iiif-images) command.
You can run the generated scripts by saving them to a file:
```bash
curl "https://annotations.allmaps.org/images/0b9aef31f14cb5bf" | \
allmaps annotation image-ids | \
allmaps script dezoomify > dezoomify.sh
bash dezoomify.sh
```
Or by piping them to Bash:
```bash
curl "https://annotations.allmaps.org/images/0b9aef31f14cb5bf" | \
allmaps annotation image-ids | \
allmaps script dezoomify | \
bash
```
#### Specifying image filenames
By default, the Bash script generated with the `allmaps script geotiff` command computes the Allmaps IDs for all the IIIF Image IDs in the Georeference Annotation and looks for JPGs with the naming convention `<allmaps-id-from-image-id.jpg` in the current directory.
For example, the Georeference Annotation https://annotations.allmaps.org/images/0b9aef31f14cb5bf contains a single georeferenced map from the following IIIF Image:
| IIIF Image ID | Allmaps ID of IIIF Image ID | Expected filename |
| :--------------------------------------------------------------------- | :-------------------------- | :--------------------- |
| `https://iiif-server.lib.uchicago.edu/ark:61001/b2mx3j80nk1f/00000001` | `0b9aef31f14cb5bf` | `0b9aef31f14cb5bf.jpg` |
You can use Allmaps CLI to extract all IIIF Image IDs from a Georeference Annotation:
```bash
curl "https://annotations.allmaps.org/images/0b9aef31f14cb5bf" | \
allmaps annotation image-ids
```
This will output:
```bash
https://iiif-server.lib.uchicago.edu/ark:61001/b2mx3j80nk1f/00000001
```
The `allmaps id` command generated the Allmaps ID from this IIIF Image ID:
```bash
curl "https://annotations.allmaps.org/images/0b9aef31f14cb5bf" | \
allmaps annotation image-ids | \
allmaps id
```
Output:
```bash
0b9aef31f14cb5bf
```
You can override the default behavior by supplying a JSON file that maps IIIF Image IDs to local image filenames:
```bash
curl "https://annotations.allmaps.org/images/0b9aef31f14cb5bf" | \
allmaps script geotiff --image-filenames-file /path/to/image-filenames.json
```
The file `/path/to/image-filenames.json` should contain a JSON object with IIIF Image IDs as keys and local image filenames as values:
```json
{
"https://iiif-server.lib.uchicago.edu/ark:61001/b2mx3j80nk1f/00000001": "/path/to/image1.jpg"
}
```
## Examples

@@ -337,1 +455,15 @@

```
### Use GDAL to generate an XYZ tile layer from a Georeference Annotation
```bash
curl "https://annotations.allmaps.org/maps/096f57b5ff35b3eb" | \
allmaps annotation image-ids | \
allmaps fetch full-image
curl "https://annotations.allmaps.org/maps/096f57b5ff35b3eb" | \
allmaps script geotiff | \
bash
gdal2tiles.py --xyz 096f57b5ff35b3eb.vrt 096f57b5ff35b3eb
```
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc