@devflow-core/dsh-devflow 0.1.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.
- package/NOTICE +13 -0
- package/README.md +82 -0
- package/assets/commands/devflow-adversarial.toml +11 -0
- package/assets/commands/devflow-audit.toml +32 -0
- package/assets/commands/devflow-debt.toml +42 -0
- package/assets/commands/devflow-find-fault.toml +11 -0
- package/assets/commands/devflow-learn.toml +21 -0
- package/assets/commands/devflow-plan.toml +58 -0
- package/assets/commands/devflow-prove.toml +20 -0
- package/assets/commands/devflow-pua.toml +40 -0
- package/assets/commands/devflow-review.toml +36 -0
- package/assets/commands/devflow-spec.toml +49 -0
- package/assets/commands/devflow.toml +35 -0
- package/assets/presets/devflow-2/NOTICE +4 -0
- package/assets/presets/devflow-2/README.md +71 -0
- package/assets/presets/devflow-2/agent.cordis.yml +337 -0
- package/assets/presets/devflow-2/custom-bash.mjs +213 -0
- package/assets/presets/devflow-2/preset.yml +3 -0
- package/assets/presets/devflow-2/tool-bootstrap.mjs +496 -0
- package/assets/scripts/devflow-audit.js +275 -0
- package/assets/scripts/devflow-debt.js +196 -0
- package/assets/scripts/devflow-doctor.js +90 -0
- package/assets/scripts/devflow-plan.js +638 -0
- package/assets/scripts/devflow-review.js +93 -0
- package/assets/scripts/devflow-spec.js +238 -0
- package/assets/skills/devflow-adversarial/SKILL.md +71 -0
- package/assets/skills/devflow-audit/SKILL.md +78 -0
- package/assets/skills/devflow-brainstorm/SKILL.md +176 -0
- package/assets/skills/devflow-brainstorm/references/interview-discipline.md +184 -0
- package/assets/skills/devflow-build/SKILL.md +238 -0
- package/assets/skills/devflow-build/references/build-methods.md +40 -0
- package/assets/skills/devflow-core/SKILL.md +93 -0
- package/assets/skills/devflow-core/references/core-methods.md +131 -0
- package/assets/skills/devflow-core/references/reference-projects.md +133 -0
- package/assets/skills/devflow-core/references/skill-guide.md +63 -0
- package/assets/skills/devflow-cut/SKILL.md +208 -0
- package/assets/skills/devflow-cut/references/cut-methods.md +65 -0
- package/assets/skills/devflow-cut/references/native-capability-checklist.md +112 -0
- package/assets/skills/devflow-docs-followup/SKILL.md +132 -0
- package/assets/skills/devflow-docs-followup/agents/openai.yaml +4 -0
- package/assets/skills/devflow-find-fault/SKILL.md +109 -0
- package/assets/skills/devflow-learn/SKILL.md +176 -0
- package/assets/skills/devflow-plan/SKILL.md +142 -0
- package/assets/skills/devflow-plan/references/plan-methods.md +74 -0
- package/assets/skills/devflow-project-knowledge/SKILL.md +354 -0
- package/assets/skills/devflow-prove/SKILL.md +216 -0
- package/assets/skills/devflow-prove/references/code-review-checklist.md +202 -0
- package/assets/skills/devflow-prove/references/flow-self-test.md +775 -0
- package/assets/skills/devflow-prove/references/proof-recovery-methods.md +26 -0
- package/assets/skills/devflow-pua/SKILL.md +197 -0
- package/assets/skills/devflow-pua/references/flavor-display.md +49 -0
- package/assets/skills/devflow-pua/references/methodology-library.md +193 -0
- package/assets/skills/devflow-pua/references/methodology-router.md +78 -0
- package/assets/skills/devflow-spec/SKILL.md +92 -0
- package/assets/skills/devflow-spec/references/spec-plan-methods.md +15 -0
- package/cordis.patch.yml +11 -0
- package/lib/dsh-home.js +33 -0
- package/lib/index.js +79 -0
- package/lib/mount-once.js +34 -0
- package/lib/sync.js +168 -0
- package/package.json +32 -0
package/lib/dsh-home.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// @devflow-core/dsh-devflow — DSH home resolution.
|
|
2
|
+
// Adapted from @linxin666/dsh-liangshen/src/dsh-home.ts (Apache-2.0):
|
|
3
|
+
// the environment override wins, the platform home fallback follows.
|
|
4
|
+
|
|
5
|
+
import { homedir } from 'node:os'
|
|
6
|
+
import { isAbsolute, join } from 'node:path'
|
|
7
|
+
|
|
8
|
+
/** Expand a leading ~ (or ~user) in a path, platform-style. */
|
|
9
|
+
export function expandHome(path, home = homedir()) {
|
|
10
|
+
if (path === '~') return home
|
|
11
|
+
if (path.startsWith('~/') || path.startsWith('~\\')) return join(home, path.slice(2))
|
|
12
|
+
return path
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Resolve the DSH home directory.
|
|
17
|
+
* @param env - process environment to read DSH_HOME from.
|
|
18
|
+
* @param home - platform home directory fallback (test seam).
|
|
19
|
+
* @returns the absolute DSH home path.
|
|
20
|
+
*/
|
|
21
|
+
export function resolveDshHome(env = process.env, home = homedir()) {
|
|
22
|
+
const raw = env.DSH_HOME
|
|
23
|
+
if (raw !== undefined && raw.trim() !== '') {
|
|
24
|
+
const expanded = expandHome(raw.trim(), home)
|
|
25
|
+
return isAbsolute(expanded) ? expanded : join(process.cwd(), expanded)
|
|
26
|
+
}
|
|
27
|
+
return join(home, '.dsh')
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Resolve the DSH home directory from the live environment. */
|
|
31
|
+
export function dshHome() {
|
|
32
|
+
return resolveDshHome()
|
|
33
|
+
}
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// @devflow-core/dsh-devflow — DevFlow asset preset plugin for the dsh web GUI.
|
|
2
|
+
//
|
|
3
|
+
// Host half only: on startup it syncs the bundled DevFlow assets (agent
|
|
4
|
+
// preset devflow-2, skills, commands, verification scripts) into the
|
|
5
|
+
// harness-home runtime roots (~/.dsh/.agent-presets, skills, commands,
|
|
6
|
+
// scripts), making the DevFlow preset selectable for new sessions and the
|
|
7
|
+
// DevFlow skills/commands/checkers available without copying files by hand,
|
|
8
|
+
// and announces the capability through a system-prompt section. No browser
|
|
9
|
+
// half, no routes, no agent tools — the preset itself provides the tools.
|
|
10
|
+
//
|
|
11
|
+
// Adapted from @linxin666/dsh-liangshen (Apache-2.0): two-phase anchored
|
|
12
|
+
// preset distribution + startup sync + system-prompt announcement.
|
|
13
|
+
|
|
14
|
+
import { fileURLToPath } from 'node:url'
|
|
15
|
+
import { dshHome } from './dsh-home.js'
|
|
16
|
+
import { mountOnce } from './mount-once.js'
|
|
17
|
+
import { syncAllAssets } from './sync.js'
|
|
18
|
+
|
|
19
|
+
/** Stable cordis plugin name. */
|
|
20
|
+
export const name = 'devflow'
|
|
21
|
+
|
|
22
|
+
/** Order of the announcement section within the tool-guidance band. */
|
|
23
|
+
const SECTION_ORDER = 150
|
|
24
|
+
|
|
25
|
+
/** Absolute path of the bundled assets tree inside this package. */
|
|
26
|
+
export function bundledAssetsRoot() {
|
|
27
|
+
return fileURLToPath(new URL('../assets/', import.meta.url))
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Model-facing announcement: plugin presence, preset, and conflict policy. */
|
|
31
|
+
export const DEVFLOW_GUIDANCE =
|
|
32
|
+
'本机已安装 @devflow-core/dsh-devflow 插件(DevFlow agent preset 分发):新建会话的预设选择器中可选「DevFlow 2.0 (Anchored)」(两阶段锚定 + Code Mode)。插件启动时把 devflow-2 预设、devflow-* skills、devflow*.toml 命令与 devflow-*.js 验证脚本同步到 ~/.dsh/(.agent-presets/skills/commands/scripts);冲突策略为 devflow-* 权威覆盖(字节相同跳过),非 devflow 资产永不触碰;升级插件后重启即自动更新。用户提到「DevFlow / devflow-2 / 锚定模式」时即指本插件,请据此协作。'
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Mount the plugin: sync bundled DevFlow assets into the harness-home
|
|
36
|
+
* runtime roots, then announce through a system-prompt section.
|
|
37
|
+
* @param ctx - host plugin context (cordis).
|
|
38
|
+
*/
|
|
39
|
+
export const apply = mountOnce('@devflow-core/dsh-devflow', (ctx) => {
|
|
40
|
+
const sync = () => {
|
|
41
|
+
const home = dshHome()
|
|
42
|
+
try {
|
|
43
|
+
const result = syncAllAssets(bundledAssetsRoot(), home)
|
|
44
|
+
for (const { id, error } of result.failed) {
|
|
45
|
+
ctx?.logger?.warn?.(`dsh-devflow: ${id} sync failed: ${error}`)
|
|
46
|
+
}
|
|
47
|
+
if (result.synced.length > 0) {
|
|
48
|
+
ctx?.logger?.info?.(`dsh-devflow: assets synced into ${home}: ${result.synced.join(', ')}`)
|
|
49
|
+
}
|
|
50
|
+
if (result.pruned.length > 0) {
|
|
51
|
+
ctx?.logger?.info?.(`dsh-devflow: pruned stale assets from ${home}: ${result.pruned.join(', ')}`)
|
|
52
|
+
}
|
|
53
|
+
} catch (error) {
|
|
54
|
+
ctx?.logger?.warn?.(`dsh-devflow: asset sync failed: ${error instanceof Error ? error.message : String(error)}`)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
sync()
|
|
59
|
+
|
|
60
|
+
// Optional announcement: register only when the systemPrompt service is
|
|
61
|
+
// available; a missing service must not block the sync (no hard inject).
|
|
62
|
+
let disposeSection
|
|
63
|
+
try {
|
|
64
|
+
const systemPrompt = ctx?.get?.('systemPrompt')
|
|
65
|
+
if (systemPrompt && typeof systemPrompt.section === 'function') {
|
|
66
|
+
disposeSection = systemPrompt.section({
|
|
67
|
+
name: 'plugin:dsh-devflow',
|
|
68
|
+
order: SECTION_ORDER,
|
|
69
|
+
text: DEVFLOW_GUIDANCE,
|
|
70
|
+
})
|
|
71
|
+
}
|
|
72
|
+
} catch {
|
|
73
|
+
disposeSection = undefined
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
ctx?.effect?.(() => () => {
|
|
77
|
+
if (typeof disposeSection === 'function') disposeSection()
|
|
78
|
+
}, 'dsh-devflow: announcement')
|
|
79
|
+
})
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// @devflow-core/dsh-devflow — host single-instance guard.
|
|
2
|
+
// Adapted from @linxin666/dsh-liangshen/src/mount-once.ts (Apache-2.0).
|
|
3
|
+
// The registry rides a global symbol so two module instances of the same
|
|
4
|
+
// package (npm copy vs repository link) still share one verdict. This plugin
|
|
5
|
+
// uses its own symbol namespace (`dsh-devflow.mounted`) so it never collides
|
|
6
|
+
// with the dsh-web-ui family registry.
|
|
7
|
+
|
|
8
|
+
const MOUNTED = Symbol.for('dsh-devflow.mounted')
|
|
9
|
+
|
|
10
|
+
function mountedSet() {
|
|
11
|
+
const registry = globalThis
|
|
12
|
+
return (registry[MOUNTED] ??= new Set())
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Wrap a cordis plugin apply so the package runs at most once per process.
|
|
17
|
+
* The first mount registers normally and unmarks when its fiber disposes;
|
|
18
|
+
* any later mount of the same package name is a no-op.
|
|
19
|
+
* @param packageName - npm package identity shared by every install source.
|
|
20
|
+
* @param fn - the original plugin apply.
|
|
21
|
+
* @returns an apply of the same shape.
|
|
22
|
+
*/
|
|
23
|
+
export function mountOnce(packageName, fn) {
|
|
24
|
+
return (...args) => {
|
|
25
|
+
const mounted = mountedSet()
|
|
26
|
+
if (mounted.has(packageName)) return
|
|
27
|
+
mounted.add(packageName)
|
|
28
|
+
const ctx = args[0]
|
|
29
|
+
ctx?.effect?.(() => () => {
|
|
30
|
+
mounted.delete(packageName)
|
|
31
|
+
})
|
|
32
|
+
return fn(...args)
|
|
33
|
+
}
|
|
34
|
+
}
|
package/lib/sync.js
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
// @devflow-core/dsh-devflow — asset sync engine.
|
|
2
|
+
// Adapted from @linxin666/dsh-liangshen/src/sync.ts (Apache-2.0), narrowed to
|
|
3
|
+
// the four DevFlow asset groups and the "devflow-* authoritative override"
|
|
4
|
+
// conflict policy the user chose: byte-identical files are skipped, differing
|
|
5
|
+
// files are overwritten, and only target files whose name matches the group's
|
|
6
|
+
// own prefix (devflow-*) and no longer exist in the source are pruned. Files
|
|
7
|
+
// outside the group prefix are never touched.
|
|
8
|
+
|
|
9
|
+
import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, utimesSync } from 'node:fs'
|
|
10
|
+
import { dirname, join, relative } from 'node:path'
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Clock/coarse-grain tolerance for the mtime fast path. When a source and a
|
|
14
|
+
* target file share a size and a near-identical mtime we still fall through to
|
|
15
|
+
* a byte comparison; a mtime gap beyond this simply proves the pair cannot be
|
|
16
|
+
* byte-identical, so we skip the read.
|
|
17
|
+
*/
|
|
18
|
+
const MTIME_TOLERANCE_MS = 1000
|
|
19
|
+
|
|
20
|
+
/** One sync run's outcome, grouped for diagnostics. */
|
|
21
|
+
export function newSyncResult() {
|
|
22
|
+
return { synced: [], current: [], failed: [], pruned: [] }
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function filesUnder(root) {
|
|
26
|
+
const out = []
|
|
27
|
+
const walk = (dir) => {
|
|
28
|
+
for (const entry of readdirSync(dir)) {
|
|
29
|
+
const path = join(dir, entry)
|
|
30
|
+
if (statSync(path).isDirectory()) walk(path)
|
|
31
|
+
else out.push(path)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
walk(root)
|
|
35
|
+
return out
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* File identity is bytes. Size and mtime are only a fast negative check: a
|
|
40
|
+
* size mismatch or a mtime gap beyond the tolerance proves the pair cannot be
|
|
41
|
+
* byte-identical without reading both, but an equal size and close mtime still
|
|
42
|
+
* fall through to a byte comparison so content differences are never missed.
|
|
43
|
+
*/
|
|
44
|
+
function sameFile(a, b) {
|
|
45
|
+
const sourceStat = statSync(a)
|
|
46
|
+
const targetStat = statSync(b)
|
|
47
|
+
if (sourceStat.size !== targetStat.size) return false
|
|
48
|
+
if (Math.abs(sourceStat.mtimeMs - targetStat.mtimeMs) > MTIME_TOLERANCE_MS) return false
|
|
49
|
+
return readFileSync(a).equals(readFileSync(b))
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Copy the whole tree under `sourceDir` into `targetDir`, creating the target
|
|
54
|
+
* directory as needed. Intentionally not `fs.cpSync` (recursive): on Node 22
|
|
55
|
+
* for Windows, `fs.cpSync` with `recursive: true` crashes the process with a
|
|
56
|
+
* fatal error (STATUS_STACK_BUFFER_OVERRUN / 0xC0000409, no JS exception is
|
|
57
|
+
* thrown) whenever the source path contains non-ASCII characters such as a
|
|
58
|
+
* CJK home directory (nodejs/node#54476). Source mtimes are preserved.
|
|
59
|
+
*/
|
|
60
|
+
function copyTreeSync(sourceDir, targetDir) {
|
|
61
|
+
mkdirSync(targetDir, { recursive: true })
|
|
62
|
+
for (const entry of readdirSync(sourceDir)) {
|
|
63
|
+
const source = join(sourceDir, entry)
|
|
64
|
+
const target = join(targetDir, entry)
|
|
65
|
+
const stat = statSync(source)
|
|
66
|
+
if (stat.isDirectory()) {
|
|
67
|
+
copyTreeSync(source, target)
|
|
68
|
+
} else {
|
|
69
|
+
copyFileSync(source, target)
|
|
70
|
+
utimesSync(target, stat.atime, stat.mtime)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Remove one target entry (file or dir) if it exists. */
|
|
76
|
+
function removeEntry(target) {
|
|
77
|
+
if (!existsSync(target)) return
|
|
78
|
+
rmSync(target, { recursive: true, force: true })
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Sync one source group into its target directory.
|
|
83
|
+
*
|
|
84
|
+
* @param sourceDir - bundled group root inside the package (e.g. assets/skills).
|
|
85
|
+
* @param targetDir - user runtime group root (e.g. <home>/skills).
|
|
86
|
+
* @param options - { prefix } the group's owned name prefix (e.g. 'devflow-').
|
|
87
|
+
* Only entries matching the prefix are copied from source or pruned from
|
|
88
|
+
* target; everything else in either directory is left untouched.
|
|
89
|
+
* @param report - SyncResult accumulator; pushes the group id when changed.
|
|
90
|
+
* @param groupId - diagnostic id for the accumulator.
|
|
91
|
+
*/
|
|
92
|
+
export function syncGroup(sourceDir, targetDir, { prefix }, report, groupId) {
|
|
93
|
+
if (!existsSync(sourceDir)) {
|
|
94
|
+
report.failed.push({ id: groupId, error: `bundled source missing: ${sourceDir}` })
|
|
95
|
+
return
|
|
96
|
+
}
|
|
97
|
+
mkdirSync(targetDir, { recursive: true })
|
|
98
|
+
|
|
99
|
+
const sourceEntries = readdirSync(sourceDir).filter((name) => name.startsWith(prefix))
|
|
100
|
+
let dirty = false
|
|
101
|
+
|
|
102
|
+
// Copy or refresh every owned source entry, then prune owned target entries
|
|
103
|
+
// the source no longer ships. Byte-identical files stay untouched so the
|
|
104
|
+
// user's mtimes and any local tooling watching them are preserved.
|
|
105
|
+
for (const name of sourceEntries) {
|
|
106
|
+
const source = join(sourceDir, name)
|
|
107
|
+
const target = join(targetDir, name)
|
|
108
|
+
const stat = statSync(source)
|
|
109
|
+
if (stat.isDirectory()) {
|
|
110
|
+
const existing = existsSync(target) && statSync(target).isDirectory()
|
|
111
|
+
if (existing && sameTree(source, target)) continue
|
|
112
|
+
removeEntry(target)
|
|
113
|
+
copyTreeSync(source, target)
|
|
114
|
+
dirty = true
|
|
115
|
+
} else {
|
|
116
|
+
if (existsSync(target) && !statSync(target).isDirectory() && sameFile(source, target)) continue
|
|
117
|
+
removeEntry(target)
|
|
118
|
+
mkdirSync(dirname(target), { recursive: true })
|
|
119
|
+
copyFileSync(source, target)
|
|
120
|
+
utimesSync(target, stat.atime, stat.mtime)
|
|
121
|
+
dirty = true
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
for (const entry of readdirSync(targetDir)) {
|
|
126
|
+
if (!entry.startsWith(prefix)) continue
|
|
127
|
+
if (sourceEntries.includes(entry)) continue
|
|
128
|
+
removeEntry(join(targetDir, entry))
|
|
129
|
+
report.pruned.push(`${groupId}/${entry}`)
|
|
130
|
+
dirty = true
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (dirty) report.synced.push(groupId)
|
|
134
|
+
else report.current.push(groupId)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** Byte-compare two directory trees without touching either. */
|
|
138
|
+
function sameTree(a, b) {
|
|
139
|
+
const aFiles = filesUnder(a)
|
|
140
|
+
const bFiles = filesUnder(b)
|
|
141
|
+
const aSet = new Set(aFiles.map((file) => relative(a, file)))
|
|
142
|
+
if (aFiles.length !== bFiles.length) return false
|
|
143
|
+
for (const file of aFiles) {
|
|
144
|
+
const rel = relative(a, file)
|
|
145
|
+
const peer = join(b, rel)
|
|
146
|
+
if (!existsSync(peer) || statSync(peer).isDirectory()) return false
|
|
147
|
+
if (!sameFile(file, peer)) return false
|
|
148
|
+
}
|
|
149
|
+
for (const file of bFiles) {
|
|
150
|
+
if (!aSet.has(relative(b, file))) return false
|
|
151
|
+
}
|
|
152
|
+
return true
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Sync every bundled DevFlow asset group into the DSH home.
|
|
157
|
+
* @param assetsRoot - package assets root (e.g. <pkg>/assets).
|
|
158
|
+
* @param home - resolved DSH home directory.
|
|
159
|
+
* @returns a SyncResult with per-group outcomes.
|
|
160
|
+
*/
|
|
161
|
+
export function syncAllAssets(assetsRoot, home) {
|
|
162
|
+
const report = newSyncResult()
|
|
163
|
+
syncGroup(join(assetsRoot, 'presets/devflow-2'), join(home, '.agent-presets/devflow-2'), { prefix: '' }, report, 'presets/devflow-2')
|
|
164
|
+
syncGroup(join(assetsRoot, 'skills'), join(home, 'skills'), { prefix: 'devflow-' }, report, 'skills')
|
|
165
|
+
syncGroup(join(assetsRoot, 'commands'), join(home, 'commands'), { prefix: 'devflow' }, report, 'commands')
|
|
166
|
+
syncGroup(join(assetsRoot, 'scripts'), join(home, 'scripts'), { prefix: 'devflow-' }, report, 'scripts')
|
|
167
|
+
return report
|
|
168
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@devflow-core/dsh-devflow",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "DevFlow for DeepSeek Harness: devflow-2 agent preset + skills + commands + verification scripts, synced into ~/.dsh on host startup.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": "^22.19.0 || >=24.0.0"
|
|
8
|
+
},
|
|
9
|
+
"main": "./lib/index.js",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": "./lib/index.js",
|
|
12
|
+
"./package.json": "./package.json",
|
|
13
|
+
"./assets/*": "./assets/*"
|
|
14
|
+
},
|
|
15
|
+
"dsh": {
|
|
16
|
+
"bundle": {
|
|
17
|
+
"patch": "./cordis.patch.yml"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"lib",
|
|
22
|
+
"assets",
|
|
23
|
+
"cordis.patch.yml",
|
|
24
|
+
"README.md",
|
|
25
|
+
"NOTICE"
|
|
26
|
+
],
|
|
27
|
+
"license": "Apache-2.0",
|
|
28
|
+
"scripts": {
|
|
29
|
+
"sync-assets": "node scripts/sync-assets.js",
|
|
30
|
+
"test": "node test/sync.test.js"
|
|
31
|
+
}
|
|
32
|
+
}
|