prosicht 1.4.0 → 1.6.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/README.md +13 -2
- package/index.js +1 -0
- package/lib/publish.js +59 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -30,13 +30,24 @@ Sunum klasörlerinde `update` yalnızca çekirdek dosyaları (`index.html`, `css
|
|
|
30
30
|
```bash
|
|
31
31
|
npx prosicht publish
|
|
32
32
|
```
|
|
33
|
-
1. deck.prosicht.com'da hesap açın ve **Yeni
|
|
33
|
+
1. deck.prosicht.com'da hesap açın ve **Yeni ekle** ile, klasörünüzle aynı türü (**Sunum** ya da **Blog yazısı**) seçerek 32 karakterlik bir key alın.
|
|
34
34
|
2. Sunum veya blog klasöründe `npx prosicht publish` çalıştırın: **Sunum** / **Blog** (klasörden tespit edilip önceden seçilir) → adres (varsayılan `deck.prosicht.com`) → key.
|
|
35
35
|
3. Link terminalde verilir. Key ve adres isterseniz `.prosicht/publish.json` içine kaydedilir (git dışı); sonraki yayınlar sormaz.
|
|
36
36
|
|
|
37
|
+
Tür yüklemeyle birlikte gönderilir (`manifest.kind`); sunucu ayrıca dosyalardan da anlar (`js/post.js` → blog, `js/scenes.js` → sunum). Hiç yayınlanmamış bir kayıt yüklenen türü alır. Daha önce sunum olarak yayınlanmış bir kaydın keyiyle blog yayınlanamaz (ya da tersi): CLI bunu açıkça söyler; panelden doğru türde yeni bir kayıt açın.
|
|
38
|
+
|
|
37
39
|
Yalnızca `index.html`, `css/`, `js/` ve `assets/` yüklenir (en fazla 50 MB, dosya başına 25 MB, 500 dosya). `/` ile başlayan yollar için uyarı verilir. Kayıtlı key panelde yenilendiyse CLI yenisini sorar.
|
|
38
40
|
|
|
39
|
-
Seçenekler: `--key <key>`, `--host <url>`, `-y` (soruları atla; tür klasörden tespit edilir).
|
|
41
|
+
Seçenekler: `--key <key>`, `--host <url>`, `-y` (soruları atla; tür klasörden tespit edilir), `-f, --force` (aşağıdaki iki denetimi atla, üzerine yaz).
|
|
42
|
+
|
|
43
|
+
### Ortak çalışma (CLI 1.6+)
|
|
44
|
+
|
|
45
|
+
İçeriğin sahibi Pro veya Ekip planındaysa panelden başka hesapları (ücretsiz olabilir) içeriğe ekler. Eklenen kişi panelde **Benimle paylaşılanlar** altından:
|
|
46
|
+
1. **Kaynak dosyalarını indir** ile yayındaki sürümü ZIP olarak alır ve açar (içinde `AGENTS.md` ve key'siz `.prosicht/publish.json` var),
|
|
47
|
+
2. **Yayın keyi al** ile kendine ait keyi alır,
|
|
48
|
+
3. klasörde `npx prosicht publish` çalıştırır; key ilk seferde sorulur.
|
|
49
|
+
|
|
50
|
+
Her yayından sonra klasörün hangi sürümün üzerine kurulu olduğu `.prosicht/publish.json`'a (`baseVersion`) yazılır ve sonraki yayında gönderilir. Bu arada başka biri (sahip ya da başka bir ortak çalışan) yeni sürüm yayınladıysa yayın reddedilir; güncel kaynağı indirip değişiklikleri aktarın ya da bilerek üzerine yazmak için `--force` kullanın. Klasörün ait olduğu içerikten başka bir içeriğin keyi girilirse de yayın reddedilir (`--force` ile o içeriğe yayınlanır). Sahibin planı ortak çalışmayı artık içermiyorsa ortak çalışanların yayını reddedilir.
|
|
40
51
|
|
|
41
52
|
## Sunum hazırlama
|
|
42
53
|
|
package/index.js
CHANGED
|
@@ -282,6 +282,7 @@ program
|
|
|
282
282
|
.option('-k, --key <key>', 'Panelden alinan 32 karakterlik yayin keyi')
|
|
283
283
|
.option('--host <url>', 'Yayin adresi (varsayilan: https://deck.prosicht.com)')
|
|
284
284
|
.option('-y, --yes', 'Sorulari atla: tur klasorden tespit edilir, key kaydedilir')
|
|
285
|
+
.option('-f, --force', 'Bu klasorden sonra yayinlanan surumun ve klasorun ait oldugu icerigin denetimini atla (uzerine yazar)')
|
|
285
286
|
.action((options) => publish(options));
|
|
286
287
|
|
|
287
288
|
program.parse(process.argv);
|
package/lib/publish.js
CHANGED
|
@@ -62,12 +62,17 @@ async function chooseHost(saved, flag) {
|
|
|
62
62
|
return normalizeHost(custom);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
async function chooseKey(saved, flag) {
|
|
65
|
+
async function chooseKey(saved, flag, config = {}) {
|
|
66
66
|
if (flag) return KEY_PATTERN.test(flag) ? flag : fail('Key 32 karakter olmali (harf ve rakam).');
|
|
67
67
|
if (saved && KEY_PATTERN.test(saved)) {
|
|
68
68
|
console.log(`Kayitli key kullaniliyor (....${saved.slice(-4)}). Degistirmek icin: --key`);
|
|
69
69
|
return saved;
|
|
70
70
|
}
|
|
71
|
+
// panelden indirilen klasör: hangi içeriğe ait olduğu belli, key kişiye özel
|
|
72
|
+
if (config.deckId && config.url) {
|
|
73
|
+
console.log(`Bu klasor ${config.url} icerigine ait. Keyinizi panelden alin:`);
|
|
74
|
+
console.log(' sahibiyseniz Iceriklerim, ortak calisiyorsaniz Benimle paylasilanlar -> Yayin keyi al.');
|
|
75
|
+
}
|
|
71
76
|
return ask({
|
|
72
77
|
type: 'password', name: 'key', message: 'Lutfen keyi giriniz',
|
|
73
78
|
validate: (v) => (KEY_PATTERN.test(String(v).trim()) ? true : 'Key 32 karakter olmali (harf ve rakam)'),
|
|
@@ -75,9 +80,13 @@ async function chooseKey(saved, flag) {
|
|
|
75
80
|
});
|
|
76
81
|
}
|
|
77
82
|
|
|
78
|
-
|
|
83
|
+
// Sunucu türü dosyalardan da anlar; kind yine de gönderilir (panelde rozet, MCP'de doğru kit).
|
|
84
|
+
// base: klasörün geldiği içerik ve sürüm; arada başkası yayınladıysa sunucu reddeder (409)
|
|
85
|
+
async function upload(host, key, files, title, kind, base) {
|
|
79
86
|
const form = new FormData();
|
|
80
|
-
|
|
87
|
+
const manifest = { title, kind, files: files.map((f) => ({ path: f.path, size: f.size })) };
|
|
88
|
+
if (base) Object.assign(manifest, { deckId: base.deckId, baseVersion: base.version });
|
|
89
|
+
form.append('manifest', JSON.stringify(manifest));
|
|
81
90
|
for (const f of files) {
|
|
82
91
|
const type = MIME_TYPES[path.extname(f.path).toLowerCase()];
|
|
83
92
|
form.append('files', new Blob([fs.readFileSync(f.abs)], { type }), path.basename(f.path));
|
|
@@ -93,8 +102,34 @@ async function upload(host, key, files, title) {
|
|
|
93
102
|
return { status: response.status, body };
|
|
94
103
|
}
|
|
95
104
|
|
|
105
|
+
const NOUN = { presentation: 'sunum', blog: 'blog yazisi' };
|
|
106
|
+
const DATIVE = { presentation: 'sunuma', blog: 'blog yazisina' };
|
|
107
|
+
const PANEL_CHOICE = { presentation: 'Sunum', blog: 'Blog yazisi' };
|
|
108
|
+
|
|
96
109
|
function explain(status, body) {
|
|
97
110
|
if (status === 401) fail('Key gecersiz veya yenilenmis. Panelden guncel keyi alin.');
|
|
111
|
+
if (status === 403 && body.code === 'collaboration_inactive') {
|
|
112
|
+
fail('Icerigin sahibinin plani ortak calismayi icermiyor (Pro veya Ekip gerekir); su an yalnizca sahibi yayinlayabilir.');
|
|
113
|
+
}
|
|
114
|
+
// indirildikten (ya da son yayından) sonra başka biri yeni sürüm yayınlamış
|
|
115
|
+
if (status === 409 && body.code === 'version_conflict') {
|
|
116
|
+
fail(`Bu klasor surum ${body.baseVersion} uzerine kurulu, ama bu arada surum ${body.version} yayinlanmis. Yayinlarsaniz o surumdeki degisiklikler kaybolur.`, [
|
|
117
|
+
'Panelden "Kaynak dosyalarini indir" ile guncel surumu alip degisikliklerinizi ona aktarin, sonra tekrar yayinlayin.',
|
|
118
|
+
'Ya da bilerek uzerine yazmak icin: npx prosicht publish --force'
|
|
119
|
+
]);
|
|
120
|
+
}
|
|
121
|
+
if (status === 409 && body.code === 'deck_mismatch') {
|
|
122
|
+
fail(`Bu klasor ${body.folderDeckId} icerigine ait, girilen key ise ${body.deckId} icerigine.`, [
|
|
123
|
+
'Klasorun ait oldugu icerigin keyini --key ile verin.',
|
|
124
|
+
`Klasoru bilerek ${body.deckId} uzerine yayinlamak icin: npx prosicht publish --force`
|
|
125
|
+
]);
|
|
126
|
+
}
|
|
127
|
+
// key, daha önce başka türde yayınlanmış bir içeriğe ait
|
|
128
|
+
if (status === 409 && DATIVE[body.deckKind] && NOUN[body.kind]) {
|
|
129
|
+
fail(`Bu key bir ${DATIVE[body.deckKind]} ait; bu klasordeki icerik bir ${NOUN[body.kind]}.`, [
|
|
130
|
+
`Panelde "Yeni ekle" ile ${PANEL_CHOICE[body.kind]} secip yeni bir key alin ve --key ile verin.`
|
|
131
|
+
]);
|
|
132
|
+
}
|
|
98
133
|
if (status === 413) fail('Dosyalar boyut sinirini asiyor (en fazla 50 MB).');
|
|
99
134
|
if (status === 400 || status === 422) fail(body.error || 'Dosyalar reddedildi.', body.details || []);
|
|
100
135
|
fail(`Sunucu hatasi (HTTP ${status})${body.error ? `: ${body.error}` : ''}`);
|
|
@@ -134,14 +169,18 @@ async function publish(options = {}) {
|
|
|
134
169
|
|
|
135
170
|
const config = readConfig(root);
|
|
136
171
|
const host = await chooseHost(options.host ? null : config.host, options.host);
|
|
137
|
-
let key = await chooseKey(options.key ? null : config.key, options.key);
|
|
172
|
+
let key = await chooseKey(options.key ? null : config.key, options.key, config);
|
|
138
173
|
if (!key) process.exit(0);
|
|
139
174
|
|
|
175
|
+
// --force: çakışma denetimi yok, klasör keyin içeriğine yayınlanır
|
|
176
|
+
const base = !options.force && config.deckId && Number.isInteger(config.baseVersion)
|
|
177
|
+
? { deckId: config.deckId, version: config.baseVersion }
|
|
178
|
+
: null;
|
|
140
179
|
const title = readTitle(root, kind);
|
|
141
180
|
const send = async () => {
|
|
142
181
|
console.log(`\n[Pro Sicht] ${files.length} dosya (${formatBytes(total)}) yukleniyor...`);
|
|
143
182
|
try {
|
|
144
|
-
return await upload(host, key, files, title);
|
|
183
|
+
return await upload(host, key, files, title, kind, base);
|
|
145
184
|
} catch (error) {
|
|
146
185
|
return fail(`${host} adresine ulasilamadi: ${error.cause?.code || error.message}`);
|
|
147
186
|
}
|
|
@@ -150,28 +189,37 @@ async function publish(options = {}) {
|
|
|
150
189
|
// kayıtlı key panelden yenilenmişse bir kez yenisini sor ve tekrar dene
|
|
151
190
|
if (result.status === 401 && key === config.key && !options.key && !options.yes) {
|
|
152
191
|
console.log('Kayitli key gecersiz; panelde yenilenmis olabilir.');
|
|
153
|
-
key = await chooseKey(null, null);
|
|
192
|
+
key = await chooseKey(null, null, config);
|
|
154
193
|
if (!key) process.exit(0);
|
|
155
194
|
result = await send();
|
|
156
195
|
}
|
|
157
196
|
if (result.status !== 200 || !result.body.url) explain(result.status, result.body);
|
|
158
197
|
|
|
159
|
-
const { url, privacy, version } = result.body;
|
|
160
|
-
console.log(`Yayinlandi (surum ${version}): ${url}`);
|
|
161
|
-
|
|
198
|
+
const { url, privacy, version, deckId, role } = result.body;
|
|
199
|
+
console.log(`Yayinlandi (${label}, surum ${version}): ${url}`);
|
|
200
|
+
// ortak çalışan gizliliği değiştiremez; yalnızca sahibi
|
|
201
|
+
if (role === 'collaborator') {
|
|
202
|
+
console.log(privacy === 'private'
|
|
203
|
+
? 'Gizlilik: yalnizca sahibi ve ortak calisanlar gorebilir. Paylasmayi sahibi panelden acar.'
|
|
204
|
+
: `Gizlilik: ${privacy === 'password' ? 'baglanti ve sifreyle' : 'baglantiya sahip herkes'} gorebilir (sahibinin ayari).`);
|
|
205
|
+
} else if (privacy === 'private') {
|
|
162
206
|
console.log('Gizlilik: yalnizca siz gorebilirsiniz. Paylasmak icin panelden "Baglantiya sahip herkes" secin.');
|
|
163
207
|
} else {
|
|
164
208
|
console.log('Gizlilik: baglantiya sahip herkes gorebilir.');
|
|
165
209
|
}
|
|
166
210
|
|
|
211
|
+
// baseVersion her yayında güncellenir: sonraki yayın bu sürümün üzerine kurulu sayılır
|
|
212
|
+
const published = { deckId, url, baseVersion: version };
|
|
167
213
|
if (config.key !== key || config.host !== host) {
|
|
168
214
|
const remember = options.yes ? true : await ask({
|
|
169
215
|
type: 'confirm', name: 'save', initial: true,
|
|
170
216
|
message: 'Key ve adres bu klasor icin kaydedilsin mi? (.prosicht/, git disi)'
|
|
171
217
|
});
|
|
172
|
-
|
|
218
|
+
const rest = { ...config };
|
|
219
|
+
delete rest.key;
|
|
220
|
+
saveConfig(root, remember ? { ...rest, host, key, ...published } : { ...rest, host, ...published });
|
|
173
221
|
} else {
|
|
174
|
-
saveConfig(root, { ...config,
|
|
222
|
+
saveConfig(root, { ...config, ...published });
|
|
175
223
|
}
|
|
176
224
|
console.log('');
|
|
177
225
|
}
|