capsium 0.1.2 → 0.2.0
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +34 -7
- data/CHANGELOG.md +58 -0
- data/Gemfile +6 -0
- data/LICENSE +21 -0
- data/README.adoc +177 -135
- data/Rakefile +8 -1
- data/bin/console +1 -1
- data/capsium.gemspec +11 -19
- data/exe/capsium +1 -1
- data/lib/capsium/cli/convert.rb +18 -0
- data/lib/capsium/cli/package.rb +86 -0
- data/lib/capsium/cli/reactor.rb +25 -0
- data/lib/capsium/cli.rb +3 -96
- data/lib/capsium/converters/jekyll.rb +5 -7
- data/lib/capsium/converters.rb +7 -0
- data/lib/capsium/package/dataset.rb +67 -34
- data/lib/capsium/package/manifest.rb +33 -22
- data/lib/capsium/package/manifest_config.rb +52 -7
- data/lib/capsium/package/metadata.rb +4 -8
- data/lib/capsium/package/metadata_config.rb +97 -9
- data/lib/capsium/package/routes.rb +39 -41
- data/lib/capsium/package/routes_config.rb +120 -44
- data/lib/capsium/package/security.rb +123 -0
- data/lib/capsium/package/security_config.rb +60 -0
- data/lib/capsium/package/storage.rb +20 -45
- data/lib/capsium/package/storage_config.rb +100 -3
- data/lib/capsium/package/validator.rb +149 -0
- data/lib/capsium/package.rb +68 -66
- data/lib/capsium/packager.rb +42 -6
- data/lib/capsium/reactor/introspection.rb +88 -0
- data/lib/capsium/reactor.rb +89 -41
- data/lib/capsium/version.rb +1 -1
- data/lib/capsium.rb +7 -9
- data/sig/capsium/package/dataset.rbs +28 -0
- data/sig/capsium/package/manifest.rbs +34 -0
- data/sig/capsium/package/manifest_config.rbs +38 -0
- data/sig/capsium/package/metadata.rbs +26 -0
- data/sig/capsium/package/metadata_config.rbs +49 -0
- data/sig/capsium/package/routes.rbs +37 -0
- data/sig/capsium/package/routes_config.rbs +74 -0
- data/sig/capsium/package/security.rbs +65 -0
- data/sig/capsium/package/security_config.rbs +57 -0
- data/sig/capsium/package/storage.rbs +28 -0
- data/sig/capsium/package/storage_config.rbs +61 -0
- data/sig/capsium/package/validator.rbs +29 -0
- data/sig/capsium/package.rbs +53 -0
- data/sig/capsium/packager.rbs +23 -0
- data/sig/capsium/reactor/introspection.rbs +31 -0
- data/sig/capsium/reactor.rbs +30 -0
- data/sig/capsium.rbs +3 -1
- metadata +52 -183
- data/lib/capsium/package/dataset_config.rb +0 -28
- data/lib/capsium/protector.rb +0 -103
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9746224c88e5a4a3b2aabe9609af2348235d6efe09dcd37fa71c710f08594829
|
|
4
|
+
data.tar.gz: fcbf1c6857f12bede912bb25d32dc83ddb84cd97757425dcf642af9e785e9478
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fce42689914eda35768a2dfa4dfa74b5c00e8b760ddb50cb6b44b810a20b1423e0a31392eaefff1270408c6ed83d4b56c10a895a54f609ff71afd117b6950194
|
|
7
|
+
data.tar.gz: a45f5ea52966810c8ab183f0ec3407287eb7c87b34f82555242372d08b944edea2c372fdabe836f5e8ef0ff7ee793bed10fcc0a6ca21e486acd2466f7fbb1b93
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
|
@@ -1,12 +1,39 @@
|
|
|
1
|
-
|
|
2
|
-
-
|
|
3
|
-
|
|
4
|
-
# local repo-specific modifications
|
|
5
|
-
# ...
|
|
1
|
+
plugins:
|
|
2
|
+
- rubocop-performance
|
|
6
3
|
|
|
7
4
|
AllCops:
|
|
8
|
-
TargetRubyVersion: 2
|
|
5
|
+
TargetRubyVersion: 3.2
|
|
9
6
|
NewCops: enable
|
|
7
|
+
SuggestExtensions: false
|
|
10
8
|
Exclude:
|
|
11
|
-
- 'lib/sts/mapper.rb'
|
|
12
9
|
- 'vendor/**/*'
|
|
10
|
+
|
|
11
|
+
Layout/LineLength:
|
|
12
|
+
Max: 100
|
|
13
|
+
|
|
14
|
+
# Project convention: double-quoted string literals.
|
|
15
|
+
Style/StringLiterals:
|
|
16
|
+
EnforcedStyle: double_quotes
|
|
17
|
+
|
|
18
|
+
# Classes are intentionally undocumented for now; API docs land with a
|
|
19
|
+
# later phase together with the RBS signatures.
|
|
20
|
+
Style/Documentation:
|
|
21
|
+
Enabled: false
|
|
22
|
+
|
|
23
|
+
# RSpec example groups and the gemspec are block-heavy by nature.
|
|
24
|
+
Metrics/BlockLength:
|
|
25
|
+
Exclude:
|
|
26
|
+
- 'spec/**/*'
|
|
27
|
+
- 'capsium.gemspec'
|
|
28
|
+
|
|
29
|
+
Metrics/ClassLength:
|
|
30
|
+
Max: 120
|
|
31
|
+
|
|
32
|
+
Metrics/MethodLength:
|
|
33
|
+
Max: 25
|
|
34
|
+
|
|
35
|
+
Metrics/AbcSize:
|
|
36
|
+
Max: 30
|
|
37
|
+
|
|
38
|
+
Metrics/CyclomaticComplexity:
|
|
39
|
+
Max: 8
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- Migrated all package configuration models from shale to lutaml-model.
|
|
8
|
+
- All configuration files now follow the canonical schemas
|
|
9
|
+
(ARCHITECTURE.md sections 2-6):
|
|
10
|
+
- `metadata.json`: `dependencies` is an object of `guid -> semver range`;
|
|
11
|
+
`name`/`version`/`description`/`guid`/`uuid` are the required fields.
|
|
12
|
+
- `manifest.json`: a `resources` object keyed by package-relative path
|
|
13
|
+
(`type`, `visibility`, optional `version`).
|
|
14
|
+
- `routes.json`: optional top-level `index` plus a `routes` array with
|
|
15
|
+
discriminated kinds (`resource` / `dataset` / handler).
|
|
16
|
+
- `storage.json`: `storage.dataSets` object; dataset `source` and
|
|
17
|
+
`schemaFile` are package-relative paths.
|
|
18
|
+
- Legacy (pre-0.2) configuration files are accepted on read and normalized
|
|
19
|
+
to the canonical forms; writers emit only the canonical forms.
|
|
20
|
+
- Manifest and routes auto-generation is deterministic (sorted); HTML files
|
|
21
|
+
get dual routes, the index HTML gets `/`, datasets get
|
|
22
|
+
`/api/v1/data/<id>`.
|
|
23
|
+
- The reactor serves dataset routes as JSON, sets `Cache-Control: public,
|
|
24
|
+
max-age=31536000` on static resources (configurable), responds 501 to
|
|
25
|
+
handler routes, and rejects packages that fail integrity verification.
|
|
26
|
+
- The CLI exits nonzero on errors.
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
|
|
30
|
+
- `security.json` with SHA-256 checksums over every package file, generated
|
|
31
|
+
at pack time; verified automatically on load (`Package#verify_integrity`,
|
|
32
|
+
`Capsium::Package::Security::IntegrityError` on mismatch).
|
|
33
|
+
- `capsium package validate <path|cap>`: per-check validation report
|
|
34
|
+
(metadata formats, on-disk existence of manifest resources, route targets
|
|
35
|
+
and dataset sources, dataset JSON-schema validation, checksums, external
|
|
36
|
+
http(s) references in content), exit status 1 on any failure.
|
|
37
|
+
- `capsium package unpack <cap> [-o dir]`.
|
|
38
|
+
- `Capsium::Package::Validator` and `Capsium::Package::Security`.
|
|
39
|
+
- Reactor introspection HTTP API (ARCHITECTURE.md section 7):
|
|
40
|
+
`GET /api/v1/introspect/metadata`, `/routes`, `/content-hashes` and
|
|
41
|
+
`/content-validity`, served as JSON by `Capsium::Reactor::Introspection`.
|
|
42
|
+
`content-hashes` is the SHA-256 of the `.cap` blob, or of the canonical
|
|
43
|
+
JSON serialization of the content checksums for directory sources;
|
|
44
|
+
`content-validity` re-verifies integrity live.
|
|
45
|
+
- Zip-slip protection on `.cap` extraction: entries escaping the
|
|
46
|
+
destination (absolute paths, drive letters, `..` segments) raise
|
|
47
|
+
`Capsium::Packager::UnsafeEntryError`.
|
|
48
|
+
- RBS signatures for the public API (`sig/`), kept green by the
|
|
49
|
+
`rbs:validate` rake task (part of the default rake task).
|
|
50
|
+
- `Capsium::Package#cap_file_path`.
|
|
51
|
+
|
|
52
|
+
### Removed
|
|
53
|
+
|
|
54
|
+
- `Capsium::Protector` (bit-rotted, insecure; encryption/signing is
|
|
55
|
+
deferred to a later phase).
|
|
56
|
+
- shale dependency (replaced by lutaml-model); base64 dependency.
|
|
57
|
+
- Unused constants `Package::PACKAGING_FILE`, `Package::SIGNATURE_FILE`,
|
|
58
|
+
`Package::ENCRYPTED_PACKAGING_FILE`, `Routes::DEFAULT_INDEX_TARGET`.
|
data/Gemfile
CHANGED
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Ribose Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.adoc
CHANGED
|
@@ -9,27 +9,14 @@ content packages with ease.
|
|
|
9
9
|
This gem provides a structured way to handle content, data, and metadata for
|
|
10
10
|
various applications.
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
== Testing out how it works
|
|
14
|
-
|
|
15
|
-
Download the mn-samples-iso built site: https://github.com/metanorma/mn-samples-iso/actions/runs/8862815829/artifacts/1453746303[mn-samples-iso-Linux].
|
|
16
|
-
|
|
17
|
-
Then run these commands:
|
|
12
|
+
== Test it out!
|
|
18
13
|
|
|
19
14
|
[source,bash]
|
|
20
15
|
----
|
|
21
|
-
$
|
|
22
|
-
$
|
|
23
|
-
$
|
|
24
|
-
|
|
25
|
-
$ echo '{"name": "mn-samples-iso","version":"0.1.0"}' > metadata.json
|
|
26
|
-
$ cd ..
|
|
27
|
-
$ bundle exec capsium package pack -f mn-samples-iso-Linux
|
|
28
|
-
Package created: mn-samples-iso-0.1.0.cap
|
|
29
|
-
$ bundle exec capsium reactor serve mn-samples-iso-0.1.0.cap
|
|
30
|
-
Starting server on http://localhost:8864
|
|
31
|
-
[2024-06-05 14:56:41] INFO WEBrick::HTTPServer#start: pid=8234 port=8864
|
|
32
|
-
...
|
|
16
|
+
$ wget https://github.com/capsiums/cap-story/releases/download/v0.9.0/story_of_claire-0.9.0.cap
|
|
17
|
+
$ capsium reactor serve story_of_claire-0.9.0.cap
|
|
18
|
+
$ open http://localhost:8864
|
|
19
|
+
# => Read the story!
|
|
33
20
|
----
|
|
34
21
|
|
|
35
22
|
== Installation
|
|
@@ -57,184 +44,231 @@ gem install capsium
|
|
|
57
44
|
|
|
58
45
|
== What is a Capsium package?
|
|
59
46
|
|
|
60
|
-
A Capsium package is a structured collection of content, data, metadata, and
|
|
47
|
+
A Capsium package is a structured collection of content, data, metadata, and
|
|
48
|
+
routing information, distributed as a single `.cap` file (a ZIP archive, MIME
|
|
49
|
+
`application/vnd.capsium.package`). The canonical layout:
|
|
61
50
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
51
|
+
[source]
|
|
52
|
+
----
|
|
53
|
+
metadata.json # REQUIRED, hand-authored
|
|
54
|
+
manifest.json # auto-generated at load/pack time when absent
|
|
55
|
+
routes.json # auto-generated when absent
|
|
56
|
+
storage.json # optional (only when datasets exist)
|
|
57
|
+
security.json # generated at pack time (SHA-256 checksums)
|
|
58
|
+
content/ # served content root (URL space mirrors paths below it)
|
|
59
|
+
data/ # datasets (optional)
|
|
60
|
+
----
|
|
61
|
+
|
|
62
|
+
Paths inside the configuration files are package-relative POSIX paths.
|
|
63
|
+
|
|
64
|
+
* **metadata.json**: name (kebab-case), version (semver), description, guid
|
|
65
|
+
(URI) and uuid are required; author, license, repository, dependencies
|
|
66
|
+
(an object of `guid -> semver range`) are optional.
|
|
67
|
+
* **manifest.json**: an object keyed by package-relative resource path, e.g.
|
|
68
|
+
`"content/index.html": { "type": "text/html", "visibility": "exported" }`.
|
|
69
|
+
Generated by scanning `content/` (MIME types via marcel) when absent.
|
|
70
|
+
* **routes.json**: an optional top-level `index` plus a `routes` array. Route
|
|
71
|
+
kinds: `{path, resource}` for static files, `{path, dataset}` for datasets
|
|
72
|
+
(served under `/api/v1/data/<id>`). HTML files get two routes (basename and
|
|
73
|
+
full filename); the index HTML additionally gets `/`.
|
|
74
|
+
* **storage.json**: dataset definitions under `storage.dataSets`, either
|
|
75
|
+
schema-backed files (`source`, `schemaFile`, `schemaType: json-schema`)
|
|
76
|
+
or SQLite (`databaseFile`, `table`).
|
|
77
|
+
* **security.json**: `security.integrityChecks.checksums` holds a SHA-256 hex
|
|
78
|
+
digest for every file in the package except `security.json` itself.
|
|
79
|
+
|
|
80
|
+
Legacy (pre-0.2) configuration files are still accepted on read and
|
|
81
|
+
normalized to the canonical forms; writers emit only the canonical forms.
|
|
67
82
|
|
|
68
83
|
== What is a Capsium reactor?
|
|
69
84
|
|
|
70
|
-
A Capsium reactor is a runtime environment that serves Capsium packages. It
|
|
85
|
+
A Capsium reactor is a runtime environment that serves Capsium packages. It
|
|
86
|
+
reads the package configuration and starts a server that can handle HTTP
|
|
87
|
+
requests according to the routes defined in the package. The reactor verifies
|
|
88
|
+
the package against `security.json` when present and rejects tampered
|
|
89
|
+
packages. Dataset routes are served as JSON; static resources are served with
|
|
90
|
+
`Cache-Control: public, max-age=31536000` (configurable). While serving, the
|
|
91
|
+
reactor also answers the introspection endpoints described below.
|
|
71
92
|
|
|
72
93
|
== CLI: Package
|
|
73
94
|
|
|
74
|
-
|
|
95
|
+
Capsium provides a CLI to help you pack and manage your packages.
|
|
75
96
|
|
|
76
|
-
|
|
97
|
+
=== Packing a package
|
|
77
98
|
|
|
78
99
|
[source,bash]
|
|
79
100
|
----
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
capsium package new my_package
|
|
83
|
-
# Shorthand
|
|
84
|
-
capsium package my_package
|
|
85
|
-
|
|
86
|
-
# TODO: Add content to the package
|
|
87
|
-
capsium package add content example.html example.css example.js
|
|
101
|
+
capsium package pack [--force/-f] path-to-package
|
|
102
|
+
----
|
|
88
103
|
|
|
89
|
-
|
|
90
|
-
|
|
104
|
+
This command generates `manifest.json`/`routes.json` when absent, writes
|
|
105
|
+
`security.json` with SHA-256 checksums of every package file, and packs the
|
|
106
|
+
directory into `{package-name}-{package-version}.cap` (name and version from
|
|
107
|
+
`metadata.json`).
|
|
91
108
|
|
|
92
|
-
|
|
93
|
-
|
|
109
|
+
.Sample `pack` command
|
|
110
|
+
====
|
|
111
|
+
[source,bash]
|
|
112
|
+
----
|
|
113
|
+
capsium package pack -f spec/fixtures/bare-package
|
|
114
|
+
----
|
|
115
|
+
====
|
|
94
116
|
|
|
95
|
-
|
|
96
|
-
capsium package add route /=example.html /index=index.html /api/v1/data/animals={type:dataset,name:animals}
|
|
117
|
+
=== Unpacking a package
|
|
97
118
|
|
|
98
|
-
|
|
99
|
-
|
|
119
|
+
[source,bash]
|
|
120
|
+
----
|
|
121
|
+
capsium package unpack bare-package-0.1.0.cap [-o/--output my_bare_package]
|
|
100
122
|
----
|
|
101
123
|
|
|
102
|
-
|
|
124
|
+
When `-o` is omitted, the package is unpacked into a directory named after
|
|
125
|
+
the `.cap` file.
|
|
103
126
|
|
|
104
|
-
|
|
127
|
+
Extraction is zip-slip safe: entries whose names would escape the
|
|
128
|
+
destination (absolute paths, drive letters, `..` segments) are rejected
|
|
129
|
+
with `Capsium::Packager::UnsafeEntryError`.
|
|
130
|
+
|
|
131
|
+
=== Validating a package
|
|
105
132
|
|
|
106
133
|
[source,bash]
|
|
107
134
|
----
|
|
108
|
-
capsium package
|
|
135
|
+
capsium package validate path-to-package-or-cap
|
|
109
136
|
----
|
|
110
137
|
|
|
111
|
-
|
|
112
|
-
filename:
|
|
138
|
+
Runs a per-check report and exits with status 1 on any failure:
|
|
113
139
|
|
|
114
|
-
*
|
|
115
|
-
|
|
140
|
+
* metadata: required fields present and well-formed (kebab-case name, semver
|
|
141
|
+
version, URI guid, UUID)
|
|
142
|
+
* manifest: every resource exists on disk
|
|
143
|
+
* routes: route targets exist; dataset routes live under `/api/v1/data/`;
|
|
144
|
+
the index resolves to an existing HTML file
|
|
145
|
+
* storage: dataset sources (and schemas) exist; dataset data passes
|
|
146
|
+
JSON-schema validation
|
|
147
|
+
* security: checksums match when `security.json` is present
|
|
148
|
+
* content: no external `http(s)` references in `content/` files
|
|
149
|
+
|
|
150
|
+
=== Inspecting a package
|
|
116
151
|
|
|
117
|
-
.Sample `pack` command
|
|
118
|
-
====
|
|
119
152
|
[source,bash]
|
|
120
153
|
----
|
|
121
|
-
capsium package
|
|
154
|
+
capsium package info|manifest|routes|metadata|storage path-to-package
|
|
122
155
|
----
|
|
123
|
-
====
|
|
124
|
-
|
|
125
|
-
|
|
126
156
|
|
|
127
157
|
== CLI: Reactor
|
|
128
158
|
|
|
129
159
|
=== Starting a reactor on your package
|
|
130
160
|
|
|
131
|
-
To start a Capsium reactor on your package, use the following command:
|
|
132
|
-
|
|
133
161
|
[source,bash]
|
|
134
162
|
----
|
|
135
|
-
capsium reactor serve my_package.cap
|
|
163
|
+
capsium reactor serve my_package.cap [--port 8864]
|
|
136
164
|
----
|
|
137
165
|
|
|
166
|
+
The reactor takes a local package directory or `.cap` file; serving
|
|
167
|
+
directly from a URL is not supported.
|
|
168
|
+
|
|
169
|
+
=== Reactor introspection API
|
|
170
|
+
|
|
171
|
+
While serving, the reactor answers the Monitoring HTTP API
|
|
172
|
+
(ARCHITECTURE.md section 7) as `application/json`:
|
|
173
|
+
|
|
174
|
+
[source]
|
|
175
|
+
----
|
|
176
|
+
GET /api/v1/introspect/metadata # => {"packages": [{"name", "version", "author", "description"}]}
|
|
177
|
+
GET /api/v1/introspect/routes # => {"routes": [{"package", "routes": [{"method", "path"}]}]}
|
|
178
|
+
GET /api/v1/introspect/content-hashes # => {"contentHashes": [{"package", "hash"}]}
|
|
179
|
+
GET /api/v1/introspect/content-validity # => {"contentValidity": [{"package", "valid", "lastChecked", "reason"?}]}
|
|
180
|
+
----
|
|
181
|
+
|
|
182
|
+
Non-GET methods on these paths are answered `405 Method Not Allowed`.
|
|
183
|
+
|
|
184
|
+
`content-hashes` is the SHA-256 of the `.cap` blob when the package was
|
|
185
|
+
served from one. For a directory source there is no blob, so the hash
|
|
186
|
+
covers the canonical (sorted-key) JSON serialization of the package
|
|
187
|
+
content checksums — the same data `security.json` integrityChecks carry.
|
|
188
|
+
|
|
189
|
+
`content-validity` re-verifies the package against `security.json` on
|
|
190
|
+
every request and reports the outcome with a UTC `lastChecked`
|
|
191
|
+
timestamp; `reason` lists the integrity errors when `valid` is false.
|
|
138
192
|
|
|
139
193
|
== Programmatically managing packages
|
|
140
194
|
|
|
141
|
-
|
|
195
|
+
The public API below ships with RBS signatures in `sig/`
|
|
196
|
+
(`bundle exec rbs -I sig validate`).
|
|
142
197
|
|
|
143
|
-
===
|
|
198
|
+
=== Loading packages
|
|
144
199
|
|
|
145
200
|
[source,ruby]
|
|
146
201
|
----
|
|
147
202
|
require 'capsium'
|
|
148
203
|
|
|
149
|
-
package
|
|
150
|
-
|
|
151
|
-
version: '0.1.0',
|
|
152
|
-
content: {
|
|
153
|
-
'example.html' => 'text/html',
|
|
154
|
-
'example.css' => 'text/css',
|
|
155
|
-
'example.js' => 'application/javascript'
|
|
156
|
-
},
|
|
157
|
-
data: {
|
|
158
|
-
'animals.yaml' => {
|
|
159
|
-
'animals' => [
|
|
160
|
-
{ 'name' => 'Lion', 'type' => 'Mammal', 'habitat' => 'Savannah' },
|
|
161
|
-
{ 'name' => 'Eagle', 'type' => 'Bird', 'habitat' => 'Mountains' },
|
|
162
|
-
{ 'name' => 'Shark', 'type' => 'Fish', 'habitat' => 'Ocean' }
|
|
163
|
-
]
|
|
164
|
-
}
|
|
165
|
-
},
|
|
166
|
-
metadata: {
|
|
167
|
-
'name' => 'sample_package',
|
|
168
|
-
'version' => '0.1.0',
|
|
169
|
-
'dependencies' => []
|
|
170
|
-
},
|
|
171
|
-
routes: {
|
|
172
|
-
'/' => 'example.html',
|
|
173
|
-
'/index' => 'index.html',
|
|
174
|
-
'/index.html' => 'index.html',
|
|
175
|
-
'/example.css' => 'example.css',
|
|
176
|
-
'/example.js' => 'example.js',
|
|
177
|
-
'/api/v1/data/animals' => { 'type' => 'dataset', 'name' => 'animals' }
|
|
178
|
-
},
|
|
179
|
-
storage: {
|
|
180
|
-
'datasets' => [
|
|
181
|
-
{
|
|
182
|
-
'name' => 'animals',
|
|
183
|
-
'source' => 'data/animals.yaml',
|
|
184
|
-
'format' => 'yaml',
|
|
185
|
-
'schema' => 'data/animals_schema.yaml'
|
|
186
|
-
}
|
|
187
|
-
]
|
|
188
|
-
}
|
|
189
|
-
)
|
|
190
|
-
|
|
191
|
-
# Save the package to a file
|
|
192
|
-
File.write('my_package.json', package.to_json(pretty: true))
|
|
204
|
+
# Read a package directory or a .cap file
|
|
205
|
+
package = Capsium::Package.new(path)
|
|
193
206
|
----
|
|
194
207
|
|
|
195
|
-
|
|
208
|
+
When `security.json` is present, the package is verified on load and
|
|
209
|
+
`Capsium::Package::Security::IntegrityError` is raised on mismatch.
|
|
196
210
|
|
|
197
|
-
|
|
211
|
+
=== Using packages in your program
|
|
198
212
|
|
|
199
213
|
[source,ruby]
|
|
200
214
|
----
|
|
201
|
-
|
|
215
|
+
# Accessing package metadata
|
|
216
|
+
puts "Package Name: #{package.metadata.name}"
|
|
217
|
+
puts "Package Version: #{package.metadata.version}"
|
|
202
218
|
|
|
203
|
-
#
|
|
204
|
-
package
|
|
219
|
+
# Accessing manifest resources
|
|
220
|
+
package.manifest.resources.each do |path, resource|
|
|
221
|
+
puts "Resource: #{path}, Type: #{resource.type}"
|
|
222
|
+
end
|
|
205
223
|
|
|
206
|
-
#
|
|
207
|
-
|
|
208
|
-
|
|
224
|
+
# Accessing routes
|
|
225
|
+
route = package.routes.resolve('/')
|
|
226
|
+
puts route.resource
|
|
209
227
|
|
|
210
|
-
|
|
228
|
+
# Accessing datasets
|
|
229
|
+
animals = package.storage.dataset('animals')
|
|
230
|
+
puts animals.data.inspect
|
|
231
|
+
|
|
232
|
+
# Verifying integrity (returns a list of typed errors, empty when valid)
|
|
233
|
+
errors = package.verify_integrity
|
|
234
|
+
----
|
|
211
235
|
|
|
212
|
-
|
|
236
|
+
=== Packing and unpacking programmatically
|
|
213
237
|
|
|
214
238
|
[source,ruby]
|
|
215
239
|
----
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
240
|
+
packager = Capsium::Packager.new
|
|
241
|
+
cap_file = packager.pack(package, force: true)
|
|
242
|
+
packager.unpack(cap_file, 'output-directory')
|
|
243
|
+
----
|
|
219
244
|
|
|
220
|
-
|
|
221
|
-
package.content.each do |filename, content_type|
|
|
222
|
-
puts "Content File: #{filename}, Content Type: #{content_type}"
|
|
223
|
-
end
|
|
245
|
+
== Building the mn-samples-iso cap package
|
|
224
246
|
|
|
225
|
-
|
|
226
|
-
animals_data = package.data['animals.yaml']
|
|
227
|
-
puts "Animals Data: #{animals_data.inspect}"
|
|
247
|
+
Download the mn-samples-iso built site: https://github.com/metanorma/mn-samples-iso/actions/runs/8862815829/artifacts/1453746303[mn-samples-iso-Linux].
|
|
228
248
|
|
|
229
|
-
|
|
230
|
-
package.routes.each do |route, destination|
|
|
231
|
-
puts "Route: #{route}, Destination: #{destination}"
|
|
232
|
-
end
|
|
249
|
+
Then run these commands:
|
|
233
250
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
251
|
+
[source,bash]
|
|
252
|
+
----
|
|
253
|
+
$ unzip mn-samples-iso-Linux.zip
|
|
254
|
+
$ cd mn-samples-iso-Linux
|
|
255
|
+
$ mkdir content
|
|
256
|
+
$ mv index.html documents.xml documents content
|
|
257
|
+
$ cat > metadata.json <<'JSON'
|
|
258
|
+
{
|
|
259
|
+
"name": "mn-samples-iso",
|
|
260
|
+
"version": "0.1.0",
|
|
261
|
+
"description": "Metanorma ISO sample documents",
|
|
262
|
+
"guid": "https://github.com/metanorma/mn-samples-iso",
|
|
263
|
+
"uuid": "123e4567-e89b-12d3-a456-426614174000"
|
|
264
|
+
}
|
|
265
|
+
JSON
|
|
266
|
+
$ cd ..
|
|
267
|
+
$ bundle exec capsium package pack -f mn-samples-iso-Linux
|
|
268
|
+
Package created: mn-samples-iso-0.1.0.cap
|
|
269
|
+
$ bundle exec capsium reactor serve mn-samples-iso-0.1.0.cap
|
|
270
|
+
Starting server on http://localhost:8864
|
|
271
|
+
...
|
|
238
272
|
----
|
|
239
273
|
|
|
240
274
|
== Contributing
|
|
@@ -247,7 +281,16 @@ To run the tests, use the following command:
|
|
|
247
281
|
|
|
248
282
|
[source,bash]
|
|
249
283
|
----
|
|
250
|
-
rspec
|
|
284
|
+
bundle exec rspec
|
|
285
|
+
----
|
|
286
|
+
|
|
287
|
+
The linter and the RBS signature validation are part of the default rake
|
|
288
|
+
task (`bundle exec rake`), or run them individually:
|
|
289
|
+
|
|
290
|
+
[source,bash]
|
|
291
|
+
----
|
|
292
|
+
bundle exec rubocop
|
|
293
|
+
bundle exec rbs -I sig validate
|
|
251
294
|
----
|
|
252
295
|
|
|
253
296
|
== License
|
|
@@ -255,4 +298,3 @@ rspec
|
|
|
255
298
|
Copyright Ribose.
|
|
256
299
|
|
|
257
300
|
Capsium is released under the MIT License. See the LICENSE file for more details.
|
|
258
|
-
|
data/Rakefile
CHANGED
|
@@ -9,4 +9,11 @@ require "rubocop/rake_task"
|
|
|
9
9
|
|
|
10
10
|
RuboCop::RakeTask.new
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
namespace :rbs do
|
|
13
|
+
desc "Validate the RBS signatures (sig/)"
|
|
14
|
+
task :validate do
|
|
15
|
+
sh "bundle exec rbs -I sig validate"
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
task default: %i[spec rubocop rbs:validate]
|
data/bin/console
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "bundler/setup"
|
|
5
|
-
require "capsium"
|
|
5
|
+
require File.expand_path("../lib/capsium", __dir__)
|
|
6
6
|
|
|
7
7
|
# You can add fixtures and/or initialization code here to make experimenting
|
|
8
8
|
# with your gem easier. You can also use a different console, if you like.
|
data/capsium.gemspec
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
require File.expand_path("lib/capsium/version", __dir__)
|
|
4
4
|
|
|
5
5
|
Gem::Specification.new do |spec|
|
|
6
6
|
spec.name = "capsium"
|
|
@@ -8,14 +8,19 @@ Gem::Specification.new do |spec|
|
|
|
8
8
|
spec.authors = ["Ribose Inc."]
|
|
9
9
|
spec.email = ["open.source@ribose.com"]
|
|
10
10
|
|
|
11
|
-
spec.summary = "Capsium"
|
|
12
|
-
spec.description = "Capsium"
|
|
11
|
+
spec.summary = "Packager and reactor for Capsium packages (.cap)"
|
|
12
|
+
spec.description = "Capsium facilitates the creation, management and " \
|
|
13
|
+
"deployment of content packages with ease. This gem " \
|
|
14
|
+
"provides a structured way to handle content, data, " \
|
|
15
|
+
"and metadata for various applications: it packages " \
|
|
16
|
+
"them into .cap files and serves them over HTTP."
|
|
13
17
|
spec.homepage = "https://github.com/capsiums/capsium"
|
|
14
18
|
spec.license = "MIT"
|
|
15
19
|
|
|
16
20
|
spec.metadata["homepage_uri"] = spec.homepage
|
|
17
21
|
spec.metadata["source_code_uri"] = spec.homepage
|
|
18
22
|
spec.metadata["changelog_uri"] = "https://github.com/capsiums/capsium/releases"
|
|
23
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
|
19
24
|
|
|
20
25
|
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
21
26
|
`git ls-files -z`
|
|
@@ -26,30 +31,17 @@ Gem::Specification.new do |spec|
|
|
|
26
31
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
27
32
|
spec.require_paths = ["lib"]
|
|
28
33
|
|
|
29
|
-
spec.required_ruby_version = ">= 2.
|
|
34
|
+
spec.required_ruby_version = ">= 3.2.0"
|
|
30
35
|
|
|
31
|
-
spec.add_dependency "cssminify"
|
|
32
36
|
spec.add_dependency "csv"
|
|
33
|
-
spec.add_dependency "htmlcompressor"
|
|
34
|
-
spec.add_dependency "html-proofer"
|
|
35
|
-
spec.add_dependency "jekyll"
|
|
36
37
|
spec.add_dependency "json"
|
|
37
38
|
spec.add_dependency "json-schema"
|
|
38
39
|
spec.add_dependency "listen"
|
|
40
|
+
spec.add_dependency "lutaml-model", ">= 0.8", "< 1.0"
|
|
39
41
|
spec.add_dependency "marcel"
|
|
40
|
-
spec.add_dependency "rubyzip", "
|
|
41
|
-
spec.add_dependency "scss_lint"
|
|
42
|
-
spec.add_dependency "shale"
|
|
42
|
+
spec.add_dependency "rubyzip", ">= 2.3.2", "< 4.0"
|
|
43
43
|
spec.add_dependency "sqlite3"
|
|
44
44
|
spec.add_dependency "thor"
|
|
45
|
-
spec.add_dependency "uglifier"
|
|
46
45
|
spec.add_dependency "webrick"
|
|
47
46
|
spec.add_dependency "yaml"
|
|
48
|
-
|
|
49
|
-
spec.add_development_dependency "pry"
|
|
50
|
-
spec.add_development_dependency "rack-test"
|
|
51
|
-
spec.add_development_dependency "rake", "~> 13.0"
|
|
52
|
-
spec.add_development_dependency "rspec", "~> 3.11"
|
|
53
|
-
spec.add_development_dependency "rubocop", "~> 1.58"
|
|
54
|
-
spec.add_development_dependency "rubocop-performance"
|
|
55
47
|
end
|